1a85f1232SAlan Somers /*-
2a85f1232SAlan Somers  * Copyright (c) 2014 Spectra Logic Corporation
3a85f1232SAlan Somers  * All rights reserved.
4a85f1232SAlan Somers  *
5a85f1232SAlan Somers  * Redistribution and use in source and binary forms, with or without
6a85f1232SAlan Somers  * modification, are permitted provided that the following conditions
7a85f1232SAlan Somers  * are met:
8a85f1232SAlan Somers  * 1. Redistributions of source code must retain the above copyright
9a85f1232SAlan Somers  *    notice, this list of conditions, and the following disclaimer,
10a85f1232SAlan Somers  *    without modification.
11a85f1232SAlan Somers  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12a85f1232SAlan Somers  *    substantially similar to the "NO WARRANTY" disclaimer below
13a85f1232SAlan Somers  *    ("Disclaimer") and any redistribution must be conditioned upon
14a85f1232SAlan Somers  *    including a substantially similar Disclaimer requirement for further
15a85f1232SAlan Somers  *    binary redistribution.
16a85f1232SAlan Somers  *
17a85f1232SAlan Somers  * NO WARRANTY
18a85f1232SAlan Somers  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19a85f1232SAlan Somers  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20a85f1232SAlan Somers  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
21a85f1232SAlan Somers  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22a85f1232SAlan Somers  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23a85f1232SAlan Somers  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24a85f1232SAlan Somers  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25a85f1232SAlan Somers  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26a85f1232SAlan Somers  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27a85f1232SAlan Somers  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28a85f1232SAlan Somers  * POSSIBILITY OF SUCH DAMAGES.
29a85f1232SAlan Somers  */
30a85f1232SAlan Somers 
31a85f1232SAlan Somers #include <rpc/rpc.h>
32a85f1232SAlan Somers #include <sys/types.h>
33a85f1232SAlan Somers #include <sys/socket.h>
34a85f1232SAlan Somers 
35a85f1232SAlan Somers #include <net/if.h>
36a85f1232SAlan Somers #include <netinet/in.h>
37a85f1232SAlan Somers #include <arpa/inet.h>
38a85f1232SAlan Somers 
39a85f1232SAlan Somers #include <ifaddrs.h>
40a85f1232SAlan Somers #include <stdlib.h>
41a85f1232SAlan Somers 
42a85f1232SAlan Somers #include <atf-c.h>
43a85f1232SAlan Somers 
44a85f1232SAlan Somers #include "rpcbind.h"
45a85f1232SAlan Somers 
46a85f1232SAlan Somers #define MAX_IFADDRS 16
47a85f1232SAlan Somers 
48a85f1232SAlan Somers int debugging = false;
49a85f1232SAlan Somers 
50a85f1232SAlan Somers /* Data for mocking getifaddrs */
51a85f1232SAlan Somers struct ifaddr_storage {
52a85f1232SAlan Somers 	struct ifaddrs ifaddr;
53a85f1232SAlan Somers 	struct sockaddr_storage addr;
54a85f1232SAlan Somers 	struct sockaddr_storage mask;
55a85f1232SAlan Somers 	struct sockaddr_storage bcast;
56a85f1232SAlan Somers } mock_ifaddr_storage[MAX_IFADDRS];
57a85f1232SAlan Somers struct ifaddrs *mock_ifaddrs = NULL;
58a85f1232SAlan Somers int ifaddr_count = 0;
59a85f1232SAlan Somers 
60a85f1232SAlan Somers /* Data for mocking listen_addr */
61a85f1232SAlan Somers int bind_address_count = 0;
62a85f1232SAlan Somers struct sockaddr* bind_addresses[MAX_IFADDRS];
63a85f1232SAlan Somers 
64a85f1232SAlan Somers /* Stub library functions */
65a85f1232SAlan Somers void
freeifaddrs(struct ifaddrs * ifp __unused)66a85f1232SAlan Somers freeifaddrs(struct ifaddrs *ifp __unused)
67a85f1232SAlan Somers {
68a85f1232SAlan Somers 	return ;
69a85f1232SAlan Somers }
70a85f1232SAlan Somers 
71a85f1232SAlan Somers int
getifaddrs(struct ifaddrs ** ifap)72a85f1232SAlan Somers getifaddrs(struct ifaddrs **ifap)
73a85f1232SAlan Somers {
74a85f1232SAlan Somers 	*ifap = mock_ifaddrs;
75a85f1232SAlan Somers 	return (0);
76a85f1232SAlan Somers }
77a85f1232SAlan Somers 
78a85f1232SAlan Somers static void
mock_ifaddr4(const char * name,const char * addr,const char * mask,const char * bcast,unsigned int flags,bool bind)79a85f1232SAlan Somers mock_ifaddr4(const char* name, const char* addr, const char* mask,
80a85f1232SAlan Somers     const char* bcast, unsigned int flags, bool bind)
81a85f1232SAlan Somers {
82a85f1232SAlan Somers 	struct ifaddrs *ifaddr = &mock_ifaddr_storage[ifaddr_count].ifaddr;
83a85f1232SAlan Somers 	struct sockaddr_in *in = (struct sockaddr_in*)
84a85f1232SAlan Somers 	    			&mock_ifaddr_storage[ifaddr_count].addr;
85a85f1232SAlan Somers 	struct sockaddr_in *mask_in = (struct sockaddr_in*)
86a85f1232SAlan Somers 	    			&mock_ifaddr_storage[ifaddr_count].mask;
87a85f1232SAlan Somers 	struct sockaddr_in *bcast_in = (struct sockaddr_in*)
88a85f1232SAlan Somers 	    			&mock_ifaddr_storage[ifaddr_count].bcast;
89a85f1232SAlan Somers 
90a85f1232SAlan Somers 	in->sin_family = AF_INET;
91a85f1232SAlan Somers 	in->sin_port = 0;
92498a196bSAlan Somers 	in->sin_len = sizeof(*in);
93a85f1232SAlan Somers 	in->sin_addr.s_addr = inet_addr(addr);
94a85f1232SAlan Somers 	mask_in->sin_family = AF_INET;
95a85f1232SAlan Somers 	mask_in->sin_port = 0;
96498a196bSAlan Somers 	mask_in->sin_len = sizeof(*mask_in);
97a85f1232SAlan Somers 	mask_in->sin_addr.s_addr = inet_addr(mask);
98a85f1232SAlan Somers 	bcast_in->sin_family = AF_INET;
99a85f1232SAlan Somers 	bcast_in->sin_port = 0;
100498a196bSAlan Somers 	bcast_in->sin_len = sizeof(*bcast_in);
101a85f1232SAlan Somers 	bcast_in->sin_addr.s_addr = inet_addr(bcast);
102a85f1232SAlan Somers 	*ifaddr = (struct ifaddrs) {
103a85f1232SAlan Somers 		.ifa_next = NULL,
104a85f1232SAlan Somers 		.ifa_name = (char*) name,
105a85f1232SAlan Somers 		.ifa_flags = flags,
106a85f1232SAlan Somers 		.ifa_addr = (struct sockaddr*) in,
107a85f1232SAlan Somers 		.ifa_netmask = (struct sockaddr*) mask_in,
108a85f1232SAlan Somers 		.ifa_broadaddr = (struct sockaddr*) bcast_in,
109a85f1232SAlan Somers 		.ifa_data = NULL,	/* addrmerge doesn't care*/
110a85f1232SAlan Somers 	};
111a85f1232SAlan Somers 
112a85f1232SAlan Somers 	if (ifaddr_count > 0)
113a85f1232SAlan Somers 		mock_ifaddr_storage[ifaddr_count - 1].ifaddr.ifa_next = ifaddr;
114a85f1232SAlan Somers 	ifaddr_count++;
115a85f1232SAlan Somers 	mock_ifaddrs = &mock_ifaddr_storage[0].ifaddr;
116a85f1232SAlan Somers 
117a85f1232SAlan Somers 	/* Optionally simulate binding an ip ala "rpcbind -h foo" */
118a85f1232SAlan Somers 	if (bind) {
119a85f1232SAlan Somers 		bind_addresses[bind_address_count] = (struct sockaddr*)in;
120a85f1232SAlan Somers 		bind_address_count++;
121a85f1232SAlan Somers 	}
122a85f1232SAlan Somers }
123a85f1232SAlan Somers 
124a85f1232SAlan Somers #ifdef INET6
125a85f1232SAlan Somers static void
mock_ifaddr6(const char * name,const char * addr,const char * mask,const char * bcast,unsigned int flags,uint32_t scope_id,bool bind)126a85f1232SAlan Somers mock_ifaddr6(const char* name, const char* addr, const char* mask,
127a85f1232SAlan Somers     const char* bcast, unsigned int flags, uint32_t scope_id, bool bind)
128a85f1232SAlan Somers {
129a85f1232SAlan Somers 	struct ifaddrs *ifaddr = &mock_ifaddr_storage[ifaddr_count].ifaddr;
130a85f1232SAlan Somers 	struct sockaddr_in6 *in6 = (struct sockaddr_in6*)
131a85f1232SAlan Somers 	    			&mock_ifaddr_storage[ifaddr_count].addr;
132a85f1232SAlan Somers 	struct sockaddr_in6 *mask_in6 = (struct sockaddr_in6*)
133a85f1232SAlan Somers 	    			&mock_ifaddr_storage[ifaddr_count].mask;
134a85f1232SAlan Somers 	struct sockaddr_in6 *bcast_in6 = (struct sockaddr_in6*)
135a85f1232SAlan Somers 	    			&mock_ifaddr_storage[ifaddr_count].bcast;
136a85f1232SAlan Somers 
137a85f1232SAlan Somers 	in6->sin6_family = AF_INET6;
138a85f1232SAlan Somers 	in6->sin6_port = 0;
139a85f1232SAlan Somers 	in6->sin6_len = sizeof(*in6);
140a85f1232SAlan Somers 	in6->sin6_scope_id = scope_id;
141a85f1232SAlan Somers 	ATF_REQUIRE_EQ(1, inet_pton(AF_INET6, addr, (void*)&in6->sin6_addr));
142a85f1232SAlan Somers 	mask_in6->sin6_family = AF_INET6;
143a85f1232SAlan Somers 	mask_in6->sin6_port = 0;
144a85f1232SAlan Somers 	mask_in6->sin6_len = sizeof(*mask_in6);
145a85f1232SAlan Somers 	mask_in6->sin6_scope_id = scope_id;
146a85f1232SAlan Somers 	ATF_REQUIRE_EQ(1, inet_pton(AF_INET6, mask,
147a85f1232SAlan Somers 	    (void*)&mask_in6->sin6_addr));
148a85f1232SAlan Somers 	bcast_in6->sin6_family = AF_INET6;
149a85f1232SAlan Somers 	bcast_in6->sin6_port = 0;
150a85f1232SAlan Somers 	bcast_in6->sin6_len = sizeof(*bcast_in6);
151a85f1232SAlan Somers 	bcast_in6->sin6_scope_id = scope_id;
152a85f1232SAlan Somers 	ATF_REQUIRE_EQ(1, inet_pton(AF_INET6, bcast,
153a85f1232SAlan Somers 	    (void*)&bcast_in6->sin6_addr));
154a85f1232SAlan Somers 	*ifaddr = (struct ifaddrs) {
155a85f1232SAlan Somers 		.ifa_next = NULL,
156a85f1232SAlan Somers 		.ifa_name = (char*) name,
157a85f1232SAlan Somers 		.ifa_flags = flags,
158a85f1232SAlan Somers 		.ifa_addr = (struct sockaddr*) in6,
159a85f1232SAlan Somers 		.ifa_netmask = (struct sockaddr*) mask_in6,
160a85f1232SAlan Somers 		.ifa_broadaddr = (struct sockaddr*) bcast_in6,
161a85f1232SAlan Somers 		.ifa_data = NULL,	/* addrmerge doesn't care*/
162a85f1232SAlan Somers 	};
163a85f1232SAlan Somers 
164a85f1232SAlan Somers 	if (ifaddr_count > 0)
165a85f1232SAlan Somers 		mock_ifaddr_storage[ifaddr_count - 1].ifaddr.ifa_next = ifaddr;
166a85f1232SAlan Somers 	ifaddr_count++;
167a85f1232SAlan Somers 	mock_ifaddrs = &mock_ifaddr_storage[0].ifaddr;
168a85f1232SAlan Somers 
169a85f1232SAlan Somers 	/* Optionally simulate binding an ip ala "rpcbind -h foo" */
170a85f1232SAlan Somers 	if (bind) {
171a85f1232SAlan Somers 		bind_addresses[bind_address_count] = (struct sockaddr*)in6;
172a85f1232SAlan Somers 		bind_address_count++;
173a85f1232SAlan Somers 	}
174a85f1232SAlan Somers }
175a85f1232SAlan Somers #else
176a85f1232SAlan Somers static void
mock_ifaddr6(const char * name __unused,const char * addr __unused,const char * mask __unused,const char * bcast __unused,unsigned int flags __unused,uint32_t scope_id __unused,bool bind __unused)177a85f1232SAlan Somers mock_ifaddr6(const char* name __unused, const char* addr __unused,
178a85f1232SAlan Somers     const char* mask __unused, const char* bcast __unused,
179a85f1232SAlan Somers     unsigned int flags __unused, uint32_t scope_id __unused, bool bind __unused)
180a85f1232SAlan Somers {
181a85f1232SAlan Somers }
182a85f1232SAlan Somers #endif /*INET6 */
183a85f1232SAlan Somers 
184a85f1232SAlan Somers static void
mock_lo0(void)185a85f1232SAlan Somers mock_lo0(void)
186a85f1232SAlan Somers {
187a85f1232SAlan Somers 	/*
188a85f1232SAlan Somers 	 * This broadcast address looks wrong, but it's what getifaddrs(2)
189a85f1232SAlan Somers 	 * actually returns.  It's invalid because IFF_BROADCAST is not set
190a85f1232SAlan Somers 	 */
191a85f1232SAlan Somers 	mock_ifaddr4("lo0", "127.0.0.1", "255.0.0.0", "127.0.0.1",
192a85f1232SAlan Somers 	    IFF_LOOPBACK | IFF_UP | IFF_RUNNING | IFF_MULTICAST, false);
193a85f1232SAlan Somers 	mock_ifaddr6("lo0", "::1", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
194a85f1232SAlan Somers 	    "::1",
195a85f1232SAlan Somers 	    IFF_LOOPBACK | IFF_UP | IFF_RUNNING | IFF_MULTICAST, 0, false);
196a85f1232SAlan Somers }
197a85f1232SAlan Somers 
198a85f1232SAlan Somers static void
mock_igb0(void)199a85f1232SAlan Somers mock_igb0(void)
200a85f1232SAlan Somers {
201a85f1232SAlan Somers 	mock_ifaddr4("igb0", "192.0.2.2", "255.255.255.128", "192.0.2.127",
202a85f1232SAlan Somers 	    IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST,
203a85f1232SAlan Somers 	    false);
204a85f1232SAlan Somers 	mock_ifaddr6("igb0", "2001:db8::2", "ffff:ffff:ffff:ffff::",
205a85f1232SAlan Somers 	    "2001:db8::ffff:ffff:ffff:ffff",
206a85f1232SAlan Somers 	    IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST,
207a85f1232SAlan Somers 	    0, false);
208a85f1232SAlan Somers 	/* Link local address */
209a85f1232SAlan Somers 	mock_ifaddr6("igb0", "fe80::2", "ffff:ffff:ffff:ffff::",
210a85f1232SAlan Somers 	    "fe80::ffff:ffff:ffff:ffff",
211a85f1232SAlan Somers 	    IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST,
212a85f1232SAlan Somers 	    2, false);
213a85f1232SAlan Somers }
214a85f1232SAlan Somers 
215a85f1232SAlan Somers /* On the same subnet as igb0 */
216a85f1232SAlan Somers static void
mock_igb1(bool bind)217a85f1232SAlan Somers mock_igb1(bool bind)
218a85f1232SAlan Somers {
219a85f1232SAlan Somers 	mock_ifaddr4("igb1", "192.0.2.3", "255.255.255.128", "192.0.2.127",
220a85f1232SAlan Somers 	    IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST,
221a85f1232SAlan Somers 	    bind);
222a85f1232SAlan Somers 	mock_ifaddr6("igb1", "2001:db8::3", "ffff:ffff:ffff:ffff::",
223a85f1232SAlan Somers 	    "2001:db8::ffff:ffff:ffff:ffff",
224a85f1232SAlan Somers 	    IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST,
225a85f1232SAlan Somers 	    0, bind);
226a85f1232SAlan Somers 	/* Link local address */
227a85f1232SAlan Somers 	mock_ifaddr6("igb1", "fe80::3", "ffff:ffff:ffff:ffff::",
228a85f1232SAlan Somers 	    "fe80::ffff:ffff:ffff:ffff",
229a85f1232SAlan Somers 	    IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST,
230a85f1232SAlan Somers 	    3, bind);
231a85f1232SAlan Somers }
232a85f1232SAlan Somers 
233a85f1232SAlan Somers /* igb2 is on a different subnet than igb0 */
234a85f1232SAlan Somers static void
mock_igb2(void)235a85f1232SAlan Somers mock_igb2(void)
236a85f1232SAlan Somers {
237a85f1232SAlan Somers 	mock_ifaddr4("igb2", "192.0.2.130", "255.255.255.128", "192.0.2.255",
238a85f1232SAlan Somers 	    IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST,
239a85f1232SAlan Somers 	    false);
240a85f1232SAlan Somers 	mock_ifaddr6("igb2", "2001:db8:1::2", "ffff:ffff:ffff:ffff::",
241a85f1232SAlan Somers 	    "2001:db8:1:0:ffff:ffff:ffff:ffff",
242a85f1232SAlan Somers 	    IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST,
243a85f1232SAlan Somers 	    0, false);
244a85f1232SAlan Somers }
245a85f1232SAlan Somers 
246a85f1232SAlan Somers /* tun0 is a P2P interface */
247a85f1232SAlan Somers static void
mock_tun0(void)248a85f1232SAlan Somers mock_tun0(void)
249a85f1232SAlan Somers {
250a85f1232SAlan Somers 	mock_ifaddr4("tun0", "192.0.2.5", "255.255.255.255", "192.0.2.6",
251a85f1232SAlan Somers 	    IFF_UP | IFF_RUNNING | IFF_POINTOPOINT | IFF_MULTICAST, false);
252a85f1232SAlan Somers 	mock_ifaddr6("tun0", "2001:db8::5",
253a85f1232SAlan Somers 	    "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
254a85f1232SAlan Somers 	    "2001:db8::6",
255a85f1232SAlan Somers 	    IFF_UP | IFF_RUNNING | IFF_POINTOPOINT | IFF_MULTICAST, 0, false);
256a85f1232SAlan Somers }
257a85f1232SAlan Somers 
258d18c9a91SDavid Bright static void
mock_mlxen0(void)259d18c9a91SDavid Bright mock_mlxen0(void)
260d18c9a91SDavid Bright {
261d18c9a91SDavid Bright 	mock_ifaddr4("mlxen0", "192.0.3.1", "255.255.255.128", "192.0.3.127",
262d18c9a91SDavid Bright 	    IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST,
263d18c9a91SDavid Bright 	    false);
264d18c9a91SDavid Bright 	/* Setting link local address before ipv6 address*/
265d18c9a91SDavid Bright 	mock_ifaddr6("mlxen0", "fe80::4", "ffff:ffff:ffff:ffff::",
266d18c9a91SDavid Bright 	    "fe80::ffff:ffff:ffff:ffff",
267d18c9a91SDavid Bright 	    IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST,
268d18c9a91SDavid Bright 	    3, false);
269d18c9a91SDavid Bright 	mock_ifaddr6("mlxen0", "2001:db8::7", "ffff:ffff:ffff:ffff::",
270d18c9a91SDavid Bright 	    "2001:db8::ffff:ffff:ffff:ffff",
271d18c9a91SDavid Bright 	    IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST,
272d18c9a91SDavid Bright 	    0, false);
273d18c9a91SDavid Bright }
274a85f1232SAlan Somers 
275a85f1232SAlan Somers /* Stub rpcbind functions */
276a85f1232SAlan Somers int
listen_addr(const struct sockaddr * sa)277a85f1232SAlan Somers listen_addr(const struct sockaddr *sa)
278a85f1232SAlan Somers {
279a85f1232SAlan Somers 	int i;
280a85f1232SAlan Somers 
281a85f1232SAlan Somers 	if (bind_address_count == 0)
282a85f1232SAlan Somers 		return (1);
283a85f1232SAlan Somers 
284a85f1232SAlan Somers 	for (i = 0; i < bind_address_count; i++) {
285a85f1232SAlan Somers 		if (bind_addresses[i]->sa_family != sa->sa_family)
286a85f1232SAlan Somers 			continue;
287a85f1232SAlan Somers 
288a85f1232SAlan Somers 		if (0 == memcmp(bind_addresses[i]->sa_data, sa->sa_data,
289a85f1232SAlan Somers 		    sa->sa_len))
290a85f1232SAlan Somers 			return (1);
291a85f1232SAlan Somers 	}
292a85f1232SAlan Somers 	return (0);
293a85f1232SAlan Somers }
294a85f1232SAlan Somers 
295a85f1232SAlan Somers struct netconfig*
rpcbind_get_conf(const char * netid __unused)296a85f1232SAlan Somers rpcbind_get_conf(const char* netid __unused)
297a85f1232SAlan Somers {
298a85f1232SAlan Somers 	/* Use static variables so we can return pointers to them */
299a85f1232SAlan Somers 	static char* lookups = NULL;
300a85f1232SAlan Somers 	static struct netconfig nconf_udp;
301a85f1232SAlan Somers #ifdef INET6
302a85f1232SAlan Somers 	static struct netconfig nconf_udp6;
303a85f1232SAlan Somers #endif /* INET6 */
304a85f1232SAlan Somers 
305a85f1232SAlan Somers 	nconf_udp.nc_netid = "udp"; //netid_storage;
306a85f1232SAlan Somers 	nconf_udp.nc_semantics = NC_TPI_CLTS;
307a85f1232SAlan Somers 	nconf_udp.nc_flag = NC_VISIBLE;
308a85f1232SAlan Somers 	nconf_udp.nc_protofmly = (char*)"inet";
309a85f1232SAlan Somers 	nconf_udp.nc_proto = (char*)"udp";
310a85f1232SAlan Somers 	nconf_udp.nc_device = (char*)"-";
311a85f1232SAlan Somers 	nconf_udp.nc_nlookups = 0;
312a85f1232SAlan Somers 	nconf_udp.nc_lookups = &lookups;
313a85f1232SAlan Somers 
314a85f1232SAlan Somers #ifdef INET6
315a85f1232SAlan Somers 	nconf_udp6.nc_netid = "udp6"; //netid_storage;
316a85f1232SAlan Somers 	nconf_udp6.nc_semantics = NC_TPI_CLTS;
317a85f1232SAlan Somers 	nconf_udp6.nc_flag = NC_VISIBLE;
318a85f1232SAlan Somers 	nconf_udp6.nc_protofmly = (char*)"inet6";
319a85f1232SAlan Somers 	nconf_udp6.nc_proto = (char*)"udp6";
320a85f1232SAlan Somers 	nconf_udp6.nc_device = (char*)"-";
321a85f1232SAlan Somers 	nconf_udp6.nc_nlookups = 0;
322a85f1232SAlan Somers 	nconf_udp6.nc_lookups = &lookups;
323a85f1232SAlan Somers #endif /* INET6 */
324a85f1232SAlan Somers 
325a85f1232SAlan Somers 	if (0 == strncmp("udp", netid, sizeof("udp")))
326a85f1232SAlan Somers 		return (&nconf_udp);
327a85f1232SAlan Somers #ifdef INET6
328a85f1232SAlan Somers 	else if (0 == strncmp("udp6", netid, sizeof("udp6")))
329a85f1232SAlan Somers 		return (&nconf_udp6);
330a85f1232SAlan Somers #endif /* INET6 */
331a85f1232SAlan Somers 	else
332a85f1232SAlan Somers 		return (NULL);
333a85f1232SAlan Somers }
334a85f1232SAlan Somers 
335a85f1232SAlan Somers /*
336a85f1232SAlan Somers  * Helper function used by most test cases
337a85f1232SAlan Somers  * param recvdstaddr	If non-null, the uaddr on which the request was received
338a85f1232SAlan Somers  */
339a85f1232SAlan Somers static char*
do_addrmerge4(const char * recvdstaddr)340a85f1232SAlan Somers do_addrmerge4(const char* recvdstaddr)
341a85f1232SAlan Somers {
342a85f1232SAlan Somers 	struct netbuf caller;
343a85f1232SAlan Somers 	struct sockaddr_in caller_in;
344a85f1232SAlan Somers 	const char *serv_uaddr, *clnt_uaddr, *netid;
345a85f1232SAlan Somers 
346a85f1232SAlan Somers 	/* caller contains the client's IP address */
347a85f1232SAlan Somers 	caller.maxlen = sizeof(struct sockaddr_storage);
348a85f1232SAlan Somers 	caller.len = sizeof(caller_in);
349a85f1232SAlan Somers 	caller_in.sin_family = AF_INET;
350a85f1232SAlan Somers 	caller_in.sin_len = sizeof(caller_in);
351a85f1232SAlan Somers 	caller_in.sin_port = 1234;
352a85f1232SAlan Somers 	caller_in.sin_addr.s_addr = inet_addr("192.0.2.1");
353a85f1232SAlan Somers 	caller.buf = (void*)&caller_in;
354a85f1232SAlan Somers 	if (recvdstaddr != NULL)
355a85f1232SAlan Somers 		clnt_uaddr = recvdstaddr;
356a85f1232SAlan Somers 	else
357a85f1232SAlan Somers 		clnt_uaddr = "192.0.2.1.3.46";
358a85f1232SAlan Somers 
359a85f1232SAlan Somers 	/* assume server is bound in INADDR_ANY port 814 */
360a85f1232SAlan Somers 	serv_uaddr = "0.0.0.0.3.46";
361a85f1232SAlan Somers 
362a85f1232SAlan Somers 	netid = "udp";
363a85f1232SAlan Somers 	return (addrmerge(&caller, serv_uaddr, clnt_uaddr, netid));
364a85f1232SAlan Somers }
365a85f1232SAlan Somers 
366a85f1232SAlan Somers #ifdef INET6
367a85f1232SAlan Somers /*
368a85f1232SAlan Somers  * Variant of do_addrmerge4 where the caller has an IPv6 address
369a85f1232SAlan Somers  * param recvdstaddr	If non-null, the uaddr on which the request was received
370a85f1232SAlan Somers  */
371a85f1232SAlan Somers static char*
do_addrmerge6(const char * recvdstaddr)372a85f1232SAlan Somers do_addrmerge6(const char* recvdstaddr)
373a85f1232SAlan Somers {
374a85f1232SAlan Somers 	struct netbuf caller;
375a85f1232SAlan Somers 	struct sockaddr_in6 caller_in6;
376a85f1232SAlan Somers 	const char *serv_uaddr, *clnt_uaddr, *netid;
377a85f1232SAlan Somers 
378a85f1232SAlan Somers 	/* caller contains the client's IP address */
379a85f1232SAlan Somers 	caller.maxlen = sizeof(struct sockaddr_storage);
380a85f1232SAlan Somers 	caller.len = sizeof(caller_in6);
381a85f1232SAlan Somers 	caller_in6.sin6_family = AF_INET6;
382a85f1232SAlan Somers 	caller_in6.sin6_len = sizeof(caller_in6);
383a85f1232SAlan Somers 	caller_in6.sin6_port = 1234;
384a85f1232SAlan Somers 	ATF_REQUIRE_EQ(1, inet_pton(AF_INET6, "2001:db8::1",
385a85f1232SAlan Somers 	    (void*)&caller_in6.sin6_addr));
386a85f1232SAlan Somers 	caller.buf = (void*)&caller_in6;
387a85f1232SAlan Somers 	if (recvdstaddr != NULL)
388a85f1232SAlan Somers 		clnt_uaddr = recvdstaddr;
389a85f1232SAlan Somers 	else
390a85f1232SAlan Somers 		clnt_uaddr = "2001:db8::1.3.46";
391a85f1232SAlan Somers 
392a85f1232SAlan Somers 	/* assume server is bound in INADDR_ANY port 814 */
393a85f1232SAlan Somers 	serv_uaddr = "::1.3.46";
394a85f1232SAlan Somers 
395a85f1232SAlan Somers 	netid = "udp6";
396a85f1232SAlan Somers 	return (addrmerge(&caller, serv_uaddr, clnt_uaddr, netid));
397a85f1232SAlan Somers }
398a85f1232SAlan Somers 
399a85f1232SAlan Somers /* Variant of do_addrmerge6 where the caller uses a link local address */
400a85f1232SAlan Somers static char*
do_addrmerge6_ll(void)401a85f1232SAlan Somers do_addrmerge6_ll(void)
402a85f1232SAlan Somers {
403a85f1232SAlan Somers 	struct netbuf caller;
404a85f1232SAlan Somers 	struct sockaddr_in6 caller_in6;
405a85f1232SAlan Somers 	const char *serv_uaddr, *clnt_uaddr, *netid;
406a85f1232SAlan Somers 
407a85f1232SAlan Somers 	/* caller contains the client's IP address */
408a85f1232SAlan Somers 	caller.maxlen = sizeof(struct sockaddr_storage);
409a85f1232SAlan Somers 	caller.len = sizeof(caller_in6);
410a85f1232SAlan Somers 	caller_in6.sin6_family = AF_INET6;
411a85f1232SAlan Somers 	caller_in6.sin6_len = sizeof(caller_in6);
412a85f1232SAlan Somers 	caller_in6.sin6_port = 1234;
413a85f1232SAlan Somers 	caller_in6.sin6_scope_id = 2; /* same as igb0 */
414a85f1232SAlan Somers 	ATF_REQUIRE_EQ(1, inet_pton(AF_INET6, "fe80::beef",
415a85f1232SAlan Somers 	    (void*)&caller_in6.sin6_addr));
416a85f1232SAlan Somers 	caller.buf = (void*)&caller_in6;
417a85f1232SAlan Somers 	clnt_uaddr = "fe80::beef.3.46";
418a85f1232SAlan Somers 
419a85f1232SAlan Somers 	/* assume server is bound in INADDR_ANY port 814 */
420a85f1232SAlan Somers 	serv_uaddr = "::1.3.46";
421a85f1232SAlan Somers 
422a85f1232SAlan Somers 	netid = "udp6";
423a85f1232SAlan Somers 	return (addrmerge(&caller, serv_uaddr, clnt_uaddr, netid));
424a85f1232SAlan Somers }
425a85f1232SAlan Somers #endif /* INET6 */
426a85f1232SAlan Somers 
427a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_noifaddrs);
ATF_TC_BODY(addrmerge_noifaddrs,tc)428a85f1232SAlan Somers ATF_TC_BODY(addrmerge_noifaddrs, tc)
429a85f1232SAlan Somers {
430a85f1232SAlan Somers 	char* maddr;
431a85f1232SAlan Somers 
432a85f1232SAlan Somers 	maddr = do_addrmerge4(NULL);
433a85f1232SAlan Somers 
434a85f1232SAlan Somers 	/* Since getifaddrs returns null, addrmerge must too */
435a85f1232SAlan Somers 	ATF_CHECK_EQ(NULL, maddr);
436a85f1232SAlan Somers }
437a85f1232SAlan Somers 
438a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_localhost_only);
ATF_TC_BODY(addrmerge_localhost_only,tc)439a85f1232SAlan Somers ATF_TC_BODY(addrmerge_localhost_only, tc)
440a85f1232SAlan Somers {
441a85f1232SAlan Somers 	char *maddr;
442a85f1232SAlan Somers 
443a85f1232SAlan Somers 	/* getifaddrs will return localhost only */
444a85f1232SAlan Somers 	mock_lo0();
445a85f1232SAlan Somers 
446a85f1232SAlan Somers 	maddr = do_addrmerge4(NULL);
447a85f1232SAlan Somers 
448a85f1232SAlan Somers 	/* We must return localhost if there is nothing better */
449a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
450a85f1232SAlan Somers 	ATF_CHECK_STREQ("127.0.0.1.3.46", maddr);
4510191f57fSAlan Somers 	free(maddr);
452a85f1232SAlan Somers }
453a85f1232SAlan Somers 
454a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_singlehomed);
ATF_TC_BODY(addrmerge_singlehomed,tc)455a85f1232SAlan Somers ATF_TC_BODY(addrmerge_singlehomed, tc)
456a85f1232SAlan Somers {
457a85f1232SAlan Somers 	char *maddr;
458a85f1232SAlan Somers 
459a85f1232SAlan Somers 	/* getifaddrs will return one public address */
460a85f1232SAlan Somers 	mock_lo0();
461a85f1232SAlan Somers 	mock_igb0();
462a85f1232SAlan Somers 
463a85f1232SAlan Somers 	maddr = do_addrmerge4(NULL);
464a85f1232SAlan Somers 
465a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
466a85f1232SAlan Somers 	ATF_CHECK_STREQ("192.0.2.2.3.46", maddr);
4670191f57fSAlan Somers 	free(maddr);
468a85f1232SAlan Somers }
469a85f1232SAlan Somers 
470a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet);
ATF_TC_BODY(addrmerge_one_addr_on_each_subnet,tc)471a85f1232SAlan Somers ATF_TC_BODY(addrmerge_one_addr_on_each_subnet, tc)
472a85f1232SAlan Somers {
473a85f1232SAlan Somers 	char *maddr;
474a85f1232SAlan Somers 
475a85f1232SAlan Somers 	mock_lo0();
476a85f1232SAlan Somers 	mock_igb0();
477a85f1232SAlan Somers 	mock_igb2();
478a85f1232SAlan Somers 
479a85f1232SAlan Somers 	maddr = do_addrmerge4(NULL);
480a85f1232SAlan Somers 
481a85f1232SAlan Somers 	/* We must return the address on the caller's subnet */
482a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
483a85f1232SAlan Somers 	ATF_CHECK_STREQ("192.0.2.2.3.46", maddr);
4840191f57fSAlan Somers 	free(maddr);
485a85f1232SAlan Somers }
486a85f1232SAlan Somers 
487a85f1232SAlan Somers 
488a85f1232SAlan Somers /*
489a85f1232SAlan Somers  * Like addrmerge_one_addr_on_each_subnet, but getifaddrs returns a different
490a85f1232SAlan Somers  * order
491a85f1232SAlan Somers  */
492a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet_rev);
ATF_TC_BODY(addrmerge_one_addr_on_each_subnet_rev,tc)493a85f1232SAlan Somers ATF_TC_BODY(addrmerge_one_addr_on_each_subnet_rev, tc)
494a85f1232SAlan Somers {
495a85f1232SAlan Somers 	char *maddr;
496a85f1232SAlan Somers 
497a85f1232SAlan Somers 	/* getifaddrs will return one public address on each of two subnets */
498a85f1232SAlan Somers 	mock_igb2();
499a85f1232SAlan Somers 	mock_igb0();
500a85f1232SAlan Somers 	mock_lo0();
501a85f1232SAlan Somers 
502a85f1232SAlan Somers 	maddr = do_addrmerge4(NULL);
503a85f1232SAlan Somers 
504a85f1232SAlan Somers 	/* We must return the address on the caller's subnet */
505a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
506a85f1232SAlan Somers 	ATF_CHECK_STREQ("192.0.2.2.3.46", maddr);
5070191f57fSAlan Somers 	free(maddr);
508a85f1232SAlan Somers }
509a85f1232SAlan Somers 
510a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_point2point);
ATF_TC_BODY(addrmerge_point2point,tc)511a85f1232SAlan Somers ATF_TC_BODY(addrmerge_point2point, tc)
512a85f1232SAlan Somers {
513a85f1232SAlan Somers 	char *maddr;
514a85f1232SAlan Somers 
515a85f1232SAlan Somers 	/* getifaddrs will return one normal and one p2p address */
516a85f1232SAlan Somers 	mock_lo0();
517a85f1232SAlan Somers 	mock_igb2();
518a85f1232SAlan Somers 	mock_tun0();
519a85f1232SAlan Somers 
520a85f1232SAlan Somers 	maddr = do_addrmerge4(NULL);
521a85f1232SAlan Somers 
522a85f1232SAlan Somers 	/* addrmerge should disprefer P2P interfaces */
523a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
524a85f1232SAlan Somers 	ATF_CHECK_STREQ("192.0.2.130.3.46", maddr);
5250191f57fSAlan Somers 	free(maddr);
526a85f1232SAlan Somers }
527a85f1232SAlan Somers 
528a85f1232SAlan Somers /* Like addrerge_point2point, but getifaddrs returns a different order */
529a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_point2point_rev);
ATF_TC_BODY(addrmerge_point2point_rev,tc)530a85f1232SAlan Somers ATF_TC_BODY(addrmerge_point2point_rev, tc)
531a85f1232SAlan Somers {
532a85f1232SAlan Somers 	char *maddr;
533a85f1232SAlan Somers 
534a85f1232SAlan Somers 	/* getifaddrs will return one normal and one p2p address */
535a85f1232SAlan Somers 	mock_tun0();
536a85f1232SAlan Somers 	mock_igb2();
537a85f1232SAlan Somers 	mock_lo0();
538a85f1232SAlan Somers 
539a85f1232SAlan Somers 	maddr = do_addrmerge4(NULL);
540a85f1232SAlan Somers 
541a85f1232SAlan Somers 	/* addrmerge should disprefer P2P interfaces */
542a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
543a85f1232SAlan Somers 	ATF_CHECK_STREQ("192.0.2.130.3.46", maddr);
5440191f57fSAlan Somers 	free(maddr);
545a85f1232SAlan Somers }
546a85f1232SAlan Somers 
547a85f1232SAlan Somers /*
548a85f1232SAlan Somers  * Simulate using rpcbind -h to select just one ip when the subnet has
549a85f1232SAlan Somers  * multiple
550a85f1232SAlan Somers  */
551a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_bindip);
ATF_TC_BODY(addrmerge_bindip,tc)552a85f1232SAlan Somers ATF_TC_BODY(addrmerge_bindip, tc)
553a85f1232SAlan Somers {
554a85f1232SAlan Somers 	char *maddr;
555a85f1232SAlan Somers 
556a85f1232SAlan Somers 	/* getifaddrs will return one public address on each of two subnets */
557a85f1232SAlan Somers 	mock_lo0();
558a85f1232SAlan Somers 	mock_igb0();
559a85f1232SAlan Somers 	mock_igb1(true);
560a85f1232SAlan Somers 
561a85f1232SAlan Somers 	maddr = do_addrmerge4(NULL);
562a85f1232SAlan Somers 
563a85f1232SAlan Somers 	/* We must return the address to which we are bound */
564a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
565a85f1232SAlan Somers 	ATF_CHECK_STREQ("192.0.2.3.3.46", maddr);
5660191f57fSAlan Somers 	free(maddr);
567a85f1232SAlan Somers }
568a85f1232SAlan Somers 
569a85f1232SAlan Somers /* Like addrmerge_bindip, but getifaddrs returns a different order */
570a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_bindip_rev);
ATF_TC_BODY(addrmerge_bindip_rev,tc)571a85f1232SAlan Somers ATF_TC_BODY(addrmerge_bindip_rev, tc)
572a85f1232SAlan Somers {
573a85f1232SAlan Somers 	char *maddr;
574a85f1232SAlan Somers 
575a85f1232SAlan Somers 	/* getifaddrs will return one public address on each of two subnets */
576a85f1232SAlan Somers 	mock_igb1(true);
577a85f1232SAlan Somers 	mock_igb0();
578a85f1232SAlan Somers 	mock_lo0();
579a85f1232SAlan Somers 
580a85f1232SAlan Somers 	maddr = do_addrmerge4(NULL);
581a85f1232SAlan Somers 
582a85f1232SAlan Somers 	/* We must return the address to which we are bound */
583a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
584a85f1232SAlan Somers 	ATF_CHECK_STREQ("192.0.2.3.3.46", maddr);
5850191f57fSAlan Somers 	free(maddr);
586a85f1232SAlan Somers }
587a85f1232SAlan Somers 
588a85f1232SAlan Somers /*
589a85f1232SAlan Somers  * The address on which the request was received is known, and is provided as
590a85f1232SAlan Somers  * the hint.
591a85f1232SAlan Somers  */
592a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr);
ATF_TC_BODY(addrmerge_recvdstaddr,tc)593a85f1232SAlan Somers ATF_TC_BODY(addrmerge_recvdstaddr, tc)
594a85f1232SAlan Somers {
595a85f1232SAlan Somers 	char *maddr;
596a85f1232SAlan Somers 
597a85f1232SAlan Somers 	mock_lo0();
598a85f1232SAlan Somers 	mock_igb0();
599a85f1232SAlan Somers 	mock_igb1(false);
600a85f1232SAlan Somers 
601a85f1232SAlan Somers 	maddr = do_addrmerge4("192.0.2.2.3.46");
602a85f1232SAlan Somers 
603a85f1232SAlan Somers 	/* We must return the address on which the request was received */
604a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
605a85f1232SAlan Somers 	ATF_CHECK_STREQ("192.0.2.2.3.46", maddr);
6060191f57fSAlan Somers 	free(maddr);
607a85f1232SAlan Somers }
608a85f1232SAlan Somers 
609a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr_rev);
ATF_TC_BODY(addrmerge_recvdstaddr_rev,tc)610a85f1232SAlan Somers ATF_TC_BODY(addrmerge_recvdstaddr_rev, tc)
611a85f1232SAlan Somers {
612a85f1232SAlan Somers 	char *maddr;
613a85f1232SAlan Somers 
614a85f1232SAlan Somers 	mock_igb1(false);
615a85f1232SAlan Somers 	mock_igb0();
616a85f1232SAlan Somers 	mock_lo0();
617a85f1232SAlan Somers 
618a85f1232SAlan Somers 	maddr = do_addrmerge4("192.0.2.2.3.46");
619a85f1232SAlan Somers 
620a85f1232SAlan Somers 	/* We must return the address on which the request was received */
621a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
622a85f1232SAlan Somers 	ATF_CHECK_STREQ("192.0.2.2.3.46", maddr);
6230191f57fSAlan Somers 	free(maddr);
624a85f1232SAlan Somers }
625a85f1232SAlan Somers 
626a85f1232SAlan Somers #ifdef INET6
627a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_localhost_only6);
ATF_TC_BODY(addrmerge_localhost_only6,tc)628a85f1232SAlan Somers ATF_TC_BODY(addrmerge_localhost_only6, tc)
629a85f1232SAlan Somers {
630a85f1232SAlan Somers 	char *maddr;
631a85f1232SAlan Somers 
632a85f1232SAlan Somers 	/* getifaddrs will return localhost only */
633a85f1232SAlan Somers 	mock_lo0();
634a85f1232SAlan Somers 
635a85f1232SAlan Somers 	maddr = do_addrmerge6(NULL);
636a85f1232SAlan Somers 
637a85f1232SAlan Somers 	/* We must return localhost if there is nothing better */
638a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
639a85f1232SAlan Somers 	ATF_CHECK_STREQ("::1.3.46", maddr);
6400191f57fSAlan Somers 	free(maddr);
641a85f1232SAlan Somers }
642a85f1232SAlan Somers 
643a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_singlehomed6);
ATF_TC_BODY(addrmerge_singlehomed6,tc)644a85f1232SAlan Somers ATF_TC_BODY(addrmerge_singlehomed6, tc)
645a85f1232SAlan Somers {
646a85f1232SAlan Somers 	char *maddr;
647a85f1232SAlan Somers 
648a85f1232SAlan Somers 	/* getifaddrs will return one public address */
649a85f1232SAlan Somers 	mock_lo0();
650a85f1232SAlan Somers 	mock_igb0();
651a85f1232SAlan Somers 
652a85f1232SAlan Somers 	maddr = do_addrmerge6(NULL);
653a85f1232SAlan Somers 
654a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
655a85f1232SAlan Somers 	ATF_CHECK_STREQ("2001:db8::2.3.46", maddr);
6560191f57fSAlan Somers 	free(maddr);
657a85f1232SAlan Somers }
658a85f1232SAlan Somers 
659a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet6);
ATF_TC_BODY(addrmerge_one_addr_on_each_subnet6,tc)660a85f1232SAlan Somers ATF_TC_BODY(addrmerge_one_addr_on_each_subnet6, tc)
661a85f1232SAlan Somers {
662a85f1232SAlan Somers 	char *maddr;
663a85f1232SAlan Somers 
664a85f1232SAlan Somers 	mock_lo0();
665a85f1232SAlan Somers 	mock_igb0();
666a85f1232SAlan Somers 	mock_igb2();
667a85f1232SAlan Somers 
668a85f1232SAlan Somers 	maddr = do_addrmerge6(NULL);
669a85f1232SAlan Somers 
670a85f1232SAlan Somers 	/* We must return the address on the caller's subnet */
671a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
672a85f1232SAlan Somers 	ATF_CHECK_STREQ("2001:db8::2.3.46", maddr);
6730191f57fSAlan Somers 	free(maddr);
674a85f1232SAlan Somers }
675a85f1232SAlan Somers 
676a85f1232SAlan Somers 
677a85f1232SAlan Somers /*
678a85f1232SAlan Somers  * Like addrmerge_one_addr_on_each_subnet6, but getifaddrs returns a different
679a85f1232SAlan Somers  * order
680a85f1232SAlan Somers  */
681a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_one_addr_on_each_subnet6_rev);
ATF_TC_BODY(addrmerge_one_addr_on_each_subnet6_rev,tc)682a85f1232SAlan Somers ATF_TC_BODY(addrmerge_one_addr_on_each_subnet6_rev, tc)
683a85f1232SAlan Somers {
684a85f1232SAlan Somers 	char *maddr;
685a85f1232SAlan Somers 
686a85f1232SAlan Somers 	/* getifaddrs will return one public address on each of two subnets */
687a85f1232SAlan Somers 	mock_igb2();
688a85f1232SAlan Somers 	mock_igb0();
689a85f1232SAlan Somers 	mock_lo0();
690a85f1232SAlan Somers 
691a85f1232SAlan Somers 	maddr = do_addrmerge6(NULL);
692a85f1232SAlan Somers 
693a85f1232SAlan Somers 	/* We must return the address on the caller's subnet */
694a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
695a85f1232SAlan Somers 	ATF_CHECK_STREQ("2001:db8::2.3.46", maddr);
6960191f57fSAlan Somers 	free(maddr);
697a85f1232SAlan Somers }
698a85f1232SAlan Somers 
699a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_point2point6);
ATF_TC_BODY(addrmerge_point2point6,tc)700a85f1232SAlan Somers ATF_TC_BODY(addrmerge_point2point6, tc)
701a85f1232SAlan Somers {
702a85f1232SAlan Somers 	char *maddr;
703a85f1232SAlan Somers 
704a85f1232SAlan Somers 	/* getifaddrs will return one normal and one p2p address */
705a85f1232SAlan Somers 	mock_lo0();
706a85f1232SAlan Somers 	mock_igb2();
707a85f1232SAlan Somers 	mock_tun0();
708a85f1232SAlan Somers 
709a85f1232SAlan Somers 	maddr = do_addrmerge6(NULL);
710a85f1232SAlan Somers 
711a85f1232SAlan Somers 	/* addrmerge should disprefer P2P interfaces */
712a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
713a85f1232SAlan Somers 	ATF_CHECK_STREQ("2001:db8:1::2.3.46", maddr);
7140191f57fSAlan Somers 	free(maddr);
715a85f1232SAlan Somers }
716a85f1232SAlan Somers 
717a85f1232SAlan Somers /* Like addrerge_point2point, but getifaddrs returns a different order */
718a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_point2point6_rev);
ATF_TC_BODY(addrmerge_point2point6_rev,tc)719a85f1232SAlan Somers ATF_TC_BODY(addrmerge_point2point6_rev, tc)
720a85f1232SAlan Somers {
721a85f1232SAlan Somers 	char *maddr;
722a85f1232SAlan Somers 
723a85f1232SAlan Somers 	/* getifaddrs will return one normal and one p2p address */
724a85f1232SAlan Somers 	mock_tun0();
725a85f1232SAlan Somers 	mock_igb2();
726a85f1232SAlan Somers 	mock_lo0();
727a85f1232SAlan Somers 
728a85f1232SAlan Somers 	maddr = do_addrmerge6(NULL);
729a85f1232SAlan Somers 
730a85f1232SAlan Somers 	/* addrmerge should disprefer P2P interfaces */
731a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
732a85f1232SAlan Somers 	ATF_CHECK_STREQ("2001:db8:1::2.3.46", maddr);
7330191f57fSAlan Somers 	free(maddr);
734a85f1232SAlan Somers }
735a85f1232SAlan Somers 
736a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_bindip6);
ATF_TC_BODY(addrmerge_bindip6,tc)737a85f1232SAlan Somers ATF_TC_BODY(addrmerge_bindip6, tc)
738a85f1232SAlan Somers {
739a85f1232SAlan Somers 	char *maddr;
740a85f1232SAlan Somers 
741a85f1232SAlan Somers 	/* getifaddrs will return one public address on each of two subnets */
742a85f1232SAlan Somers 	mock_lo0();
743a85f1232SAlan Somers 	mock_igb0();
744a85f1232SAlan Somers 	mock_igb1(true);
745a85f1232SAlan Somers 
746a85f1232SAlan Somers 	maddr = do_addrmerge6(NULL);
747a85f1232SAlan Somers 
748a85f1232SAlan Somers 	/* We must return the address to which we are bound */
749a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
750a85f1232SAlan Somers 	ATF_CHECK_STREQ("2001:db8::3.3.46", maddr);
7510191f57fSAlan Somers 	free(maddr);
752a85f1232SAlan Somers }
753a85f1232SAlan Somers 
754a85f1232SAlan Somers /* Like addrerge_bindip, but getifaddrs returns a different order */
755a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_bindip6_rev);
ATF_TC_BODY(addrmerge_bindip6_rev,tc)756a85f1232SAlan Somers ATF_TC_BODY(addrmerge_bindip6_rev, tc)
757a85f1232SAlan Somers {
758a85f1232SAlan Somers 	char *maddr;
759a85f1232SAlan Somers 
760a85f1232SAlan Somers 	/* getifaddrs will return one public address on each of two subnets */
761a85f1232SAlan Somers 	mock_igb1(true);
762a85f1232SAlan Somers 	mock_igb0();
763a85f1232SAlan Somers 	mock_lo0();
764a85f1232SAlan Somers 
765a85f1232SAlan Somers 	maddr = do_addrmerge6(NULL);
766a85f1232SAlan Somers 
767a85f1232SAlan Somers 	/* We must return the address to which we are bound */
768a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
769a85f1232SAlan Somers 	ATF_CHECK_STREQ("2001:db8::3.3.46", maddr);
7700191f57fSAlan Somers 	free(maddr);
771a85f1232SAlan Somers }
772a85f1232SAlan Somers 
773a85f1232SAlan Somers /*
774a85f1232SAlan Somers  * IPv6 Link Local addresses with the same scope id as the caller, if the caller
775a85f1232SAlan Somers  * is also a link local address, should be preferred
776a85f1232SAlan Somers  */
777a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_ipv6_linklocal);
ATF_TC_BODY(addrmerge_ipv6_linklocal,tc)778a85f1232SAlan Somers ATF_TC_BODY(addrmerge_ipv6_linklocal, tc)
779a85f1232SAlan Somers {
780a85f1232SAlan Somers 	char *maddr;
781a85f1232SAlan Somers 
782a85f1232SAlan Somers 	/*
783a85f1232SAlan Somers 	 * getifaddrs will return two link local addresses with the same netmask
784a85f1232SAlan Somers 	 * and prefix but different scope IDs
785a85f1232SAlan Somers 	 */
786a85f1232SAlan Somers 	mock_igb1(false);
787a85f1232SAlan Somers 	mock_igb0();
788a85f1232SAlan Somers 	mock_lo0();
789a85f1232SAlan Somers 
790a85f1232SAlan Somers 	maddr = do_addrmerge6_ll();
791a85f1232SAlan Somers 
792a85f1232SAlan Somers 	/* We must return the address to which we are bound */
793a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
794a85f1232SAlan Somers 	ATF_CHECK_STREQ("fe80::2.3.46", maddr);
7950191f57fSAlan Somers 	free(maddr);
796a85f1232SAlan Somers }
797a85f1232SAlan Somers 
798a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_ipv6_linklocal_rev);
ATF_TC_BODY(addrmerge_ipv6_linklocal_rev,tc)799a85f1232SAlan Somers ATF_TC_BODY(addrmerge_ipv6_linklocal_rev, tc)
800a85f1232SAlan Somers {
801a85f1232SAlan Somers 	char *maddr;
802a85f1232SAlan Somers 
803a85f1232SAlan Somers 	/*
804a85f1232SAlan Somers 	 * getifaddrs will return two link local addresses with the same netmask
805a85f1232SAlan Somers 	 * and prefix but different scope IDs
806a85f1232SAlan Somers 	 */
807a85f1232SAlan Somers 	mock_lo0();
808a85f1232SAlan Somers 	mock_igb0();
809a85f1232SAlan Somers 	mock_igb1(false);
810a85f1232SAlan Somers 
811a85f1232SAlan Somers 	maddr = do_addrmerge6_ll();
812a85f1232SAlan Somers 
813a85f1232SAlan Somers 	/* We must return the address to which we are bound */
814a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
815a85f1232SAlan Somers 	ATF_CHECK_STREQ("fe80::2.3.46", maddr);
8160191f57fSAlan Somers 	free(maddr);
817a85f1232SAlan Somers }
818a85f1232SAlan Somers 
819a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr6);
ATF_TC_BODY(addrmerge_recvdstaddr6,tc)820a85f1232SAlan Somers ATF_TC_BODY(addrmerge_recvdstaddr6, tc)
821a85f1232SAlan Somers {
822a85f1232SAlan Somers 	char *maddr;
823a85f1232SAlan Somers 
824a85f1232SAlan Somers 	mock_lo0();
825a85f1232SAlan Somers 	mock_igb0();
826a85f1232SAlan Somers 	mock_igb1(false);
827a85f1232SAlan Somers 
828a85f1232SAlan Somers 	maddr = do_addrmerge6("2001:db8::2.3.46");
829a85f1232SAlan Somers 
830a85f1232SAlan Somers 	/* We must return the address on which the request was received */
831a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
832a85f1232SAlan Somers 	ATF_CHECK_STREQ("2001:db8::2.3.46", maddr);
8330191f57fSAlan Somers 	free(maddr);
834a85f1232SAlan Somers }
835a85f1232SAlan Somers 
836a85f1232SAlan Somers ATF_TC_WITHOUT_HEAD(addrmerge_recvdstaddr6_rev);
ATF_TC_BODY(addrmerge_recvdstaddr6_rev,tc)837a85f1232SAlan Somers ATF_TC_BODY(addrmerge_recvdstaddr6_rev, tc)
838a85f1232SAlan Somers {
839a85f1232SAlan Somers 	char *maddr;
840a85f1232SAlan Somers 
841a85f1232SAlan Somers 	mock_igb1(false);
842a85f1232SAlan Somers 	mock_igb0();
843a85f1232SAlan Somers 	mock_lo0();
844a85f1232SAlan Somers 
845a85f1232SAlan Somers 	maddr = do_addrmerge6("2001:db8::2.3.46");
846a85f1232SAlan Somers 
847a85f1232SAlan Somers 	/* We must return the address on which the request was received */
848a85f1232SAlan Somers 	ATF_REQUIRE(maddr != NULL);
849a85f1232SAlan Somers 	ATF_CHECK_STREQ("2001:db8::2.3.46", maddr);
8500191f57fSAlan Somers 	free(maddr);
851a85f1232SAlan Somers }
852d18c9a91SDavid Bright 
853d18c9a91SDavid Bright ATF_TC_WITHOUT_HEAD(addrmerge_ipv6_other_subnet);
ATF_TC_BODY(addrmerge_ipv6_other_subnet,tc)854d18c9a91SDavid Bright ATF_TC_BODY(addrmerge_ipv6_other_subnet, tc)
855d18c9a91SDavid Bright {
856d18c9a91SDavid Bright 	char *maddr;
857d18c9a91SDavid Bright 
858d18c9a91SDavid Bright 	/* getifaddrs will return link local before normal ipv6 */
859d18c9a91SDavid Bright 	mock_lo0();
860d18c9a91SDavid Bright 	mock_mlxen0();
861d18c9a91SDavid Bright 
862d18c9a91SDavid Bright 	maddr = do_addrmerge6("2001:db8:1::1.3.46");
863d18c9a91SDavid Bright 
864d18c9a91SDavid Bright 	/* We must return the closest ipv6 address*/
865d18c9a91SDavid Bright 	ATF_REQUIRE(maddr != NULL);
866d18c9a91SDavid Bright 	ATF_CHECK_STREQ("2001:db8::7.3.46", maddr);
867d18c9a91SDavid Bright 	free(maddr);
868d18c9a91SDavid Bright }
869a85f1232SAlan Somers #endif /* INET6 */
870a85f1232SAlan Somers 
871a85f1232SAlan Somers 
ATF_TP_ADD_TCS(tp)872a85f1232SAlan Somers ATF_TP_ADD_TCS(tp)
873a85f1232SAlan Somers {
874a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_noifaddrs);
875a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_localhost_only);
876a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_singlehomed);
877a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_one_addr_on_each_subnet);
878a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_one_addr_on_each_subnet_rev);
879a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_point2point);
880a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_point2point_rev);
881a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_bindip);
882a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_bindip_rev);
883a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_recvdstaddr);
884a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_recvdstaddr_rev);
885a85f1232SAlan Somers #ifdef INET6
886a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_localhost_only6);
887a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_singlehomed6);
888a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_one_addr_on_each_subnet6);
889a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_one_addr_on_each_subnet6_rev);
890a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_point2point6);
891a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_point2point6_rev);
892a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_bindip6);
893a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_bindip6_rev);
894a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_ipv6_linklocal);
895a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_ipv6_linklocal_rev);
896a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_recvdstaddr6);
897a85f1232SAlan Somers 	ATF_TP_ADD_TC(tp, addrmerge_recvdstaddr6_rev);
898d18c9a91SDavid Bright 	ATF_TP_ADD_TC(tp, addrmerge_ipv6_other_subnet);
899a85f1232SAlan Somers #endif
900a85f1232SAlan Somers 
901a85f1232SAlan Somers 	return (atf_no_error());
902a85f1232SAlan Somers }
903