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