xref: /freebsd/tests/sys/kern/unix_seqpacket_test.c (revision f9927821240aae9083a56ea66c4725e7f0082461)
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
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
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 *
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 *
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
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
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
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
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) {
263a8eb96d5SAlan Somers 				/*
264a8eb96d5SAlan Somers 				 * XXX: This is bug-compatible with the kernel.
265a8eb96d5SAlan Somers 				 * The kernel returns EMSGSIZE when it should
266a8eb96d5SAlan Somers 				 * return EAGAIN
267a8eb96d5SAlan Somers 				 */
268a8eb96d5SAlan Somers 				if (errno == EAGAIN || errno == EMSGSIZE)
269a8eb96d5SAlan Somers 					currently_sending = false;
270a8eb96d5SAlan Somers 				else {
271a8eb96d5SAlan Somers 					perror("send");
272a8eb96d5SAlan Somers 					atf_tc_fail("send failed");
273a8eb96d5SAlan Somers 				}
274a8eb96d5SAlan Somers 			} else  {
275a8eb96d5SAlan Somers 				ATF_CHECK_EQ_MSG(pktsize, ssize,
276a8eb96d5SAlan Somers 				    "expected %zd=send(...) but got %zd",
277a8eb96d5SAlan Somers 				    pktsize, ssize);
278a8eb96d5SAlan Somers 				num_sent++;
279a8eb96d5SAlan Somers 			}
280a8eb96d5SAlan Somers 		} else {
281a8eb96d5SAlan Somers 			/* The simulated receiving process */
282a8eb96d5SAlan Somers 			rsize = recv(sv[1], rcvbuf, pktsize, MSG_WAITALL);
283a8eb96d5SAlan Somers 			if (rsize < 0) {
284a8eb96d5SAlan Somers 				if (errno == EAGAIN) {
285a8eb96d5SAlan Somers 					currently_sending = true;
286a8eb96d5SAlan Somers 					ATF_REQUIRE_MSG(num_sent < numpkts,
287a8eb96d5SAlan Somers 					    "Packets were lost!");
288a8eb96d5SAlan Somers 				}
289a8eb96d5SAlan Somers 				else {
290a8eb96d5SAlan Somers 					perror("recv");
291a8eb96d5SAlan Somers 					atf_tc_fail("recv failed");
292a8eb96d5SAlan Somers 				}
293a8eb96d5SAlan Somers 			} else  {
294a8eb96d5SAlan Somers 				ATF_CHECK_EQ_MSG(pktsize, rsize,
295a8eb96d5SAlan Somers 				    "expected %zd=recv(...) but got %zd",
296a8eb96d5SAlan Somers 				    pktsize, rsize);
297a8eb96d5SAlan Somers 				memset(comparebuf, num_received, pktsize);
298a8eb96d5SAlan Somers 				ATF_CHECK_EQ_MSG(0, memcmp(comparebuf, rcvbuf,
299a8eb96d5SAlan Somers 				    			   pktsize),
300a8eb96d5SAlan Somers 				    "Received data miscompare");
301a8eb96d5SAlan Somers 				num_received++;
302a8eb96d5SAlan Somers 			}
303a8eb96d5SAlan Somers 		}
304a8eb96d5SAlan Somers 	}
305e594026dSAlan Somers 	close(sv[0]);
306e594026dSAlan Somers 	close(sv[1]);
307a8eb96d5SAlan Somers }
308a8eb96d5SAlan Somers 
309a8eb96d5SAlan Somers typedef struct {
310a8eb96d5SAlan Somers 	ssize_t	pktsize;
311a8eb96d5SAlan Somers 	int	numpkts;
312a8eb96d5SAlan Somers 	int	so;
313a8eb96d5SAlan Somers } test_pipe_thread_data_t;
314a8eb96d5SAlan Somers 
315a8eb96d5SAlan Somers static void*
316a8eb96d5SAlan Somers test_pipe_writer(void* args)
317a8eb96d5SAlan Somers {
318a8eb96d5SAlan Somers 	test_pipe_thread_data_t* td = args;
319a8eb96d5SAlan Somers 	char sndbuf[td->pktsize];
320a8eb96d5SAlan Somers 	ssize_t ssize;
321a8eb96d5SAlan Somers 	int i;
322a8eb96d5SAlan Somers 
323a8eb96d5SAlan Somers 	for(i=0; i < td->numpkts; i++) {
324a8eb96d5SAlan Somers 			memset(sndbuf, i, td->pktsize);
325a8eb96d5SAlan Somers 			ssize = send(td->so, sndbuf, td->pktsize, MSG_EOR);
326a8eb96d5SAlan Somers 			if (ssize < 0) {
327a8eb96d5SAlan Somers 				perror("send");
328a8eb96d5SAlan Somers 				atf_tc_fail("send returned < 0");
329a8eb96d5SAlan Somers 			}
330a8eb96d5SAlan Somers 			ATF_CHECK_EQ_MSG(td->pktsize, ssize,
331a8eb96d5SAlan Somers 			    		 "expected %zd=send(...) but got %zd",
332a8eb96d5SAlan Somers 			    		  td->pktsize, ssize);
333a8eb96d5SAlan Somers 	}
334a8eb96d5SAlan Somers 	return (0);
335a8eb96d5SAlan Somers }
336a8eb96d5SAlan Somers 
337a8eb96d5SAlan Somers static void*
338a8eb96d5SAlan Somers test_pipe_reader(void* args)
339a8eb96d5SAlan Somers {
340a8eb96d5SAlan Somers 	test_pipe_thread_data_t* td = args;
341a8eb96d5SAlan Somers 	char rcvbuf[td->pktsize];
342a8eb96d5SAlan Somers 	char comparebuf[td->pktsize];
343a8eb96d5SAlan Somers 	ssize_t rsize;
344a8eb96d5SAlan Somers 	int i, d;
345a8eb96d5SAlan Somers 
346a8eb96d5SAlan Somers 	for(i=0; i < td->numpkts; i++) {
347a8eb96d5SAlan Somers 		memset(comparebuf, i, td->pktsize);
348a8eb96d5SAlan Somers 		rsize = recv(td->so, rcvbuf, td->pktsize, MSG_WAITALL);
349a8eb96d5SAlan Somers 		if (rsize < 0) {
350a8eb96d5SAlan Somers 			perror("recv");
351a8eb96d5SAlan Somers 			atf_tc_fail("recv returned < 0");
352a8eb96d5SAlan Somers 		}
353a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(td->pktsize, rsize,
354a8eb96d5SAlan Somers 		    		 "expected %zd=send(...) but got %zd",
355a8eb96d5SAlan Somers 				 td->pktsize, rsize);
356a8eb96d5SAlan Somers 		d = memcmp(comparebuf, rcvbuf, td->pktsize);
357a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(0, d,
358a8eb96d5SAlan Somers 		    		 "Received data miscompare on packet %d", i);
359a8eb96d5SAlan Somers 	}
360a8eb96d5SAlan Somers 	return (0);
361a8eb96d5SAlan Somers }
362a8eb96d5SAlan Somers 
363a8eb96d5SAlan Somers 
3645d5b721aSAlan Somers static void
365ea703329SBrooks Davis test_pipe(int sndbufsize, int rcvbufsize)
366a8eb96d5SAlan Somers {
367a8eb96d5SAlan Somers 	test_pipe_thread_data_t writer_data, reader_data;
368a8eb96d5SAlan Somers 	pthread_t writer, reader;
369a8eb96d5SAlan Somers 	int sv[2];
370a8eb96d5SAlan Somers 	const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
371a8eb96d5SAlan Somers 	int numpkts;
372a8eb96d5SAlan Somers 
373a8eb96d5SAlan Somers 	/* setup the socket pair */
374a8eb96d5SAlan Somers 	do_socketpair(sv);
375a8eb96d5SAlan Somers 	/* Setup the buffers */
376a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
377a8eb96d5SAlan Somers 	    sizeof(sndbufsize)));
378a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
379a8eb96d5SAlan Somers 	    sizeof(rcvbufsize)));
380a8eb96d5SAlan Somers 
381a8eb96d5SAlan Somers 	/* Send a total amount of data comfortably greater than the buffers */
382a8eb96d5SAlan Somers 	numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
383a8eb96d5SAlan Somers 
384a8eb96d5SAlan Somers 	/* Start the child threads */
385a8eb96d5SAlan Somers 	writer_data.pktsize = pktsize;
386a8eb96d5SAlan Somers 	writer_data.numpkts = numpkts;
387a8eb96d5SAlan Somers 	writer_data.so = sv[0];
388a8eb96d5SAlan Somers 	reader_data.pktsize = pktsize;
389a8eb96d5SAlan Somers 	reader_data.numpkts = numpkts;
390a8eb96d5SAlan Somers 	reader_data.so = sv[1];
391a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, pthread_create(&writer, NULL, test_pipe_writer,
392a8eb96d5SAlan Somers 	    				 (void*)&writer_data));
3938de34a88SAlan Somers 	/*
3948de34a88SAlan Somers 	 * Give the writer time to start writing, and hopefully block, before
3958de34a88SAlan Somers 	 * starting the reader.  This increases the likelihood of the test case
3968de34a88SAlan Somers 	 * failing due to PR kern/185812
3978de34a88SAlan Somers 	 */
3988de34a88SAlan Somers 	usleep(1000);
399a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, pthread_create(&reader, NULL, test_pipe_reader,
400a8eb96d5SAlan Somers 	    				 (void*)&reader_data));
401a8eb96d5SAlan Somers 
402a8eb96d5SAlan Somers 	/* Join the children */
403a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, pthread_join(writer, NULL));
404a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, pthread_join(reader, NULL));
405e594026dSAlan Somers 	close(sv[0]);
406e594026dSAlan Somers 	close(sv[1]);
407a8eb96d5SAlan Somers }
408a8eb96d5SAlan Somers 
409a8eb96d5SAlan Somers 
410a8eb96d5SAlan Somers /*
411a8eb96d5SAlan Somers  * Test Cases
412a8eb96d5SAlan Somers  */
413a8eb96d5SAlan Somers 
414a8eb96d5SAlan Somers /* Create a SEQPACKET socket */
415a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(create_socket);
416a8eb96d5SAlan Somers ATF_TC_BODY(create_socket, tc)
417a8eb96d5SAlan Somers {
418a8eb96d5SAlan Somers 	int s;
419a8eb96d5SAlan Somers 
420a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
4216addc01eSAlan Somers 	ATF_REQUIRE(s >= 0);
422e594026dSAlan Somers 	close(s);
423a8eb96d5SAlan Somers }
424a8eb96d5SAlan Somers 
425a8eb96d5SAlan Somers /* Create SEQPACKET sockets using socketpair(2) */
426a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(create_socketpair);
427a8eb96d5SAlan Somers ATF_TC_BODY(create_socketpair, tc)
428a8eb96d5SAlan Somers {
429a8eb96d5SAlan Somers 	int sv[2];
430a8eb96d5SAlan Somers 	int s;
431a8eb96d5SAlan Somers 
432a8eb96d5SAlan Somers 	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
433a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, s);
434a8eb96d5SAlan Somers 	ATF_CHECK(sv[0] >= 0);
435a8eb96d5SAlan Somers 	ATF_CHECK(sv[1] >= 0);
436a8eb96d5SAlan Somers 	ATF_CHECK(sv[0] != sv[1]);
437e594026dSAlan Somers 	close(sv[0]);
438e594026dSAlan Somers 	close(sv[1]);
439a8eb96d5SAlan Somers }
440a8eb96d5SAlan Somers 
441a8eb96d5SAlan Somers /* Call listen(2) without first calling bind(2).  It should fail */
442a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(listen_unbound);
443a8eb96d5SAlan Somers ATF_TC_BODY(listen_unbound, tc)
444a8eb96d5SAlan Somers {
445a8eb96d5SAlan Somers 	int s, r;
446a8eb96d5SAlan Somers 
447a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
448a8eb96d5SAlan Somers 	ATF_REQUIRE(s > 0);
449a8eb96d5SAlan Somers 	r = listen(s, -1);
450a8eb96d5SAlan Somers 	/* expect listen to fail since we haven't called bind(2) */
451a8eb96d5SAlan Somers 	ATF_CHECK(r != 0);
452e594026dSAlan Somers 	close(s);
453a8eb96d5SAlan Somers }
454a8eb96d5SAlan Somers 
455a8eb96d5SAlan Somers /* Bind the socket to a file */
456a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(bind);
457a8eb96d5SAlan Somers ATF_TC_BODY(bind, tc)
458a8eb96d5SAlan Somers {
459a8eb96d5SAlan Somers 	struct sockaddr_un sun;
460a8eb96d5SAlan Somers 	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
461a8eb96d5SAlan Somers 	const char *path = "sock";
462a8eb96d5SAlan Somers 	int s, r;
463a8eb96d5SAlan Somers 
464a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
465a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
466a8eb96d5SAlan Somers 
467a8eb96d5SAlan Somers 	bzero(&sun, sizeof(sun));
468a8eb96d5SAlan Somers 	sun.sun_family = AF_LOCAL;
469a8eb96d5SAlan Somers 	sun.sun_len = sizeof(sun);
470a8eb96d5SAlan Somers 	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
471a8eb96d5SAlan Somers 	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
472a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, r);
473e594026dSAlan Somers 	close(s);
474a8eb96d5SAlan Somers }
475a8eb96d5SAlan Somers 
476a8eb96d5SAlan Somers /* listen(2) a socket that is already bound(2) should succeed */
477a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(listen_bound);
478a8eb96d5SAlan Somers ATF_TC_BODY(listen_bound, tc)
479a8eb96d5SAlan Somers {
4801f46c32cSGleb Smirnoff 	int s;
481a8eb96d5SAlan Somers 
4821f46c32cSGleb Smirnoff 	(void)mk_listening_socket(&s);
483e594026dSAlan Somers 	close(s);
484a8eb96d5SAlan Somers }
485a8eb96d5SAlan Somers 
486a8eb96d5SAlan Somers /* connect(2) can make a connection */
487a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(connect);
488a8eb96d5SAlan Somers ATF_TC_BODY(connect, tc)
489a8eb96d5SAlan Somers {
4901f46c32cSGleb Smirnoff 	const struct sockaddr_un *sun;
4911f46c32cSGleb Smirnoff 	int s, err, s2;
492a8eb96d5SAlan Somers 
4931f46c32cSGleb Smirnoff 	sun = mk_listening_socket(&s);
494a8eb96d5SAlan Somers 
495a8eb96d5SAlan Somers 	/* Create the other socket */
496a8eb96d5SAlan Somers 	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
497a8eb96d5SAlan Somers 	ATF_REQUIRE(s2 >= 0);
4981f46c32cSGleb Smirnoff 	err = connect(s2, (struct sockaddr *)sun, sizeof(*sun));
499a8eb96d5SAlan Somers 	if (err != 0) {
500a8eb96d5SAlan Somers 		perror("connect");
501a8eb96d5SAlan Somers 		atf_tc_fail("connect(2) failed");
502a8eb96d5SAlan Somers 	}
503e594026dSAlan Somers 	close(s);
504e594026dSAlan Somers 	close(s2);
505a8eb96d5SAlan Somers }
506a8eb96d5SAlan Somers 
5073bc122d2SGleb Smirnoff /*
5083bc122d2SGleb Smirnoff  * An undocumented feature that we probably want to preserve: sending to
5093bc122d2SGleb Smirnoff  * a socket that isn't yet accepted lands data on the socket.  It can be
5103bc122d2SGleb Smirnoff  * read after accept(2).
5113bc122d2SGleb Smirnoff  */
5123bc122d2SGleb Smirnoff ATF_TC_WITHOUT_HEAD(send_before_accept);
5133bc122d2SGleb Smirnoff ATF_TC_BODY(send_before_accept, tc)
5143bc122d2SGleb Smirnoff {
5153bc122d2SGleb Smirnoff 	const char buf[] = "hello";
5163bc122d2SGleb Smirnoff 	char repl[sizeof(buf)];
5173bc122d2SGleb Smirnoff 	const struct sockaddr_un *sun;
5183bc122d2SGleb Smirnoff 	int l, s, a;
5193bc122d2SGleb Smirnoff 
5203bc122d2SGleb Smirnoff 	sun = mk_listening_socket(&l);
5213bc122d2SGleb Smirnoff 
5223bc122d2SGleb Smirnoff 	ATF_REQUIRE((s = socket(PF_LOCAL, SOCK_SEQPACKET, 0)) > 0);
5233bc122d2SGleb Smirnoff 	ATF_REQUIRE(connect(s, (struct sockaddr *)sun, sizeof(*sun)) == 0);
5243bc122d2SGleb Smirnoff 	ATF_REQUIRE(send(s, &buf, sizeof(buf), 0) == sizeof(buf));
5253bc122d2SGleb Smirnoff 	ATF_REQUIRE((a = accept(l, NULL, NULL)) != 1);
5263bc122d2SGleb Smirnoff 	ATF_REQUIRE(recv(a, &repl, sizeof(repl), 0) == sizeof(buf));
5273bc122d2SGleb Smirnoff 	ATF_REQUIRE(strcmp(buf, repl) == 0);
5283bc122d2SGleb Smirnoff 	close(l);
5293bc122d2SGleb Smirnoff 	close(s);
5303bc122d2SGleb Smirnoff 	close(a);
5313bc122d2SGleb Smirnoff }
5323bc122d2SGleb Smirnoff 
533*f9927821SGleb Smirnoff /*
534*f9927821SGleb Smirnoff  * Test that close(2) of the peer ends in EPIPE when we try to send(2).
535*f9927821SGleb Smirnoff  * Test both normal case as well as a peer that was not accept(2)-ed.
536*f9927821SGleb Smirnoff  */
537*f9927821SGleb Smirnoff static bool sigpipe_received = false;
538*f9927821SGleb Smirnoff static void
539*f9927821SGleb Smirnoff sigpipe_handler(int signo __unused)
540*f9927821SGleb Smirnoff {
541*f9927821SGleb Smirnoff 	sigpipe_received = true;
542*f9927821SGleb Smirnoff }
543*f9927821SGleb Smirnoff 
544*f9927821SGleb Smirnoff ATF_TC_WITHOUT_HEAD(send_to_closed);
545*f9927821SGleb Smirnoff ATF_TC_BODY(send_to_closed, tc)
546*f9927821SGleb Smirnoff {
547*f9927821SGleb Smirnoff 	struct sigaction sa = {
548*f9927821SGleb Smirnoff 		.sa_handler = sigpipe_handler,
549*f9927821SGleb Smirnoff 	};
550*f9927821SGleb Smirnoff 	const struct sockaddr_un *sun;
551*f9927821SGleb Smirnoff 	int l, s, a;
552*f9927821SGleb Smirnoff 
553*f9927821SGleb Smirnoff 	ATF_REQUIRE(sigemptyset(&sa.sa_mask) == 0);
554*f9927821SGleb Smirnoff 	ATF_REQUIRE(sigaction(SIGPIPE, &sa, NULL) == 0);
555*f9927821SGleb Smirnoff 
556*f9927821SGleb Smirnoff 	sun = mk_listening_socket(&l);
557*f9927821SGleb Smirnoff 
558*f9927821SGleb Smirnoff 	ATF_REQUIRE((s = socket(PF_LOCAL, SOCK_SEQPACKET, 0)) > 0);
559*f9927821SGleb Smirnoff 	ATF_REQUIRE(connect(s, (struct sockaddr *)sun, sizeof(*sun)) == 0);
560*f9927821SGleb Smirnoff 	ATF_REQUIRE((a = accept(l, NULL, NULL)) != 1);
561*f9927821SGleb Smirnoff 	close(a);
562*f9927821SGleb Smirnoff 	ATF_REQUIRE(send(s, &s, sizeof(s), 0) == -1);
563*f9927821SGleb Smirnoff 	ATF_REQUIRE(errno == EPIPE);
564*f9927821SGleb Smirnoff 	ATF_REQUIRE(sigpipe_received == true);
565*f9927821SGleb Smirnoff 	close(s);
566*f9927821SGleb Smirnoff 
567*f9927821SGleb Smirnoff 	ATF_REQUIRE((s = socket(PF_LOCAL, SOCK_SEQPACKET, 0)) > 0);
568*f9927821SGleb Smirnoff 	ATF_REQUIRE(connect(s, (struct sockaddr *)sun, sizeof(*sun)) == 0);
569*f9927821SGleb Smirnoff 	close(l);
570*f9927821SGleb Smirnoff 	sigpipe_received = false;
571*f9927821SGleb Smirnoff 	ATF_REQUIRE(send(s, &s, sizeof(s), 0) == -1);
572*f9927821SGleb Smirnoff 	ATF_REQUIRE(errno == EPIPE);
573*f9927821SGleb Smirnoff 	ATF_REQUIRE(sigpipe_received == true);
574*f9927821SGleb Smirnoff 	close(s);
575*f9927821SGleb Smirnoff 
576*f9927821SGleb Smirnoff 	sa.sa_handler = SIG_DFL;
577*f9927821SGleb Smirnoff 	ATF_REQUIRE(sigaction(SIGPIPE, &sa, NULL) == 0);
578*f9927821SGleb Smirnoff }
579*f9927821SGleb Smirnoff 
580253d8a1fSGleb Smirnoff /* Implied connect is unix/dgram only feature. Fails on stream or seqpacket. */
581253d8a1fSGleb Smirnoff ATF_TC_WITHOUT_HEAD(implied_connect);
582253d8a1fSGleb Smirnoff ATF_TC_BODY(implied_connect, tc)
583253d8a1fSGleb Smirnoff {
584253d8a1fSGleb Smirnoff 	const struct sockaddr_un *sun;
585253d8a1fSGleb Smirnoff 	int l, s;
586253d8a1fSGleb Smirnoff 
587253d8a1fSGleb Smirnoff 	sun = mk_listening_socket(&l);
588253d8a1fSGleb Smirnoff 
589253d8a1fSGleb Smirnoff 	ATF_REQUIRE((s = socket(PF_LOCAL, SOCK_SEQPACKET, 0)) > 0);
590253d8a1fSGleb Smirnoff 	ATF_REQUIRE(sendto(s, &s, sizeof(s), 0, (struct sockaddr *)sun,
591253d8a1fSGleb Smirnoff 	    sizeof(*sun)) == -1);
592253d8a1fSGleb Smirnoff 	ATF_REQUIRE(errno == ENOTCONN);
593253d8a1fSGleb Smirnoff 	close(l);
594253d8a1fSGleb Smirnoff 	close(s);
595253d8a1fSGleb Smirnoff }
596253d8a1fSGleb Smirnoff 
597a8eb96d5SAlan Somers /* accept(2) can receive a connection */
598a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(accept);
599a8eb96d5SAlan Somers ATF_TC_BODY(accept, tc)
600a8eb96d5SAlan Somers {
601a8eb96d5SAlan Somers 	int sv[2];
602a8eb96d5SAlan Somers 
603a8eb96d5SAlan Somers 	mk_pair_of_sockets(sv);
604e594026dSAlan Somers 	close(sv[0]);
605e594026dSAlan Somers 	close(sv[1]);
606a8eb96d5SAlan Somers }
607a8eb96d5SAlan Somers 
608a8eb96d5SAlan Somers 
609a8eb96d5SAlan Somers /* Set O_NONBLOCK on the socket */
610a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(fcntl_nonblock);
611a8eb96d5SAlan Somers ATF_TC_BODY(fcntl_nonblock, tc)
612a8eb96d5SAlan Somers {
613a8eb96d5SAlan Somers 	int s;
614a8eb96d5SAlan Somers 
615a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
616a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
617a8eb96d5SAlan Somers 	if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
618a8eb96d5SAlan Somers 		perror("fcntl");
619a8eb96d5SAlan Somers 		atf_tc_fail("fcntl failed");
620a8eb96d5SAlan Somers 	}
621e594026dSAlan Somers 	close(s);
622a8eb96d5SAlan Somers }
623a8eb96d5SAlan Somers 
624a8eb96d5SAlan Somers /* Resize the send and receive buffers */
625a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(resize_buffers);
626a8eb96d5SAlan Somers ATF_TC_BODY(resize_buffers, tc)
627a8eb96d5SAlan Somers {
628a8eb96d5SAlan Somers 	int s;
629a8eb96d5SAlan Somers 	int sndbuf = 12345;
630a8eb96d5SAlan Somers 	int rcvbuf = 23456;
631a8eb96d5SAlan Somers 	int xs, xr;
632a8eb96d5SAlan Somers 	socklen_t sl = sizeof(xs);
633a8eb96d5SAlan Somers 
634a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
635a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
636a8eb96d5SAlan Somers 
637a8eb96d5SAlan Somers 	printf("                       Socket Buffer Sizes\n");
638a8eb96d5SAlan Somers 	printf("                              | SNDBUF  | RCVBUF  |\n");
639a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
640a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
641a8eb96d5SAlan Somers 	printf("Default                       | %7d | %7d |\n", xs, xr);
642a8eb96d5SAlan Somers 
643a8eb96d5SAlan Somers 	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) != 0){
644a8eb96d5SAlan Somers 		perror("setsockopt");
645a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_SNDBUF) failed");
646a8eb96d5SAlan Somers 	}
647a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
648a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
649a8eb96d5SAlan Somers 	printf("After changing SNDBUF         | %7d | %7d |\n", xs, xr);
650a8eb96d5SAlan Somers 
651a8eb96d5SAlan Somers 	if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) != 0){
652a8eb96d5SAlan Somers 		perror("setsockopt");
653a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_RCVBUF) failed");
654a8eb96d5SAlan Somers 	}
655a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
656a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
657a8eb96d5SAlan Somers 	printf("After changing RCVBUF         | %7d | %7d |\n", xs, xr);
658e594026dSAlan Somers 	close(s);
659a8eb96d5SAlan Somers }
660a8eb96d5SAlan Somers 
661a8eb96d5SAlan Somers /*
662a8eb96d5SAlan Somers  * Resize the send and receive buffers of a connected socketpair
663a8eb96d5SAlan Somers  * Print some useful debugging info too
664a8eb96d5SAlan Somers  */
665a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(resize_connected_buffers);
666a8eb96d5SAlan Somers ATF_TC_BODY(resize_connected_buffers, tc)
667a8eb96d5SAlan Somers {
668a8eb96d5SAlan Somers 	int sv[2];
669a8eb96d5SAlan Somers 	int sndbuf = 12345;
670a8eb96d5SAlan Somers 	int rcvbuf = 23456;
671a8eb96d5SAlan Somers 	int err;
672a8eb96d5SAlan Somers 	int ls, lr, rs, rr;
673a8eb96d5SAlan Somers 	socklen_t sl = sizeof(ls);
674a8eb96d5SAlan Somers 
675a8eb96d5SAlan Somers 	/* setup the socket pair */
676a8eb96d5SAlan Somers 	do_socketpair(sv);
677a8eb96d5SAlan Somers 
678a8eb96d5SAlan Somers 	printf("                       Socket Buffer Sizes\n");
679a8eb96d5SAlan Somers 	printf("                              | Left Socket       | Right Socket      |\n");
680a8eb96d5SAlan Somers 	printf("                              | SNDBUF  | RCVBUF  | SNDBUF  | RCVBUF  |\n");
681a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
682a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
683a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
684a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
685a8eb96d5SAlan Somers 	printf("Default                       | %7d | %7d | %7d | %7d |\n",
686a8eb96d5SAlan Somers 	    ls, lr, rs, rr);
687a8eb96d5SAlan Somers 
688a8eb96d5SAlan Somers 	/* Update one side's send buffer */
689a8eb96d5SAlan Somers 	err = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
690a8eb96d5SAlan Somers 	if (err != 0){
691a8eb96d5SAlan Somers 		perror("setsockopt");
692a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_SNDBUF) failed");
693a8eb96d5SAlan Somers 	}
694a8eb96d5SAlan Somers 
695a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
696a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
697a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
698a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
699a8eb96d5SAlan Somers 	printf("After changing Left's SNDBUF  | %7d | %7d | %7d | %7d |\n",
700a8eb96d5SAlan Somers 	    ls, lr, rs, rr);
701a8eb96d5SAlan Somers 
702a8eb96d5SAlan Somers 	/* Update the same side's receive buffer */
703a8eb96d5SAlan Somers 	err = setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
704a8eb96d5SAlan Somers 	if (err != 0){
705a8eb96d5SAlan Somers 		perror("setsockopt");
706a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_RCVBUF) failed");
707a8eb96d5SAlan Somers 	}
708a8eb96d5SAlan Somers 
709a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
710a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
711a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
712a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
713a8eb96d5SAlan Somers 	printf("After changing Left's RCVBUF  | %7d | %7d | %7d | %7d |\n",
714a8eb96d5SAlan Somers 	    ls, lr, rs, rr);
715e594026dSAlan Somers 	close(sv[0]);
716e594026dSAlan Somers 	close(sv[1]);
717a8eb96d5SAlan Somers }
718a8eb96d5SAlan Somers 
719a8eb96d5SAlan Somers 
720a8eb96d5SAlan Somers /* send(2) and recv(2) a single short record */
721a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(send_recv);
722a8eb96d5SAlan Somers ATF_TC_BODY(send_recv, tc)
723a8eb96d5SAlan Somers {
724a8eb96d5SAlan Somers 	int sv[2];
725a8eb96d5SAlan Somers 	const int bufsize = 64;
726a8eb96d5SAlan Somers 	const char *data = "data";
727a8eb96d5SAlan Somers 	char recv_buf[bufsize];
7285d5b721aSAlan Somers 	ssize_t datalen;
729a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
730a8eb96d5SAlan Somers 
731a8eb96d5SAlan Somers 	/* setup the socket pair */
732a8eb96d5SAlan Somers 	do_socketpair(sv);
733a8eb96d5SAlan Somers 
734a8eb96d5SAlan Somers 	/* send and receive a small packet */
735a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
736a8eb96d5SAlan Somers 	ssize = send(sv[0], data, datalen, MSG_EOR);
737a8eb96d5SAlan Somers 	if (ssize < 0) {
738a8eb96d5SAlan Somers 		perror("send");
739a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
740a8eb96d5SAlan Somers 	}
741a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
742a8eb96d5SAlan Somers 	    datalen, ssize);
743a8eb96d5SAlan Somers 
744a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
745a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
746e594026dSAlan Somers 	close(sv[0]);
747e594026dSAlan Somers 	close(sv[1]);
748a8eb96d5SAlan Somers }
749a8eb96d5SAlan Somers 
750a8eb96d5SAlan Somers /* sendto(2) and recvfrom(2) a single short record
751a8eb96d5SAlan Somers  * According to The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
752a8eb96d5SAlan Somers  * Edition, sendto(2) is exactly the same as send(2) on a connection-mode socket
753a8eb96d5SAlan Somers  *
754a8eb96d5SAlan Somers  * According to the same spec, not all protocols are required to provide the
755a8eb96d5SAlan Somers  * source addres in recvfrom(2).
756a8eb96d5SAlan Somers  */
757a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendto_recvfrom);
758a8eb96d5SAlan Somers ATF_TC_BODY(sendto_recvfrom, tc)
759a8eb96d5SAlan Somers {
760983a2d91SEnji Cooper #ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS
7611f46c32cSGleb Smirnoff 	const sockaddr_un *sun;
762983a2d91SEnji Cooper #endif
763a8eb96d5SAlan Somers 	struct sockaddr_storage from;
764a8eb96d5SAlan Somers 	int sv[2];
765a8eb96d5SAlan Somers 	const int bufsize = 64;
766a8eb96d5SAlan Somers 	const char *data = "data";
767a8eb96d5SAlan Somers 	char recv_buf[bufsize];
7685d5b721aSAlan Somers 	ssize_t datalen;
769a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
770a8eb96d5SAlan Somers 	socklen_t fromlen;
771a8eb96d5SAlan Somers 
772a8eb96d5SAlan Somers 	/* setup the socket pair */
773983a2d91SEnji Cooper #ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS
7741f46c32cSGleb Smirnoff 	sun =
775983a2d91SEnji Cooper #endif
776983a2d91SEnji Cooper 		mk_pair_of_sockets(sv);
777a8eb96d5SAlan Somers 
778a8eb96d5SAlan Somers 	/* send and receive a small packet */
779a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
780a8eb96d5SAlan Somers 	ssize = sendto(sv[0], data, datalen, MSG_EOR, NULL, 0);
781a8eb96d5SAlan Somers 	if (ssize < 0) {
782a8eb96d5SAlan Somers 		perror("send");
783a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
784a8eb96d5SAlan Somers 	}
785a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
786a8eb96d5SAlan Somers 	    datalen, ssize);
787a8eb96d5SAlan Somers 
788a8eb96d5SAlan Somers 	fromlen = sizeof(from);
789a8eb96d5SAlan Somers 	rsize = recvfrom(sv[1], recv_buf, bufsize, MSG_WAITALL,
790a8eb96d5SAlan Somers 	    (struct sockaddr*)&from, &fromlen);
791a8eb96d5SAlan Somers 	if (ssize < 0) {
792a8eb96d5SAlan Somers 		perror("recvfrom");
793a8eb96d5SAlan Somers 		atf_tc_fail("recvfrom returned < 0");
794a8eb96d5SAlan Somers 	}
795a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
796a8eb96d5SAlan Somers 
797983a2d91SEnji Cooper #ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS
798a8eb96d5SAlan Somers 	/*
799a8eb96d5SAlan Somers 	 * FreeBSD does not currently provide the source address for SEQ_PACKET
800a8eb96d5SAlan Somers 	 * AF_UNIX sockets, and POSIX does not require it, so these two checks
801a8eb96d5SAlan Somers 	 * are disabled.  If FreeBSD gains that feature in the future, then
802a8eb96d5SAlan Somers 	 * these checks may be reenabled
803a8eb96d5SAlan Somers 	 */
804983a2d91SEnji Cooper 	ATF_CHECK_EQ(PF_LOCAL, from.ss_family);
8051f46c32cSGleb Smirnoff 	ATF_CHECK_STREQ(sun->sun_path, ((struct sockaddr_un*)&from)->sun_path);
806983a2d91SEnji Cooper #endif
807e594026dSAlan Somers 	close(sv[0]);
808e594026dSAlan Somers 	close(sv[1]);
809a8eb96d5SAlan Somers }
810a8eb96d5SAlan Somers 
811a8eb96d5SAlan Somers /*
812a8eb96d5SAlan Somers  * send(2) and recv(2) a single short record with sockets created the
813a8eb96d5SAlan Somers  * traditional way, involving bind, listen, connect, and accept
814a8eb96d5SAlan Somers  */
815a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(send_recv_with_connect);
816a8eb96d5SAlan Somers ATF_TC_BODY(send_recv_with_connect, tc)
817a8eb96d5SAlan Somers {
818a8eb96d5SAlan Somers 	int sv[2];
819a8eb96d5SAlan Somers 	const int bufsize = 64;
820a8eb96d5SAlan Somers 	const char *data = "data";
821a8eb96d5SAlan Somers 	char recv_buf[bufsize];
8225d5b721aSAlan Somers 	ssize_t datalen;
823a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
824a8eb96d5SAlan Somers 
825a8eb96d5SAlan Somers 	mk_pair_of_sockets(sv);
826a8eb96d5SAlan Somers 
827a8eb96d5SAlan Somers 	/* send and receive a small packet */
828a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
829a8eb96d5SAlan Somers 	ssize = send(sv[0], data, datalen, MSG_EOR);
830a8eb96d5SAlan Somers 	if (ssize < 0) {
831a8eb96d5SAlan Somers 		perror("send");
832a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
833a8eb96d5SAlan Somers 	}
834a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
835a8eb96d5SAlan Somers 	    datalen, ssize);
836a8eb96d5SAlan Somers 
837a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
838a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
839e594026dSAlan Somers 	close(sv[0]);
840e594026dSAlan Somers 	close(sv[1]);
841a8eb96d5SAlan Somers }
842a8eb96d5SAlan Somers 
843a8eb96d5SAlan Somers /* send(2) should fail on a shutdown socket */
844a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(shutdown_send);
845a8eb96d5SAlan Somers ATF_TC_BODY(shutdown_send, tc)
846a8eb96d5SAlan Somers {
8471f46c32cSGleb Smirnoff 	const struct sockaddr_un *sun;
8484446a47aSSergey Kandaurov 	const char *data = "data";
849fa5e5f53SEnji Cooper 	ssize_t datalen, ssize;
8504446a47aSSergey Kandaurov 	int s, err, s2;
851a8eb96d5SAlan Somers 
8521f46c32cSGleb Smirnoff 	sun = mk_listening_socket(&s);
8534446a47aSSergey Kandaurov 
8544446a47aSSergey Kandaurov 	/* Create the other socket */
8554446a47aSSergey Kandaurov 	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
8564446a47aSSergey Kandaurov 	ATF_REQUIRE(s2 >= 0);
8571f46c32cSGleb Smirnoff 	err = connect(s2, (struct sockaddr *)sun, sizeof(*sun));
8584446a47aSSergey Kandaurov 	if (err != 0) {
8594446a47aSSergey Kandaurov 		perror("connect");
8604446a47aSSergey Kandaurov 		atf_tc_fail("connect(2) failed");
8614446a47aSSergey Kandaurov 	}
8624446a47aSSergey Kandaurov 
8634446a47aSSergey Kandaurov 	ATF_CHECK_EQ(0, shutdown(s2, SHUT_RDWR));
864fa5e5f53SEnji Cooper 	datalen = strlen(data) + 1;	/* +1 for the null */
865a8eb96d5SAlan Somers 	/* USE MSG_NOSIGNAL so we don't get SIGPIPE */
866fa5e5f53SEnji Cooper 	ssize = send(s2, data, datalen, MSG_EOR | MSG_NOSIGNAL);
867a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EPIPE, errno);
868a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, ssize);
869e594026dSAlan Somers 	close(s);
8704446a47aSSergey Kandaurov 	close(s2);
871a8eb96d5SAlan Somers }
872a8eb96d5SAlan Somers 
873a8eb96d5SAlan Somers /* send(2) should cause SIGPIPE on a shutdown socket */
874a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(shutdown_send_sigpipe);
875a8eb96d5SAlan Somers ATF_TC_BODY(shutdown_send_sigpipe, tc)
876a8eb96d5SAlan Somers {
8771f46c32cSGleb Smirnoff 	const struct sockaddr_un *sun;
8784446a47aSSergey Kandaurov 	const char *data = "data";
879fa5e5f53SEnji Cooper 	ssize_t datalen;
8804446a47aSSergey Kandaurov 	int s, err, s2;
881a8eb96d5SAlan Somers 
8821f46c32cSGleb Smirnoff 	sun = mk_listening_socket(&s);
8834446a47aSSergey Kandaurov 
8844446a47aSSergey Kandaurov 	/* Create the other socket */
8854446a47aSSergey Kandaurov 	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
8864446a47aSSergey Kandaurov 	ATF_REQUIRE(s2 >= 0);
8871f46c32cSGleb Smirnoff 	err = connect(s2, (struct sockaddr *)sun, sizeof(*sun));
8884446a47aSSergey Kandaurov 	if (err != 0) {
8894446a47aSSergey Kandaurov 		perror("connect");
8904446a47aSSergey Kandaurov 		atf_tc_fail("connect(2) failed");
8914446a47aSSergey Kandaurov 	}
8924446a47aSSergey Kandaurov 
8934446a47aSSergey Kandaurov 	ATF_CHECK_EQ(0, shutdown(s2, SHUT_RDWR));
894a8eb96d5SAlan Somers 	ATF_REQUIRE(SIG_ERR != signal(SIGPIPE, shutdown_send_sigpipe_handler));
895fa5e5f53SEnji Cooper 	datalen = strlen(data) + 1;	/* +1 for the null */
8966dd202ceSJohn Baldwin 	(void)send(s2, data, datalen, MSG_EOR);
897a8eb96d5SAlan Somers 	ATF_CHECK_EQ(1, got_sigpipe);
898e594026dSAlan Somers 	close(s);
8994446a47aSSergey Kandaurov 	close(s2);
900a8eb96d5SAlan Somers }
901a8eb96d5SAlan Somers 
902a8eb96d5SAlan Somers /* nonblocking send(2) and recv(2) a single short record */
903a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(send_recv_nonblocking);
904a8eb96d5SAlan Somers ATF_TC_BODY(send_recv_nonblocking, tc)
905a8eb96d5SAlan Somers {
906a8eb96d5SAlan Somers 	int sv[2];
907a8eb96d5SAlan Somers 	const int bufsize = 64;
908a8eb96d5SAlan Somers 	const char *data = "data";
909a8eb96d5SAlan Somers 	char recv_buf[bufsize];
9105d5b721aSAlan Somers 	ssize_t datalen;
911a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
912a8eb96d5SAlan Somers 
913a8eb96d5SAlan Somers 	/* setup the socket pair */
914a8eb96d5SAlan Somers 	do_socketpair_nonblocking(sv);
915a8eb96d5SAlan Somers 
916a8eb96d5SAlan Somers 	/* Verify that there is nothing to receive */
917a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
918a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EAGAIN, errno);
919a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, rsize);
920a8eb96d5SAlan Somers 
921a8eb96d5SAlan Somers 	/* send and receive a small packet */
922a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
923a8eb96d5SAlan Somers 	ssize = send(sv[0], data, datalen, MSG_EOR);
924a8eb96d5SAlan Somers 	if (ssize < 0) {
925a8eb96d5SAlan Somers 		perror("send");
926a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
927a8eb96d5SAlan Somers 	}
928a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
929a8eb96d5SAlan Somers 	    datalen, ssize);
930a8eb96d5SAlan Somers 
931a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
932a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
933e594026dSAlan Somers 	close(sv[0]);
934e594026dSAlan Somers 	close(sv[1]);
935a8eb96d5SAlan Somers }
936a8eb96d5SAlan Somers 
937a8eb96d5SAlan Somers /*
938a8eb96d5SAlan Somers  * We should get EAGAIN if we try to send a message larger than the socket
939a8eb96d5SAlan Somers  * buffer, with nonblocking sockets.  Test with several different sockbuf sizes
940a8eb96d5SAlan Somers  */
941a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_8k_8k);
942a8eb96d5SAlan Somers ATF_TC_BODY(eagain_8k_8k, tc)
943a8eb96d5SAlan Somers {
944a8eb96d5SAlan Somers 	test_eagain(8192, 8192);
945a8eb96d5SAlan Somers }
946a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_8k_128k);
947a8eb96d5SAlan Somers ATF_TC_BODY(eagain_8k_128k, tc)
948a8eb96d5SAlan Somers {
949a8eb96d5SAlan Somers 	test_eagain(8192, 131072);
950a8eb96d5SAlan Somers }
951a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_128k_8k);
952a8eb96d5SAlan Somers ATF_TC_BODY(eagain_128k_8k, tc)
953a8eb96d5SAlan Somers {
954a8eb96d5SAlan Somers 	test_eagain(131072, 8192);
955a8eb96d5SAlan Somers }
956a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_128k_128k);
957a8eb96d5SAlan Somers ATF_TC_BODY(eagain_128k_128k, tc)
958a8eb96d5SAlan Somers {
959a8eb96d5SAlan Somers 	test_eagain(131072, 131072);
960a8eb96d5SAlan Somers }
961a8eb96d5SAlan Somers 
962a8eb96d5SAlan Somers 
963a8eb96d5SAlan Somers /*
964a8eb96d5SAlan Somers  * nonblocking send(2) and recv(2) of several records, which should collectively
965a8eb96d5SAlan Somers  * fill up the send buffer but not the receive buffer
966a8eb96d5SAlan Somers  */
967a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(rcvbuf_oversized);
968a8eb96d5SAlan Somers ATF_TC_BODY(rcvbuf_oversized, tc)
969a8eb96d5SAlan Somers {
9705d5b721aSAlan Somers 	int i;
971a8eb96d5SAlan Somers 	int sv[2];
9723be7751dSJulio Merino 	const ssize_t pktsize = 1024;
973ea703329SBrooks Davis 	const int sndbufsize = 8192;
974ea703329SBrooks Davis 	const int rcvbufsize = 131072;
9755d5b721aSAlan Somers 	const size_t geometric_mean_bufsize = 32768;
9765d5b721aSAlan Somers 	const int numpkts = geometric_mean_bufsize / pktsize;
977a8eb96d5SAlan Somers 	char sndbuf[pktsize];
978a8eb96d5SAlan Somers 	char recv_buf[pktsize];
979a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
980a8eb96d5SAlan Somers 
981a8eb96d5SAlan Somers 	/* setup the socket pair */
982a8eb96d5SAlan Somers 	do_socketpair_nonblocking(sv);
9835d5b721aSAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
9845d5b721aSAlan Somers 	    sizeof(sndbufsize)));
9855d5b721aSAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
9865d5b721aSAlan Somers 	    sizeof(rcvbufsize)));
987a8eb96d5SAlan Somers 
988a8eb96d5SAlan Somers 	/*
989a8eb96d5SAlan Somers 	 * Send and receive packets that are collectively greater than the send
990a8eb96d5SAlan Somers 	 * buffer, but less than the receive buffer
991a8eb96d5SAlan Somers 	 */
9925d5b721aSAlan Somers 	for (i=0; i < numpkts; i++) {
993a8eb96d5SAlan Somers 		/* Fill the buffer */
994a8eb96d5SAlan Somers 		memset(sndbuf, i, pktsize);
995a8eb96d5SAlan Somers 
996a8eb96d5SAlan Somers 		/* send the packet */
997a8eb96d5SAlan Somers 		ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
998a8eb96d5SAlan Somers 		if (ssize < 0) {
999a8eb96d5SAlan Somers 			perror("send");
1000a8eb96d5SAlan Somers 			atf_tc_fail("send returned < 0");
1001a8eb96d5SAlan Somers 		}
1002a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(pktsize, ssize,
1003a8eb96d5SAlan Somers 		    "expected %zd=send(...) but got %zd", pktsize, ssize);
1004a8eb96d5SAlan Somers 
1005a8eb96d5SAlan Somers 		/* Receive it */
1006a8eb96d5SAlan Somers 
1007a8eb96d5SAlan Somers 		rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
1008a8eb96d5SAlan Somers 		if (rsize < 0) {
1009a8eb96d5SAlan Somers 			perror("recv");
1010a8eb96d5SAlan Somers 			atf_tc_fail("recv returned < 0");
1011a8eb96d5SAlan Somers 		}
1012a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(pktsize, rsize,
1013a8eb96d5SAlan Somers 		    "expected %zd=send(...) but got %zd", pktsize, rsize);
1014a8eb96d5SAlan Somers 
1015a8eb96d5SAlan Somers 		/* Verify the contents */
1016a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(0, memcmp(sndbuf, recv_buf, pktsize),
1017a8eb96d5SAlan Somers 		    "Received data miscompare");
1018a8eb96d5SAlan Somers 	}
1019a8eb96d5SAlan Somers 
1020a8eb96d5SAlan Somers 	/* Trying to receive again should return EAGAIN */
1021a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
1022a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EAGAIN, errno);
1023a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, rsize);
1024e594026dSAlan Somers 	close(sv[0]);
1025e594026dSAlan Somers 	close(sv[1]);
1026a8eb96d5SAlan Somers }
1027a8eb96d5SAlan Somers 
1028a8eb96d5SAlan Somers /*
1029a8eb96d5SAlan Somers  * Simulate the behavior of a blocking pipe.  The sender will send until his
1030a8eb96d5SAlan Somers  * buffer fills up, then we'll simulate a scheduler switch that will allow the
1031a8eb96d5SAlan Somers  * receiver to read until his buffer empties.  Repeat the process until the
1032a8eb96d5SAlan Somers  * transfer is complete.
1033a8eb96d5SAlan Somers  * Repeat the test with multiple send and receive buffer sizes
1034a8eb96d5SAlan Somers  */
1035a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_8k);
1036a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_8k_8k, tc)
1037a8eb96d5SAlan Somers {
1038a8eb96d5SAlan Somers 	test_pipe_simulator(8192, 8192);
1039a8eb96d5SAlan Somers }
1040a8eb96d5SAlan Somers 
1041a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_128k);
1042a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_8k_128k, tc)
1043a8eb96d5SAlan Somers {
1044a8eb96d5SAlan Somers 	test_pipe_simulator(8192, 131072);
1045a8eb96d5SAlan Somers }
1046a8eb96d5SAlan Somers 
1047a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_8k);
1048a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_128k_8k, tc)
1049a8eb96d5SAlan Somers {
1050a8eb96d5SAlan Somers 	test_pipe_simulator(131072, 8192);
1051a8eb96d5SAlan Somers }
1052a8eb96d5SAlan Somers 
1053a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_128k);
1054a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_128k_128k, tc)
1055a8eb96d5SAlan Somers {
1056a8eb96d5SAlan Somers 	test_pipe_simulator(131072, 131072);
1057a8eb96d5SAlan Somers }
1058a8eb96d5SAlan Somers 
1059a8eb96d5SAlan Somers /*
1060a8eb96d5SAlan Somers  * Test blocking I/O by passing data between two threads.  The total amount of
1061a8eb96d5SAlan Somers  * data will be >> buffer size to force blocking.  Repeat the test with multiple
1062a8eb96d5SAlan Somers  * send and receive buffer sizes
1063a8eb96d5SAlan Somers  */
1064a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_8k_8k);
1065a8eb96d5SAlan Somers ATF_TC_BODY(pipe_8k_8k, tc)
1066a8eb96d5SAlan Somers {
1067a8eb96d5SAlan Somers 	test_pipe(8192, 8192);
1068a8eb96d5SAlan Somers }
1069a8eb96d5SAlan Somers 
1070a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_8k_128k);
1071a8eb96d5SAlan Somers ATF_TC_BODY(pipe_8k_128k, tc)
1072a8eb96d5SAlan Somers {
1073a8eb96d5SAlan Somers 	test_pipe(8192, 131072);
1074a8eb96d5SAlan Somers }
1075a8eb96d5SAlan Somers 
1076a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_128k_8k);
1077a8eb96d5SAlan Somers ATF_TC_BODY(pipe_128k_8k, tc)
1078a8eb96d5SAlan Somers {
1079a8eb96d5SAlan Somers 	test_pipe(131072, 8192);
1080a8eb96d5SAlan Somers }
1081a8eb96d5SAlan Somers 
1082a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_128k_128k);
1083a8eb96d5SAlan Somers ATF_TC_BODY(pipe_128k_128k, tc)
1084a8eb96d5SAlan Somers {
1085a8eb96d5SAlan Somers 	test_pipe(131072, 131072);
1086a8eb96d5SAlan Somers }
1087a8eb96d5SAlan Somers 
1088a8eb96d5SAlan Somers 
1089a8eb96d5SAlan Somers /*
1090a8eb96d5SAlan Somers  * Test single-packet I/O with and without blocking, with symmetric buffers of
1091a8eb96d5SAlan Somers  * various sizes
1092a8eb96d5SAlan Somers  */
1093a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_8k);
1094a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_8k, tc)
1095a8eb96d5SAlan Somers {
1096a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(8 * 1024, true);
1097a8eb96d5SAlan Somers }
1098a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_16k);
1099a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_16k, tc)
1100a8eb96d5SAlan Somers {
1101a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(16 * 1024, true);
1102a8eb96d5SAlan Somers }
1103a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_32k);
1104a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_32k, tc)
1105a8eb96d5SAlan Somers {
1106a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(32 * 1024, true);
1107a8eb96d5SAlan Somers }
1108a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_64k);
1109a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_64k, tc)
1110a8eb96d5SAlan Somers {
1111a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(64 * 1024, true);
1112a8eb96d5SAlan Somers }
1113a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_128k);
1114a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_128k, tc)
1115a8eb96d5SAlan Somers {
1116a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(128 * 1024, true);
1117a8eb96d5SAlan Somers }
1118a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_8k_nonblocking);
1119a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_8k_nonblocking, tc)
1120a8eb96d5SAlan Somers {
1121a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(8 * 1024, false);
1122a8eb96d5SAlan Somers }
1123a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_16k_nonblocking);
1124a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_16k_nonblocking, tc)
1125a8eb96d5SAlan Somers {
1126a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(16 * 1024, false);
1127a8eb96d5SAlan Somers }
1128a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_32k_nonblocking);
1129a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_32k_nonblocking, tc)
1130a8eb96d5SAlan Somers {
1131a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(32 * 1024, false);
1132a8eb96d5SAlan Somers }
1133a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_64k_nonblocking);
1134a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_64k_nonblocking, tc)
1135a8eb96d5SAlan Somers {
1136a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(64 * 1024, false);
1137a8eb96d5SAlan Somers }
1138a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_128k_nonblocking);
1139a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_128k_nonblocking, tc)
1140a8eb96d5SAlan Somers {
1141a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(128 * 1024, false);
1142a8eb96d5SAlan Somers }
1143a8eb96d5SAlan Somers 
1144eb338e23SGleb Smirnoff ATF_TC(random_eor_and_waitall);
1145eb338e23SGleb Smirnoff ATF_TC_HEAD(random_eor_and_waitall, tc)
1146eb338e23SGleb Smirnoff {
1147eb338e23SGleb Smirnoff 	atf_tc_set_md_var(tc, "descr", "Test random sized send/recv with "
1148eb338e23SGleb Smirnoff 	    "randomly placed MSG_EOR and randomly applied MSG_WAITALL on "
1149eb338e23SGleb Smirnoff 	    "PF_UNIX/SOCK_SEQPACKET");
1150eb338e23SGleb Smirnoff }
1151eb338e23SGleb Smirnoff 
1152eb338e23SGleb Smirnoff struct random_eor_params {
1153eb338e23SGleb Smirnoff 	u_long recvspace;
1154eb338e23SGleb Smirnoff 	char *sendbuf;
1155eb338e23SGleb Smirnoff 	size_t *records;
1156eb338e23SGleb Smirnoff 	u_int nrecords;
1157eb338e23SGleb Smirnoff 	int sock;
1158eb338e23SGleb Smirnoff 	u_short seed[6];
1159eb338e23SGleb Smirnoff };
1160eb338e23SGleb Smirnoff 
1161eb338e23SGleb Smirnoff #define	RANDOM_TESTSIZE	((size_t)100 * 1024 * 1024)
1162eb338e23SGleb Smirnoff /* Below defines are factor of recvspace. */
1163eb338e23SGleb Smirnoff #define	RANDOM_MAXRECORD	10
1164eb338e23SGleb Smirnoff #define	RANDOM_SENDSIZE	2
1165eb338e23SGleb Smirnoff #define	RANDOM_RECVSIZE	4
1166eb338e23SGleb Smirnoff 
1167eb338e23SGleb Smirnoff static void *
1168eb338e23SGleb Smirnoff sending_thread(void *arg)
1169eb338e23SGleb Smirnoff {
1170eb338e23SGleb Smirnoff 	struct random_eor_params *params = arg;
1171eb338e23SGleb Smirnoff 	size_t off = 0;
1172eb338e23SGleb Smirnoff 	int eor = 0;
1173eb338e23SGleb Smirnoff 
1174eb338e23SGleb Smirnoff 	while (off < RANDOM_TESTSIZE) {
1175eb338e23SGleb Smirnoff 		ssize_t len;
1176eb338e23SGleb Smirnoff 		int flags;
1177eb338e23SGleb Smirnoff 
1178eb338e23SGleb Smirnoff 		len = nrand48(&params->seed[3]) %
1179eb338e23SGleb Smirnoff 		    (RANDOM_SENDSIZE * params->recvspace);
1180eb338e23SGleb Smirnoff 		if (off + len >= params->records[eor]) {
1181eb338e23SGleb Smirnoff 			len = params->records[eor] - off;
1182eb338e23SGleb Smirnoff 			flags = MSG_EOR;
1183eb338e23SGleb Smirnoff 			eor++;
1184eb338e23SGleb Smirnoff 		} else
1185eb338e23SGleb Smirnoff 			flags = 0;
1186eb338e23SGleb Smirnoff 		ATF_REQUIRE(send(params->sock, &params->sendbuf[off], len,
1187eb338e23SGleb Smirnoff 		    flags) == len);
1188eb338e23SGleb Smirnoff 		off += len;
1189eb338e23SGleb Smirnoff #ifdef DEBUG
1190eb338e23SGleb Smirnoff 		printf("send %zd%s\n", off, flags ? " EOR" : "");
1191eb338e23SGleb Smirnoff #endif
1192eb338e23SGleb Smirnoff 	}
1193eb338e23SGleb Smirnoff 
1194eb338e23SGleb Smirnoff 	return (NULL);
1195eb338e23SGleb Smirnoff }
1196eb338e23SGleb Smirnoff 
1197eb338e23SGleb Smirnoff ATF_TC_BODY(random_eor_and_waitall, tc)
1198eb338e23SGleb Smirnoff {
1199eb338e23SGleb Smirnoff 	struct random_eor_params params;
1200eb338e23SGleb Smirnoff 	void *recvbuf;
1201eb338e23SGleb Smirnoff 	pthread_t t;
1202eb338e23SGleb Smirnoff 	size_t off;
1203eb338e23SGleb Smirnoff 	int fd[2], eor;
1204eb338e23SGleb Smirnoff 
1205eb338e23SGleb Smirnoff 	arc4random_buf(params.seed, sizeof(params.seed));
1206eb338e23SGleb Smirnoff 	printf("Using seed:");
1207eb338e23SGleb Smirnoff 	for (u_int i = 0; i < (u_int)sizeof(params.seed)/sizeof(u_short); i++)
1208eb338e23SGleb Smirnoff 		printf(" 0x%.4x,", params.seed[i]);
1209eb338e23SGleb Smirnoff 	printf("\n");
1210eb338e23SGleb Smirnoff 
1211eb338e23SGleb Smirnoff 	ATF_REQUIRE((params.sendbuf = malloc(RANDOM_TESTSIZE)) != NULL);
1212eb338e23SGleb Smirnoff 	for (u_int i = 0; i < RANDOM_TESTSIZE / (u_int )sizeof(long); i++)
1213eb338e23SGleb Smirnoff 		((long *)params.sendbuf)[i] = nrand48(&params.seed[0]);
1214eb338e23SGleb Smirnoff 
1215eb338e23SGleb Smirnoff 	ATF_REQUIRE(sysctlbyname("net.local.stream.recvspace",
1216eb338e23SGleb Smirnoff 	    &params.recvspace, &(size_t){sizeof(u_long)}, NULL, 0) != -1);
1217eb338e23SGleb Smirnoff 	ATF_REQUIRE((recvbuf =
1218eb338e23SGleb Smirnoff 	    malloc(RANDOM_RECVSIZE * params.recvspace)) != NULL);
1219eb338e23SGleb Smirnoff 
1220eb338e23SGleb Smirnoff 	params.nrecords = 2 * RANDOM_TESTSIZE /
1221eb338e23SGleb Smirnoff 	    (RANDOM_MAXRECORD * params.recvspace);
1222eb338e23SGleb Smirnoff 
1223eb338e23SGleb Smirnoff 	ATF_REQUIRE((params.records =
1224eb338e23SGleb Smirnoff 	    malloc(params.nrecords * sizeof(size_t *))) != NULL);
1225eb338e23SGleb Smirnoff 	off = 0;
1226eb338e23SGleb Smirnoff 	for (u_int i = 0; i < params.nrecords; i++) {
1227eb338e23SGleb Smirnoff 		off += 1 + nrand48(&params.seed[0]) %
1228eb338e23SGleb Smirnoff 		    (RANDOM_MAXRECORD * params.recvspace);
1229eb338e23SGleb Smirnoff 		if (off > RANDOM_TESTSIZE) {
1230eb338e23SGleb Smirnoff 			params.nrecords = i;
1231eb338e23SGleb Smirnoff 			break;
1232eb338e23SGleb Smirnoff 		}
1233eb338e23SGleb Smirnoff 		params.records[i] = off;
1234eb338e23SGleb Smirnoff 	}
1235eb338e23SGleb Smirnoff 	params.records[params.nrecords - 1] = RANDOM_TESTSIZE;
1236eb338e23SGleb Smirnoff 
1237eb338e23SGleb Smirnoff 	ATF_REQUIRE(socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, fd) == 0);
1238eb338e23SGleb Smirnoff 	params.sock = fd[0];
1239eb338e23SGleb Smirnoff 	ATF_REQUIRE(pthread_create(&t, NULL, sending_thread, &params) == 0);
1240eb338e23SGleb Smirnoff 
1241eb338e23SGleb Smirnoff 	off = 0;
1242eb338e23SGleb Smirnoff 	eor = 0;
1243eb338e23SGleb Smirnoff 	while (off < RANDOM_TESTSIZE) {
1244eb338e23SGleb Smirnoff 		struct iovec iov = {
1245eb338e23SGleb Smirnoff 			.iov_base = recvbuf,
1246eb338e23SGleb Smirnoff 			.iov_len = nrand48(&params.seed[0]) %
1247eb338e23SGleb Smirnoff 			    (RANDOM_RECVSIZE * params.recvspace)
1248eb338e23SGleb Smirnoff 		};
1249eb338e23SGleb Smirnoff 		struct msghdr hdr = {
1250eb338e23SGleb Smirnoff 			.msg_iov = &iov,
1251eb338e23SGleb Smirnoff 			.msg_iovlen = 1,
1252eb338e23SGleb Smirnoff 		};
1253eb338e23SGleb Smirnoff 		size_t len;
1254eb338e23SGleb Smirnoff 		int waitall = iov.iov_len & 0x1 ? MSG_WAITALL : 0;
1255eb338e23SGleb Smirnoff 
1256eb338e23SGleb Smirnoff 		len = recvmsg(fd[1], &hdr, waitall);
1257eb338e23SGleb Smirnoff 		if (waitall && !(hdr.msg_flags & MSG_EOR))
1258eb338e23SGleb Smirnoff 			ATF_CHECK_EQ_MSG(len, iov.iov_len,
1259eb338e23SGleb Smirnoff 			    "recvmsg(MSG_WAITALL): %zd, expected %zd",
1260eb338e23SGleb Smirnoff 			    len, iov.iov_len);
1261eb338e23SGleb Smirnoff 		if (off + len == params.records[eor]) {
1262eb338e23SGleb Smirnoff 			ATF_REQUIRE_MSG(hdr.msg_flags & MSG_EOR,
1263eb338e23SGleb Smirnoff 			    "recvmsg(): expected EOR @ %zd", off + len);
1264eb338e23SGleb Smirnoff 			eor++;
1265eb338e23SGleb Smirnoff 		} else {
1266eb338e23SGleb Smirnoff 			ATF_REQUIRE_MSG(off + len < params.records[eor],
1267eb338e23SGleb Smirnoff 			    "recvmsg() past EOR: %zd, expected %zd",
1268eb338e23SGleb Smirnoff 			    off + len, params.records[eor]);
1269eb338e23SGleb Smirnoff 			ATF_REQUIRE_MSG(!(hdr.msg_flags & MSG_EOR),
1270eb338e23SGleb Smirnoff 			    "recvmsg() spurious EOR at %zd, expected %zd",
1271eb338e23SGleb Smirnoff 			    off + len, params.records[eor]);
1272eb338e23SGleb Smirnoff 		}
1273eb338e23SGleb Smirnoff 		ATF_REQUIRE_MSG(0 == memcmp(params.sendbuf + off, recvbuf, len),
1274eb338e23SGleb Smirnoff 		    "data corruption past %zd", off);
1275eb338e23SGleb Smirnoff 		off += len;
1276eb338e23SGleb Smirnoff #ifdef DEBUG
1277eb338e23SGleb Smirnoff 		printf("recv %zd%s %zd/%zd%s\n", off,
1278eb338e23SGleb Smirnoff 		    (hdr.msg_flags & MSG_EOR) ?  " EOR" : "",
1279eb338e23SGleb Smirnoff 		    len, iov.iov_len,
1280eb338e23SGleb Smirnoff 		    waitall ? " WAITALL" : "");
1281eb338e23SGleb Smirnoff #endif
1282eb338e23SGleb Smirnoff 	}
1283eb338e23SGleb Smirnoff 
1284eb338e23SGleb Smirnoff 	ATF_REQUIRE(pthread_join(t, NULL) == 0);
1285eb338e23SGleb Smirnoff 	free(params.sendbuf);
1286eb338e23SGleb Smirnoff 	free(recvbuf);
1287eb338e23SGleb Smirnoff 	free(params.records);
1288eb338e23SGleb Smirnoff }
1289a8eb96d5SAlan Somers 
1290a8eb96d5SAlan Somers /*
1291a8eb96d5SAlan Somers  * Main.
1292a8eb96d5SAlan Somers  */
1293a8eb96d5SAlan Somers 
1294a8eb96d5SAlan Somers ATF_TP_ADD_TCS(tp)
1295a8eb96d5SAlan Somers {
1296a8eb96d5SAlan Somers 	/* Basic creation and connection tests */
1297a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, create_socket);
1298a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, create_socketpair);
1299a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, listen_unbound);
1300a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, bind);
1301a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, listen_bound);
1302a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, connect);
1303a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, accept);
1304a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, fcntl_nonblock);
1305a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, resize_buffers);
1306a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, resize_connected_buffers);
1307a8eb96d5SAlan Somers 
1308a8eb96d5SAlan Somers 	/* Unthreaded I/O tests */
1309a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, send_recv);
1310a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, send_recv_nonblocking);
1311a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, send_recv_with_connect);
1312a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendto_recvfrom);
13133bc122d2SGleb Smirnoff 	ATF_TP_ADD_TC(tp, send_before_accept);
1314*f9927821SGleb Smirnoff 	ATF_TP_ADD_TC(tp, send_to_closed);
1315253d8a1fSGleb Smirnoff 	ATF_TP_ADD_TC(tp, implied_connect);
1316a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, shutdown_send);
1317a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, shutdown_send_sigpipe);
1318a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_8k_8k);
1319a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_8k_128k);
1320a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_128k_8k);
1321a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_128k_128k);
1322a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_8k);
1323a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_16k);
1324a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_32k);
1325a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_64k);
1326a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_128k);
1327a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_8k_nonblocking);
1328a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_16k_nonblocking);
1329a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_32k_nonblocking);
1330a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_64k_nonblocking);
1331a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_128k_nonblocking);
1332a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, rcvbuf_oversized);
1333a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_8k_8k);
1334a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_8k_128k);
1335a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_128k_8k);
1336a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_128k_128k);
1337a8eb96d5SAlan Somers 
1338a8eb96d5SAlan Somers 	/* Threaded I/O tests with blocking sockets */
1339a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_8k_8k);
1340a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_8k_128k);
1341a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_128k_8k);
1342a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_128k_128k);
1343eb338e23SGleb Smirnoff 	ATF_TP_ADD_TC(tp, random_eor_and_waitall);
1344a8eb96d5SAlan Somers 
1345a8eb96d5SAlan Somers 	return atf_no_error();
1346a8eb96d5SAlan Somers }
1347