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