1 /*- 2 * Copyright (c) 2018 The FreeBSD Foundation 3 * 4 * This software was developed by Mark Johnston under sponsorship from 5 * the FreeBSD Foundation. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are 9 * met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided with the 15 * distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/param.h> 31 #include <sys/event.h> 32 #include <sys/filio.h> 33 #include <sys/ioccom.h> 34 #include <sys/socket.h> 35 36 #include <netinet/in.h> 37 #include <netinet/tcp.h> 38 39 #include <err.h> 40 #include <errno.h> 41 #include <pthread.h> 42 #include <stdatomic.h> 43 #include <stdlib.h> 44 #include <unistd.h> 45 46 #include <atf-c.h> 47 48 /* 49 * Given an array of non-blocking listening sockets configured in a LB group 50 * for "addr", try connecting to "addr" in a loop and verify that connections 51 * are roughly balanced across the sockets. 52 */ 53 static void 54 lb_simple_accept_loop(int domain, const struct sockaddr *addr, int sds[], 55 size_t nsds, int nconns) 56 { 57 size_t i; 58 int *acceptcnt; 59 int csd, error, excnt, sd; 60 const struct linger lopt = { 1, 0 }; 61 62 /* 63 * We expect each listening socket to accept roughly nconns/nsds 64 * connections, but allow for some error. 65 */ 66 excnt = nconns / nsds / 8; 67 acceptcnt = calloc(nsds, sizeof(*acceptcnt)); 68 ATF_REQUIRE_MSG(acceptcnt != NULL, "calloc() failed: %s", 69 strerror(errno)); 70 71 while (nconns-- > 0) { 72 sd = socket(domain, SOCK_STREAM, 0); 73 ATF_REQUIRE_MSG(sd >= 0, "socket() failed: %s", 74 strerror(errno)); 75 76 error = connect(sd, addr, addr->sa_len); 77 ATF_REQUIRE_MSG(error == 0, "connect() failed: %s", 78 strerror(errno)); 79 80 error = setsockopt(sd, SOL_SOCKET, SO_LINGER, &lopt, sizeof(lopt)); 81 ATF_REQUIRE_MSG(error == 0, "Setting linger failed: %s", 82 strerror(errno)); 83 84 /* 85 * Poll the listening sockets. 86 */ 87 do { 88 for (i = 0; i < nsds; i++) { 89 csd = accept(sds[i], NULL, NULL); 90 if (csd < 0) { 91 ATF_REQUIRE_MSG(errno == EWOULDBLOCK || 92 errno == EAGAIN, 93 "accept() failed: %s", 94 strerror(errno)); 95 continue; 96 } 97 98 error = close(csd); 99 ATF_REQUIRE_MSG(error == 0, 100 "close() failed: %s", strerror(errno)); 101 102 acceptcnt[i]++; 103 break; 104 } 105 } while (i == nsds); 106 107 error = close(sd); 108 ATF_REQUIRE_MSG(error == 0, "close() failed: %s", 109 strerror(errno)); 110 } 111 112 for (i = 0; i < nsds; i++) 113 ATF_REQUIRE_MSG(acceptcnt[i] > excnt, "uneven balancing"); 114 } 115 116 static int 117 lb_listen_socket(int domain, int flags) 118 { 119 int one; 120 int error, sd; 121 122 sd = socket(domain, SOCK_STREAM | flags, 0); 123 ATF_REQUIRE_MSG(sd >= 0, "socket() failed: %s", strerror(errno)); 124 125 one = 1; 126 error = setsockopt(sd, SOL_SOCKET, SO_REUSEPORT_LB, &one, sizeof(one)); 127 ATF_REQUIRE_MSG(error == 0, "setsockopt(SO_REUSEPORT_LB) failed: %s", 128 strerror(errno)); 129 130 return (sd); 131 } 132 133 ATF_TC_WITHOUT_HEAD(basic_ipv4); 134 ATF_TC_BODY(basic_ipv4, tc) 135 { 136 struct sockaddr_in addr; 137 socklen_t slen; 138 size_t i; 139 const int nconns = 16384; 140 int error, sds[16]; 141 uint16_t port; 142 143 sds[0] = lb_listen_socket(PF_INET, SOCK_NONBLOCK); 144 145 memset(&addr, 0, sizeof(addr)); 146 addr.sin_len = sizeof(addr); 147 addr.sin_family = AF_INET; 148 addr.sin_port = htons(0); 149 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 150 error = bind(sds[0], (const struct sockaddr *)&addr, sizeof(addr)); 151 ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno)); 152 error = listen(sds[0], 1); 153 ATF_REQUIRE_MSG(error == 0, "listen() failed: %s", strerror(errno)); 154 155 slen = sizeof(addr); 156 error = getsockname(sds[0], (struct sockaddr *)&addr, &slen); 157 ATF_REQUIRE_MSG(error == 0, "getsockname() failed: %s", 158 strerror(errno)); 159 ATF_REQUIRE_MSG(slen == sizeof(addr), "sockaddr size changed"); 160 port = addr.sin_port; 161 162 memset(&addr, 0, sizeof(addr)); 163 addr.sin_len = sizeof(addr); 164 addr.sin_family = AF_INET; 165 addr.sin_port = port; 166 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 167 for (i = 1; i < nitems(sds); i++) { 168 sds[i] = lb_listen_socket(PF_INET, SOCK_NONBLOCK); 169 170 error = bind(sds[i], (const struct sockaddr *)&addr, 171 sizeof(addr)); 172 ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", 173 strerror(errno)); 174 error = listen(sds[i], 1); 175 ATF_REQUIRE_MSG(error == 0, "listen() failed: %s", 176 strerror(errno)); 177 } 178 179 lb_simple_accept_loop(PF_INET, (struct sockaddr *)&addr, sds, 180 nitems(sds), nconns); 181 for (i = 0; i < nitems(sds); i++) { 182 error = close(sds[i]); 183 ATF_REQUIRE_MSG(error == 0, "close() failed: %s", 184 strerror(errno)); 185 } 186 } 187 188 ATF_TC_WITHOUT_HEAD(basic_ipv6); 189 ATF_TC_BODY(basic_ipv6, tc) 190 { 191 const struct in6_addr loopback6 = IN6ADDR_LOOPBACK_INIT; 192 struct sockaddr_in6 addr; 193 socklen_t slen; 194 size_t i; 195 const int nconns = 16384; 196 int error, sds[16]; 197 uint16_t port; 198 199 sds[0] = lb_listen_socket(PF_INET6, SOCK_NONBLOCK); 200 201 memset(&addr, 0, sizeof(addr)); 202 addr.sin6_len = sizeof(addr); 203 addr.sin6_family = AF_INET6; 204 addr.sin6_port = htons(0); 205 addr.sin6_addr = loopback6; 206 error = bind(sds[0], (const struct sockaddr *)&addr, sizeof(addr)); 207 ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno)); 208 error = listen(sds[0], 1); 209 ATF_REQUIRE_MSG(error == 0, "listen() failed: %s", strerror(errno)); 210 211 slen = sizeof(addr); 212 error = getsockname(sds[0], (struct sockaddr *)&addr, &slen); 213 ATF_REQUIRE_MSG(error == 0, "getsockname() failed: %s", 214 strerror(errno)); 215 ATF_REQUIRE_MSG(slen == sizeof(addr), "sockaddr size changed"); 216 port = addr.sin6_port; 217 218 memset(&addr, 0, sizeof(addr)); 219 addr.sin6_len = sizeof(addr); 220 addr.sin6_family = AF_INET6; 221 addr.sin6_port = port; 222 addr.sin6_addr = loopback6; 223 for (i = 1; i < nitems(sds); i++) { 224 sds[i] = lb_listen_socket(PF_INET6, SOCK_NONBLOCK); 225 226 error = bind(sds[i], (const struct sockaddr *)&addr, 227 sizeof(addr)); 228 ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", 229 strerror(errno)); 230 error = listen(sds[i], 1); 231 ATF_REQUIRE_MSG(error == 0, "listen() failed: %s", 232 strerror(errno)); 233 } 234 235 lb_simple_accept_loop(PF_INET6, (struct sockaddr *)&addr, sds, 236 nitems(sds), nconns); 237 for (i = 0; i < nitems(sds); i++) { 238 error = close(sds[i]); 239 ATF_REQUIRE_MSG(error == 0, "close() failed: %s", 240 strerror(errno)); 241 } 242 } 243 244 struct concurrent_add_softc { 245 struct sockaddr_storage ss; 246 int socks[128]; 247 int kq; 248 }; 249 250 static void * 251 listener(void *arg) 252 { 253 for (struct concurrent_add_softc *sc = arg;;) { 254 struct kevent kev; 255 ssize_t n; 256 int error, count, cs, s; 257 uint8_t b; 258 259 count = kevent(sc->kq, NULL, 0, &kev, 1, NULL); 260 ATF_REQUIRE_MSG(count == 1, 261 "kevent() failed: %s", strerror(errno)); 262 263 s = (int)kev.ident; 264 cs = accept(s, NULL, NULL); 265 ATF_REQUIRE_MSG(cs >= 0, 266 "accept() failed: %s", strerror(errno)); 267 268 b = 'M'; 269 n = write(cs, &b, sizeof(b)); 270 ATF_REQUIRE_MSG(n >= 0, "write() failed: %s", strerror(errno)); 271 ATF_REQUIRE(n == 1); 272 273 error = close(cs); 274 ATF_REQUIRE_MSG(error == 0 || errno == ECONNRESET, 275 "close() failed: %s", strerror(errno)); 276 } 277 } 278 279 static void * 280 connector(void *arg) 281 { 282 for (struct concurrent_add_softc *sc = arg;;) { 283 ssize_t n; 284 int error, s; 285 uint8_t b; 286 287 s = socket(sc->ss.ss_family, SOCK_STREAM, 0); 288 ATF_REQUIRE_MSG(s >= 0, "socket() failed: %s", strerror(errno)); 289 290 error = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (int[]){1}, 291 sizeof(int)); 292 293 error = connect(s, (struct sockaddr *)&sc->ss, sc->ss.ss_len); 294 ATF_REQUIRE_MSG(error == 0, "connect() failed: %s", 295 strerror(errno)); 296 297 n = read(s, &b, sizeof(b)); 298 ATF_REQUIRE_MSG(n >= 0, "read() failed: %s", 299 strerror(errno)); 300 ATF_REQUIRE(n == 1); 301 ATF_REQUIRE(b == 'M'); 302 error = close(s); 303 ATF_REQUIRE_MSG(error == 0, 304 "close() failed: %s", strerror(errno)); 305 } 306 } 307 308 /* 309 * Run three threads. One accepts connections from listening sockets on a 310 * kqueue, while the other makes connections. The third thread slowly adds 311 * sockets to the LB group. This is meant to help flush out race conditions. 312 */ 313 ATF_TC_WITHOUT_HEAD(concurrent_add); 314 ATF_TC_BODY(concurrent_add, tc) 315 { 316 struct concurrent_add_softc sc; 317 struct sockaddr_in *sin; 318 pthread_t threads[4]; 319 int error; 320 321 sc.kq = kqueue(); 322 ATF_REQUIRE_MSG(sc.kq >= 0, "kqueue() failed: %s", strerror(errno)); 323 324 error = pthread_create(&threads[0], NULL, listener, &sc); 325 ATF_REQUIRE_MSG(error == 0, "pthread_create() failed: %s", 326 strerror(error)); 327 328 sin = (struct sockaddr_in *)&sc.ss; 329 memset(sin, 0, sizeof(*sin)); 330 sin->sin_len = sizeof(*sin); 331 sin->sin_family = AF_INET; 332 sin->sin_port = htons(0); 333 sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK); 334 335 for (size_t i = 0; i < nitems(sc.socks); i++) { 336 struct kevent kev; 337 int s; 338 339 sc.socks[i] = s = socket(AF_INET, SOCK_STREAM, 0); 340 ATF_REQUIRE_MSG(s >= 0, "socket() failed: %s", strerror(errno)); 341 342 error = setsockopt(s, SOL_SOCKET, SO_REUSEPORT_LB, (int[]){1}, 343 sizeof(int)); 344 ATF_REQUIRE_MSG(error == 0, 345 "setsockopt(SO_REUSEPORT_LB) failed: %s", strerror(errno)); 346 347 error = bind(s, (struct sockaddr *)sin, sizeof(*sin)); 348 ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", 349 strerror(errno)); 350 351 error = listen(s, 5); 352 ATF_REQUIRE_MSG(error == 0, "listen() failed: %s", 353 strerror(errno)); 354 355 EV_SET(&kev, s, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); 356 error = kevent(sc.kq, &kev, 1, NULL, 0, NULL); 357 ATF_REQUIRE_MSG(error == 0, "kevent() failed: %s", 358 strerror(errno)); 359 360 if (i == 0) { 361 socklen_t slen = sizeof(sc.ss); 362 363 error = getsockname(sc.socks[i], 364 (struct sockaddr *)&sc.ss, &slen); 365 ATF_REQUIRE_MSG(error == 0, "getsockname() failed: %s", 366 strerror(errno)); 367 ATF_REQUIRE(sc.ss.ss_family == AF_INET); 368 369 for (size_t j = 1; j < nitems(threads); j++) { 370 error = pthread_create(&threads[j], NULL, 371 connector, &sc); 372 ATF_REQUIRE_MSG(error == 0, 373 "pthread_create() failed: %s", 374 strerror(error)); 375 } 376 } 377 378 usleep(20000); 379 } 380 381 for (size_t j = nitems(threads); j > 0; j--) { 382 ATF_REQUIRE(pthread_cancel(threads[j - 1]) == 0); 383 ATF_REQUIRE(pthread_join(threads[j - 1], NULL) == 0); 384 } 385 } 386 387 /* 388 * Try calling listen(2) twice on a socket with SO_REUSEPORT_LB set. 389 */ 390 ATF_TC_WITHOUT_HEAD(double_listen_ipv4); 391 ATF_TC_BODY(double_listen_ipv4, tc) 392 { 393 struct sockaddr_in sin; 394 int error, s; 395 396 s = lb_listen_socket(PF_INET, 0); 397 398 memset(&sin, 0, sizeof(sin)); 399 sin.sin_len = sizeof(sin); 400 sin.sin_family = AF_INET; 401 sin.sin_port = htons(0); 402 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 403 error = bind(s, (struct sockaddr *)&sin, sizeof(sin)); 404 ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno)); 405 406 error = listen(s, 1); 407 ATF_REQUIRE_MSG(error == 0, "listen() failed: %s", strerror(errno)); 408 error = listen(s, 2); 409 ATF_REQUIRE_MSG(error == 0, "listen() failed: %s", strerror(errno)); 410 411 error = close(s); 412 ATF_REQUIRE_MSG(error == 0, "close() failed: %s", strerror(errno)); 413 } 414 415 /* 416 * Try calling listen(2) twice on a socket with SO_REUSEPORT_LB set. 417 */ 418 ATF_TC_WITHOUT_HEAD(double_listen_ipv6); 419 ATF_TC_BODY(double_listen_ipv6, tc) 420 { 421 struct sockaddr_in6 sin6; 422 int error, s; 423 424 s = lb_listen_socket(PF_INET6, 0); 425 426 memset(&sin6, 0, sizeof(sin6)); 427 sin6.sin6_len = sizeof(sin6); 428 sin6.sin6_family = AF_INET6; 429 sin6.sin6_port = htons(0); 430 sin6.sin6_addr = in6addr_loopback; 431 error = bind(s, (struct sockaddr *)&sin6, sizeof(sin6)); 432 ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno)); 433 434 error = listen(s, 1); 435 ATF_REQUIRE_MSG(error == 0, "listen() failed: %s", strerror(errno)); 436 error = listen(s, 2); 437 ATF_REQUIRE_MSG(error == 0, "listen() failed: %s", strerror(errno)); 438 439 error = close(s); 440 ATF_REQUIRE_MSG(error == 0, "close() failed: %s", strerror(errno)); 441 } 442 443 /* 444 * Try binding many sockets to the same lbgroup without calling listen(2) on 445 * them. 446 */ 447 ATF_TC_WITHOUT_HEAD(bind_without_listen); 448 ATF_TC_BODY(bind_without_listen, tc) 449 { 450 const int nsockets = 100; 451 struct sockaddr_in sin; 452 socklen_t socklen; 453 int error, s, s2[nsockets]; 454 455 s = lb_listen_socket(PF_INET, 0); 456 457 memset(&sin, 0, sizeof(sin)); 458 sin.sin_len = sizeof(sin); 459 sin.sin_family = AF_INET; 460 sin.sin_port = htons(0); 461 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 462 error = bind(s, (struct sockaddr *)&sin, sizeof(sin)); 463 ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno)); 464 465 socklen = sizeof(sin); 466 error = getsockname(s, (struct sockaddr *)&sin, &socklen); 467 ATF_REQUIRE_MSG(error == 0, "getsockname() failed: %s", 468 strerror(errno)); 469 470 for (int i = 0; i < nsockets; i++) { 471 s2[i] = lb_listen_socket(PF_INET, 0); 472 error = bind(s2[i], (struct sockaddr *)&sin, sizeof(sin)); 473 ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno)); 474 } 475 for (int i = 0; i < nsockets; i++) { 476 error = listen(s2[i], 1); 477 ATF_REQUIRE_MSG(error == 0, "listen() failed: %s", strerror(errno)); 478 } 479 for (int i = 0; i < nsockets; i++) { 480 error = close(s2[i]); 481 ATF_REQUIRE_MSG(error == 0, "close() failed: %s", strerror(errno)); 482 } 483 484 error = close(s); 485 ATF_REQUIRE_MSG(error == 0, "close() failed: %s", strerror(errno)); 486 } 487 488 /* 489 * Check that SO_REUSEPORT_LB doesn't mess with connect(2). 490 * Two sockets: 491 * 1) auxiliary peer socket 'p', where we connect to 492 * 2) test socket 's', that sets SO_REUSEPORT_LB and then connect(2)s to 'p' 493 */ 494 ATF_TC_WITHOUT_HEAD(connect_not_bound); 495 ATF_TC_BODY(connect_not_bound, tc) 496 { 497 struct sockaddr_in sin = { 498 .sin_family = AF_INET, 499 .sin_len = sizeof(sin), 500 .sin_addr = { htonl(INADDR_LOOPBACK) }, 501 }; 502 socklen_t slen = sizeof(struct sockaddr_in); 503 int p, s, rv; 504 505 ATF_REQUIRE((p = socket(PF_INET, SOCK_STREAM, 0)) > 0); 506 ATF_REQUIRE(bind(p, (struct sockaddr *)&sin, sizeof(sin)) == 0); 507 ATF_REQUIRE(listen(p, 1) == 0); 508 ATF_REQUIRE(getsockname(p, (struct sockaddr *)&sin, &slen) == 0); 509 510 s = lb_listen_socket(PF_INET, 0); 511 rv = connect(s, (struct sockaddr *)&sin, sizeof(sin)); 512 ATF_REQUIRE_MSG(rv == -1 && errno == EOPNOTSUPP, 513 "Expected EOPNOTSUPP on connect(2) not met. Got %d, errno %d", 514 rv, errno); 515 rv = sendto(s, "test", 4, 0, (struct sockaddr *)&sin, 516 sizeof(sin)); 517 ATF_REQUIRE_MSG(rv == -1 && errno == EOPNOTSUPP, 518 "Expected EOPNOTSUPP on sendto(2) not met. Got %d, errno %d", 519 rv, errno); 520 521 close(p); 522 close(s); 523 } 524 525 /* 526 * Same as above, but we also bind(2) between setsockopt(2) of SO_REUSEPORT_LB 527 * and the connect(2). 528 */ 529 ATF_TC_WITHOUT_HEAD(connect_bound); 530 ATF_TC_BODY(connect_bound, tc) 531 { 532 struct sockaddr_in sin = { 533 .sin_family = AF_INET, 534 .sin_len = sizeof(sin), 535 .sin_addr = { htonl(INADDR_LOOPBACK) }, 536 }; 537 socklen_t slen = sizeof(struct sockaddr_in); 538 int p, s, rv; 539 540 ATF_REQUIRE((p = socket(PF_INET, SOCK_STREAM, 0)) > 0); 541 ATF_REQUIRE(bind(p, (struct sockaddr *)&sin, sizeof(sin)) == 0); 542 ATF_REQUIRE(listen(p, 1) == 0); 543 544 s = lb_listen_socket(PF_INET, 0); 545 ATF_REQUIRE(bind(s, (struct sockaddr *)&sin, sizeof(sin)) == 0); 546 ATF_REQUIRE(getsockname(p, (struct sockaddr *)&sin, &slen) == 0); 547 rv = connect(s, (struct sockaddr *)&sin, sizeof(sin)); 548 ATF_REQUIRE_MSG(rv == -1 && errno == EOPNOTSUPP, 549 "Expected EOPNOTSUPP on connect(2) not met. Got %d, errno %d", 550 rv, errno); 551 rv = sendto(s, "test", 4, 0, (struct sockaddr *)&sin, 552 sizeof(sin)); 553 ATF_REQUIRE_MSG(rv == -1 && errno == EOPNOTSUPP, 554 "Expected EOPNOTSUPP on sendto(2) not met. Got %d, errno %d", 555 rv, errno); 556 557 close(p); 558 close(s); 559 } 560 561 /* 562 * The kernel erroneously permits calling connect() on a UDP socket with 563 * SO_REUSEPORT_LB set. Verify that packets sent to the bound address are 564 * dropped unless they come from the connected address. 565 */ 566 ATF_TC_WITHOUT_HEAD(connect_udp); 567 ATF_TC_BODY(connect_udp, tc) 568 { 569 struct sockaddr_in sin = { 570 .sin_family = AF_INET, 571 .sin_len = sizeof(sin), 572 .sin_addr = { htonl(INADDR_LOOPBACK) }, 573 }; 574 ssize_t n; 575 int error, len, s1, s2, s3; 576 char ch; 577 578 s1 = socket(PF_INET, SOCK_DGRAM, 0); 579 ATF_REQUIRE(s1 >= 0); 580 s2 = socket(PF_INET, SOCK_DGRAM, 0); 581 ATF_REQUIRE(s2 >= 0); 582 s3 = socket(PF_INET, SOCK_DGRAM, 0); 583 ATF_REQUIRE(s3 >= 0); 584 585 error = setsockopt(s1, SOL_SOCKET, SO_REUSEPORT_LB, (int[]){1}, 586 sizeof(int)); 587 ATF_REQUIRE_MSG(error == 0, 588 "setsockopt(SO_REUSEPORT_LB) failed: %s", strerror(errno)); 589 error = bind(s1, (struct sockaddr *)&sin, sizeof(sin)); 590 ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno)); 591 592 error = bind(s2, (struct sockaddr *)&sin, sizeof(sin)); 593 ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno)); 594 595 error = bind(s3, (struct sockaddr *)&sin, sizeof(sin)); 596 ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno)); 597 598 /* Connect to an address not owned by s2. */ 599 error = getsockname(s3, (struct sockaddr *)&sin, 600 (socklen_t[]){sizeof(sin)}); 601 ATF_REQUIRE(error == 0); 602 error = connect(s1, (struct sockaddr *)&sin, sizeof(sin)); 603 ATF_REQUIRE_MSG(error == 0, "connect() failed: %s", strerror(errno)); 604 605 /* Try to send a packet to s1 from s2. */ 606 error = getsockname(s1, (struct sockaddr *)&sin, 607 (socklen_t[]){sizeof(sin)}); 608 ATF_REQUIRE(error == 0); 609 610 ch = 42; 611 n = sendto(s2, &ch, sizeof(ch), 0, (struct sockaddr *)&sin, 612 sizeof(sin)); 613 ATF_REQUIRE(n == 1); 614 615 /* Give the packet some time to arrive. */ 616 usleep(100000); 617 618 /* s1 is connected to s3 and shouldn't receive from s2. */ 619 error = ioctl(s1, FIONREAD, &len); 620 ATF_REQUIRE(error == 0); 621 ATF_REQUIRE_MSG(len == 0, "unexpected data available"); 622 623 /* ... but s3 can of course send to s1. */ 624 n = sendto(s3, &ch, sizeof(ch), 0, (struct sockaddr *)&sin, 625 sizeof(sin)); 626 ATF_REQUIRE(n == 1); 627 usleep(100000); 628 error = ioctl(s1, FIONREAD, &len); 629 ATF_REQUIRE(error == 0); 630 ATF_REQUIRE_MSG(len == 1, "expected data available"); 631 } 632 633 /* 634 * The kernel erroneously permits calling connect() on a UDP socket with 635 * SO_REUSEPORT_LB set. Verify that packets sent to the bound address are 636 * dropped unless they come from the connected address. 637 */ 638 ATF_TC_WITHOUT_HEAD(connect_udp6); 639 ATF_TC_BODY(connect_udp6, tc) 640 { 641 struct sockaddr_in6 sin6 = { 642 .sin6_family = AF_INET6, 643 .sin6_len = sizeof(sin6), 644 .sin6_addr = IN6ADDR_LOOPBACK_INIT, 645 }; 646 ssize_t n; 647 int error, len, s1, s2, s3; 648 char ch; 649 650 s1 = socket(PF_INET6, SOCK_DGRAM, 0); 651 ATF_REQUIRE(s1 >= 0); 652 s2 = socket(PF_INET6, SOCK_DGRAM, 0); 653 ATF_REQUIRE(s2 >= 0); 654 s3 = socket(PF_INET6, SOCK_DGRAM, 0); 655 ATF_REQUIRE(s3 >= 0); 656 657 error = setsockopt(s1, SOL_SOCKET, SO_REUSEPORT_LB, (int[]){1}, 658 sizeof(int)); 659 ATF_REQUIRE_MSG(error == 0, 660 "setsockopt(SO_REUSEPORT_LB) failed: %s", strerror(errno)); 661 error = bind(s1, (struct sockaddr *)&sin6, sizeof(sin6)); 662 ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno)); 663 664 error = bind(s2, (struct sockaddr *)&sin6, sizeof(sin6)); 665 ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno)); 666 667 error = bind(s3, (struct sockaddr *)&sin6, sizeof(sin6)); 668 ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno)); 669 670 /* Connect to an address not owned by s2. */ 671 error = getsockname(s3, (struct sockaddr *)&sin6, 672 (socklen_t[]){sizeof(sin6)}); 673 ATF_REQUIRE(error == 0); 674 error = connect(s1, (struct sockaddr *)&sin6, sizeof(sin6)); 675 ATF_REQUIRE_MSG(error == 0, "connect() failed: %s", strerror(errno)); 676 677 /* Try to send a packet to s1 from s2. */ 678 error = getsockname(s1, (struct sockaddr *)&sin6, 679 (socklen_t[]){sizeof(sin6)}); 680 ATF_REQUIRE(error == 0); 681 682 ch = 42; 683 n = sendto(s2, &ch, sizeof(ch), 0, (struct sockaddr *)&sin6, 684 sizeof(sin6)); 685 ATF_REQUIRE(n == 1); 686 687 /* Give the packet some time to arrive. */ 688 usleep(100000); 689 690 /* s1 is connected to s3 and shouldn't receive from s2. */ 691 error = ioctl(s1, FIONREAD, &len); 692 ATF_REQUIRE(error == 0); 693 ATF_REQUIRE_MSG(len == 0, "unexpected data available"); 694 695 /* ... but s3 can of course send to s1. */ 696 n = sendto(s3, &ch, sizeof(ch), 0, (struct sockaddr *)&sin6, 697 sizeof(sin6)); 698 ATF_REQUIRE(n == 1); 699 usleep(100000); 700 error = ioctl(s1, FIONREAD, &len); 701 ATF_REQUIRE(error == 0); 702 ATF_REQUIRE_MSG(len == 1, "expected data available"); 703 } 704 705 ATF_TP_ADD_TCS(tp) 706 { 707 ATF_TP_ADD_TC(tp, basic_ipv4); 708 ATF_TP_ADD_TC(tp, basic_ipv6); 709 ATF_TP_ADD_TC(tp, concurrent_add); 710 ATF_TP_ADD_TC(tp, double_listen_ipv4); 711 ATF_TP_ADD_TC(tp, double_listen_ipv6); 712 ATF_TP_ADD_TC(tp, bind_without_listen); 713 ATF_TP_ADD_TC(tp, connect_not_bound); 714 ATF_TP_ADD_TC(tp, connect_bound); 715 ATF_TP_ADD_TC(tp, connect_udp); 716 ATF_TP_ADD_TC(tp, connect_udp6); 717 718 return (atf_no_error()); 719 } 720