Home | History | Annotate | Line # | Download | only in racoon
      1 /*	$NetBSD: grabmyaddr.c,v 1.42 2025/03/08 16:39:08 christos Exp $	*/
      2 /*
      3  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
      4  * Copyright (C) 2008 Timo Teras <timo.teras (at) 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(void *ctx, int fd);
     71 static int kernel_open_socket(void);
     72 static void kernel_sync(void);
     73 
     74 struct myaddr {
     75 	LIST_ENTRY(myaddr) chain;
     76 	struct sockaddr_storage addr;
     77 	int fd;
     78 	int udp_encap;
     79 };
     80 
     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
     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
    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
    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
    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
    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
    203 myaddr_flush(void)
    204 {
    205 	myaddr_flush_list(&configured);
    206 }
    207 
    208 int
    209 myaddr_listen(struct sockaddr *addr, int udp_encap)
    210 {
    211 	struct myaddr *my;
    212 
    213 	if (sysdep_sa_len(addr) > sizeof(my->addr)) {
    214 		plog(LLV_ERROR, LOCATION, NULL,
    215 		     "sockaddr size larger than sockaddr_storage\n");
    216 		return -1;
    217 	}
    218 
    219 	my = racoon_calloc(1, sizeof(struct myaddr));
    220 	if (my == NULL)
    221 		return -1;
    222 
    223 	memcpy(&my->addr, addr, sysdep_sa_len(addr));
    224 	my->udp_encap = udp_encap;
    225 	my->fd = -1;
    226 	LIST_INSERT_HEAD(&configured, my, chain);
    227 
    228 	return 0;
    229 }
    230 
    231 void
    232 myaddr_sync()
    233 {
    234 	struct myaddr *my, *next;
    235 
    236 	if (!lcconf->strict_address) {
    237 		kernel_sync();
    238 
    239 		/* delete all existing listeners which are not configured */
    240 		for (my = LIST_FIRST(&opened); my; my = next) {
    241 			next = LIST_NEXT(my, chain);
    242 
    243 			if (!myaddr_configured((struct sockaddr *) &my->addr))
    244 				myaddr_delete(my);
    245 		}
    246 	}
    247 }
    248 
    249 int
    250 myaddr_getfd(struct sockaddr *addr)
    251 {
    252 	struct myaddr *my;
    253 
    254 	LIST_FOREACH(my, &opened, chain) {
    255 		if (cmpsaddr((struct sockaddr *) &my->addr, addr) <= CMPSADDR_WILDPORT_MATCH)
    256 			return my->fd;
    257 	}
    258 
    259 	return -1;
    260 }
    261 
    262 int
    263 myaddr_getsport(struct sockaddr *addr)
    264 {
    265 	struct myaddr *my;
    266 	int port = 0, wport;
    267 
    268 	LIST_FOREACH(my, &opened, chain) {
    269 		switch (cmpsaddr((struct sockaddr *) &my->addr, addr)) {
    270 		case CMPSADDR_MATCH:
    271 			return extract_port((struct sockaddr *) &my->addr);
    272 		case CMPSADDR_WILDPORT_MATCH:
    273 			wport = extract_port((struct sockaddr *) &my->addr);
    274 			if (port == 0 || wport < port)
    275 				port = wport;
    276 			break;
    277 		}
    278 	}
    279 
    280 	if (port == 0)
    281 		port = PORT_ISAKMP;
    282 
    283 	return port;
    284 }
    285 
    286 void
    287 myaddr_init_lists()
    288 {
    289 	LIST_INIT(&configured);
    290 	LIST_INIT(&opened);
    291 }
    292 
    293 int
    294 myaddr_init()
    295 {
    296         if (!lcconf->strict_address) {
    297 		lcconf->rtsock = kernel_open_socket();
    298 		if (lcconf->rtsock < 0)
    299 			return -1;
    300 		monitor_fd(lcconf->rtsock, kernel_receive, NULL, 0);
    301 	} else {
    302 		lcconf->rtsock = -1;
    303 		if (!myaddr_open_all_configured(NULL))
    304 			return -1;
    305 	}
    306 	return 0;
    307 }
    308 
    309 void
    310 myaddr_close()
    311 {
    312 	myaddr_flush_list(&configured);
    313 	myaddr_flush_list(&opened);
    314 	if (lcconf->rtsock != -1) {
    315 		unmonitor_fd(lcconf->rtsock);
    316 		close(lcconf->rtsock);
    317 	}
    318 }
    319 
    320 #if defined(USE_NETLINK)
    321 
    322 static int netlink_fd = -1;
    323 
    324 #define NLMSG_TAIL(nmsg) \
    325 	((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
    326 
    327 static void
    328 parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
    329 {
    330 	memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
    331 	while (RTA_OK(rta, len)) {
    332 		if (rta->rta_type <= max)
    333 			tb[rta->rta_type] = rta;
    334 		rta = RTA_NEXT(rta,len);
    335 	}
    336 }
    337 
    338 static int
    339 netlink_add_rtattr_l(struct nlmsghdr *n, int maxlen, int type,
    340 		     const void *data, int alen)
    341 {
    342 	int len = RTA_LENGTH(alen);
    343 	struct rtattr *rta;
    344 
    345 	if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen)
    346 		return FALSE;
    347 
    348 	rta = NLMSG_TAIL(n);
    349 	rta->rta_type = type;
    350 	rta->rta_len = len;
    351 	memcpy(RTA_DATA(rta), data, alen);
    352 	n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
    353 	return TRUE;
    354 }
    355 
    356 static int
    357 netlink_enumerate(fd, family, type)
    358 	int fd;
    359 	int family;
    360 	int type;
    361 {
    362 	struct {
    363 		struct nlmsghdr nlh;
    364 		struct rtgenmsg g;
    365 	} req;
    366 	struct sockaddr_nl addr;
    367 	static __u32 seq = 0;
    368 
    369 	memset(&addr, 0, sizeof(addr));
    370 	addr.nl_family = AF_NETLINK;
    371 
    372 	memset(&req, 0, sizeof(req));
    373 	req.nlh.nlmsg_len = sizeof(req);
    374 	req.nlh.nlmsg_type = type;
    375 	req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
    376 	req.nlh.nlmsg_pid = 0;
    377 	req.nlh.nlmsg_seq = ++seq;
    378 	req.g.rtgen_family = family;
    379 
    380 	return sendto(fd, (void *) &req, sizeof(req), 0,
    381 		      (struct sockaddr *) &addr, sizeof(addr)) >= 0;
    382 }
    383 
    384 static void
    385 netlink_add_del_address(int add, struct sockaddr *saddr)
    386 {
    387 	plog(LLV_DEBUG, LOCATION, NULL,
    388 	     "Netlink: address %s %s\n",
    389 	     saddrwop2str((struct sockaddr *) saddr),
    390 	     add ? "added" : "deleted");
    391 
    392 	if (add)
    393 		myaddr_open_all_configured(saddr);
    394 	else
    395 		myaddr_close_all_open(saddr);
    396 }
    397 
    398 #ifdef INET6
    399 static int
    400 netlink_process_addr(struct nlmsghdr *h)
    401 {
    402 	struct sockaddr_storage addr;
    403 	struct ifaddrmsg *ifa;
    404 	struct rtattr *rta[IFA_MAX+1];
    405 	struct sockaddr_in6 *sin6;
    406 
    407 	ifa = NLMSG_DATA(h);
    408 	parse_rtattr(rta, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(h));
    409 
    410 	if (ifa->ifa_family != AF_INET6)
    411 		return 0;
    412 	if (ifa->ifa_flags & IFA_F_TENTATIVE)
    413 		return 0;
    414 	if (rta[IFA_LOCAL] == NULL)
    415 		rta[IFA_LOCAL] = rta[IFA_ADDRESS];
    416 	if (rta[IFA_LOCAL] == NULL)
    417 		return 0;
    418 
    419 	memset(&addr, 0, sizeof(addr));
    420 	addr.ss_family = ifa->ifa_family;
    421 	sin6 = (struct sockaddr_in6 *) &addr;
    422 	memcpy(&sin6->sin6_addr, RTA_DATA(rta[IFA_LOCAL]),
    423 		sizeof(sin6->sin6_addr));
    424 	if (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
    425 		return 0;
    426 	sin6->sin6_scope_id = ifa->ifa_index;
    427 
    428 	netlink_add_del_address(h->nlmsg_type == RTM_NEWADDR,
    429 				(struct sockaddr *) &addr);
    430 
    431 	return 0;
    432 }
    433 #endif
    434 
    435 static int
    436 netlink_route_is_local(int family, const unsigned char *addr, size_t addr_len)
    437 {
    438 	struct {
    439 		struct nlmsghdr n;
    440 		struct rtmsg    r;
    441 		char            buf[1024];
    442 	} req;
    443 	struct rtmsg *r = NLMSG_DATA(&req.n);
    444 	struct rtattr *rta[RTA_MAX+1];
    445 	struct sockaddr_nl nladdr;
    446 	ssize_t rlen;
    447 
    448 	memset(&req, 0, sizeof(req));
    449 	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
    450 	req.n.nlmsg_flags = NLM_F_REQUEST;
    451 	req.n.nlmsg_type = RTM_GETROUTE;
    452 	req.r.rtm_family = family;
    453 	netlink_add_rtattr_l(&req.n, sizeof(req), RTA_DST,
    454 			     addr, addr_len);
    455 	req.r.rtm_dst_len = addr_len * 8;
    456 
    457 	memset(&nladdr, 0, sizeof(nladdr));
    458 	nladdr.nl_family = AF_NETLINK;
    459 
    460 	if (sendto(netlink_fd, &req, sizeof(req), 0,
    461 		   (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0)
    462 		return 0;
    463 	rlen = recv(netlink_fd, &req, sizeof(req), 0);
    464 	if (rlen < 0)
    465 		return 0;
    466 
    467 	return  req.n.nlmsg_type == RTM_NEWROUTE &&
    468 		req.r.rtm_type == RTN_LOCAL;
    469 }
    470 
    471 static int
    472 netlink_process_route(struct nlmsghdr *h)
    473 {
    474 	struct sockaddr_storage addr;
    475 	struct rtmsg *rtm;
    476 	struct rtattr *rta[RTA_MAX+1];
    477 	struct sockaddr_in *sin;
    478 #ifdef INET6
    479 	struct sockaddr_in6 *sin6;
    480 #endif
    481 
    482 	rtm = NLMSG_DATA(h);
    483 
    484 	/* local IP addresses get local route in the local table */
    485 	if (rtm->rtm_type != RTN_LOCAL ||
    486 	    rtm->rtm_table != RT_TABLE_LOCAL)
    487 		return 0;
    488 
    489 	parse_rtattr(rta, IFA_MAX, RTM_RTA(rtm), IFA_PAYLOAD(h));
    490 	if (rta[RTA_DST] == NULL)
    491  		return 0;
    492 
    493 	/* setup the socket address */
    494 	memset(&addr, 0, sizeof(addr));
    495 	addr.ss_family = rtm->rtm_family;
    496 	switch (rtm->rtm_family) {
    497 	case AF_INET:
    498 		sin = (struct sockaddr_in *) &addr;
    499 		memcpy(&sin->sin_addr, RTA_DATA(rta[RTA_DST]),
    500 			sizeof(sin->sin_addr));
    501 		break;
    502 #ifdef INET6
    503 	case AF_INET6:
    504 		sin6 = (struct sockaddr_in6 *) &addr;
    505 		memcpy(&sin6->sin6_addr, RTA_DATA(rta[RTA_DST]),
    506 			sizeof(sin6->sin6_addr));
    507 		/* Link-local addresses are handled with RTM_NEWADDR
    508 		 * notifications */
    509 		if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
    510 			return 0;
    511 		break;
    512 #endif
    513 	default:
    514 		return 0;
    515 	}
    516 
    517 	/* If local route was deleted, check if there is still local
    518 	 * route for the same IP on another interface */
    519 	if (h->nlmsg_type == RTM_DELROUTE &&
    520 	    netlink_route_is_local(rtm->rtm_family,
    521 				   RTA_DATA(rta[RTA_DST]),
    522 				   RTA_PAYLOAD(rta[RTA_DST]))) {
    523 		plog(LLV_DEBUG, LOCATION, NULL,
    524 			"Netlink: not deleting %s yet, it exists still\n",
    525 			saddrwop2str((struct sockaddr *) &addr));
    526 		return 0;
    527 	}
    528 
    529 	netlink_add_del_address(h->nlmsg_type == RTM_NEWROUTE,
    530 				(struct sockaddr *) &addr);
    531 	return 0;
    532 }
    533 
    534 static int
    535 netlink_process(struct nlmsghdr *h)
    536 {
    537 	switch (h->nlmsg_type) {
    538 #ifdef INET6
    539 	case RTM_NEWADDR:
    540 	case RTM_DELADDR:
    541 		return netlink_process_addr(h);
    542 #endif
    543 	case RTM_NEWROUTE:
    544 	case RTM_DELROUTE:
    545 		return netlink_process_route(h);
    546 	}
    547 	return 0;
    548 }
    549 
    550 static int
    551 kernel_receive(ctx, fd)
    552 	void *ctx;
    553 	int fd;
    554 {
    555 	struct sockaddr_nl nladdr;
    556 	struct iovec iov;
    557 	struct msghdr msg = {
    558 		.msg_name = &nladdr,
    559 		.msg_namelen = sizeof(nladdr),
    560 		.msg_iov = &iov,
    561 		.msg_iovlen = 1,
    562 	};
    563 	struct nlmsghdr *h;
    564 	int len, status;
    565 	char buf[16*1024];
    566 
    567 	iov.iov_base = buf;
    568 	while (1) {
    569 		iov.iov_len = sizeof(buf);
    570 		status = recvmsg(fd, &msg, MSG_DONTWAIT);
    571 		if (status < 0) {
    572 			if (errno == EINTR)
    573 				continue;
    574 			if (errno == EAGAIN)
    575 				return FALSE;
    576 			continue;
    577 		}
    578 		if (status == 0)
    579 			return FALSE;
    580 
    581 		h = (struct nlmsghdr *) buf;
    582 		while (NLMSG_OK(h, status)) {
    583 			netlink_process(h);
    584 			h = NLMSG_NEXT(h, status);
    585 		}
    586 	}
    587 
    588 	return TRUE;
    589 }
    590 
    591 static int
    592 netlink_open_socket()
    593 {
    594 	int fd;
    595 
    596 	fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    597 	if (fd < 0) {
    598 		plog(LLV_ERROR, LOCATION, NULL,
    599 			"socket(PF_NETLINK) failed: %s",
    600 			strerror(errno));
    601 		return -1;
    602 	}
    603 	close_on_exec(fd);
    604 	if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
    605 		plog(LLV_WARNING, LOCATION, NULL,
    606 		     "failed to put socket in non-blocking mode\n");
    607 
    608 	return fd;
    609 }
    610 
    611 static int
    612 kernel_open_socket()
    613 {
    614 	struct sockaddr_nl nl;
    615 	int fd;
    616 
    617 	if (netlink_fd < 0) {
    618 		netlink_fd = netlink_open_socket();
    619 		if (netlink_fd < 0)
    620 			return -1;
    621 	}
    622 
    623 	fd = netlink_open_socket();
    624 	if (fd < 0)
    625 		return fd;
    626 
    627 	/* We monitor IPv4 addresses using RTMGRP_IPV4_ROUTE group
    628 	 * the get the RTN_LOCAL routes which are automatically added
    629 	 * by kernel. This is because:
    630 	 *  - Linux kernel has a bug that calling bind() immediately
    631 	 *    after IPv4 RTM_NEWADDR event can fail
    632 	 *  - if IP is configured in multiple interfaces, we get
    633 	 *    RTM_DELADDR for each of them. RTN_LOCAL gets deleted only
    634 	 *    after the last IP address is deconfigured.
    635 	 * The latter reason is also why I chose to use route
    636 	 * notifications for IPv6. However, we do need to use RTM_NEWADDR
    637 	 * for the link-local IPv6 addresses to get the interface index
    638 	 * that is needed in bind().
    639 	 */
    640 	memset(&nl, 0, sizeof(nl));
    641 	nl.nl_family = AF_NETLINK;
    642 	nl.nl_groups = RTMGRP_IPV4_ROUTE
    643 #ifdef INET6
    644 			| RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE
    645 #endif
    646 			;
    647 	if (bind(fd, (struct sockaddr*) &nl, sizeof(nl)) < 0) {
    648 		plog(LLV_ERROR, LOCATION, NULL,
    649 		     "bind(PF_NETLINK) failed: %s\n",
    650 		     strerror(errno));
    651 		close(fd);
    652 		return -1;
    653 	}
    654 	return fd;
    655 }
    656 
    657 static void
    658 kernel_sync()
    659 {
    660 	int fd = lcconf->rtsock;
    661 
    662 	/* refresh addresses */
    663 	if (!netlink_enumerate(fd, PF_UNSPEC, RTM_GETROUTE)) {
    664 		plog(LLV_ERROR, LOCATION, NULL,
    665 		     "unable to enumerate addresses: %s\n",
    666 		     strerror(errno));
    667 	}
    668 	while (kernel_receive(NULL, fd) == TRUE);
    669 
    670 #ifdef INET6
    671 	if (!netlink_enumerate(fd, PF_INET6, RTM_GETADDR)) {
    672 		plog(LLV_ERROR, LOCATION, NULL,
    673 		     "unable to enumerate addresses: %s\n",
    674 		     strerror(errno));
    675 	}
    676 	while (kernel_receive(NULL, fd) == TRUE);
    677 #endif
    678 }
    679 
    680 #elif defined(USE_ROUTE)
    681 
    682 #ifndef RT_ROUNDUP
    683 #define RT_ROUNDUP(a) \
    684   ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
    685 #endif
    686 #define SAROUNDUP(X)   RT_ROUNDUP(((struct sockaddr *)(X))->sa_len)
    687 
    688 
    689 static size_t
    690 parse_address(caddr_t start, caddr_t end, struct sockaddr_storage *dest)
    691 {
    692 	size_t len;
    693 
    694 	if (start >= end)
    695 		return 0;
    696 
    697 	len = SAROUNDUP(start);
    698 	if (start + len > end)
    699 		return end - start;
    700 
    701 	if (dest != NULL && len <= sizeof(struct sockaddr_storage))
    702 		memcpy(dest, start, len);
    703 
    704 	return len;
    705 }
    706 
    707 static void
    708 parse_addresses(caddr_t start, caddr_t end, int flags,
    709     struct sockaddr_storage *addr)
    710 {
    711 	memset(addr, 0, sizeof(*addr));
    712 	if (flags & RTA_DST)
    713 		start += parse_address(start, end, NULL);
    714 	if (flags & RTA_GATEWAY)
    715 		start += parse_address(start, end, NULL);
    716 	if (flags & RTA_NETMASK)
    717 		start += parse_address(start, end, NULL);
    718 	if (flags & RTA_GENMASK)
    719 		start += parse_address(start, end, NULL);
    720 	if (flags & RTA_IFP)
    721 		start += parse_address(start, end, NULL);
    722 	if (flags & RTA_IFA)
    723 		start += parse_address(start, end, addr);
    724 	if (flags & RTA_AUTHOR)
    725 		start += parse_address(start, end, NULL);
    726 	if (flags & RTA_BRD)
    727 		start += parse_address(start, end, NULL);
    728 }
    729 
    730 static void
    731 kernel_handle_message(caddr_t msg)
    732 {
    733 	struct rt_msghdr *rtm = (struct rt_msghdr *) msg;
    734 	struct ifa_msghdr *ifa = (struct ifa_msghdr *) msg;
    735 	struct sockaddr_storage addr;
    736 
    737 	switch (rtm->rtm_type) {
    738 	case RTM_NEWADDR:
    739 		parse_addresses((caddr_t)(ifa + 1), msg + ifa->ifam_msglen,
    740 				ifa->ifam_addrs, &addr);
    741 		myaddr_open_all_configured((struct sockaddr *) &addr);
    742 		break;
    743 	case RTM_DELADDR:
    744 		parse_addresses((caddr_t)(ifa + 1), msg + ifa->ifam_msglen,
    745 				ifa->ifam_addrs, &addr);
    746 		myaddr_close_all_open((struct sockaddr *) &addr);
    747 		break;
    748 	case RTM_ADD:
    749 	case RTM_DELETE:
    750 	case RTM_CHANGE:
    751 	case RTM_GET:
    752 	case RTM_MISS:
    753 #ifdef RTM_LOSING
    754 	case RTM_LOSING:
    755 #endif
    756 #ifdef RTM_REDIRECT
    757 	case RTM_REDIRECT:
    758 #endif
    759 	case RTM_IFINFO:
    760 #ifdef RTM_OIFINFO
    761 	case RTM_OIFINFO:
    762 #endif
    763 #ifdef RTM_NEWMADDR
    764 	case RTM_NEWMADDR:
    765 	case RTM_DELMADDR:
    766 #endif
    767 #ifdef RTM_IFANNOUNCE
    768 	case RTM_IFANNOUNCE:
    769 #endif
    770 #ifdef RTM_IEEE80211
    771 	case RTM_IEEE80211:
    772 #endif
    773 		break;
    774 	default:
    775 		plog(LLV_WARNING, LOCATION, NULL,
    776 		     "unrecognized route message with rtm_type: %d\n",
    777 		     rtm->rtm_type);
    778 		break;
    779 	}
    780 }
    781 
    782 /*ARGSUSED*/
    783 static int
    784 kernel_receive(void *ctx __unused, int fd)
    785 {
    786 	char buf[16*1024];
    787 	struct rt_msghdr *rtm = (struct rt_msghdr *) buf;
    788 	ssize_t len;
    789 
    790 	len = read(fd, &buf, sizeof(buf));
    791 	if (len <= 0) {
    792 		if (len < 0 && errno != EWOULDBLOCK && errno != EAGAIN)
    793 			plog(LLV_WARNING, LOCATION, NULL,
    794 			     "routing socket error: %s", strerror(errno));
    795 		return FALSE;
    796 	}
    797 
    798 	if (rtm->rtm_msglen != len) {
    799 		plog(LLV_WARNING, LOCATION, NULL,
    800 		     "kernel_receive: rtm->rtm_msglen %d, len %zd, type %d\n",
    801 		     rtm->rtm_msglen, len, rtm->rtm_type);
    802 		return FALSE;
    803 	}
    804 
    805 	kernel_handle_message(buf);
    806 	return TRUE;
    807 }
    808 
    809 static int
    810 kernel_open_socket()
    811 {
    812 	int fd;
    813 #ifdef RO_MSGFILTER
    814 	unsigned char msgfilter[] = { RTM_NEWADDR, RTM_DELADDR };
    815 #endif
    816 
    817 	fd = socket(PF_ROUTE, SOCK_RAW, 0);
    818 	if (fd < 0) {
    819 		plog(LLV_ERROR, LOCATION, NULL,
    820 			"socket(PF_ROUTE) failed: %s",
    821 			strerror(errno));
    822 		return -1;
    823 	}
    824 #ifdef RO_MSGFILTER
    825 	if (setsockopt(fd, PF_ROUTE, RO_MSGFILTER,
    826 	    &msgfilter, sizeof(msgfilter)) < 0)
    827 		plog(LLV_WARNING, LOCATION, NULL,
    828 		     "setsockopt(RO_MSGFILER) failed: %s",
    829 		     strerror(errno));
    830 #endif
    831 	close_on_exec(fd);
    832 	if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
    833 		plog(LLV_WARNING, LOCATION, NULL,
    834 		     "failed to put socket in non-blocking mode\n");
    835 
    836 	return fd;
    837 }
    838 
    839 static void
    840 kernel_sync()
    841 {
    842 	caddr_t ref, buf, end;
    843 	size_t bufsiz;
    844 	struct rt_msghdr *rtm;
    845 
    846 #define MIBSIZ 6
    847 	int mib[MIBSIZ] = {
    848 		CTL_NET,
    849 		PF_ROUTE,
    850 		0,
    851 		0, /*  AF_INET & AF_INET6 */
    852 		NET_RT_IFLIST,
    853 		0
    854 	};
    855 
    856 	if (sysctl(mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) {
    857 		plog(LLV_WARNING, LOCATION, NULL,
    858 		     "sysctl() error: %s", strerror(errno));
    859 		return;
    860 	}
    861 
    862 	ref = buf = racoon_malloc(bufsiz);
    863 
    864 	if (sysctl(mib, MIBSIZ, buf, &bufsiz, NULL, 0) >= 0) {
    865 		/* Parse both interfaces and addresses. */
    866 		for (end = buf + bufsiz; buf < end; buf += rtm->rtm_msglen) {
    867 			rtm = (struct rt_msghdr *) buf;
    868 			if (rtm->rtm_version != RTM_VERSION)
    869 				continue;
    870 			kernel_handle_message(buf);
    871 		}
    872 	} else {
    873 		plog(LLV_WARNING, LOCATION, NULL,
    874 		     "sysctl() error: %s", strerror(errno));
    875 	}
    876 
    877 	racoon_free(ref);
    878 }
    879 
    880 #else
    881 
    882 #error No supported interface to monitor local addresses.
    883 
    884 #endif
    885