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