xref: /minix/minix/tests/test93.c (revision 03ac74ed)
1 /* Tests for network interfaces and routing (LWIP) - by D.C. van Moolenbroek */
2 /* This test needs to be run as root: it manipulates network settings. */
3 /*
4  * TODO: due to time constraints, this test is currently absolutely minimal.
5  * It does not yet test by far most of the service code it is supposed to test,
6  * in particular interface management code, interface address assignment code,
7  * routing sockets code, and routing code. The second subtest (test93b) in this
8  * file serves as a reasonable example of how many of the future subtests
9  * should operate, though: by issuing interface IOCTLs and routing commands on
10  * a loopback interface created for the occasion.
11  */
12 #include <stdlib.h>
13 #include <string.h>
14 #include <stddef.h>
15 #include <sys/socket.h>
16 #include <sys/ioctl.h>
17 #include <net/if.h>
18 #include <net/if_dl.h>
19 #include <net/route.h>
20 #include <netinet/in.h>
21 #include <netinet6/in6_var.h>
22 #include <arpa/inet.h>
23 
24 #include "common.h"
25 #include "socklib.h"
26 
27 #define TEST_IFNAME	"lo93"
28 
29 #define ITERATIONS 2
30 
31 static const enum state rtlnk_states[] = {
32 		S_NEW,		S_N_SHUT_R,	S_N_SHUT_W,	S_N_SHUT_RW,
33 };
34 
35 static const int rt_results[][__arraycount(rtlnk_states)] = {
36 	[C_ACCEPT]		= {
37 		-EOPNOTSUPP,	-EOPNOTSUPP,	-EOPNOTSUPP,	-EOPNOTSUPP,
38 	},
39 	[C_BIND]		= {
40 		-EOPNOTSUPP,	-EOPNOTSUPP,	-EOPNOTSUPP,	-EOPNOTSUPP,
41 	},
42 	[C_CONNECT]		= {
43 		-EOPNOTSUPP,	-EOPNOTSUPP,	-EOPNOTSUPP,	-EOPNOTSUPP,
44 	},
45 	[C_GETPEERNAME]		= {
46 		0,		0,		0,		0,
47 	},
48 	[C_GETSOCKNAME]		= {
49 		0,		0,		0,		0,
50 	},
51 	[C_GETSOCKOPT_ERR]	= {
52 		0,		0,		0,		0,
53 	},
54 	[C_GETSOCKOPT_KA]	= {
55 		0,		0,		0,		0,
56 	},
57 	[C_GETSOCKOPT_RB]	= {
58 		0,		0,		0,		0,
59 	},
60 	[C_IOCTL_NREAD]		= {
61 		0,		0,		0,		0,
62 	},
63 	[C_LISTEN]		= {
64 		-EOPNOTSUPP,	-EOPNOTSUPP,	-EOPNOTSUPP,	-EOPNOTSUPP,
65 	},
66 	[C_RECV]		= {
67 		-EAGAIN,	0,		-EAGAIN,	0,
68 	},
69 	[C_RECVFROM]		= {
70 		-EAGAIN,	0,		-EAGAIN,	0,
71 	},
72 	[C_SEND]		= {
73 		-ENOBUFS,	-ENOBUFS,	-EPIPE,		-EPIPE,
74 	},
75 	[C_SENDTO]		= {
76 		-EISCONN,	-EISCONN,	-EPIPE,		-EPIPE,
77 	},
78 	[C_SELECT_R]		= {
79 		0,		1,		0,		1,
80 	},
81 	[C_SELECT_W]		= {
82 		1,		1,		1,		1,
83 	},
84 	[C_SELECT_X]		= {
85 		0,		0,		0,		0,
86 	},
87 	[C_SETSOCKOPT_BC]	= {
88 		0,		0,		0,		0,
89 	},
90 	[C_SETSOCKOPT_KA]	= {
91 		0,		0,		0,		0,
92 	},
93 	[C_SETSOCKOPT_L]	= {
94 		0,		0,		0,		0,
95 	},
96 	[C_SETSOCKOPT_RA]	= {
97 		0,		0,		0,		0,
98 	},
99 	[C_SHUTDOWN_R]		= {
100 		0,		0,		0,		0,
101 	},
102 	[C_SHUTDOWN_RW]		= {
103 		0,		0,		0,		0,
104 	},
105 	[C_SHUTDOWN_W]		= {
106 		0,		0,		0,		0,
107 	},
108 };
109 
110 static const int lnk_results[][__arraycount(rtlnk_states)] = {
111 	[C_ACCEPT]		= {
112 		-EOPNOTSUPP,	-EOPNOTSUPP,	-EOPNOTSUPP,	-EOPNOTSUPP,
113 	},
114 	[C_BIND]		= {
115 		-EOPNOTSUPP,	-EOPNOTSUPP,	-EOPNOTSUPP,	-EOPNOTSUPP,
116 	},
117 	[C_CONNECT]		= {
118 		-EOPNOTSUPP,	-EOPNOTSUPP,	-EOPNOTSUPP,	-EOPNOTSUPP,
119 	},
120 	[C_GETPEERNAME]		= {
121 		-EOPNOTSUPP,	-EOPNOTSUPP,	-EOPNOTSUPP,	-EOPNOTSUPP,
122 	},
123 	[C_GETSOCKNAME]		= {
124 		-EOPNOTSUPP,	-EOPNOTSUPP,	-EOPNOTSUPP,	-EOPNOTSUPP,
125 	},
126 	[C_GETSOCKOPT_ERR]	= {
127 		0,		0,		0,		0,
128 	},
129 	[C_GETSOCKOPT_KA]	= {
130 		0,		0,		0,		0,
131 	},
132 	[C_GETSOCKOPT_RB]	= {
133 		-ENOPROTOOPT,	-ENOPROTOOPT,	-ENOPROTOOPT,	-ENOPROTOOPT,
134 	},
135 	[C_IOCTL_NREAD]		= {
136 		0,		0,		0,		0,
137 	},
138 	[C_LISTEN]		= {
139 		-EOPNOTSUPP,	-EOPNOTSUPP,	-EOPNOTSUPP,	-EOPNOTSUPP,
140 	},
141 	[C_RECV]		= {
142 		-EOPNOTSUPP,	0,		-EOPNOTSUPP,	0,
143 	},
144 	[C_RECVFROM]		= {
145 		-EOPNOTSUPP,	0,		-EOPNOTSUPP,	0,
146 	},
147 	[C_SEND]		= {
148 		-EOPNOTSUPP,	-EOPNOTSUPP,	-EPIPE,		-EPIPE,
149 	},
150 	[C_SENDTO]		= {
151 		-EOPNOTSUPP,	-EOPNOTSUPP,	-EPIPE,		-EPIPE,
152 	},
153 	[C_SELECT_R]		= {
154 		1,		1,		1,		1,
155 	},
156 	[C_SELECT_W]		= {
157 		1,		1,		1,		1,
158 	},
159 	[C_SELECT_X]		= {
160 		0,		0,		0,		0,
161 	},
162 	[C_SETSOCKOPT_BC]	= {
163 		0,		0,		0,		0,
164 	},
165 	[C_SETSOCKOPT_KA]	= {
166 		0,		0,		0,		0,
167 	},
168 	[C_SETSOCKOPT_L]	= {
169 		0,		0,		0,		0,
170 	},
171 	[C_SETSOCKOPT_RA]	= {
172 		0,		0,		0,		0,
173 	},
174 	[C_SHUTDOWN_R]		= {
175 		0,		0,		0,		0,
176 	},
177 	[C_SHUTDOWN_RW]		= {
178 		0,		0,		0,		0,
179 	},
180 	[C_SHUTDOWN_W]		= {
181 		0,		0,		0,		0,
182 	},
183 };
184 
185 /*
186  * Set up a routing or link socket file descriptor in the requested state and
187  * pass it to socklib_sweep_call() along with local and remote addresses and
188  * their lengths.
189  */
190 static int
191 rtlnk_sweep(int domain, int type, int protocol, enum state state,
192 	enum call call)
193 {
194 	struct sockaddr sa;
195 	int r, fd;
196 
197 	memset(&sa, 0, sizeof(sa));
198 	sa.sa_family = domain;
199 
200 	if ((fd = socket(domain, type | SOCK_NONBLOCK, protocol)) < 0) e(0);
201 
202 	switch (state) {
203 	case S_NEW: break;
204 	case S_N_SHUT_R: if (shutdown(fd, SHUT_RD)) e(0); break;
205 	case S_N_SHUT_W: if (shutdown(fd, SHUT_WR)) e(0); break;
206 	case S_N_SHUT_RW: if (shutdown(fd, SHUT_RDWR)) e(0); break;
207 	default: e(0);
208 	}
209 
210 	r = socklib_sweep_call(call, fd, &sa, &sa,
211 	    offsetof(struct sockaddr, sa_data));
212 
213 	if (close(fd) != 0) e(0);
214 
215 	return r;
216 }
217 
218 /*
219  * Sweep test for socket calls versus socket states of routing and link
220  * sockets.
221  */
222 static void
223 test93a(void)
224 {
225 
226 	subtest = 1;
227 
228 	socklib_sweep(AF_ROUTE, SOCK_RAW, 0, rtlnk_states,
229 	    __arraycount(rtlnk_states), (const int *)rt_results, rtlnk_sweep);
230 
231 	/*
232 	 * Our implementation of link sockets currently serves only one
233 	 * purpose, and that is to pass on ioctl() calls issued on the socket.
234 	 * As such, the results here are not too important.  The test mostly
235 	 * ensures that all calls actually complete--for example, that there is
236 	 * no function pointer NULL check missing in libsockevent.
237 	 */
238 	socklib_sweep(AF_LINK, SOCK_DGRAM, 0, rtlnk_states,
239 	    __arraycount(rtlnk_states), (const int *)lnk_results, rtlnk_sweep);
240 }
241 
242 /*
243  * Attempt to destroy the test loopback interface.  Return 0 if destruction was
244  * successful, or -1 if no such interface existed.
245  */
246 static int
247 test93_destroy_if(void)
248 {
249 	struct ifreq ifr;
250 	int r, fd;
251 
252 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) e(0);
253 
254 	memset(&ifr, 0, sizeof(ifr));
255 	strlcpy(ifr.ifr_name, TEST_IFNAME, sizeof(ifr.ifr_name));
256 
257 	r = ioctl(fd, SIOCIFDESTROY, &ifr);
258 	if (r != 0 && (r != -1 || errno != ENXIO)) e(0);
259 
260 	if (close(fd) != 0) e(0);
261 
262 	return r;
263 }
264 
265 /*
266  * Destroy the test interface at exit.  It is always safe to do so as its name
267  * is sufficiently unique, and we do not want to leave it around.
268  */
269 static void
270 test93_destroy_if_atexit(void)
271 {
272 	static int atexit_set = 0;
273 
274 	if (!atexit_set) {
275 		(void)test93_destroy_if();
276 
277 		atexit_set = 1;
278 	}
279 }
280 
281 /*
282  * Attempt to create a test loopback interface.  Return 0 if creation was
283  * successful, or -1 if no more interfaces could be created.
284  */
285 static int
286 test93_create_if(void)
287 {
288 	struct ifreq ifr;
289 	int r, fd;
290 
291 	(void)test93_destroy_if();
292 
293 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) e(0);
294 
295 	memset(&ifr, 0, sizeof(ifr));
296 	strlcpy(ifr.ifr_name, TEST_IFNAME, sizeof(ifr.ifr_name));
297 
298 	r = ioctl(fd, SIOCIFCREATE, &ifr);
299 	if (r != 0 && (r != -1 || errno != ENOBUFS)) e(0);
300 
301 	if (close(fd) != 0) e(0);
302 
303 	atexit(test93_destroy_if_atexit);
304 
305 	return r;
306 }
307 
308 /*
309  * Set the interface-up value for an interface to the given boolean value.
310  */
311 static void
312 test93_set_if_up(const char * ifname, int up)
313 {
314 	struct ifreq ifr;
315 	int fd;
316 
317 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) e(0);
318 
319 	memset(&ifr, 0, sizeof(ifr));
320 	strlcpy(ifr.ifr_name, TEST_IFNAME, sizeof(ifr.ifr_name));
321 
322 	if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0) e(0);
323 
324 	if (up)
325 		ifr.ifr_flags |= IFF_UP;
326 	else
327 		ifr.ifr_flags &= ~IFF_UP;
328 
329 	if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0) e(0);
330 
331 	if (close(fd) != 0) e(0);
332 }
333 
334 /*
335  * Construct an IPv6 network mask for a certain prefix length.
336  */
337 static void
338 test93_make_netmask6(struct sockaddr_in6 * sin6, unsigned int prefix)
339 {
340 	unsigned int byte, bit;
341 
342 	if (prefix > 128) e(0);
343 	memset(sin6, 0, sizeof(*sin6));
344 	sin6->sin6_family = AF_INET6;
345 
346 	byte = prefix / NBBY;
347 	bit = prefix % NBBY;
348 
349 	if (byte > 0)
350 		memset(sin6->sin6_addr.s6_addr, 0xff, byte);
351 	if (bit != 0)
352 		sin6->sin6_addr.s6_addr[byte] = 0xff << (NBBY - bit);
353 }
354 
355 /*
356  * Issue a modifying routing command, which must be one of RTM_ADD, RTM_CHANGE,
357  * RTM_DELETE, or RTM_LOCK.  The destination address (IPv4 or IPv6) and netmask
358  * prefix are required.  The flags (RTF_), interface name, and gateway are
359  * optional depending on the command (and flags) being issued.  Return 0 on
360  * success, and -1 with errno set on failure.
361  */
362 static int
363 test93_route_cmd(int cmd, const struct sockaddr * dest, socklen_t dest_len,
364 	unsigned int prefix, int flags, const char * ifname,
365 	const struct sockaddr * gw, socklen_t gw_len)
366 {
367 	static unsigned int seq = 0;
368 	struct sockaddr_storage destss, maskss, ifpss, gwss;
369 	struct sockaddr_in mask4;
370 	struct sockaddr_in6 mask6;
371 	struct sockaddr_dl ifp;
372 	struct rt_msghdr rtm;
373 	struct iovec iov[5];
374 	struct msghdr msg;
375 	unsigned int i, iovlen;
376 	int r, fd, err;
377 
378 	memset(&rtm, 0, sizeof(rtm));
379 	rtm.rtm_version = RTM_VERSION;
380 	rtm.rtm_type = cmd;
381 	rtm.rtm_flags = flags;
382 	rtm.rtm_addrs = RTA_DST | RTA_NETMASK;
383 	rtm.rtm_seq = ++seq;
384 
385 	iovlen = 0;
386 	iov[iovlen].iov_base = &rtm;
387 	iov[iovlen++].iov_len = sizeof(rtm);
388 
389 	memset(&destss, 0, sizeof(destss));
390 	memcpy(&destss, dest, dest_len);
391 	destss.ss_len = dest_len;
392 
393 	iov[iovlen].iov_base = &destss;
394 	iov[iovlen++].iov_len = RT_ROUNDUP(dest_len);
395 
396 	/* Do this in RTA order. */
397 	memset(&gwss, 0, sizeof(gwss));
398 	if (gw != NULL) {
399 		memcpy(&gwss, gw, gw_len);
400 		gwss.ss_len = gw_len;
401 
402 		rtm.rtm_addrs |= RTA_GATEWAY;
403 		iov[iovlen].iov_base = &gwss;
404 		iov[iovlen++].iov_len = RT_ROUNDUP(gwss.ss_len);
405 	}
406 
407 	memset(&maskss, 0, sizeof(maskss));
408 	switch (dest->sa_family) {
409 	case AF_INET:
410 		if (prefix > 32) e(0);
411 		memset(&mask4, 0, sizeof(mask4));
412 		mask4.sin_family = AF_INET;
413 		if (prefix < 32)
414 			mask4.sin_addr.s_addr = htonl(0xffffffffUL << prefix);
415 
416 		memcpy(&maskss, &mask4, sizeof(mask4));
417 		maskss.ss_len = sizeof(mask4);
418 
419 		break;
420 
421 	case AF_INET6:
422 		test93_make_netmask6(&mask6, prefix);
423 
424 		memcpy(&maskss, &mask6, sizeof(mask6));
425 		maskss.ss_len = sizeof(mask6);
426 
427 		break;
428 
429 	default:
430 		e(0);
431 	}
432 
433 	iov[iovlen].iov_base = &maskss;
434 	iov[iovlen++].iov_len = RT_ROUNDUP(maskss.ss_len);
435 
436 	if (ifname != NULL) {
437 		memset(&ifp, 0, sizeof(ifp));
438 		ifp.sdl_nlen = strlen(ifname);
439 		ifp.sdl_len = offsetof(struct sockaddr_dl, sdl_data) +
440 		    ifp.sdl_nlen;
441 		ifp.sdl_family = AF_LINK;
442 
443 		memset(&ifpss, 0, sizeof(ifpss));
444 		memcpy(&ifpss, &ifp, ifp.sdl_len);
445 		memcpy(&((struct sockaddr_dl *)&ifpss)->sdl_data, ifname,
446 		    ifp.sdl_nlen);
447 
448 		rtm.rtm_addrs |= RTA_IFP;
449 		iov[iovlen].iov_base = &ifpss;
450 		iov[iovlen++].iov_len = RT_ROUNDUP(ifpss.ss_len);
451 	}
452 
453 	memset(&msg, 0, sizeof(msg));
454 	msg.msg_iov = iov;
455 	msg.msg_iovlen = iovlen;
456 
457 	if ((fd = socket(AF_ROUTE, SOCK_RAW, 0)) < 0) e(0);
458 
459 	for (i = 0; i < iovlen; i++)
460 		rtm.rtm_msglen += iov[i].iov_len;
461 
462 	r = sendmsg(fd, &msg, 0);
463 	if (r != rtm.rtm_msglen && r != -1) e(0);
464 	err = errno;
465 
466 	/*
467 	 * We could just shut down the socket for reading, but this is just an
468 	 * extra test we can do basically for free.
469 	 */
470 	rtm.rtm_seq = 0;
471 	do {
472 		iov[0].iov_base = &rtm;
473 		iov[0].iov_len = sizeof(rtm);
474 
475 		if (recvmsg(fd, &msg, 0) <= 0) e(0);
476 	} while (rtm.rtm_pid != getpid() || rtm.rtm_seq != seq);
477 
478 	if (r == -1) {
479 		if (rtm.rtm_errno != err) e(0);
480 		if (rtm.rtm_flags & RTF_DONE) e(0);
481 	} else {
482 		if (rtm.rtm_errno != 0) e(0);
483 		if (!(rtm.rtm_flags & RTF_DONE)) e(0);
484 	}
485 
486 	if (close(fd) != 0) e(0);
487 
488 	errno = err;
489 	return (r > 0) ? 0 : -1;
490 }
491 
492 /*
493  * Add or delete an IPv6 address to or from an interface.  The interface name,
494  * address, and prefix length must always be given.  When adding, a set of
495  * flags (IN6_IFF) and lifetimes must be given as well.
496  */
497 static void
498 test93_ipv6_addr(int add, const char * ifname,
499 	const struct sockaddr_in6 * sin6, unsigned int prefix, int flags,
500 	uint32_t valid_life, uint32_t pref_life)
501 {
502 	struct in6_aliasreq ifra;
503 	int fd;
504 
505 	memset(&ifra, 0, sizeof(ifra));
506 	strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
507 	memcpy(&ifra.ifra_addr, sin6, sizeof(ifra.ifra_addr));
508 	/* leave ifra_dstaddr blank */
509 	test93_make_netmask6(&ifra.ifra_prefixmask, prefix);
510 	ifra.ifra_flags = flags;
511 	ifra.ifra_lifetime.ia6t_vltime = valid_life;
512 	ifra.ifra_lifetime.ia6t_pltime = pref_life;
513 
514 	if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) e(0);
515 
516 	if (ioctl(fd, (add) ? SIOCAIFADDR_IN6 : SIOCDIFADDR_IN6, &ifra) != 0)
517 		e(0);
518 
519 	if (close(fd) != 0) e(0);
520 }
521 
522 static const struct {
523 	int result; /* 0..2 = prefer srcN, -1 = no preference */
524 	const char *dest_addr;
525 	const char *src0_addr;
526 	unsigned int src0_prefix;
527 	int src0_flags;
528 	const char *src1_addr;
529 	unsigned int src1_prefix;
530 	int src1_flags;
531 	const char *src2_addr;
532 	unsigned int src2_prefix;
533 	int src2_flags;
534 } test93b_table[] = {
535 	/*
536 	 * These are all the applicable tests from RFC 6724 Sec. 10.1, slightly
537 	 * changed not to use the default link-local address of lo0.
538 	 */
539 	/* Prefer appropriate scope: */
540 	{ 0, "2001:db8:1::1", "2001:db8:3::1", 64, 0, "fe80::93:1", 64, 0 },
541 	/* Prefer appropriate scope: */
542 	{ 0, "ff05::1", "2001:db8:3::1", 64, 0, "fe80::93:1", 64, 0 },
543 	/* Prefer same address: */
544 	{ 0, "2001:db8:1::1", "2001:db8:1::1", 64, IN6_IFF_DEPRECATED,
545 	    "2001:db8:2::1", 64, 0 },
546 	/* Prefer appropriate scope: */
547 	{ 0, "fe80::93:1", "fe80::93:2", 64, IN6_IFF_DEPRECATED,
548 	    "2001:db8:2::1", 64, 0 },
549 	/* Longest matching prefix: */
550 	{ 0, "2001:db8:1::1", "2001:db8:1::2", 64, 0, "2001:db8:3::2", 64, 0 },
551 	/* Prefer matching label: */
552 	{ 0, "2002:c633:6401::1", "2002:c633:6401::d5e3:7953:13eb:22e8", 64,
553 	    IN6_IFF_TEMPORARY, "2001:db8:1::2", 64, 0 },
554 	/* Prefer temporary address: */
555 	{ 1, "2001:db8:1::d5e3:0:0:1", "2001:db8:1::2", 64, 0,
556 	    "2001:db8:1::d5e3:7953:13eb:22e8", 64, IN6_IFF_TEMPORARY },
557 	/*
558 	 * Our own additional tests.
559 	 */
560 	/* Prefer same address: */
561 	{ 1, "4000:93::1", "2001:db8:3::1", 64, 0, "4000:93::1", 64, 0 },
562 	{ 2, "2001:db8:1::1", "2001:db8:3::1", 64, 0, "fe80::93:1", 64, 0,
563 	    "2001:db8:1::1", 64, 0 },
564 	/* Prefer appropriate scope: */
565 	{ 1, "ff01::1", "2001:db8:3::1", 64, 0, "fe80::93:1", 64, 0 },
566 	{ 1, "ff02::1", "2001:db8:3::1", 64, 0, "fe80::93:1", 64, 0 },
567 	{ 0, "ff0e::1", "2001:db8:3::1", 64, 0, "fe80::93:1", 64, 0 },
568 	{ 1, "fd00:93::1", "2001:db8:3::1", 64, 0, "fd00::93:2", 64, 0 },
569 	{ 1, "fd00:93::1", "fe80::93:1", 64, 0, "fd00::93:2", 64, 0 },
570 	{ 0, "fd00:93::1", "2001:db8:3::1", 64, 0, "fe80::93:1", 64, 0 },
571 	{ 1, "2001:db8:1::1", "fe80::93:1", 64, 0, "fd00::93:2", 64, 0 },
572 	{ 0, "2001:db8:1::1", "2001:db8:3::1", 64, 0, "4000:93::1", 64, 0 },
573 	{ 0, "4000:93::2", "2001:db8:3::1", 64, 0, "4000:93::1", 64, 0 },
574 	{ 2, "2001:db8:1::1", "fe80::93:1", 64, 0, "fd00::93:1", 64, 0,
575 	    "2001:db8:3::1", 64, 0 },
576 	{ 2, "2001:db8:1::1", "fe80::93:1", 64, IN6_IFF_DEPRECATED,
577 	    "fe80::93:2", 64, 0, "2001:db8:3::1", 64, 0 },
578 	/* Avoid deprecated address: */
579 	{ 1, "2002:c633:6401::1", "2002:c633:6401::d5e3:7953:13eb:22e8", 64,
580 	    IN6_IFF_DEPRECATED, "2001:db8:1::2", 64, 0 },
581 	{ 2, "2001:db8:1::1", "2001:db8:1::3", 64, IN6_IFF_DEPRECATED,
582 	    "2001:db8:2::1", 64, IN6_IFF_DEPRECATED, "2001:db8:3::1", 64, 0 },
583 	{ 2, "2001:db8:1::1", "2002:db8:1::3", 64, IN6_IFF_DEPRECATED,
584 	    "2001:db8:2::1", 64, IN6_IFF_DEPRECATED, "2001:db8:3::1", 64, 0 },
585 	/* Prefer matching label: */
586 	{ 0, "2002:c633:6401::1", "2002:c633:6401::d5e3:7953:13eb:22e8", 64, 0,
587 	    "2001:db8:1::2", 64, IN6_IFF_TEMPORARY },
588 	{ 2, "2002:c633:6401::1", "2001:db8:3::2", 64, 0, "2001:db8:1::2", 64,
589 	    IN6_IFF_TEMPORARY, "2002:c633:6401::d5e3:7953:13eb:22e8", 64, 0 },
590 	{ 2, "2001:db8:1::1", "2003:db8::1", 64, 0, "3ffe:db8::1", 64, 0,
591 	    "2001:db8:3::1", 64, 0 },
592 	/* Prefer temporary address: */
593 	{ 0, "2001:db8:1::d5e3:0:0:1", "2001:db8:1::2", 96, IN6_IFF_TEMPORARY,
594 	    "2001:db8:1::d5e3:7953:13eb:22e8", 96, 0 },
595 	{ 2, "2002:c633:6401::1", "2001:db8:3::2", 64, 0, "2002:c633:6401::2",
596 	    64, 0, "2002:c633:6401::d5e3:7953:13eb:22e8", 64,
597 	    IN6_IFF_TEMPORARY },
598 	/* Longest matching prefix: */
599 	{ 1, "2001:db8:1::d5e3:0:0:1", "2001:db8:1::2", 96, 0,
600 	    "2001:db8:1::d5e3:7953:13eb:22e8", 96, 0 },
601 	{ 2, "2001:db8:1:1::1", "2001:db8:2:1::2", 64, 0, "2001:db8:1:2::2",
602 	    64, 0, "2001:db8:1:1::2", 64, 0 },
603 	{ 0, "2001:db8:1::1", "2001:db8:1::2", 47, 0, "2001:db8:3::2", 47, 0 },
604 	/* No preference (a tie): */
605 	{ -1, "2001:db8:1::1", "2001:db8:1::2", 46, 0, "2001:db8:3::2", 46,
606 	    0 },
607 	{ -1, "2001:db8::1:0:0:1", "2001:db8::1:0:0:2", 64, 0,
608 	    "2001:db8::2:0:0:2", 64, 0, "2001:db8::3:0:0:2", 64, 0 },
609 };
610 
611 struct src_addr {
612 	struct sockaddr_in6 addr;
613 	unsigned int prefix;
614 	int flags;
615 };
616 
617 /*
618  * Test source address selection with a particular destination address and two
619  * or three source addresses.
620  */
621 static void
622 sub93b(int result, const struct sockaddr_in6 * dest, unsigned int ifindex,
623 	const struct src_addr * src0, const struct src_addr * src1,
624 	const struct src_addr * src2)
625 {
626 	struct sockaddr_in6 dest_copy, src;
627 	socklen_t len;
628 	int fd, rt_res;
629 
630 	/* Add the candidate source addresses. */
631 	test93_ipv6_addr(1, TEST_IFNAME, &src0->addr, src0->prefix,
632 	    src0->flags, 0xffffffffUL, 0xffffffffUL);
633 
634 	test93_ipv6_addr(1, TEST_IFNAME, &src1->addr, src1->prefix,
635 	    src1->flags, 0xffffffffUL, 0xffffffffUL);
636 
637 	if (src2 != NULL)
638 		test93_ipv6_addr(1, TEST_IFNAME, &src2->addr, src2->prefix,
639 		    src2->flags, 0xffffffffUL, 0xffffffffUL);
640 
641 	/*
642 	 * We need to make sure that packets to the destination are routed to
643 	 * our test interface at all, so create a route for it.  Creating the
644 	 * route may fail if the destination address is equal to either of the
645 	 * source addresses, but that is fine.  We use a blackhole route here,
646 	 * but this test should not generate any traffic anyway.
647 	 */
648 	rt_res = test93_route_cmd(RTM_ADD, (struct sockaddr *)dest,
649 	    sizeof(*dest), 128, RTF_UP | RTF_BLACKHOLE | RTF_STATIC,
650 	    TEST_IFNAME, NULL, 0);
651 	if (rt_res != 0 && (rt_res != -1 || errno != EEXIST)) e(0);
652 
653 	if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) e(0);
654 
655 	/* Set a scope ID if necessary. */
656 	memcpy(&dest_copy, dest, sizeof(dest_copy));
657 	dest_copy.sin6_port = 1; /* anything that is not zero */
658 	if (IN6_IS_ADDR_LINKLOCAL(&dest_copy.sin6_addr) ||
659 	    IN6_IS_ADDR_MC_NODELOCAL(&dest_copy.sin6_addr) ||
660 	    IN6_IS_ADDR_MC_LINKLOCAL(&dest_copy.sin6_addr))
661 		dest_copy.sin6_scope_id = ifindex;
662 
663 	/* Connecting also selects a source address. */
664 	if (connect(fd, (struct sockaddr *)&dest_copy, sizeof(dest_copy)) != 0)
665 		e(0);
666 
667 	/* Obtain the selected source address. */
668 	len = sizeof(src);
669 	if (getsockname(fd, (struct sockaddr *)&src, &len) != 0) e(0);
670 
671 	/*
672 	 * If the chosen destination address has a scope ID, it must be for our
673 	 * test interface.
674 	 */
675 	if (src.sin6_scope_id != 0 && src.sin6_scope_id != ifindex) e(0);
676 
677 	/* Is it the expected candidate source address? */
678 	if (!memcmp(&src.sin6_addr, &src0->addr.sin6_addr,
679 	    sizeof(src.sin6_addr))) {
680 		if (result != 0) e(0);
681 	} else if (!memcmp(&src.sin6_addr, &src1->addr.sin6_addr,
682 	    sizeof(src.sin6_addr))) {
683 		if (result != 1) e(0);
684 	} else if (src2 != NULL && !memcmp(&src.sin6_addr,
685 	    &src2->addr.sin6_addr, sizeof(src.sin6_addr))) {
686 		if (result != 2) e(0);
687 	} else
688 		e(0);
689 
690 	/* Clean up. */
691 	if (close(fd) != 0) e(0);
692 
693 	if (rt_res == 0) {
694 		if (test93_route_cmd(RTM_DELETE, (struct sockaddr *)dest,
695 		    sizeof(*dest), 128, 0, NULL, NULL, 0) != 0) e(0);
696 	}
697 
698 	if (src2 != NULL)
699 		test93_ipv6_addr(0, TEST_IFNAME, &src2->addr, src2->prefix, 0,
700 		    0, 0);
701 
702 	test93_ipv6_addr(0, TEST_IFNAME, &src1->addr, src1->prefix, 0, 0, 0);
703 
704 	test93_ipv6_addr(0, TEST_IFNAME, &src0->addr, src0->prefix, 0, 0, 0);
705 }
706 
707 /*
708  * IPv6 source address selection algorithm test.
709  */
710 static void
711 test93b(void)
712 {
713 	static const int order[][3] = {
714 		{ 0, 1, 2 },
715 		{ 1, 0, 2 },
716 		{ 0, 2, 1 },
717 		{ 1, 2, 0 },
718 		{ 2, 0, 1 },
719 		{ 2, 1, 0 }
720 	};
721 	struct sockaddr_in6 dest;
722 	struct src_addr src[3];
723 	unsigned int i, j, k, count, ifindex;
724 	int result;
725 
726 	subtest = 2;
727 
728 	if (test93_create_if() != 0)
729 		return; /* skip this test */
730 
731 	if ((ifindex = if_nametoindex(TEST_IFNAME)) == 0) e(0);
732 
733 	test93_set_if_up(TEST_IFNAME, 1);
734 
735 	for (i = 0; i < __arraycount(test93b_table); i++) {
736 		memset(&dest, 0, sizeof(dest));
737 		dest.sin6_family = AF_INET6;
738 		if (inet_pton(AF_INET6, test93b_table[i].dest_addr,
739 		    &dest.sin6_addr) != 1) e(0);
740 
741 		memset(&src[0].addr, 0, sizeof(src[0].addr));
742 		src[0].addr.sin6_family = AF_INET6;
743 		if (inet_pton(AF_INET6, test93b_table[i].src0_addr,
744 		    &src[0].addr.sin6_addr) != 1) e(0);
745 		src[0].prefix = test93b_table[i].src0_prefix;
746 		src[0].flags = test93b_table[i].src0_flags;
747 
748 		memset(&src[1].addr, 0, sizeof(src[1].addr));
749 		src[1].addr.sin6_family = AF_INET6;
750 		if (inet_pton(AF_INET6, test93b_table[i].src1_addr,
751 		    &src[1].addr.sin6_addr) != 1) e(0);
752 		src[1].prefix = test93b_table[i].src1_prefix;
753 		src[1].flags = test93b_table[i].src1_flags;
754 
755 		if (test93b_table[i].src2_addr != NULL) {
756 			memset(&src[2].addr, 0, sizeof(src[2].addr));
757 			src[2].addr.sin6_family = AF_INET6;
758 			if (inet_pton(AF_INET6, test93b_table[i].src2_addr,
759 			    &src[2].addr.sin6_addr) != 1) e(0);
760 			src[2].prefix = test93b_table[i].src2_prefix;
761 			src[2].flags = test93b_table[i].src2_flags;
762 
763 			count = 6;
764 		} else
765 			count = 2;
766 
767 		result = test93b_table[i].result;
768 
769 		/*
770 		 * Try all orders for the source addresses.  The permutation
771 		 * part can be done much better, but it really does not matter.
772 		 */
773 		for (j = 0; j < count; j++) {
774 			for (k = 0; k < count; k++)
775 				if (result == -1 || order[j][k] == result)
776 					break;
777 
778 			sub93b((result != -1) ? k : 0, &dest, ifindex,
779 			    &src[order[j][0]], &src[order[j][1]],
780 			    (count > 2) ? &src[order[j][2]] : NULL);
781 		}
782 	}
783 
784 	if (test93_destroy_if() != 0) e(0);
785 }
786 
787 /*
788  * Interface index number wrapping test.
789  */
790 static void
791 test93c(void)
792 {
793 	unsigned int i;
794 
795 	subtest = 3;
796 
797 	/* There might not be an available loopback interface at all. */
798 	if (test93_create_if() != 0)
799 		return; /* skip this test */
800 
801 	if (test93_destroy_if() != 0) e(0);
802 
803 	/*
804 	 * During the development of the LWIP service, the lwIP library's
805 	 * interface index assignment was still in its infancy.  This test aims
806 	 * to ensure that future changes in the library do not break our
807 	 * service.
808 	 */
809 	for (i = 0; i < UINT8_MAX + 1; i++) {
810 		if (test93_create_if() != 0) e(0);
811 
812 		if (test93_destroy_if() != 0) e(0);
813 	}
814 }
815 
816 /*
817  * Test program for LWIP interface and routing management.
818  */
819 int
820 main(int argc, char ** argv)
821 {
822 	int i, m;
823 
824 	start(93);
825 
826 	if (argc == 2)
827 		m = atoi(argv[1]);
828 	else
829 		m = 0xFF;
830 
831 	for (i = 0; i < ITERATIONS; i++) {
832 		if (m & 0x01) test93a();
833 		if (m & 0x02) test93b();
834 		if (m & 0x04) test93c();
835 	}
836 
837 	quit();
838 	/* NOTREACHED */
839 }
840