xref: /freebsd/tests/sys/net/routing/rtsock_common.h (revision 652a9748855320619e075c4e83aef2f5294412d2)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2019 Alexander V. Chernikov
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD$
28  */
29 
30 #ifndef _NET_ROUTING_RTSOCK_COMMON_H_
31 #define _NET_ROUTING_RTSOCK_COMMON_H_
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38 #include <stdbool.h>
39 #include <ctype.h>
40 #include <poll.h>
41 
42 #include <sys/types.h>
43 #include <sys/time.h>
44 #include <sys/param.h>
45 #include <sys/socket.h>
46 #include <sys/ioctl.h>
47 #include <sys/jail.h>
48 #include <net/if.h>
49 #include <net/if_dl.h>
50 #include <net/route.h>
51 
52 #include <arpa/inet.h>
53 #include <net/ethernet.h>
54 
55 #include <netinet/in.h>
56 #include <netinet6/in6_var.h>
57 #include <netinet6/nd6.h>
58 
59 #include <ifaddrs.h>
60 
61 #include <errno.h>
62 #include <err.h>
63 #include <sysexits.h>
64 
65 #include <atf-c.h>
66 
67 #include "rtsock_print.h"
68 #include "params.h"
69 
70 void rtsock_update_rtm_len(struct rt_msghdr *rtm);
71 void rtsock_validate_message(char *buffer, ssize_t len);
72 void rtsock_add_rtm_sa(struct rt_msghdr *rtm, int addr_type, struct sockaddr *sa);
73 
74 void file_append_line(char *fname, char *text);
75 
76 static int _rtm_seq = 42;
77 
78 
79 /*
80  * Checks if the interface cloner module is present for @name.
81  */
82 static int
83 _check_cloner(char *name)
84 {
85 	struct if_clonereq ifcr;
86 	char *cp, *buf;
87 	int idx;
88 	int s;
89 	int found = 0;
90 
91 	s = socket(AF_LOCAL, SOCK_DGRAM, 0);
92 	if (s == -1)
93 		err(1, "socket(AF_LOCAL,SOCK_DGRAM)");
94 
95 	memset(&ifcr, 0, sizeof(ifcr));
96 
97 	if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0)
98 		err(1, "SIOCIFGCLONERS for count");
99 
100 	buf = malloc(ifcr.ifcr_total * IFNAMSIZ);
101 	if (buf == NULL)
102 		err(1, "unable to allocate cloner name buffer");
103 
104 	ifcr.ifcr_count = ifcr.ifcr_total;
105 	ifcr.ifcr_buffer = buf;
106 
107 	if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0)
108 		err(1, "SIOCIFGCLONERS for names");
109 
110 	/*
111 	 * In case some disappeared in the mean time, clamp it down.
112 	 */
113 	if (ifcr.ifcr_count > ifcr.ifcr_total)
114 		ifcr.ifcr_count = ifcr.ifcr_total;
115 
116 	for (cp = buf, idx = 0; idx < ifcr.ifcr_count; idx++, cp += IFNAMSIZ) {
117 		if (!strcmp(cp, name)) {
118 			found = 1;
119 			break;
120 		}
121 	}
122 
123 	free(buf);
124 	close(s);
125 
126 	return (found);
127 }
128 
129 /*
130  * Tries to ensure if_tap is loaded.
131  * Checks list of interface cloners first, then tries
132  * to load the module.
133  *
134  * return nonzero on success.
135  */
136 static int
137 _enforce_cloner_loaded(char *cloner_name)
138 {
139 	if (_check_cloner(cloner_name))
140 		return (1);
141 	/* need to load */
142 	RLOG("trying to load %s driver", cloner_name);
143 
144 	char cmd[64];
145 
146 	snprintf(cmd, sizeof(cmd), "/sbin/kldload if_%s", cloner_name);
147 	int ret = system(cmd);
148 	if (ret != 0) {
149 		RLOG("'%s' failed, error %d", cmd, ret);
150 		return (0);
151 	}
152 
153 	return (1);
154 }
155 
156 static char *
157 iface_create(char *ifname_orig)
158 {
159 	struct ifreq ifr;
160 	int s;
161 	char prefix[IFNAMSIZ], ifname[IFNAMSIZ], *result;
162 
163 	char *src, *dst;
164 	for (src = ifname_orig, dst = prefix; *src && isalpha(*src); src++)
165 		*dst++ = *src;
166 	*dst = '\0';
167 
168 	if (_enforce_cloner_loaded(prefix) == 0)
169 		return (NULL);
170 
171 	memset(&ifr, 0, sizeof(struct ifreq));
172 
173 	s = socket(AF_LOCAL, SOCK_DGRAM, 0);
174 	strlcpy(ifr.ifr_name, ifname_orig, sizeof(ifr.ifr_name));
175 
176 	RLOG("creating iface %s %s", prefix, ifr.ifr_name);
177 	if (ioctl(s, SIOCIFCREATE2, &ifr) < 0)
178 		err(1, "SIOCIFCREATE2");
179 
180 	strlcpy(ifname, ifr.ifr_name, IFNAMSIZ);
181 	RLOG("created interface %s", ifname);
182 
183 	result = strdup(ifname);
184 
185 	file_append_line(IFACES_FNAME, ifname);
186 	if (strstr(ifname, "epair") == ifname) {
187 		/* call returned epairXXXa, need to add epairXXXb */
188 		ifname[strlen(ifname) - 1] = 'b';
189 		file_append_line(IFACES_FNAME, ifname);
190 	}
191 
192 	return (result);
193 }
194 
195 static int
196 iface_destroy(char *ifname)
197 {
198 	struct ifreq ifr;
199 	int s;
200 
201 	s = socket(AF_LOCAL, SOCK_DGRAM, 0);
202 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
203 
204 	RLOG("destroying interface %s", ifname);
205 	if (ioctl(s, SIOCIFDESTROY, &ifr) < 0)
206 		return (0);
207 
208 	return (1);
209 }
210 
211 /*
212  * Open tunneling device such as tuntap and returns fd.
213  */
214 int
215 iface_open(char *ifname)
216 {
217 	char path[256];
218 
219 	snprintf(path, sizeof(path), "/dev/%s", ifname);
220 
221 	RLOG("opening interface %s", ifname);
222 	int fd = open(path, O_RDWR|O_EXCL);
223 	if (fd == -1) {
224 		RLOG_ERRNO("unable to open interface %s", ifname);
225 		return (-1);
226 	}
227 
228 	return (fd);
229 }
230 
231 /*
232  * Sets primary IPv4 addr.
233  * Returns 0 on success.
234  */
235 inline int
236 iface_setup_addr(char *ifname, char *addr, int plen)
237 {
238 	char cmd[512];
239 	char *af;
240 
241 	if (strchr(addr, ':'))
242 		af = "inet6";
243 	else
244 		af = "inet";
245 	RLOG("setting af_%s %s/%d on %s", af, addr, plen, ifname);
246 	snprintf(cmd, sizeof(cmd), "/sbin/ifconfig %s %s %s/%d", ifname,
247 		af, addr, plen);
248 
249 	return system(cmd);
250 }
251 
252 /*
253  * Removes primary IPv4 prefix.
254  * Returns 0 on success.
255  */
256 inline int
257 iface_delete_addr(char *ifname, char *addr)
258 {
259 	char cmd[512];
260 
261 	if (strchr(addr, ':')) {
262 		RLOG("removing IPv6 %s from %s", addr, ifname);
263 		snprintf(cmd, sizeof(cmd), "/sbin/ifconfig %s inet6 %s delete", ifname, addr);
264 	} else {
265 		RLOG("removing IPv4 %s from %s", addr, ifname);
266 		snprintf(cmd, sizeof(cmd), "/sbin/ifconfig %s -alias %s", ifname, addr);
267 	}
268 
269 	return system(cmd);
270 }
271 
272 int
273 iface_turn_up(char *ifname)
274 {
275 	struct ifreq ifr;
276 	int s;
277 
278 	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
279 		RLOG_ERRNO("socket");
280 		return (-1);
281 	}
282 	memset(&ifr, 0, sizeof(struct ifreq));
283 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
284 	if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
285 		RLOG_ERRNO("ioctl(SIOCGIFFLAGS)");
286 		return (-1);
287 	}
288 	/* Update flags */
289 	if ((ifr.ifr_flags & IFF_UP) == 0) {
290 		ifr.ifr_flags |= IFF_UP;
291 		if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) {
292 			RLOG_ERRNO("ioctl(SIOSGIFFLAGS)");
293 			return (-1);
294 		}
295 		RLOG("turned interface %s up", ifname);
296 	}
297 
298 	return (0);
299 }
300 
301 /*
302  * Removes ND6_IFF_IFDISABLED from IPv6 interface flags.
303  * Returns 0 on success.
304  */
305 int
306 iface_enable_ipv6(char *ifname)
307 {
308 	struct in6_ndireq nd;
309 	int s;
310 
311 	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
312 		err(1, "socket");
313 	}
314 	memset(&nd, 0, sizeof(nd));
315 	strlcpy(nd.ifname, ifname, sizeof(nd.ifname));
316 	if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&nd) < 0) {
317 		RLOG_ERRNO("ioctl(SIOCGIFINFO_IN6)");
318 		return (-1);
319 	}
320 	/* Update flags */
321 	if ((nd.ndi.flags & ND6_IFF_IFDISABLED) != 0) {
322 		nd.ndi.flags &= ~ND6_IFF_IFDISABLED;
323 		if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd) < 0) {
324 			RLOG_ERRNO("ioctl(SIOCSIFINFO_IN6)");
325 			return (-1);
326 		}
327 		RLOG("enabled IPv6 for %s", ifname);
328 	}
329 
330 	return (0);
331 }
332 
333 void
334 file_append_line(char *fname, char *text)
335 {
336 	FILE *f;
337 
338 	f = fopen(fname, "a");
339 	fputs(text, f);
340 	fputs("\n", f);
341 	fclose(f);
342 }
343 
344 static int
345 vnet_wait_interface(char *vnet_name, char *ifname)
346 {
347 	char buf[512], cmd[512], *line, *token;
348 	FILE *fp;
349 	int i;
350 
351 	snprintf(cmd, sizeof(cmd), "/usr/sbin/jexec %s /sbin/ifconfig -l", vnet_name);
352 	for (int i = 0; i < 50; i++) {
353 		fp = popen(cmd, "r");
354 		line = fgets(buf, sizeof(buf), fp);
355 		/* cut last\n */
356 		if (line[0])
357 			line[strlen(line)-1] = '\0';
358 		while ((token = strsep(&line, " ")) != NULL) {
359 			if (strcmp(token, ifname) == 0)
360 				return (1);
361 		}
362 
363 		/* sleep 100ms */
364 		usleep(1000 * 100);
365 	}
366 
367 	return (0);
368 }
369 
370 void
371 vnet_switch(char *vnet_name, char **ifnames, int count)
372 {
373 	char buf[512], cmd[512], *line;
374 	FILE *fp;
375 	int jid, len, ret;
376 
377 	RLOG("switching to vnet %s with interface(s) %s", vnet_name, ifnames[0]);
378 	len = snprintf(cmd, sizeof(cmd),
379 	    "/usr/sbin/jail -i -c name=%s persist vnet", vnet_name);
380 	for (int i = 0; i < count && len < sizeof(cmd); i++) {
381 		len += snprintf(&cmd[len], sizeof(cmd) - len,
382 		    " vnet.interface=%s", ifnames[i]);
383 	}
384 	RLOG("jail cmd: \"%s\"\n", cmd);
385 
386 	fp = popen(cmd, "r");
387 	if (fp == NULL)
388 		atf_tc_fail("jail creation failed");
389 	line = fgets(buf, sizeof(buf), fp);
390 	if (line == NULL)
391 		atf_tc_fail("empty output from jail(8)");
392 	jid = strtol(line, NULL, 10);
393 	if (jid <= 0) {
394 		atf_tc_fail("invalid jail output: %s", line);
395 	}
396 
397 	RLOG("created jail jid=%d", jid);
398 	file_append_line(JAILS_FNAME, vnet_name);
399 
400 	/* Wait while interface appearsh inside vnet */
401 	for (int i = 0; i < count; i++) {
402 		if (vnet_wait_interface(vnet_name, ifnames[i]))
403 			continue;
404 		atf_tc_fail("unable to move interface %s to jail %s",
405 		    ifnames[i], vnet_name);
406 	}
407 
408 	if (jail_attach(jid) == -1) {
409 		RLOG_ERRNO("jail %s attach failed: ret=%d", vnet_name, errno);
410 		atf_tc_fail("jail attach failed");
411 	}
412 
413 	RLOG("attached to the jail");
414 }
415 
416 void
417 vnet_switch_one(char *vnet_name, char *ifname)
418 {
419 	char *ifnames[1];
420 
421 	ifnames[0] = ifname;
422 	vnet_switch(vnet_name, ifnames, 1);
423 }
424 
425 
426 #define	SA_F_IGNORE_IFNAME	0x01
427 #define	SA_F_IGNORE_IFTYPE	0x02
428 #define	SA_F_IGNORE_MEMCMP	0x04
429 int
430 sa_equal_msg_flags(const struct sockaddr *a, const struct sockaddr *b, char *msg, size_t sz, int flags)
431 {
432 	char a_s[64], b_s[64];
433 	const struct sockaddr_in *a4, *b4;
434 	const struct sockaddr_in6 *a6, *b6;
435 	const struct sockaddr_dl *al, *bl;
436 
437 	if (a == NULL) {
438 		snprintf(msg, sz, "first sa is NULL");
439 		return 0;
440 	}
441 	if (b == NULL) {
442 		snprintf(msg, sz, "second sa is NULL");
443 		return 0;
444 	}
445 
446 	if (a->sa_family != b->sa_family) {
447 		snprintf(msg, sz, "family: %d vs %d", a->sa_family, b->sa_family);
448 		return 0;
449 	}
450 	if (a->sa_len != b->sa_len) {
451 		snprintf(msg, sz, "len: %d vs %d", a->sa_len, b->sa_len);
452 		return 0;
453 	}
454 
455 	switch (a->sa_family) {
456 	case AF_INET:
457 		a4 = (const struct sockaddr_in *)a;
458 		b4 = (const struct sockaddr_in *)b;
459 		if (a4->sin_addr.s_addr != b4->sin_addr.s_addr) {
460 			inet_ntop(AF_INET, &a4->sin_addr, a_s, sizeof(a_s));
461 			inet_ntop(AF_INET, &b4->sin_addr, b_s, sizeof(b_s));
462 			snprintf(msg, sz, "addr diff: %s vs %s", a_s, b_s);
463 			return 0;
464 		}
465 		if (a4->sin_port != b4->sin_port) {
466 			snprintf(msg, sz, "port diff: %d vs %d",
467 					ntohs(a4->sin_port), ntohs(b4->sin_port));
468 			//return 0;
469 		}
470 		const uint32_t *a32, *b32;
471 		a32 = (const uint32_t *)a4->sin_zero;
472 		b32 = (const uint32_t *)b4->sin_zero;
473 		if ((*a32 != *b32) || (*(a32 + 1) != *(b32 + 1))) {
474 			snprintf(msg, sz, "zero diff: 0x%08X%08X vs 0x%08X%08X",
475 					ntohl(*a32), ntohl(*(a32 + 1)),
476 					ntohl(*b32), ntohl(*(b32 + 1)));
477 			return 0;
478 		}
479 		return 1;
480 	case AF_INET6:
481 		a6 = (const struct sockaddr_in6 *)a;
482 		b6 = (const struct sockaddr_in6 *)b;
483 		if (!IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr)) {
484 			inet_ntop(AF_INET6, &a6->sin6_addr, a_s, sizeof(a_s));
485 			inet_ntop(AF_INET6, &b6->sin6_addr, a_s, sizeof(a_s));
486 			snprintf(msg, sz, "addr diff: %s vs %s", a_s, b_s);
487 			return 0;
488 		}
489 		if (a6->sin6_scope_id != b6->sin6_scope_id) {
490 			snprintf(msg, sz, "scope diff: %u vs %u", a6->sin6_scope_id, b6->sin6_scope_id);
491 			return 0;
492 		}
493 		break;
494 	case AF_LINK:
495 		al = (const struct sockaddr_dl *)a;
496 		bl = (const struct sockaddr_dl *)b;
497 
498 		if (al->sdl_index != bl->sdl_index) {
499 			snprintf(msg, sz, "sdl_index diff: %u vs %u", al->sdl_index, bl->sdl_index);
500 			return 0;
501 		}
502 
503 		if ((al->sdl_alen != bl->sdl_alen) || (memcmp(LLADDR(al), LLADDR(bl), al->sdl_alen) != 0)) {
504 			char abuf[64], bbuf[64];
505 			sa_print_hd(abuf, sizeof(abuf), LLADDR(al), al->sdl_alen);
506 			sa_print_hd(bbuf, sizeof(bbuf), LLADDR(bl), bl->sdl_alen);
507 			snprintf(msg, sz, "sdl_alen diff: {%s} (%d) vs {%s} (%d)",
508 			    abuf, al->sdl_alen, bbuf, bl->sdl_alen);
509 			return 0;
510 		}
511 
512 		if (((flags & SA_F_IGNORE_IFTYPE) == 0) && (al->sdl_type != bl->sdl_type)) {
513 			snprintf(msg, sz, "sdl_type diff: %u vs %u", al->sdl_type, bl->sdl_type);
514 			return 0;
515 		}
516 
517 		if (((flags & SA_F_IGNORE_IFNAME) == 0) && ((al->sdl_nlen != bl->sdl_nlen) ||
518 			    (memcmp(al->sdl_data, bl->sdl_data, al->sdl_nlen) != 0))) {
519 			char abuf[64], bbuf[64];
520 			memcpy(abuf, al->sdl_data, al->sdl_nlen);
521 			abuf[al->sdl_nlen] = '\0';
522 			memcpy(bbuf, bl->sdl_data, bl->sdl_nlen);
523 			abuf[bl->sdl_nlen] = '\0';
524 			snprintf(msg, sz, "sdl_nlen diff: {%s} (%d) vs {%s} (%d)",
525 			    abuf, al->sdl_nlen, bbuf, bl->sdl_nlen);
526 			return 0;
527 		}
528 
529 		if (flags & SA_F_IGNORE_MEMCMP)
530 			return 1;
531 		break;
532 	}
533 
534 	if (memcmp(a, b, a->sa_len)) {
535 		int i;
536 		for (i = 0; i < a->sa_len; i++)
537 			if (((const char *)a)[i] != ((const char *)b)[i])
538 				break;
539 
540 		sa_print(a, 1);
541 		sa_print(b, 1);
542 
543 		snprintf(msg, sz, "overall memcmp() reports diff for af %d offset %d",
544 				a->sa_family, i);
545 		return 0;
546 	}
547 	return 1;
548 }
549 
550 int
551 sa_equal_msg(const struct sockaddr *a, const struct sockaddr *b, char *msg, size_t sz)
552 {
553 
554 	return sa_equal_msg_flags(a, b, msg, sz, 0);
555 }
556 
557 void
558 sa_fill_mask4(struct sockaddr_in *sin, int plen)
559 {
560 
561 	memset(sin, 0, sizeof(struct sockaddr_in));
562 	sin->sin_family = AF_INET;
563 	sin->sin_len = sizeof(struct sockaddr_in);
564 	sin->sin_addr.s_addr = htonl(plen ? ~((1 << (32 - plen)) - 1) : 0);
565 }
566 
567 void
568 sa_fill_mask6(struct sockaddr_in6 *sin6, uint8_t mask)
569 {
570 	uint32_t *cp;
571 
572 	memset(sin6, 0, sizeof(struct sockaddr_in6));
573 	sin6->sin6_family = AF_INET6;
574 	sin6->sin6_len = sizeof(struct sockaddr_in6);
575 
576 	for (cp = (uint32_t *)&sin6->sin6_addr; mask >= 32; mask -= 32)
577 		*cp++ = 0xFFFFFFFF;
578 	if (mask > 0)
579 		*cp = htonl(mask ? ~((1 << (32 - mask)) - 1) : 0);
580 }
581 
582 /* 52:54:00:14:e3:10 */
583 #define	ETHER_MAC_MAX_LENGTH	17
584 
585 int
586 sa_convert_str_to_sa(const char *_addr, struct sockaddr *sa)
587 {
588 	int error;
589 
590 	int af = AF_UNSPEC;
591 
592 	char *addr = strdup(_addr);
593 	int retcode = 0;
594 
595 	/* classify AF by str */
596 	if (strchr(addr, ':')) {
597 		/* inet6 or ether */
598 		char *k;
599 		int delim_cnt = 0;
600 		for (k = addr; *k; k++)
601 			if (*k == ':')
602 				delim_cnt++;
603 		af = AF_INET6;
604 
605 		if (delim_cnt == 5) {
606 			k = strchr(addr, '%');
607 			if (k != NULL && (k - addr) <= ETHER_MAC_MAX_LENGTH)
608 				af = AF_LINK;
609 		}
610 	} else if (strchr(addr, '.'))
611 		af = AF_INET;
612 
613 	/* */
614 	char *delimiter;
615 	int ifindex = 0;
616 	char *ifname = NULL;
617 	if ((delimiter = strchr(addr, '%')) != NULL) {
618 		*delimiter = '\0';
619 		ifname = delimiter + 1;
620 		ifindex = if_nametoindex(ifname);
621 		if (ifindex == 0)
622 			RLOG("unable to find ifindex for '%s'", ifname);
623 		else
624 			RLOG("if %s mapped to %d", ifname, ifindex);
625 	}
626 
627 	if (af == AF_INET6) {
628 		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
629 		memset(sin6, 0, sizeof(struct sockaddr_in6));
630 		sin6->sin6_family = AF_INET6;
631 		sin6->sin6_len = sizeof(struct sockaddr_in6);
632 		sin6->sin6_scope_id = ifindex;
633 		error = inet_pton(AF_INET6, addr, &sin6->sin6_addr);
634 		if (error != 1)
635 			RLOG_ERRNO("inet_ntop() failed: ret=%d", error);
636 		else
637 			retcode = 1;
638 	} else if (af == AF_INET) {
639 		struct sockaddr_in *sin = (struct sockaddr_in *)sa;
640 		memset(sin, 0, sizeof(struct sockaddr_in));
641 		sin->sin_family = AF_INET;
642 		sin->sin_len = sizeof(struct sockaddr_in);
643 		error = inet_pton(AF_INET, addr, &sin->sin_addr);
644 		if (error != 1)
645 			RLOG("inet_ntop() failed: ret=%d", error);
646 		else
647 			retcode = 1;
648 	} else if (af == AF_LINK) {
649 		struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
650 		memset(sdl, 0, sizeof(struct sockaddr_dl));
651 		sdl->sdl_family = AF_LINK;
652 		sdl->sdl_len = sizeof(struct sockaddr_dl);
653 		sdl->sdl_index = ifindex;
654 		sdl->sdl_alen = 6;
655 		struct ether_addr *ea = (struct ether_addr *)LLADDR(sdl);
656 		if (ether_aton_r(addr, ea) == NULL)
657 			RLOG("ether_aton() failed");
658 		else
659 			retcode = 1;
660 	}
661 
662 	return (retcode);
663 }
664 
665 
666 int
667 rtsock_setup_socket()
668 {
669 	int fd;
670 	int af = AF_UNSPEC; /* 0 to capture messages from all AFs */
671 	fd = socket(PF_ROUTE, SOCK_RAW, af);
672 
673 	ATF_REQUIRE_MSG(fd != -1, "rtsock open failed: %s", strerror(errno));
674 
675 	/* Listen for our messages */
676 	int on = 1;
677 	if (setsockopt(fd, SOL_SOCKET,SO_USELOOPBACK, &on, sizeof(on)) < 0)
678 		RLOG_ERRNO("setsockopt failed");
679 
680 	return (fd);
681 }
682 
683 ssize_t
684 rtsock_send_rtm(int fd, struct rt_msghdr *rtm)
685 {
686 	int my_errno;
687 	ssize_t len;
688 
689 	rtsock_update_rtm_len(rtm);
690 
691 	len = write(fd, rtm, rtm->rtm_msglen);
692 	my_errno = errno;
693 	RTSOCK_ATF_REQUIRE_MSG(rtm, len == rtm->rtm_msglen,
694 	    "rtsock write failed: want %d got %zd (%s)",
695 	    rtm->rtm_msglen, len, strerror(my_errno));
696 
697 	return (len);
698 }
699 
700 struct rt_msghdr *
701 rtsock_read_rtm(int fd, char *buffer, size_t buflen)
702 {
703 	ssize_t len;
704 	struct pollfd pfd;
705 	int poll_delay = 5 * 1000; /* 5 seconds */
706 
707 	/* Check for the data available to read first */
708 	memset(&pfd, 0, sizeof(pfd));
709 	pfd.fd = fd;
710 	pfd.events = POLLIN;
711 
712 	if (poll(&pfd, 1, poll_delay) == 0)
713 		ATF_REQUIRE_MSG(1 == 0, "rtsock read timed out (%d seconds passed)",
714 		    poll_delay / 1000);
715 
716 	len = read(fd, buffer, buflen);
717 	int my_errno = errno;
718 	ATF_REQUIRE_MSG(len > 0, "rtsock read failed: %s", strerror(my_errno));
719 
720 	rtsock_validate_message(buffer, len);
721 	return ((struct rt_msghdr *)buffer);
722 }
723 
724 struct rt_msghdr *
725 rtsock_read_rtm_reply(int fd, char *buffer, size_t buflen, int seq)
726 {
727 	struct rt_msghdr *rtm;
728 	int found = 0;
729 
730 	while (true) {
731 		rtm = rtsock_read_rtm(fd, buffer, buflen);
732 		if (rtm->rtm_pid == getpid() && rtm->rtm_seq == seq)
733 			found = 1;
734 		if (found)
735 			RLOG("--- MATCHED RTSOCK MESSAGE ---");
736 		else
737 			RLOG("--- SKIPPED RTSOCK MESSAGE ---");
738 		rtsock_print_rtm(rtm);
739 		if (found)
740 			return (rtm);
741 	}
742 
743 	/* NOTREACHED */
744 }
745 
746 void
747 rtsock_prepare_route_message_base(struct rt_msghdr *rtm, int cmd)
748 {
749 
750 	memset(rtm, 0, sizeof(struct rt_msghdr));
751 	rtm->rtm_type = cmd;
752 	rtm->rtm_version = RTM_VERSION;
753 	rtm->rtm_seq = _rtm_seq++;
754 }
755 
756 void
757 rtsock_prepare_route_message(struct rt_msghdr *rtm, int cmd, struct sockaddr *dst,
758   struct sockaddr *mask, struct sockaddr *gw)
759 {
760 
761 	rtsock_prepare_route_message_base(rtm, cmd);
762 	if (dst != NULL)
763 		rtsock_add_rtm_sa(rtm, RTA_DST, dst);
764 
765 	if (gw != NULL) {
766 		rtsock_add_rtm_sa(rtm, RTA_GATEWAY, gw);
767 		rtm->rtm_flags |= RTF_GATEWAY;
768 	}
769 
770 	if (mask != NULL)
771 		rtsock_add_rtm_sa(rtm, RTA_NETMASK, mask);
772 }
773 
774 void
775 rtsock_add_rtm_sa(struct rt_msghdr *rtm, int addr_type, struct sockaddr *sa)
776 {
777 	char *ptr = (char *)(rtm + 1);
778 	for (int i = 0; i < RTAX_MAX; i++) {
779 		if (rtm->rtm_addrs & (1 << i)) {
780 			/* add */
781 			ptr += ALIGN(((struct sockaddr *)ptr)->sa_len);
782 		}
783 	}
784 
785 	rtm->rtm_addrs |= addr_type;
786 	memcpy(ptr, sa, sa->sa_len);
787 }
788 
789 struct sockaddr *
790 rtsock_find_rtm_sa(struct rt_msghdr *rtm, int addr_type)
791 {
792 	char *ptr = (char *)(rtm + 1);
793 	for (int i = 0; i < RTAX_MAX; i++) {
794 		if (rtm->rtm_addrs & (1 << i)) {
795 			if (addr_type == (1 << i))
796 				return ((struct sockaddr *)ptr);
797 			/* add */
798 			ptr += ALIGN(((struct sockaddr *)ptr)->sa_len);
799 		}
800 	}
801 
802 	return (NULL);
803 }
804 
805 size_t
806 rtsock_calc_rtm_len(struct rt_msghdr *rtm)
807 {
808 	size_t len = sizeof(struct rt_msghdr);
809 
810 	char *ptr = (char *)(rtm + 1);
811 	for (int i = 0; i < RTAX_MAX; i++) {
812 		if (rtm->rtm_addrs & (1 << i)) {
813 			/* add */
814 			int sa_len = ALIGN(((struct sockaddr *)ptr)->sa_len);
815 			len += sa_len;
816 			ptr += sa_len;
817 		}
818 	}
819 
820 	return len;
821 }
822 
823 void
824 rtsock_update_rtm_len(struct rt_msghdr *rtm)
825 {
826 
827 	rtm->rtm_msglen = rtsock_calc_rtm_len(rtm);
828 }
829 
830 static void
831 _validate_message_sockaddrs(char *buffer, int rtm_len, size_t offset, int rtm_addrs)
832 {
833 	struct sockaddr *sa;
834 	size_t parsed_len = offset;
835 
836 	/* Offset denotes initial header size */
837 	sa = (struct sockaddr *)(buffer + offset);
838 
839 	for (int i = 0; i < RTAX_MAX; i++) {
840 		if ((rtm_addrs & (1 << i)) == 0)
841 			continue;
842 		parsed_len += SA_SIZE(sa);
843 		RTSOCK_ATF_REQUIRE_MSG((struct rt_msghdr *)buffer, parsed_len <= rtm_len,
844 		    "SA %d: len %d exceeds msg size %d", i, (int)sa->sa_len, rtm_len);
845 		if (sa->sa_family == AF_LINK) {
846 			struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
847 			int data_len = sdl->sdl_nlen + sdl->sdl_alen;
848 			data_len += offsetof(struct sockaddr_dl, sdl_data);
849 
850 			RTSOCK_ATF_REQUIRE_MSG((struct rt_msghdr *)buffer,
851 			    data_len <= rtm_len,
852 			    "AF_LINK data size exceeds total len: %u vs %u, nlen=%d alen=%d",
853 			    data_len, rtm_len, sdl->sdl_nlen, sdl->sdl_alen);
854 		}
855 		sa = (struct sockaddr *)((char *)sa + SA_SIZE(sa));
856 	}
857 
858 	RTSOCK_ATF_REQUIRE_MSG((struct rt_msghdr *)buffer, parsed_len == rtm_len,
859 	    "message len != parsed len: expected %d parsed %d",
860 	    rtm_len, (int)parsed_len);
861 }
862 
863 /*
864  * Raises error if base syntax checks fails.
865  */
866 void
867 rtsock_validate_message(char *buffer, ssize_t len)
868 {
869 	struct rt_msghdr *rtm;
870 
871 	ATF_REQUIRE_MSG(len > 0, "read() return %zd, error: %s", len, strerror(errno));
872 
873 	rtm = (struct rt_msghdr *)buffer;
874 	ATF_REQUIRE_MSG(rtm->rtm_version == RTM_VERSION, "unknown RTM_VERSION: expected %d got %d",
875 			RTM_VERSION, rtm->rtm_version);
876 	ATF_REQUIRE_MSG(rtm->rtm_msglen <= len, "wrong message length: expected %d got %d",
877 			(int)len, (int)rtm->rtm_msglen);
878 
879 	switch (rtm->rtm_type) {
880 	case RTM_GET:
881 	case RTM_ADD:
882 	case RTM_DELETE:
883 	case RTM_CHANGE:
884 		_validate_message_sockaddrs(buffer, rtm->rtm_msglen,
885 		    sizeof(struct rt_msghdr), rtm->rtm_addrs);
886 		break;
887 	case RTM_DELADDR:
888 	case RTM_NEWADDR:
889 		_validate_message_sockaddrs(buffer, rtm->rtm_msglen,
890 		    sizeof(struct ifa_msghdr), ((struct ifa_msghdr *)buffer)->ifam_addrs);
891 		break;
892 	}
893 }
894 
895 void
896 rtsock_validate_pid_ours(struct rt_msghdr *rtm)
897 {
898 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_pid == getpid(), "expected pid %d, got %d",
899 	    getpid(), rtm->rtm_pid);
900 }
901 
902 void
903 rtsock_validate_pid_user(struct rt_msghdr *rtm)
904 {
905 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_pid > 0, "expected non-zero pid, got %d",
906 	    rtm->rtm_pid);
907 }
908 
909 void
910 rtsock_validate_pid_kernel(struct rt_msghdr *rtm)
911 {
912 	RTSOCK_ATF_REQUIRE_MSG(rtm, rtm->rtm_pid == 0, "expected zero pid, got %d",
913 	    rtm->rtm_pid);
914 }
915 
916 #endif
917