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(¶ms->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, ¶ms->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(¶ms.seed[0]);
1241
1242 ATF_REQUIRE(sysctlbyname("net.local.seqpacket.recvspace",
1243 ¶ms.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(¶ms.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, ¶ms) == 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(¶ms.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