1a8eb96d5SAlan Somers /*-
2eb338e23SGleb Smirnoff  *
3eb338e23SGleb Smirnoff  * Copyright (c) 2024 Gleb Smirnoff <glebius@FreeBSD.org>
4a8eb96d5SAlan Somers  * Copyright (c) 2014 Spectra Logic Corporation. All rights reserved.
5eb338e23SGleb Smirnoff  *
6a8eb96d5SAlan Somers  * Redistribution and use in source and binary forms, with or without
7a8eb96d5SAlan Somers  * modification, are permitted provided that the following conditions
8a8eb96d5SAlan Somers  * are met:
9a8eb96d5SAlan Somers  * 1. Redistributions of source code must retain the above copyright
10a8eb96d5SAlan Somers  *    notice, this list of conditions and the following disclaimer.
11a8eb96d5SAlan Somers  * 2. Redistributions in binary form must reproduce the above copyright
12a8eb96d5SAlan Somers  *    notice, this list of conditions and the following disclaimer in the
13a8eb96d5SAlan Somers  *    documentation and/or other materials provided with the distribution.
14a8eb96d5SAlan Somers  *
15a8eb96d5SAlan Somers  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16a8eb96d5SAlan Somers  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17a8eb96d5SAlan Somers  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18a8eb96d5SAlan Somers  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
19a8eb96d5SAlan Somers  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20a8eb96d5SAlan Somers  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21a8eb96d5SAlan Somers  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22a8eb96d5SAlan Somers  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23a8eb96d5SAlan Somers  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24a8eb96d5SAlan Somers  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25a8eb96d5SAlan Somers  * SUCH DAMAGE.
26a8eb96d5SAlan Somers  */
27a8eb96d5SAlan Somers 
28a8eb96d5SAlan Somers #include <sys/cdefs.h>
29a8eb96d5SAlan Somers #include <errno.h>
30a8eb96d5SAlan Somers #include <fcntl.h>
31a8eb96d5SAlan Somers #include <pthread.h>
32a8eb96d5SAlan Somers #include <signal.h>
33eb338e23SGleb Smirnoff #include <stdlib.h>
34a8eb96d5SAlan Somers #include <sys/socket.h>
35eb338e23SGleb Smirnoff #include <sys/sysctl.h>
36a8eb96d5SAlan Somers #include <sys/un.h>
37a8eb96d5SAlan Somers 
38a8eb96d5SAlan Somers #include <stdio.h>
39a8eb96d5SAlan Somers 
40a8eb96d5SAlan Somers #include <atf-c.h>
41a8eb96d5SAlan Somers 
42a8eb96d5SAlan Somers /*
43a8eb96d5SAlan Somers  * Helper functions
44a8eb96d5SAlan Somers  */
45a8eb96d5SAlan Somers 
46a8eb96d5SAlan Somers #define MIN(x, y)	((x) < (y) ? (x) : (y))
47a8eb96d5SAlan Somers #define MAX(x, y)	((x) > (y) ? (x) : (y))
48a8eb96d5SAlan Somers 
495d5b721aSAlan Somers static void
do_socketpair(int * sv)50a8eb96d5SAlan Somers do_socketpair(int *sv)
51a8eb96d5SAlan Somers {
52a8eb96d5SAlan Somers 	int s;
53a8eb96d5SAlan Somers 
54a8eb96d5SAlan Somers 	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
55a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, s);
56a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[0] >= 0);
57a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[1] >= 0);
58a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[0] != sv[1]);
59a8eb96d5SAlan Somers }
60a8eb96d5SAlan Somers 
615d5b721aSAlan Somers static void
do_socketpair_nonblocking(int * sv)62a8eb96d5SAlan Somers do_socketpair_nonblocking(int *sv)
63a8eb96d5SAlan Somers {
64a8eb96d5SAlan Somers 	int s;
65a8eb96d5SAlan Somers 
66a8eb96d5SAlan Somers 	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
67a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, s);
68a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[0] >= 0);
69a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[1] >= 0);
70a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[0] != sv[1]);
71a8eb96d5SAlan Somers 	ATF_REQUIRE(-1 != fcntl(sv[0], F_SETFL, O_NONBLOCK));
72a8eb96d5SAlan Somers 	ATF_REQUIRE(-1 != fcntl(sv[1], F_SETFL, O_NONBLOCK));
73a8eb96d5SAlan Somers }
74a8eb96d5SAlan Somers 
75a8eb96d5SAlan Somers /*
761f46c32cSGleb Smirnoff  * Returns a bound and listening socket.
77a8eb96d5SAlan Somers  * @return	const char* The path to the socket
78a8eb96d5SAlan Somers  */
791f46c32cSGleb Smirnoff static const struct sockaddr_un *
mk_listening_socket(int * sv)801f46c32cSGleb Smirnoff mk_listening_socket(int *sv)
81a8eb96d5SAlan Somers {
82a8eb96d5SAlan Somers 	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
831f46c32cSGleb Smirnoff 	static const struct sockaddr_un sun = {
841f46c32cSGleb Smirnoff 		.sun_family = AF_LOCAL,
851f46c32cSGleb Smirnoff 		.sun_len = sizeof(sun),
861f46c32cSGleb Smirnoff 		.sun_path = "sock",
871f46c32cSGleb Smirnoff 	};
881f46c32cSGleb Smirnoff 	int s, r, l;
89a8eb96d5SAlan Somers 
90a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
91a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
92a8eb96d5SAlan Somers 
931f46c32cSGleb Smirnoff 	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
941f46c32cSGleb Smirnoff 	l = listen(s, -1);
951f46c32cSGleb Smirnoff 	ATF_CHECK_EQ(0, r);
961f46c32cSGleb Smirnoff 	ATF_CHECK_EQ(0, l);
971f46c32cSGleb Smirnoff 
981f46c32cSGleb Smirnoff 	if (sv != NULL)
991f46c32cSGleb Smirnoff 		*sv = s;
1001f46c32cSGleb Smirnoff 
1011f46c32cSGleb Smirnoff 	return (&sun);
1021f46c32cSGleb Smirnoff }
1031f46c32cSGleb Smirnoff 
1041f46c32cSGleb Smirnoff /*
1051f46c32cSGleb Smirnoff  * Returns a pair of sockets made the hard way: bind, listen, connect & accept
1061f46c32cSGleb Smirnoff  * @return	const char* The path to the socket
1071f46c32cSGleb Smirnoff  */
1081f46c32cSGleb Smirnoff static const struct sockaddr_un *
mk_pair_of_sockets(int * sv)1091f46c32cSGleb Smirnoff mk_pair_of_sockets(int *sv)
1101f46c32cSGleb Smirnoff {
1111f46c32cSGleb Smirnoff 	const struct sockaddr_un *sun;
1121f46c32cSGleb Smirnoff 	int s, s2, err, s1;
1131f46c32cSGleb Smirnoff 
1141f46c32cSGleb Smirnoff 	sun = mk_listening_socket(&s);
115a8eb96d5SAlan Somers 
116a8eb96d5SAlan Somers 	/* Create the other socket */
117a8eb96d5SAlan Somers 	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
118a8eb96d5SAlan Somers 	ATF_REQUIRE(s2 >= 0);
1191f46c32cSGleb Smirnoff 	err = connect(s2, (struct sockaddr *)sun, sizeof(*sun));
120a8eb96d5SAlan Somers 	if (err != 0) {
121a8eb96d5SAlan Somers 		perror("connect");
122a8eb96d5SAlan Somers 		atf_tc_fail("connect(2) failed");
123a8eb96d5SAlan Somers 	}
124a8eb96d5SAlan Somers 
125a8eb96d5SAlan Somers 	/* Accept it */
126a8eb96d5SAlan Somers 	s1 = accept(s, NULL, NULL);
127a8eb96d5SAlan Somers 	if (s1 == -1) {
128a8eb96d5SAlan Somers 		perror("accept");
129a8eb96d5SAlan Somers 		atf_tc_fail("accept(2) failed");
130a8eb96d5SAlan Somers 	}
131a8eb96d5SAlan Somers 
132a8eb96d5SAlan Somers 	sv[0] = s1;
133a8eb96d5SAlan Somers 	sv[1] = s2;
134e594026dSAlan Somers 
135e594026dSAlan Somers 	close(s);
136e594026dSAlan Somers 
1371f46c32cSGleb Smirnoff 	return (sun);
138a8eb96d5SAlan Somers }
139a8eb96d5SAlan Somers 
140a8eb96d5SAlan Somers static volatile sig_atomic_t got_sigpipe = 0;
141a8eb96d5SAlan Somers static void
shutdown_send_sigpipe_handler(int __unused x)1425d5b721aSAlan Somers shutdown_send_sigpipe_handler(int __unused x)
143a8eb96d5SAlan Somers {
144a8eb96d5SAlan Somers 	got_sigpipe = 1;
145a8eb96d5SAlan Somers }
146a8eb96d5SAlan Somers 
147a8eb96d5SAlan Somers /*
148a8eb96d5SAlan Somers  * Parameterized test function bodies
149a8eb96d5SAlan Somers  */
1505d5b721aSAlan Somers static void
test_eagain(int sndbufsize,int rcvbufsize)151ea703329SBrooks Davis test_eagain(int sndbufsize, int rcvbufsize)
152a8eb96d5SAlan Somers {
153a8eb96d5SAlan Somers 	int i;
154a8eb96d5SAlan Somers 	int sv[2];
155a8eb96d5SAlan Somers 	const size_t totalsize = (sndbufsize + rcvbufsize) * 2;
156a8eb96d5SAlan Somers 	const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
1575d5b721aSAlan Somers 	const int numpkts = totalsize / pktsize;
158a8eb96d5SAlan Somers 	char sndbuf[pktsize];
1595d5b721aSAlan Somers 	ssize_t ssize;
160a8eb96d5SAlan Somers 
161a8eb96d5SAlan Somers 	/* setup the socket pair */
162b9a9db10SAlan Somers 	do_socketpair_nonblocking(sv);
163a8eb96d5SAlan Somers 	/* Setup the buffers */
164a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
165a8eb96d5SAlan Somers 	    sizeof(sndbufsize)));
166a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
167a8eb96d5SAlan Somers 	    sizeof(rcvbufsize)));
168a8eb96d5SAlan Somers 
169a8eb96d5SAlan Somers 	bzero(sndbuf, pktsize);
170a8eb96d5SAlan Somers 	/* Send data until we get EAGAIN */
1715d5b721aSAlan Somers 	for(i=0; i < numpkts; i++) {
172a8eb96d5SAlan Somers 		ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
173a8eb96d5SAlan Somers 		if (ssize == -1) {
174e594026dSAlan Somers 			if (errno == EAGAIN) {
175e594026dSAlan Somers 				close(sv[0]);
176e594026dSAlan Somers 				close(sv[1]);
177a8eb96d5SAlan Somers 				atf_tc_pass();
178e594026dSAlan Somers 			}
179a8eb96d5SAlan Somers 			else {
180a8eb96d5SAlan Somers 				perror("send");
181a8eb96d5SAlan Somers 				atf_tc_fail("send returned < 0 but not EAGAIN");
182a8eb96d5SAlan Somers 			}
183a8eb96d5SAlan Somers 		}
184a8eb96d5SAlan Somers 	}
185a8eb96d5SAlan Somers 	atf_tc_fail("Never got EAGAIN");
186a8eb96d5SAlan Somers }
187a8eb96d5SAlan Somers 
1885d5b721aSAlan Somers static void
test_sendrecv_symmetric_buffers(int bufsize,int blocking)189ea703329SBrooks Davis test_sendrecv_symmetric_buffers(int bufsize, int blocking) {
190a8eb96d5SAlan Somers 	int s;
191a8eb96d5SAlan Somers 	int sv[2];
1925d5b721aSAlan Somers 	const ssize_t pktsize = bufsize / 2;
193a8eb96d5SAlan Somers 	char sndbuf[pktsize];
194a8eb96d5SAlan Somers 	char recv_buf[pktsize];
195a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
196a8eb96d5SAlan Somers 
197a8eb96d5SAlan Somers 	/* setup the socket pair */
198a8eb96d5SAlan Somers 	if (blocking)
199a8eb96d5SAlan Somers 		do_socketpair(sv);
200a8eb96d5SAlan Somers 	else
201a8eb96d5SAlan Somers 		do_socketpair_nonblocking(sv);
202a8eb96d5SAlan Somers 
203a8eb96d5SAlan Somers 	/* Setup the buffers */
204a8eb96d5SAlan Somers 	s = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
205a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, s);
206a8eb96d5SAlan Somers 	s = setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
207a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, s);
208a8eb96d5SAlan Somers 
209a8eb96d5SAlan Somers 	/* Fill the send buffer */
210a8eb96d5SAlan Somers 	bzero(sndbuf, pktsize);
211a8eb96d5SAlan Somers 
212a8eb96d5SAlan Somers 	/* send and receive the packet */
213a8eb96d5SAlan Somers 	ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
214a8eb96d5SAlan Somers 	if (ssize < 0) {
215a8eb96d5SAlan Somers 		perror("send");
216a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
217a8eb96d5SAlan Somers 	}
218a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(pktsize, ssize, "expected %zd=send(...) but got %zd",
219a8eb96d5SAlan Somers 	    pktsize, ssize);
220a8eb96d5SAlan Somers 
221a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
222a8eb96d5SAlan Somers 	if (rsize < 0) {
223a8eb96d5SAlan Somers 		perror("recv");
224a8eb96d5SAlan Somers 		atf_tc_fail("recv returned < 0");
225a8eb96d5SAlan Somers 	}
226a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(pktsize, rsize, "expected %zd=send(...) but got %zd",
227a8eb96d5SAlan Somers 	    pktsize, rsize);
228e594026dSAlan Somers 	close(sv[0]);
229e594026dSAlan Somers 	close(sv[1]);
230a8eb96d5SAlan Somers }
231a8eb96d5SAlan Somers 
2325d5b721aSAlan Somers static void
test_pipe_simulator(int sndbufsize,int rcvbufsize)233ea703329SBrooks Davis test_pipe_simulator(int sndbufsize, int rcvbufsize)
234a8eb96d5SAlan Somers {
2355d5b721aSAlan Somers 	int num_sent, num_received;
236a8eb96d5SAlan Somers 	int sv[2];
2375d5b721aSAlan Somers 	const ssize_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
238a8eb96d5SAlan Somers 	int numpkts;
239a8eb96d5SAlan Somers 	char sndbuf[pktsize];
240a8eb96d5SAlan Somers 	char rcvbuf[pktsize];
241a8eb96d5SAlan Somers 	char comparebuf[pktsize];
242a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
243a8eb96d5SAlan Somers 	bool currently_sending = true;
244a8eb96d5SAlan Somers 
245a8eb96d5SAlan Somers 	/* setup the socket pair */
246a8eb96d5SAlan Somers 	do_socketpair_nonblocking(sv);
247a8eb96d5SAlan Somers 	/* Setup the buffers */
248a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
249a8eb96d5SAlan Somers 	    sizeof(sndbufsize)));
250a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
251a8eb96d5SAlan Somers 	    sizeof(rcvbufsize)));
252a8eb96d5SAlan Somers 
253a8eb96d5SAlan Somers 	/* Send a total amount of data comfortably greater than the buffers */
254a8eb96d5SAlan Somers 	numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
255a8eb96d5SAlan Somers 	for (num_sent=0, num_received=0;
256a8eb96d5SAlan Somers 	     num_sent < numpkts || num_received < numpkts; ) {
257a8eb96d5SAlan Somers 		if (currently_sending && num_sent < numpkts) {
258a8eb96d5SAlan Somers 			/* The simulated sending process */
259a8eb96d5SAlan Somers 			/* fill the buffer */
260a8eb96d5SAlan Somers 			memset(sndbuf, num_sent, pktsize);
261a8eb96d5SAlan Somers 			ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
262a8eb96d5SAlan Somers 			if (ssize < 0) {
2630b499297SGleb Smirnoff 				if (errno == EAGAIN)
264a8eb96d5SAlan Somers 					currently_sending = false;
265a8eb96d5SAlan Somers 				else {
266a8eb96d5SAlan Somers 					perror("send");
267a8eb96d5SAlan Somers 					atf_tc_fail("send failed");
268a8eb96d5SAlan Somers 				}
269a8eb96d5SAlan Somers 			} else  {
270a8eb96d5SAlan Somers 				ATF_CHECK_EQ_MSG(pktsize, ssize,
271a8eb96d5SAlan Somers 				    "expected %zd=send(...) but got %zd",
272a8eb96d5SAlan Somers 				    pktsize, ssize);
273a8eb96d5SAlan Somers 				num_sent++;
274a8eb96d5SAlan Somers 			}
275a8eb96d5SAlan Somers 		} else {
276a8eb96d5SAlan Somers 			/* The simulated receiving process */
277a8eb96d5SAlan Somers 			rsize = recv(sv[1], rcvbuf, pktsize, MSG_WAITALL);
278a8eb96d5SAlan Somers 			if (rsize < 0) {
279a8eb96d5SAlan Somers 				if (errno == EAGAIN) {
280a8eb96d5SAlan Somers 					currently_sending = true;
281a8eb96d5SAlan Somers 					ATF_REQUIRE_MSG(num_sent < numpkts,
282a8eb96d5SAlan Somers 					    "Packets were lost!");
283a8eb96d5SAlan Somers 				}
284a8eb96d5SAlan Somers 				else {
285a8eb96d5SAlan Somers 					perror("recv");
286a8eb96d5SAlan Somers 					atf_tc_fail("recv failed");
287a8eb96d5SAlan Somers 				}
288a8eb96d5SAlan Somers 			} else  {
289a8eb96d5SAlan Somers 				ATF_CHECK_EQ_MSG(pktsize, rsize,
290a8eb96d5SAlan Somers 				    "expected %zd=recv(...) but got %zd",
291a8eb96d5SAlan Somers 				    pktsize, rsize);
292a8eb96d5SAlan Somers 				memset(comparebuf, num_received, pktsize);
293a8eb96d5SAlan Somers 				ATF_CHECK_EQ_MSG(0, memcmp(comparebuf, rcvbuf,
294a8eb96d5SAlan Somers 				    			   pktsize),
295a8eb96d5SAlan Somers 				    "Received data miscompare");
296a8eb96d5SAlan Somers 				num_received++;
297a8eb96d5SAlan Somers 			}
298a8eb96d5SAlan Somers 		}
299a8eb96d5SAlan Somers 	}
300e594026dSAlan Somers 	close(sv[0]);
301e594026dSAlan Somers 	close(sv[1]);
302a8eb96d5SAlan Somers }
303a8eb96d5SAlan Somers 
304a8eb96d5SAlan Somers typedef struct {
305a8eb96d5SAlan Somers 	ssize_t	pktsize;
306a8eb96d5SAlan Somers 	int	numpkts;
307a8eb96d5SAlan Somers 	int	so;
308a8eb96d5SAlan Somers } test_pipe_thread_data_t;
309a8eb96d5SAlan Somers 
310a8eb96d5SAlan Somers static void*
test_pipe_writer(void * args)311a8eb96d5SAlan Somers test_pipe_writer(void* args)
312a8eb96d5SAlan Somers {
313a8eb96d5SAlan Somers 	test_pipe_thread_data_t* td = args;
314a8eb96d5SAlan Somers 	char sndbuf[td->pktsize];
315a8eb96d5SAlan Somers 	ssize_t ssize;
316a8eb96d5SAlan Somers 	int i;
317a8eb96d5SAlan Somers 
318a8eb96d5SAlan Somers 	for(i=0; i < td->numpkts; i++) {
319a8eb96d5SAlan Somers 			memset(sndbuf, i, td->pktsize);
320a8eb96d5SAlan Somers 			ssize = send(td->so, sndbuf, td->pktsize, MSG_EOR);
321a8eb96d5SAlan Somers 			if (ssize < 0) {
322a8eb96d5SAlan Somers 				perror("send");
323a8eb96d5SAlan Somers 				atf_tc_fail("send returned < 0");
324a8eb96d5SAlan Somers 			}
325a8eb96d5SAlan Somers 			ATF_CHECK_EQ_MSG(td->pktsize, ssize,
326a8eb96d5SAlan Somers 			    		 "expected %zd=send(...) but got %zd",
327a8eb96d5SAlan Somers 			    		  td->pktsize, ssize);
328a8eb96d5SAlan Somers 	}
329a8eb96d5SAlan Somers 	return (0);
330a8eb96d5SAlan Somers }
331a8eb96d5SAlan Somers 
332a8eb96d5SAlan Somers static void*
test_pipe_reader(void * args)333a8eb96d5SAlan Somers test_pipe_reader(void* args)
334a8eb96d5SAlan Somers {
335a8eb96d5SAlan Somers 	test_pipe_thread_data_t* td = args;
336a8eb96d5SAlan Somers 	char rcvbuf[td->pktsize];
337a8eb96d5SAlan Somers 	char comparebuf[td->pktsize];
338a8eb96d5SAlan Somers 	ssize_t rsize;
339a8eb96d5SAlan Somers 	int i, d;
340a8eb96d5SAlan Somers 
341a8eb96d5SAlan Somers 	for(i=0; i < td->numpkts; i++) {
342a8eb96d5SAlan Somers 		memset(comparebuf, i, td->pktsize);
343a8eb96d5SAlan Somers 		rsize = recv(td->so, rcvbuf, td->pktsize, MSG_WAITALL);
344a8eb96d5SAlan Somers 		if (rsize < 0) {
345a8eb96d5SAlan Somers 			perror("recv");
346a8eb96d5SAlan Somers 			atf_tc_fail("recv returned < 0");
347a8eb96d5SAlan Somers 		}
348a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(td->pktsize, rsize,
349a8eb96d5SAlan Somers 		    		 "expected %zd=send(...) but got %zd",
350a8eb96d5SAlan Somers 				 td->pktsize, rsize);
351a8eb96d5SAlan Somers 		d = memcmp(comparebuf, rcvbuf, td->pktsize);
352a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(0, d,
353a8eb96d5SAlan Somers 		    		 "Received data miscompare on packet %d", i);
354a8eb96d5SAlan Somers 	}
355a8eb96d5SAlan Somers 	return (0);
356a8eb96d5SAlan Somers }
357a8eb96d5SAlan Somers 
358a8eb96d5SAlan Somers 
3595d5b721aSAlan Somers static void
test_pipe(int sndbufsize,int rcvbufsize)360ea703329SBrooks Davis test_pipe(int sndbufsize, int rcvbufsize)
361a8eb96d5SAlan Somers {
362a8eb96d5SAlan Somers 	test_pipe_thread_data_t writer_data, reader_data;
363a8eb96d5SAlan Somers 	pthread_t writer, reader;
364a8eb96d5SAlan Somers 	int sv[2];
365a8eb96d5SAlan Somers 	const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
366a8eb96d5SAlan Somers 	int numpkts;
367a8eb96d5SAlan Somers 
368a8eb96d5SAlan Somers 	/* setup the socket pair */
369a8eb96d5SAlan Somers 	do_socketpair(sv);
370a8eb96d5SAlan Somers 	/* Setup the buffers */
371a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
372a8eb96d5SAlan Somers 	    sizeof(sndbufsize)));
373a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
374a8eb96d5SAlan Somers 	    sizeof(rcvbufsize)));
375a8eb96d5SAlan Somers 
376a8eb96d5SAlan Somers 	/* Send a total amount of data comfortably greater than the buffers */
377a8eb96d5SAlan Somers 	numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
378a8eb96d5SAlan Somers 
379a8eb96d5SAlan Somers 	/* Start the child threads */
380a8eb96d5SAlan Somers 	writer_data.pktsize = pktsize;
381a8eb96d5SAlan Somers 	writer_data.numpkts = numpkts;
382a8eb96d5SAlan Somers 	writer_data.so = sv[0];
383a8eb96d5SAlan Somers 	reader_data.pktsize = pktsize;
384a8eb96d5SAlan Somers 	reader_data.numpkts = numpkts;
385a8eb96d5SAlan Somers 	reader_data.so = sv[1];
386a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, pthread_create(&writer, NULL, test_pipe_writer,
387a8eb96d5SAlan Somers 	    				 (void*)&writer_data));
3888de34a88SAlan Somers 	/*
3898de34a88SAlan Somers 	 * Give the writer time to start writing, and hopefully block, before
3908de34a88SAlan Somers 	 * starting the reader.  This increases the likelihood of the test case
3918de34a88SAlan Somers 	 * failing due to PR kern/185812
3928de34a88SAlan Somers 	 */
3938de34a88SAlan Somers 	usleep(1000);
394a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, pthread_create(&reader, NULL, test_pipe_reader,
395a8eb96d5SAlan Somers 	    				 (void*)&reader_data));
396a8eb96d5SAlan Somers 
397a8eb96d5SAlan Somers 	/* Join the children */
398a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, pthread_join(writer, NULL));
399a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, pthread_join(reader, NULL));
400e594026dSAlan Somers 	close(sv[0]);
401e594026dSAlan Somers 	close(sv[1]);
402a8eb96d5SAlan Somers }
403a8eb96d5SAlan Somers 
404a8eb96d5SAlan Somers 
405a8eb96d5SAlan Somers /*
406a8eb96d5SAlan Somers  * Test Cases
407a8eb96d5SAlan Somers  */
408a8eb96d5SAlan Somers 
409a8eb96d5SAlan Somers /* Create a SEQPACKET socket */
410a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(create_socket);
ATF_TC_BODY(create_socket,tc)411a8eb96d5SAlan Somers ATF_TC_BODY(create_socket, tc)
412a8eb96d5SAlan Somers {
413a8eb96d5SAlan Somers 	int s;
414a8eb96d5SAlan Somers 
415a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
4166addc01eSAlan Somers 	ATF_REQUIRE(s >= 0);
417e594026dSAlan Somers 	close(s);
418a8eb96d5SAlan Somers }
419a8eb96d5SAlan Somers 
420a8eb96d5SAlan Somers /* Create SEQPACKET sockets using socketpair(2) */
421a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(create_socketpair);
ATF_TC_BODY(create_socketpair,tc)422a8eb96d5SAlan Somers ATF_TC_BODY(create_socketpair, tc)
423a8eb96d5SAlan Somers {
424a8eb96d5SAlan Somers 	int sv[2];
425a8eb96d5SAlan Somers 	int s;
426a8eb96d5SAlan Somers 
427a8eb96d5SAlan Somers 	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
428a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, s);
429a8eb96d5SAlan Somers 	ATF_CHECK(sv[0] >= 0);
430a8eb96d5SAlan Somers 	ATF_CHECK(sv[1] >= 0);
431a8eb96d5SAlan Somers 	ATF_CHECK(sv[0] != sv[1]);
432e594026dSAlan Somers 	close(sv[0]);
433e594026dSAlan Somers 	close(sv[1]);
434a8eb96d5SAlan Somers }
435a8eb96d5SAlan Somers 
436a8eb96d5SAlan Somers /* Call listen(2) without first calling bind(2).  It should fail */
437a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(listen_unbound);
ATF_TC_BODY(listen_unbound,tc)438a8eb96d5SAlan Somers ATF_TC_BODY(listen_unbound, tc)
439a8eb96d5SAlan Somers {
440a8eb96d5SAlan Somers 	int s, r;
441a8eb96d5SAlan Somers 
442a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
443a8eb96d5SAlan Somers 	ATF_REQUIRE(s > 0);
444a8eb96d5SAlan Somers 	r = listen(s, -1);
445a8eb96d5SAlan Somers 	/* expect listen to fail since we haven't called bind(2) */
446a8eb96d5SAlan Somers 	ATF_CHECK(r != 0);
447e594026dSAlan Somers 	close(s);
448a8eb96d5SAlan Somers }
449a8eb96d5SAlan Somers 
450a8eb96d5SAlan Somers /* Bind the socket to a file */
451a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(bind);
ATF_TC_BODY(bind,tc)452a8eb96d5SAlan Somers ATF_TC_BODY(bind, tc)
453a8eb96d5SAlan Somers {
454a8eb96d5SAlan Somers 	struct sockaddr_un sun;
455a8eb96d5SAlan Somers 	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
456a8eb96d5SAlan Somers 	const char *path = "sock";
457a8eb96d5SAlan Somers 	int s, r;
458a8eb96d5SAlan Somers 
459a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
460a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
461a8eb96d5SAlan Somers 
462a8eb96d5SAlan Somers 	bzero(&sun, sizeof(sun));
463a8eb96d5SAlan Somers 	sun.sun_family = AF_LOCAL;
464a8eb96d5SAlan Somers 	sun.sun_len = sizeof(sun);
465a8eb96d5SAlan Somers 	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
466a8eb96d5SAlan Somers 	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
467a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, r);
468e594026dSAlan Somers 	close(s);
469a8eb96d5SAlan Somers }
470a8eb96d5SAlan Somers 
471a8eb96d5SAlan Somers /* listen(2) a socket that is already bound(2) should succeed */
472a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(listen_bound);
ATF_TC_BODY(listen_bound,tc)473a8eb96d5SAlan Somers ATF_TC_BODY(listen_bound, tc)
474a8eb96d5SAlan Somers {
4751f46c32cSGleb Smirnoff 	int s;
476a8eb96d5SAlan Somers 
4771f46c32cSGleb Smirnoff 	(void)mk_listening_socket(&s);
478e594026dSAlan Somers 	close(s);
479a8eb96d5SAlan Somers }
480a8eb96d5SAlan Somers 
481a8eb96d5SAlan Somers /* connect(2) can make a connection */
482a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(connect);
ATF_TC_BODY(connect,tc)483a8eb96d5SAlan Somers ATF_TC_BODY(connect, tc)
484a8eb96d5SAlan Somers {
4851f46c32cSGleb Smirnoff 	const struct sockaddr_un *sun;
4861f46c32cSGleb Smirnoff 	int s, err, s2;
487a8eb96d5SAlan Somers 
4881f46c32cSGleb Smirnoff 	sun = mk_listening_socket(&s);
489a8eb96d5SAlan Somers 
490a8eb96d5SAlan Somers 	/* Create the other socket */
491a8eb96d5SAlan Somers 	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
492a8eb96d5SAlan Somers 	ATF_REQUIRE(s2 >= 0);
4931f46c32cSGleb Smirnoff 	err = connect(s2, (struct sockaddr *)sun, sizeof(*sun));
494a8eb96d5SAlan Somers 	if (err != 0) {
495a8eb96d5SAlan Somers 		perror("connect");
496a8eb96d5SAlan Somers 		atf_tc_fail("connect(2) failed");
497a8eb96d5SAlan Somers 	}
498e594026dSAlan Somers 	close(s);
499e594026dSAlan Somers 	close(s2);
500a8eb96d5SAlan Somers }
501a8eb96d5SAlan Somers 
5023bc122d2SGleb Smirnoff /*
5033bc122d2SGleb Smirnoff  * An undocumented feature that we probably want to preserve: sending to
5043bc122d2SGleb Smirnoff  * a socket that isn't yet accepted lands data on the socket.  It can be
5053bc122d2SGleb Smirnoff  * read after accept(2).
5063bc122d2SGleb Smirnoff  */
5073bc122d2SGleb Smirnoff ATF_TC_WITHOUT_HEAD(send_before_accept);
ATF_TC_BODY(send_before_accept,tc)5083bc122d2SGleb Smirnoff ATF_TC_BODY(send_before_accept, tc)
5093bc122d2SGleb Smirnoff {
5103bc122d2SGleb Smirnoff 	const char buf[] = "hello";
5113bc122d2SGleb Smirnoff 	char repl[sizeof(buf)];
5123bc122d2SGleb Smirnoff 	const struct sockaddr_un *sun;
5133bc122d2SGleb Smirnoff 	int l, s, a;
5143bc122d2SGleb Smirnoff 
5153bc122d2SGleb Smirnoff 	sun = mk_listening_socket(&l);
5163bc122d2SGleb Smirnoff 
5173bc122d2SGleb Smirnoff 	ATF_REQUIRE((s = socket(PF_LOCAL, SOCK_SEQPACKET, 0)) > 0);
5183bc122d2SGleb Smirnoff 	ATF_REQUIRE(connect(s, (struct sockaddr *)sun, sizeof(*sun)) == 0);
5193bc122d2SGleb Smirnoff 	ATF_REQUIRE(send(s, &buf, sizeof(buf), 0) == sizeof(buf));
5203bc122d2SGleb Smirnoff 	ATF_REQUIRE((a = accept(l, NULL, NULL)) != 1);
5213bc122d2SGleb Smirnoff 	ATF_REQUIRE(recv(a, &repl, sizeof(repl), 0) == sizeof(buf));
5223bc122d2SGleb Smirnoff 	ATF_REQUIRE(strcmp(buf, repl) == 0);
5233bc122d2SGleb Smirnoff 	close(l);
5243bc122d2SGleb Smirnoff 	close(s);
5253bc122d2SGleb Smirnoff 	close(a);
5263bc122d2SGleb Smirnoff }
5273bc122d2SGleb Smirnoff 
528f9927821SGleb Smirnoff /*
529f9927821SGleb Smirnoff  * Test that close(2) of the peer ends in EPIPE when we try to send(2).
530f9927821SGleb Smirnoff  * Test both normal case as well as a peer that was not accept(2)-ed.
531f9927821SGleb Smirnoff  */
532f9927821SGleb Smirnoff static bool sigpipe_received = false;
533f9927821SGleb Smirnoff static void
sigpipe_handler(int signo __unused)534f9927821SGleb Smirnoff sigpipe_handler(int signo __unused)
535f9927821SGleb Smirnoff {
536f9927821SGleb Smirnoff 	sigpipe_received = true;
537f9927821SGleb Smirnoff }
538f9927821SGleb Smirnoff 
539f9927821SGleb Smirnoff ATF_TC_WITHOUT_HEAD(send_to_closed);
ATF_TC_BODY(send_to_closed,tc)540f9927821SGleb Smirnoff ATF_TC_BODY(send_to_closed, tc)
541f9927821SGleb Smirnoff {
542f9927821SGleb Smirnoff 	struct sigaction sa = {
543f9927821SGleb Smirnoff 		.sa_handler = sigpipe_handler,
544f9927821SGleb Smirnoff 	};
545f9927821SGleb Smirnoff 	const struct sockaddr_un *sun;
546f9927821SGleb Smirnoff 	int l, s, a;
547f9927821SGleb Smirnoff 
548f9927821SGleb Smirnoff 	ATF_REQUIRE(sigemptyset(&sa.sa_mask) == 0);
549f9927821SGleb Smirnoff 	ATF_REQUIRE(sigaction(SIGPIPE, &sa, NULL) == 0);
550f9927821SGleb Smirnoff 
551f9927821SGleb Smirnoff 	sun = mk_listening_socket(&l);
552f9927821SGleb Smirnoff 
553f9927821SGleb Smirnoff 	ATF_REQUIRE((s = socket(PF_LOCAL, SOCK_SEQPACKET, 0)) > 0);
554f9927821SGleb Smirnoff 	ATF_REQUIRE(connect(s, (struct sockaddr *)sun, sizeof(*sun)) == 0);
555f9927821SGleb Smirnoff 	ATF_REQUIRE((a = accept(l, NULL, NULL)) != 1);
556f9927821SGleb Smirnoff 	close(a);
557f9927821SGleb Smirnoff 	ATF_REQUIRE(send(s, &s, sizeof(s), 0) == -1);
558f9927821SGleb Smirnoff 	ATF_REQUIRE(errno == EPIPE);
559f9927821SGleb Smirnoff 	ATF_REQUIRE(sigpipe_received == true);
560f9927821SGleb Smirnoff 	close(s);
561f9927821SGleb Smirnoff 
562f9927821SGleb Smirnoff 	ATF_REQUIRE((s = socket(PF_LOCAL, SOCK_SEQPACKET, 0)) > 0);
563f9927821SGleb Smirnoff 	ATF_REQUIRE(connect(s, (struct sockaddr *)sun, sizeof(*sun)) == 0);
564f9927821SGleb Smirnoff 	close(l);
565f9927821SGleb Smirnoff 	sigpipe_received = false;
566f9927821SGleb Smirnoff 	ATF_REQUIRE(send(s, &s, sizeof(s), 0) == -1);
567f9927821SGleb Smirnoff 	ATF_REQUIRE(errno == EPIPE);
568f9927821SGleb Smirnoff 	ATF_REQUIRE(sigpipe_received == true);
569f9927821SGleb Smirnoff 	close(s);
570f9927821SGleb Smirnoff 
571f9927821SGleb Smirnoff 	sa.sa_handler = SIG_DFL;
572f9927821SGleb Smirnoff 	ATF_REQUIRE(sigaction(SIGPIPE, &sa, NULL) == 0);
573f9927821SGleb Smirnoff }
574f9927821SGleb Smirnoff 
575253d8a1fSGleb Smirnoff /* Implied connect is unix/dgram only feature. Fails on stream or seqpacket. */
576253d8a1fSGleb Smirnoff ATF_TC_WITHOUT_HEAD(implied_connect);
ATF_TC_BODY(implied_connect,tc)577253d8a1fSGleb Smirnoff ATF_TC_BODY(implied_connect, tc)
578253d8a1fSGleb Smirnoff {
579253d8a1fSGleb Smirnoff 	const struct sockaddr_un *sun;
580253d8a1fSGleb Smirnoff 	int l, s;
581253d8a1fSGleb Smirnoff 
582253d8a1fSGleb Smirnoff 	sun = mk_listening_socket(&l);
583253d8a1fSGleb Smirnoff 
584253d8a1fSGleb Smirnoff 	ATF_REQUIRE((s = socket(PF_LOCAL, SOCK_SEQPACKET, 0)) > 0);
585253d8a1fSGleb Smirnoff 	ATF_REQUIRE(sendto(s, &s, sizeof(s), 0, (struct sockaddr *)sun,
586253d8a1fSGleb Smirnoff 	    sizeof(*sun)) == -1);
587253d8a1fSGleb Smirnoff 	ATF_REQUIRE(errno == ENOTCONN);
588253d8a1fSGleb Smirnoff 	close(l);
589253d8a1fSGleb Smirnoff 	close(s);
590253d8a1fSGleb Smirnoff }
591253d8a1fSGleb Smirnoff 
592a8eb96d5SAlan Somers /* accept(2) can receive a connection */
593a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(accept);
ATF_TC_BODY(accept,tc)594a8eb96d5SAlan Somers ATF_TC_BODY(accept, tc)
595a8eb96d5SAlan Somers {
596a8eb96d5SAlan Somers 	int sv[2];
597a8eb96d5SAlan Somers 
598a8eb96d5SAlan Somers 	mk_pair_of_sockets(sv);
599e594026dSAlan Somers 	close(sv[0]);
600e594026dSAlan Somers 	close(sv[1]);
601a8eb96d5SAlan Somers }
602a8eb96d5SAlan Somers 
603a8eb96d5SAlan Somers 
604a8eb96d5SAlan Somers /* Set O_NONBLOCK on the socket */
605a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(fcntl_nonblock);
ATF_TC_BODY(fcntl_nonblock,tc)606a8eb96d5SAlan Somers ATF_TC_BODY(fcntl_nonblock, tc)
607a8eb96d5SAlan Somers {
608a8eb96d5SAlan Somers 	int s;
609a8eb96d5SAlan Somers 
610a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
611a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
612a8eb96d5SAlan Somers 	if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
613a8eb96d5SAlan Somers 		perror("fcntl");
614a8eb96d5SAlan Somers 		atf_tc_fail("fcntl failed");
615a8eb96d5SAlan Somers 	}
616e594026dSAlan Somers 	close(s);
617a8eb96d5SAlan Somers }
618a8eb96d5SAlan Somers 
619a8eb96d5SAlan Somers /* Resize the send and receive buffers */
620a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(resize_buffers);
ATF_TC_BODY(resize_buffers,tc)621a8eb96d5SAlan Somers ATF_TC_BODY(resize_buffers, tc)
622a8eb96d5SAlan Somers {
623a8eb96d5SAlan Somers 	int s;
624a8eb96d5SAlan Somers 	int sndbuf = 12345;
625a8eb96d5SAlan Somers 	int rcvbuf = 23456;
626a8eb96d5SAlan Somers 	int xs, xr;
627a8eb96d5SAlan Somers 	socklen_t sl = sizeof(xs);
628a8eb96d5SAlan Somers 
629a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
630a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
631a8eb96d5SAlan Somers 
632a8eb96d5SAlan Somers 	printf("                       Socket Buffer Sizes\n");
633a8eb96d5SAlan Somers 	printf("                              | SNDBUF  | RCVBUF  |\n");
634a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
635a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
636a8eb96d5SAlan Somers 	printf("Default                       | %7d | %7d |\n", xs, xr);
637a8eb96d5SAlan Somers 
638a8eb96d5SAlan Somers 	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) != 0){
639a8eb96d5SAlan Somers 		perror("setsockopt");
640a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_SNDBUF) failed");
641a8eb96d5SAlan Somers 	}
642a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
643a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
644a8eb96d5SAlan Somers 	printf("After changing SNDBUF         | %7d | %7d |\n", xs, xr);
645a8eb96d5SAlan Somers 
646a8eb96d5SAlan Somers 	if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) != 0){
647a8eb96d5SAlan Somers 		perror("setsockopt");
648a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_RCVBUF) failed");
649a8eb96d5SAlan Somers 	}
650a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
651a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
652a8eb96d5SAlan Somers 	printf("After changing RCVBUF         | %7d | %7d |\n", xs, xr);
653e594026dSAlan Somers 	close(s);
654a8eb96d5SAlan Somers }
655a8eb96d5SAlan Somers 
656a8eb96d5SAlan Somers /*
657a8eb96d5SAlan Somers  * Resize the send and receive buffers of a connected socketpair
658a8eb96d5SAlan Somers  * Print some useful debugging info too
659a8eb96d5SAlan Somers  */
660a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(resize_connected_buffers);
ATF_TC_BODY(resize_connected_buffers,tc)661a8eb96d5SAlan Somers ATF_TC_BODY(resize_connected_buffers, tc)
662a8eb96d5SAlan Somers {
663a8eb96d5SAlan Somers 	int sv[2];
664a8eb96d5SAlan Somers 	int sndbuf = 12345;
665a8eb96d5SAlan Somers 	int rcvbuf = 23456;
666a8eb96d5SAlan Somers 	int err;
667a8eb96d5SAlan Somers 	int ls, lr, rs, rr;
668a8eb96d5SAlan Somers 	socklen_t sl = sizeof(ls);
669a8eb96d5SAlan Somers 
670a8eb96d5SAlan Somers 	/* setup the socket pair */
671a8eb96d5SAlan Somers 	do_socketpair(sv);
672a8eb96d5SAlan Somers 
673a8eb96d5SAlan Somers 	printf("                       Socket Buffer Sizes\n");
674a8eb96d5SAlan Somers 	printf("                              | Left Socket       | Right Socket      |\n");
675a8eb96d5SAlan Somers 	printf("                              | SNDBUF  | RCVBUF  | SNDBUF  | RCVBUF  |\n");
676a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
677a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
678a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
679a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
680a8eb96d5SAlan Somers 	printf("Default                       | %7d | %7d | %7d | %7d |\n",
681a8eb96d5SAlan Somers 	    ls, lr, rs, rr);
682a8eb96d5SAlan Somers 
683a8eb96d5SAlan Somers 	/* Update one side's send buffer */
684a8eb96d5SAlan Somers 	err = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
685a8eb96d5SAlan Somers 	if (err != 0){
686a8eb96d5SAlan Somers 		perror("setsockopt");
687a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_SNDBUF) failed");
688a8eb96d5SAlan Somers 	}
689a8eb96d5SAlan Somers 
690a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
691a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
692a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
693a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
694a8eb96d5SAlan Somers 	printf("After changing Left's SNDBUF  | %7d | %7d | %7d | %7d |\n",
695a8eb96d5SAlan Somers 	    ls, lr, rs, rr);
696a8eb96d5SAlan Somers 
697a8eb96d5SAlan Somers 	/* Update the same side's receive buffer */
698a8eb96d5SAlan Somers 	err = setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
699a8eb96d5SAlan Somers 	if (err != 0){
700a8eb96d5SAlan Somers 		perror("setsockopt");
701a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_RCVBUF) failed");
702a8eb96d5SAlan Somers 	}
703a8eb96d5SAlan Somers 
704a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
705a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
706a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
707a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
708a8eb96d5SAlan Somers 	printf("After changing Left's RCVBUF  | %7d | %7d | %7d | %7d |\n",
709a8eb96d5SAlan Somers 	    ls, lr, rs, rr);
710e594026dSAlan Somers 	close(sv[0]);
711e594026dSAlan Somers 	close(sv[1]);
712a8eb96d5SAlan Somers }
713a8eb96d5SAlan Somers 
714a8eb96d5SAlan Somers 
715a8eb96d5SAlan Somers /* send(2) and recv(2) a single short record */
716a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(send_recv);
ATF_TC_BODY(send_recv,tc)717a8eb96d5SAlan Somers ATF_TC_BODY(send_recv, tc)
718a8eb96d5SAlan Somers {
719a8eb96d5SAlan Somers 	int sv[2];
720a8eb96d5SAlan Somers 	const int bufsize = 64;
721a8eb96d5SAlan Somers 	const char *data = "data";
722a8eb96d5SAlan Somers 	char recv_buf[bufsize];
7235d5b721aSAlan Somers 	ssize_t datalen;
724a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
725a8eb96d5SAlan Somers 
726a8eb96d5SAlan Somers 	/* setup the socket pair */
727a8eb96d5SAlan Somers 	do_socketpair(sv);
728a8eb96d5SAlan Somers 
729a8eb96d5SAlan Somers 	/* send and receive a small packet */
730a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
731a8eb96d5SAlan Somers 	ssize = send(sv[0], data, datalen, MSG_EOR);
732a8eb96d5SAlan Somers 	if (ssize < 0) {
733a8eb96d5SAlan Somers 		perror("send");
734a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
735a8eb96d5SAlan Somers 	}
736a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
737a8eb96d5SAlan Somers 	    datalen, ssize);
738a8eb96d5SAlan Somers 
739a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
740a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
741e594026dSAlan Somers 	close(sv[0]);
742e594026dSAlan Somers 	close(sv[1]);
743a8eb96d5SAlan Somers }
744a8eb96d5SAlan Somers 
745a8eb96d5SAlan Somers /* sendto(2) and recvfrom(2) a single short record
746a8eb96d5SAlan Somers  * According to The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
747a8eb96d5SAlan Somers  * Edition, sendto(2) is exactly the same as send(2) on a connection-mode socket
748a8eb96d5SAlan Somers  *
749a8eb96d5SAlan Somers  * According to the same spec, not all protocols are required to provide the
750a8eb96d5SAlan Somers  * source addres in recvfrom(2).
751a8eb96d5SAlan Somers  */
752a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendto_recvfrom);
ATF_TC_BODY(sendto_recvfrom,tc)753a8eb96d5SAlan Somers ATF_TC_BODY(sendto_recvfrom, tc)
754a8eb96d5SAlan Somers {
755983a2d91SEnji Cooper #ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS
7561f46c32cSGleb Smirnoff 	const sockaddr_un *sun;
757983a2d91SEnji Cooper #endif
758a8eb96d5SAlan Somers 	struct sockaddr_storage from;
759a8eb96d5SAlan Somers 	int sv[2];
760a8eb96d5SAlan Somers 	const int bufsize = 64;
761a8eb96d5SAlan Somers 	const char *data = "data";
762a8eb96d5SAlan Somers 	char recv_buf[bufsize];
7635d5b721aSAlan Somers 	ssize_t datalen;
764a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
765a8eb96d5SAlan Somers 	socklen_t fromlen;
766a8eb96d5SAlan Somers 
767a8eb96d5SAlan Somers 	/* setup the socket pair */
768983a2d91SEnji Cooper #ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS
7691f46c32cSGleb Smirnoff 	sun =
770983a2d91SEnji Cooper #endif
771983a2d91SEnji Cooper 		mk_pair_of_sockets(sv);
772a8eb96d5SAlan Somers 
773a8eb96d5SAlan Somers 	/* send and receive a small packet */
774a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
775a8eb96d5SAlan Somers 	ssize = sendto(sv[0], data, datalen, MSG_EOR, NULL, 0);
776a8eb96d5SAlan Somers 	if (ssize < 0) {
777a8eb96d5SAlan Somers 		perror("send");
778a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
779a8eb96d5SAlan Somers 	}
780a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
781a8eb96d5SAlan Somers 	    datalen, ssize);
782a8eb96d5SAlan Somers 
783a8eb96d5SAlan Somers 	fromlen = sizeof(from);
784a8eb96d5SAlan Somers 	rsize = recvfrom(sv[1], recv_buf, bufsize, MSG_WAITALL,
785a8eb96d5SAlan Somers 	    (struct sockaddr*)&from, &fromlen);
786a8eb96d5SAlan Somers 	if (ssize < 0) {
787a8eb96d5SAlan Somers 		perror("recvfrom");
788a8eb96d5SAlan Somers 		atf_tc_fail("recvfrom returned < 0");
789a8eb96d5SAlan Somers 	}
790a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
791a8eb96d5SAlan Somers 
792983a2d91SEnji Cooper #ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS
793a8eb96d5SAlan Somers 	/*
794a8eb96d5SAlan Somers 	 * FreeBSD does not currently provide the source address for SEQ_PACKET
795a8eb96d5SAlan Somers 	 * AF_UNIX sockets, and POSIX does not require it, so these two checks
796a8eb96d5SAlan Somers 	 * are disabled.  If FreeBSD gains that feature in the future, then
797a8eb96d5SAlan Somers 	 * these checks may be reenabled
798a8eb96d5SAlan Somers 	 */
799983a2d91SEnji Cooper 	ATF_CHECK_EQ(PF_LOCAL, from.ss_family);
8001f46c32cSGleb Smirnoff 	ATF_CHECK_STREQ(sun->sun_path, ((struct sockaddr_un*)&from)->sun_path);
801983a2d91SEnji Cooper #endif
802e594026dSAlan Somers 	close(sv[0]);
803e594026dSAlan Somers 	close(sv[1]);
804a8eb96d5SAlan Somers }
805a8eb96d5SAlan Somers 
806a8eb96d5SAlan Somers /*
807a8eb96d5SAlan Somers  * send(2) and recv(2) a single short record with sockets created the
808a8eb96d5SAlan Somers  * traditional way, involving bind, listen, connect, and accept
809a8eb96d5SAlan Somers  */
810a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(send_recv_with_connect);
ATF_TC_BODY(send_recv_with_connect,tc)811a8eb96d5SAlan Somers ATF_TC_BODY(send_recv_with_connect, tc)
812a8eb96d5SAlan Somers {
813a8eb96d5SAlan Somers 	int sv[2];
814a8eb96d5SAlan Somers 	const int bufsize = 64;
815a8eb96d5SAlan Somers 	const char *data = "data";
816a8eb96d5SAlan Somers 	char recv_buf[bufsize];
8175d5b721aSAlan Somers 	ssize_t datalen;
818a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
819a8eb96d5SAlan Somers 
820a8eb96d5SAlan Somers 	mk_pair_of_sockets(sv);
821a8eb96d5SAlan Somers 
822a8eb96d5SAlan Somers 	/* send and receive a small packet */
823a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
824a8eb96d5SAlan Somers 	ssize = send(sv[0], data, datalen, MSG_EOR);
825a8eb96d5SAlan Somers 	if (ssize < 0) {
826a8eb96d5SAlan Somers 		perror("send");
827a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
828a8eb96d5SAlan Somers 	}
829a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
830a8eb96d5SAlan Somers 	    datalen, ssize);
831a8eb96d5SAlan Somers 
832a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
833a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
834e594026dSAlan Somers 	close(sv[0]);
835e594026dSAlan Somers 	close(sv[1]);
836a8eb96d5SAlan Somers }
837a8eb96d5SAlan Somers 
838a8eb96d5SAlan Somers /* send(2) should fail on a shutdown socket */
839a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(shutdown_send);
ATF_TC_BODY(shutdown_send,tc)840a8eb96d5SAlan Somers ATF_TC_BODY(shutdown_send, tc)
841a8eb96d5SAlan Somers {
8421f46c32cSGleb Smirnoff 	const struct sockaddr_un *sun;
8434446a47aSSergey Kandaurov 	const char *data = "data";
844fa5e5f53SEnji Cooper 	ssize_t datalen, ssize;
8454446a47aSSergey Kandaurov 	int s, err, s2;
846a8eb96d5SAlan Somers 
8471f46c32cSGleb Smirnoff 	sun = mk_listening_socket(&s);
8484446a47aSSergey Kandaurov 
8494446a47aSSergey Kandaurov 	/* Create the other socket */
8504446a47aSSergey Kandaurov 	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
8514446a47aSSergey Kandaurov 	ATF_REQUIRE(s2 >= 0);
8521f46c32cSGleb Smirnoff 	err = connect(s2, (struct sockaddr *)sun, sizeof(*sun));
8534446a47aSSergey Kandaurov 	if (err != 0) {
8544446a47aSSergey Kandaurov 		perror("connect");
8554446a47aSSergey Kandaurov 		atf_tc_fail("connect(2) failed");
8564446a47aSSergey Kandaurov 	}
8574446a47aSSergey Kandaurov 
8584446a47aSSergey Kandaurov 	ATF_CHECK_EQ(0, shutdown(s2, SHUT_RDWR));
859fa5e5f53SEnji Cooper 	datalen = strlen(data) + 1;	/* +1 for the null */
860a8eb96d5SAlan Somers 	/* USE MSG_NOSIGNAL so we don't get SIGPIPE */
861fa5e5f53SEnji Cooper 	ssize = send(s2, data, datalen, MSG_EOR | MSG_NOSIGNAL);
862a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EPIPE, errno);
863a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, ssize);
864e594026dSAlan Somers 	close(s);
8654446a47aSSergey Kandaurov 	close(s2);
866a8eb96d5SAlan Somers }
867a8eb96d5SAlan Somers 
868a8eb96d5SAlan Somers /* send(2) should cause SIGPIPE on a shutdown socket */
869a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(shutdown_send_sigpipe);
ATF_TC_BODY(shutdown_send_sigpipe,tc)870a8eb96d5SAlan Somers ATF_TC_BODY(shutdown_send_sigpipe, tc)
871a8eb96d5SAlan Somers {
8721f46c32cSGleb Smirnoff 	const struct sockaddr_un *sun;
8734446a47aSSergey Kandaurov 	const char *data = "data";
874fa5e5f53SEnji Cooper 	ssize_t datalen;
8754446a47aSSergey Kandaurov 	int s, err, s2;
876a8eb96d5SAlan Somers 
8771f46c32cSGleb Smirnoff 	sun = mk_listening_socket(&s);
8784446a47aSSergey Kandaurov 
8794446a47aSSergey Kandaurov 	/* Create the other socket */
8804446a47aSSergey Kandaurov 	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
8814446a47aSSergey Kandaurov 	ATF_REQUIRE(s2 >= 0);
8821f46c32cSGleb Smirnoff 	err = connect(s2, (struct sockaddr *)sun, sizeof(*sun));
8834446a47aSSergey Kandaurov 	if (err != 0) {
8844446a47aSSergey Kandaurov 		perror("connect");
8854446a47aSSergey Kandaurov 		atf_tc_fail("connect(2) failed");
8864446a47aSSergey Kandaurov 	}
8874446a47aSSergey Kandaurov 
8884446a47aSSergey Kandaurov 	ATF_CHECK_EQ(0, shutdown(s2, SHUT_RDWR));
889a8eb96d5SAlan Somers 	ATF_REQUIRE(SIG_ERR != signal(SIGPIPE, shutdown_send_sigpipe_handler));
890fa5e5f53SEnji Cooper 	datalen = strlen(data) + 1;	/* +1 for the null */
8916dd202ceSJohn Baldwin 	(void)send(s2, data, datalen, MSG_EOR);
892a8eb96d5SAlan Somers 	ATF_CHECK_EQ(1, got_sigpipe);
893e594026dSAlan Somers 	close(s);
8944446a47aSSergey Kandaurov 	close(s2);
895a8eb96d5SAlan Somers }
896a8eb96d5SAlan Somers 
897a8eb96d5SAlan Somers /* nonblocking send(2) and recv(2) a single short record */
898a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(send_recv_nonblocking);
ATF_TC_BODY(send_recv_nonblocking,tc)899a8eb96d5SAlan Somers ATF_TC_BODY(send_recv_nonblocking, tc)
900a8eb96d5SAlan Somers {
901a8eb96d5SAlan Somers 	int sv[2];
902a8eb96d5SAlan Somers 	const int bufsize = 64;
903a8eb96d5SAlan Somers 	const char *data = "data";
904a8eb96d5SAlan Somers 	char recv_buf[bufsize];
9055d5b721aSAlan Somers 	ssize_t datalen;
906a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
907a8eb96d5SAlan Somers 
908a8eb96d5SAlan Somers 	/* setup the socket pair */
909a8eb96d5SAlan Somers 	do_socketpair_nonblocking(sv);
910a8eb96d5SAlan Somers 
911a8eb96d5SAlan Somers 	/* Verify that there is nothing to receive */
912a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
913a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EAGAIN, errno);
914a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, rsize);
915a8eb96d5SAlan Somers 
916a8eb96d5SAlan Somers 	/* send and receive a small packet */
917a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
918a8eb96d5SAlan Somers 	ssize = send(sv[0], data, datalen, MSG_EOR);
919a8eb96d5SAlan Somers 	if (ssize < 0) {
920a8eb96d5SAlan Somers 		perror("send");
921a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
922a8eb96d5SAlan Somers 	}
923a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
924a8eb96d5SAlan Somers 	    datalen, ssize);
925a8eb96d5SAlan Somers 
926a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
927a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
928e594026dSAlan Somers 	close(sv[0]);
929e594026dSAlan Somers 	close(sv[1]);
930a8eb96d5SAlan Somers }
931a8eb96d5SAlan Somers 
932a8eb96d5SAlan Somers /*
933a8eb96d5SAlan Somers  * We should get EAGAIN if we try to send a message larger than the socket
934a8eb96d5SAlan Somers  * buffer, with nonblocking sockets.  Test with several different sockbuf sizes
935a8eb96d5SAlan Somers  */
936a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_8k_8k);
ATF_TC_BODY(eagain_8k_8k,tc)937a8eb96d5SAlan Somers ATF_TC_BODY(eagain_8k_8k, tc)
938a8eb96d5SAlan Somers {
939a8eb96d5SAlan Somers 	test_eagain(8192, 8192);
940a8eb96d5SAlan Somers }
941a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_8k_128k);
ATF_TC_BODY(eagain_8k_128k,tc)942a8eb96d5SAlan Somers ATF_TC_BODY(eagain_8k_128k, tc)
943a8eb96d5SAlan Somers {
944a8eb96d5SAlan Somers 	test_eagain(8192, 131072);
945a8eb96d5SAlan Somers }
946a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_128k_8k);
ATF_TC_BODY(eagain_128k_8k,tc)947a8eb96d5SAlan Somers ATF_TC_BODY(eagain_128k_8k, tc)
948a8eb96d5SAlan Somers {
949a8eb96d5SAlan Somers 	test_eagain(131072, 8192);
950a8eb96d5SAlan Somers }
951a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_128k_128k);
ATF_TC_BODY(eagain_128k_128k,tc)952a8eb96d5SAlan Somers ATF_TC_BODY(eagain_128k_128k, tc)
953a8eb96d5SAlan Somers {
954a8eb96d5SAlan Somers 	test_eagain(131072, 131072);
955a8eb96d5SAlan Somers }
956a8eb96d5SAlan Somers 
957a8eb96d5SAlan Somers 
958a8eb96d5SAlan Somers /*
959a8eb96d5SAlan Somers  * nonblocking send(2) and recv(2) of several records, which should collectively
960a8eb96d5SAlan Somers  * fill up the send buffer but not the receive buffer
961a8eb96d5SAlan Somers  */
962a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(rcvbuf_oversized);
ATF_TC_BODY(rcvbuf_oversized,tc)963a8eb96d5SAlan Somers ATF_TC_BODY(rcvbuf_oversized, tc)
964a8eb96d5SAlan Somers {
9655d5b721aSAlan Somers 	int i;
966a8eb96d5SAlan Somers 	int sv[2];
9673be7751dSJulio Merino 	const ssize_t pktsize = 1024;
968ea703329SBrooks Davis 	const int sndbufsize = 8192;
969ea703329SBrooks Davis 	const int rcvbufsize = 131072;
9705d5b721aSAlan Somers 	const size_t geometric_mean_bufsize = 32768;
9715d5b721aSAlan Somers 	const int numpkts = geometric_mean_bufsize / pktsize;
972a8eb96d5SAlan Somers 	char sndbuf[pktsize];
973a8eb96d5SAlan Somers 	char recv_buf[pktsize];
974a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
975a8eb96d5SAlan Somers 
976a8eb96d5SAlan Somers 	/* setup the socket pair */
977a8eb96d5SAlan Somers 	do_socketpair_nonblocking(sv);
9785d5b721aSAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
9795d5b721aSAlan Somers 	    sizeof(sndbufsize)));
9805d5b721aSAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
9815d5b721aSAlan Somers 	    sizeof(rcvbufsize)));
982a8eb96d5SAlan Somers 
983a8eb96d5SAlan Somers 	/*
984a8eb96d5SAlan Somers 	 * Send and receive packets that are collectively greater than the send
985a8eb96d5SAlan Somers 	 * buffer, but less than the receive buffer
986a8eb96d5SAlan Somers 	 */
9875d5b721aSAlan Somers 	for (i=0; i < numpkts; i++) {
988a8eb96d5SAlan Somers 		/* Fill the buffer */
989a8eb96d5SAlan Somers 		memset(sndbuf, i, pktsize);
990a8eb96d5SAlan Somers 
991a8eb96d5SAlan Somers 		/* send the packet */
992a8eb96d5SAlan Somers 		ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
993a8eb96d5SAlan Somers 		if (ssize < 0) {
994a8eb96d5SAlan Somers 			perror("send");
995a8eb96d5SAlan Somers 			atf_tc_fail("send returned < 0");
996a8eb96d5SAlan Somers 		}
997a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(pktsize, ssize,
998a8eb96d5SAlan Somers 		    "expected %zd=send(...) but got %zd", pktsize, ssize);
999a8eb96d5SAlan Somers 
1000a8eb96d5SAlan Somers 		/* Receive it */
1001a8eb96d5SAlan Somers 
1002a8eb96d5SAlan Somers 		rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
1003a8eb96d5SAlan Somers 		if (rsize < 0) {
1004a8eb96d5SAlan Somers 			perror("recv");
1005a8eb96d5SAlan Somers 			atf_tc_fail("recv returned < 0");
1006a8eb96d5SAlan Somers 		}
1007a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(pktsize, rsize,
1008a8eb96d5SAlan Somers 		    "expected %zd=send(...) but got %zd", pktsize, rsize);
1009a8eb96d5SAlan Somers 
1010a8eb96d5SAlan Somers 		/* Verify the contents */
1011a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(0, memcmp(sndbuf, recv_buf, pktsize),
1012a8eb96d5SAlan Somers 		    "Received data miscompare");
1013a8eb96d5SAlan Somers 	}
1014a8eb96d5SAlan Somers 
1015a8eb96d5SAlan Somers 	/* Trying to receive again should return EAGAIN */
1016a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
1017a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EAGAIN, errno);
1018a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, rsize);
1019e594026dSAlan Somers 	close(sv[0]);
1020e594026dSAlan Somers 	close(sv[1]);
1021a8eb96d5SAlan Somers }
1022a8eb96d5SAlan Somers 
1023a8eb96d5SAlan Somers /*
1024a8eb96d5SAlan Somers  * Simulate the behavior of a blocking pipe.  The sender will send until his
1025a8eb96d5SAlan Somers  * buffer fills up, then we'll simulate a scheduler switch that will allow the
1026a8eb96d5SAlan Somers  * receiver to read until his buffer empties.  Repeat the process until the
1027a8eb96d5SAlan Somers  * transfer is complete.
1028a8eb96d5SAlan Somers  * Repeat the test with multiple send and receive buffer sizes
1029a8eb96d5SAlan Somers  */
1030a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_8k);
ATF_TC_BODY(pipe_simulator_8k_8k,tc)1031a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_8k_8k, tc)
1032a8eb96d5SAlan Somers {
1033a8eb96d5SAlan Somers 	test_pipe_simulator(8192, 8192);
1034a8eb96d5SAlan Somers }
1035a8eb96d5SAlan Somers 
1036a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_128k);
ATF_TC_BODY(pipe_simulator_8k_128k,tc)1037a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_8k_128k, tc)
1038a8eb96d5SAlan Somers {
1039a8eb96d5SAlan Somers 	test_pipe_simulator(8192, 131072);
1040a8eb96d5SAlan Somers }
1041a8eb96d5SAlan Somers 
1042a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_8k);
ATF_TC_BODY(pipe_simulator_128k_8k,tc)1043a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_128k_8k, tc)
1044a8eb96d5SAlan Somers {
1045a8eb96d5SAlan Somers 	test_pipe_simulator(131072, 8192);
1046a8eb96d5SAlan Somers }
1047a8eb96d5SAlan Somers 
1048a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_128k);
ATF_TC_BODY(pipe_simulator_128k_128k,tc)1049a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_128k_128k, tc)
1050a8eb96d5SAlan Somers {
1051a8eb96d5SAlan Somers 	test_pipe_simulator(131072, 131072);
1052a8eb96d5SAlan Somers }
1053a8eb96d5SAlan Somers 
1054a8eb96d5SAlan Somers /*
1055a8eb96d5SAlan Somers  * Test blocking I/O by passing data between two threads.  The total amount of
1056a8eb96d5SAlan Somers  * data will be >> buffer size to force blocking.  Repeat the test with multiple
1057a8eb96d5SAlan Somers  * send and receive buffer sizes
1058a8eb96d5SAlan Somers  */
1059a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_8k_8k);
ATF_TC_BODY(pipe_8k_8k,tc)1060a8eb96d5SAlan Somers ATF_TC_BODY(pipe_8k_8k, tc)
1061a8eb96d5SAlan Somers {
1062a8eb96d5SAlan Somers 	test_pipe(8192, 8192);
1063a8eb96d5SAlan Somers }
1064a8eb96d5SAlan Somers 
1065a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_8k_128k);
ATF_TC_BODY(pipe_8k_128k,tc)1066a8eb96d5SAlan Somers ATF_TC_BODY(pipe_8k_128k, tc)
1067a8eb96d5SAlan Somers {
1068a8eb96d5SAlan Somers 	test_pipe(8192, 131072);
1069a8eb96d5SAlan Somers }
1070a8eb96d5SAlan Somers 
1071a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_128k_8k);
ATF_TC_BODY(pipe_128k_8k,tc)1072a8eb96d5SAlan Somers ATF_TC_BODY(pipe_128k_8k, tc)
1073a8eb96d5SAlan Somers {
1074a8eb96d5SAlan Somers 	test_pipe(131072, 8192);
1075a8eb96d5SAlan Somers }
1076a8eb96d5SAlan Somers 
1077a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_128k_128k);
ATF_TC_BODY(pipe_128k_128k,tc)1078a8eb96d5SAlan Somers ATF_TC_BODY(pipe_128k_128k, tc)
1079a8eb96d5SAlan Somers {
1080a8eb96d5SAlan Somers 	test_pipe(131072, 131072);
1081a8eb96d5SAlan Somers }
1082a8eb96d5SAlan Somers 
1083a8eb96d5SAlan Somers 
1084a8eb96d5SAlan Somers /*
1085a8eb96d5SAlan Somers  * Test single-packet I/O with and without blocking, with symmetric buffers of
1086a8eb96d5SAlan Somers  * various sizes
1087a8eb96d5SAlan Somers  */
1088a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_8k);
ATF_TC_BODY(sendrecv_8k,tc)1089a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_8k, tc)
1090a8eb96d5SAlan Somers {
1091a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(8 * 1024, true);
1092a8eb96d5SAlan Somers }
1093a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_16k);
ATF_TC_BODY(sendrecv_16k,tc)1094a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_16k, tc)
1095a8eb96d5SAlan Somers {
1096a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(16 * 1024, true);
1097a8eb96d5SAlan Somers }
1098a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_32k);
ATF_TC_BODY(sendrecv_32k,tc)1099a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_32k, tc)
1100a8eb96d5SAlan Somers {
1101a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(32 * 1024, true);
1102a8eb96d5SAlan Somers }
1103a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_64k);
ATF_TC_BODY(sendrecv_64k,tc)1104a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_64k, tc)
1105a8eb96d5SAlan Somers {
1106a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(64 * 1024, true);
1107a8eb96d5SAlan Somers }
1108a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_128k);
ATF_TC_BODY(sendrecv_128k,tc)1109a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_128k, tc)
1110a8eb96d5SAlan Somers {
1111a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(128 * 1024, true);
1112a8eb96d5SAlan Somers }
1113a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_8k_nonblocking);
ATF_TC_BODY(sendrecv_8k_nonblocking,tc)1114a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_8k_nonblocking, tc)
1115a8eb96d5SAlan Somers {
1116a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(8 * 1024, false);
1117a8eb96d5SAlan Somers }
1118a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_16k_nonblocking);
ATF_TC_BODY(sendrecv_16k_nonblocking,tc)1119a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_16k_nonblocking, tc)
1120a8eb96d5SAlan Somers {
1121a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(16 * 1024, false);
1122a8eb96d5SAlan Somers }
1123a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_32k_nonblocking);
ATF_TC_BODY(sendrecv_32k_nonblocking,tc)1124a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_32k_nonblocking, tc)
1125a8eb96d5SAlan Somers {
1126a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(32 * 1024, false);
1127a8eb96d5SAlan Somers }
1128a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_64k_nonblocking);
ATF_TC_BODY(sendrecv_64k_nonblocking,tc)1129a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_64k_nonblocking, tc)
1130a8eb96d5SAlan Somers {
1131a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(64 * 1024, false);
1132a8eb96d5SAlan Somers }
1133a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_128k_nonblocking);
ATF_TC_BODY(sendrecv_128k_nonblocking,tc)1134a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_128k_nonblocking, tc)
1135a8eb96d5SAlan Somers {
1136a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(128 * 1024, false);
1137a8eb96d5SAlan Somers }
1138a8eb96d5SAlan Somers 
1139eb338e23SGleb Smirnoff ATF_TC(random_eor_and_waitall);
ATF_TC_HEAD(random_eor_and_waitall,tc)1140eb338e23SGleb Smirnoff ATF_TC_HEAD(random_eor_and_waitall, tc)
1141eb338e23SGleb Smirnoff {
1142eb338e23SGleb Smirnoff 	atf_tc_set_md_var(tc, "descr", "Test random sized send/recv with "
1143eb338e23SGleb Smirnoff 	    "randomly placed MSG_EOR and randomly applied MSG_WAITALL on "
1144eb338e23SGleb Smirnoff 	    "PF_UNIX/SOCK_SEQPACKET");
1145eb338e23SGleb Smirnoff }
1146eb338e23SGleb Smirnoff 
1147eb338e23SGleb Smirnoff struct random_eor_params {
1148eb338e23SGleb Smirnoff 	u_long recvspace;
1149eb338e23SGleb Smirnoff 	char *sendbuf;
1150eb338e23SGleb Smirnoff 	size_t *records;
1151eb338e23SGleb Smirnoff 	u_int nrecords;
1152eb338e23SGleb Smirnoff 	int sock;
1153eb338e23SGleb Smirnoff 	u_short seed[6];
1154eb338e23SGleb Smirnoff };
1155eb338e23SGleb Smirnoff 
1156eb338e23SGleb Smirnoff #define	RANDOM_TESTSIZE	((size_t)100 * 1024 * 1024)
1157eb338e23SGleb Smirnoff /* Below defines are factor of recvspace. */
1158eb338e23SGleb Smirnoff #define	RANDOM_MAXRECORD	10
1159eb338e23SGleb Smirnoff #define	RANDOM_SENDSIZE	2
1160eb338e23SGleb Smirnoff #define	RANDOM_RECVSIZE	4
1161eb338e23SGleb Smirnoff 
1162eb338e23SGleb Smirnoff static void *
sending_thread(void * arg)1163eb338e23SGleb Smirnoff sending_thread(void *arg)
1164eb338e23SGleb Smirnoff {
1165eb338e23SGleb Smirnoff 	struct random_eor_params *params = arg;
1166eb338e23SGleb Smirnoff 	size_t off = 0;
1167eb338e23SGleb Smirnoff 	int eor = 0;
1168eb338e23SGleb Smirnoff 
1169eb338e23SGleb Smirnoff 	while (off < RANDOM_TESTSIZE) {
1170eb338e23SGleb Smirnoff 		ssize_t len;
1171eb338e23SGleb Smirnoff 		int flags;
1172eb338e23SGleb Smirnoff 
1173eb338e23SGleb Smirnoff 		len = nrand48(&params->seed[3]) %
1174eb338e23SGleb Smirnoff 		    (RANDOM_SENDSIZE * params->recvspace);
1175eb338e23SGleb Smirnoff 		if (off + len >= params->records[eor]) {
1176eb338e23SGleb Smirnoff 			len = params->records[eor] - off;
1177eb338e23SGleb Smirnoff 			flags = MSG_EOR;
1178eb338e23SGleb Smirnoff 			eor++;
1179eb338e23SGleb Smirnoff 		} else
1180eb338e23SGleb Smirnoff 			flags = 0;
1181eb338e23SGleb Smirnoff 		ATF_REQUIRE(send(params->sock, &params->sendbuf[off], len,
1182eb338e23SGleb Smirnoff 		    flags) == len);
1183eb338e23SGleb Smirnoff 		off += len;
1184eb338e23SGleb Smirnoff #ifdef DEBUG
1185eb338e23SGleb Smirnoff 		printf("send %zd%s\n", off, flags ? " EOR" : "");
1186eb338e23SGleb Smirnoff #endif
1187eb338e23SGleb Smirnoff 	}
1188eb338e23SGleb Smirnoff 
1189eb338e23SGleb Smirnoff 	return (NULL);
1190eb338e23SGleb Smirnoff }
1191eb338e23SGleb Smirnoff 
ATF_TC_BODY(random_eor_and_waitall,tc)1192eb338e23SGleb Smirnoff ATF_TC_BODY(random_eor_and_waitall, tc)
1193eb338e23SGleb Smirnoff {
1194eb338e23SGleb Smirnoff 	struct random_eor_params params;
1195eb338e23SGleb Smirnoff 	void *recvbuf;
1196eb338e23SGleb Smirnoff 	pthread_t t;
1197eb338e23SGleb Smirnoff 	size_t off;
1198eb338e23SGleb Smirnoff 	int fd[2], eor;
1199eb338e23SGleb Smirnoff 
1200eb338e23SGleb Smirnoff 	arc4random_buf(params.seed, sizeof(params.seed));
1201eb338e23SGleb Smirnoff 	printf("Using seed:");
1202eb338e23SGleb Smirnoff 	for (u_int i = 0; i < (u_int)sizeof(params.seed)/sizeof(u_short); i++)
1203eb338e23SGleb Smirnoff 		printf(" 0x%.4x,", params.seed[i]);
1204eb338e23SGleb Smirnoff 	printf("\n");
1205eb338e23SGleb Smirnoff 
1206eb338e23SGleb Smirnoff 	ATF_REQUIRE((params.sendbuf = malloc(RANDOM_TESTSIZE)) != NULL);
1207eb338e23SGleb Smirnoff 	for (u_int i = 0; i < RANDOM_TESTSIZE / (u_int )sizeof(long); i++)
1208eb338e23SGleb Smirnoff 		((long *)params.sendbuf)[i] = nrand48(&params.seed[0]);
1209eb338e23SGleb Smirnoff 
1210eb338e23SGleb Smirnoff 	ATF_REQUIRE(sysctlbyname("net.local.stream.recvspace",
1211eb338e23SGleb Smirnoff 	    &params.recvspace, &(size_t){sizeof(u_long)}, NULL, 0) != -1);
1212eb338e23SGleb Smirnoff 	ATF_REQUIRE((recvbuf =
1213eb338e23SGleb Smirnoff 	    malloc(RANDOM_RECVSIZE * params.recvspace)) != NULL);
1214eb338e23SGleb Smirnoff 
1215eb338e23SGleb Smirnoff 	params.nrecords = 2 * RANDOM_TESTSIZE /
1216eb338e23SGleb Smirnoff 	    (RANDOM_MAXRECORD * params.recvspace);
1217eb338e23SGleb Smirnoff 
1218eb338e23SGleb Smirnoff 	ATF_REQUIRE((params.records =
1219eb338e23SGleb Smirnoff 	    malloc(params.nrecords * sizeof(size_t *))) != NULL);
1220eb338e23SGleb Smirnoff 	off = 0;
1221eb338e23SGleb Smirnoff 	for (u_int i = 0; i < params.nrecords; i++) {
1222eb338e23SGleb Smirnoff 		off += 1 + nrand48(&params.seed[0]) %
1223eb338e23SGleb Smirnoff 		    (RANDOM_MAXRECORD * params.recvspace);
1224eb338e23SGleb Smirnoff 		if (off > RANDOM_TESTSIZE) {
1225eb338e23SGleb Smirnoff 			params.nrecords = i;
1226eb338e23SGleb Smirnoff 			break;
1227eb338e23SGleb Smirnoff 		}
1228eb338e23SGleb Smirnoff 		params.records[i] = off;
1229eb338e23SGleb Smirnoff 	}
1230eb338e23SGleb Smirnoff 	params.records[params.nrecords - 1] = RANDOM_TESTSIZE;
1231eb338e23SGleb Smirnoff 
1232eb338e23SGleb Smirnoff 	ATF_REQUIRE(socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, fd) == 0);
1233eb338e23SGleb Smirnoff 	params.sock = fd[0];
1234eb338e23SGleb Smirnoff 	ATF_REQUIRE(pthread_create(&t, NULL, sending_thread, &params) == 0);
1235eb338e23SGleb Smirnoff 
1236eb338e23SGleb Smirnoff 	off = 0;
1237eb338e23SGleb Smirnoff 	eor = 0;
1238eb338e23SGleb Smirnoff 	while (off < RANDOM_TESTSIZE) {
1239eb338e23SGleb Smirnoff 		struct iovec iov = {
1240eb338e23SGleb Smirnoff 			.iov_base = recvbuf,
1241eb338e23SGleb Smirnoff 			.iov_len = nrand48(&params.seed[0]) %
1242eb338e23SGleb Smirnoff 			    (RANDOM_RECVSIZE * params.recvspace)
1243eb338e23SGleb Smirnoff 		};
1244eb338e23SGleb Smirnoff 		struct msghdr hdr = {
1245eb338e23SGleb Smirnoff 			.msg_iov = &iov,
1246eb338e23SGleb Smirnoff 			.msg_iovlen = 1,
1247eb338e23SGleb Smirnoff 		};
1248eb338e23SGleb Smirnoff 		size_t len;
1249eb338e23SGleb Smirnoff 		int waitall = iov.iov_len & 0x1 ? MSG_WAITALL : 0;
1250eb338e23SGleb Smirnoff 
1251eb338e23SGleb Smirnoff 		len = recvmsg(fd[1], &hdr, waitall);
1252eb338e23SGleb Smirnoff 		if (waitall && !(hdr.msg_flags & MSG_EOR))
1253eb338e23SGleb Smirnoff 			ATF_CHECK_EQ_MSG(len, iov.iov_len,
1254eb338e23SGleb Smirnoff 			    "recvmsg(MSG_WAITALL): %zd, expected %zd",
1255eb338e23SGleb Smirnoff 			    len, iov.iov_len);
1256eb338e23SGleb Smirnoff 		if (off + len == params.records[eor]) {
1257eb338e23SGleb Smirnoff 			ATF_REQUIRE_MSG(hdr.msg_flags & MSG_EOR,
1258eb338e23SGleb Smirnoff 			    "recvmsg(): expected EOR @ %zd", off + len);
1259eb338e23SGleb Smirnoff 			eor++;
1260eb338e23SGleb Smirnoff 		} else {
1261eb338e23SGleb Smirnoff 			ATF_REQUIRE_MSG(off + len < params.records[eor],
1262eb338e23SGleb Smirnoff 			    "recvmsg() past EOR: %zd, expected %zd",
1263eb338e23SGleb Smirnoff 			    off + len, params.records[eor]);
1264eb338e23SGleb Smirnoff 			ATF_REQUIRE_MSG(!(hdr.msg_flags & MSG_EOR),
1265eb338e23SGleb Smirnoff 			    "recvmsg() spurious EOR at %zd, expected %zd",
1266eb338e23SGleb Smirnoff 			    off + len, params.records[eor]);
1267eb338e23SGleb Smirnoff 		}
1268eb338e23SGleb Smirnoff 		ATF_REQUIRE_MSG(0 == memcmp(params.sendbuf + off, recvbuf, len),
1269eb338e23SGleb Smirnoff 		    "data corruption past %zd", off);
1270eb338e23SGleb Smirnoff 		off += len;
1271eb338e23SGleb Smirnoff #ifdef DEBUG
1272eb338e23SGleb Smirnoff 		printf("recv %zd%s %zd/%zd%s\n", off,
1273eb338e23SGleb Smirnoff 		    (hdr.msg_flags & MSG_EOR) ?  " EOR" : "",
1274eb338e23SGleb Smirnoff 		    len, iov.iov_len,
1275eb338e23SGleb Smirnoff 		    waitall ? " WAITALL" : "");
1276eb338e23SGleb Smirnoff #endif
1277eb338e23SGleb Smirnoff 	}
1278eb338e23SGleb Smirnoff 
1279eb338e23SGleb Smirnoff 	ATF_REQUIRE(pthread_join(t, NULL) == 0);
1280eb338e23SGleb Smirnoff 	free(params.sendbuf);
1281eb338e23SGleb Smirnoff 	free(recvbuf);
1282eb338e23SGleb Smirnoff 	free(params.records);
1283eb338e23SGleb Smirnoff }
1284a8eb96d5SAlan Somers 
1285a8eb96d5SAlan Somers /*
1286a8eb96d5SAlan Somers  * Main.
1287a8eb96d5SAlan Somers  */
1288a8eb96d5SAlan Somers 
ATF_TP_ADD_TCS(tp)1289a8eb96d5SAlan Somers ATF_TP_ADD_TCS(tp)
1290a8eb96d5SAlan Somers {
1291a8eb96d5SAlan Somers 	/* Basic creation and connection tests */
1292a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, create_socket);
1293a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, create_socketpair);
1294a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, listen_unbound);
1295a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, bind);
1296a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, listen_bound);
1297a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, connect);
1298a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, accept);
1299a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, fcntl_nonblock);
1300a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, resize_buffers);
1301a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, resize_connected_buffers);
1302a8eb96d5SAlan Somers 
1303a8eb96d5SAlan Somers 	/* Unthreaded I/O tests */
1304a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, send_recv);
1305a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, send_recv_nonblocking);
1306a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, send_recv_with_connect);
1307a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendto_recvfrom);
13083bc122d2SGleb Smirnoff 	ATF_TP_ADD_TC(tp, send_before_accept);
1309f9927821SGleb Smirnoff 	ATF_TP_ADD_TC(tp, send_to_closed);
1310253d8a1fSGleb Smirnoff 	ATF_TP_ADD_TC(tp, implied_connect);
1311a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, shutdown_send);
1312a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, shutdown_send_sigpipe);
1313a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_8k_8k);
1314a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_8k_128k);
1315a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_128k_8k);
1316a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_128k_128k);
1317a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_8k);
1318a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_16k);
1319a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_32k);
1320a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_64k);
1321a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_128k);
1322a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_8k_nonblocking);
1323a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_16k_nonblocking);
1324a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_32k_nonblocking);
1325a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_64k_nonblocking);
1326a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_128k_nonblocking);
1327a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, rcvbuf_oversized);
1328a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_8k_8k);
1329a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_8k_128k);
1330a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_128k_8k);
1331a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_128k_128k);
1332a8eb96d5SAlan Somers 
1333a8eb96d5SAlan Somers 	/* Threaded I/O tests with blocking sockets */
1334a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_8k_8k);
1335a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_8k_128k);
1336a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_128k_8k);
1337a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_128k_128k);
1338eb338e23SGleb Smirnoff 	ATF_TP_ADD_TC(tp, random_eor_and_waitall);
1339a8eb96d5SAlan Somers 
1340a8eb96d5SAlan Somers 	return atf_no_error();
1341a8eb96d5SAlan Somers }
1342