xref: /freebsd-src/usr.sbin/rpcbind/tests/addrmerge_test.c (revision 3311ff84eac3b7e82f28e331df0586036c6d361c)
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 }
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 }
454 
455 ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet);
456 ATF_TC_BODY(addrmerge_one_addr_on_each_subnet, tc)
457 {
458 	char *maddr;
459 
460 	mock_lo0();
461 	mock_igb0();
462 	mock_igb2();
463 
464 	maddr = do_addrmerge4(NULL);
465 
466 	/* We must return the address on the caller's subnet */
467 	ATF_REQUIRE(maddr != NULL);
468 	ATF_CHECK_STREQ("192.0.2.2.3.46", maddr);
469 }
470 
471 
472 /*
473  * Like addrmerge_one_addr_on_each_subnet, but getifaddrs returns a different
474  * order
475  */
476 ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet_rev);
477 ATF_TC_BODY(addrmerge_one_addr_on_each_subnet_rev, tc)
478 {
479 	char *maddr;
480 
481 	/* getifaddrs will return one public address on each of two subnets */
482 	mock_igb2();
483 	mock_igb0();
484 	mock_lo0();
485 
486 	maddr = do_addrmerge4(NULL);
487 
488 	/* We must return the address on the caller's subnet */
489 	ATF_REQUIRE(maddr != NULL);
490 	ATF_CHECK_STREQ("192.0.2.2.3.46", maddr);
491 }
492 
493 ATF_TC_WITHOUT_HEAD(addrmerge_point2point);
494 ATF_TC_BODY(addrmerge_point2point, tc)
495 {
496 	char *maddr;
497 
498 	/* getifaddrs will return one normal and one p2p address */
499 	mock_lo0();
500 	mock_igb2();
501 	mock_tun0();
502 
503 	maddr = do_addrmerge4(NULL);
504 
505 	/* addrmerge should disprefer P2P interfaces */
506 	ATF_REQUIRE(maddr != NULL);
507 	ATF_CHECK_STREQ("192.0.2.130.3.46", maddr);
508 }
509 
510 /* Like addrerge_point2point, but getifaddrs returns a different order */
511 ATF_TC_WITHOUT_HEAD(addrmerge_point2point_rev);
512 ATF_TC_BODY(addrmerge_point2point_rev, tc)
513 {
514 	char *maddr;
515 
516 	/* getifaddrs will return one normal and one p2p address */
517 	mock_tun0();
518 	mock_igb2();
519 	mock_lo0();
520 
521 	maddr = do_addrmerge4(NULL);
522 
523 	/* addrmerge should disprefer P2P interfaces */
524 	ATF_REQUIRE(maddr != NULL);
525 	ATF_CHECK_STREQ("192.0.2.130.3.46", maddr);
526 }
527 
528 /*
529  * Simulate using rpcbind -h to select just one ip when the subnet has
530  * multiple
531  */
532 ATF_TC_WITHOUT_HEAD(addrmerge_bindip);
533 ATF_TC_BODY(addrmerge_bindip, tc)
534 {
535 	char *maddr;
536 
537 	/* getifaddrs will return one public address on each of two subnets */
538 	mock_lo0();
539 	mock_igb0();
540 	mock_igb1(true);
541 
542 	maddr = do_addrmerge4(NULL);
543 
544 	/* We must return the address to which we are bound */
545 	ATF_REQUIRE(maddr != NULL);
546 	ATF_CHECK_STREQ("192.0.2.3.3.46", maddr);
547 }
548 
549 /* Like addrmerge_bindip, but getifaddrs returns a different order */
550 ATF_TC_WITHOUT_HEAD(addrmerge_bindip_rev);
551 ATF_TC_BODY(addrmerge_bindip_rev, tc)
552 {
553 	char *maddr;
554 
555 	/* getifaddrs will return one public address on each of two subnets */
556 	mock_igb1(true);
557 	mock_igb0();
558 	mock_lo0();
559 
560 	maddr = do_addrmerge4(NULL);
561 
562 	/* We must return the address to which we are bound */
563 	ATF_REQUIRE(maddr != NULL);
564 	ATF_CHECK_STREQ("192.0.2.3.3.46", maddr);
565 }
566 
567 /*
568  * The address on which the request was received is known, and is provided as
569  * the hint.
570  */
571 ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr);
572 ATF_TC_BODY(addrmerge_recvdstaddr, tc)
573 {
574 	char *maddr;
575 
576 	mock_lo0();
577 	mock_igb0();
578 	mock_igb1(false);
579 
580 	maddr = do_addrmerge4("192.0.2.2.3.46");
581 
582 	/* We must return the address on which the request was received */
583 	ATF_REQUIRE(maddr != NULL);
584 	ATF_CHECK_STREQ("192.0.2.2.3.46", maddr);
585 }
586 
587 ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr_rev);
588 ATF_TC_BODY(addrmerge_recvdstaddr_rev, tc)
589 {
590 	char *maddr;
591 
592 	mock_igb1(false);
593 	mock_igb0();
594 	mock_lo0();
595 
596 	maddr = do_addrmerge4("192.0.2.2.3.46");
597 
598 	/* We must return the address on which the request was received */
599 	ATF_REQUIRE(maddr != NULL);
600 	ATF_CHECK_STREQ("192.0.2.2.3.46", maddr);
601 }
602 
603 #ifdef INET6
604 ATF_TC_WITHOUT_HEAD(addrmerge_localhost_only6);
605 ATF_TC_BODY(addrmerge_localhost_only6, tc)
606 {
607 	char *maddr;
608 
609 	/* getifaddrs will return localhost only */
610 	mock_lo0();
611 
612 	maddr = do_addrmerge6(NULL);
613 
614 	/* We must return localhost if there is nothing better */
615 	ATF_REQUIRE(maddr != NULL);
616 	ATF_CHECK_STREQ("::1.3.46", maddr);
617 }
618 
619 ATF_TC_WITHOUT_HEAD(addrmerge_singlehomed6);
620 ATF_TC_BODY(addrmerge_singlehomed6, tc)
621 {
622 	char *maddr;
623 
624 	/* getifaddrs will return one public address */
625 	mock_lo0();
626 	mock_igb0();
627 
628 	maddr = do_addrmerge6(NULL);
629 
630 	ATF_REQUIRE(maddr != NULL);
631 	ATF_CHECK_STREQ("2001:db8::2.3.46", maddr);
632 }
633 
634 ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet6);
635 ATF_TC_BODY(addrmerge_one_addr_on_each_subnet6, tc)
636 {
637 	char *maddr;
638 
639 	mock_lo0();
640 	mock_igb0();
641 	mock_igb2();
642 
643 	maddr = do_addrmerge6(NULL);
644 
645 	/* We must return the address on the caller's subnet */
646 	ATF_REQUIRE(maddr != NULL);
647 	ATF_CHECK_STREQ("2001:db8::2.3.46", maddr);
648 }
649 
650 
651 /*
652  * Like addrmerge_one_addr_on_each_subnet6, but getifaddrs returns a different
653  * order
654  */
655 ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet6_rev);
656 ATF_TC_BODY(addrmerge_one_addr_on_each_subnet6_rev, tc)
657 {
658 	char *maddr;
659 
660 	/* getifaddrs will return one public address on each of two subnets */
661 	mock_igb2();
662 	mock_igb0();
663 	mock_lo0();
664 
665 	maddr = do_addrmerge6(NULL);
666 
667 	/* We must return the address on the caller's subnet */
668 	ATF_REQUIRE(maddr != NULL);
669 	ATF_CHECK_STREQ("2001:db8::2.3.46", maddr);
670 }
671 
672 ATF_TC_WITHOUT_HEAD(addrmerge_point2point6);
673 ATF_TC_BODY(addrmerge_point2point6, tc)
674 {
675 	char *maddr;
676 
677 	/* getifaddrs will return one normal and one p2p address */
678 	mock_lo0();
679 	mock_igb2();
680 	mock_tun0();
681 
682 	maddr = do_addrmerge6(NULL);
683 
684 	/* addrmerge should disprefer P2P interfaces */
685 	ATF_REQUIRE(maddr != NULL);
686 	ATF_CHECK_STREQ("2001:db8:1::2.3.46", maddr);
687 }
688 
689 /* Like addrerge_point2point, but getifaddrs returns a different order */
690 ATF_TC_WITHOUT_HEAD(addrmerge_point2point6_rev);
691 ATF_TC_BODY(addrmerge_point2point6_rev, tc)
692 {
693 	char *maddr;
694 
695 	/* getifaddrs will return one normal and one p2p address */
696 	mock_tun0();
697 	mock_igb2();
698 	mock_lo0();
699 
700 	maddr = do_addrmerge6(NULL);
701 
702 	/* addrmerge should disprefer P2P interfaces */
703 	ATF_REQUIRE(maddr != NULL);
704 	ATF_CHECK_STREQ("2001:db8:1::2.3.46", maddr);
705 }
706 
707 ATF_TC_WITHOUT_HEAD(addrmerge_bindip6);
708 ATF_TC_BODY(addrmerge_bindip6, tc)
709 {
710 	char *maddr;
711 
712 	/* getifaddrs will return one public address on each of two subnets */
713 	mock_lo0();
714 	mock_igb0();
715 	mock_igb1(true);
716 
717 	maddr = do_addrmerge6(NULL);
718 
719 	/* We must return the address to which we are bound */
720 	ATF_REQUIRE(maddr != NULL);
721 	ATF_CHECK_STREQ("2001:db8::3.3.46", maddr);
722 }
723 
724 /* Like addrerge_bindip, but getifaddrs returns a different order */
725 ATF_TC_WITHOUT_HEAD(addrmerge_bindip6_rev);
726 ATF_TC_BODY(addrmerge_bindip6_rev, tc)
727 {
728 	char *maddr;
729 
730 	/* getifaddrs will return one public address on each of two subnets */
731 	mock_igb1(true);
732 	mock_igb0();
733 	mock_lo0();
734 
735 	maddr = do_addrmerge6(NULL);
736 
737 	/* We must return the address to which we are bound */
738 	ATF_REQUIRE(maddr != NULL);
739 	ATF_CHECK_STREQ("2001:db8::3.3.46", maddr);
740 }
741 
742 /*
743  * IPv6 Link Local addresses with the same scope id as the caller, if the caller
744  * is also a link local address, should be preferred
745  */
746 ATF_TC_WITHOUT_HEAD(addrmerge_ipv6_linklocal);
747 ATF_TC_BODY(addrmerge_ipv6_linklocal, tc)
748 {
749 	char *maddr;
750 
751 	/*
752 	 * getifaddrs will return two link local addresses with the same netmask
753 	 * and prefix but different scope IDs
754 	 */
755 	mock_igb1(false);
756 	mock_igb0();
757 	mock_lo0();
758 
759 	maddr = do_addrmerge6_ll();
760 
761 	/* We must return the address to which we are bound */
762 	ATF_REQUIRE(maddr != NULL);
763 	ATF_CHECK_STREQ("fe80::2.3.46", maddr);
764 }
765 
766 ATF_TC_WITHOUT_HEAD(addrmerge_ipv6_linklocal_rev);
767 ATF_TC_BODY(addrmerge_ipv6_linklocal_rev, tc)
768 {
769 	char *maddr;
770 
771 	/*
772 	 * getifaddrs will return two link local addresses with the same netmask
773 	 * and prefix but different scope IDs
774 	 */
775 	mock_lo0();
776 	mock_igb0();
777 	mock_igb1(false);
778 
779 	maddr = do_addrmerge6_ll();
780 
781 	/* We must return the address to which we are bound */
782 	ATF_REQUIRE(maddr != NULL);
783 	ATF_CHECK_STREQ("fe80::2.3.46", maddr);
784 }
785 
786 ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr6);
787 ATF_TC_BODY(addrmerge_recvdstaddr6, tc)
788 {
789 	char *maddr;
790 
791 	mock_lo0();
792 	mock_igb0();
793 	mock_igb1(false);
794 
795 	maddr = do_addrmerge6("2001:db8::2.3.46");
796 
797 	/* We must return the address on which the request was received */
798 	ATF_REQUIRE(maddr != NULL);
799 	ATF_CHECK_STREQ("2001:db8::2.3.46", maddr);
800 }
801 
802 ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr6_rev);
803 ATF_TC_BODY(addrmerge_recvdstaddr6_rev, tc)
804 {
805 	char *maddr;
806 
807 	mock_igb1(false);
808 	mock_igb0();
809 	mock_lo0();
810 
811 	maddr = do_addrmerge6("2001:db8::2.3.46");
812 
813 	/* We must return the address on which the request was received */
814 	ATF_REQUIRE(maddr != NULL);
815 	ATF_CHECK_STREQ("2001:db8::2.3.46", maddr);
816 }
817 #endif /* INET6 */
818 
819 
820 ATF_TP_ADD_TCS(tp)
821 {
822 	ATF_TP_ADD_TC(tp, addrmerge_noifaddrs);
823 	ATF_TP_ADD_TC(tp, addrmerge_localhost_only);
824 	ATF_TP_ADD_TC(tp, addrmerge_singlehomed);
825 	ATF_TP_ADD_TC(tp, addrmerge_one_addr_on_each_subnet);
826 	ATF_TP_ADD_TC(tp, addrmerge_one_addr_on_each_subnet_rev);
827 	ATF_TP_ADD_TC(tp, addrmerge_point2point);
828 	ATF_TP_ADD_TC(tp, addrmerge_point2point_rev);
829 	ATF_TP_ADD_TC(tp, addrmerge_bindip);
830 	ATF_TP_ADD_TC(tp, addrmerge_bindip_rev);
831 	ATF_TP_ADD_TC(tp, addrmerge_recvdstaddr);
832 	ATF_TP_ADD_TC(tp, addrmerge_recvdstaddr_rev);
833 #ifdef INET6
834 	ATF_TP_ADD_TC(tp, addrmerge_localhost_only6);
835 	ATF_TP_ADD_TC(tp, addrmerge_singlehomed6);
836 	ATF_TP_ADD_TC(tp, addrmerge_one_addr_on_each_subnet6);
837 	ATF_TP_ADD_TC(tp, addrmerge_one_addr_on_each_subnet6_rev);
838 	ATF_TP_ADD_TC(tp, addrmerge_point2point6);
839 	ATF_TP_ADD_TC(tp, addrmerge_point2point6_rev);
840 	ATF_TP_ADD_TC(tp, addrmerge_bindip6);
841 	ATF_TP_ADD_TC(tp, addrmerge_bindip6_rev);
842 	ATF_TP_ADD_TC(tp, addrmerge_ipv6_linklocal);
843 	ATF_TP_ADD_TC(tp, addrmerge_ipv6_linklocal_rev);
844 	ATF_TP_ADD_TC(tp, addrmerge_recvdstaddr6);
845 	ATF_TP_ADD_TC(tp, addrmerge_recvdstaddr6_rev);
846 #endif
847 
848 	return (atf_no_error());
849 }
850