1 /*- 2 * Copyright (c) 2014 Spectra Logic Corporation 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions, and the following disclaimer, 10 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * substantially similar to the "NO WARRANTY" disclaimer below 13 * ("Disclaimer") and any redistribution must be conditioned upon 14 * including a substantially similar Disclaimer requirement for further 15 * binary redistribution. 16 * 17 * NO WARRANTY 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGES. 29 * 30 * $FreeBSD$ 31 */ 32 33 #include <rpc/rpc.h> 34 #include <sys/types.h> 35 #include <sys/socket.h> 36 37 #include <net/if.h> 38 #include <netinet/in.h> 39 #include <arpa/inet.h> 40 41 #include <ifaddrs.h> 42 #include <stdlib.h> 43 44 #include <atf-c.h> 45 46 #include "rpcbind.h" 47 48 #define MAX_IFADDRS 16 49 50 int debugging = false; 51 52 /* Data for mocking getifaddrs */ 53 struct ifaddr_storage { 54 struct ifaddrs ifaddr; 55 struct sockaddr_storage addr; 56 struct sockaddr_storage mask; 57 struct sockaddr_storage bcast; 58 } mock_ifaddr_storage[MAX_IFADDRS]; 59 struct ifaddrs *mock_ifaddrs = NULL; 60 int ifaddr_count = 0; 61 62 /* Data for mocking listen_addr */ 63 int bind_address_count = 0; 64 struct sockaddr* bind_addresses[MAX_IFADDRS]; 65 66 /* Stub library functions */ 67 void 68 freeifaddrs(struct ifaddrs *ifp __unused) 69 { 70 return ; 71 } 72 73 int 74 getifaddrs(struct ifaddrs **ifap) 75 { 76 *ifap = mock_ifaddrs; 77 return (0); 78 } 79 80 static void 81 mock_ifaddr4(const char* name, const char* addr, const char* mask, 82 const char* bcast, unsigned int flags, bool bind) 83 { 84 struct ifaddrs *ifaddr = &mock_ifaddr_storage[ifaddr_count].ifaddr; 85 struct sockaddr_in *in = (struct sockaddr_in*) 86 &mock_ifaddr_storage[ifaddr_count].addr; 87 struct sockaddr_in *mask_in = (struct sockaddr_in*) 88 &mock_ifaddr_storage[ifaddr_count].mask; 89 struct sockaddr_in *bcast_in = (struct sockaddr_in*) 90 &mock_ifaddr_storage[ifaddr_count].bcast; 91 92 in->sin_family = AF_INET; 93 in->sin_port = 0; 94 in->sin_len = sizeof(*in); 95 in->sin_addr.s_addr = inet_addr(addr); 96 mask_in->sin_family = AF_INET; 97 mask_in->sin_port = 0; 98 mask_in->sin_len = sizeof(*mask_in); 99 mask_in->sin_addr.s_addr = inet_addr(mask); 100 bcast_in->sin_family = AF_INET; 101 bcast_in->sin_port = 0; 102 bcast_in->sin_len = sizeof(*bcast_in); 103 bcast_in->sin_addr.s_addr = inet_addr(bcast); 104 *ifaddr = (struct ifaddrs) { 105 .ifa_next = NULL, 106 .ifa_name = (char*) name, 107 .ifa_flags = flags, 108 .ifa_addr = (struct sockaddr*) in, 109 .ifa_netmask = (struct sockaddr*) mask_in, 110 .ifa_broadaddr = (struct sockaddr*) bcast_in, 111 .ifa_data = NULL, /* addrmerge doesn't care*/ 112 }; 113 114 if (ifaddr_count > 0) 115 mock_ifaddr_storage[ifaddr_count - 1].ifaddr.ifa_next = ifaddr; 116 ifaddr_count++; 117 mock_ifaddrs = &mock_ifaddr_storage[0].ifaddr; 118 119 /* Optionally simulate binding an ip ala "rpcbind -h foo" */ 120 if (bind) { 121 bind_addresses[bind_address_count] = (struct sockaddr*)in; 122 bind_address_count++; 123 } 124 } 125 126 #ifdef INET6 127 static void 128 mock_ifaddr6(const char* name, const char* addr, const char* mask, 129 const char* bcast, unsigned int flags, uint32_t scope_id, bool bind) 130 { 131 struct ifaddrs *ifaddr = &mock_ifaddr_storage[ifaddr_count].ifaddr; 132 struct sockaddr_in6 *in6 = (struct sockaddr_in6*) 133 &mock_ifaddr_storage[ifaddr_count].addr; 134 struct sockaddr_in6 *mask_in6 = (struct sockaddr_in6*) 135 &mock_ifaddr_storage[ifaddr_count].mask; 136 struct sockaddr_in6 *bcast_in6 = (struct sockaddr_in6*) 137 &mock_ifaddr_storage[ifaddr_count].bcast; 138 139 in6->sin6_family = AF_INET6; 140 in6->sin6_port = 0; 141 in6->sin6_len = sizeof(*in6); 142 in6->sin6_scope_id = scope_id; 143 ATF_REQUIRE_EQ(1, inet_pton(AF_INET6, addr, (void*)&in6->sin6_addr)); 144 mask_in6->sin6_family = AF_INET6; 145 mask_in6->sin6_port = 0; 146 mask_in6->sin6_len = sizeof(*mask_in6); 147 mask_in6->sin6_scope_id = scope_id; 148 ATF_REQUIRE_EQ(1, inet_pton(AF_INET6, mask, 149 (void*)&mask_in6->sin6_addr)); 150 bcast_in6->sin6_family = AF_INET6; 151 bcast_in6->sin6_port = 0; 152 bcast_in6->sin6_len = sizeof(*bcast_in6); 153 bcast_in6->sin6_scope_id = scope_id; 154 ATF_REQUIRE_EQ(1, inet_pton(AF_INET6, bcast, 155 (void*)&bcast_in6->sin6_addr)); 156 *ifaddr = (struct ifaddrs) { 157 .ifa_next = NULL, 158 .ifa_name = (char*) name, 159 .ifa_flags = flags, 160 .ifa_addr = (struct sockaddr*) in6, 161 .ifa_netmask = (struct sockaddr*) mask_in6, 162 .ifa_broadaddr = (struct sockaddr*) bcast_in6, 163 .ifa_data = NULL, /* addrmerge doesn't care*/ 164 }; 165 166 if (ifaddr_count > 0) 167 mock_ifaddr_storage[ifaddr_count - 1].ifaddr.ifa_next = ifaddr; 168 ifaddr_count++; 169 mock_ifaddrs = &mock_ifaddr_storage[0].ifaddr; 170 171 /* Optionally simulate binding an ip ala "rpcbind -h foo" */ 172 if (bind) { 173 bind_addresses[bind_address_count] = (struct sockaddr*)in6; 174 bind_address_count++; 175 } 176 } 177 #else 178 static void 179 mock_ifaddr6(const char* name __unused, const char* addr __unused, 180 const char* mask __unused, const char* bcast __unused, 181 unsigned int flags __unused, uint32_t scope_id __unused, bool bind __unused) 182 { 183 } 184 #endif /*INET6 */ 185 186 static void 187 mock_lo0(void) 188 { 189 /* 190 * This broadcast address looks wrong, but it's what getifaddrs(2) 191 * actually returns. It's invalid because IFF_BROADCAST is not set 192 */ 193 mock_ifaddr4("lo0", "127.0.0.1", "255.0.0.0", "127.0.0.1", 194 IFF_LOOPBACK | IFF_UP | IFF_RUNNING | IFF_MULTICAST, false); 195 mock_ifaddr6("lo0", "::1", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 196 "::1", 197 IFF_LOOPBACK | IFF_UP | IFF_RUNNING | IFF_MULTICAST, 0, false); 198 } 199 200 static void 201 mock_igb0(void) 202 { 203 mock_ifaddr4("igb0", "192.0.2.2", "255.255.255.128", "192.0.2.127", 204 IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST, 205 false); 206 mock_ifaddr6("igb0", "2001:db8::2", "ffff:ffff:ffff:ffff::", 207 "2001:db8::ffff:ffff:ffff:ffff", 208 IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST, 209 0, false); 210 /* Link local address */ 211 mock_ifaddr6("igb0", "fe80::2", "ffff:ffff:ffff:ffff::", 212 "fe80::ffff:ffff:ffff:ffff", 213 IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST, 214 2, false); 215 } 216 217 /* On the same subnet as igb0 */ 218 static void 219 mock_igb1(bool bind) 220 { 221 mock_ifaddr4("igb1", "192.0.2.3", "255.255.255.128", "192.0.2.127", 222 IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST, 223 bind); 224 mock_ifaddr6("igb1", "2001:db8::3", "ffff:ffff:ffff:ffff::", 225 "2001:db8::ffff:ffff:ffff:ffff", 226 IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST, 227 0, bind); 228 /* Link local address */ 229 mock_ifaddr6("igb1", "fe80::3", "ffff:ffff:ffff:ffff::", 230 "fe80::ffff:ffff:ffff:ffff", 231 IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST, 232 3, bind); 233 } 234 235 /* igb2 is on a different subnet than igb0 */ 236 static void 237 mock_igb2(void) 238 { 239 mock_ifaddr4("igb2", "192.0.2.130", "255.255.255.128", "192.0.2.255", 240 IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST, 241 false); 242 mock_ifaddr6("igb2", "2001:db8:1::2", "ffff:ffff:ffff:ffff::", 243 "2001:db8:1:0:ffff:ffff:ffff:ffff", 244 IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST, 245 0, false); 246 } 247 248 /* tun0 is a P2P interface */ 249 static void 250 mock_tun0(void) 251 { 252 mock_ifaddr4("tun0", "192.0.2.5", "255.255.255.255", "192.0.2.6", 253 IFF_UP | IFF_RUNNING | IFF_POINTOPOINT | IFF_MULTICAST, false); 254 mock_ifaddr6("tun0", "2001:db8::5", 255 "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 256 "2001:db8::6", 257 IFF_UP | IFF_RUNNING | IFF_POINTOPOINT | IFF_MULTICAST, 0, false); 258 } 259 260 261 /* Stub rpcbind functions */ 262 int 263 listen_addr(const struct sockaddr *sa) 264 { 265 int i; 266 267 if (bind_address_count == 0) 268 return (1); 269 270 for (i = 0; i < bind_address_count; i++) { 271 if (bind_addresses[i]->sa_family != sa->sa_family) 272 continue; 273 274 if (0 == memcmp(bind_addresses[i]->sa_data, sa->sa_data, 275 sa->sa_len)) 276 return (1); 277 } 278 return (0); 279 } 280 281 struct netconfig* 282 rpcbind_get_conf(const char* netid __unused) 283 { 284 /* Use static variables so we can return pointers to them */ 285 static char* lookups = NULL; 286 static struct netconfig nconf_udp; 287 #ifdef INET6 288 static struct netconfig nconf_udp6; 289 #endif /* INET6 */ 290 291 nconf_udp.nc_netid = "udp"; //netid_storage; 292 nconf_udp.nc_semantics = NC_TPI_CLTS; 293 nconf_udp.nc_flag = NC_VISIBLE; 294 nconf_udp.nc_protofmly = (char*)"inet"; 295 nconf_udp.nc_proto = (char*)"udp"; 296 nconf_udp.nc_device = (char*)"-"; 297 nconf_udp.nc_nlookups = 0; 298 nconf_udp.nc_lookups = &lookups; 299 300 #ifdef INET6 301 nconf_udp6.nc_netid = "udp6"; //netid_storage; 302 nconf_udp6.nc_semantics = NC_TPI_CLTS; 303 nconf_udp6.nc_flag = NC_VISIBLE; 304 nconf_udp6.nc_protofmly = (char*)"inet6"; 305 nconf_udp6.nc_proto = (char*)"udp6"; 306 nconf_udp6.nc_device = (char*)"-"; 307 nconf_udp6.nc_nlookups = 0; 308 nconf_udp6.nc_lookups = &lookups; 309 #endif /* INET6 */ 310 311 if (0 == strncmp("udp", netid, sizeof("udp"))) 312 return (&nconf_udp); 313 #ifdef INET6 314 else if (0 == strncmp("udp6", netid, sizeof("udp6"))) 315 return (&nconf_udp6); 316 #endif /* INET6 */ 317 else 318 return (NULL); 319 } 320 321 /* 322 * Helper function used by most test cases 323 * param recvdstaddr If non-null, the uaddr on which the request was received 324 */ 325 static char* 326 do_addrmerge4(const char* recvdstaddr) 327 { 328 struct netbuf caller; 329 struct sockaddr_in caller_in; 330 const char *serv_uaddr, *clnt_uaddr, *netid; 331 332 /* caller contains the client's IP address */ 333 caller.maxlen = sizeof(struct sockaddr_storage); 334 caller.len = sizeof(caller_in); 335 caller_in.sin_family = AF_INET; 336 caller_in.sin_len = sizeof(caller_in); 337 caller_in.sin_port = 1234; 338 caller_in.sin_addr.s_addr = inet_addr("192.0.2.1"); 339 caller.buf = (void*)&caller_in; 340 if (recvdstaddr != NULL) 341 clnt_uaddr = recvdstaddr; 342 else 343 clnt_uaddr = "192.0.2.1.3.46"; 344 345 /* assume server is bound in INADDR_ANY port 814 */ 346 serv_uaddr = "0.0.0.0.3.46"; 347 348 netid = "udp"; 349 return (addrmerge(&caller, serv_uaddr, clnt_uaddr, netid)); 350 } 351 352 #ifdef INET6 353 /* 354 * Variant of do_addrmerge4 where the caller has an IPv6 address 355 * param recvdstaddr If non-null, the uaddr on which the request was received 356 */ 357 static char* 358 do_addrmerge6(const char* recvdstaddr) 359 { 360 struct netbuf caller; 361 struct sockaddr_in6 caller_in6; 362 const char *serv_uaddr, *clnt_uaddr, *netid; 363 364 /* caller contains the client's IP address */ 365 caller.maxlen = sizeof(struct sockaddr_storage); 366 caller.len = sizeof(caller_in6); 367 caller_in6.sin6_family = AF_INET6; 368 caller_in6.sin6_len = sizeof(caller_in6); 369 caller_in6.sin6_port = 1234; 370 ATF_REQUIRE_EQ(1, inet_pton(AF_INET6, "2001:db8::1", 371 (void*)&caller_in6.sin6_addr)); 372 caller.buf = (void*)&caller_in6; 373 if (recvdstaddr != NULL) 374 clnt_uaddr = recvdstaddr; 375 else 376 clnt_uaddr = "2001:db8::1.3.46"; 377 378 /* assume server is bound in INADDR_ANY port 814 */ 379 serv_uaddr = "::1.3.46"; 380 381 netid = "udp6"; 382 return (addrmerge(&caller, serv_uaddr, clnt_uaddr, netid)); 383 } 384 385 /* Variant of do_addrmerge6 where the caller uses a link local address */ 386 static char* 387 do_addrmerge6_ll(void) 388 { 389 struct netbuf caller; 390 struct sockaddr_in6 caller_in6; 391 const char *serv_uaddr, *clnt_uaddr, *netid; 392 393 /* caller contains the client's IP address */ 394 caller.maxlen = sizeof(struct sockaddr_storage); 395 caller.len = sizeof(caller_in6); 396 caller_in6.sin6_family = AF_INET6; 397 caller_in6.sin6_len = sizeof(caller_in6); 398 caller_in6.sin6_port = 1234; 399 caller_in6.sin6_scope_id = 2; /* same as igb0 */ 400 ATF_REQUIRE_EQ(1, inet_pton(AF_INET6, "fe80::beef", 401 (void*)&caller_in6.sin6_addr)); 402 caller.buf = (void*)&caller_in6; 403 clnt_uaddr = "fe80::beef.3.46"; 404 405 /* assume server is bound in INADDR_ANY port 814 */ 406 serv_uaddr = "::1.3.46"; 407 408 netid = "udp6"; 409 return (addrmerge(&caller, serv_uaddr, clnt_uaddr, netid)); 410 } 411 #endif /* INET6 */ 412 413 ATF_TC_WITHOUT_HEAD(addrmerge_noifaddrs); 414 ATF_TC_BODY(addrmerge_noifaddrs, tc) 415 { 416 char* maddr; 417 418 maddr = do_addrmerge4(NULL); 419 420 /* Since getifaddrs returns null, addrmerge must too */ 421 ATF_CHECK_EQ(NULL, maddr); 422 } 423 424 ATF_TC_WITHOUT_HEAD(addrmerge_localhost_only); 425 ATF_TC_BODY(addrmerge_localhost_only, tc) 426 { 427 char *maddr; 428 429 /* getifaddrs will return localhost only */ 430 mock_lo0(); 431 432 maddr = do_addrmerge4(NULL); 433 434 /* We must return localhost if there is nothing better */ 435 ATF_REQUIRE(maddr != NULL); 436 ATF_CHECK_STREQ("127.0.0.1.3.46", maddr); 437 free(maddr); 438 } 439 440 ATF_TC_WITHOUT_HEAD(addrmerge_singlehomed); 441 ATF_TC_BODY(addrmerge_singlehomed, tc) 442 { 443 char *maddr; 444 445 /* getifaddrs will return one public address */ 446 mock_lo0(); 447 mock_igb0(); 448 449 maddr = do_addrmerge4(NULL); 450 451 ATF_REQUIRE(maddr != NULL); 452 ATF_CHECK_STREQ("192.0.2.2.3.46", maddr); 453 free(maddr); 454 } 455 456 ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet); 457 ATF_TC_BODY(addrmerge_one_addr_on_each_subnet, tc) 458 { 459 char *maddr; 460 461 mock_lo0(); 462 mock_igb0(); 463 mock_igb2(); 464 465 maddr = do_addrmerge4(NULL); 466 467 /* We must return the address on the caller's subnet */ 468 ATF_REQUIRE(maddr != NULL); 469 ATF_CHECK_STREQ("192.0.2.2.3.46", maddr); 470 free(maddr); 471 } 472 473 474 /* 475 * Like addrmerge_one_addr_on_each_subnet, but getifaddrs returns a different 476 * order 477 */ 478 ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet_rev); 479 ATF_TC_BODY(addrmerge_one_addr_on_each_subnet_rev, tc) 480 { 481 char *maddr; 482 483 /* getifaddrs will return one public address on each of two subnets */ 484 mock_igb2(); 485 mock_igb0(); 486 mock_lo0(); 487 488 maddr = do_addrmerge4(NULL); 489 490 /* We must return the address on the caller's subnet */ 491 ATF_REQUIRE(maddr != NULL); 492 ATF_CHECK_STREQ("192.0.2.2.3.46", maddr); 493 free(maddr); 494 } 495 496 ATF_TC_WITHOUT_HEAD(addrmerge_point2point); 497 ATF_TC_BODY(addrmerge_point2point, tc) 498 { 499 char *maddr; 500 501 /* getifaddrs will return one normal and one p2p address */ 502 mock_lo0(); 503 mock_igb2(); 504 mock_tun0(); 505 506 maddr = do_addrmerge4(NULL); 507 508 /* addrmerge should disprefer P2P interfaces */ 509 ATF_REQUIRE(maddr != NULL); 510 ATF_CHECK_STREQ("192.0.2.130.3.46", maddr); 511 free(maddr); 512 } 513 514 /* Like addrerge_point2point, but getifaddrs returns a different order */ 515 ATF_TC_WITHOUT_HEAD(addrmerge_point2point_rev); 516 ATF_TC_BODY(addrmerge_point2point_rev, tc) 517 { 518 char *maddr; 519 520 /* getifaddrs will return one normal and one p2p address */ 521 mock_tun0(); 522 mock_igb2(); 523 mock_lo0(); 524 525 maddr = do_addrmerge4(NULL); 526 527 /* addrmerge should disprefer P2P interfaces */ 528 ATF_REQUIRE(maddr != NULL); 529 ATF_CHECK_STREQ("192.0.2.130.3.46", maddr); 530 free(maddr); 531 } 532 533 /* 534 * Simulate using rpcbind -h to select just one ip when the subnet has 535 * multiple 536 */ 537 ATF_TC_WITHOUT_HEAD(addrmerge_bindip); 538 ATF_TC_BODY(addrmerge_bindip, tc) 539 { 540 char *maddr; 541 542 /* getifaddrs will return one public address on each of two subnets */ 543 mock_lo0(); 544 mock_igb0(); 545 mock_igb1(true); 546 547 maddr = do_addrmerge4(NULL); 548 549 /* We must return the address to which we are bound */ 550 ATF_REQUIRE(maddr != NULL); 551 ATF_CHECK_STREQ("192.0.2.3.3.46", maddr); 552 free(maddr); 553 } 554 555 /* Like addrmerge_bindip, but getifaddrs returns a different order */ 556 ATF_TC_WITHOUT_HEAD(addrmerge_bindip_rev); 557 ATF_TC_BODY(addrmerge_bindip_rev, tc) 558 { 559 char *maddr; 560 561 /* getifaddrs will return one public address on each of two subnets */ 562 mock_igb1(true); 563 mock_igb0(); 564 mock_lo0(); 565 566 maddr = do_addrmerge4(NULL); 567 568 /* We must return the address to which we are bound */ 569 ATF_REQUIRE(maddr != NULL); 570 ATF_CHECK_STREQ("192.0.2.3.3.46", maddr); 571 free(maddr); 572 } 573 574 /* 575 * The address on which the request was received is known, and is provided as 576 * the hint. 577 */ 578 ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr); 579 ATF_TC_BODY(addrmerge_recvdstaddr, tc) 580 { 581 char *maddr; 582 583 mock_lo0(); 584 mock_igb0(); 585 mock_igb1(false); 586 587 maddr = do_addrmerge4("192.0.2.2.3.46"); 588 589 /* We must return the address on which the request was received */ 590 ATF_REQUIRE(maddr != NULL); 591 ATF_CHECK_STREQ("192.0.2.2.3.46", maddr); 592 free(maddr); 593 } 594 595 ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr_rev); 596 ATF_TC_BODY(addrmerge_recvdstaddr_rev, tc) 597 { 598 char *maddr; 599 600 mock_igb1(false); 601 mock_igb0(); 602 mock_lo0(); 603 604 maddr = do_addrmerge4("192.0.2.2.3.46"); 605 606 /* We must return the address on which the request was received */ 607 ATF_REQUIRE(maddr != NULL); 608 ATF_CHECK_STREQ("192.0.2.2.3.46", maddr); 609 free(maddr); 610 } 611 612 #ifdef INET6 613 ATF_TC_WITHOUT_HEAD(addrmerge_localhost_only6); 614 ATF_TC_BODY(addrmerge_localhost_only6, tc) 615 { 616 char *maddr; 617 618 /* getifaddrs will return localhost only */ 619 mock_lo0(); 620 621 maddr = do_addrmerge6(NULL); 622 623 /* We must return localhost if there is nothing better */ 624 ATF_REQUIRE(maddr != NULL); 625 ATF_CHECK_STREQ("::1.3.46", maddr); 626 free(maddr); 627 } 628 629 ATF_TC_WITHOUT_HEAD(addrmerge_singlehomed6); 630 ATF_TC_BODY(addrmerge_singlehomed6, tc) 631 { 632 char *maddr; 633 634 /* getifaddrs will return one public address */ 635 mock_lo0(); 636 mock_igb0(); 637 638 maddr = do_addrmerge6(NULL); 639 640 ATF_REQUIRE(maddr != NULL); 641 ATF_CHECK_STREQ("2001:db8::2.3.46", maddr); 642 free(maddr); 643 } 644 645 ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet6); 646 ATF_TC_BODY(addrmerge_one_addr_on_each_subnet6, tc) 647 { 648 char *maddr; 649 650 mock_lo0(); 651 mock_igb0(); 652 mock_igb2(); 653 654 maddr = do_addrmerge6(NULL); 655 656 /* We must return the address on the caller's subnet */ 657 ATF_REQUIRE(maddr != NULL); 658 ATF_CHECK_STREQ("2001:db8::2.3.46", maddr); 659 free(maddr); 660 } 661 662 663 /* 664 * Like addrmerge_one_addr_on_each_subnet6, but getifaddrs returns a different 665 * order 666 */ 667 ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet6_rev); 668 ATF_TC_BODY(addrmerge_one_addr_on_each_subnet6_rev, tc) 669 { 670 char *maddr; 671 672 /* getifaddrs will return one public address on each of two subnets */ 673 mock_igb2(); 674 mock_igb0(); 675 mock_lo0(); 676 677 maddr = do_addrmerge6(NULL); 678 679 /* We must return the address on the caller's subnet */ 680 ATF_REQUIRE(maddr != NULL); 681 ATF_CHECK_STREQ("2001:db8::2.3.46", maddr); 682 free(maddr); 683 } 684 685 ATF_TC_WITHOUT_HEAD(addrmerge_point2point6); 686 ATF_TC_BODY(addrmerge_point2point6, tc) 687 { 688 char *maddr; 689 690 /* getifaddrs will return one normal and one p2p address */ 691 mock_lo0(); 692 mock_igb2(); 693 mock_tun0(); 694 695 maddr = do_addrmerge6(NULL); 696 697 /* addrmerge should disprefer P2P interfaces */ 698 ATF_REQUIRE(maddr != NULL); 699 ATF_CHECK_STREQ("2001:db8:1::2.3.46", maddr); 700 free(maddr); 701 } 702 703 /* Like addrerge_point2point, but getifaddrs returns a different order */ 704 ATF_TC_WITHOUT_HEAD(addrmerge_point2point6_rev); 705 ATF_TC_BODY(addrmerge_point2point6_rev, tc) 706 { 707 char *maddr; 708 709 /* getifaddrs will return one normal and one p2p address */ 710 mock_tun0(); 711 mock_igb2(); 712 mock_lo0(); 713 714 maddr = do_addrmerge6(NULL); 715 716 /* addrmerge should disprefer P2P interfaces */ 717 ATF_REQUIRE(maddr != NULL); 718 ATF_CHECK_STREQ("2001:db8:1::2.3.46", maddr); 719 free(maddr); 720 } 721 722 ATF_TC_WITHOUT_HEAD(addrmerge_bindip6); 723 ATF_TC_BODY(addrmerge_bindip6, tc) 724 { 725 char *maddr; 726 727 /* getifaddrs will return one public address on each of two subnets */ 728 mock_lo0(); 729 mock_igb0(); 730 mock_igb1(true); 731 732 maddr = do_addrmerge6(NULL); 733 734 /* We must return the address to which we are bound */ 735 ATF_REQUIRE(maddr != NULL); 736 ATF_CHECK_STREQ("2001:db8::3.3.46", maddr); 737 free(maddr); 738 } 739 740 /* Like addrerge_bindip, but getifaddrs returns a different order */ 741 ATF_TC_WITHOUT_HEAD(addrmerge_bindip6_rev); 742 ATF_TC_BODY(addrmerge_bindip6_rev, tc) 743 { 744 char *maddr; 745 746 /* getifaddrs will return one public address on each of two subnets */ 747 mock_igb1(true); 748 mock_igb0(); 749 mock_lo0(); 750 751 maddr = do_addrmerge6(NULL); 752 753 /* We must return the address to which we are bound */ 754 ATF_REQUIRE(maddr != NULL); 755 ATF_CHECK_STREQ("2001:db8::3.3.46", maddr); 756 free(maddr); 757 } 758 759 /* 760 * IPv6 Link Local addresses with the same scope id as the caller, if the caller 761 * is also a link local address, should be preferred 762 */ 763 ATF_TC_WITHOUT_HEAD(addrmerge_ipv6_linklocal); 764 ATF_TC_BODY(addrmerge_ipv6_linklocal, tc) 765 { 766 char *maddr; 767 768 /* 769 * getifaddrs will return two link local addresses with the same netmask 770 * and prefix but different scope IDs 771 */ 772 mock_igb1(false); 773 mock_igb0(); 774 mock_lo0(); 775 776 maddr = do_addrmerge6_ll(); 777 778 /* We must return the address to which we are bound */ 779 ATF_REQUIRE(maddr != NULL); 780 ATF_CHECK_STREQ("fe80::2.3.46", maddr); 781 free(maddr); 782 } 783 784 ATF_TC_WITHOUT_HEAD(addrmerge_ipv6_linklocal_rev); 785 ATF_TC_BODY(addrmerge_ipv6_linklocal_rev, tc) 786 { 787 char *maddr; 788 789 /* 790 * getifaddrs will return two link local addresses with the same netmask 791 * and prefix but different scope IDs 792 */ 793 mock_lo0(); 794 mock_igb0(); 795 mock_igb1(false); 796 797 maddr = do_addrmerge6_ll(); 798 799 /* We must return the address to which we are bound */ 800 ATF_REQUIRE(maddr != NULL); 801 ATF_CHECK_STREQ("fe80::2.3.46", maddr); 802 free(maddr); 803 } 804 805 ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr6); 806 ATF_TC_BODY(addrmerge_recvdstaddr6, tc) 807 { 808 char *maddr; 809 810 mock_lo0(); 811 mock_igb0(); 812 mock_igb1(false); 813 814 maddr = do_addrmerge6("2001:db8::2.3.46"); 815 816 /* We must return the address on which the request was received */ 817 ATF_REQUIRE(maddr != NULL); 818 ATF_CHECK_STREQ("2001:db8::2.3.46", maddr); 819 free(maddr); 820 } 821 822 ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr6_rev); 823 ATF_TC_BODY(addrmerge_recvdstaddr6_rev, tc) 824 { 825 char *maddr; 826 827 mock_igb1(false); 828 mock_igb0(); 829 mock_lo0(); 830 831 maddr = do_addrmerge6("2001:db8::2.3.46"); 832 833 /* We must return the address on which the request was received */ 834 ATF_REQUIRE(maddr != NULL); 835 ATF_CHECK_STREQ("2001:db8::2.3.46", maddr); 836 free(maddr); 837 } 838 #endif /* INET6 */ 839 840 841 ATF_TP_ADD_TCS(tp) 842 { 843 ATF_TP_ADD_TC(tp, addrmerge_noifaddrs); 844 ATF_TP_ADD_TC(tp, addrmerge_localhost_only); 845 ATF_TP_ADD_TC(tp, addrmerge_singlehomed); 846 ATF_TP_ADD_TC(tp, addrmerge_one_addr_on_each_subnet); 847 ATF_TP_ADD_TC(tp, addrmerge_one_addr_on_each_subnet_rev); 848 ATF_TP_ADD_TC(tp, addrmerge_point2point); 849 ATF_TP_ADD_TC(tp, addrmerge_point2point_rev); 850 ATF_TP_ADD_TC(tp, addrmerge_bindip); 851 ATF_TP_ADD_TC(tp, addrmerge_bindip_rev); 852 ATF_TP_ADD_TC(tp, addrmerge_recvdstaddr); 853 ATF_TP_ADD_TC(tp, addrmerge_recvdstaddr_rev); 854 #ifdef INET6 855 ATF_TP_ADD_TC(tp, addrmerge_localhost_only6); 856 ATF_TP_ADD_TC(tp, addrmerge_singlehomed6); 857 ATF_TP_ADD_TC(tp, addrmerge_one_addr_on_each_subnet6); 858 ATF_TP_ADD_TC(tp, addrmerge_one_addr_on_each_subnet6_rev); 859 ATF_TP_ADD_TC(tp, addrmerge_point2point6); 860 ATF_TP_ADD_TC(tp, addrmerge_point2point6_rev); 861 ATF_TP_ADD_TC(tp, addrmerge_bindip6); 862 ATF_TP_ADD_TC(tp, addrmerge_bindip6_rev); 863 ATF_TP_ADD_TC(tp, addrmerge_ipv6_linklocal); 864 ATF_TP_ADD_TC(tp, addrmerge_ipv6_linklocal_rev); 865 ATF_TP_ADD_TC(tp, addrmerge_recvdstaddr6); 866 ATF_TP_ADD_TC(tp, addrmerge_recvdstaddr6_rev); 867 #endif 868 869 return (atf_no_error()); 870 } 871