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