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 48int debugging = false; 49 50/* Data for mocking getifaddrs */ 51struct 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]; 57struct ifaddrs *mock_ifaddrs = NULL; 58int ifaddr_count = 0; 59 60/* Data for mocking listen_addr */ 61int bind_address_count = 0; 62struct sockaddr* bind_addresses[MAX_IFADDRS]; 63 64/* Stub library functions */ 65void 66freeifaddrs(struct ifaddrs *ifp __unused) 67{ 68 return ; 69} 70 71int 72getifaddrs(struct ifaddrs **ifap) 73{ 74 *ifap = mock_ifaddrs; 75 return (0); 76} 77 78static void 79mock_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 125static void 126mock_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 176static void 177mock_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 184static void 185mock_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 198static void 199mock_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 */ 216static void 217mock_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 */ 234static void 235mock_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 */ 247static void 248mock_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 258static void 259mock_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 */ 276int 277listen_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 295struct netconfig* 296rpcbind_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 */ 339static char* 340do_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 */ 371static char* 372do_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 */ 400static char* 401do_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 427ATF_TC_WITHOUT_HEAD(addrmerge_noifaddrs); 428ATF_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 438ATF_TC_WITHOUT_HEAD(addrmerge_localhost_only); 439ATF_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 454ATF_TC_WITHOUT_HEAD(addrmerge_singlehomed); 455ATF_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 470ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet); 471ATF_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 */ 492ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet_rev); 493ATF_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 510ATF_TC_WITHOUT_HEAD(addrmerge_point2point); 511ATF_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 */ 529ATF_TC_WITHOUT_HEAD(addrmerge_point2point_rev); 530ATF_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 */ 551ATF_TC_WITHOUT_HEAD(addrmerge_bindip); 552ATF_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 */ 570ATF_TC_WITHOUT_HEAD(addrmerge_bindip_rev); 571ATF_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 */ 592ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr); 593ATF_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 609ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr_rev); 610ATF_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 627ATF_TC_WITHOUT_HEAD(addrmerge_localhost_only6); 628ATF_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 643ATF_TC_WITHOUT_HEAD(addrmerge_singlehomed6); 644ATF_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 659ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet6); 660ATF_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 */ 681ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet6_rev); 682ATF_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 699ATF_TC_WITHOUT_HEAD(addrmerge_point2point6); 700ATF_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 */ 718ATF_TC_WITHOUT_HEAD(addrmerge_point2point6_rev); 719ATF_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 736ATF_TC_WITHOUT_HEAD(addrmerge_bindip6); 737ATF_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 */ 755ATF_TC_WITHOUT_HEAD(addrmerge_bindip6_rev); 756ATF_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 */ 777ATF_TC_WITHOUT_HEAD(addrmerge_ipv6_linklocal); 778ATF_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 798ATF_TC_WITHOUT_HEAD(addrmerge_ipv6_linklocal_rev); 799ATF_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 819ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr6); 820ATF_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 836ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr6_rev); 837ATF_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 853ATF_TC_WITHOUT_HEAD(addrmerge_ipv6_other_subnet); 854ATF_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 872ATF_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