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 sv[0] = s1; 128 sv[1] = s2; 129 130 close(s); 131 132 return (sun); 133 } 134 135 static volatile sig_atomic_t got_sigpipe = 0; 136 static void 137 shutdown_send_sigpipe_handler(int __unused x) 138 { 139 got_sigpipe = 1; 140 } 141 142 /* 143 * Parameterized test function bodies 144 */ 145 static void 146 test_eagain(int sndbufsize, int rcvbufsize) 147 { 148 int i; 149 int sv[2]; 150 const size_t totalsize = (sndbufsize + rcvbufsize) * 2; 151 const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4; 152 const int numpkts = totalsize / pktsize; 153 char sndbuf[pktsize]; 154 ssize_t ssize; 155 156 /* setup the socket pair */ 157 do_socketpair_nonblocking(sv); 158 /* Setup the buffers */ 159 ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize, 160 sizeof(sndbufsize))); 161 ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize, 162 sizeof(rcvbufsize))); 163 164 bzero(sndbuf, pktsize); 165 /* Send data until we get EAGAIN */ 166 for(i=0; i < numpkts; i++) { 167 ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); 168 if (ssize == -1) { 169 if (errno == EAGAIN) { 170 close(sv[0]); 171 close(sv[1]); 172 atf_tc_pass(); 173 } 174 else { 175 perror("send"); 176 atf_tc_fail("send returned < 0 but not EAGAIN"); 177 } 178 } 179 } 180 atf_tc_fail("Never got EAGAIN"); 181 } 182 183 static void 184 test_sendrecv_symmetric_buffers(int bufsize, int blocking) { 185 int s; 186 int sv[2]; 187 const ssize_t pktsize = bufsize / 2; 188 char sndbuf[pktsize]; 189 char recv_buf[pktsize]; 190 ssize_t ssize, rsize; 191 192 /* setup the socket pair */ 193 if (blocking) 194 do_socketpair(sv); 195 else 196 do_socketpair_nonblocking(sv); 197 198 /* Setup the buffers */ 199 s = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)); 200 ATF_REQUIRE_EQ(0, s); 201 s = setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)); 202 ATF_REQUIRE_EQ(0, s); 203 204 /* Fill the send buffer */ 205 bzero(sndbuf, pktsize); 206 207 /* send and receive the packet */ 208 ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); 209 if (ssize < 0) { 210 perror("send"); 211 atf_tc_fail("send returned < 0"); 212 } 213 ATF_CHECK_EQ_MSG(pktsize, ssize, "expected %zd=send(...) but got %zd", 214 pktsize, ssize); 215 216 rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL); 217 if (rsize < 0) { 218 perror("recv"); 219 atf_tc_fail("recv returned < 0"); 220 } 221 ATF_CHECK_EQ_MSG(pktsize, rsize, "expected %zd=send(...) but got %zd", 222 pktsize, rsize); 223 close(sv[0]); 224 close(sv[1]); 225 } 226 227 static void 228 test_pipe_simulator(int sndbufsize, int rcvbufsize) 229 { 230 int num_sent, num_received; 231 int sv[2]; 232 const ssize_t pktsize = MIN(sndbufsize, rcvbufsize) / 4; 233 int numpkts; 234 char sndbuf[pktsize]; 235 char rcvbuf[pktsize]; 236 char comparebuf[pktsize]; 237 ssize_t ssize, rsize; 238 bool currently_sending = true; 239 240 /* setup the socket pair */ 241 do_socketpair_nonblocking(sv); 242 /* Setup the buffers */ 243 ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize, 244 sizeof(sndbufsize))); 245 ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize, 246 sizeof(rcvbufsize))); 247 248 /* Send a total amount of data comfortably greater than the buffers */ 249 numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize; 250 for (num_sent=0, num_received=0; 251 num_sent < numpkts || num_received < numpkts; ) { 252 if (currently_sending && num_sent < numpkts) { 253 /* The simulated sending process */ 254 /* fill the buffer */ 255 memset(sndbuf, num_sent, pktsize); 256 ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); 257 if (ssize < 0) { 258 /* 259 * XXX: This is bug-compatible with the kernel. 260 * The kernel returns EMSGSIZE when it should 261 * return EAGAIN 262 */ 263 if (errno == EAGAIN || errno == EMSGSIZE) 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* 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* 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 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); 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); 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); 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); 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); 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); 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); 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 /* Implied connect is unix/dgram only feature. Fails on stream or seqpacket. */ 529 ATF_TC_WITHOUT_HEAD(implied_connect); 530 ATF_TC_BODY(implied_connect, tc) 531 { 532 const struct sockaddr_un *sun; 533 int l, s; 534 535 sun = mk_listening_socket(&l); 536 537 ATF_REQUIRE((s = socket(PF_LOCAL, SOCK_SEQPACKET, 0)) > 0); 538 ATF_REQUIRE(sendto(s, &s, sizeof(s), 0, (struct sockaddr *)sun, 539 sizeof(*sun)) == -1); 540 ATF_REQUIRE(errno == ENOTCONN); 541 close(l); 542 close(s); 543 } 544 545 /* accept(2) can receive a connection */ 546 ATF_TC_WITHOUT_HEAD(accept); 547 ATF_TC_BODY(accept, tc) 548 { 549 int sv[2]; 550 551 mk_pair_of_sockets(sv); 552 close(sv[0]); 553 close(sv[1]); 554 } 555 556 557 /* Set O_NONBLOCK on the socket */ 558 ATF_TC_WITHOUT_HEAD(fcntl_nonblock); 559 ATF_TC_BODY(fcntl_nonblock, tc) 560 { 561 int s; 562 563 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 564 ATF_REQUIRE(s >= 0); 565 if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) { 566 perror("fcntl"); 567 atf_tc_fail("fcntl failed"); 568 } 569 close(s); 570 } 571 572 /* Resize the send and receive buffers */ 573 ATF_TC_WITHOUT_HEAD(resize_buffers); 574 ATF_TC_BODY(resize_buffers, tc) 575 { 576 int s; 577 int sndbuf = 12345; 578 int rcvbuf = 23456; 579 int xs, xr; 580 socklen_t sl = sizeof(xs); 581 582 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 583 ATF_REQUIRE(s >= 0); 584 585 printf(" Socket Buffer Sizes\n"); 586 printf(" | SNDBUF | RCVBUF |\n"); 587 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl)); 588 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl)); 589 printf("Default | %7d | %7d |\n", xs, xr); 590 591 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) != 0){ 592 perror("setsockopt"); 593 atf_tc_fail("setsockopt(SO_SNDBUF) failed"); 594 } 595 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl)); 596 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl)); 597 printf("After changing SNDBUF | %7d | %7d |\n", xs, xr); 598 599 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) != 0){ 600 perror("setsockopt"); 601 atf_tc_fail("setsockopt(SO_RCVBUF) failed"); 602 } 603 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl)); 604 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl)); 605 printf("After changing RCVBUF | %7d | %7d |\n", xs, xr); 606 close(s); 607 } 608 609 /* 610 * Resize the send and receive buffers of a connected socketpair 611 * Print some useful debugging info too 612 */ 613 ATF_TC_WITHOUT_HEAD(resize_connected_buffers); 614 ATF_TC_BODY(resize_connected_buffers, tc) 615 { 616 int sv[2]; 617 int sndbuf = 12345; 618 int rcvbuf = 23456; 619 int err; 620 int ls, lr, rs, rr; 621 socklen_t sl = sizeof(ls); 622 623 /* setup the socket pair */ 624 do_socketpair(sv); 625 626 printf(" Socket Buffer Sizes\n"); 627 printf(" | Left Socket | Right Socket |\n"); 628 printf(" | SNDBUF | RCVBUF | SNDBUF | RCVBUF |\n"); 629 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl)); 630 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl)); 631 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl)); 632 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl)); 633 printf("Default | %7d | %7d | %7d | %7d |\n", 634 ls, lr, rs, rr); 635 636 /* Update one side's send buffer */ 637 err = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)); 638 if (err != 0){ 639 perror("setsockopt"); 640 atf_tc_fail("setsockopt(SO_SNDBUF) failed"); 641 } 642 643 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl)); 644 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl)); 645 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl)); 646 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl)); 647 printf("After changing Left's SNDBUF | %7d | %7d | %7d | %7d |\n", 648 ls, lr, rs, rr); 649 650 /* Update the same side's receive buffer */ 651 err = setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)); 652 if (err != 0){ 653 perror("setsockopt"); 654 atf_tc_fail("setsockopt(SO_RCVBUF) failed"); 655 } 656 657 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl)); 658 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl)); 659 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl)); 660 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl)); 661 printf("After changing Left's RCVBUF | %7d | %7d | %7d | %7d |\n", 662 ls, lr, rs, rr); 663 close(sv[0]); 664 close(sv[1]); 665 } 666 667 668 /* send(2) and recv(2) a single short record */ 669 ATF_TC_WITHOUT_HEAD(send_recv); 670 ATF_TC_BODY(send_recv, tc) 671 { 672 int sv[2]; 673 const int bufsize = 64; 674 const char *data = "data"; 675 char recv_buf[bufsize]; 676 ssize_t datalen; 677 ssize_t ssize, rsize; 678 679 /* setup the socket pair */ 680 do_socketpair(sv); 681 682 /* send and receive a small packet */ 683 datalen = strlen(data) + 1; /* +1 for the null */ 684 ssize = send(sv[0], data, datalen, MSG_EOR); 685 if (ssize < 0) { 686 perror("send"); 687 atf_tc_fail("send returned < 0"); 688 } 689 ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd", 690 datalen, ssize); 691 692 rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL); 693 ATF_CHECK_EQ(datalen, rsize); 694 close(sv[0]); 695 close(sv[1]); 696 } 697 698 /* sendto(2) and recvfrom(2) a single short record 699 * According to The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 700 * Edition, sendto(2) is exactly the same as send(2) on a connection-mode socket 701 * 702 * According to the same spec, not all protocols are required to provide the 703 * source addres in recvfrom(2). 704 */ 705 ATF_TC_WITHOUT_HEAD(sendto_recvfrom); 706 ATF_TC_BODY(sendto_recvfrom, tc) 707 { 708 #ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS 709 const sockaddr_un *sun; 710 #endif 711 struct sockaddr_storage from; 712 int sv[2]; 713 const int bufsize = 64; 714 const char *data = "data"; 715 char recv_buf[bufsize]; 716 ssize_t datalen; 717 ssize_t ssize, rsize; 718 socklen_t fromlen; 719 720 /* setup the socket pair */ 721 #ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS 722 sun = 723 #endif 724 mk_pair_of_sockets(sv); 725 726 /* send and receive a small packet */ 727 datalen = strlen(data) + 1; /* +1 for the null */ 728 ssize = sendto(sv[0], data, datalen, MSG_EOR, NULL, 0); 729 if (ssize < 0) { 730 perror("send"); 731 atf_tc_fail("send returned < 0"); 732 } 733 ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd", 734 datalen, ssize); 735 736 fromlen = sizeof(from); 737 rsize = recvfrom(sv[1], recv_buf, bufsize, MSG_WAITALL, 738 (struct sockaddr*)&from, &fromlen); 739 if (ssize < 0) { 740 perror("recvfrom"); 741 atf_tc_fail("recvfrom returned < 0"); 742 } 743 ATF_CHECK_EQ(datalen, rsize); 744 745 #ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS 746 /* 747 * FreeBSD does not currently provide the source address for SEQ_PACKET 748 * AF_UNIX sockets, and POSIX does not require it, so these two checks 749 * are disabled. If FreeBSD gains that feature in the future, then 750 * these checks may be reenabled 751 */ 752 ATF_CHECK_EQ(PF_LOCAL, from.ss_family); 753 ATF_CHECK_STREQ(sun->sun_path, ((struct sockaddr_un*)&from)->sun_path); 754 #endif 755 close(sv[0]); 756 close(sv[1]); 757 } 758 759 /* 760 * send(2) and recv(2) a single short record with sockets created the 761 * traditional way, involving bind, listen, connect, and accept 762 */ 763 ATF_TC_WITHOUT_HEAD(send_recv_with_connect); 764 ATF_TC_BODY(send_recv_with_connect, tc) 765 { 766 int sv[2]; 767 const int bufsize = 64; 768 const char *data = "data"; 769 char recv_buf[bufsize]; 770 ssize_t datalen; 771 ssize_t ssize, rsize; 772 773 mk_pair_of_sockets(sv); 774 775 /* send and receive a small packet */ 776 datalen = strlen(data) + 1; /* +1 for the null */ 777 ssize = send(sv[0], data, datalen, MSG_EOR); 778 if (ssize < 0) { 779 perror("send"); 780 atf_tc_fail("send returned < 0"); 781 } 782 ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd", 783 datalen, ssize); 784 785 rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL); 786 ATF_CHECK_EQ(datalen, rsize); 787 close(sv[0]); 788 close(sv[1]); 789 } 790 791 /* send(2) should fail on a shutdown socket */ 792 ATF_TC_WITHOUT_HEAD(shutdown_send); 793 ATF_TC_BODY(shutdown_send, tc) 794 { 795 const struct sockaddr_un *sun; 796 const char *data = "data"; 797 ssize_t datalen, ssize; 798 int s, err, s2; 799 800 sun = mk_listening_socket(&s); 801 802 /* Create the other socket */ 803 s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 804 ATF_REQUIRE(s2 >= 0); 805 err = connect(s2, (struct sockaddr *)sun, sizeof(*sun)); 806 if (err != 0) { 807 perror("connect"); 808 atf_tc_fail("connect(2) failed"); 809 } 810 811 ATF_CHECK_EQ(0, shutdown(s2, SHUT_RDWR)); 812 datalen = strlen(data) + 1; /* +1 for the null */ 813 /* USE MSG_NOSIGNAL so we don't get SIGPIPE */ 814 ssize = send(s2, data, datalen, MSG_EOR | MSG_NOSIGNAL); 815 ATF_CHECK_EQ(EPIPE, errno); 816 ATF_CHECK_EQ(-1, ssize); 817 close(s); 818 close(s2); 819 } 820 821 /* send(2) should cause SIGPIPE on a shutdown socket */ 822 ATF_TC_WITHOUT_HEAD(shutdown_send_sigpipe); 823 ATF_TC_BODY(shutdown_send_sigpipe, tc) 824 { 825 const struct sockaddr_un *sun; 826 const char *data = "data"; 827 ssize_t datalen; 828 int s, err, s2; 829 830 sun = mk_listening_socket(&s); 831 832 /* Create the other socket */ 833 s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0); 834 ATF_REQUIRE(s2 >= 0); 835 err = connect(s2, (struct sockaddr *)sun, sizeof(*sun)); 836 if (err != 0) { 837 perror("connect"); 838 atf_tc_fail("connect(2) failed"); 839 } 840 841 ATF_CHECK_EQ(0, shutdown(s2, SHUT_RDWR)); 842 ATF_REQUIRE(SIG_ERR != signal(SIGPIPE, shutdown_send_sigpipe_handler)); 843 datalen = strlen(data) + 1; /* +1 for the null */ 844 (void)send(s2, data, datalen, MSG_EOR); 845 ATF_CHECK_EQ(1, got_sigpipe); 846 close(s); 847 close(s2); 848 } 849 850 /* nonblocking send(2) and recv(2) a single short record */ 851 ATF_TC_WITHOUT_HEAD(send_recv_nonblocking); 852 ATF_TC_BODY(send_recv_nonblocking, tc) 853 { 854 int sv[2]; 855 const int bufsize = 64; 856 const char *data = "data"; 857 char recv_buf[bufsize]; 858 ssize_t datalen; 859 ssize_t ssize, rsize; 860 861 /* setup the socket pair */ 862 do_socketpair_nonblocking(sv); 863 864 /* Verify that there is nothing to receive */ 865 rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL); 866 ATF_CHECK_EQ(EAGAIN, errno); 867 ATF_CHECK_EQ(-1, rsize); 868 869 /* send and receive a small packet */ 870 datalen = strlen(data) + 1; /* +1 for the null */ 871 ssize = send(sv[0], data, datalen, MSG_EOR); 872 if (ssize < 0) { 873 perror("send"); 874 atf_tc_fail("send returned < 0"); 875 } 876 ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd", 877 datalen, ssize); 878 879 rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL); 880 ATF_CHECK_EQ(datalen, rsize); 881 close(sv[0]); 882 close(sv[1]); 883 } 884 885 /* 886 * We should get EAGAIN if we try to send a message larger than the socket 887 * buffer, with nonblocking sockets. Test with several different sockbuf sizes 888 */ 889 ATF_TC_WITHOUT_HEAD(eagain_8k_8k); 890 ATF_TC_BODY(eagain_8k_8k, tc) 891 { 892 test_eagain(8192, 8192); 893 } 894 ATF_TC_WITHOUT_HEAD(eagain_8k_128k); 895 ATF_TC_BODY(eagain_8k_128k, tc) 896 { 897 test_eagain(8192, 131072); 898 } 899 ATF_TC_WITHOUT_HEAD(eagain_128k_8k); 900 ATF_TC_BODY(eagain_128k_8k, tc) 901 { 902 test_eagain(131072, 8192); 903 } 904 ATF_TC_WITHOUT_HEAD(eagain_128k_128k); 905 ATF_TC_BODY(eagain_128k_128k, tc) 906 { 907 test_eagain(131072, 131072); 908 } 909 910 911 /* 912 * nonblocking send(2) and recv(2) of several records, which should collectively 913 * fill up the send buffer but not the receive buffer 914 */ 915 ATF_TC_WITHOUT_HEAD(rcvbuf_oversized); 916 ATF_TC_BODY(rcvbuf_oversized, tc) 917 { 918 int i; 919 int sv[2]; 920 const ssize_t pktsize = 1024; 921 const int sndbufsize = 8192; 922 const int rcvbufsize = 131072; 923 const size_t geometric_mean_bufsize = 32768; 924 const int numpkts = geometric_mean_bufsize / pktsize; 925 char sndbuf[pktsize]; 926 char recv_buf[pktsize]; 927 ssize_t ssize, rsize; 928 929 /* setup the socket pair */ 930 do_socketpair_nonblocking(sv); 931 ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize, 932 sizeof(sndbufsize))); 933 ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize, 934 sizeof(rcvbufsize))); 935 936 /* 937 * Send and receive packets that are collectively greater than the send 938 * buffer, but less than the receive buffer 939 */ 940 for (i=0; i < numpkts; i++) { 941 /* Fill the buffer */ 942 memset(sndbuf, i, pktsize); 943 944 /* send the packet */ 945 ssize = send(sv[0], sndbuf, pktsize, MSG_EOR); 946 if (ssize < 0) { 947 perror("send"); 948 atf_tc_fail("send returned < 0"); 949 } 950 ATF_CHECK_EQ_MSG(pktsize, ssize, 951 "expected %zd=send(...) but got %zd", pktsize, ssize); 952 953 /* Receive it */ 954 955 rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL); 956 if (rsize < 0) { 957 perror("recv"); 958 atf_tc_fail("recv returned < 0"); 959 } 960 ATF_CHECK_EQ_MSG(pktsize, rsize, 961 "expected %zd=send(...) but got %zd", pktsize, rsize); 962 963 /* Verify the contents */ 964 ATF_CHECK_EQ_MSG(0, memcmp(sndbuf, recv_buf, pktsize), 965 "Received data miscompare"); 966 } 967 968 /* Trying to receive again should return EAGAIN */ 969 rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL); 970 ATF_CHECK_EQ(EAGAIN, errno); 971 ATF_CHECK_EQ(-1, rsize); 972 close(sv[0]); 973 close(sv[1]); 974 } 975 976 /* 977 * Simulate the behavior of a blocking pipe. The sender will send until his 978 * buffer fills up, then we'll simulate a scheduler switch that will allow the 979 * receiver to read until his buffer empties. Repeat the process until the 980 * transfer is complete. 981 * Repeat the test with multiple send and receive buffer sizes 982 */ 983 ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_8k); 984 ATF_TC_BODY(pipe_simulator_8k_8k, tc) 985 { 986 test_pipe_simulator(8192, 8192); 987 } 988 989 ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_128k); 990 ATF_TC_BODY(pipe_simulator_8k_128k, tc) 991 { 992 test_pipe_simulator(8192, 131072); 993 } 994 995 ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_8k); 996 ATF_TC_BODY(pipe_simulator_128k_8k, tc) 997 { 998 test_pipe_simulator(131072, 8192); 999 } 1000 1001 ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_128k); 1002 ATF_TC_BODY(pipe_simulator_128k_128k, tc) 1003 { 1004 test_pipe_simulator(131072, 131072); 1005 } 1006 1007 /* 1008 * Test blocking I/O by passing data between two threads. The total amount of 1009 * data will be >> buffer size to force blocking. Repeat the test with multiple 1010 * send and receive buffer sizes 1011 */ 1012 ATF_TC_WITHOUT_HEAD(pipe_8k_8k); 1013 ATF_TC_BODY(pipe_8k_8k, tc) 1014 { 1015 test_pipe(8192, 8192); 1016 } 1017 1018 ATF_TC_WITHOUT_HEAD(pipe_8k_128k); 1019 ATF_TC_BODY(pipe_8k_128k, tc) 1020 { 1021 test_pipe(8192, 131072); 1022 } 1023 1024 ATF_TC_WITHOUT_HEAD(pipe_128k_8k); 1025 ATF_TC_BODY(pipe_128k_8k, tc) 1026 { 1027 test_pipe(131072, 8192); 1028 } 1029 1030 ATF_TC_WITHOUT_HEAD(pipe_128k_128k); 1031 ATF_TC_BODY(pipe_128k_128k, tc) 1032 { 1033 test_pipe(131072, 131072); 1034 } 1035 1036 1037 /* 1038 * Test single-packet I/O with and without blocking, with symmetric buffers of 1039 * various sizes 1040 */ 1041 ATF_TC_WITHOUT_HEAD(sendrecv_8k); 1042 ATF_TC_BODY(sendrecv_8k, tc) 1043 { 1044 test_sendrecv_symmetric_buffers(8 * 1024, true); 1045 } 1046 ATF_TC_WITHOUT_HEAD(sendrecv_16k); 1047 ATF_TC_BODY(sendrecv_16k, tc) 1048 { 1049 test_sendrecv_symmetric_buffers(16 * 1024, true); 1050 } 1051 ATF_TC_WITHOUT_HEAD(sendrecv_32k); 1052 ATF_TC_BODY(sendrecv_32k, tc) 1053 { 1054 test_sendrecv_symmetric_buffers(32 * 1024, true); 1055 } 1056 ATF_TC_WITHOUT_HEAD(sendrecv_64k); 1057 ATF_TC_BODY(sendrecv_64k, tc) 1058 { 1059 test_sendrecv_symmetric_buffers(64 * 1024, true); 1060 } 1061 ATF_TC_WITHOUT_HEAD(sendrecv_128k); 1062 ATF_TC_BODY(sendrecv_128k, tc) 1063 { 1064 test_sendrecv_symmetric_buffers(128 * 1024, true); 1065 } 1066 ATF_TC_WITHOUT_HEAD(sendrecv_8k_nonblocking); 1067 ATF_TC_BODY(sendrecv_8k_nonblocking, tc) 1068 { 1069 test_sendrecv_symmetric_buffers(8 * 1024, false); 1070 } 1071 ATF_TC_WITHOUT_HEAD(sendrecv_16k_nonblocking); 1072 ATF_TC_BODY(sendrecv_16k_nonblocking, tc) 1073 { 1074 test_sendrecv_symmetric_buffers(16 * 1024, false); 1075 } 1076 ATF_TC_WITHOUT_HEAD(sendrecv_32k_nonblocking); 1077 ATF_TC_BODY(sendrecv_32k_nonblocking, tc) 1078 { 1079 test_sendrecv_symmetric_buffers(32 * 1024, false); 1080 } 1081 ATF_TC_WITHOUT_HEAD(sendrecv_64k_nonblocking); 1082 ATF_TC_BODY(sendrecv_64k_nonblocking, tc) 1083 { 1084 test_sendrecv_symmetric_buffers(64 * 1024, false); 1085 } 1086 ATF_TC_WITHOUT_HEAD(sendrecv_128k_nonblocking); 1087 ATF_TC_BODY(sendrecv_128k_nonblocking, tc) 1088 { 1089 test_sendrecv_symmetric_buffers(128 * 1024, false); 1090 } 1091 1092 1093 /* 1094 * Main. 1095 */ 1096 1097 ATF_TP_ADD_TCS(tp) 1098 { 1099 /* Basic creation and connection tests */ 1100 ATF_TP_ADD_TC(tp, create_socket); 1101 ATF_TP_ADD_TC(tp, create_socketpair); 1102 ATF_TP_ADD_TC(tp, listen_unbound); 1103 ATF_TP_ADD_TC(tp, bind); 1104 ATF_TP_ADD_TC(tp, listen_bound); 1105 ATF_TP_ADD_TC(tp, connect); 1106 ATF_TP_ADD_TC(tp, accept); 1107 ATF_TP_ADD_TC(tp, fcntl_nonblock); 1108 ATF_TP_ADD_TC(tp, resize_buffers); 1109 ATF_TP_ADD_TC(tp, resize_connected_buffers); 1110 1111 /* Unthreaded I/O tests */ 1112 ATF_TP_ADD_TC(tp, send_recv); 1113 ATF_TP_ADD_TC(tp, send_recv_nonblocking); 1114 ATF_TP_ADD_TC(tp, send_recv_with_connect); 1115 ATF_TP_ADD_TC(tp, sendto_recvfrom); 1116 ATF_TP_ADD_TC(tp, send_before_accept); 1117 ATF_TP_ADD_TC(tp, implied_connect); 1118 ATF_TP_ADD_TC(tp, shutdown_send); 1119 ATF_TP_ADD_TC(tp, shutdown_send_sigpipe); 1120 ATF_TP_ADD_TC(tp, eagain_8k_8k); 1121 ATF_TP_ADD_TC(tp, eagain_8k_128k); 1122 ATF_TP_ADD_TC(tp, eagain_128k_8k); 1123 ATF_TP_ADD_TC(tp, eagain_128k_128k); 1124 ATF_TP_ADD_TC(tp, sendrecv_8k); 1125 ATF_TP_ADD_TC(tp, sendrecv_16k); 1126 ATF_TP_ADD_TC(tp, sendrecv_32k); 1127 ATF_TP_ADD_TC(tp, sendrecv_64k); 1128 ATF_TP_ADD_TC(tp, sendrecv_128k); 1129 ATF_TP_ADD_TC(tp, sendrecv_8k_nonblocking); 1130 ATF_TP_ADD_TC(tp, sendrecv_16k_nonblocking); 1131 ATF_TP_ADD_TC(tp, sendrecv_32k_nonblocking); 1132 ATF_TP_ADD_TC(tp, sendrecv_64k_nonblocking); 1133 ATF_TP_ADD_TC(tp, sendrecv_128k_nonblocking); 1134 ATF_TP_ADD_TC(tp, rcvbuf_oversized); 1135 ATF_TP_ADD_TC(tp, pipe_simulator_8k_8k); 1136 ATF_TP_ADD_TC(tp, pipe_simulator_8k_128k); 1137 ATF_TP_ADD_TC(tp, pipe_simulator_128k_8k); 1138 ATF_TP_ADD_TC(tp, pipe_simulator_128k_128k); 1139 1140 /* Threaded I/O tests with blocking sockets */ 1141 ATF_TP_ADD_TC(tp, pipe_8k_8k); 1142 ATF_TP_ADD_TC(tp, pipe_8k_128k); 1143 ATF_TP_ADD_TC(tp, pipe_128k_8k); 1144 ATF_TP_ADD_TC(tp, pipe_128k_128k); 1145 1146 return atf_no_error(); 1147 } 1148