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