1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2024-2025 Stormshield 5 */ 6 7 #include <sys/types.h> 8 #include <sys/ioctl.h> 9 #include <sys/socket.h> 10 #include <sys/sysctl.h> 11 12 #include <netinet/in.h> 13 #include <netinet/ip.h> 14 #include <netinet/ip6.h> 15 #include <netinet/ip_icmp.h> 16 #include <netinet/icmp6.h> 17 18 #include <errno.h> 19 #include <fcntl.h> 20 #include <pwd.h> 21 #include <stdio.h> 22 #include <string.h> 23 24 #include <atf-c.h> 25 26 #define MAKETEST_TCP(name) \ 27 ATF_TC_WITHOUT_HEAD(name ## _tcp); \ 28 ATF_TC_BODY(name ## _tcp, tc) \ 29 { \ 30 name(PF_INET, SOCK_STREAM, tc); \ 31 } \ 32 ATF_TC_WITHOUT_HEAD(name ## _tcp6); \ 33 ATF_TC_BODY(name ## _tcp6, tc) \ 34 { \ 35 name(PF_INET6, SOCK_STREAM, tc); \ 36 } 37 #define MAKETEST_UDP(name) \ 38 ATF_TC_WITHOUT_HEAD(name ## _udp); \ 39 ATF_TC_BODY(name ## _udp, tc) \ 40 { \ 41 name(PF_INET, SOCK_DGRAM, tc); \ 42 } \ 43 ATF_TC_WITHOUT_HEAD(name ## _udp6); \ 44 ATF_TC_BODY(name ## _udp6, tc) \ 45 { \ 46 name(PF_INET6, SOCK_DGRAM, tc); \ 47 } 48 #define MAKETEST_RAW(name) \ 49 ATF_TC(name ## _raw); \ 50 ATF_TC_HEAD(name ## _raw, tc) \ 51 { \ 52 atf_tc_set_md_var(tc, "require.user", \ 53 "root"); \ 54 } \ 55 ATF_TC_BODY(name ## _raw, tc) \ 56 { \ 57 name(PF_INET, SOCK_RAW, tc); \ 58 } \ 59 ATF_TC(name ## _raw6); \ 60 ATF_TC_HEAD(name ## _raw6, tc) \ 61 { \ 62 atf_tc_set_md_var(tc, "require.user", \ 63 "root"); \ 64 } \ 65 ATF_TC_BODY(name ## _raw6, tc) \ 66 { \ 67 name(PF_INET6, SOCK_RAW, tc); \ 68 } 69 70 #define MAKETEST(name) \ 71 MAKETEST_TCP(name) \ 72 MAKETEST_UDP(name) 73 74 #define LISTTEST_TCP(name) \ 75 ATF_TP_ADD_TC(tp, name ## _tcp); \ 76 ATF_TP_ADD_TC(tp, name ## _tcp6); 77 #define LISTTEST_UDP(name) \ 78 ATF_TP_ADD_TC(tp, name ## _udp); \ 79 ATF_TP_ADD_TC(tp, name ## _udp6); 80 #define LISTTEST_RAW(name) \ 81 ATF_TP_ADD_TC(tp, name ## _raw); \ 82 ATF_TP_ADD_TC(tp, name ## _raw6); 83 #define LISTTEST(name) \ 84 LISTTEST_TCP(name) \ 85 LISTTEST_UDP(name) 86 87 static void 88 checked_close(int s) 89 { 90 int error; 91 92 error = close(s); 93 ATF_REQUIRE_MSG(error == 0, "close failed: %s", strerror(errno)); 94 } 95 96 static int 97 mksockp(int domain, int type, int fib, int proto) 98 { 99 int error, s; 100 101 s = socket(domain, type, proto); 102 ATF_REQUIRE(s != -1); 103 error = setsockopt(s, SOL_SOCKET, SO_SETFIB, &fib, sizeof(fib)); 104 ATF_REQUIRE_MSG(error == 0, "setsockopt failed: %s", strerror(errno)); 105 106 return (s); 107 } 108 109 static int 110 mksock(int domain, int type, int fib) 111 { 112 return (mksockp(domain, type, fib, 0)); 113 } 114 115 static void 116 require_fibs_multibind(int socktype, int minfibs) 117 { 118 const char *sysctl; 119 size_t sz; 120 int error, fibs, multibind; 121 122 fibs = 0; 123 sz = sizeof(fibs); 124 error = sysctlbyname("net.fibs", &fibs, &sz, NULL, 0); 125 ATF_REQUIRE_MSG(error == 0, "sysctlbyname failed: %s", strerror(errno)); 126 ATF_REQUIRE_MSG(fibs >= 1, "strange FIB count %d", fibs); 127 if (fibs == 1) 128 atf_tc_skip("multiple FIBs not enabled"); 129 if (fibs < minfibs) 130 atf_tc_skip("not enough FIBs, need %d", minfibs); 131 132 switch (socktype) { 133 case SOCK_STREAM: 134 sysctl = "net.inet.tcp.bind_all_fibs"; 135 break; 136 case SOCK_DGRAM: 137 sysctl = "net.inet.udp.bind_all_fibs"; 138 break; 139 case SOCK_RAW: 140 sysctl = "net.inet.raw.bind_all_fibs"; 141 break; 142 default: 143 atf_tc_fail("unknown socket type %d", socktype); 144 break; 145 } 146 147 multibind = -1; 148 sz = sizeof(multibind); 149 error = sysctlbyname(sysctl, &multibind, &sz, NULL, 0); 150 ATF_REQUIRE_MSG(error == 0, "sysctlbyname failed: %s", strerror(errno)); 151 if (multibind != 0) 152 atf_tc_skip("FIB multibind not configured (%s)", sysctl); 153 } 154 155 /* 156 * Make sure that different users can't bind to the same port from different 157 * FIBs. 158 */ 159 static void 160 multibind_different_user(int domain, int type, const atf_tc_t *tc) 161 { 162 struct sockaddr_storage ss; 163 struct passwd *passwd; 164 const char *user; 165 socklen_t sslen; 166 int error, s[2]; 167 168 if (geteuid() != 0) 169 atf_tc_skip("need root privileges"); 170 if (!atf_tc_has_config_var(tc, "unprivileged_user")) 171 atf_tc_skip("unprivileged_user not set"); 172 173 ATF_REQUIRE(domain == PF_INET || domain == PF_INET6); 174 sslen = domain == PF_INET ? sizeof(struct sockaddr_in) : 175 sizeof(struct sockaddr_in6); 176 177 require_fibs_multibind(type, 2); 178 179 s[0] = mksock(domain, type, 0); 180 181 memset(&ss, 0, sizeof(ss)); 182 ss.ss_family = domain; 183 ss.ss_len = sslen; 184 error = bind(s[0], (struct sockaddr *)&ss, sslen); 185 ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno)); 186 187 error = getsockname(s[0], (struct sockaddr *)&ss, &sslen); 188 ATF_REQUIRE_MSG(error == 0, "getsockname failed: %s", strerror(errno)); 189 190 /* 191 * Create a second socket in a different FIB, and bind it to the same 192 * address/port tuple. This should succeed if done as the same user as 193 * the first socket, and should fail otherwise. 194 */ 195 s[1] = mksock(domain, type, 1); 196 error = bind(s[1], (struct sockaddr *)&ss, sslen); 197 ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno)); 198 ATF_REQUIRE_MSG(close(s[1]) == 0, "close failed: %s", strerror(errno)); 199 200 user = atf_tc_get_config_var(tc, "unprivileged_user"); 201 passwd = getpwnam(user); 202 ATF_REQUIRE(passwd != NULL); 203 error = seteuid(passwd->pw_uid); 204 ATF_REQUIRE_MSG(error == 0, "seteuid failed: %s", strerror(errno)); 205 206 /* Repeat the bind as a different user. */ 207 s[1] = mksock(domain, type, 1); 208 error = bind(s[1], (struct sockaddr *)&ss, sslen); 209 ATF_REQUIRE_ERRNO(EADDRINUSE, error == -1); 210 ATF_REQUIRE_MSG(close(s[1]) == 0, "close failed: %s", strerror(errno)); 211 } 212 MAKETEST(multibind_different_user); 213 214 /* 215 * Verify that a listening socket only accepts connections originating from the 216 * same FIB. 217 */ 218 static void 219 per_fib_listening_socket(int domain, int type, const atf_tc_t *tc __unused) 220 { 221 struct sockaddr_storage ss; 222 socklen_t sslen; 223 int cs1, cs2, error, fib1, fib2, ls1, ls2, ns; 224 225 ATF_REQUIRE(type == SOCK_STREAM); 226 ATF_REQUIRE(domain == PF_INET || domain == PF_INET6); 227 require_fibs_multibind(type, 2); 228 229 fib1 = 0; 230 fib2 = 1; 231 232 ls1 = mksock(domain, type, fib1); 233 ls2 = mksock(domain, type, fib2); 234 235 sslen = domain == PF_INET ? sizeof(struct sockaddr_in) : 236 sizeof(struct sockaddr_in6); 237 238 memset(&ss, 0, sizeof(ss)); 239 ss.ss_family = domain; 240 ss.ss_len = sslen; 241 error = bind(ls1, (struct sockaddr *)&ss, sslen); 242 ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno)); 243 244 error = getsockname(ls1, (struct sockaddr *)&ss, &sslen); 245 ATF_REQUIRE_MSG(error == 0, "getsockname failed: %s", strerror(errno)); 246 247 error = listen(ls1, 5); 248 ATF_REQUIRE_MSG(error == 0, "listen failed: %s", strerror(errno)); 249 250 cs1 = mksock(domain, type, fib1); 251 cs2 = mksock(domain, type, fib2); 252 253 /* 254 * Make sure we can connect from the same FIB. 255 */ 256 error = connect(cs1, (struct sockaddr *)&ss, sslen); 257 ATF_REQUIRE_MSG(error == 0, "connect failed: %s", strerror(errno)); 258 ns = accept(ls1, NULL, NULL); 259 ATF_REQUIRE_MSG(ns != -1, "accept failed: %s", strerror(errno)); 260 checked_close(ns); 261 checked_close(cs1); 262 cs1 = mksock(domain, type, fib1); 263 264 /* 265 * ... but not from a different FIB. 266 */ 267 error = connect(cs2, (struct sockaddr *)&ss, sslen); 268 ATF_REQUIRE_MSG(error == -1, "connect succeeded unexpectedly"); 269 ATF_REQUIRE_MSG(errno == ECONNREFUSED, "unexpected error %d", errno); 270 checked_close(cs2); 271 cs2 = mksock(domain, type, fib2); 272 273 /* 274 * ... but if there are multiple listening sockets, we always connect to 275 * the same FIB. 276 */ 277 error = bind(ls2, (struct sockaddr *)&ss, sslen); 278 ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno)); 279 error = listen(ls2, 5); 280 ATF_REQUIRE_MSG(error == 0, "listen failed: %s", strerror(errno)); 281 282 for (int i = 0; i < 10; i++) { 283 error = connect(cs1, (struct sockaddr *)&ss, sslen); 284 ATF_REQUIRE_MSG(error == 0, "connect failed: %s", 285 strerror(errno)); 286 ns = accept(ls1, NULL, NULL); 287 ATF_REQUIRE_MSG(ns != -1, "accept failed: %s", strerror(errno)); 288 289 checked_close(ns); 290 checked_close(cs1); 291 cs1 = mksock(domain, type, fib1); 292 } 293 for (int i = 0; i < 10; i++) { 294 error = connect(cs2, (struct sockaddr *)&ss, sslen); 295 ATF_REQUIRE_MSG(error == 0, "connect failed: %s", 296 strerror(errno)); 297 ns = accept(ls2, NULL, NULL); 298 ATF_REQUIRE_MSG(ns != -1, "accept failed: %s", strerror(errno)); 299 300 checked_close(ns); 301 checked_close(cs2); 302 cs2 = mksock(domain, type, fib2); 303 } 304 305 /* 306 * ... and if we close one of the listening sockets, we're back to only 307 * being able to connect from the same FIB. 308 */ 309 checked_close(ls1); 310 error = connect(cs1, (struct sockaddr *)&ss, sslen); 311 ATF_REQUIRE_MSG(error == -1, "connect succeeded unexpectedly"); 312 ATF_REQUIRE_MSG(errno == ECONNREFUSED, "unexpected error %d", errno); 313 checked_close(cs1); 314 315 error = connect(cs2, (struct sockaddr *)&ss, sslen); 316 ATF_REQUIRE_MSG(error == 0, "connect failed: %s", strerror(errno)); 317 ns = accept(ls2, NULL, NULL); 318 ATF_REQUIRE_MSG(ns != -1, "accept failed: %s", strerror(errno)); 319 checked_close(ns); 320 checked_close(cs2); 321 checked_close(ls2); 322 } 323 MAKETEST_TCP(per_fib_listening_socket); 324 325 /* 326 * Verify that a bound datagram socket only accepts data from the same FIB. 327 */ 328 static void 329 per_fib_dgram_socket(int domain, int type, const atf_tc_t *tc __unused) 330 { 331 struct sockaddr_storage ss; 332 struct sockaddr_in6 *sin6p; 333 socklen_t sslen; 334 ssize_t n; 335 int error, cs1, cs2, fib1, fib2, ss1, ss2; 336 char b; 337 338 ATF_REQUIRE(type == SOCK_DGRAM); 339 ATF_REQUIRE(domain == PF_INET || domain == PF_INET6); 340 require_fibs_multibind(type, 2); 341 342 fib1 = 0; 343 fib2 = 1; 344 345 cs1 = mksock(domain, type, fib1); 346 cs2 = mksock(domain, type, fib2); 347 348 ss1 = mksock(domain, type, fib1); 349 ss2 = mksock(domain, type, fib2); 350 351 sslen = domain == PF_INET ? sizeof(struct sockaddr_in) : 352 sizeof(struct sockaddr_in6); 353 354 memset(&ss, 0, sizeof(ss)); 355 ss.ss_family = domain; 356 ss.ss_len = sslen; 357 error = bind(ss1, (struct sockaddr *)&ss, sslen); 358 ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno)); 359 360 error = getsockname(ss1, (struct sockaddr *)&ss, &sslen); 361 ATF_REQUIRE_MSG(error == 0, "getsockname failed: %s", strerror(errno)); 362 363 if (domain == PF_INET6) { 364 sin6p = (struct sockaddr_in6 *)&ss; 365 sin6p->sin6_addr = in6addr_loopback; 366 } 367 368 /* If we send a byte from cs1, it should be recieved by ss1. */ 369 b = 42; 370 n = sendto(cs1, &b, sizeof(b), 0, (struct sockaddr *)&ss, sslen); 371 ATF_REQUIRE_MSG(n == 1, "sendto failed: %s", strerror(errno)); 372 n = recv(ss1, &b, sizeof(b), 0); 373 ATF_REQUIRE(n == 1); 374 ATF_REQUIRE(b == 42); 375 376 /* If we send a byte from cs2, it should not be received by ss1. */ 377 b = 42; 378 n = sendto(cs2, &b, sizeof(b), 0, (struct sockaddr *)&ss, sslen); 379 ATF_REQUIRE_MSG(n == 1, "sendto failed: %s", strerror(errno)); 380 usleep(10000); 381 n = recv(ss1, &b, sizeof(b), MSG_DONTWAIT); 382 ATF_REQUIRE_ERRNO(EWOULDBLOCK, n == -1); 383 384 error = bind(ss2, (struct sockaddr *)&ss, sslen); 385 ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno)); 386 387 /* Repeat now that ss2 is bound. */ 388 b = 42; 389 n = sendto(cs1, &b, sizeof(b), 0, (struct sockaddr *)&ss, sslen); 390 ATF_REQUIRE_MSG(n == 1, "sendto failed: %s", strerror(errno)); 391 n = recv(ss1, &b, sizeof(b), 0); 392 ATF_REQUIRE(n == 1); 393 ATF_REQUIRE(b == 42); 394 395 b = 42; 396 n = sendto(cs2, &b, sizeof(b), 0, (struct sockaddr *)&ss, sslen); 397 ATF_REQUIRE_MSG(n == 1, "sendto failed: %s", strerror(errno)); 398 n = recv(ss2, &b, sizeof(b), 0); 399 ATF_REQUIRE(n == 1); 400 ATF_REQUIRE(b == 42); 401 402 checked_close(ss1); 403 checked_close(ss2); 404 checked_close(cs1); 405 checked_close(cs2); 406 } 407 MAKETEST_UDP(per_fib_dgram_socket); 408 409 static size_t 410 ping(int s, const struct sockaddr *sa, socklen_t salen) 411 { 412 struct { 413 struct icmphdr icmp; 414 char data[64]; 415 } icmp; 416 ssize_t n; 417 418 memset(&icmp, 0, sizeof(icmp)); 419 icmp.icmp.icmp_type = ICMP_ECHO; 420 icmp.icmp.icmp_code = 0; 421 icmp.icmp.icmp_cksum = htons((unsigned short)~(ICMP_ECHO << 8)); 422 n = sendto(s, &icmp, sizeof(icmp), 0, sa, salen); 423 ATF_REQUIRE_MSG(n == (ssize_t)sizeof(icmp), "sendto failed: %s", 424 strerror(errno)); 425 426 return (sizeof(icmp) + sizeof(struct ip)); 427 } 428 429 static size_t 430 ping6(int s, const struct sockaddr *sa, socklen_t salen) 431 { 432 struct { 433 struct icmp6_hdr icmp6; 434 char data[64]; 435 } icmp6; 436 ssize_t n; 437 438 memset(&icmp6, 0, sizeof(icmp6)); 439 icmp6.icmp6.icmp6_type = ICMP6_ECHO_REQUEST; 440 icmp6.icmp6.icmp6_code = 0; 441 icmp6.icmp6.icmp6_cksum = 442 htons((unsigned short)~(ICMP6_ECHO_REQUEST << 8)); 443 n = sendto(s, &icmp6, sizeof(icmp6), 0, sa, salen); 444 ATF_REQUIRE_MSG(n == (ssize_t)sizeof(icmp6), "sendto failed: %s", 445 strerror(errno)); 446 447 return (sizeof(icmp6)); 448 } 449 450 static void 451 per_fib_raw_socket(int domain, int type, const atf_tc_t *tc __unused) 452 { 453 struct sockaddr_in sin; 454 struct sockaddr_in6 sin6; 455 ssize_t n; 456 size_t sz; 457 int error, cs, s[2], proto; 458 uint8_t b[256]; 459 460 ATF_REQUIRE(type == SOCK_RAW); 461 ATF_REQUIRE(domain == PF_INET || domain == PF_INET6); 462 require_fibs_multibind(type, 2); 463 464 proto = domain == PF_INET ? IPPROTO_ICMP : IPPROTO_ICMPV6; 465 s[0] = mksockp(domain, type, 0, proto); 466 s[1] = mksockp(domain, type, 1, proto); 467 468 if (domain == PF_INET) { 469 memset(&sin, 0, sizeof(sin)); 470 sin.sin_family = domain; 471 sin.sin_len = sizeof(sin); 472 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 473 error = bind(s[0], (struct sockaddr *)&sin, sizeof(sin)); 474 } else /* if (domain == PF_INET6) */ { 475 memset(&sin6, 0, sizeof(sin6)); 476 sin6.sin6_family = domain; 477 sin6.sin6_len = sizeof(sin6); 478 sin6.sin6_addr = in6addr_loopback; 479 error = bind(s[0], (struct sockaddr *)&sin6, sizeof(sin6)); 480 } 481 ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno)); 482 483 for (int i = 0; i < 2; i++) { 484 cs = mksockp(domain, type, i, proto); 485 if (domain == PF_INET) { 486 sz = ping(cs, (struct sockaddr *)&sin, sizeof(sin)); 487 } else /* if (domain == PF_INET6) */ { 488 sz = ping6(cs, (struct sockaddr *)&sin6, sizeof(sin6)); 489 } 490 n = recv(s[i], b, sizeof(b), 0); 491 ATF_REQUIRE_MSG(n > 0, "recv failed: %s", strerror(errno)); 492 ATF_REQUIRE_MSG(n == (ssize_t)sz, 493 "short packet received: %zd", n); 494 495 if (domain == PF_INET6) { 496 /* Get the echo reply as well. */ 497 n = recv(s[i], b, sizeof(b), 0); 498 ATF_REQUIRE_MSG(n > 0, 499 "recv failed: %s", strerror(errno)); 500 ATF_REQUIRE_MSG(n == (ssize_t)sz, 501 "short packet received: %zd", n); 502 } 503 504 /* Make sure that the other socket didn't receive anything. */ 505 n = recv(s[1 - i], b, sizeof(b), MSG_DONTWAIT); 506 printf("n = %zd i = %d\n", n, i); 507 ATF_REQUIRE_ERRNO(EWOULDBLOCK, n == -1); 508 509 checked_close(cs); 510 } 511 512 checked_close(s[0]); 513 checked_close(s[1]); 514 } 515 MAKETEST_RAW(per_fib_raw_socket); 516 517 /* 518 * Create a pair of load-balancing listening socket groups, one in each FIB, and 519 * make sure that connections to the group are only load-balanced within the 520 * same FIB. 521 */ 522 static void 523 multibind_lbgroup_stream(int domain, int type, const atf_tc_t *tc __unused) 524 { 525 struct sockaddr_storage ss; 526 socklen_t sslen; 527 int error, as, cs, s[3]; 528 529 ATF_REQUIRE(type == SOCK_STREAM); 530 ATF_REQUIRE(domain == PF_INET || domain == PF_INET6); 531 require_fibs_multibind(type, 2); 532 533 s[0] = mksock(domain, type, 0); 534 ATF_REQUIRE(setsockopt(s[0], SOL_SOCKET, SO_REUSEPORT_LB, &(int){1}, 535 sizeof(int)) == 0); 536 ATF_REQUIRE(fcntl(s[0], F_SETFL, O_NONBLOCK) == 0); 537 s[1] = mksock(domain, type, 0); 538 ATF_REQUIRE(setsockopt(s[1], SOL_SOCKET, SO_REUSEPORT_LB, &(int){1}, 539 sizeof(int)) == 0); 540 ATF_REQUIRE(fcntl(s[1], F_SETFL, O_NONBLOCK) == 0); 541 s[2] = mksock(domain, type, 1); 542 ATF_REQUIRE(setsockopt(s[2], SOL_SOCKET, SO_REUSEPORT_LB, &(int){1}, 543 sizeof(int)) == 0); 544 545 sslen = domain == PF_INET ? sizeof(struct sockaddr_in) : 546 sizeof(struct sockaddr_in6); 547 memset(&ss, 0, sizeof(ss)); 548 ss.ss_family = domain; 549 ss.ss_len = sslen; 550 error = bind(s[0], (struct sockaddr *)&ss, sslen); 551 ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno)); 552 error = listen(s[0], 5); 553 ATF_REQUIRE_MSG(error == 0, "listen failed: %s", strerror(errno)); 554 error = getsockname(s[0], (struct sockaddr *)&ss, &sslen); 555 ATF_REQUIRE_MSG(error == 0, "getsockname failed: %s", strerror(errno)); 556 557 error = bind(s[1], (struct sockaddr *)&ss, sslen); 558 ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno)); 559 error = listen(s[1], 5); 560 ATF_REQUIRE_MSG(error == 0, "listen failed: %s", strerror(errno)); 561 562 error = bind(s[2], (struct sockaddr *)&ss, sslen); 563 ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno)); 564 error = listen(s[2], 5); 565 ATF_REQUIRE_MSG(error == 0, "listen failed: %s", strerror(errno)); 566 567 /* 568 * Initiate connections from FIB 0, make sure they go to s[0] or s[1]. 569 */ 570 for (int count = 0; count < 100; count++) { 571 cs = mksock(domain, type, 0); 572 error = connect(cs, (struct sockaddr *)&ss, sslen); 573 ATF_REQUIRE_MSG(error == 0, "connect failed: %s", 574 strerror(errno)); 575 576 do { 577 as = accept(s[0], NULL, NULL); 578 if (as == -1) { 579 ATF_REQUIRE_MSG(errno == EWOULDBLOCK, 580 "accept failed: %s", strerror(errno)); 581 as = accept(s[1], NULL, NULL); 582 if (as == -1) { 583 ATF_REQUIRE_MSG(errno == EWOULDBLOCK, 584 "accept failed: %s", 585 strerror(errno)); 586 } 587 } 588 } while (as == -1); 589 checked_close(as); 590 checked_close(cs); 591 } 592 593 /* 594 * Initiate connections from FIB 1, make sure they go to s[2]. 595 */ 596 for (int count = 0; count < 100; count++) { 597 cs = mksock(domain, type, 1); 598 error = connect(cs, (struct sockaddr *)&ss, sslen); 599 ATF_REQUIRE_MSG(error == 0, "connect failed: %s", 600 strerror(errno)); 601 602 as = accept(s[2], NULL, NULL); 603 ATF_REQUIRE_MSG(as != -1, "accept failed: %s", strerror(errno)); 604 checked_close(as); 605 checked_close(cs); 606 } 607 608 checked_close(s[0]); 609 checked_close(s[1]); 610 checked_close(s[2]); 611 } 612 MAKETEST_TCP(multibind_lbgroup_stream); 613 614 static void 615 multibind_lbgroup_dgram(int domain, int type, const atf_tc_t *tc __unused) 616 { 617 struct sockaddr_storage ss; 618 struct sockaddr_in6 *sin6p; 619 socklen_t sslen; 620 ssize_t n; 621 int error, cs, s[3]; 622 char b; 623 624 ATF_REQUIRE(type == SOCK_DGRAM); 625 ATF_REQUIRE(domain == PF_INET || domain == PF_INET6); 626 require_fibs_multibind(type, 2); 627 628 s[0] = mksock(domain, type, 0); 629 ATF_REQUIRE(setsockopt(s[0], SOL_SOCKET, SO_REUSEPORT_LB, &(int){1}, 630 sizeof(int)) == 0); 631 s[1] = mksock(domain, type, 0); 632 ATF_REQUIRE(setsockopt(s[1], SOL_SOCKET, SO_REUSEPORT_LB, &(int){1}, 633 sizeof(int)) == 0); 634 s[2] = mksock(domain, type, 1); 635 ATF_REQUIRE(setsockopt(s[2], SOL_SOCKET, SO_REUSEPORT_LB, &(int){1}, 636 sizeof(int)) == 0); 637 638 sslen = domain == PF_INET ? sizeof(struct sockaddr_in) : 639 sizeof(struct sockaddr_in6); 640 memset(&ss, 0, sizeof(ss)); 641 ss.ss_family = domain; 642 ss.ss_len = sslen; 643 error = bind(s[0], (struct sockaddr *)&ss, sslen); 644 ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno)); 645 error = getsockname(s[0], (struct sockaddr *)&ss, &sslen); 646 ATF_REQUIRE_MSG(error == 0, "getsockname failed: %s", strerror(errno)); 647 648 error = bind(s[1], (struct sockaddr *)&ss, sslen); 649 ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno)); 650 error = bind(s[2], (struct sockaddr *)&ss, sslen); 651 ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno)); 652 653 if (domain == PF_INET6) { 654 sin6p = (struct sockaddr_in6 *)&ss; 655 sin6p->sin6_addr = in6addr_loopback; 656 } 657 658 /* 659 * Send a packet from FIB 0, make sure it goes to s[0] or s[1]. 660 */ 661 cs = mksock(domain, type, 0); 662 for (int count = 0; count < 100; count++) { 663 int bytes, rs; 664 665 b = 42; 666 n = sendto(cs, &b, sizeof(b), 0, (struct sockaddr *)&ss, sslen); 667 ATF_REQUIRE_MSG(n == 1, "sendto failed: %s", strerror(errno)); 668 usleep(1000); 669 670 error = ioctl(s[0], FIONREAD, &bytes); 671 ATF_REQUIRE_MSG(error == 0, "ioctl failed: %s", 672 strerror(errno)); 673 if (bytes == 0) { 674 error = ioctl(s[1], FIONREAD, &bytes); 675 ATF_REQUIRE_MSG(error == 0, "ioctl failed: %s", 676 strerror(errno)); 677 rs = s[1]; 678 } else { 679 rs = s[0]; 680 } 681 n = recv(rs, &b, sizeof(b), 0); 682 ATF_REQUIRE(n == 1); 683 ATF_REQUIRE(b == 42); 684 ATF_REQUIRE(bytes == 1); 685 } 686 checked_close(cs); 687 688 /* 689 * Send a packet from FIB 1, make sure it goes to s[2]. 690 */ 691 cs = mksock(domain, type, 1); 692 for (int count = 0; count < 100; count++) { 693 b = 42; 694 n = sendto(cs, &b, sizeof(b), 0, (struct sockaddr *)&ss, sslen); 695 ATF_REQUIRE_MSG(n == 1, "sendto failed: %s", strerror(errno)); 696 usleep(1000); 697 698 n = recv(s[2], &b, sizeof(b), 0); 699 ATF_REQUIRE(n == 1); 700 ATF_REQUIRE(b == 42); 701 } 702 checked_close(cs); 703 704 checked_close(s[0]); 705 checked_close(s[1]); 706 checked_close(s[2]); 707 } 708 MAKETEST_UDP(multibind_lbgroup_dgram); 709 710 /* 711 * Make sure that we can't change the FIB of a bound socket. 712 */ 713 static void 714 no_setfib_after_bind(int domain, int type, const atf_tc_t *tc __unused) 715 { 716 struct sockaddr_storage ss; 717 socklen_t sslen; 718 int error, s; 719 720 ATF_REQUIRE(domain == PF_INET || domain == PF_INET6); 721 require_fibs_multibind(type, 2); 722 723 s = mksock(domain, type, 0); 724 725 sslen = domain == PF_INET ? sizeof(struct sockaddr_in) : 726 sizeof(struct sockaddr_in6); 727 memset(&ss, 0, sizeof(ss)); 728 ss.ss_family = domain; 729 ss.ss_len = sslen; 730 error = bind(s, (struct sockaddr *)&ss, sslen); 731 ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno)); 732 733 error = setsockopt(s, SOL_SOCKET, SO_SETFIB, &(int){1}, sizeof(int)); 734 ATF_REQUIRE_ERRNO(EISCONN, error == -1); 735 736 /* It's ok to set the FIB number to its current value. */ 737 error = setsockopt(s, SOL_SOCKET, SO_SETFIB, &(int){0}, sizeof(int)); 738 ATF_REQUIRE_MSG(error == 0, "setsockopt failed: %s", strerror(errno)); 739 740 checked_close(s); 741 } 742 MAKETEST(no_setfib_after_bind); 743 744 ATF_TP_ADD_TCS(tp) 745 { 746 LISTTEST(multibind_different_user); 747 LISTTEST_TCP(per_fib_listening_socket); 748 LISTTEST_UDP(per_fib_dgram_socket); 749 LISTTEST_RAW(per_fib_raw_socket); 750 LISTTEST_TCP(multibind_lbgroup_stream); 751 LISTTEST_UDP(multibind_lbgroup_dgram); 752 LISTTEST(no_setfib_after_bind); 753 754 return (atf_no_error()); 755 } 756