2 * Copyright (c) 2014 Spectra Logic Corporation
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
34 #include <sys/types.h>
35 #include <sys/socket.h>
38 #include <netinet/in.h>
39 #include <arpa/inet.h>
49 #define MAX_IFADDRS 16
51 int debugging = false;
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;
63 /* Data for mocking listen_addr */
64 int bind_address_count = 0;
65 struct sockaddr* bind_addresses[MAX_IFADDRS];
67 /* Stub library functions */
69 freeifaddrs(struct ifaddrs *ifp __unused)
75 getifaddrs(struct ifaddrs **ifap)
82 mock_ifaddr4(const char* name, const char* addr, const char* mask,
83 const char* bcast, unsigned int flags, bool bind)
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;
93 in->sin_family = AF_INET;
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) {
107 .ifa_name = (char*) name,
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*/
115 if (ifaddr_count > 0)
116 mock_ifaddr_storage[ifaddr_count - 1].ifaddr.ifa_next = ifaddr;
118 mock_ifaddrs = &mock_ifaddr_storage[0].ifaddr;
120 /* Optionally simulate binding an ip ala "rpcbind -h foo" */
122 bind_addresses[bind_address_count] = (struct sockaddr*)in;
123 bind_address_count++;
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)
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;
140 in6->sin6_family = AF_INET6;
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) {
159 .ifa_name = (char*) name,
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*/
167 if (ifaddr_count > 0)
168 mock_ifaddr_storage[ifaddr_count - 1].ifaddr.ifa_next = ifaddr;
170 mock_ifaddrs = &mock_ifaddr_storage[0].ifaddr;
172 /* Optionally simulate binding an ip ala "rpcbind -h foo" */
174 bind_addresses[bind_address_count] = (struct sockaddr*)in6;
175 bind_address_count++;
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)
191 * This broadcast address looks wrong, but it's what getifaddrs(2)
192 * actually returns. It's invalid because IFF_BROADCAST is not set
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",
198 IFF_LOOPBACK | IFF_UP | IFF_RUNNING | IFF_MULTICAST, 0, false);
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,
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,
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,
218 /* On the same subnet as igb0 */
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,
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,
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,
236 /* igb2 is on a different subnet than igb0 */
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,
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,
249 /* tun0 is a P2P interface */
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",
258 IFF_UP | IFF_RUNNING | IFF_POINTOPOINT | IFF_MULTICAST, 0, false);
262 /* Stub rpcbind functions */
264 listen_addr(const struct sockaddr *sa)
268 if (bind_address_count == 0)
271 for (i = 0; i < bind_address_count; i++) {
272 if (bind_addresses[i]->sa_family != sa->sa_family)
275 if (0 == memcmp(bind_addresses[i]->sa_data, sa->sa_data,
283 rpcbind_get_conf(const char* netid __unused)
285 /* Use static variables so we can return pointers to them */
286 static char* lookups = NULL;
287 static struct netconfig nconf_udp;
289 static struct netconfig nconf_udp6;
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;
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;
312 if (0 == strncmp("udp", netid, sizeof("udp")))
315 else if (0 == strncmp("udp6", netid, sizeof("udp6")))
316 return (&nconf_udp6);
323 * Helper function used by most test cases
324 * param recvdstaddr If non-null, the uaddr on which the request was received
327 do_addrmerge4(const char* recvdstaddr)
329 struct netbuf caller;
330 struct sockaddr_in caller_in;
331 const char *serv_uaddr, *clnt_uaddr, *netid;
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;
344 clnt_uaddr = "192.0.2.1.3.46";
346 /* assume server is bound in INADDR_ANY port 814 */
347 serv_uaddr = "0.0.0.0.3.46";
350 return (addrmerge(&caller, serv_uaddr, clnt_uaddr, netid));
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
359 do_addrmerge6(const char* recvdstaddr)
361 struct netbuf caller;
362 struct sockaddr_in6 caller_in6;
363 const char *serv_uaddr, *clnt_uaddr, *netid;
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;
377 clnt_uaddr = "2001:db8::1.3.46";
379 /* assume server is bound in INADDR_ANY port 814 */
380 serv_uaddr = "::1.3.46";
383 return (addrmerge(&caller, serv_uaddr, clnt_uaddr, netid));
386 /* Variant of do_addrmerge6 where the caller uses a link local address */
388 do_addrmerge6_ll(void)
390 struct netbuf caller;
391 struct sockaddr_in6 caller_in6;
392 const char *serv_uaddr, *clnt_uaddr, *netid;
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";
406 /* assume server is bound in INADDR_ANY port 814 */
407 serv_uaddr = "::1.3.46";
410 return (addrmerge(&caller, serv_uaddr, clnt_uaddr, netid));
414 ATF_TC_WITHOUT_HEAD(addrmerge_noifaddrs);
415 ATF_TC_BODY(addrmerge_noifaddrs, tc)
419 maddr = do_addrmerge4(NULL);
421 /* Since getifaddrs returns null, addrmerge must too */
422 ATF_CHECK_EQ(NULL, maddr);
425 ATF_TC_WITHOUT_HEAD(addrmerge_localhost_only);
426 ATF_TC_BODY(addrmerge_localhost_only, tc)
430 /* getifaddrs will return localhost only */
433 maddr = do_addrmerge4(NULL);
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);
441 ATF_TC_WITHOUT_HEAD(addrmerge_singlehomed);
442 ATF_TC_BODY(addrmerge_singlehomed, tc)
446 /* getifaddrs will return one public address */
450 maddr = do_addrmerge4(NULL);
452 ATF_REQUIRE(maddr != NULL);
453 ATF_CHECK_STREQ("192.0.2.2.3.46", maddr);
457 ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet);
458 ATF_TC_BODY(addrmerge_one_addr_on_each_subnet, tc)
466 maddr = do_addrmerge4(NULL);
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);
476 * Like addrmerge_one_addr_on_each_subnet, but getifaddrs returns a different
479 ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet_rev);
480 ATF_TC_BODY(addrmerge_one_addr_on_each_subnet_rev, tc)
484 /* getifaddrs will return one public address on each of two subnets */
489 maddr = do_addrmerge4(NULL);
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);
497 ATF_TC_WITHOUT_HEAD(addrmerge_point2point);
498 ATF_TC_BODY(addrmerge_point2point, tc)
502 /* getifaddrs will return one normal and one p2p address */
507 maddr = do_addrmerge4(NULL);
509 /* addrmerge should disprefer P2P interfaces */
510 ATF_REQUIRE(maddr != NULL);
511 ATF_CHECK_STREQ("192.0.2.130.3.46", maddr);
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)
521 /* getifaddrs will return one normal and one p2p address */
526 maddr = do_addrmerge4(NULL);
528 /* addrmerge should disprefer P2P interfaces */
529 ATF_REQUIRE(maddr != NULL);
530 ATF_CHECK_STREQ("192.0.2.130.3.46", maddr);
535 * Simulate using rpcbind -h to select just one ip when the subnet has
538 ATF_TC_WITHOUT_HEAD(addrmerge_bindip);
539 ATF_TC_BODY(addrmerge_bindip, tc)
543 /* getifaddrs will return one public address on each of two subnets */
548 maddr = do_addrmerge4(NULL);
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);
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)
562 /* getifaddrs will return one public address on each of two subnets */
567 maddr = do_addrmerge4(NULL);
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);
576 * The address on which the request was received is known, and is provided as
579 ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr);
580 ATF_TC_BODY(addrmerge_recvdstaddr, tc)
588 maddr = do_addrmerge4("192.0.2.2.3.46");
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);
596 ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr_rev);
597 ATF_TC_BODY(addrmerge_recvdstaddr_rev, tc)
605 maddr = do_addrmerge4("192.0.2.2.3.46");
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);
614 ATF_TC_WITHOUT_HEAD(addrmerge_localhost_only6);
615 ATF_TC_BODY(addrmerge_localhost_only6, tc)
619 /* getifaddrs will return localhost only */
622 maddr = do_addrmerge6(NULL);
624 /* We must return localhost if there is nothing better */
625 ATF_REQUIRE(maddr != NULL);
626 ATF_CHECK_STREQ("::1.3.46", maddr);
630 ATF_TC_WITHOUT_HEAD(addrmerge_singlehomed6);
631 ATF_TC_BODY(addrmerge_singlehomed6, tc)
635 /* getifaddrs will return one public address */
639 maddr = do_addrmerge6(NULL);
641 ATF_REQUIRE(maddr != NULL);
642 ATF_CHECK_STREQ("2001:db8::2.3.46", maddr);
646 ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet6);
647 ATF_TC_BODY(addrmerge_one_addr_on_each_subnet6, tc)
655 maddr = do_addrmerge6(NULL);
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);
665 * Like addrmerge_one_addr_on_each_subnet6, but getifaddrs returns a different
668 ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet6_rev);
669 ATF_TC_BODY(addrmerge_one_addr_on_each_subnet6_rev, tc)
673 /* getifaddrs will return one public address on each of two subnets */
678 maddr = do_addrmerge6(NULL);
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);
686 ATF_TC_WITHOUT_HEAD(addrmerge_point2point6);
687 ATF_TC_BODY(addrmerge_point2point6, tc)
691 /* getifaddrs will return one normal and one p2p address */
696 maddr = do_addrmerge6(NULL);
698 /* addrmerge should disprefer P2P interfaces */
699 ATF_REQUIRE(maddr != NULL);
700 ATF_CHECK_STREQ("2001:db8:1::2.3.46", maddr);
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)
710 /* getifaddrs will return one normal and one p2p address */
715 maddr = do_addrmerge6(NULL);
717 /* addrmerge should disprefer P2P interfaces */
718 ATF_REQUIRE(maddr != NULL);
719 ATF_CHECK_STREQ("2001:db8:1::2.3.46", maddr);
723 ATF_TC_WITHOUT_HEAD(addrmerge_bindip6);
724 ATF_TC_BODY(addrmerge_bindip6, tc)
728 /* getifaddrs will return one public address on each of two subnets */
733 maddr = do_addrmerge6(NULL);
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);
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)
747 /* getifaddrs will return one public address on each of two subnets */
752 maddr = do_addrmerge6(NULL);
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);
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
764 ATF_TC_WITHOUT_HEAD(addrmerge_ipv6_linklocal);
765 ATF_TC_BODY(addrmerge_ipv6_linklocal, tc)
770 * getifaddrs will return two link local addresses with the same netmask
771 * and prefix but different scope IDs
777 maddr = do_addrmerge6_ll();
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);
785 ATF_TC_WITHOUT_HEAD(addrmerge_ipv6_linklocal_rev);
786 ATF_TC_BODY(addrmerge_ipv6_linklocal_rev, tc)
791 * getifaddrs will return two link local addresses with the same netmask
792 * and prefix but different scope IDs
798 maddr = do_addrmerge6_ll();
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);
806 ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr6);
807 ATF_TC_BODY(addrmerge_recvdstaddr6, tc)
815 maddr = do_addrmerge6("2001:db8::2.3.46");
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);
823 ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr6_rev);
824 ATF_TC_BODY(addrmerge_recvdstaddr6_rev, tc)
832 maddr = do_addrmerge6("2001:db8::2.3.46");
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);
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);
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);
870 return (atf_no_error());