1261081Sasomers/*-
2261081Sasomers * Copyright (c) 2014 Spectra Logic Corporation. All rights reserved.
3261081Sasomers * Redistribution and use in source and binary forms, with or without
4261081Sasomers * modification, are permitted provided that the following conditions
5261081Sasomers * are met:
6261081Sasomers * 1. Redistributions of source code must retain the above copyright
7261081Sasomers *    notice, this list of conditions and the following disclaimer.
8261081Sasomers * 2. Redistributions in binary form must reproduce the above copyright
9261081Sasomers *    notice, this list of conditions and the following disclaimer in the
10261081Sasomers *    documentation and/or other materials provided with the distribution.
11261081Sasomers *
12261081Sasomers * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13261081Sasomers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14261081Sasomers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15261081Sasomers * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
16261081Sasomers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17261081Sasomers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18261081Sasomers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19261081Sasomers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20261081Sasomers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21261081Sasomers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22261081Sasomers * SUCH DAMAGE.
23261081Sasomers */
24261081Sasomers
25261081Sasomers#include <sys/cdefs.h>
26261081Sasomers__FBSDID("$FreeBSD: stable/10/tests/sys/kern/unix_seqpacket_test.c 317834 2017-05-05 16:24:35Z brooks $");
27261081Sasomers
28261081Sasomers#include <errno.h>
29261081Sasomers#include <fcntl.h>
30261081Sasomers#include <pthread.h>
31261081Sasomers#include <signal.h>
32261081Sasomers#include <sys/socket.h>
33261081Sasomers#include <sys/un.h>
34261081Sasomers
35261081Sasomers#include <stdio.h>
36261081Sasomers
37261081Sasomers#include <atf-c.h>
38261081Sasomers
39261081Sasomers/*
40261081Sasomers * Helper functions
41261081Sasomers */
42261081Sasomers
43261081Sasomers#define MIN(x, y)	((x) < (y) ? (x) : (y))
44261081Sasomers#define MAX(x, y)	((x) > (y) ? (x) : (y))
45261081Sasomers
46263572Sasomersstatic void
47261081Sasomersdo_socketpair(int *sv)
48261081Sasomers{
49261081Sasomers	int s;
50293143Sngie
51261081Sasomers	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
52261081Sasomers	ATF_REQUIRE_EQ(0, s);
53261081Sasomers	ATF_REQUIRE(sv[0] >= 0);
54261081Sasomers	ATF_REQUIRE(sv[1] >= 0);
55261081Sasomers	ATF_REQUIRE(sv[0] != sv[1]);
56261081Sasomers}
57261081Sasomers
58263572Sasomersstatic void
59261081Sasomersdo_socketpair_nonblocking(int *sv)
60261081Sasomers{
61261081Sasomers	int s;
62293143Sngie
63261081Sasomers	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
64261081Sasomers	ATF_REQUIRE_EQ(0, s);
65261081Sasomers	ATF_REQUIRE(sv[0] >= 0);
66261081Sasomers	ATF_REQUIRE(sv[1] >= 0);
67261081Sasomers	ATF_REQUIRE(sv[0] != sv[1]);
68261081Sasomers	ATF_REQUIRE(-1 != fcntl(sv[0], F_SETFL, O_NONBLOCK));
69261081Sasomers	ATF_REQUIRE(-1 != fcntl(sv[1], F_SETFL, O_NONBLOCK));
70261081Sasomers}
71261081Sasomers
72293143Sngie/*
73261081Sasomers * Returns a pair of sockets made the hard way: bind, listen, connect & accept
74261081Sasomers * @return	const char* The path to the socket
75261081Sasomers */
76263572Sasomersstatic const char*
77261081Sasomersmk_pair_of_sockets(int *sv)
78261081Sasomers{
79261081Sasomers	struct sockaddr_un sun;
80261081Sasomers	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
81261081Sasomers	const char *path = "sock";
82261081Sasomers	int s, err, s2, s1;
83261081Sasomers
84261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
85261081Sasomers	ATF_REQUIRE(s >= 0);
86261081Sasomers
87261081Sasomers	bzero(&sun, sizeof(sun));
88261081Sasomers	sun.sun_family = AF_LOCAL;
89261081Sasomers	sun.sun_len = sizeof(sun);
90261081Sasomers	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
91261081Sasomers	err = bind(s, (struct sockaddr *)&sun, sizeof(sun));
92261081Sasomers	err = listen(s, -1);
93261081Sasomers	ATF_CHECK_EQ(0, err);
94261081Sasomers
95261081Sasomers	/* Create the other socket */
96261081Sasomers	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
97261081Sasomers	ATF_REQUIRE(s2 >= 0);
98261081Sasomers	err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
99261081Sasomers	if (err != 0) {
100261081Sasomers		perror("connect");
101261081Sasomers		atf_tc_fail("connect(2) failed");
102261081Sasomers	}
103293143Sngie
104261081Sasomers	/* Accept it */
105261081Sasomers	s1 = accept(s, NULL, NULL);
106261081Sasomers	if (s1 == -1) {
107261081Sasomers		perror("accept");
108261081Sasomers		atf_tc_fail("accept(2) failed");
109261081Sasomers	}
110261081Sasomers
111261081Sasomers	sv[0] = s1;
112261081Sasomers	sv[1] = s2;
113293275Sngie
114293275Sngie	close(s);
115293275Sngie
116261081Sasomers	return (path);
117261081Sasomers}
118261081Sasomers
119261081Sasomersstatic volatile sig_atomic_t got_sigpipe = 0;
120261081Sasomersstatic void
121263572Sasomersshutdown_send_sigpipe_handler(int __unused x)
122261081Sasomers{
123261081Sasomers	got_sigpipe = 1;
124261081Sasomers}
125261081Sasomers
126261081Sasomers/*
127261081Sasomers * Parameterized test function bodies
128261081Sasomers */
129263572Sasomersstatic void
130317834Sbrookstest_eagain(int sndbufsize, int rcvbufsize)
131261081Sasomers{
132261081Sasomers	int i;
133261081Sasomers	int sv[2];
134261081Sasomers	const size_t totalsize = (sndbufsize + rcvbufsize) * 2;
135261081Sasomers	const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
136263572Sasomers	const int numpkts = totalsize / pktsize;
137261081Sasomers	char sndbuf[pktsize];
138263572Sasomers	ssize_t ssize;
139261081Sasomers
140261081Sasomers	/* setup the socket pair */
141262871Sasomers	do_socketpair_nonblocking(sv);
142261081Sasomers	/* Setup the buffers */
143261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
144261081Sasomers	    sizeof(sndbufsize)));
145261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
146261081Sasomers	    sizeof(rcvbufsize)));
147261081Sasomers
148261081Sasomers	bzero(sndbuf, pktsize);
149261081Sasomers	/* Send data until we get EAGAIN */
150263572Sasomers	for(i=0; i < numpkts; i++) {
151261081Sasomers		ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
152261081Sasomers		if (ssize == -1) {
153293275Sngie			if (errno == EAGAIN) {
154293275Sngie				close(sv[0]);
155293275Sngie				close(sv[1]);
156261081Sasomers				atf_tc_pass();
157293275Sngie			}
158261081Sasomers			else {
159261081Sasomers				perror("send");
160261081Sasomers				atf_tc_fail("send returned < 0 but not EAGAIN");
161261081Sasomers			}
162261081Sasomers		}
163261081Sasomers	}
164261081Sasomers	atf_tc_fail("Never got EAGAIN");
165261081Sasomers}
166261081Sasomers
167263572Sasomersstatic void
168317834Sbrookstest_sendrecv_symmetric_buffers(int bufsize, int blocking) {
169261081Sasomers	int s;
170261081Sasomers	int sv[2];
171263572Sasomers	const ssize_t pktsize = bufsize / 2;
172261081Sasomers	char sndbuf[pktsize];
173261081Sasomers	char recv_buf[pktsize];
174261081Sasomers	ssize_t ssize, rsize;
175261081Sasomers
176261081Sasomers	/* setup the socket pair */
177261081Sasomers	if (blocking)
178261081Sasomers		do_socketpair(sv);
179261081Sasomers	else
180261081Sasomers		do_socketpair_nonblocking(sv);
181261081Sasomers
182261081Sasomers	/* Setup the buffers */
183261081Sasomers	s = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
184261081Sasomers	ATF_REQUIRE_EQ(0, s);
185261081Sasomers	s = setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
186261081Sasomers	ATF_REQUIRE_EQ(0, s);
187261081Sasomers
188261081Sasomers	/* Fill the send buffer */
189261081Sasomers	bzero(sndbuf, pktsize);
190261081Sasomers
191261081Sasomers	/* send and receive the packet */
192261081Sasomers	ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
193261081Sasomers	if (ssize < 0) {
194261081Sasomers		perror("send");
195261081Sasomers		atf_tc_fail("send returned < 0");
196261081Sasomers	}
197261081Sasomers	ATF_CHECK_EQ_MSG(pktsize, ssize, "expected %zd=send(...) but got %zd",
198261081Sasomers	    pktsize, ssize);
199261081Sasomers
200261081Sasomers	rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
201261081Sasomers	if (rsize < 0) {
202261081Sasomers		perror("recv");
203261081Sasomers		atf_tc_fail("recv returned < 0");
204261081Sasomers	}
205261081Sasomers	ATF_CHECK_EQ_MSG(pktsize, rsize, "expected %zd=send(...) but got %zd",
206261081Sasomers	    pktsize, rsize);
207293275Sngie	close(sv[0]);
208293275Sngie	close(sv[1]);
209261081Sasomers}
210261081Sasomers
211263572Sasomersstatic void
212317834Sbrookstest_pipe_simulator(int sndbufsize, int rcvbufsize)
213261081Sasomers{
214263572Sasomers	int num_sent, num_received;
215261081Sasomers	int sv[2];
216263572Sasomers	const ssize_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
217261081Sasomers	int numpkts;
218261081Sasomers	char sndbuf[pktsize];
219261081Sasomers	char rcvbuf[pktsize];
220261081Sasomers	char comparebuf[pktsize];
221261081Sasomers	ssize_t ssize, rsize;
222261081Sasomers	bool currently_sending = true;
223261081Sasomers
224261081Sasomers	/* setup the socket pair */
225261081Sasomers	do_socketpair_nonblocking(sv);
226261081Sasomers	/* Setup the buffers */
227261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
228261081Sasomers	    sizeof(sndbufsize)));
229261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
230261081Sasomers	    sizeof(rcvbufsize)));
231261081Sasomers
232261081Sasomers	/* Send a total amount of data comfortably greater than the buffers */
233261081Sasomers	numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
234261081Sasomers	for (num_sent=0, num_received=0;
235261081Sasomers	     num_sent < numpkts || num_received < numpkts; ) {
236261081Sasomers		if (currently_sending && num_sent < numpkts) {
237261081Sasomers			/* The simulated sending process */
238261081Sasomers			/* fill the buffer */
239261081Sasomers			memset(sndbuf, num_sent, pktsize);
240261081Sasomers			ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
241261081Sasomers			if (ssize < 0) {
242293143Sngie				/*
243261081Sasomers				 * XXX: This is bug-compatible with the kernel.
244261081Sasomers				 * The kernel returns EMSGSIZE when it should
245261081Sasomers				 * return EAGAIN
246261081Sasomers				 */
247261081Sasomers				if (errno == EAGAIN || errno == EMSGSIZE)
248261081Sasomers					currently_sending = false;
249261081Sasomers				else {
250261081Sasomers					perror("send");
251261081Sasomers					atf_tc_fail("send failed");
252261081Sasomers				}
253261081Sasomers			} else  {
254261081Sasomers				ATF_CHECK_EQ_MSG(pktsize, ssize,
255261081Sasomers				    "expected %zd=send(...) but got %zd",
256261081Sasomers				    pktsize, ssize);
257261081Sasomers				num_sent++;
258261081Sasomers			}
259261081Sasomers		} else {
260261081Sasomers			/* The simulated receiving process */
261261081Sasomers			rsize = recv(sv[1], rcvbuf, pktsize, MSG_WAITALL);
262261081Sasomers			if (rsize < 0) {
263261081Sasomers				if (errno == EAGAIN) {
264261081Sasomers					currently_sending = true;
265261081Sasomers					ATF_REQUIRE_MSG(num_sent < numpkts,
266261081Sasomers					    "Packets were lost!");
267261081Sasomers				}
268261081Sasomers				else {
269261081Sasomers					perror("recv");
270261081Sasomers					atf_tc_fail("recv failed");
271261081Sasomers				}
272261081Sasomers			} else  {
273261081Sasomers				ATF_CHECK_EQ_MSG(pktsize, rsize,
274261081Sasomers				    "expected %zd=recv(...) but got %zd",
275261081Sasomers				    pktsize, rsize);
276261081Sasomers				memset(comparebuf, num_received, pktsize);
277261081Sasomers				ATF_CHECK_EQ_MSG(0, memcmp(comparebuf, rcvbuf,
278293143Sngie				    			   pktsize),
279261081Sasomers				    "Received data miscompare");
280261081Sasomers				num_received++;
281261081Sasomers			}
282261081Sasomers		}
283261081Sasomers	}
284293275Sngie	close(sv[0]);
285293275Sngie	close(sv[1]);
286261081Sasomers}
287261081Sasomers
288261081Sasomerstypedef struct {
289261081Sasomers	ssize_t	pktsize;
290261081Sasomers	int	numpkts;
291261081Sasomers	int	so;
292261081Sasomers} test_pipe_thread_data_t;
293261081Sasomers
294261081Sasomersstatic void*
295261081Sasomerstest_pipe_writer(void* args)
296261081Sasomers{
297261081Sasomers	test_pipe_thread_data_t* td = args;
298261081Sasomers	char sndbuf[td->pktsize];
299261081Sasomers	ssize_t ssize;
300261081Sasomers	int i;
301261081Sasomers
302261081Sasomers	for(i=0; i < td->numpkts; i++) {
303261081Sasomers			memset(sndbuf, i, td->pktsize);
304261081Sasomers			ssize = send(td->so, sndbuf, td->pktsize, MSG_EOR);
305261081Sasomers			if (ssize < 0) {
306261081Sasomers				perror("send");
307261081Sasomers				atf_tc_fail("send returned < 0");
308261081Sasomers			}
309261081Sasomers			ATF_CHECK_EQ_MSG(td->pktsize, ssize,
310261081Sasomers			    		 "expected %zd=send(...) but got %zd",
311261081Sasomers			    		  td->pktsize, ssize);
312261081Sasomers	}
313261081Sasomers	return (0);
314261081Sasomers}
315261081Sasomers
316261081Sasomersstatic void*
317261081Sasomerstest_pipe_reader(void* args)
318261081Sasomers{
319261081Sasomers	test_pipe_thread_data_t* td = args;
320261081Sasomers	char rcvbuf[td->pktsize];
321261081Sasomers	char comparebuf[td->pktsize];
322261081Sasomers	ssize_t rsize;
323261081Sasomers	int i, d;
324261081Sasomers
325261081Sasomers	for(i=0; i < td->numpkts; i++) {
326261081Sasomers		memset(comparebuf, i, td->pktsize);
327261081Sasomers		rsize = recv(td->so, rcvbuf, td->pktsize, MSG_WAITALL);
328261081Sasomers		if (rsize < 0) {
329261081Sasomers			perror("recv");
330261081Sasomers			atf_tc_fail("recv returned < 0");
331261081Sasomers		}
332261081Sasomers		ATF_CHECK_EQ_MSG(td->pktsize, rsize,
333261081Sasomers		    		 "expected %zd=send(...) but got %zd",
334261081Sasomers				 td->pktsize, rsize);
335261081Sasomers		d = memcmp(comparebuf, rcvbuf, td->pktsize);
336293143Sngie		ATF_CHECK_EQ_MSG(0, d,
337261081Sasomers		    		 "Received data miscompare on packet %d", i);
338261081Sasomers	}
339261081Sasomers	return (0);
340261081Sasomers}
341261081Sasomers
342261081Sasomers
343263572Sasomersstatic void
344317834Sbrookstest_pipe(int sndbufsize, int rcvbufsize)
345261081Sasomers{
346261081Sasomers	test_pipe_thread_data_t writer_data, reader_data;
347261081Sasomers	pthread_t writer, reader;
348261081Sasomers	int sv[2];
349261081Sasomers	const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
350261081Sasomers	int numpkts;
351261081Sasomers
352261081Sasomers	/* setup the socket pair */
353261081Sasomers	do_socketpair(sv);
354261081Sasomers	/* Setup the buffers */
355261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
356261081Sasomers	    sizeof(sndbufsize)));
357261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
358261081Sasomers	    sizeof(rcvbufsize)));
359261081Sasomers
360261081Sasomers	/* Send a total amount of data comfortably greater than the buffers */
361261081Sasomers	numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
362261081Sasomers
363261081Sasomers	/* Start the child threads */
364261081Sasomers	writer_data.pktsize = pktsize;
365261081Sasomers	writer_data.numpkts = numpkts;
366261081Sasomers	writer_data.so = sv[0];
367261081Sasomers	reader_data.pktsize = pktsize;
368261081Sasomers	reader_data.numpkts = numpkts;
369261081Sasomers	reader_data.so = sv[1];
370261081Sasomers	ATF_REQUIRE_EQ(0, pthread_create(&writer, NULL, test_pipe_writer,
371261081Sasomers	    				 (void*)&writer_data));
372293143Sngie	/*
373263820Sasomers	 * Give the writer time to start writing, and hopefully block, before
374263820Sasomers	 * starting the reader.  This increases the likelihood of the test case
375263820Sasomers	 * failing due to PR kern/185812
376263820Sasomers	 */
377263820Sasomers	usleep(1000);
378261081Sasomers	ATF_REQUIRE_EQ(0, pthread_create(&reader, NULL, test_pipe_reader,
379261081Sasomers	    				 (void*)&reader_data));
380261081Sasomers
381261081Sasomers	/* Join the children */
382261081Sasomers	ATF_REQUIRE_EQ(0, pthread_join(writer, NULL));
383261081Sasomers	ATF_REQUIRE_EQ(0, pthread_join(reader, NULL));
384293275Sngie	close(sv[0]);
385293275Sngie	close(sv[1]);
386261081Sasomers}
387261081Sasomers
388261081Sasomers
389261081Sasomers/*
390261081Sasomers * Test Cases
391261081Sasomers */
392261081Sasomers
393261081Sasomers/* Create a SEQPACKET socket */
394261081SasomersATF_TC_WITHOUT_HEAD(create_socket);
395261081SasomersATF_TC_BODY(create_socket, tc)
396261081Sasomers{
397261081Sasomers	int s;
398261081Sasomers
399261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
400293273Sngie	ATF_REQUIRE(s >= 0);
401293275Sngie	close(s);
402261081Sasomers}
403261081Sasomers
404261081Sasomers/* Create SEQPACKET sockets using socketpair(2) */
405261081SasomersATF_TC_WITHOUT_HEAD(create_socketpair);
406261081SasomersATF_TC_BODY(create_socketpair, tc)
407261081Sasomers{
408261081Sasomers	int sv[2];
409261081Sasomers	int s;
410261081Sasomers
411261081Sasomers	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
412261081Sasomers	ATF_CHECK_EQ(0, s);
413261081Sasomers	ATF_CHECK(sv[0] >= 0);
414261081Sasomers	ATF_CHECK(sv[1] >= 0);
415261081Sasomers	ATF_CHECK(sv[0] != sv[1]);
416293275Sngie	close(sv[0]);
417293275Sngie	close(sv[1]);
418261081Sasomers}
419261081Sasomers
420261081Sasomers/* Call listen(2) without first calling bind(2).  It should fail */
421261081SasomersATF_TC_WITHOUT_HEAD(listen_unbound);
422261081SasomersATF_TC_BODY(listen_unbound, tc)
423261081Sasomers{
424261081Sasomers	int s, r;
425261081Sasomers
426261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
427261081Sasomers	ATF_REQUIRE(s > 0);
428261081Sasomers	r = listen(s, -1);
429261081Sasomers	/* expect listen to fail since we haven't called bind(2) */
430261081Sasomers	ATF_CHECK(r != 0);
431293275Sngie	close(s);
432261081Sasomers}
433261081Sasomers
434261081Sasomers/* Bind the socket to a file */
435261081SasomersATF_TC_WITHOUT_HEAD(bind);
436261081SasomersATF_TC_BODY(bind, tc)
437261081Sasomers{
438261081Sasomers	struct sockaddr_un sun;
439261081Sasomers	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
440261081Sasomers	const char *path = "sock";
441261081Sasomers	int s, r;
442261081Sasomers
443261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
444261081Sasomers	ATF_REQUIRE(s >= 0);
445261081Sasomers
446261081Sasomers	bzero(&sun, sizeof(sun));
447261081Sasomers	sun.sun_family = AF_LOCAL;
448261081Sasomers	sun.sun_len = sizeof(sun);
449261081Sasomers	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
450261081Sasomers	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
451261081Sasomers	ATF_CHECK_EQ(0, r);
452293275Sngie	close(s);
453261081Sasomers}
454261081Sasomers
455261081Sasomers/* listen(2) a socket that is already bound(2) should succeed */
456261081SasomersATF_TC_WITHOUT_HEAD(listen_bound);
457261081SasomersATF_TC_BODY(listen_bound, tc)
458261081Sasomers{
459261081Sasomers	struct sockaddr_un sun;
460261081Sasomers	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
461261081Sasomers	const char *path = "sock";
462261081Sasomers	int s, r, l;
463261081Sasomers
464261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
465261081Sasomers	ATF_REQUIRE(s >= 0);
466261081Sasomers
467261081Sasomers	bzero(&sun, sizeof(sun));
468261081Sasomers	sun.sun_family = AF_LOCAL;
469261081Sasomers	sun.sun_len = sizeof(sun);
470261081Sasomers	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
471261081Sasomers	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
472261081Sasomers	l = listen(s, -1);
473261081Sasomers	ATF_CHECK_EQ(0, r);
474261081Sasomers	ATF_CHECK_EQ(0, l);
475293275Sngie	close(s);
476261081Sasomers}
477261081Sasomers
478261081Sasomers/* connect(2) can make a connection */
479261081SasomersATF_TC_WITHOUT_HEAD(connect);
480261081SasomersATF_TC_BODY(connect, tc)
481261081Sasomers{
482261081Sasomers	struct sockaddr_un sun;
483261081Sasomers	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
484261081Sasomers	const char *path = "sock";
485261081Sasomers	int s, r, err, l, s2;
486261081Sasomers
487261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
488261081Sasomers	ATF_REQUIRE(s >= 0);
489261081Sasomers
490261081Sasomers	bzero(&sun, sizeof(sun));
491261081Sasomers	sun.sun_family = AF_LOCAL;
492261081Sasomers	sun.sun_len = sizeof(sun);
493261081Sasomers	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
494261081Sasomers	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
495261081Sasomers	l = listen(s, -1);
496261081Sasomers	ATF_CHECK_EQ(0, r);
497261081Sasomers	ATF_CHECK_EQ(0, l);
498261081Sasomers
499261081Sasomers	/* Create the other socket */
500261081Sasomers	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
501261081Sasomers	ATF_REQUIRE(s2 >= 0);
502261081Sasomers	err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
503261081Sasomers	if (err != 0) {
504261081Sasomers		perror("connect");
505261081Sasomers		atf_tc_fail("connect(2) failed");
506261081Sasomers	}
507293275Sngie	close(s);
508293275Sngie	close(s2);
509261081Sasomers}
510261081Sasomers
511261081Sasomers/* accept(2) can receive a connection */
512261081SasomersATF_TC_WITHOUT_HEAD(accept);
513261081SasomersATF_TC_BODY(accept, tc)
514261081Sasomers{
515261081Sasomers	int sv[2];
516261081Sasomers
517261081Sasomers	mk_pair_of_sockets(sv);
518293275Sngie	close(sv[0]);
519293275Sngie	close(sv[1]);
520261081Sasomers}
521261081Sasomers
522261081Sasomers
523261081Sasomers/* Set O_NONBLOCK on the socket */
524261081SasomersATF_TC_WITHOUT_HEAD(fcntl_nonblock);
525261081SasomersATF_TC_BODY(fcntl_nonblock, tc)
526261081Sasomers{
527261081Sasomers	int s;
528261081Sasomers
529261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
530261081Sasomers	ATF_REQUIRE(s >= 0);
531261081Sasomers	if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
532261081Sasomers		perror("fcntl");
533261081Sasomers		atf_tc_fail("fcntl failed");
534261081Sasomers	}
535293275Sngie	close(s);
536261081Sasomers}
537261081Sasomers
538261081Sasomers/* Resize the send and receive buffers */
539261081SasomersATF_TC_WITHOUT_HEAD(resize_buffers);
540261081SasomersATF_TC_BODY(resize_buffers, tc)
541261081Sasomers{
542261081Sasomers	int s;
543261081Sasomers	int sndbuf = 12345;
544261081Sasomers	int rcvbuf = 23456;
545261081Sasomers	int xs, xr;
546261081Sasomers	socklen_t sl = sizeof(xs);
547261081Sasomers
548261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
549261081Sasomers	ATF_REQUIRE(s >= 0);
550261081Sasomers
551261081Sasomers	printf("                       Socket Buffer Sizes\n");
552261081Sasomers	printf("                              | SNDBUF  | RCVBUF  |\n");
553261081Sasomers	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
554261081Sasomers	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
555261081Sasomers	printf("Default                       | %7d | %7d |\n", xs, xr);
556261081Sasomers
557261081Sasomers	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) != 0){
558261081Sasomers		perror("setsockopt");
559261081Sasomers		atf_tc_fail("setsockopt(SO_SNDBUF) failed");
560261081Sasomers	}
561261081Sasomers	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
562261081Sasomers	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
563261081Sasomers	printf("After changing SNDBUF         | %7d | %7d |\n", xs, xr);
564293143Sngie
565261081Sasomers	if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) != 0){
566261081Sasomers		perror("setsockopt");
567261081Sasomers		atf_tc_fail("setsockopt(SO_RCVBUF) failed");
568261081Sasomers	}
569261081Sasomers	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
570261081Sasomers	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
571261081Sasomers	printf("After changing RCVBUF         | %7d | %7d |\n", xs, xr);
572293275Sngie	close(s);
573261081Sasomers}
574261081Sasomers
575261081Sasomers/*
576261081Sasomers * Resize the send and receive buffers of a connected socketpair
577261081Sasomers * Print some useful debugging info too
578261081Sasomers */
579261081SasomersATF_TC_WITHOUT_HEAD(resize_connected_buffers);
580261081SasomersATF_TC_BODY(resize_connected_buffers, tc)
581261081Sasomers{
582261081Sasomers	int sv[2];
583261081Sasomers	int sndbuf = 12345;
584261081Sasomers	int rcvbuf = 23456;
585261081Sasomers	int err;
586261081Sasomers	int ls, lr, rs, rr;
587261081Sasomers	socklen_t sl = sizeof(ls);
588261081Sasomers
589261081Sasomers	/* setup the socket pair */
590261081Sasomers	do_socketpair(sv);
591261081Sasomers
592261081Sasomers	printf("                       Socket Buffer Sizes\n");
593261081Sasomers	printf("                              | Left Socket       | Right Socket      |\n");
594261081Sasomers	printf("                              | SNDBUF  | RCVBUF  | SNDBUF  | RCVBUF  |\n");
595261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
596261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
597261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
598261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
599261081Sasomers	printf("Default                       | %7d | %7d | %7d | %7d |\n",
600261081Sasomers	    ls, lr, rs, rr);
601261081Sasomers
602261081Sasomers	/* Update one side's send buffer */
603261081Sasomers	err = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
604261081Sasomers	if (err != 0){
605261081Sasomers		perror("setsockopt");
606261081Sasomers		atf_tc_fail("setsockopt(SO_SNDBUF) failed");
607261081Sasomers	}
608261081Sasomers
609261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
610261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
611261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
612261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
613261081Sasomers	printf("After changing Left's SNDBUF  | %7d | %7d | %7d | %7d |\n",
614261081Sasomers	    ls, lr, rs, rr);
615261081Sasomers
616261081Sasomers	/* Update the same side's receive buffer */
617261081Sasomers	err = setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
618261081Sasomers	if (err != 0){
619261081Sasomers		perror("setsockopt");
620261081Sasomers		atf_tc_fail("setsockopt(SO_RCVBUF) failed");
621261081Sasomers	}
622261081Sasomers
623261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
624261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
625261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
626261081Sasomers	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
627261081Sasomers	printf("After changing Left's RCVBUF  | %7d | %7d | %7d | %7d |\n",
628261081Sasomers	    ls, lr, rs, rr);
629293275Sngie	close(sv[0]);
630293275Sngie	close(sv[1]);
631261081Sasomers}
632261081Sasomers
633261081Sasomers
634261081Sasomers/* send(2) and recv(2) a single short record */
635261081SasomersATF_TC_WITHOUT_HEAD(send_recv);
636261081SasomersATF_TC_BODY(send_recv, tc)
637261081Sasomers{
638261081Sasomers	int sv[2];
639261081Sasomers	const int bufsize = 64;
640261081Sasomers	const char *data = "data";
641261081Sasomers	char recv_buf[bufsize];
642263572Sasomers	ssize_t datalen;
643261081Sasomers	ssize_t ssize, rsize;
644261081Sasomers
645261081Sasomers	/* setup the socket pair */
646261081Sasomers	do_socketpair(sv);
647261081Sasomers
648261081Sasomers	/* send and receive a small packet */
649261081Sasomers	datalen = strlen(data) + 1;	/* +1 for the null */
650261081Sasomers	ssize = send(sv[0], data, datalen, MSG_EOR);
651261081Sasomers	if (ssize < 0) {
652261081Sasomers		perror("send");
653261081Sasomers		atf_tc_fail("send returned < 0");
654261081Sasomers	}
655261081Sasomers	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
656261081Sasomers	    datalen, ssize);
657261081Sasomers
658261081Sasomers	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
659261081Sasomers	ATF_CHECK_EQ(datalen, rsize);
660293275Sngie	close(sv[0]);
661293275Sngie	close(sv[1]);
662261081Sasomers}
663261081Sasomers
664261081Sasomers/* sendto(2) and recvfrom(2) a single short record
665261081Sasomers * According to The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
666261081Sasomers * Edition, sendto(2) is exactly the same as send(2) on a connection-mode socket
667261081Sasomers *
668261081Sasomers * According to the same spec, not all protocols are required to provide the
669261081Sasomers * source addres in recvfrom(2).
670261081Sasomers */
671261081SasomersATF_TC_WITHOUT_HEAD(sendto_recvfrom);
672261081SasomersATF_TC_BODY(sendto_recvfrom, tc)
673261081Sasomers{
674261081Sasomers	const char* path;
675261081Sasomers	struct sockaddr_storage from;
676261081Sasomers	int sv[2];
677261081Sasomers	const int bufsize = 64;
678261081Sasomers	const char *data = "data";
679261081Sasomers	char recv_buf[bufsize];
680263572Sasomers	ssize_t datalen;
681261081Sasomers	ssize_t ssize, rsize;
682261081Sasomers	socklen_t fromlen;
683261081Sasomers
684261081Sasomers	/* setup the socket pair */
685261081Sasomers	path = mk_pair_of_sockets(sv);
686261081Sasomers
687261081Sasomers	/* send and receive a small packet */
688261081Sasomers	datalen = strlen(data) + 1;	/* +1 for the null */
689261081Sasomers	ssize = sendto(sv[0], data, datalen, MSG_EOR, NULL, 0);
690261081Sasomers	if (ssize < 0) {
691261081Sasomers		perror("send");
692261081Sasomers		atf_tc_fail("send returned < 0");
693261081Sasomers	}
694261081Sasomers	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
695261081Sasomers	    datalen, ssize);
696261081Sasomers
697261081Sasomers	fromlen = sizeof(from);
698261081Sasomers	rsize = recvfrom(sv[1], recv_buf, bufsize, MSG_WAITALL,
699261081Sasomers	    (struct sockaddr*)&from, &fromlen);
700261081Sasomers	if (ssize < 0) {
701261081Sasomers		perror("recvfrom");
702261081Sasomers		atf_tc_fail("recvfrom returned < 0");
703261081Sasomers	}
704261081Sasomers	ATF_CHECK_EQ(datalen, rsize);
705261081Sasomers
706293143Sngie	/*
707261081Sasomers	 * FreeBSD does not currently provide the source address for SEQ_PACKET
708261081Sasomers	 * AF_UNIX sockets, and POSIX does not require it, so these two checks
709261081Sasomers	 * are disabled.  If FreeBSD gains that feature in the future, then
710261081Sasomers	 * these checks may be reenabled
711261081Sasomers	 */
712261081Sasomers	/* ATF_CHECK_EQ(PF_LOCAL, from.ss_family); */
713261081Sasomers	/* ATF_CHECK_STREQ(path, ((struct sockaddr_un*)&from)->sun_path); */
714293275Sngie	close(sv[0]);
715293275Sngie	close(sv[1]);
716261081Sasomers}
717261081Sasomers
718293143Sngie/*
719261081Sasomers * send(2) and recv(2) a single short record with sockets created the
720261081Sasomers * traditional way, involving bind, listen, connect, and accept
721261081Sasomers */
722261081SasomersATF_TC_WITHOUT_HEAD(send_recv_with_connect);
723261081SasomersATF_TC_BODY(send_recv_with_connect, tc)
724261081Sasomers{
725261081Sasomers	int sv[2];
726261081Sasomers	const int bufsize = 64;
727261081Sasomers	const char *data = "data";
728261081Sasomers	char recv_buf[bufsize];
729263572Sasomers	ssize_t datalen;
730261081Sasomers	ssize_t ssize, rsize;
731261081Sasomers
732261081Sasomers	mk_pair_of_sockets(sv);
733261081Sasomers
734261081Sasomers	/* send and receive a small packet */
735261081Sasomers	datalen = strlen(data) + 1;	/* +1 for the null */
736261081Sasomers	ssize = send(sv[0], data, datalen, MSG_EOR);
737261081Sasomers	if (ssize < 0) {
738261081Sasomers		perror("send");
739261081Sasomers		atf_tc_fail("send returned < 0");
740261081Sasomers	}
741261081Sasomers	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
742261081Sasomers	    datalen, ssize);
743261081Sasomers
744261081Sasomers	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
745261081Sasomers	ATF_CHECK_EQ(datalen, rsize);
746293275Sngie	close(sv[0]);
747293275Sngie	close(sv[1]);
748261081Sasomers}
749261081Sasomers
750261081Sasomers/* send(2) should fail on a shutdown socket */
751261081SasomersATF_TC_WITHOUT_HEAD(shutdown_send);
752261081SasomersATF_TC_BODY(shutdown_send, tc)
753261081Sasomers{
754261081Sasomers	int s;
755293275Sngie	const char data[] = "data";
756261081Sasomers	ssize_t ssize;
757261081Sasomers
758261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
759293275Sngie	ATF_REQUIRE(s >= 0);
760261081Sasomers	ATF_CHECK_EQ(0, shutdown(s, SHUT_RDWR));
761261081Sasomers	/* USE MSG_NOSIGNAL so we don't get SIGPIPE */
762261081Sasomers	ssize = send(s, data, sizeof(data), MSG_EOR | MSG_NOSIGNAL);
763261081Sasomers	ATF_CHECK_EQ(EPIPE, errno);
764261081Sasomers	ATF_CHECK_EQ(-1, ssize);
765293275Sngie	close(s);
766261081Sasomers}
767261081Sasomers
768261081Sasomers/* send(2) should cause SIGPIPE on a shutdown socket */
769261081SasomersATF_TC_WITHOUT_HEAD(shutdown_send_sigpipe);
770261081SasomersATF_TC_BODY(shutdown_send_sigpipe, tc)
771261081Sasomers{
772261081Sasomers	int s;
773293275Sngie	const char data[] = "data";
774261081Sasomers	ssize_t ssize;
775261081Sasomers
776261081Sasomers	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
777293275Sngie	ATF_REQUIRE(s >= 0);
778261081Sasomers	ATF_CHECK_EQ(0, shutdown(s, SHUT_RDWR));
779261081Sasomers	ATF_REQUIRE(SIG_ERR != signal(SIGPIPE, shutdown_send_sigpipe_handler));
780261081Sasomers	ssize = send(s, data, sizeof(data), MSG_EOR);
781261081Sasomers	ATF_CHECK_EQ(1, got_sigpipe);
782293275Sngie	close(s);
783261081Sasomers}
784261081Sasomers
785261081Sasomers/* nonblocking send(2) and recv(2) a single short record */
786261081SasomersATF_TC_WITHOUT_HEAD(send_recv_nonblocking);
787261081SasomersATF_TC_BODY(send_recv_nonblocking, tc)
788261081Sasomers{
789261081Sasomers	int sv[2];
790261081Sasomers	const int bufsize = 64;
791261081Sasomers	const char *data = "data";
792261081Sasomers	char recv_buf[bufsize];
793263572Sasomers	ssize_t datalen;
794261081Sasomers	ssize_t ssize, rsize;
795261081Sasomers
796261081Sasomers	/* setup the socket pair */
797261081Sasomers	do_socketpair_nonblocking(sv);
798261081Sasomers
799261081Sasomers	/* Verify that there is nothing to receive */
800261081Sasomers	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
801261081Sasomers	ATF_CHECK_EQ(EAGAIN, errno);
802261081Sasomers	ATF_CHECK_EQ(-1, rsize);
803261081Sasomers
804261081Sasomers	/* send and receive a small packet */
805261081Sasomers	datalen = strlen(data) + 1;	/* +1 for the null */
806261081Sasomers	ssize = send(sv[0], data, datalen, MSG_EOR);
807261081Sasomers	if (ssize < 0) {
808261081Sasomers		perror("send");
809261081Sasomers		atf_tc_fail("send returned < 0");
810261081Sasomers	}
811261081Sasomers	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
812261081Sasomers	    datalen, ssize);
813261081Sasomers
814261081Sasomers	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
815261081Sasomers	ATF_CHECK_EQ(datalen, rsize);
816293275Sngie	close(sv[0]);
817293275Sngie	close(sv[1]);
818261081Sasomers}
819261081Sasomers
820293143Sngie/*
821261081Sasomers * We should get EMSGSIZE if we try to send a message larger than the socket
822261081Sasomers * buffer, with blocking sockets
823261081Sasomers */
824261081SasomersATF_TC_WITHOUT_HEAD(emsgsize);
825261081SasomersATF_TC_BODY(emsgsize, tc)
826261081Sasomers{
827261081Sasomers	int sv[2];
828317834Sbrooks	const int sndbufsize = 8192;
829317834Sbrooks	const int rcvbufsize = 8192;
830261081Sasomers	const size_t pktsize = (sndbufsize + rcvbufsize) * 2;
831261081Sasomers	char sndbuf[pktsize];
832263572Sasomers	ssize_t ssize;
833261081Sasomers
834261081Sasomers	/* setup the socket pair */
835261081Sasomers	do_socketpair(sv);
836261081Sasomers	/* Setup the buffers */
837261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
838261081Sasomers	    sizeof(sndbufsize)));
839261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
840261081Sasomers	    sizeof(rcvbufsize)));
841261081Sasomers
842261081Sasomers	ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
843261081Sasomers	ATF_CHECK_EQ(EMSGSIZE, errno);
844261081Sasomers	ATF_CHECK_EQ(-1, ssize);
845293275Sngie	close(sv[0]);
846293275Sngie	close(sv[1]);
847261081Sasomers}
848261081Sasomers
849293143Sngie/*
850261081Sasomers * We should get EMSGSIZE if we try to send a message larger than the socket
851261081Sasomers * buffer, with nonblocking sockets
852261081Sasomers */
853261081SasomersATF_TC_WITHOUT_HEAD(emsgsize_nonblocking);
854261081SasomersATF_TC_BODY(emsgsize_nonblocking, tc)
855261081Sasomers{
856261081Sasomers	int sv[2];
857317834Sbrooks	const int sndbufsize = 8192;
858317834Sbrooks	const int rcvbufsize = 8192;
859261081Sasomers	const size_t pktsize = (sndbufsize + rcvbufsize) * 2;
860261081Sasomers	char sndbuf[pktsize];
861263572Sasomers	ssize_t ssize;
862261081Sasomers
863261081Sasomers	/* setup the socket pair */
864261081Sasomers	do_socketpair_nonblocking(sv);
865261081Sasomers	/* Setup the buffers */
866261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
867261081Sasomers	    sizeof(sndbufsize)));
868261081Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
869261081Sasomers	    sizeof(rcvbufsize)));
870261081Sasomers
871261081Sasomers	ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
872261081Sasomers	ATF_CHECK_EQ(EMSGSIZE, errno);
873261081Sasomers	ATF_CHECK_EQ(-1, ssize);
874293275Sngie	close(sv[0]);
875293275Sngie	close(sv[1]);
876261081Sasomers}
877261081Sasomers
878261081Sasomers
879293143Sngie/*
880261081Sasomers * We should get EAGAIN if we try to send a message larger than the socket
881261081Sasomers * buffer, with nonblocking sockets.  Test with several different sockbuf sizes
882261081Sasomers */
883261081SasomersATF_TC_WITHOUT_HEAD(eagain_8k_8k);
884261081SasomersATF_TC_BODY(eagain_8k_8k, tc)
885261081Sasomers{
886261081Sasomers	test_eagain(8192, 8192);
887261081Sasomers}
888261081SasomersATF_TC_WITHOUT_HEAD(eagain_8k_128k);
889261081SasomersATF_TC_BODY(eagain_8k_128k, tc)
890261081Sasomers{
891261081Sasomers	test_eagain(8192, 131072);
892261081Sasomers}
893261081SasomersATF_TC_WITHOUT_HEAD(eagain_128k_8k);
894261081SasomersATF_TC_BODY(eagain_128k_8k, tc)
895261081Sasomers{
896261081Sasomers	test_eagain(131072, 8192);
897261081Sasomers}
898261081SasomersATF_TC_WITHOUT_HEAD(eagain_128k_128k);
899261081SasomersATF_TC_BODY(eagain_128k_128k, tc)
900261081Sasomers{
901261081Sasomers	test_eagain(131072, 131072);
902261081Sasomers}
903261081Sasomers
904261081Sasomers
905293143Sngie/*
906261081Sasomers * nonblocking send(2) and recv(2) of several records, which should collectively
907261081Sasomers * fill up the send buffer but not the receive buffer
908261081Sasomers */
909261081SasomersATF_TC_WITHOUT_HEAD(rcvbuf_oversized);
910261081SasomersATF_TC_BODY(rcvbuf_oversized, tc)
911261081Sasomers{
912263572Sasomers	int i;
913261081Sasomers	int sv[2];
914264607Sjmmv	const ssize_t pktsize = 1024;
915317834Sbrooks	const int sndbufsize = 8192;
916317834Sbrooks	const int rcvbufsize = 131072;
917263572Sasomers	const size_t geometric_mean_bufsize = 32768;
918263572Sasomers	const int numpkts = geometric_mean_bufsize / pktsize;
919261081Sasomers	char sndbuf[pktsize];
920261081Sasomers	char recv_buf[pktsize];
921261081Sasomers	ssize_t ssize, rsize;
922261081Sasomers
923261081Sasomers	/* setup the socket pair */
924261081Sasomers	do_socketpair_nonblocking(sv);
925263572Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
926263572Sasomers	    sizeof(sndbufsize)));
927263572Sasomers	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
928263572Sasomers	    sizeof(rcvbufsize)));
929261081Sasomers
930293143Sngie	/*
931261081Sasomers	 * Send and receive packets that are collectively greater than the send
932261081Sasomers	 * buffer, but less than the receive buffer
933261081Sasomers	 */
934263572Sasomers	for (i=0; i < numpkts; i++) {
935261081Sasomers		/* Fill the buffer */
936261081Sasomers		memset(sndbuf, i, pktsize);
937261081Sasomers
938261081Sasomers		/* send the packet */
939261081Sasomers		ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
940261081Sasomers		if (ssize < 0) {
941261081Sasomers			perror("send");
942261081Sasomers			atf_tc_fail("send returned < 0");
943261081Sasomers		}
944261081Sasomers		ATF_CHECK_EQ_MSG(pktsize, ssize,
945261081Sasomers		    "expected %zd=send(...) but got %zd", pktsize, ssize);
946261081Sasomers
947261081Sasomers		/* Receive it */
948261081Sasomers
949261081Sasomers		rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
950261081Sasomers		if (rsize < 0) {
951261081Sasomers			perror("recv");
952261081Sasomers			atf_tc_fail("recv returned < 0");
953261081Sasomers		}
954261081Sasomers		ATF_CHECK_EQ_MSG(pktsize, rsize,
955261081Sasomers		    "expected %zd=send(...) but got %zd", pktsize, rsize);
956261081Sasomers
957261081Sasomers		/* Verify the contents */
958293143Sngie		ATF_CHECK_EQ_MSG(0, memcmp(sndbuf, recv_buf, pktsize),
959261081Sasomers		    "Received data miscompare");
960261081Sasomers	}
961261081Sasomers
962261081Sasomers	/* Trying to receive again should return EAGAIN */
963261081Sasomers	rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
964261081Sasomers	ATF_CHECK_EQ(EAGAIN, errno);
965261081Sasomers	ATF_CHECK_EQ(-1, rsize);
966293275Sngie	close(sv[0]);
967293275Sngie	close(sv[1]);
968261081Sasomers}
969261081Sasomers
970293143Sngie/*
971261081Sasomers * Simulate the behavior of a blocking pipe.  The sender will send until his
972261081Sasomers * buffer fills up, then we'll simulate a scheduler switch that will allow the
973261081Sasomers * receiver to read until his buffer empties.  Repeat the process until the
974261081Sasomers * transfer is complete.
975261081Sasomers * Repeat the test with multiple send and receive buffer sizes
976261081Sasomers */
977261081SasomersATF_TC_WITHOUT_HEAD(pipe_simulator_8k_8k);
978261081SasomersATF_TC_BODY(pipe_simulator_8k_8k, tc)
979261081Sasomers{
980261081Sasomers	test_pipe_simulator(8192, 8192);
981261081Sasomers}
982261081Sasomers
983261081SasomersATF_TC_WITHOUT_HEAD(pipe_simulator_8k_128k);
984261081SasomersATF_TC_BODY(pipe_simulator_8k_128k, tc)
985261081Sasomers{
986261081Sasomers	test_pipe_simulator(8192, 131072);
987261081Sasomers}
988261081Sasomers
989261081SasomersATF_TC_WITHOUT_HEAD(pipe_simulator_128k_8k);
990261081SasomersATF_TC_BODY(pipe_simulator_128k_8k, tc)
991261081Sasomers{
992261081Sasomers	test_pipe_simulator(131072, 8192);
993261081Sasomers}
994261081Sasomers
995261081SasomersATF_TC_WITHOUT_HEAD(pipe_simulator_128k_128k);
996261081SasomersATF_TC_BODY(pipe_simulator_128k_128k, tc)
997261081Sasomers{
998261081Sasomers	test_pipe_simulator(131072, 131072);
999261081Sasomers}
1000261081Sasomers
1001293143Sngie/*
1002261081Sasomers * Test blocking I/O by passing data between two threads.  The total amount of
1003261081Sasomers * data will be >> buffer size to force blocking.  Repeat the test with multiple
1004261081Sasomers * send and receive buffer sizes
1005261081Sasomers */
1006261081SasomersATF_TC_WITHOUT_HEAD(pipe_8k_8k);
1007261081SasomersATF_TC_BODY(pipe_8k_8k, tc)
1008261081Sasomers{
1009261081Sasomers	test_pipe(8192, 8192);
1010261081Sasomers}
1011261081Sasomers
1012261081SasomersATF_TC_WITHOUT_HEAD(pipe_8k_128k);
1013261081SasomersATF_TC_BODY(pipe_8k_128k, tc)
1014261081Sasomers{
1015261081Sasomers	test_pipe(8192, 131072);
1016261081Sasomers}
1017261081Sasomers
1018261081SasomersATF_TC_WITHOUT_HEAD(pipe_128k_8k);
1019261081SasomersATF_TC_BODY(pipe_128k_8k, tc)
1020261081Sasomers{
1021261081Sasomers	test_pipe(131072, 8192);
1022261081Sasomers}
1023261081Sasomers
1024261081SasomersATF_TC_WITHOUT_HEAD(pipe_128k_128k);
1025261081SasomersATF_TC_BODY(pipe_128k_128k, tc)
1026261081Sasomers{
1027261081Sasomers	test_pipe(131072, 131072);
1028261081Sasomers}
1029261081Sasomers
1030261081Sasomers
1031261081Sasomers/*
1032261081Sasomers * Test single-packet I/O with and without blocking, with symmetric buffers of
1033261081Sasomers * various sizes
1034261081Sasomers */
1035261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_8k);
1036261081SasomersATF_TC_BODY(sendrecv_8k, tc)
1037261081Sasomers{
1038261081Sasomers	test_sendrecv_symmetric_buffers(8 * 1024, true);
1039261081Sasomers}
1040261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_16k);
1041261081SasomersATF_TC_BODY(sendrecv_16k, tc)
1042261081Sasomers{
1043261081Sasomers	test_sendrecv_symmetric_buffers(16 * 1024, true);
1044261081Sasomers}
1045261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_32k);
1046261081SasomersATF_TC_BODY(sendrecv_32k, tc)
1047261081Sasomers{
1048261081Sasomers	test_sendrecv_symmetric_buffers(32 * 1024, true);
1049261081Sasomers}
1050261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_64k);
1051261081SasomersATF_TC_BODY(sendrecv_64k, tc)
1052261081Sasomers{
1053261081Sasomers	test_sendrecv_symmetric_buffers(64 * 1024, true);
1054261081Sasomers}
1055261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_128k);
1056261081SasomersATF_TC_BODY(sendrecv_128k, tc)
1057261081Sasomers{
1058261081Sasomers	test_sendrecv_symmetric_buffers(128 * 1024, true);
1059261081Sasomers}
1060261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_8k_nonblocking);
1061261081SasomersATF_TC_BODY(sendrecv_8k_nonblocking, tc)
1062261081Sasomers{
1063261081Sasomers	test_sendrecv_symmetric_buffers(8 * 1024, false);
1064261081Sasomers}
1065261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_16k_nonblocking);
1066261081SasomersATF_TC_BODY(sendrecv_16k_nonblocking, tc)
1067261081Sasomers{
1068261081Sasomers	test_sendrecv_symmetric_buffers(16 * 1024, false);
1069261081Sasomers}
1070261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_32k_nonblocking);
1071261081SasomersATF_TC_BODY(sendrecv_32k_nonblocking, tc)
1072261081Sasomers{
1073261081Sasomers	test_sendrecv_symmetric_buffers(32 * 1024, false);
1074261081Sasomers}
1075261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_64k_nonblocking);
1076261081SasomersATF_TC_BODY(sendrecv_64k_nonblocking, tc)
1077261081Sasomers{
1078261081Sasomers	test_sendrecv_symmetric_buffers(64 * 1024, false);
1079261081Sasomers}
1080261081SasomersATF_TC_WITHOUT_HEAD(sendrecv_128k_nonblocking);
1081261081SasomersATF_TC_BODY(sendrecv_128k_nonblocking, tc)
1082261081Sasomers{
1083261081Sasomers	test_sendrecv_symmetric_buffers(128 * 1024, false);
1084261081Sasomers}
1085261081Sasomers
1086261081Sasomers
1087261081Sasomers/*
1088261081Sasomers * Main.
1089261081Sasomers */
1090261081Sasomers
1091261081SasomersATF_TP_ADD_TCS(tp)
1092261081Sasomers{
1093261081Sasomers	/* Basic creation and connection tests */
1094261081Sasomers	ATF_TP_ADD_TC(tp, create_socket);
1095261081Sasomers	ATF_TP_ADD_TC(tp, create_socketpair);
1096261081Sasomers	ATF_TP_ADD_TC(tp, listen_unbound);
1097261081Sasomers	ATF_TP_ADD_TC(tp, bind);
1098261081Sasomers	ATF_TP_ADD_TC(tp, listen_bound);
1099261081Sasomers	ATF_TP_ADD_TC(tp, connect);
1100261081Sasomers	ATF_TP_ADD_TC(tp, accept);
1101261081Sasomers	ATF_TP_ADD_TC(tp, fcntl_nonblock);
1102261081Sasomers	ATF_TP_ADD_TC(tp, resize_buffers);
1103261081Sasomers	ATF_TP_ADD_TC(tp, resize_connected_buffers);
1104261081Sasomers
1105261081Sasomers	/* Unthreaded I/O tests */
1106261081Sasomers	ATF_TP_ADD_TC(tp, send_recv);
1107261081Sasomers	ATF_TP_ADD_TC(tp, send_recv_nonblocking);
1108261081Sasomers	ATF_TP_ADD_TC(tp, send_recv_with_connect);
1109261081Sasomers	ATF_TP_ADD_TC(tp, sendto_recvfrom);
1110261081Sasomers	ATF_TP_ADD_TC(tp, shutdown_send);
1111261081Sasomers	ATF_TP_ADD_TC(tp, shutdown_send_sigpipe);
1112261081Sasomers	ATF_TP_ADD_TC(tp, emsgsize);
1113261081Sasomers	ATF_TP_ADD_TC(tp, emsgsize_nonblocking);
1114261081Sasomers	ATF_TP_ADD_TC(tp, eagain_8k_8k);
1115261081Sasomers	ATF_TP_ADD_TC(tp, eagain_8k_128k);
1116261081Sasomers	ATF_TP_ADD_TC(tp, eagain_128k_8k);
1117261081Sasomers	ATF_TP_ADD_TC(tp, eagain_128k_128k);
1118261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_8k);
1119261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_16k);
1120261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_32k);
1121261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_64k);
1122261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_128k);
1123261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_8k_nonblocking);
1124261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_16k_nonblocking);
1125261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_32k_nonblocking);
1126261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_64k_nonblocking);
1127261081Sasomers	ATF_TP_ADD_TC(tp, sendrecv_128k_nonblocking);
1128261081Sasomers	ATF_TP_ADD_TC(tp, rcvbuf_oversized);
1129261081Sasomers	ATF_TP_ADD_TC(tp, pipe_simulator_8k_8k);
1130261081Sasomers	ATF_TP_ADD_TC(tp, pipe_simulator_8k_128k);
1131261081Sasomers	ATF_TP_ADD_TC(tp, pipe_simulator_128k_8k);
1132261081Sasomers	ATF_TP_ADD_TC(tp, pipe_simulator_128k_128k);
1133261081Sasomers
1134261081Sasomers	/* Threaded I/O tests with blocking sockets */
1135261081Sasomers	ATF_TP_ADD_TC(tp, pipe_8k_8k);
1136261081Sasomers	ATF_TP_ADD_TC(tp, pipe_8k_128k);
1137261081Sasomers	ATF_TP_ADD_TC(tp, pipe_128k_8k);
1138261081Sasomers	ATF_TP_ADD_TC(tp, pipe_128k_128k);
1139261081Sasomers
1140261081Sasomers	return atf_no_error();
1141261081Sasomers}
1142