1a8eb96d5SAlan Somers /*-
2a8eb96d5SAlan Somers  * Copyright (c) 2014 Spectra Logic Corporation. All rights reserved.
3a8eb96d5SAlan Somers  * Redistribution and use in source and binary forms, with or without
4a8eb96d5SAlan Somers  * modification, are permitted provided that the following conditions
5a8eb96d5SAlan Somers  * are met:
6a8eb96d5SAlan Somers  * 1. Redistributions of source code must retain the above copyright
7a8eb96d5SAlan Somers  *    notice, this list of conditions and the following disclaimer.
8a8eb96d5SAlan Somers  * 2. Redistributions in binary form must reproduce the above copyright
9a8eb96d5SAlan Somers  *    notice, this list of conditions and the following disclaimer in the
10a8eb96d5SAlan Somers  *    documentation and/or other materials provided with the distribution.
11a8eb96d5SAlan Somers  *
12a8eb96d5SAlan Somers  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13a8eb96d5SAlan Somers  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14a8eb96d5SAlan Somers  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15a8eb96d5SAlan Somers  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
16a8eb96d5SAlan Somers  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17a8eb96d5SAlan Somers  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18a8eb96d5SAlan Somers  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19a8eb96d5SAlan Somers  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20a8eb96d5SAlan Somers  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21a8eb96d5SAlan Somers  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22a8eb96d5SAlan Somers  * SUCH DAMAGE.
23a8eb96d5SAlan Somers  */
24a8eb96d5SAlan Somers 
25a8eb96d5SAlan Somers #include <sys/cdefs.h>
26a8eb96d5SAlan Somers __FBSDID("$FreeBSD$");
27a8eb96d5SAlan Somers 
28a8eb96d5SAlan Somers #include <errno.h>
29a8eb96d5SAlan Somers #include <fcntl.h>
30a8eb96d5SAlan Somers #include <pthread.h>
31a8eb96d5SAlan Somers #include <signal.h>
32a8eb96d5SAlan Somers #include <sys/socket.h>
33a8eb96d5SAlan Somers #include <sys/un.h>
34a8eb96d5SAlan Somers 
35a8eb96d5SAlan Somers #include <stdio.h>
36a8eb96d5SAlan Somers 
37a8eb96d5SAlan Somers #include <atf-c.h>
38a8eb96d5SAlan Somers 
39a8eb96d5SAlan Somers /*
40a8eb96d5SAlan Somers  * Helper functions
41a8eb96d5SAlan Somers  */
42a8eb96d5SAlan Somers 
43a8eb96d5SAlan Somers #define MIN(x, y)	((x) < (y) ? (x) : (y))
44a8eb96d5SAlan Somers #define MAX(x, y)	((x) > (y) ? (x) : (y))
45a8eb96d5SAlan Somers 
465d5b721aSAlan Somers static void
47a8eb96d5SAlan Somers do_socketpair(int *sv)
48a8eb96d5SAlan Somers {
49a8eb96d5SAlan Somers 	int s;
50a8eb96d5SAlan Somers 
51a8eb96d5SAlan Somers 	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
52a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, s);
53a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[0] >= 0);
54a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[1] >= 0);
55a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[0] != sv[1]);
56a8eb96d5SAlan Somers }
57a8eb96d5SAlan Somers 
585d5b721aSAlan Somers static void
59a8eb96d5SAlan Somers do_socketpair_nonblocking(int *sv)
60a8eb96d5SAlan Somers {
61a8eb96d5SAlan Somers 	int s;
62a8eb96d5SAlan Somers 
63a8eb96d5SAlan Somers 	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
64a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, s);
65a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[0] >= 0);
66a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[1] >= 0);
67a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[0] != sv[1]);
68a8eb96d5SAlan Somers 	ATF_REQUIRE(-1 != fcntl(sv[0], F_SETFL, O_NONBLOCK));
69a8eb96d5SAlan Somers 	ATF_REQUIRE(-1 != fcntl(sv[1], F_SETFL, O_NONBLOCK));
70a8eb96d5SAlan Somers }
71a8eb96d5SAlan Somers 
72a8eb96d5SAlan Somers /*
73a8eb96d5SAlan Somers  * Returns a pair of sockets made the hard way: bind, listen, connect & accept
74a8eb96d5SAlan Somers  * @return	const char* The path to the socket
75a8eb96d5SAlan Somers  */
765d5b721aSAlan Somers static const char*
77a8eb96d5SAlan Somers mk_pair_of_sockets(int *sv)
78a8eb96d5SAlan Somers {
79a8eb96d5SAlan Somers 	struct sockaddr_un sun;
80a8eb96d5SAlan Somers 	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
81a8eb96d5SAlan Somers 	const char *path = "sock";
82a8eb96d5SAlan Somers 	int s, err, s2, s1;
83a8eb96d5SAlan Somers 
84a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
85a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
86a8eb96d5SAlan Somers 
87a8eb96d5SAlan Somers 	bzero(&sun, sizeof(sun));
88a8eb96d5SAlan Somers 	sun.sun_family = AF_LOCAL;
89a8eb96d5SAlan Somers 	sun.sun_len = sizeof(sun);
90a8eb96d5SAlan Somers 	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
91a8eb96d5SAlan Somers 	err = bind(s, (struct sockaddr *)&sun, sizeof(sun));
92a8eb96d5SAlan Somers 	err = listen(s, -1);
93a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, err);
94a8eb96d5SAlan Somers 
95a8eb96d5SAlan Somers 	/* Create the other socket */
96a8eb96d5SAlan Somers 	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
97a8eb96d5SAlan Somers 	ATF_REQUIRE(s2 >= 0);
98a8eb96d5SAlan Somers 	err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
99a8eb96d5SAlan Somers 	if (err != 0) {
100a8eb96d5SAlan Somers 		perror("connect");
101a8eb96d5SAlan Somers 		atf_tc_fail("connect(2) failed");
102a8eb96d5SAlan Somers 	}
103a8eb96d5SAlan Somers 
104a8eb96d5SAlan Somers 	/* Accept it */
105a8eb96d5SAlan Somers 	s1 = accept(s, NULL, NULL);
106a8eb96d5SAlan Somers 	if (s1 == -1) {
107a8eb96d5SAlan Somers 		perror("accept");
108a8eb96d5SAlan Somers 		atf_tc_fail("accept(2) failed");
109a8eb96d5SAlan Somers 	}
110a8eb96d5SAlan Somers 
111a8eb96d5SAlan Somers 	sv[0] = s1;
112a8eb96d5SAlan Somers 	sv[1] = s2;
113e594026dSAlan Somers 
114e594026dSAlan Somers 	close(s);
115e594026dSAlan Somers 
116a8eb96d5SAlan Somers 	return (path);
117a8eb96d5SAlan Somers }
118a8eb96d5SAlan Somers 
119a8eb96d5SAlan Somers static volatile sig_atomic_t got_sigpipe = 0;
120a8eb96d5SAlan Somers static void
1215d5b721aSAlan Somers shutdown_send_sigpipe_handler(int __unused x)
122a8eb96d5SAlan Somers {
123a8eb96d5SAlan Somers 	got_sigpipe = 1;
124a8eb96d5SAlan Somers }
125a8eb96d5SAlan Somers 
126a8eb96d5SAlan Somers /*
127a8eb96d5SAlan Somers  * Parameterized test function bodies
128a8eb96d5SAlan Somers  */
1295d5b721aSAlan Somers static void
130a8eb96d5SAlan Somers test_eagain(size_t sndbufsize, size_t rcvbufsize)
131a8eb96d5SAlan Somers {
132a8eb96d5SAlan Somers 	int i;
133a8eb96d5SAlan Somers 	int sv[2];
134a8eb96d5SAlan Somers 	const size_t totalsize = (sndbufsize + rcvbufsize) * 2;
135a8eb96d5SAlan Somers 	const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
1365d5b721aSAlan Somers 	const int numpkts = totalsize / pktsize;
137a8eb96d5SAlan Somers 	char sndbuf[pktsize];
1385d5b721aSAlan Somers 	ssize_t ssize;
139a8eb96d5SAlan Somers 
140a8eb96d5SAlan Somers 	/* setup the socket pair */
141b9a9db10SAlan Somers 	do_socketpair_nonblocking(sv);
142a8eb96d5SAlan Somers 	/* Setup the buffers */
143a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
144a8eb96d5SAlan Somers 	    sizeof(sndbufsize)));
145a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
146a8eb96d5SAlan Somers 	    sizeof(rcvbufsize)));
147a8eb96d5SAlan Somers 
148a8eb96d5SAlan Somers 	bzero(sndbuf, pktsize);
149a8eb96d5SAlan Somers 	/* Send data until we get EAGAIN */
1505d5b721aSAlan Somers 	for(i=0; i < numpkts; i++) {
151a8eb96d5SAlan Somers 		ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
152a8eb96d5SAlan Somers 		if (ssize == -1) {
153e594026dSAlan Somers 			if (errno == EAGAIN) {
154e594026dSAlan Somers 				close(sv[0]);
155e594026dSAlan Somers 				close(sv[1]);
156a8eb96d5SAlan Somers 				atf_tc_pass();
157e594026dSAlan Somers 			}
158a8eb96d5SAlan Somers 			else {
159a8eb96d5SAlan Somers 				perror("send");
160a8eb96d5SAlan Somers 				atf_tc_fail("send returned < 0 but not EAGAIN");
161a8eb96d5SAlan Somers 			}
162a8eb96d5SAlan Somers 		}
163a8eb96d5SAlan Somers 	}
164a8eb96d5SAlan Somers 	atf_tc_fail("Never got EAGAIN");
165a8eb96d5SAlan Somers }
166a8eb96d5SAlan Somers 
1675d5b721aSAlan Somers static void
168a8eb96d5SAlan Somers test_sendrecv_symmetric_buffers(size_t bufsize, int blocking) {
169a8eb96d5SAlan Somers 	int s;
170a8eb96d5SAlan Somers 	int sv[2];
1715d5b721aSAlan Somers 	const ssize_t pktsize = bufsize / 2;
172a8eb96d5SAlan Somers 	char sndbuf[pktsize];
173a8eb96d5SAlan Somers 	char recv_buf[pktsize];
174a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
175a8eb96d5SAlan Somers 
176a8eb96d5SAlan Somers 	/* setup the socket pair */
177a8eb96d5SAlan Somers 	if (blocking)
178a8eb96d5SAlan Somers 		do_socketpair(sv);
179a8eb96d5SAlan Somers 	else
180a8eb96d5SAlan Somers 		do_socketpair_nonblocking(sv);
181a8eb96d5SAlan Somers 
182a8eb96d5SAlan Somers 	/* Setup the buffers */
183a8eb96d5SAlan Somers 	s = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
184a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, s);
185a8eb96d5SAlan Somers 	s = setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
186a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, s);
187a8eb96d5SAlan Somers 
188a8eb96d5SAlan Somers 	/* Fill the send buffer */
189a8eb96d5SAlan Somers 	bzero(sndbuf, pktsize);
190a8eb96d5SAlan Somers 
191a8eb96d5SAlan Somers 	/* send and receive the packet */
192a8eb96d5SAlan Somers 	ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
193a8eb96d5SAlan Somers 	if (ssize < 0) {
194a8eb96d5SAlan Somers 		perror("send");
195a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
196a8eb96d5SAlan Somers 	}
197a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(pktsize, ssize, "expected %zd=send(...) but got %zd",
198a8eb96d5SAlan Somers 	    pktsize, ssize);
199a8eb96d5SAlan Somers 
200a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
201a8eb96d5SAlan Somers 	if (rsize < 0) {
202a8eb96d5SAlan Somers 		perror("recv");
203a8eb96d5SAlan Somers 		atf_tc_fail("recv returned < 0");
204a8eb96d5SAlan Somers 	}
205a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(pktsize, rsize, "expected %zd=send(...) but got %zd",
206a8eb96d5SAlan Somers 	    pktsize, rsize);
207e594026dSAlan Somers 	close(sv[0]);
208e594026dSAlan Somers 	close(sv[1]);
209a8eb96d5SAlan Somers }
210a8eb96d5SAlan Somers 
2115d5b721aSAlan Somers static void
212a8eb96d5SAlan Somers test_pipe_simulator(size_t sndbufsize, size_t rcvbufsize)
213a8eb96d5SAlan Somers {
2145d5b721aSAlan Somers 	int num_sent, num_received;
215a8eb96d5SAlan Somers 	int sv[2];
2165d5b721aSAlan Somers 	const ssize_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
217a8eb96d5SAlan Somers 	int numpkts;
218a8eb96d5SAlan Somers 	char sndbuf[pktsize];
219a8eb96d5SAlan Somers 	char rcvbuf[pktsize];
220a8eb96d5SAlan Somers 	char comparebuf[pktsize];
221a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
222a8eb96d5SAlan Somers 	bool currently_sending = true;
223a8eb96d5SAlan Somers 
224a8eb96d5SAlan Somers 	/* setup the socket pair */
225a8eb96d5SAlan Somers 	do_socketpair_nonblocking(sv);
226a8eb96d5SAlan Somers 	/* Setup the buffers */
227a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
228a8eb96d5SAlan Somers 	    sizeof(sndbufsize)));
229a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
230a8eb96d5SAlan Somers 	    sizeof(rcvbufsize)));
231a8eb96d5SAlan Somers 
232a8eb96d5SAlan Somers 	/* Send a total amount of data comfortably greater than the buffers */
233a8eb96d5SAlan Somers 	numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
234a8eb96d5SAlan Somers 	for (num_sent=0, num_received=0;
235a8eb96d5SAlan Somers 	     num_sent < numpkts || num_received < numpkts; ) {
236a8eb96d5SAlan Somers 		if (currently_sending && num_sent < numpkts) {
237a8eb96d5SAlan Somers 			/* The simulated sending process */
238a8eb96d5SAlan Somers 			/* fill the buffer */
239a8eb96d5SAlan Somers 			memset(sndbuf, num_sent, pktsize);
240a8eb96d5SAlan Somers 			ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
241a8eb96d5SAlan Somers 			if (ssize < 0) {
242a8eb96d5SAlan Somers 				/*
243a8eb96d5SAlan Somers 				 * XXX: This is bug-compatible with the kernel.
244a8eb96d5SAlan Somers 				 * The kernel returns EMSGSIZE when it should
245a8eb96d5SAlan Somers 				 * return EAGAIN
246a8eb96d5SAlan Somers 				 */
247a8eb96d5SAlan Somers 				if (errno == EAGAIN || errno == EMSGSIZE)
248a8eb96d5SAlan Somers 					currently_sending = false;
249a8eb96d5SAlan Somers 				else {
250a8eb96d5SAlan Somers 					perror("send");
251a8eb96d5SAlan Somers 					atf_tc_fail("send failed");
252a8eb96d5SAlan Somers 				}
253a8eb96d5SAlan Somers 			} else  {
254a8eb96d5SAlan Somers 				ATF_CHECK_EQ_MSG(pktsize, ssize,
255a8eb96d5SAlan Somers 				    "expected %zd=send(...) but got %zd",
256a8eb96d5SAlan Somers 				    pktsize, ssize);
257a8eb96d5SAlan Somers 				num_sent++;
258a8eb96d5SAlan Somers 			}
259a8eb96d5SAlan Somers 		} else {
260a8eb96d5SAlan Somers 			/* The simulated receiving process */
261a8eb96d5SAlan Somers 			rsize = recv(sv[1], rcvbuf, pktsize, MSG_WAITALL);
262a8eb96d5SAlan Somers 			if (rsize < 0) {
263a8eb96d5SAlan Somers 				if (errno == EAGAIN) {
264a8eb96d5SAlan Somers 					currently_sending = true;
265a8eb96d5SAlan Somers 					ATF_REQUIRE_MSG(num_sent < numpkts,
266a8eb96d5SAlan Somers 					    "Packets were lost!");
267a8eb96d5SAlan Somers 				}
268a8eb96d5SAlan Somers 				else {
269a8eb96d5SAlan Somers 					perror("recv");
270a8eb96d5SAlan Somers 					atf_tc_fail("recv failed");
271a8eb96d5SAlan Somers 				}
272a8eb96d5SAlan Somers 			} else  {
273a8eb96d5SAlan Somers 				ATF_CHECK_EQ_MSG(pktsize, rsize,
274a8eb96d5SAlan Somers 				    "expected %zd=recv(...) but got %zd",
275a8eb96d5SAlan Somers 				    pktsize, rsize);
276a8eb96d5SAlan Somers 				memset(comparebuf, num_received, pktsize);
277a8eb96d5SAlan Somers 				ATF_CHECK_EQ_MSG(0, memcmp(comparebuf, rcvbuf,
278a8eb96d5SAlan Somers 				    			   pktsize),
279a8eb96d5SAlan Somers 				    "Received data miscompare");
280a8eb96d5SAlan Somers 				num_received++;
281a8eb96d5SAlan Somers 			}
282a8eb96d5SAlan Somers 		}
283a8eb96d5SAlan Somers 	}
284e594026dSAlan Somers 	close(sv[0]);
285e594026dSAlan Somers 	close(sv[1]);
286a8eb96d5SAlan Somers }
287a8eb96d5SAlan Somers 
288a8eb96d5SAlan Somers typedef struct {
289a8eb96d5SAlan Somers 	ssize_t	pktsize;
290a8eb96d5SAlan Somers 	int	numpkts;
291a8eb96d5SAlan Somers 	int	so;
292a8eb96d5SAlan Somers } test_pipe_thread_data_t;
293a8eb96d5SAlan Somers 
294a8eb96d5SAlan Somers static void*
295a8eb96d5SAlan Somers test_pipe_writer(void* args)
296a8eb96d5SAlan Somers {
297a8eb96d5SAlan Somers 	test_pipe_thread_data_t* td = args;
298a8eb96d5SAlan Somers 	char sndbuf[td->pktsize];
299a8eb96d5SAlan Somers 	ssize_t ssize;
300a8eb96d5SAlan Somers 	int i;
301a8eb96d5SAlan Somers 
302a8eb96d5SAlan Somers 	for(i=0; i < td->numpkts; i++) {
303a8eb96d5SAlan Somers 			memset(sndbuf, i, td->pktsize);
304a8eb96d5SAlan Somers 			ssize = send(td->so, sndbuf, td->pktsize, MSG_EOR);
305a8eb96d5SAlan Somers 			if (ssize < 0) {
306a8eb96d5SAlan Somers 				perror("send");
307a8eb96d5SAlan Somers 				atf_tc_fail("send returned < 0");
308a8eb96d5SAlan Somers 			}
309a8eb96d5SAlan Somers 			ATF_CHECK_EQ_MSG(td->pktsize, ssize,
310a8eb96d5SAlan Somers 			    		 "expected %zd=send(...) but got %zd",
311a8eb96d5SAlan Somers 			    		  td->pktsize, ssize);
312a8eb96d5SAlan Somers 	}
313a8eb96d5SAlan Somers 	return (0);
314a8eb96d5SAlan Somers }
315a8eb96d5SAlan Somers 
316a8eb96d5SAlan Somers static void*
317a8eb96d5SAlan Somers test_pipe_reader(void* args)
318a8eb96d5SAlan Somers {
319a8eb96d5SAlan Somers 	test_pipe_thread_data_t* td = args;
320a8eb96d5SAlan Somers 	char rcvbuf[td->pktsize];
321a8eb96d5SAlan Somers 	char comparebuf[td->pktsize];
322a8eb96d5SAlan Somers 	ssize_t rsize;
323a8eb96d5SAlan Somers 	int i, d;
324a8eb96d5SAlan Somers 
325a8eb96d5SAlan Somers 	for(i=0; i < td->numpkts; i++) {
326a8eb96d5SAlan Somers 		memset(comparebuf, i, td->pktsize);
327a8eb96d5SAlan Somers 		rsize = recv(td->so, rcvbuf, td->pktsize, MSG_WAITALL);
328a8eb96d5SAlan Somers 		if (rsize < 0) {
329a8eb96d5SAlan Somers 			perror("recv");
330a8eb96d5SAlan Somers 			atf_tc_fail("recv returned < 0");
331a8eb96d5SAlan Somers 		}
332a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(td->pktsize, rsize,
333a8eb96d5SAlan Somers 		    		 "expected %zd=send(...) but got %zd",
334a8eb96d5SAlan Somers 				 td->pktsize, rsize);
335a8eb96d5SAlan Somers 		d = memcmp(comparebuf, rcvbuf, td->pktsize);
336a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(0, d,
337a8eb96d5SAlan Somers 		    		 "Received data miscompare on packet %d", i);
338a8eb96d5SAlan Somers 	}
339a8eb96d5SAlan Somers 	return (0);
340a8eb96d5SAlan Somers }
341a8eb96d5SAlan Somers 
342a8eb96d5SAlan Somers 
3435d5b721aSAlan Somers static void
344a8eb96d5SAlan Somers test_pipe(size_t sndbufsize, size_t rcvbufsize)
345a8eb96d5SAlan Somers {
346a8eb96d5SAlan Somers 	test_pipe_thread_data_t writer_data, reader_data;
347a8eb96d5SAlan Somers 	pthread_t writer, reader;
348a8eb96d5SAlan Somers 	int sv[2];
349a8eb96d5SAlan Somers 	const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
350a8eb96d5SAlan Somers 	int numpkts;
351a8eb96d5SAlan Somers 
352a8eb96d5SAlan Somers 	/* setup the socket pair */
353a8eb96d5SAlan Somers 	do_socketpair(sv);
354a8eb96d5SAlan Somers 	/* Setup the buffers */
355a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
356a8eb96d5SAlan Somers 	    sizeof(sndbufsize)));
357a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
358a8eb96d5SAlan Somers 	    sizeof(rcvbufsize)));
359a8eb96d5SAlan Somers 
360a8eb96d5SAlan Somers 	/* Send a total amount of data comfortably greater than the buffers */
361a8eb96d5SAlan Somers 	numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
362a8eb96d5SAlan Somers 
363a8eb96d5SAlan Somers 	/* Start the child threads */
364a8eb96d5SAlan Somers 	writer_data.pktsize = pktsize;
365a8eb96d5SAlan Somers 	writer_data.numpkts = numpkts;
366a8eb96d5SAlan Somers 	writer_data.so = sv[0];
367a8eb96d5SAlan Somers 	reader_data.pktsize = pktsize;
368a8eb96d5SAlan Somers 	reader_data.numpkts = numpkts;
369a8eb96d5SAlan Somers 	reader_data.so = sv[1];
370a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, pthread_create(&writer, NULL, test_pipe_writer,
371a8eb96d5SAlan Somers 	    				 (void*)&writer_data));
3728de34a88SAlan Somers 	/*
3738de34a88SAlan Somers 	 * Give the writer time to start writing, and hopefully block, before
3748de34a88SAlan Somers 	 * starting the reader.  This increases the likelihood of the test case
3758de34a88SAlan Somers 	 * failing due to PR kern/185812
3768de34a88SAlan Somers 	 */
3778de34a88SAlan Somers 	usleep(1000);
378a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, pthread_create(&reader, NULL, test_pipe_reader,
379a8eb96d5SAlan Somers 	    				 (void*)&reader_data));
380a8eb96d5SAlan Somers 
381a8eb96d5SAlan Somers 	/* Join the children */
382a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, pthread_join(writer, NULL));
383a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, pthread_join(reader, NULL));
384e594026dSAlan Somers 	close(sv[0]);
385e594026dSAlan Somers 	close(sv[1]);
386a8eb96d5SAlan Somers }
387a8eb96d5SAlan Somers 
388a8eb96d5SAlan Somers 
389a8eb96d5SAlan Somers /*
390a8eb96d5SAlan Somers  * Test Cases
391a8eb96d5SAlan Somers  */
392a8eb96d5SAlan Somers 
393a8eb96d5SAlan Somers /* Create a SEQPACKET socket */
394a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(create_socket);
395a8eb96d5SAlan Somers ATF_TC_BODY(create_socket, tc)
396a8eb96d5SAlan Somers {
397a8eb96d5SAlan Somers 	int s;
398a8eb96d5SAlan Somers 
399a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
4006addc01eSAlan Somers 	ATF_REQUIRE(s >= 0);
401e594026dSAlan Somers 	close(s);
402a8eb96d5SAlan Somers }
403a8eb96d5SAlan Somers 
404a8eb96d5SAlan Somers /* Create SEQPACKET sockets using socketpair(2) */
405a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(create_socketpair);
406a8eb96d5SAlan Somers ATF_TC_BODY(create_socketpair, tc)
407a8eb96d5SAlan Somers {
408a8eb96d5SAlan Somers 	int sv[2];
409a8eb96d5SAlan Somers 	int s;
410a8eb96d5SAlan Somers 
411a8eb96d5SAlan Somers 	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
412a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, s);
413a8eb96d5SAlan Somers 	ATF_CHECK(sv[0] >= 0);
414a8eb96d5SAlan Somers 	ATF_CHECK(sv[1] >= 0);
415a8eb96d5SAlan Somers 	ATF_CHECK(sv[0] != sv[1]);
416e594026dSAlan Somers 	close(sv[0]);
417e594026dSAlan Somers 	close(sv[1]);
418a8eb96d5SAlan Somers }
419a8eb96d5SAlan Somers 
420a8eb96d5SAlan Somers /* Call listen(2) without first calling bind(2).  It should fail */
421a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(listen_unbound);
422a8eb96d5SAlan Somers ATF_TC_BODY(listen_unbound, tc)
423a8eb96d5SAlan Somers {
424a8eb96d5SAlan Somers 	int s, r;
425a8eb96d5SAlan Somers 
426a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
427a8eb96d5SAlan Somers 	ATF_REQUIRE(s > 0);
428a8eb96d5SAlan Somers 	r = listen(s, -1);
429a8eb96d5SAlan Somers 	/* expect listen to fail since we haven't called bind(2) */
430a8eb96d5SAlan Somers 	ATF_CHECK(r != 0);
431e594026dSAlan Somers 	close(s);
432a8eb96d5SAlan Somers }
433a8eb96d5SAlan Somers 
434a8eb96d5SAlan Somers /* Bind the socket to a file */
435a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(bind);
436a8eb96d5SAlan Somers ATF_TC_BODY(bind, tc)
437a8eb96d5SAlan Somers {
438a8eb96d5SAlan Somers 	struct sockaddr_un sun;
439a8eb96d5SAlan Somers 	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
440a8eb96d5SAlan Somers 	const char *path = "sock";
441a8eb96d5SAlan Somers 	int s, r;
442a8eb96d5SAlan Somers 
443a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
444a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
445a8eb96d5SAlan Somers 
446a8eb96d5SAlan Somers 	bzero(&sun, sizeof(sun));
447a8eb96d5SAlan Somers 	sun.sun_family = AF_LOCAL;
448a8eb96d5SAlan Somers 	sun.sun_len = sizeof(sun);
449a8eb96d5SAlan Somers 	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
450a8eb96d5SAlan Somers 	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
451a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, r);
452e594026dSAlan Somers 	close(s);
453a8eb96d5SAlan Somers }
454a8eb96d5SAlan Somers 
455a8eb96d5SAlan Somers /* listen(2) a socket that is already bound(2) should succeed */
456a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(listen_bound);
457a8eb96d5SAlan Somers ATF_TC_BODY(listen_bound, 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, l;
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 	l = listen(s, -1);
473a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, r);
474a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, l);
475e594026dSAlan Somers 	close(s);
476a8eb96d5SAlan Somers }
477a8eb96d5SAlan Somers 
478a8eb96d5SAlan Somers /* connect(2) can make a connection */
479a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(connect);
480a8eb96d5SAlan Somers ATF_TC_BODY(connect, tc)
481a8eb96d5SAlan Somers {
482a8eb96d5SAlan Somers 	struct sockaddr_un sun;
483a8eb96d5SAlan Somers 	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
484a8eb96d5SAlan Somers 	const char *path = "sock";
485a8eb96d5SAlan Somers 	int s, r, err, l, s2;
486a8eb96d5SAlan Somers 
487a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
488a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
489a8eb96d5SAlan Somers 
490a8eb96d5SAlan Somers 	bzero(&sun, sizeof(sun));
491a8eb96d5SAlan Somers 	sun.sun_family = AF_LOCAL;
492a8eb96d5SAlan Somers 	sun.sun_len = sizeof(sun);
493a8eb96d5SAlan Somers 	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
494a8eb96d5SAlan Somers 	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
495a8eb96d5SAlan Somers 	l = listen(s, -1);
496a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, r);
497a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, l);
498a8eb96d5SAlan Somers 
499a8eb96d5SAlan Somers 	/* Create the other socket */
500a8eb96d5SAlan Somers 	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
501a8eb96d5SAlan Somers 	ATF_REQUIRE(s2 >= 0);
502a8eb96d5SAlan Somers 	err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
503a8eb96d5SAlan Somers 	if (err != 0) {
504a8eb96d5SAlan Somers 		perror("connect");
505a8eb96d5SAlan Somers 		atf_tc_fail("connect(2) failed");
506a8eb96d5SAlan Somers 	}
507e594026dSAlan Somers 	close(s);
508e594026dSAlan Somers 	close(s2);
509a8eb96d5SAlan Somers }
510a8eb96d5SAlan Somers 
511a8eb96d5SAlan Somers /* accept(2) can receive a connection */
512a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(accept);
513a8eb96d5SAlan Somers ATF_TC_BODY(accept, tc)
514a8eb96d5SAlan Somers {
515a8eb96d5SAlan Somers 	int sv[2];
516a8eb96d5SAlan Somers 
517a8eb96d5SAlan Somers 	mk_pair_of_sockets(sv);
518e594026dSAlan Somers 	close(sv[0]);
519e594026dSAlan Somers 	close(sv[1]);
520a8eb96d5SAlan Somers }
521a8eb96d5SAlan Somers 
522a8eb96d5SAlan Somers 
523a8eb96d5SAlan Somers /* Set O_NONBLOCK on the socket */
524a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(fcntl_nonblock);
525a8eb96d5SAlan Somers ATF_TC_BODY(fcntl_nonblock, tc)
526a8eb96d5SAlan Somers {
527a8eb96d5SAlan Somers 	int s;
528a8eb96d5SAlan Somers 
529a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
530a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
531a8eb96d5SAlan Somers 	if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
532a8eb96d5SAlan Somers 		perror("fcntl");
533a8eb96d5SAlan Somers 		atf_tc_fail("fcntl failed");
534a8eb96d5SAlan Somers 	}
535e594026dSAlan Somers 	close(s);
536a8eb96d5SAlan Somers }
537a8eb96d5SAlan Somers 
538a8eb96d5SAlan Somers /* Resize the send and receive buffers */
539a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(resize_buffers);
540a8eb96d5SAlan Somers ATF_TC_BODY(resize_buffers, tc)
541a8eb96d5SAlan Somers {
542a8eb96d5SAlan Somers 	int s;
543a8eb96d5SAlan Somers 	int sndbuf = 12345;
544a8eb96d5SAlan Somers 	int rcvbuf = 23456;
545a8eb96d5SAlan Somers 	int xs, xr;
546a8eb96d5SAlan Somers 	socklen_t sl = sizeof(xs);
547a8eb96d5SAlan Somers 
548a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
549a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
550a8eb96d5SAlan Somers 
551a8eb96d5SAlan Somers 	printf("                       Socket Buffer Sizes\n");
552a8eb96d5SAlan Somers 	printf("                              | SNDBUF  | RCVBUF  |\n");
553a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
554a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
555a8eb96d5SAlan Somers 	printf("Default                       | %7d | %7d |\n", xs, xr);
556a8eb96d5SAlan Somers 
557a8eb96d5SAlan Somers 	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) != 0){
558a8eb96d5SAlan Somers 		perror("setsockopt");
559a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_SNDBUF) failed");
560a8eb96d5SAlan Somers 	}
561a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
562a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
563a8eb96d5SAlan Somers 	printf("After changing SNDBUF         | %7d | %7d |\n", xs, xr);
564a8eb96d5SAlan Somers 
565a8eb96d5SAlan Somers 	if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) != 0){
566a8eb96d5SAlan Somers 		perror("setsockopt");
567a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_RCVBUF) failed");
568a8eb96d5SAlan Somers 	}
569a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
570a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
571a8eb96d5SAlan Somers 	printf("After changing RCVBUF         | %7d | %7d |\n", xs, xr);
572e594026dSAlan Somers 	close(s);
573a8eb96d5SAlan Somers }
574a8eb96d5SAlan Somers 
575a8eb96d5SAlan Somers /*
576a8eb96d5SAlan Somers  * Resize the send and receive buffers of a connected socketpair
577a8eb96d5SAlan Somers  * Print some useful debugging info too
578a8eb96d5SAlan Somers  */
579a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(resize_connected_buffers);
580a8eb96d5SAlan Somers ATF_TC_BODY(resize_connected_buffers, tc)
581a8eb96d5SAlan Somers {
582a8eb96d5SAlan Somers 	int sv[2];
583a8eb96d5SAlan Somers 	int sndbuf = 12345;
584a8eb96d5SAlan Somers 	int rcvbuf = 23456;
585a8eb96d5SAlan Somers 	int err;
586a8eb96d5SAlan Somers 	int ls, lr, rs, rr;
587a8eb96d5SAlan Somers 	socklen_t sl = sizeof(ls);
588a8eb96d5SAlan Somers 
589a8eb96d5SAlan Somers 	/* setup the socket pair */
590a8eb96d5SAlan Somers 	do_socketpair(sv);
591a8eb96d5SAlan Somers 
592a8eb96d5SAlan Somers 	printf("                       Socket Buffer Sizes\n");
593a8eb96d5SAlan Somers 	printf("                              | Left Socket       | Right Socket      |\n");
594a8eb96d5SAlan Somers 	printf("                              | SNDBUF  | RCVBUF  | SNDBUF  | RCVBUF  |\n");
595a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
596a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
597a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
598a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
599a8eb96d5SAlan Somers 	printf("Default                       | %7d | %7d | %7d | %7d |\n",
600a8eb96d5SAlan Somers 	    ls, lr, rs, rr);
601a8eb96d5SAlan Somers 
602a8eb96d5SAlan Somers 	/* Update one side's send buffer */
603a8eb96d5SAlan Somers 	err = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
604a8eb96d5SAlan Somers 	if (err != 0){
605a8eb96d5SAlan Somers 		perror("setsockopt");
606a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_SNDBUF) failed");
607a8eb96d5SAlan Somers 	}
608a8eb96d5SAlan Somers 
609a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
610a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
611a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
612a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
613a8eb96d5SAlan Somers 	printf("After changing Left's SNDBUF  | %7d | %7d | %7d | %7d |\n",
614a8eb96d5SAlan Somers 	    ls, lr, rs, rr);
615a8eb96d5SAlan Somers 
616a8eb96d5SAlan Somers 	/* Update the same side's receive buffer */
617a8eb96d5SAlan Somers 	err = setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
618a8eb96d5SAlan Somers 	if (err != 0){
619a8eb96d5SAlan Somers 		perror("setsockopt");
620a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_RCVBUF) failed");
621a8eb96d5SAlan Somers 	}
622a8eb96d5SAlan Somers 
623a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
624a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
625a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
626a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
627a8eb96d5SAlan Somers 	printf("After changing Left's RCVBUF  | %7d | %7d | %7d | %7d |\n",
628a8eb96d5SAlan Somers 	    ls, lr, rs, rr);
629e594026dSAlan Somers 	close(sv[0]);
630e594026dSAlan Somers 	close(sv[1]);
631a8eb96d5SAlan Somers }
632a8eb96d5SAlan Somers 
633a8eb96d5SAlan Somers 
634a8eb96d5SAlan Somers /* send(2) and recv(2) a single short record */
635a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(send_recv);
636a8eb96d5SAlan Somers ATF_TC_BODY(send_recv, tc)
637a8eb96d5SAlan Somers {
638a8eb96d5SAlan Somers 	int sv[2];
639a8eb96d5SAlan Somers 	const int bufsize = 64;
640a8eb96d5SAlan Somers 	const char *data = "data";
641a8eb96d5SAlan Somers 	char recv_buf[bufsize];
6425d5b721aSAlan Somers 	ssize_t datalen;
643a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
644a8eb96d5SAlan Somers 
645a8eb96d5SAlan Somers 	/* setup the socket pair */
646a8eb96d5SAlan Somers 	do_socketpair(sv);
647a8eb96d5SAlan Somers 
648a8eb96d5SAlan Somers 	/* send and receive a small packet */
649a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
650a8eb96d5SAlan Somers 	ssize = send(sv[0], data, datalen, MSG_EOR);
651a8eb96d5SAlan Somers 	if (ssize < 0) {
652a8eb96d5SAlan Somers 		perror("send");
653a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
654a8eb96d5SAlan Somers 	}
655a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
656a8eb96d5SAlan Somers 	    datalen, ssize);
657a8eb96d5SAlan Somers 
658a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
659a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
660e594026dSAlan Somers 	close(sv[0]);
661e594026dSAlan Somers 	close(sv[1]);
662a8eb96d5SAlan Somers }
663a8eb96d5SAlan Somers 
664a8eb96d5SAlan Somers /* sendto(2) and recvfrom(2) a single short record
665a8eb96d5SAlan Somers  * According to The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
666a8eb96d5SAlan Somers  * Edition, sendto(2) is exactly the same as send(2) on a connection-mode socket
667a8eb96d5SAlan Somers  *
668a8eb96d5SAlan Somers  * According to the same spec, not all protocols are required to provide the
669a8eb96d5SAlan Somers  * source addres in recvfrom(2).
670a8eb96d5SAlan Somers  */
671a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendto_recvfrom);
672a8eb96d5SAlan Somers ATF_TC_BODY(sendto_recvfrom, tc)
673a8eb96d5SAlan Somers {
674983a2d91SEnji Cooper #ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS
675a8eb96d5SAlan Somers 	const char* path;
676983a2d91SEnji Cooper #endif
677a8eb96d5SAlan Somers 	struct sockaddr_storage from;
678a8eb96d5SAlan Somers 	int sv[2];
679a8eb96d5SAlan Somers 	const int bufsize = 64;
680a8eb96d5SAlan Somers 	const char *data = "data";
681a8eb96d5SAlan Somers 	char recv_buf[bufsize];
6825d5b721aSAlan Somers 	ssize_t datalen;
683a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
684a8eb96d5SAlan Somers 	socklen_t fromlen;
685a8eb96d5SAlan Somers 
686a8eb96d5SAlan Somers 	/* setup the socket pair */
687983a2d91SEnji Cooper #ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS
688983a2d91SEnji Cooper 	path =
689983a2d91SEnji Cooper #endif
690983a2d91SEnji Cooper 		mk_pair_of_sockets(sv);
691a8eb96d5SAlan Somers 
692a8eb96d5SAlan Somers 	/* send and receive a small packet */
693a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
694a8eb96d5SAlan Somers 	ssize = sendto(sv[0], data, datalen, MSG_EOR, NULL, 0);
695a8eb96d5SAlan Somers 	if (ssize < 0) {
696a8eb96d5SAlan Somers 		perror("send");
697a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
698a8eb96d5SAlan Somers 	}
699a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
700a8eb96d5SAlan Somers 	    datalen, ssize);
701a8eb96d5SAlan Somers 
702a8eb96d5SAlan Somers 	fromlen = sizeof(from);
703a8eb96d5SAlan Somers 	rsize = recvfrom(sv[1], recv_buf, bufsize, MSG_WAITALL,
704a8eb96d5SAlan Somers 	    (struct sockaddr*)&from, &fromlen);
705a8eb96d5SAlan Somers 	if (ssize < 0) {
706a8eb96d5SAlan Somers 		perror("recvfrom");
707a8eb96d5SAlan Somers 		atf_tc_fail("recvfrom returned < 0");
708a8eb96d5SAlan Somers 	}
709a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
710a8eb96d5SAlan Somers 
711983a2d91SEnji Cooper #ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS
712a8eb96d5SAlan Somers 	/*
713a8eb96d5SAlan Somers 	 * FreeBSD does not currently provide the source address for SEQ_PACKET
714a8eb96d5SAlan Somers 	 * AF_UNIX sockets, and POSIX does not require it, so these two checks
715a8eb96d5SAlan Somers 	 * are disabled.  If FreeBSD gains that feature in the future, then
716a8eb96d5SAlan Somers 	 * these checks may be reenabled
717a8eb96d5SAlan Somers 	 */
718983a2d91SEnji Cooper 	ATF_CHECK_EQ(PF_LOCAL, from.ss_family);
719983a2d91SEnji Cooper 	ATF_CHECK_STREQ(path, ((struct sockaddr_un*)&from)->sun_path);
720983a2d91SEnji Cooper #endif
721e594026dSAlan Somers 	close(sv[0]);
722e594026dSAlan Somers 	close(sv[1]);
723a8eb96d5SAlan Somers }
724a8eb96d5SAlan Somers 
725a8eb96d5SAlan Somers /*
726a8eb96d5SAlan Somers  * send(2) and recv(2) a single short record with sockets created the
727a8eb96d5SAlan Somers  * traditional way, involving bind, listen, connect, and accept
728a8eb96d5SAlan Somers  */
729a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(send_recv_with_connect);
730a8eb96d5SAlan Somers ATF_TC_BODY(send_recv_with_connect, tc)
731a8eb96d5SAlan Somers {
732a8eb96d5SAlan Somers 	int sv[2];
733a8eb96d5SAlan Somers 	const int bufsize = 64;
734a8eb96d5SAlan Somers 	const char *data = "data";
735a8eb96d5SAlan Somers 	char recv_buf[bufsize];
7365d5b721aSAlan Somers 	ssize_t datalen;
737a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
738a8eb96d5SAlan Somers 
739a8eb96d5SAlan Somers 	mk_pair_of_sockets(sv);
740a8eb96d5SAlan Somers 
741a8eb96d5SAlan Somers 	/* send and receive a small packet */
742a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
743a8eb96d5SAlan Somers 	ssize = send(sv[0], data, datalen, MSG_EOR);
744a8eb96d5SAlan Somers 	if (ssize < 0) {
745a8eb96d5SAlan Somers 		perror("send");
746a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
747a8eb96d5SAlan Somers 	}
748a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
749a8eb96d5SAlan Somers 	    datalen, ssize);
750a8eb96d5SAlan Somers 
751a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
752a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
753e594026dSAlan Somers 	close(sv[0]);
754e594026dSAlan Somers 	close(sv[1]);
755a8eb96d5SAlan Somers }
756a8eb96d5SAlan Somers 
757a8eb96d5SAlan Somers /* send(2) should fail on a shutdown socket */
758a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(shutdown_send);
759a8eb96d5SAlan Somers ATF_TC_BODY(shutdown_send, tc)
760a8eb96d5SAlan Somers {
7614446a47aSSergey Kandaurov 	struct sockaddr_un sun;
7624446a47aSSergey Kandaurov 	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
7634446a47aSSergey Kandaurov 	const char *path = "sock";
7644446a47aSSergey Kandaurov 	const char *data = "data";
765a8eb96d5SAlan Somers 	ssize_t ssize;
7664446a47aSSergey Kandaurov 	int s, err, s2;
767a8eb96d5SAlan Somers 
768a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
769e594026dSAlan Somers 	ATF_REQUIRE(s >= 0);
7704446a47aSSergey Kandaurov 
7714446a47aSSergey Kandaurov 	bzero(&sun, sizeof(sun));
7724446a47aSSergey Kandaurov 	sun.sun_family = AF_LOCAL;
7734446a47aSSergey Kandaurov 	sun.sun_len = sizeof(sun);
7744446a47aSSergey Kandaurov 	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
7754446a47aSSergey Kandaurov 	err = bind(s, (struct sockaddr *)&sun, sizeof(sun));
7764446a47aSSergey Kandaurov 	err = listen(s, -1);
7774446a47aSSergey Kandaurov 	ATF_CHECK_EQ(0, err);
7784446a47aSSergey Kandaurov 
7794446a47aSSergey Kandaurov 	/* Create the other socket */
7804446a47aSSergey Kandaurov 	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
7814446a47aSSergey Kandaurov 	ATF_REQUIRE(s2 >= 0);
7824446a47aSSergey Kandaurov 	err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
7834446a47aSSergey Kandaurov 	if (err != 0) {
7844446a47aSSergey Kandaurov 		perror("connect");
7854446a47aSSergey Kandaurov 		atf_tc_fail("connect(2) failed");
7864446a47aSSergey Kandaurov 	}
7874446a47aSSergey Kandaurov 
7884446a47aSSergey Kandaurov 	ATF_CHECK_EQ(0, shutdown(s2, SHUT_RDWR));
789a8eb96d5SAlan Somers 	/* USE MSG_NOSIGNAL so we don't get SIGPIPE */
7904446a47aSSergey Kandaurov 	ssize = send(s2, data, sizeof(data), MSG_EOR | MSG_NOSIGNAL);
791a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EPIPE, errno);
792a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, ssize);
793e594026dSAlan Somers 	close(s);
7944446a47aSSergey Kandaurov 	close(s2);
795a8eb96d5SAlan Somers }
796a8eb96d5SAlan Somers 
797a8eb96d5SAlan Somers /* send(2) should cause SIGPIPE on a shutdown socket */
798a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(shutdown_send_sigpipe);
799a8eb96d5SAlan Somers ATF_TC_BODY(shutdown_send_sigpipe, tc)
800a8eb96d5SAlan Somers {
8014446a47aSSergey Kandaurov 	struct sockaddr_un sun;
8024446a47aSSergey Kandaurov 	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
8034446a47aSSergey Kandaurov 	const char *path = "sock";
8044446a47aSSergey Kandaurov 	const char *data = "data";
8054446a47aSSergey Kandaurov 	int s, err, s2;
806a8eb96d5SAlan Somers 
807a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
808e594026dSAlan Somers 	ATF_REQUIRE(s >= 0);
8094446a47aSSergey Kandaurov 
8104446a47aSSergey Kandaurov 	bzero(&sun, sizeof(sun));
8114446a47aSSergey Kandaurov 	sun.sun_family = AF_LOCAL;
8124446a47aSSergey Kandaurov 	sun.sun_len = sizeof(sun);
8134446a47aSSergey Kandaurov 	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
8144446a47aSSergey Kandaurov 	err = bind(s, (struct sockaddr *)&sun, sizeof(sun));
8154446a47aSSergey Kandaurov 	err = listen(s, -1);
8164446a47aSSergey Kandaurov 	ATF_CHECK_EQ(0, err);
8174446a47aSSergey Kandaurov 
8184446a47aSSergey Kandaurov 	/* Create the other socket */
8194446a47aSSergey Kandaurov 	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
8204446a47aSSergey Kandaurov 	ATF_REQUIRE(s2 >= 0);
8214446a47aSSergey Kandaurov 	err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
8224446a47aSSergey Kandaurov 	if (err != 0) {
8234446a47aSSergey Kandaurov 		perror("connect");
8244446a47aSSergey Kandaurov 		atf_tc_fail("connect(2) failed");
8254446a47aSSergey Kandaurov 	}
8264446a47aSSergey Kandaurov 
8274446a47aSSergey Kandaurov 	ATF_CHECK_EQ(0, shutdown(s2, SHUT_RDWR));
828a8eb96d5SAlan Somers 	ATF_REQUIRE(SIG_ERR != signal(SIGPIPE, shutdown_send_sigpipe_handler));
829983a2d91SEnji Cooper 	(void)send(s2, data, sizeof(data), MSG_EOR);
830a8eb96d5SAlan Somers 	ATF_CHECK_EQ(1, got_sigpipe);
831e594026dSAlan Somers 	close(s);
8324446a47aSSergey Kandaurov 	close(s2);
833a8eb96d5SAlan Somers }
834a8eb96d5SAlan Somers 
835a8eb96d5SAlan Somers /* nonblocking send(2) and recv(2) a single short record */
836a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(send_recv_nonblocking);
837a8eb96d5SAlan Somers ATF_TC_BODY(send_recv_nonblocking, tc)
838a8eb96d5SAlan Somers {
839a8eb96d5SAlan Somers 	int sv[2];
840a8eb96d5SAlan Somers 	const int bufsize = 64;
841a8eb96d5SAlan Somers 	const char *data = "data";
842a8eb96d5SAlan Somers 	char recv_buf[bufsize];
8435d5b721aSAlan Somers 	ssize_t datalen;
844a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
845a8eb96d5SAlan Somers 
846a8eb96d5SAlan Somers 	/* setup the socket pair */
847a8eb96d5SAlan Somers 	do_socketpair_nonblocking(sv);
848a8eb96d5SAlan Somers 
849a8eb96d5SAlan Somers 	/* Verify that there is nothing to receive */
850a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
851a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EAGAIN, errno);
852a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, rsize);
853a8eb96d5SAlan Somers 
854a8eb96d5SAlan Somers 	/* send and receive a small packet */
855a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
856a8eb96d5SAlan Somers 	ssize = send(sv[0], data, datalen, MSG_EOR);
857a8eb96d5SAlan Somers 	if (ssize < 0) {
858a8eb96d5SAlan Somers 		perror("send");
859a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
860a8eb96d5SAlan Somers 	}
861a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
862a8eb96d5SAlan Somers 	    datalen, ssize);
863a8eb96d5SAlan Somers 
864a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
865a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
866e594026dSAlan Somers 	close(sv[0]);
867e594026dSAlan Somers 	close(sv[1]);
868a8eb96d5SAlan Somers }
869a8eb96d5SAlan Somers 
870a8eb96d5SAlan Somers /*
871a8eb96d5SAlan Somers  * We should get EMSGSIZE if we try to send a message larger than the socket
872a8eb96d5SAlan Somers  * buffer, with blocking sockets
873a8eb96d5SAlan Somers  */
874a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(emsgsize);
875a8eb96d5SAlan Somers ATF_TC_BODY(emsgsize, tc)
876a8eb96d5SAlan Somers {
877a8eb96d5SAlan Somers 	int sv[2];
878a8eb96d5SAlan Somers 	const size_t sndbufsize = 8192;
879a8eb96d5SAlan Somers 	const size_t rcvbufsize = 8192;
880a8eb96d5SAlan Somers 	const size_t pktsize = (sndbufsize + rcvbufsize) * 2;
881a8eb96d5SAlan Somers 	char sndbuf[pktsize];
8825d5b721aSAlan Somers 	ssize_t ssize;
883a8eb96d5SAlan Somers 
884a8eb96d5SAlan Somers 	/* setup the socket pair */
885a8eb96d5SAlan Somers 	do_socketpair(sv);
886a8eb96d5SAlan Somers 	/* Setup the buffers */
887a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
888a8eb96d5SAlan Somers 	    sizeof(sndbufsize)));
889a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
890a8eb96d5SAlan Somers 	    sizeof(rcvbufsize)));
891a8eb96d5SAlan Somers 
892a8eb96d5SAlan Somers 	ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
893a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EMSGSIZE, errno);
894a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, ssize);
895e594026dSAlan Somers 	close(sv[0]);
896e594026dSAlan Somers 	close(sv[1]);
897a8eb96d5SAlan Somers }
898a8eb96d5SAlan Somers 
899a8eb96d5SAlan Somers /*
900a8eb96d5SAlan Somers  * We should get EMSGSIZE if we try to send a message larger than the socket
901a8eb96d5SAlan Somers  * buffer, with nonblocking sockets
902a8eb96d5SAlan Somers  */
903a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(emsgsize_nonblocking);
904a8eb96d5SAlan Somers ATF_TC_BODY(emsgsize_nonblocking, tc)
905a8eb96d5SAlan Somers {
906a8eb96d5SAlan Somers 	int sv[2];
907a8eb96d5SAlan Somers 	const size_t sndbufsize = 8192;
908a8eb96d5SAlan Somers 	const size_t rcvbufsize = 8192;
909a8eb96d5SAlan Somers 	const size_t pktsize = (sndbufsize + rcvbufsize) * 2;
910a8eb96d5SAlan Somers 	char sndbuf[pktsize];
9115d5b721aSAlan Somers 	ssize_t ssize;
912a8eb96d5SAlan Somers 
913a8eb96d5SAlan Somers 	/* setup the socket pair */
914a8eb96d5SAlan Somers 	do_socketpair_nonblocking(sv);
915a8eb96d5SAlan Somers 	/* Setup the buffers */
916a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
917a8eb96d5SAlan Somers 	    sizeof(sndbufsize)));
918a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
919a8eb96d5SAlan Somers 	    sizeof(rcvbufsize)));
920a8eb96d5SAlan Somers 
921a8eb96d5SAlan Somers 	ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
922a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EMSGSIZE, errno);
923a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, ssize);
924e594026dSAlan Somers 	close(sv[0]);
925e594026dSAlan Somers 	close(sv[1]);
926a8eb96d5SAlan Somers }
927a8eb96d5SAlan Somers 
928a8eb96d5SAlan Somers 
929a8eb96d5SAlan Somers /*
930a8eb96d5SAlan Somers  * We should get EAGAIN if we try to send a message larger than the socket
931a8eb96d5SAlan Somers  * buffer, with nonblocking sockets.  Test with several different sockbuf sizes
932a8eb96d5SAlan Somers  */
933a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_8k_8k);
934a8eb96d5SAlan Somers ATF_TC_BODY(eagain_8k_8k, tc)
935a8eb96d5SAlan Somers {
936a8eb96d5SAlan Somers 	test_eagain(8192, 8192);
937a8eb96d5SAlan Somers }
938a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_8k_128k);
939a8eb96d5SAlan Somers ATF_TC_BODY(eagain_8k_128k, tc)
940a8eb96d5SAlan Somers {
941a8eb96d5SAlan Somers 	test_eagain(8192, 131072);
942a8eb96d5SAlan Somers }
943a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_128k_8k);
944a8eb96d5SAlan Somers ATF_TC_BODY(eagain_128k_8k, tc)
945a8eb96d5SAlan Somers {
946a8eb96d5SAlan Somers 	test_eagain(131072, 8192);
947a8eb96d5SAlan Somers }
948a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_128k_128k);
949a8eb96d5SAlan Somers ATF_TC_BODY(eagain_128k_128k, tc)
950a8eb96d5SAlan Somers {
951a8eb96d5SAlan Somers 	test_eagain(131072, 131072);
952a8eb96d5SAlan Somers }
953a8eb96d5SAlan Somers 
954a8eb96d5SAlan Somers 
955a8eb96d5SAlan Somers /*
956a8eb96d5SAlan Somers  * nonblocking send(2) and recv(2) of several records, which should collectively
957a8eb96d5SAlan Somers  * fill up the send buffer but not the receive buffer
958a8eb96d5SAlan Somers  */
959a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(rcvbuf_oversized);
960a8eb96d5SAlan Somers ATF_TC_BODY(rcvbuf_oversized, tc)
961a8eb96d5SAlan Somers {
9625d5b721aSAlan Somers 	int i;
963a8eb96d5SAlan Somers 	int sv[2];
9643be7751dSJulio Merino 	const ssize_t pktsize = 1024;
965a8eb96d5SAlan Somers 	const size_t sndbufsize = 8192;
966a8eb96d5SAlan Somers 	const size_t rcvbufsize = 131072;
9675d5b721aSAlan Somers 	const size_t geometric_mean_bufsize = 32768;
9685d5b721aSAlan Somers 	const int numpkts = geometric_mean_bufsize / pktsize;
969a8eb96d5SAlan Somers 	char sndbuf[pktsize];
970a8eb96d5SAlan Somers 	char recv_buf[pktsize];
971a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
972a8eb96d5SAlan Somers 
973a8eb96d5SAlan Somers 	/* setup the socket pair */
974a8eb96d5SAlan Somers 	do_socketpair_nonblocking(sv);
9755d5b721aSAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
9765d5b721aSAlan Somers 	    sizeof(sndbufsize)));
9775d5b721aSAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
9785d5b721aSAlan Somers 	    sizeof(rcvbufsize)));
979a8eb96d5SAlan Somers 
980a8eb96d5SAlan Somers 	/*
981a8eb96d5SAlan Somers 	 * Send and receive packets that are collectively greater than the send
982a8eb96d5SAlan Somers 	 * buffer, but less than the receive buffer
983a8eb96d5SAlan Somers 	 */
9845d5b721aSAlan Somers 	for (i=0; i < numpkts; i++) {
985a8eb96d5SAlan Somers 		/* Fill the buffer */
986a8eb96d5SAlan Somers 		memset(sndbuf, i, pktsize);
987a8eb96d5SAlan Somers 
988a8eb96d5SAlan Somers 		/* send the packet */
989a8eb96d5SAlan Somers 		ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
990a8eb96d5SAlan Somers 		if (ssize < 0) {
991a8eb96d5SAlan Somers 			perror("send");
992a8eb96d5SAlan Somers 			atf_tc_fail("send returned < 0");
993a8eb96d5SAlan Somers 		}
994a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(pktsize, ssize,
995a8eb96d5SAlan Somers 		    "expected %zd=send(...) but got %zd", pktsize, ssize);
996a8eb96d5SAlan Somers 
997a8eb96d5SAlan Somers 		/* Receive it */
998a8eb96d5SAlan Somers 
999a8eb96d5SAlan Somers 		rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
1000a8eb96d5SAlan Somers 		if (rsize < 0) {
1001a8eb96d5SAlan Somers 			perror("recv");
1002a8eb96d5SAlan Somers 			atf_tc_fail("recv returned < 0");
1003a8eb96d5SAlan Somers 		}
1004a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(pktsize, rsize,
1005a8eb96d5SAlan Somers 		    "expected %zd=send(...) but got %zd", pktsize, rsize);
1006a8eb96d5SAlan Somers 
1007a8eb96d5SAlan Somers 		/* Verify the contents */
1008a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(0, memcmp(sndbuf, recv_buf, pktsize),
1009a8eb96d5SAlan Somers 		    "Received data miscompare");
1010a8eb96d5SAlan Somers 	}
1011a8eb96d5SAlan Somers 
1012a8eb96d5SAlan Somers 	/* Trying to receive again should return EAGAIN */
1013a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
1014a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EAGAIN, errno);
1015a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, rsize);
1016e594026dSAlan Somers 	close(sv[0]);
1017e594026dSAlan Somers 	close(sv[1]);
1018a8eb96d5SAlan Somers }
1019a8eb96d5SAlan Somers 
1020a8eb96d5SAlan Somers /*
1021a8eb96d5SAlan Somers  * Simulate the behavior of a blocking pipe.  The sender will send until his
1022a8eb96d5SAlan Somers  * buffer fills up, then we'll simulate a scheduler switch that will allow the
1023a8eb96d5SAlan Somers  * receiver to read until his buffer empties.  Repeat the process until the
1024a8eb96d5SAlan Somers  * transfer is complete.
1025a8eb96d5SAlan Somers  * Repeat the test with multiple send and receive buffer sizes
1026a8eb96d5SAlan Somers  */
1027a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_8k);
1028a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_8k_8k, tc)
1029a8eb96d5SAlan Somers {
1030a8eb96d5SAlan Somers 	test_pipe_simulator(8192, 8192);
1031a8eb96d5SAlan Somers }
1032a8eb96d5SAlan Somers 
1033a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_128k);
1034a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_8k_128k, tc)
1035a8eb96d5SAlan Somers {
1036a8eb96d5SAlan Somers 	test_pipe_simulator(8192, 131072);
1037a8eb96d5SAlan Somers }
1038a8eb96d5SAlan Somers 
1039a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_8k);
1040a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_128k_8k, tc)
1041a8eb96d5SAlan Somers {
1042a8eb96d5SAlan Somers 	test_pipe_simulator(131072, 8192);
1043a8eb96d5SAlan Somers }
1044a8eb96d5SAlan Somers 
1045a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_128k);
1046a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_128k_128k, tc)
1047a8eb96d5SAlan Somers {
1048a8eb96d5SAlan Somers 	test_pipe_simulator(131072, 131072);
1049a8eb96d5SAlan Somers }
1050a8eb96d5SAlan Somers 
1051a8eb96d5SAlan Somers /*
1052a8eb96d5SAlan Somers  * Test blocking I/O by passing data between two threads.  The total amount of
1053a8eb96d5SAlan Somers  * data will be >> buffer size to force blocking.  Repeat the test with multiple
1054a8eb96d5SAlan Somers  * send and receive buffer sizes
1055a8eb96d5SAlan Somers  */
1056a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_8k_8k);
1057a8eb96d5SAlan Somers ATF_TC_BODY(pipe_8k_8k, tc)
1058a8eb96d5SAlan Somers {
1059a8eb96d5SAlan Somers 	test_pipe(8192, 8192);
1060a8eb96d5SAlan Somers }
1061a8eb96d5SAlan Somers 
1062a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_8k_128k);
1063a8eb96d5SAlan Somers ATF_TC_BODY(pipe_8k_128k, tc)
1064a8eb96d5SAlan Somers {
1065a8eb96d5SAlan Somers 	test_pipe(8192, 131072);
1066a8eb96d5SAlan Somers }
1067a8eb96d5SAlan Somers 
1068a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_128k_8k);
1069a8eb96d5SAlan Somers ATF_TC_BODY(pipe_128k_8k, tc)
1070a8eb96d5SAlan Somers {
1071a8eb96d5SAlan Somers 	test_pipe(131072, 8192);
1072a8eb96d5SAlan Somers }
1073a8eb96d5SAlan Somers 
1074a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_128k_128k);
1075a8eb96d5SAlan Somers ATF_TC_BODY(pipe_128k_128k, tc)
1076a8eb96d5SAlan Somers {
1077a8eb96d5SAlan Somers 	test_pipe(131072, 131072);
1078a8eb96d5SAlan Somers }
1079a8eb96d5SAlan Somers 
1080a8eb96d5SAlan Somers 
1081a8eb96d5SAlan Somers /*
1082a8eb96d5SAlan Somers  * Test single-packet I/O with and without blocking, with symmetric buffers of
1083a8eb96d5SAlan Somers  * various sizes
1084a8eb96d5SAlan Somers  */
1085a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_8k);
1086a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_8k, tc)
1087a8eb96d5SAlan Somers {
1088a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(8 * 1024, true);
1089a8eb96d5SAlan Somers }
1090a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_16k);
1091a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_16k, tc)
1092a8eb96d5SAlan Somers {
1093a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(16 * 1024, true);
1094a8eb96d5SAlan Somers }
1095a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_32k);
1096a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_32k, tc)
1097a8eb96d5SAlan Somers {
1098a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(32 * 1024, true);
1099a8eb96d5SAlan Somers }
1100a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_64k);
1101a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_64k, tc)
1102a8eb96d5SAlan Somers {
1103a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(64 * 1024, true);
1104a8eb96d5SAlan Somers }
1105a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_128k);
1106a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_128k, tc)
1107a8eb96d5SAlan Somers {
1108a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(128 * 1024, true);
1109a8eb96d5SAlan Somers }
1110a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_8k_nonblocking);
1111a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_8k_nonblocking, tc)
1112a8eb96d5SAlan Somers {
1113a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(8 * 1024, false);
1114a8eb96d5SAlan Somers }
1115a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_16k_nonblocking);
1116a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_16k_nonblocking, tc)
1117a8eb96d5SAlan Somers {
1118a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(16 * 1024, false);
1119a8eb96d5SAlan Somers }
1120a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_32k_nonblocking);
1121a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_32k_nonblocking, tc)
1122a8eb96d5SAlan Somers {
1123a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(32 * 1024, false);
1124a8eb96d5SAlan Somers }
1125a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_64k_nonblocking);
1126a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_64k_nonblocking, tc)
1127a8eb96d5SAlan Somers {
1128a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(64 * 1024, false);
1129a8eb96d5SAlan Somers }
1130a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_128k_nonblocking);
1131a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_128k_nonblocking, tc)
1132a8eb96d5SAlan Somers {
1133a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(128 * 1024, false);
1134a8eb96d5SAlan Somers }
1135a8eb96d5SAlan Somers 
1136a8eb96d5SAlan Somers 
1137a8eb96d5SAlan Somers /*
1138a8eb96d5SAlan Somers  * Main.
1139a8eb96d5SAlan Somers  */
1140a8eb96d5SAlan Somers 
1141a8eb96d5SAlan Somers ATF_TP_ADD_TCS(tp)
1142a8eb96d5SAlan Somers {
1143a8eb96d5SAlan Somers 	/* Basic creation and connection tests */
1144a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, create_socket);
1145a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, create_socketpair);
1146a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, listen_unbound);
1147a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, bind);
1148a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, listen_bound);
1149a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, connect);
1150a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, accept);
1151a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, fcntl_nonblock);
1152a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, resize_buffers);
1153a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, resize_connected_buffers);
1154a8eb96d5SAlan Somers 
1155a8eb96d5SAlan Somers 	/* Unthreaded I/O tests */
1156a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, send_recv);
1157a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, send_recv_nonblocking);
1158a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, send_recv_with_connect);
1159a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendto_recvfrom);
1160a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, shutdown_send);
1161a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, shutdown_send_sigpipe);
1162a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, emsgsize);
1163a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, emsgsize_nonblocking);
1164a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_8k_8k);
1165a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_8k_128k);
1166a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_128k_8k);
1167a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_128k_128k);
1168a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_8k);
1169a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_16k);
1170a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_32k);
1171a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_64k);
1172a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_128k);
1173a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_8k_nonblocking);
1174a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_16k_nonblocking);
1175a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_32k_nonblocking);
1176a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_64k_nonblocking);
1177a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_128k_nonblocking);
1178a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, rcvbuf_oversized);
1179a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_8k_8k);
1180a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_8k_128k);
1181a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_128k_8k);
1182a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_128k_128k);
1183a8eb96d5SAlan Somers 
1184a8eb96d5SAlan Somers 	/* Threaded I/O tests with blocking sockets */
1185a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_8k_8k);
1186a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_8k_128k);
1187a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_128k_8k);
1188a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_128k_128k);
1189a8eb96d5SAlan Somers 
1190a8eb96d5SAlan Somers 	return atf_no_error();
1191a8eb96d5SAlan Somers }
1192