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