]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - usr.sbin/rpcbind/tests/addrmerge_test.c
MFC: r346856
[FreeBSD/stable/10.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 #include <stdio.h>
44
45 #include <atf-c.h>
46
47 #include "rpcbind.h"
48
49 #define MAX_IFADDRS 16
50
51 int debugging = false;
52
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;
61 int ifaddr_count = 0; 
62
63 /* Data for mocking listen_addr */
64 int bind_address_count = 0;
65 struct sockaddr* bind_addresses[MAX_IFADDRS];
66
67 /* Stub library functions */
68 void
69 freeifaddrs(struct ifaddrs *ifp __unused)
70 {
71         return ;
72 }
73
74 int
75 getifaddrs(struct ifaddrs **ifap)
76 {
77         *ifap = mock_ifaddrs;
78         return (0);
79 }
80
81 static void
82 mock_ifaddr4(const char* name, const char* addr, const char* mask,
83     const char* bcast, unsigned int flags, bool bind)
84 {
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;
92
93         in->sin_family = AF_INET;
94         in->sin_port = 0;
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) {
106                 .ifa_next = NULL,
107                 .ifa_name = (char*) name,
108                 .ifa_flags = flags,
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*/
113         };
114
115         if (ifaddr_count > 0)
116                 mock_ifaddr_storage[ifaddr_count - 1].ifaddr.ifa_next = ifaddr;
117         ifaddr_count++;
118         mock_ifaddrs = &mock_ifaddr_storage[0].ifaddr;
119
120         /* Optionally simulate binding an ip ala "rpcbind -h foo" */
121         if (bind) {
122                 bind_addresses[bind_address_count] = (struct sockaddr*)in;
123                 bind_address_count++;
124         }
125 }
126
127 #ifdef INET6
128 static void
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)
131 {
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;
139
140         in6->sin6_family = AF_INET6;
141         in6->sin6_port = 0;
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) {
158                 .ifa_next = NULL,
159                 .ifa_name = (char*) name,
160                 .ifa_flags = flags,
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*/
165         };
166
167         if (ifaddr_count > 0)
168                 mock_ifaddr_storage[ifaddr_count - 1].ifaddr.ifa_next = ifaddr;
169         ifaddr_count++;
170         mock_ifaddrs = &mock_ifaddr_storage[0].ifaddr;
171
172         /* Optionally simulate binding an ip ala "rpcbind -h foo" */
173         if (bind) {
174                 bind_addresses[bind_address_count] = (struct sockaddr*)in6;
175                 bind_address_count++;
176         }
177 }
178 #else
179 static void
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)
183 {
184 }
185 #endif /*INET6 */
186
187 static void
188 mock_lo0(void)
189 {
190         /* 
191          * This broadcast address looks wrong, but it's what getifaddrs(2)
192          * actually returns.  It's invalid because IFF_BROADCAST is not set
193          */
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",
197             "::1",
198             IFF_LOOPBACK | IFF_UP | IFF_RUNNING | IFF_MULTICAST, 0, false);
199 }
200
201 static void
202 mock_igb0(void)
203 {
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,
206             false);
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,
210             0, false);
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,
215             2, false);
216 }
217
218 /* On the same subnet as igb0 */
219 static void
220 mock_igb1(bool bind)
221 {
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,
224             bind);
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,
228             0, bind);
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,
233             3, bind);
234 }
235
236 /* igb2 is on a different subnet than igb0 */
237 static void
238 mock_igb2(void)
239 {
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,
242             false);
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,
246             0, false);
247 }
248
249 /* tun0 is a P2P interface */
250 static void
251 mock_tun0(void)
252 {
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",
257             "2001:db8::6",
258             IFF_UP | IFF_RUNNING | IFF_POINTOPOINT | IFF_MULTICAST, 0, false);
259 }
260
261
262 /* Stub rpcbind functions */
263 int
264 listen_addr(const struct sockaddr *sa)
265 {
266         int i;
267         
268         if (bind_address_count == 0)
269                 return (1);
270         
271         for (i = 0; i < bind_address_count; i++) {
272                 if (bind_addresses[i]->sa_family != sa->sa_family)
273                         continue;
274
275                 if (0 == memcmp(bind_addresses[i]->sa_data, sa->sa_data,
276                     sa->sa_len))
277                         return (1);
278         }
279         return (0);
280 }
281
282 struct netconfig*
283 rpcbind_get_conf(const char* netid __unused)
284 {
285         /* Use static variables so we can return pointers to them */
286         static char* lookups = NULL;
287         static struct netconfig nconf_udp;
288 #ifdef INET6
289         static struct netconfig nconf_udp6;
290 #endif /* INET6 */
291
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;
300
301 #ifdef INET6
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;
310 #endif /* INET6 */
311
312         if (0 == strncmp("udp", netid, sizeof("udp")))
313                 return (&nconf_udp);
314 #ifdef INET6
315         else if (0 == strncmp("udp6", netid, sizeof("udp6")))
316                 return (&nconf_udp6);
317 #endif /* INET6 */
318         else
319                 return (NULL);
320 }
321
322 /*
323  * Helper function used by most test cases
324  * param recvdstaddr    If non-null, the uaddr on which the request was received
325  */
326 static char*
327 do_addrmerge4(const char* recvdstaddr)
328 {
329         struct netbuf caller;
330         struct sockaddr_in caller_in;
331         const char *serv_uaddr, *clnt_uaddr, *netid;
332         
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;
343         else
344                 clnt_uaddr = "192.0.2.1.3.46";
345
346         /* assume server is bound in INADDR_ANY port 814 */
347         serv_uaddr = "0.0.0.0.3.46";
348
349         netid = "udp";
350         return (addrmerge(&caller, serv_uaddr, clnt_uaddr, netid));
351 }
352
353 #ifdef INET6
354 /*
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
357  */
358 static char*
359 do_addrmerge6(const char* recvdstaddr)
360 {
361         struct netbuf caller;
362         struct sockaddr_in6 caller_in6;
363         const char *serv_uaddr, *clnt_uaddr, *netid;
364         
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;
376         else
377                 clnt_uaddr = "2001:db8::1.3.46";
378
379         /* assume server is bound in INADDR_ANY port 814 */
380         serv_uaddr = "::1.3.46";
381
382         netid = "udp6";
383         return (addrmerge(&caller, serv_uaddr, clnt_uaddr, netid));
384 }
385
386 /* Variant of do_addrmerge6 where the caller uses a link local address */
387 static char*
388 do_addrmerge6_ll(void)
389 {
390         struct netbuf caller;
391         struct sockaddr_in6 caller_in6;
392         const char *serv_uaddr, *clnt_uaddr, *netid;
393         
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";
405
406         /* assume server is bound in INADDR_ANY port 814 */
407         serv_uaddr = "::1.3.46";
408
409         netid = "udp6";
410         return (addrmerge(&caller, serv_uaddr, clnt_uaddr, netid));
411 }
412 #endif /* INET6 */
413
414 ATF_TC_WITHOUT_HEAD(addrmerge_noifaddrs);
415 ATF_TC_BODY(addrmerge_noifaddrs, tc)
416 {
417         char* maddr;
418
419         maddr = do_addrmerge4(NULL);
420
421         /* Since getifaddrs returns null, addrmerge must too */
422         ATF_CHECK_EQ(NULL, maddr);
423 }
424
425 ATF_TC_WITHOUT_HEAD(addrmerge_localhost_only);
426 ATF_TC_BODY(addrmerge_localhost_only, tc)
427 {
428         char *maddr;
429         
430         /* getifaddrs will return localhost only */
431         mock_lo0();
432
433         maddr = do_addrmerge4(NULL);
434
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);
438         free(maddr);
439 }
440
441 ATF_TC_WITHOUT_HEAD(addrmerge_singlehomed);
442 ATF_TC_BODY(addrmerge_singlehomed, tc)
443 {
444         char *maddr;
445         
446         /* getifaddrs will return one public address */
447         mock_lo0();
448         mock_igb0();
449
450         maddr = do_addrmerge4(NULL);
451
452         ATF_REQUIRE(maddr != NULL);
453         ATF_CHECK_STREQ("192.0.2.2.3.46", maddr);
454         free(maddr);
455 }
456
457 ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet);
458 ATF_TC_BODY(addrmerge_one_addr_on_each_subnet, tc)
459 {
460         char *maddr;
461         
462         mock_lo0();
463         mock_igb0();
464         mock_igb2();
465
466         maddr = do_addrmerge4(NULL);
467
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);
471         free(maddr);
472 }
473
474
475 /*
476  * Like addrmerge_one_addr_on_each_subnet, but getifaddrs returns a different
477  * order
478  */
479 ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet_rev);
480 ATF_TC_BODY(addrmerge_one_addr_on_each_subnet_rev, tc)
481 {
482         char *maddr;
483         
484         /* getifaddrs will return one public address on each of two subnets */
485         mock_igb2();
486         mock_igb0();
487         mock_lo0();
488
489         maddr = do_addrmerge4(NULL);
490
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);
494         free(maddr);
495 }
496
497 ATF_TC_WITHOUT_HEAD(addrmerge_point2point);
498 ATF_TC_BODY(addrmerge_point2point, tc)
499 {
500         char *maddr;
501         
502         /* getifaddrs will return one normal and one p2p address */
503         mock_lo0();
504         mock_igb2();
505         mock_tun0();
506
507         maddr = do_addrmerge4(NULL);
508
509         /* addrmerge should disprefer P2P interfaces */
510         ATF_REQUIRE(maddr != NULL);
511         ATF_CHECK_STREQ("192.0.2.130.3.46", maddr);
512         free(maddr);
513 }
514
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)
518 {
519         char *maddr;
520         
521         /* getifaddrs will return one normal and one p2p address */
522         mock_tun0();
523         mock_igb2();
524         mock_lo0();
525
526         maddr = do_addrmerge4(NULL);
527
528         /* addrmerge should disprefer P2P interfaces */
529         ATF_REQUIRE(maddr != NULL);
530         ATF_CHECK_STREQ("192.0.2.130.3.46", maddr);
531         free(maddr);
532 }
533
534 /*
535  * Simulate using rpcbind -h to select just one ip when the subnet has
536  * multiple
537  */
538 ATF_TC_WITHOUT_HEAD(addrmerge_bindip);
539 ATF_TC_BODY(addrmerge_bindip, tc)
540 {
541         char *maddr;
542         
543         /* getifaddrs will return one public address on each of two subnets */
544         mock_lo0();
545         mock_igb0();
546         mock_igb1(true);
547
548         maddr = do_addrmerge4(NULL);
549
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);
553         free(maddr);
554 }
555
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)
559 {
560         char *maddr;
561         
562         /* getifaddrs will return one public address on each of two subnets */
563         mock_igb1(true);
564         mock_igb0();
565         mock_lo0();
566
567         maddr = do_addrmerge4(NULL);
568
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);
572         free(maddr);
573 }
574
575 /* 
576  * The address on which the request was received is known, and is provided as
577  * the hint.
578  */
579 ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr);
580 ATF_TC_BODY(addrmerge_recvdstaddr, tc)
581 {
582         char *maddr;
583         
584         mock_lo0();
585         mock_igb0();
586         mock_igb1(false);
587
588         maddr = do_addrmerge4("192.0.2.2.3.46");
589
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);
593         free(maddr);
594 }
595
596 ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr_rev);
597 ATF_TC_BODY(addrmerge_recvdstaddr_rev, tc)
598 {
599         char *maddr;
600         
601         mock_igb1(false);
602         mock_igb0();
603         mock_lo0();
604
605         maddr = do_addrmerge4("192.0.2.2.3.46");
606
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);
610         free(maddr);
611 }
612
613 #ifdef INET6
614 ATF_TC_WITHOUT_HEAD(addrmerge_localhost_only6);
615 ATF_TC_BODY(addrmerge_localhost_only6, tc)
616 {
617         char *maddr;
618         
619         /* getifaddrs will return localhost only */
620         mock_lo0();
621
622         maddr = do_addrmerge6(NULL);
623
624         /* We must return localhost if there is nothing better */
625         ATF_REQUIRE(maddr != NULL);
626         ATF_CHECK_STREQ("::1.3.46", maddr);
627         free(maddr);
628 }
629
630 ATF_TC_WITHOUT_HEAD(addrmerge_singlehomed6);
631 ATF_TC_BODY(addrmerge_singlehomed6, tc)
632 {
633         char *maddr;
634         
635         /* getifaddrs will return one public address */
636         mock_lo0();
637         mock_igb0();
638
639         maddr = do_addrmerge6(NULL);
640
641         ATF_REQUIRE(maddr != NULL);
642         ATF_CHECK_STREQ("2001:db8::2.3.46", maddr);
643         free(maddr);
644 }
645
646 ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet6);
647 ATF_TC_BODY(addrmerge_one_addr_on_each_subnet6, tc)
648 {
649         char *maddr;
650         
651         mock_lo0();
652         mock_igb0();
653         mock_igb2();
654
655         maddr = do_addrmerge6(NULL);
656
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);
660         free(maddr);
661 }
662
663
664 /*
665  * Like addrmerge_one_addr_on_each_subnet6, but getifaddrs returns a different
666  * order
667  */
668 ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet6_rev);
669 ATF_TC_BODY(addrmerge_one_addr_on_each_subnet6_rev, tc)
670 {
671         char *maddr;
672         
673         /* getifaddrs will return one public address on each of two subnets */
674         mock_igb2();
675         mock_igb0();
676         mock_lo0();
677
678         maddr = do_addrmerge6(NULL);
679
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);
683         free(maddr);
684 }
685
686 ATF_TC_WITHOUT_HEAD(addrmerge_point2point6);
687 ATF_TC_BODY(addrmerge_point2point6, tc)
688 {
689         char *maddr;
690         
691         /* getifaddrs will return one normal and one p2p address */
692         mock_lo0();
693         mock_igb2();
694         mock_tun0();
695
696         maddr = do_addrmerge6(NULL);
697
698         /* addrmerge should disprefer P2P interfaces */
699         ATF_REQUIRE(maddr != NULL);
700         ATF_CHECK_STREQ("2001:db8:1::2.3.46", maddr);
701         free(maddr);
702 }
703
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)
707 {
708         char *maddr;
709         
710         /* getifaddrs will return one normal and one p2p address */
711         mock_tun0();
712         mock_igb2();
713         mock_lo0();
714
715         maddr = do_addrmerge6(NULL);
716
717         /* addrmerge should disprefer P2P interfaces */
718         ATF_REQUIRE(maddr != NULL);
719         ATF_CHECK_STREQ("2001:db8:1::2.3.46", maddr);
720         free(maddr);
721 }
722
723 ATF_TC_WITHOUT_HEAD(addrmerge_bindip6);
724 ATF_TC_BODY(addrmerge_bindip6, tc)
725 {
726         char *maddr;
727         
728         /* getifaddrs will return one public address on each of two subnets */
729         mock_lo0();
730         mock_igb0();
731         mock_igb1(true);
732
733         maddr = do_addrmerge6(NULL);
734
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);
738         free(maddr);
739 }
740
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)
744 {
745         char *maddr;
746         
747         /* getifaddrs will return one public address on each of two subnets */
748         mock_igb1(true);
749         mock_igb0();
750         mock_lo0();
751
752         maddr = do_addrmerge6(NULL);
753
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);
757         free(maddr);
758 }
759
760 /* 
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
763  */
764 ATF_TC_WITHOUT_HEAD(addrmerge_ipv6_linklocal);
765 ATF_TC_BODY(addrmerge_ipv6_linklocal, tc)
766 {
767         char *maddr;
768         
769         /* 
770          * getifaddrs will return two link local addresses with the same netmask
771          * and prefix but different scope IDs
772          */
773         mock_igb1(false);
774         mock_igb0();
775         mock_lo0();
776
777         maddr = do_addrmerge6_ll();
778
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);
782         free(maddr);
783 }
784
785 ATF_TC_WITHOUT_HEAD(addrmerge_ipv6_linklocal_rev);
786 ATF_TC_BODY(addrmerge_ipv6_linklocal_rev, tc)
787 {
788         char *maddr;
789         
790         /* 
791          * getifaddrs will return two link local addresses with the same netmask
792          * and prefix but different scope IDs
793          */
794         mock_lo0();
795         mock_igb0();
796         mock_igb1(false);
797
798         maddr = do_addrmerge6_ll();
799
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);
803         free(maddr);
804 }
805
806 ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr6);
807 ATF_TC_BODY(addrmerge_recvdstaddr6, tc)
808 {
809         char *maddr;
810         
811         mock_lo0();
812         mock_igb0();
813         mock_igb1(false);
814
815         maddr = do_addrmerge6("2001:db8::2.3.46");
816
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);
820         free(maddr);
821 }
822
823 ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr6_rev);
824 ATF_TC_BODY(addrmerge_recvdstaddr6_rev, tc)
825 {
826         char *maddr;
827         
828         mock_igb1(false);
829         mock_igb0();
830         mock_lo0();
831
832         maddr = do_addrmerge6("2001:db8::2.3.46");
833
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);
837         free(maddr);
838 }
839 #endif /* INET6 */
840
841
842 ATF_TP_ADD_TCS(tp)
843 {
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);
855 #ifdef INET6
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);
868 #endif
869
870         return (atf_no_error());
871 }