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