xref: /netbsd-src/crypto/dist/ipsec-tools/src/racoon/grabmyaddr.c (revision 8f3b9c1ccd246e6788305c2776179106ccc53fb2)
1 /*	$NetBSD: grabmyaddr.c,v 1.40 2023/02/27 13:39:09 kardel Exp $	*/
2 /*
3  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
4  * Copyright (C) 2008 Timo Teras <timo.teras@iki.fi>.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the project nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include "config.h"
33 
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <string.h>
38 #include <sys/types.h>
39 #include <sys/queue.h>
40 #include <sys/socket.h>
41 
42 #ifdef __linux__
43 #include <linux/netlink.h>
44 #include <linux/rtnetlink.h>
45 #define USE_NETLINK
46 #else
47 #include <net/route.h>
48 #include <net/if.h>
49 #include <net/if_dl.h>
50 #include <sys/sysctl.h>
51 #define USE_ROUTE
52 #endif
53 
54 #include "var.h"
55 #include "misc.h"
56 #include "vmbuf.h"
57 #include "plog.h"
58 #include "sockmisc.h"
59 #include "session.h"
60 #include "debug.h"
61 
62 #include "localconf.h"
63 #include "handler.h"
64 #include "grabmyaddr.h"
65 #include "sockmisc.h"
66 #include "isakmp_var.h"
67 #include "gcmalloc.h"
68 #include "nattraversal.h"
69 
70 static int kernel_receive __P((void *ctx, int fd));
71 static int kernel_open_socket __P((void));
72 static void kernel_sync __P((void));
73 
74 struct myaddr {
75 	LIST_ENTRY(myaddr) chain;
76 	struct sockaddr_storage addr;
77 	int fd;
78 	int udp_encap;
79 };
80 
LIST_HEAD(_myaddr_list_,myaddr)81 static LIST_HEAD(_myaddr_list_, myaddr) configured, opened;
82 
83 static void
84 myaddr_delete(struct myaddr *my)
85 {
86 	if (my->fd != -1)
87 		isakmp_close(my->fd);
88 	LIST_REMOVE(my, chain);
89 	racoon_free(my);
90 }
91 
92 static int
myaddr_configured(struct sockaddr * addr)93 myaddr_configured(struct sockaddr *addr)
94 {
95 	struct myaddr *cfg;
96 
97 	if (LIST_EMPTY(&configured))
98 		return TRUE;
99 
100 	LIST_FOREACH(cfg, &configured, chain) {
101 		if (cmpsaddr(addr, (struct sockaddr *) &cfg->addr) <= CMPSADDR_WILDPORT_MATCH)
102 			return TRUE;
103 	}
104 
105 	return FALSE;
106 }
107 
108 static int
myaddr_open(struct sockaddr * addr,int udp_encap)109 myaddr_open(struct sockaddr *addr, int udp_encap)
110 {
111 	struct myaddr *my;
112 
113 	/* Already open? */
114 	LIST_FOREACH(my, &opened, chain) {
115 		if (cmpsaddr(addr, (struct sockaddr *) &my->addr) <= CMPSADDR_WILDPORT_MATCH)
116 			return TRUE;
117 	}
118 
119 	my = racoon_calloc(1, sizeof(struct myaddr));
120 	if (my == NULL)
121 		return FALSE;
122 
123 	memcpy(&my->addr, addr, sysdep_sa_len(addr));
124 	my->fd = isakmp_open(addr, udp_encap);
125 	if (my->fd < 0) {
126 		racoon_free(my);
127 		return FALSE;
128 	}
129 	my->udp_encap = udp_encap;
130 	LIST_INSERT_HEAD(&opened, my, chain);
131 	return TRUE;
132 }
133 
134 static int
myaddr_open_all_configured(struct sockaddr * addr)135 myaddr_open_all_configured(struct sockaddr *addr)
136 {
137 	/* create all configured, not already opened addresses */
138 	struct myaddr *cfg;
139 
140 	if (addr != NULL) {
141 		switch (addr->sa_family) {
142 		case AF_INET:
143 #ifdef INET6
144 		case AF_INET6:
145 #endif
146 			break;
147 		default:
148 			return FALSE;
149 		}
150 	}
151 
152 	LIST_FOREACH(cfg, &configured, chain) {
153 		if (addr != NULL &&
154 		    cmpsaddr(addr, (struct sockaddr *) &cfg->addr) > CMPSADDR_WILDPORT_MATCH)
155 			continue;
156 		if (!myaddr_open((struct sockaddr *) &cfg->addr, cfg->udp_encap))
157 			return FALSE;
158 	}
159 	if (LIST_EMPTY(&configured)) {
160 #ifdef ENABLE_HYBRID
161 		/* Exclude any address we got through ISAKMP mode config */
162 		if (exclude_cfg_addr(addr) == 0)
163 			return FALSE;
164 #endif
165 		set_port(addr, lcconf->port_isakmp);
166 		myaddr_open(addr, FALSE);
167 #ifdef ENABLE_NATT
168 		set_port(addr, lcconf->port_isakmp_natt);
169 		myaddr_open(addr, TRUE);
170 #endif
171 	}
172 	return TRUE;
173 }
174 
175 static void
myaddr_close_all_open(struct sockaddr * addr)176 myaddr_close_all_open(struct sockaddr *addr)
177 {
178 	/* delete all matching open sockets */
179 	struct myaddr *my, *next;
180 
181 	for (my = LIST_FIRST(&opened); my; my = next) {
182 		next = LIST_NEXT(my, chain);
183 
184 		if (cmpsaddr((struct sockaddr *) addr,
185 			     (struct sockaddr *) &my->addr)
186 		    <= CMPSADDR_WOP_MATCH)
187 			myaddr_delete(my);
188 	}
189 }
190 
191 static void
myaddr_flush_list(struct _myaddr_list_ * list)192 myaddr_flush_list(struct _myaddr_list_ *list)
193 {
194 	struct myaddr *my, *next;
195 
196 	for (my = LIST_FIRST(list); my; my = next) {
197 		next = LIST_NEXT(my, chain);
198 		myaddr_delete(my);
199 	}
200 }
201 
202 void
myaddr_flush()203 myaddr_flush()
204 {
205 	myaddr_flush_list(&configured);
206 }
207 
208 int
myaddr_listen(addr,udp_encap)209 myaddr_listen(addr, udp_encap)
210 	struct sockaddr *addr;
211 	int udp_encap;
212 {
213 	struct myaddr *my;
214 
215 	if (sysdep_sa_len(addr) > sizeof(my->addr)) {
216 		plog(LLV_ERROR, LOCATION, NULL,
217 		     "sockaddr size larger than sockaddr_storage\n");
218 		return -1;
219 	}
220 
221 	my = racoon_calloc(1, sizeof(struct myaddr));
222 	if (my == NULL)
223 		return -1;
224 
225 	memcpy(&my->addr, addr, sysdep_sa_len(addr));
226 	my->udp_encap = udp_encap;
227 	my->fd = -1;
228 	LIST_INSERT_HEAD(&configured, my, chain);
229 
230 	return 0;
231 }
232 
233 void
myaddr_sync()234 myaddr_sync()
235 {
236 	struct myaddr *my, *next;
237 
238 	if (!lcconf->strict_address) {
239 		kernel_sync();
240 
241 		/* delete all existing listeners which are not configured */
242 		for (my = LIST_FIRST(&opened); my; my = next) {
243 			next = LIST_NEXT(my, chain);
244 
245 			if (!myaddr_configured((struct sockaddr *) &my->addr))
246 				myaddr_delete(my);
247 		}
248 	}
249 }
250 
251 int
myaddr_getfd(addr)252 myaddr_getfd(addr)
253         struct sockaddr *addr;
254 {
255 	struct myaddr *my;
256 
257 	LIST_FOREACH(my, &opened, chain) {
258 		if (cmpsaddr((struct sockaddr *) &my->addr, addr) <= CMPSADDR_WILDPORT_MATCH)
259 			return my->fd;
260 	}
261 
262 	return -1;
263 }
264 
265 int
myaddr_getsport(addr)266 myaddr_getsport(addr)
267 	struct sockaddr *addr;
268 {
269 	struct myaddr *my;
270 	int port = 0, wport;
271 
272 	LIST_FOREACH(my, &opened, chain) {
273 		switch (cmpsaddr((struct sockaddr *) &my->addr, addr)) {
274 		case CMPSADDR_MATCH:
275 			return extract_port((struct sockaddr *) &my->addr);
276 		case CMPSADDR_WILDPORT_MATCH:
277 			wport = extract_port((struct sockaddr *) &my->addr);
278 			if (port == 0 || wport < port)
279 				port = wport;
280 			break;
281 		}
282 	}
283 
284 	if (port == 0)
285 		port = PORT_ISAKMP;
286 
287 	return port;
288 }
289 
290 void
myaddr_init_lists()291 myaddr_init_lists()
292 {
293 	LIST_INIT(&configured);
294 	LIST_INIT(&opened);
295 }
296 
297 int
myaddr_init()298 myaddr_init()
299 {
300         if (!lcconf->strict_address) {
301 		lcconf->rtsock = kernel_open_socket();
302 		if (lcconf->rtsock < 0)
303 			return -1;
304 		monitor_fd(lcconf->rtsock, kernel_receive, NULL, 0);
305 	} else {
306 		lcconf->rtsock = -1;
307 		if (!myaddr_open_all_configured(NULL))
308 			return -1;
309 	}
310 	return 0;
311 }
312 
313 void
myaddr_close()314 myaddr_close()
315 {
316 	myaddr_flush_list(&configured);
317 	myaddr_flush_list(&opened);
318 	if (lcconf->rtsock != -1) {
319 		unmonitor_fd(lcconf->rtsock);
320 		close(lcconf->rtsock);
321 	}
322 }
323 
324 #if defined(USE_NETLINK)
325 
326 static int netlink_fd = -1;
327 
328 #define NLMSG_TAIL(nmsg) \
329 	((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
330 
331 static void
parse_rtattr(struct rtattr * tb[],int max,struct rtattr * rta,int len)332 parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
333 {
334 	memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
335 	while (RTA_OK(rta, len)) {
336 		if (rta->rta_type <= max)
337 			tb[rta->rta_type] = rta;
338 		rta = RTA_NEXT(rta,len);
339 	}
340 }
341 
342 static int
netlink_add_rtattr_l(struct nlmsghdr * n,int maxlen,int type,const void * data,int alen)343 netlink_add_rtattr_l(struct nlmsghdr *n, int maxlen, int type,
344 		     const void *data, int alen)
345 {
346 	int len = RTA_LENGTH(alen);
347 	struct rtattr *rta;
348 
349 	if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen)
350 		return FALSE;
351 
352 	rta = NLMSG_TAIL(n);
353 	rta->rta_type = type;
354 	rta->rta_len = len;
355 	memcpy(RTA_DATA(rta), data, alen);
356 	n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
357 	return TRUE;
358 }
359 
360 static int
netlink_enumerate(fd,family,type)361 netlink_enumerate(fd, family, type)
362 	int fd;
363 	int family;
364 	int type;
365 {
366 	struct {
367 		struct nlmsghdr nlh;
368 		struct rtgenmsg g;
369 	} req;
370 	struct sockaddr_nl addr;
371 	static __u32 seq = 0;
372 
373 	memset(&addr, 0, sizeof(addr));
374 	addr.nl_family = AF_NETLINK;
375 
376 	memset(&req, 0, sizeof(req));
377 	req.nlh.nlmsg_len = sizeof(req);
378 	req.nlh.nlmsg_type = type;
379 	req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
380 	req.nlh.nlmsg_pid = 0;
381 	req.nlh.nlmsg_seq = ++seq;
382 	req.g.rtgen_family = family;
383 
384 	return sendto(fd, (void *) &req, sizeof(req), 0,
385 		      (struct sockaddr *) &addr, sizeof(addr)) >= 0;
386 }
387 
388 static void
netlink_add_del_address(int add,struct sockaddr * saddr)389 netlink_add_del_address(int add, struct sockaddr *saddr)
390 {
391 	plog(LLV_DEBUG, LOCATION, NULL,
392 	     "Netlink: address %s %s\n",
393 	     saddrwop2str((struct sockaddr *) saddr),
394 	     add ? "added" : "deleted");
395 
396 	if (add)
397 		myaddr_open_all_configured(saddr);
398 	else
399 		myaddr_close_all_open(saddr);
400 }
401 
402 #ifdef INET6
403 static int
netlink_process_addr(struct nlmsghdr * h)404 netlink_process_addr(struct nlmsghdr *h)
405 {
406 	struct sockaddr_storage addr;
407 	struct ifaddrmsg *ifa;
408 	struct rtattr *rta[IFA_MAX+1];
409 	struct sockaddr_in6 *sin6;
410 
411 	ifa = NLMSG_DATA(h);
412 	parse_rtattr(rta, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(h));
413 
414 	if (ifa->ifa_family != AF_INET6)
415 		return 0;
416 	if (ifa->ifa_flags & IFA_F_TENTATIVE)
417 		return 0;
418 	if (rta[IFA_LOCAL] == NULL)
419 		rta[IFA_LOCAL] = rta[IFA_ADDRESS];
420 	if (rta[IFA_LOCAL] == NULL)
421 		return 0;
422 
423 	memset(&addr, 0, sizeof(addr));
424 	addr.ss_family = ifa->ifa_family;
425 	sin6 = (struct sockaddr_in6 *) &addr;
426 	memcpy(&sin6->sin6_addr, RTA_DATA(rta[IFA_LOCAL]),
427 		sizeof(sin6->sin6_addr));
428 	if (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
429 		return 0;
430 	sin6->sin6_scope_id = ifa->ifa_index;
431 
432 	netlink_add_del_address(h->nlmsg_type == RTM_NEWADDR,
433 				(struct sockaddr *) &addr);
434 
435 	return 0;
436 }
437 #endif
438 
439 static int
netlink_route_is_local(int family,const unsigned char * addr,size_t addr_len)440 netlink_route_is_local(int family, const unsigned char *addr, size_t addr_len)
441 {
442 	struct {
443 		struct nlmsghdr n;
444 		struct rtmsg    r;
445 		char            buf[1024];
446 	} req;
447 	struct rtmsg *r = NLMSG_DATA(&req.n);
448 	struct rtattr *rta[RTA_MAX+1];
449 	struct sockaddr_nl nladdr;
450 	ssize_t rlen;
451 
452 	memset(&req, 0, sizeof(req));
453 	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
454 	req.n.nlmsg_flags = NLM_F_REQUEST;
455 	req.n.nlmsg_type = RTM_GETROUTE;
456 	req.r.rtm_family = family;
457 	netlink_add_rtattr_l(&req.n, sizeof(req), RTA_DST,
458 			     addr, addr_len);
459 	req.r.rtm_dst_len = addr_len * 8;
460 
461 	memset(&nladdr, 0, sizeof(nladdr));
462 	nladdr.nl_family = AF_NETLINK;
463 
464 	if (sendto(netlink_fd, &req, sizeof(req), 0,
465 		   (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0)
466 		return 0;
467 	rlen = recv(netlink_fd, &req, sizeof(req), 0);
468 	if (rlen < 0)
469 		return 0;
470 
471 	return  req.n.nlmsg_type == RTM_NEWROUTE &&
472 		req.r.rtm_type == RTN_LOCAL;
473 }
474 
475 static int
netlink_process_route(struct nlmsghdr * h)476 netlink_process_route(struct nlmsghdr *h)
477 {
478 	struct sockaddr_storage addr;
479 	struct rtmsg *rtm;
480 	struct rtattr *rta[RTA_MAX+1];
481 	struct sockaddr_in *sin;
482 #ifdef INET6
483 	struct sockaddr_in6 *sin6;
484 #endif
485 
486 	rtm = NLMSG_DATA(h);
487 
488 	/* local IP addresses get local route in the local table */
489 	if (rtm->rtm_type != RTN_LOCAL ||
490 	    rtm->rtm_table != RT_TABLE_LOCAL)
491 		return 0;
492 
493 	parse_rtattr(rta, IFA_MAX, RTM_RTA(rtm), IFA_PAYLOAD(h));
494 	if (rta[RTA_DST] == NULL)
495  		return 0;
496 
497 	/* setup the socket address */
498 	memset(&addr, 0, sizeof(addr));
499 	addr.ss_family = rtm->rtm_family;
500 	switch (rtm->rtm_family) {
501 	case AF_INET:
502 		sin = (struct sockaddr_in *) &addr;
503 		memcpy(&sin->sin_addr, RTA_DATA(rta[RTA_DST]),
504 			sizeof(sin->sin_addr));
505 		break;
506 #ifdef INET6
507 	case AF_INET6:
508 		sin6 = (struct sockaddr_in6 *) &addr;
509 		memcpy(&sin6->sin6_addr, RTA_DATA(rta[RTA_DST]),
510 			sizeof(sin6->sin6_addr));
511 		/* Link-local addresses are handled with RTM_NEWADDR
512 		 * notifications */
513 		if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
514 			return 0;
515 		break;
516 #endif
517 	default:
518 		return 0;
519 	}
520 
521 	/* If local route was deleted, check if there is still local
522 	 * route for the same IP on another interface */
523 	if (h->nlmsg_type == RTM_DELROUTE &&
524 	    netlink_route_is_local(rtm->rtm_family,
525 				   RTA_DATA(rta[RTA_DST]),
526 				   RTA_PAYLOAD(rta[RTA_DST]))) {
527 		plog(LLV_DEBUG, LOCATION, NULL,
528 			"Netlink: not deleting %s yet, it exists still\n",
529 			saddrwop2str((struct sockaddr *) &addr));
530 		return 0;
531 	}
532 
533 	netlink_add_del_address(h->nlmsg_type == RTM_NEWROUTE,
534 				(struct sockaddr *) &addr);
535 	return 0;
536 }
537 
538 static int
netlink_process(struct nlmsghdr * h)539 netlink_process(struct nlmsghdr *h)
540 {
541 	switch (h->nlmsg_type) {
542 #ifdef INET6
543 	case RTM_NEWADDR:
544 	case RTM_DELADDR:
545 		return netlink_process_addr(h);
546 #endif
547 	case RTM_NEWROUTE:
548 	case RTM_DELROUTE:
549 		return netlink_process_route(h);
550 	}
551 	return 0;
552 }
553 
554 static int
kernel_receive(ctx,fd)555 kernel_receive(ctx, fd)
556 	void *ctx;
557 	int fd;
558 {
559 	struct sockaddr_nl nladdr;
560 	struct iovec iov;
561 	struct msghdr msg = {
562 		.msg_name = &nladdr,
563 		.msg_namelen = sizeof(nladdr),
564 		.msg_iov = &iov,
565 		.msg_iovlen = 1,
566 	};
567 	struct nlmsghdr *h;
568 	int len, status;
569 	char buf[16*1024];
570 
571 	iov.iov_base = buf;
572 	while (1) {
573 		iov.iov_len = sizeof(buf);
574 		status = recvmsg(fd, &msg, MSG_DONTWAIT);
575 		if (status < 0) {
576 			if (errno == EINTR)
577 				continue;
578 			if (errno == EAGAIN)
579 				return FALSE;
580 			continue;
581 		}
582 		if (status == 0)
583 			return FALSE;
584 
585 		h = (struct nlmsghdr *) buf;
586 		while (NLMSG_OK(h, status)) {
587 			netlink_process(h);
588 			h = NLMSG_NEXT(h, status);
589 		}
590 	}
591 
592 	return TRUE;
593 }
594 
595 static int
netlink_open_socket()596 netlink_open_socket()
597 {
598 	int fd;
599 
600 	fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
601 	if (fd < 0) {
602 		plog(LLV_ERROR, LOCATION, NULL,
603 			"socket(PF_NETLINK) failed: %s",
604 			strerror(errno));
605 		return -1;
606 	}
607 	close_on_exec(fd);
608 	if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
609 		plog(LLV_WARNING, LOCATION, NULL,
610 		     "failed to put socket in non-blocking mode\n");
611 
612 	return fd;
613 }
614 
615 static int
kernel_open_socket()616 kernel_open_socket()
617 {
618 	struct sockaddr_nl nl;
619 	int fd;
620 
621 	if (netlink_fd < 0) {
622 		netlink_fd = netlink_open_socket();
623 		if (netlink_fd < 0)
624 			return -1;
625 	}
626 
627 	fd = netlink_open_socket();
628 	if (fd < 0)
629 		return fd;
630 
631 	/* We monitor IPv4 addresses using RTMGRP_IPV4_ROUTE group
632 	 * the get the RTN_LOCAL routes which are automatically added
633 	 * by kernel. This is because:
634 	 *  - Linux kernel has a bug that calling bind() immediately
635 	 *    after IPv4 RTM_NEWADDR event can fail
636 	 *  - if IP is configured in multiple interfaces, we get
637 	 *    RTM_DELADDR for each of them. RTN_LOCAL gets deleted only
638 	 *    after the last IP address is deconfigured.
639 	 * The latter reason is also why I chose to use route
640 	 * notifications for IPv6. However, we do need to use RTM_NEWADDR
641 	 * for the link-local IPv6 addresses to get the interface index
642 	 * that is needed in bind().
643 	 */
644 	memset(&nl, 0, sizeof(nl));
645 	nl.nl_family = AF_NETLINK;
646 	nl.nl_groups = RTMGRP_IPV4_ROUTE
647 #ifdef INET6
648 			| RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE
649 #endif
650 			;
651 	if (bind(fd, (struct sockaddr*) &nl, sizeof(nl)) < 0) {
652 		plog(LLV_ERROR, LOCATION, NULL,
653 		     "bind(PF_NETLINK) failed: %s\n",
654 		     strerror(errno));
655 		close(fd);
656 		return -1;
657 	}
658 	return fd;
659 }
660 
661 static void
kernel_sync()662 kernel_sync()
663 {
664 	int fd = lcconf->rtsock;
665 
666 	/* refresh addresses */
667 	if (!netlink_enumerate(fd, PF_UNSPEC, RTM_GETROUTE)) {
668 		plog(LLV_ERROR, LOCATION, NULL,
669 		     "unable to enumerate addresses: %s\n",
670 		     strerror(errno));
671 	}
672 	while (kernel_receive(NULL, fd) == TRUE);
673 
674 #ifdef INET6
675 	if (!netlink_enumerate(fd, PF_INET6, RTM_GETADDR)) {
676 		plog(LLV_ERROR, LOCATION, NULL,
677 		     "unable to enumerate addresses: %s\n",
678 		     strerror(errno));
679 	}
680 	while (kernel_receive(NULL, fd) == TRUE);
681 #endif
682 }
683 
684 #elif defined(USE_ROUTE)
685 
686 #ifndef RT_ROUNDUP
687 #define RT_ROUNDUP(a) \
688   ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
689 #endif
690 #define SAROUNDUP(X)   RT_ROUNDUP(((struct sockaddr *)(X))->sa_len)
691 
692 
693 static size_t
parse_address(caddr_t start,caddr_t end,struct sockaddr_storage * dest)694 parse_address(caddr_t start, caddr_t end, struct sockaddr_storage *dest)
695 {
696 	int len;
697 
698 	if (start >= end)
699 		return 0;
700 
701 	len = SAROUNDUP(start);
702 	if (start + len > end)
703 		return end - start;
704 
705 	if (dest != NULL && len <= sizeof(struct sockaddr_storage))
706 		memcpy(dest, start, len);
707 
708 	return len;
709 }
710 
711 static void
parse_addresses(start,end,flags,addr)712 parse_addresses(start, end, flags, addr)
713 	caddr_t start;
714 	caddr_t end;
715 	int flags;
716 	struct sockaddr_storage *addr;
717 {
718 	memset(addr, 0, sizeof(*addr));
719 	if (flags & RTA_DST)
720 		start += parse_address(start, end, NULL);
721 	if (flags & RTA_GATEWAY)
722 		start += parse_address(start, end, NULL);
723 	if (flags & RTA_NETMASK)
724 		start += parse_address(start, end, NULL);
725 	if (flags & RTA_GENMASK)
726 		start += parse_address(start, end, NULL);
727 	if (flags & RTA_IFP)
728 		start += parse_address(start, end, NULL);
729 	if (flags & RTA_IFA)
730 		start += parse_address(start, end, addr);
731 	if (flags & RTA_AUTHOR)
732 		start += parse_address(start, end, NULL);
733 	if (flags & RTA_BRD)
734 		start += parse_address(start, end, NULL);
735 }
736 
737 static void
kernel_handle_message(caddr_t msg)738 kernel_handle_message(caddr_t msg)
739 {
740 	struct rt_msghdr *rtm = (struct rt_msghdr *) msg;
741 	struct ifa_msghdr *ifa = (struct ifa_msghdr *) msg;
742 	struct sockaddr_storage addr;
743 
744 	switch (rtm->rtm_type) {
745 	case RTM_NEWADDR:
746 		parse_addresses(ifa + 1, msg + ifa->ifam_msglen,
747 				ifa->ifam_addrs, &addr);
748 		myaddr_open_all_configured((struct sockaddr *) &addr);
749 		break;
750 	case RTM_DELADDR:
751 		parse_addresses(ifa + 1, msg + ifa->ifam_msglen,
752 				ifa->ifam_addrs, &addr);
753 		myaddr_close_all_open((struct sockaddr *) &addr);
754 		break;
755 	case RTM_ADD:
756 	case RTM_DELETE:
757 	case RTM_CHANGE:
758 	case RTM_GET:
759 	case RTM_MISS:
760 #ifdef RTM_LOSING
761 	case RTM_LOSING:
762 #endif
763 #ifdef RTM_REDIRECT
764 	case RTM_REDIRECT:
765 #endif
766 	case RTM_IFINFO:
767 #ifdef RTM_OIFINFO
768 	case RTM_OIFINFO:
769 #endif
770 #ifdef RTM_NEWMADDR
771 	case RTM_NEWMADDR:
772 	case RTM_DELMADDR:
773 #endif
774 #ifdef RTM_IFANNOUNCE
775 	case RTM_IFANNOUNCE:
776 #endif
777 #ifdef RTM_IEEE80211
778 	case RTM_IEEE80211:
779 #endif
780 		break;
781 	default:
782 		plog(LLV_WARNING, LOCATION, NULL,
783 		     "unrecognized route message with rtm_type: %d\n",
784 		     rtm->rtm_type);
785 		break;
786 	}
787 }
788 
789 static int
kernel_receive(ctx,fd)790 kernel_receive(ctx, fd)
791 	void *ctx;
792 	int fd;
793 {
794 	char buf[16*1024];
795 	struct rt_msghdr *rtm = (struct rt_msghdr *) buf;
796 	int len;
797 
798 	len = read(fd, &buf, sizeof(buf));
799 	if (len <= 0) {
800 		if (len < 0 && errno != EWOULDBLOCK && errno != EAGAIN)
801 			plog(LLV_WARNING, LOCATION, NULL,
802 			     "routing socket error: %s", strerror(errno));
803 		return FALSE;
804 	}
805 
806 	if (rtm->rtm_msglen != len) {
807 		plog(LLV_WARNING, LOCATION, NULL,
808 		     "kernel_receive: rtm->rtm_msglen %d, len %d, type %d\n",
809 		     rtm->rtm_msglen, len, rtm->rtm_type);
810 		return FALSE;
811 	}
812 
813 	kernel_handle_message(buf);
814 	return TRUE;
815 }
816 
817 static int
kernel_open_socket()818 kernel_open_socket()
819 {
820 	int fd;
821 #ifdef RO_MSGFILTER
822 	unsigned char msgfilter[] = { RTM_NEWADDR, RTM_DELADDR };
823 #endif
824 
825 	fd = socket(PF_ROUTE, SOCK_RAW, 0);
826 	if (fd < 0) {
827 		plog(LLV_ERROR, LOCATION, NULL,
828 			"socket(PF_ROUTE) failed: %s",
829 			strerror(errno));
830 		return -1;
831 	}
832 #ifdef RO_MSGFILTER
833 	if (setsockopt(fd, PF_ROUTE, RO_MSGFILTER,
834 	    &msgfilter, sizeof(msgfilter)) < 0)
835 		plog(LLV_WARNING, LOCATION, NULL,
836 		     "setsockopt(RO_MSGFILER) failed: %s",
837 		     strerror(errno));
838 #endif
839 	close_on_exec(fd);
840 	if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
841 		plog(LLV_WARNING, LOCATION, NULL,
842 		     "failed to put socket in non-blocking mode\n");
843 
844 	return fd;
845 }
846 
847 static void
kernel_sync()848 kernel_sync()
849 {
850 	caddr_t ref, buf, end;
851 	size_t bufsiz;
852 	struct rt_msghdr *rtm;
853 
854 #define MIBSIZ 6
855 	int mib[MIBSIZ] = {
856 		CTL_NET,
857 		PF_ROUTE,
858 		0,
859 		0, /*  AF_INET & AF_INET6 */
860 		NET_RT_IFLIST,
861 		0
862 	};
863 
864 	if (sysctl(mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) {
865 		plog(LLV_WARNING, LOCATION, NULL,
866 		     "sysctl() error: %s", strerror(errno));
867 		return;
868 	}
869 
870 	ref = buf = racoon_malloc(bufsiz);
871 
872 	if (sysctl(mib, MIBSIZ, buf, &bufsiz, NULL, 0) >= 0) {
873 		/* Parse both interfaces and addresses. */
874 		for (end = buf + bufsiz; buf < end; buf += rtm->rtm_msglen) {
875 			rtm = (struct rt_msghdr *) buf;
876 			if (rtm->rtm_version != RTM_VERSION)
877 				continue;
878 			kernel_handle_message(buf);
879 		}
880 	} else {
881 		plog(LLV_WARNING, LOCATION, NULL,
882 		     "sysctl() error: %s", strerror(errno));
883 	}
884 
885 	racoon_free(ref);
886 }
887 
888 #else
889 
890 #error No supported interface to monitor local addresses.
891 
892 #endif
893