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 static void 261 mock_mlxen0(void) 262 { 263 mock_ifaddr4("mlxen0", "192.0.3.1", "255.255.255.128", "192.0.3.127", 264 IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST, 265 false); 266 /* Setting link local address before ipv6 address*/ 267 mock_ifaddr6("mlxen0", "fe80::4", "ffff:ffff:ffff:ffff::", 268 "fe80::ffff:ffff:ffff:ffff", 269 IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST, 270 3, false); 271 mock_ifaddr6("mlxen0", "2001:db8::7", "ffff:ffff:ffff:ffff::", 272 "2001:db8::ffff:ffff:ffff:ffff", 273 IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST, 274 0, false); 275 } 276 277 /* Stub rpcbind functions */ 278 int 279 listen_addr(const struct sockaddr *sa) 280 { 281 int i; 282 283 if (bind_address_count == 0) 284 return (1); 285 286 for (i = 0; i < bind_address_count; i++) { 287 if (bind_addresses[i]->sa_family != sa->sa_family) 288 continue; 289 290 if (0 == memcmp(bind_addresses[i]->sa_data, sa->sa_data, 291 sa->sa_len)) 292 return (1); 293 } 294 return (0); 295 } 296 297 struct netconfig* 298 rpcbind_get_conf(const char* netid __unused) 299 { 300 /* Use static variables so we can return pointers to them */ 301 static char* lookups = NULL; 302 static struct netconfig nconf_udp; 303 #ifdef INET6 304 static struct netconfig nconf_udp6; 305 #endif /* INET6 */ 306 307 nconf_udp.nc_netid = "udp"; //netid_storage; 308 nconf_udp.nc_semantics = NC_TPI_CLTS; 309 nconf_udp.nc_flag = NC_VISIBLE; 310 nconf_udp.nc_protofmly = (char*)"inet"; 311 nconf_udp.nc_proto = (char*)"udp"; 312 nconf_udp.nc_device = (char*)"-"; 313 nconf_udp.nc_nlookups = 0; 314 nconf_udp.nc_lookups = &lookups; 315 316 #ifdef INET6 317 nconf_udp6.nc_netid = "udp6"; //netid_storage; 318 nconf_udp6.nc_semantics = NC_TPI_CLTS; 319 nconf_udp6.nc_flag = NC_VISIBLE; 320 nconf_udp6.nc_protofmly = (char*)"inet6"; 321 nconf_udp6.nc_proto = (char*)"udp6"; 322 nconf_udp6.nc_device = (char*)"-"; 323 nconf_udp6.nc_nlookups = 0; 324 nconf_udp6.nc_lookups = &lookups; 325 #endif /* INET6 */ 326 327 if (0 == strncmp("udp", netid, sizeof("udp"))) 328 return (&nconf_udp); 329 #ifdef INET6 330 else if (0 == strncmp("udp6", netid, sizeof("udp6"))) 331 return (&nconf_udp6); 332 #endif /* INET6 */ 333 else 334 return (NULL); 335 } 336 337 /* 338 * Helper function used by most test cases 339 * param recvdstaddr If non-null, the uaddr on which the request was received 340 */ 341 static char* 342 do_addrmerge4(const char* recvdstaddr) 343 { 344 struct netbuf caller; 345 struct sockaddr_in caller_in; 346 const char *serv_uaddr, *clnt_uaddr, *netid; 347 348 /* caller contains the client's IP address */ 349 caller.maxlen = sizeof(struct sockaddr_storage); 350 caller.len = sizeof(caller_in); 351 caller_in.sin_family = AF_INET; 352 caller_in.sin_len = sizeof(caller_in); 353 caller_in.sin_port = 1234; 354 caller_in.sin_addr.s_addr = inet_addr("192.0.2.1"); 355 caller.buf = (void*)&caller_in; 356 if (recvdstaddr != NULL) 357 clnt_uaddr = recvdstaddr; 358 else 359 clnt_uaddr = "192.0.2.1.3.46"; 360 361 /* assume server is bound in INADDR_ANY port 814 */ 362 serv_uaddr = "0.0.0.0.3.46"; 363 364 netid = "udp"; 365 return (addrmerge(&caller, serv_uaddr, clnt_uaddr, netid)); 366 } 367 368 #ifdef INET6 369 /* 370 * Variant of do_addrmerge4 where the caller has an IPv6 address 371 * param recvdstaddr If non-null, the uaddr on which the request was received 372 */ 373 static char* 374 do_addrmerge6(const char* recvdstaddr) 375 { 376 struct netbuf caller; 377 struct sockaddr_in6 caller_in6; 378 const char *serv_uaddr, *clnt_uaddr, *netid; 379 380 /* caller contains the client's IP address */ 381 caller.maxlen = sizeof(struct sockaddr_storage); 382 caller.len = sizeof(caller_in6); 383 caller_in6.sin6_family = AF_INET6; 384 caller_in6.sin6_len = sizeof(caller_in6); 385 caller_in6.sin6_port = 1234; 386 ATF_REQUIRE_EQ(1, inet_pton(AF_INET6, "2001:db8::1", 387 (void*)&caller_in6.sin6_addr)); 388 caller.buf = (void*)&caller_in6; 389 if (recvdstaddr != NULL) 390 clnt_uaddr = recvdstaddr; 391 else 392 clnt_uaddr = "2001:db8::1.3.46"; 393 394 /* assume server is bound in INADDR_ANY port 814 */ 395 serv_uaddr = "::1.3.46"; 396 397 netid = "udp6"; 398 return (addrmerge(&caller, serv_uaddr, clnt_uaddr, netid)); 399 } 400 401 /* Variant of do_addrmerge6 where the caller uses a link local address */ 402 static char* 403 do_addrmerge6_ll(void) 404 { 405 struct netbuf caller; 406 struct sockaddr_in6 caller_in6; 407 const char *serv_uaddr, *clnt_uaddr, *netid; 408 409 /* caller contains the client's IP address */ 410 caller.maxlen = sizeof(struct sockaddr_storage); 411 caller.len = sizeof(caller_in6); 412 caller_in6.sin6_family = AF_INET6; 413 caller_in6.sin6_len = sizeof(caller_in6); 414 caller_in6.sin6_port = 1234; 415 caller_in6.sin6_scope_id = 2; /* same as igb0 */ 416 ATF_REQUIRE_EQ(1, inet_pton(AF_INET6, "fe80::beef", 417 (void*)&caller_in6.sin6_addr)); 418 caller.buf = (void*)&caller_in6; 419 clnt_uaddr = "fe80::beef.3.46"; 420 421 /* assume server is bound in INADDR_ANY port 814 */ 422 serv_uaddr = "::1.3.46"; 423 424 netid = "udp6"; 425 return (addrmerge(&caller, serv_uaddr, clnt_uaddr, netid)); 426 } 427 #endif /* INET6 */ 428 429 ATF_TC_WITHOUT_HEAD(addrmerge_noifaddrs); 430 ATF_TC_BODY(addrmerge_noifaddrs, tc) 431 { 432 char* maddr; 433 434 maddr = do_addrmerge4(NULL); 435 436 /* Since getifaddrs returns null, addrmerge must too */ 437 ATF_CHECK_EQ(NULL, maddr); 438 } 439 440 ATF_TC_WITHOUT_HEAD(addrmerge_localhost_only); 441 ATF_TC_BODY(addrmerge_localhost_only, tc) 442 { 443 char *maddr; 444 445 /* getifaddrs will return localhost only */ 446 mock_lo0(); 447 448 maddr = do_addrmerge4(NULL); 449 450 /* We must return localhost if there is nothing better */ 451 ATF_REQUIRE(maddr != NULL); 452 ATF_CHECK_STREQ("127.0.0.1.3.46", maddr); 453 free(maddr); 454 } 455 456 ATF_TC_WITHOUT_HEAD(addrmerge_singlehomed); 457 ATF_TC_BODY(addrmerge_singlehomed, tc) 458 { 459 char *maddr; 460 461 /* getifaddrs will return one public address */ 462 mock_lo0(); 463 mock_igb0(); 464 465 maddr = do_addrmerge4(NULL); 466 467 ATF_REQUIRE(maddr != NULL); 468 ATF_CHECK_STREQ("192.0.2.2.3.46", maddr); 469 free(maddr); 470 } 471 472 ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet); 473 ATF_TC_BODY(addrmerge_one_addr_on_each_subnet, tc) 474 { 475 char *maddr; 476 477 mock_lo0(); 478 mock_igb0(); 479 mock_igb2(); 480 481 maddr = do_addrmerge4(NULL); 482 483 /* We must return the address on the caller's subnet */ 484 ATF_REQUIRE(maddr != NULL); 485 ATF_CHECK_STREQ("192.0.2.2.3.46", maddr); 486 free(maddr); 487 } 488 489 490 /* 491 * Like addrmerge_one_addr_on_each_subnet, but getifaddrs returns a different 492 * order 493 */ 494 ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet_rev); 495 ATF_TC_BODY(addrmerge_one_addr_on_each_subnet_rev, tc) 496 { 497 char *maddr; 498 499 /* getifaddrs will return one public address on each of two subnets */ 500 mock_igb2(); 501 mock_igb0(); 502 mock_lo0(); 503 504 maddr = do_addrmerge4(NULL); 505 506 /* We must return the address on the caller's subnet */ 507 ATF_REQUIRE(maddr != NULL); 508 ATF_CHECK_STREQ("192.0.2.2.3.46", maddr); 509 free(maddr); 510 } 511 512 ATF_TC_WITHOUT_HEAD(addrmerge_point2point); 513 ATF_TC_BODY(addrmerge_point2point, tc) 514 { 515 char *maddr; 516 517 /* getifaddrs will return one normal and one p2p address */ 518 mock_lo0(); 519 mock_igb2(); 520 mock_tun0(); 521 522 maddr = do_addrmerge4(NULL); 523 524 /* addrmerge should disprefer P2P interfaces */ 525 ATF_REQUIRE(maddr != NULL); 526 ATF_CHECK_STREQ("192.0.2.130.3.46", maddr); 527 free(maddr); 528 } 529 530 /* Like addrerge_point2point, but getifaddrs returns a different order */ 531 ATF_TC_WITHOUT_HEAD(addrmerge_point2point_rev); 532 ATF_TC_BODY(addrmerge_point2point_rev, tc) 533 { 534 char *maddr; 535 536 /* getifaddrs will return one normal and one p2p address */ 537 mock_tun0(); 538 mock_igb2(); 539 mock_lo0(); 540 541 maddr = do_addrmerge4(NULL); 542 543 /* addrmerge should disprefer P2P interfaces */ 544 ATF_REQUIRE(maddr != NULL); 545 ATF_CHECK_STREQ("192.0.2.130.3.46", maddr); 546 free(maddr); 547 } 548 549 /* 550 * Simulate using rpcbind -h to select just one ip when the subnet has 551 * multiple 552 */ 553 ATF_TC_WITHOUT_HEAD(addrmerge_bindip); 554 ATF_TC_BODY(addrmerge_bindip, tc) 555 { 556 char *maddr; 557 558 /* getifaddrs will return one public address on each of two subnets */ 559 mock_lo0(); 560 mock_igb0(); 561 mock_igb1(true); 562 563 maddr = do_addrmerge4(NULL); 564 565 /* We must return the address to which we are bound */ 566 ATF_REQUIRE(maddr != NULL); 567 ATF_CHECK_STREQ("192.0.2.3.3.46", maddr); 568 free(maddr); 569 } 570 571 /* Like addrmerge_bindip, but getifaddrs returns a different order */ 572 ATF_TC_WITHOUT_HEAD(addrmerge_bindip_rev); 573 ATF_TC_BODY(addrmerge_bindip_rev, tc) 574 { 575 char *maddr; 576 577 /* getifaddrs will return one public address on each of two subnets */ 578 mock_igb1(true); 579 mock_igb0(); 580 mock_lo0(); 581 582 maddr = do_addrmerge4(NULL); 583 584 /* We must return the address to which we are bound */ 585 ATF_REQUIRE(maddr != NULL); 586 ATF_CHECK_STREQ("192.0.2.3.3.46", maddr); 587 free(maddr); 588 } 589 590 /* 591 * The address on which the request was received is known, and is provided as 592 * the hint. 593 */ 594 ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr); 595 ATF_TC_BODY(addrmerge_recvdstaddr, tc) 596 { 597 char *maddr; 598 599 mock_lo0(); 600 mock_igb0(); 601 mock_igb1(false); 602 603 maddr = do_addrmerge4("192.0.2.2.3.46"); 604 605 /* We must return the address on which the request was received */ 606 ATF_REQUIRE(maddr != NULL); 607 ATF_CHECK_STREQ("192.0.2.2.3.46", maddr); 608 free(maddr); 609 } 610 611 ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr_rev); 612 ATF_TC_BODY(addrmerge_recvdstaddr_rev, tc) 613 { 614 char *maddr; 615 616 mock_igb1(false); 617 mock_igb0(); 618 mock_lo0(); 619 620 maddr = do_addrmerge4("192.0.2.2.3.46"); 621 622 /* We must return the address on which the request was received */ 623 ATF_REQUIRE(maddr != NULL); 624 ATF_CHECK_STREQ("192.0.2.2.3.46", maddr); 625 free(maddr); 626 } 627 628 #ifdef INET6 629 ATF_TC_WITHOUT_HEAD(addrmerge_localhost_only6); 630 ATF_TC_BODY(addrmerge_localhost_only6, tc) 631 { 632 char *maddr; 633 634 /* getifaddrs will return localhost only */ 635 mock_lo0(); 636 637 maddr = do_addrmerge6(NULL); 638 639 /* We must return localhost if there is nothing better */ 640 ATF_REQUIRE(maddr != NULL); 641 ATF_CHECK_STREQ("::1.3.46", maddr); 642 free(maddr); 643 } 644 645 ATF_TC_WITHOUT_HEAD(addrmerge_singlehomed6); 646 ATF_TC_BODY(addrmerge_singlehomed6, tc) 647 { 648 char *maddr; 649 650 /* getifaddrs will return one public address */ 651 mock_lo0(); 652 mock_igb0(); 653 654 maddr = do_addrmerge6(NULL); 655 656 ATF_REQUIRE(maddr != NULL); 657 ATF_CHECK_STREQ("2001:db8::2.3.46", maddr); 658 free(maddr); 659 } 660 661 ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet6); 662 ATF_TC_BODY(addrmerge_one_addr_on_each_subnet6, tc) 663 { 664 char *maddr; 665 666 mock_lo0(); 667 mock_igb0(); 668 mock_igb2(); 669 670 maddr = do_addrmerge6(NULL); 671 672 /* We must return the address on the caller's subnet */ 673 ATF_REQUIRE(maddr != NULL); 674 ATF_CHECK_STREQ("2001:db8::2.3.46", maddr); 675 free(maddr); 676 } 677 678 679 /* 680 * Like addrmerge_one_addr_on_each_subnet6, but getifaddrs returns a different 681 * order 682 */ 683 ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet6_rev); 684 ATF_TC_BODY(addrmerge_one_addr_on_each_subnet6_rev, tc) 685 { 686 char *maddr; 687 688 /* getifaddrs will return one public address on each of two subnets */ 689 mock_igb2(); 690 mock_igb0(); 691 mock_lo0(); 692 693 maddr = do_addrmerge6(NULL); 694 695 /* We must return the address on the caller's subnet */ 696 ATF_REQUIRE(maddr != NULL); 697 ATF_CHECK_STREQ("2001:db8::2.3.46", maddr); 698 free(maddr); 699 } 700 701 ATF_TC_WITHOUT_HEAD(addrmerge_point2point6); 702 ATF_TC_BODY(addrmerge_point2point6, tc) 703 { 704 char *maddr; 705 706 /* getifaddrs will return one normal and one p2p address */ 707 mock_lo0(); 708 mock_igb2(); 709 mock_tun0(); 710 711 maddr = do_addrmerge6(NULL); 712 713 /* addrmerge should disprefer P2P interfaces */ 714 ATF_REQUIRE(maddr != NULL); 715 ATF_CHECK_STREQ("2001:db8:1::2.3.46", maddr); 716 free(maddr); 717 } 718 719 /* Like addrerge_point2point, but getifaddrs returns a different order */ 720 ATF_TC_WITHOUT_HEAD(addrmerge_point2point6_rev); 721 ATF_TC_BODY(addrmerge_point2point6_rev, tc) 722 { 723 char *maddr; 724 725 /* getifaddrs will return one normal and one p2p address */ 726 mock_tun0(); 727 mock_igb2(); 728 mock_lo0(); 729 730 maddr = do_addrmerge6(NULL); 731 732 /* addrmerge should disprefer P2P interfaces */ 733 ATF_REQUIRE(maddr != NULL); 734 ATF_CHECK_STREQ("2001:db8:1::2.3.46", maddr); 735 free(maddr); 736 } 737 738 ATF_TC_WITHOUT_HEAD(addrmerge_bindip6); 739 ATF_TC_BODY(addrmerge_bindip6, tc) 740 { 741 char *maddr; 742 743 /* getifaddrs will return one public address on each of two subnets */ 744 mock_lo0(); 745 mock_igb0(); 746 mock_igb1(true); 747 748 maddr = do_addrmerge6(NULL); 749 750 /* We must return the address to which we are bound */ 751 ATF_REQUIRE(maddr != NULL); 752 ATF_CHECK_STREQ("2001:db8::3.3.46", maddr); 753 free(maddr); 754 } 755 756 /* Like addrerge_bindip, but getifaddrs returns a different order */ 757 ATF_TC_WITHOUT_HEAD(addrmerge_bindip6_rev); 758 ATF_TC_BODY(addrmerge_bindip6_rev, tc) 759 { 760 char *maddr; 761 762 /* getifaddrs will return one public address on each of two subnets */ 763 mock_igb1(true); 764 mock_igb0(); 765 mock_lo0(); 766 767 maddr = do_addrmerge6(NULL); 768 769 /* We must return the address to which we are bound */ 770 ATF_REQUIRE(maddr != NULL); 771 ATF_CHECK_STREQ("2001:db8::3.3.46", maddr); 772 free(maddr); 773 } 774 775 /* 776 * IPv6 Link Local addresses with the same scope id as the caller, if the caller 777 * is also a link local address, should be preferred 778 */ 779 ATF_TC_WITHOUT_HEAD(addrmerge_ipv6_linklocal); 780 ATF_TC_BODY(addrmerge_ipv6_linklocal, tc) 781 { 782 char *maddr; 783 784 /* 785 * getifaddrs will return two link local addresses with the same netmask 786 * and prefix but different scope IDs 787 */ 788 mock_igb1(false); 789 mock_igb0(); 790 mock_lo0(); 791 792 maddr = do_addrmerge6_ll(); 793 794 /* We must return the address to which we are bound */ 795 ATF_REQUIRE(maddr != NULL); 796 ATF_CHECK_STREQ("fe80::2.3.46", maddr); 797 free(maddr); 798 } 799 800 ATF_TC_WITHOUT_HEAD(addrmerge_ipv6_linklocal_rev); 801 ATF_TC_BODY(addrmerge_ipv6_linklocal_rev, tc) 802 { 803 char *maddr; 804 805 /* 806 * getifaddrs will return two link local addresses with the same netmask 807 * and prefix but different scope IDs 808 */ 809 mock_lo0(); 810 mock_igb0(); 811 mock_igb1(false); 812 813 maddr = do_addrmerge6_ll(); 814 815 /* We must return the address to which we are bound */ 816 ATF_REQUIRE(maddr != NULL); 817 ATF_CHECK_STREQ("fe80::2.3.46", maddr); 818 free(maddr); 819 } 820 821 ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr6); 822 ATF_TC_BODY(addrmerge_recvdstaddr6, tc) 823 { 824 char *maddr; 825 826 mock_lo0(); 827 mock_igb0(); 828 mock_igb1(false); 829 830 maddr = do_addrmerge6("2001:db8::2.3.46"); 831 832 /* We must return the address on which the request was received */ 833 ATF_REQUIRE(maddr != NULL); 834 ATF_CHECK_STREQ("2001:db8::2.3.46", maddr); 835 free(maddr); 836 } 837 838 ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr6_rev); 839 ATF_TC_BODY(addrmerge_recvdstaddr6_rev, tc) 840 { 841 char *maddr; 842 843 mock_igb1(false); 844 mock_igb0(); 845 mock_lo0(); 846 847 maddr = do_addrmerge6("2001:db8::2.3.46"); 848 849 /* We must return the address on which the request was received */ 850 ATF_REQUIRE(maddr != NULL); 851 ATF_CHECK_STREQ("2001:db8::2.3.46", maddr); 852 free(maddr); 853 } 854 855 ATF_TC_WITHOUT_HEAD(addrmerge_ipv6_other_subnet); 856 ATF_TC_BODY(addrmerge_ipv6_other_subnet, tc) 857 { 858 char *maddr; 859 860 /* getifaddrs will return link local before normal ipv6 */ 861 mock_lo0(); 862 mock_mlxen0(); 863 864 maddr = do_addrmerge6("2001:db8:1::1.3.46"); 865 866 /* We must return the closest ipv6 address*/ 867 ATF_REQUIRE(maddr != NULL); 868 ATF_CHECK_STREQ("2001:db8::7.3.46", maddr); 869 free(maddr); 870 } 871 #endif /* INET6 */ 872 873 874 ATF_TP_ADD_TCS(tp) 875 { 876 ATF_TP_ADD_TC(tp, addrmerge_noifaddrs); 877 ATF_TP_ADD_TC(tp, addrmerge_localhost_only); 878 ATF_TP_ADD_TC(tp, addrmerge_singlehomed); 879 ATF_TP_ADD_TC(tp, addrmerge_one_addr_on_each_subnet); 880 ATF_TP_ADD_TC(tp, addrmerge_one_addr_on_each_subnet_rev); 881 ATF_TP_ADD_TC(tp, addrmerge_point2point); 882 ATF_TP_ADD_TC(tp, addrmerge_point2point_rev); 883 ATF_TP_ADD_TC(tp, addrmerge_bindip); 884 ATF_TP_ADD_TC(tp, addrmerge_bindip_rev); 885 ATF_TP_ADD_TC(tp, addrmerge_recvdstaddr); 886 ATF_TP_ADD_TC(tp, addrmerge_recvdstaddr_rev); 887 #ifdef INET6 888 ATF_TP_ADD_TC(tp, addrmerge_localhost_only6); 889 ATF_TP_ADD_TC(tp, addrmerge_singlehomed6); 890 ATF_TP_ADD_TC(tp, addrmerge_one_addr_on_each_subnet6); 891 ATF_TP_ADD_TC(tp, addrmerge_one_addr_on_each_subnet6_rev); 892 ATF_TP_ADD_TC(tp, addrmerge_point2point6); 893 ATF_TP_ADD_TC(tp, addrmerge_point2point6_rev); 894 ATF_TP_ADD_TC(tp, addrmerge_bindip6); 895 ATF_TP_ADD_TC(tp, addrmerge_bindip6_rev); 896 ATF_TP_ADD_TC(tp, addrmerge_ipv6_linklocal); 897 ATF_TP_ADD_TC(tp, addrmerge_ipv6_linklocal_rev); 898 ATF_TP_ADD_TC(tp, addrmerge_recvdstaddr6); 899 ATF_TP_ADD_TC(tp, addrmerge_recvdstaddr6_rev); 900 ATF_TP_ADD_TC(tp, addrmerge_ipv6_other_subnet); 901 #endif 902 903 return (atf_no_error()); 904 } 905