• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*	$NetBSD: grabmyaddr.c,v 1.28 2011/03/14 17:18:12 tteras 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(my)
85 	struct myaddr *my;
86 {
87 	if (my->fd != -1)
88 		isakmp_close(my->fd);
89 	LIST_REMOVE(my, chain);
90 	racoon_free(my);
91 }
92 
93 static int
myaddr_configured(addr)94 myaddr_configured(addr)
95 	struct sockaddr *addr;
96 {
97 	struct myaddr *cfg;
98 
99 	if (LIST_EMPTY(&configured))
100 		return TRUE;
101 
102 	LIST_FOREACH(cfg, &configured, chain) {
103 		if (cmpsaddr(addr, (struct sockaddr *) &cfg->addr) <= CMPSADDR_WILDPORT_MATCH)
104 			return TRUE;
105 	}
106 
107 	return FALSE;
108 }
109 
110 static int
myaddr_open(addr,udp_encap)111 myaddr_open(addr, udp_encap)
112 	struct sockaddr *addr;
113 	int udp_encap;
114 {
115 	struct myaddr *my;
116 
117 	/* Already open? */
118 	LIST_FOREACH(my, &opened, chain) {
119 		if (cmpsaddr(addr, (struct sockaddr *) &my->addr) <= CMPSADDR_WILDPORT_MATCH)
120 			return TRUE;
121 	}
122 
123 	my = racoon_calloc(1, sizeof(struct myaddr));
124 	if (my == NULL)
125 		return FALSE;
126 
127 	memcpy(&my->addr, addr, sysdep_sa_len(addr));
128 	my->fd = isakmp_open(addr, udp_encap);
129 	if (my->fd < 0) {
130 		racoon_free(my);
131 		return FALSE;
132 	}
133 	my->udp_encap = udp_encap;
134 	LIST_INSERT_HEAD(&opened, my, chain);
135 	return TRUE;
136 }
137 
138 static int
myaddr_open_all_configured(addr)139 myaddr_open_all_configured(addr)
140 	struct sockaddr *addr;
141 {
142 	/* create all configured, not already opened addresses */
143 	struct myaddr *cfg, *my;
144 
145 	if (addr != NULL) {
146 		switch (addr->sa_family) {
147 		case AF_INET:
148 #ifdef INET6
149 		case AF_INET6:
150 #endif
151 			break;
152 		default:
153 			return FALSE;
154 		}
155 	}
156 
157 	LIST_FOREACH(cfg, &configured, chain) {
158 		if (addr != NULL &&
159 		    cmpsaddr(addr, (struct sockaddr *) &cfg->addr) > CMPSADDR_WILDPORT_MATCH)
160 			continue;
161 		if (!myaddr_open((struct sockaddr *) &cfg->addr, cfg->udp_encap))
162 			return FALSE;
163 	}
164 	if (LIST_EMPTY(&configured)) {
165 #ifdef ENABLE_HYBRID
166 		/* Exclude any address we got through ISAKMP mode config */
167 		if (exclude_cfg_addr(addr) == 0)
168 			return FALSE;
169 #endif
170 		set_port(addr, lcconf->port_isakmp);
171 		myaddr_open(addr, FALSE);
172 #ifdef ENABLE_NATT
173 		set_port(addr, lcconf->port_isakmp_natt);
174 		myaddr_open(addr, TRUE);
175 #endif
176 	}
177 	return TRUE;
178 }
179 
180 static void
myaddr_close_all_open(addr)181 myaddr_close_all_open(addr)
182 	struct sockaddr *addr;
183 {
184 	/* delete all matching open sockets */
185 	struct myaddr *my, *next;
186 
187 	for (my = LIST_FIRST(&opened); my; my = next) {
188 		next = LIST_NEXT(my, chain);
189 
190 		if (cmpsaddr((struct sockaddr *) addr,
191 			     (struct sockaddr *) &my->addr)
192 		    <= CMPSADDR_WOP_MATCH)
193 			myaddr_delete(my);
194 	}
195 }
196 
197 static void
myaddr_flush_list(list)198 myaddr_flush_list(list)
199 	struct _myaddr_list_ *list;
200 {
201 	struct myaddr *my, *next;
202 
203 	for (my = LIST_FIRST(list); my; my = next) {
204 		next = LIST_NEXT(my, chain);
205 		myaddr_delete(my);
206 	}
207 }
208 
209 void
myaddr_flush()210 myaddr_flush()
211 {
212 	myaddr_flush_list(&configured);
213 }
214 
215 int
myaddr_listen(addr,udp_encap)216 myaddr_listen(addr, udp_encap)
217 	struct sockaddr *addr;
218 	int udp_encap;
219 {
220 	struct myaddr *my;
221 
222 	if (sysdep_sa_len(addr) > sizeof(my->addr)) {
223 		plog(LLV_ERROR, LOCATION, NULL,
224 		     "sockaddr size larger than sockaddr_storage\n");
225 		return -1;
226 	}
227 
228 	my = racoon_calloc(1, sizeof(struct myaddr));
229 	if (my == NULL)
230 		return -1;
231 
232 	memcpy(&my->addr, addr, sysdep_sa_len(addr));
233 	my->udp_encap = udp_encap;
234 	my->fd = -1;
235 	LIST_INSERT_HEAD(&configured, my, chain);
236 
237 	return 0;
238 }
239 
240 void
myaddr_sync()241 myaddr_sync()
242 {
243 	struct myaddr *my, *next;
244 
245 	if (!lcconf->strict_address) {
246 		kernel_sync();
247 
248 		/* delete all existing listeners which are not configured */
249 		for (my = LIST_FIRST(&opened); my; my = next) {
250 			next = LIST_NEXT(my, chain);
251 
252 			if (!myaddr_configured((struct sockaddr *) &my->addr))
253 				myaddr_delete(my);
254 		}
255 	}
256 }
257 
258 int
myaddr_getfd(addr)259 myaddr_getfd(addr)
260         struct sockaddr *addr;
261 {
262 	struct myaddr *my;
263 
264 	LIST_FOREACH(my, &opened, chain) {
265 		if (cmpsaddr((struct sockaddr *) &my->addr, addr) <= CMPSADDR_WILDPORT_MATCH)
266 			return my->fd;
267 	}
268 
269 	return -1;
270 }
271 
272 int
myaddr_getsport(addr)273 myaddr_getsport(addr)
274 	struct sockaddr *addr;
275 {
276 	struct myaddr *my;
277 
278 	LIST_FOREACH(my, &opened, chain) {
279 		if (cmpsaddr((struct sockaddr *) &my->addr, addr) <= CMPSADDR_WILDPORT_MATCH)
280 			return extract_port((struct sockaddr *) &my->addr);
281 	}
282 
283 	return PORT_ISAKMP;
284 }
285 
286 void
myaddr_init_lists()287 myaddr_init_lists()
288 {
289 	LIST_INIT(&configured);
290 	LIST_INIT(&opened);
291 }
292 
293 int
myaddr_init()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
myaddr_close()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
parse_rtattr(struct rtattr * tb[],int max,struct rtattr * rta,int len)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
netlink_add_rtattr_l(struct nlmsghdr * n,int maxlen,int type,const void * data,int alen)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
netlink_enumerate(fd,family,type)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
netlink_add_del_address(int add,struct sockaddr * saddr)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
netlink_process_addr(struct nlmsghdr * h)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
netlink_route_is_local(int family,const unsigned char * addr,size_t addr_len)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
netlink_process_route(struct nlmsghdr * h)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
netlink_process(struct nlmsghdr * h)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
kernel_receive(ctx,fd)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
netlink_open_socket()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
kernel_open_socket()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
kernel_sync()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 #define ROUNDUP(a) \
683   ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
684 
685 #define SAROUNDUP(X)   ROUNDUP(((struct sockaddr *)(X))->sa_len)
686 
687 static size_t
parse_address(start,end,dest)688 parse_address(start, end, dest)
689 	caddr_t start;
690 	caddr_t end;
691 	struct sockaddr_storage *dest;
692 {
693 	int len;
694 
695 	if (start >= end)
696 		return 0;
697 
698 	len = SAROUNDUP(start);
699 	if (start + len > end)
700 		return end - start;
701 
702 	if (dest != NULL && len <= sizeof(struct sockaddr_storage))
703 		memcpy(dest, start, len);
704 
705 	return len;
706 }
707 
708 static void
parse_addresses(start,end,flags,addr)709 parse_addresses(start, end, flags, addr)
710 	caddr_t start;
711 	caddr_t end;
712 	int flags;
713 	struct sockaddr_storage *addr;
714 {
715 	memset(addr, 0, sizeof(*addr));
716 	if (flags & RTA_DST)
717 		start += parse_address(start, end, NULL);
718 	if (flags & RTA_GATEWAY)
719 		start += parse_address(start, end, NULL);
720 	if (flags & RTA_NETMASK)
721 		start += parse_address(start, end, NULL);
722 	if (flags & RTA_GENMASK)
723 		start += parse_address(start, end, NULL);
724 	if (flags & RTA_IFP)
725 		start += parse_address(start, end, NULL);
726 	if (flags & RTA_IFA)
727 		start += parse_address(start, end, addr);
728 	if (flags & RTA_AUTHOR)
729 		start += parse_address(start, end, NULL);
730 	if (flags & RTA_BRD)
731 		start += parse_address(start, end, NULL);
732 }
733 
734 static void
kernel_handle_message(msg)735 kernel_handle_message(msg)
736 	caddr_t msg;
737 {
738 	struct rt_msghdr *rtm = (struct rt_msghdr *) msg;
739 	struct ifa_msghdr *ifa = (struct ifa_msghdr *) msg;
740 	struct sockaddr_storage addr;
741 
742 	switch (rtm->rtm_type) {
743 	case RTM_NEWADDR:
744 		parse_addresses(ifa + 1, msg + ifa->ifam_msglen,
745 				ifa->ifam_addrs, &addr);
746 		myaddr_open_all_configured((struct sockaddr *) &addr);
747 		break;
748 	case RTM_DELADDR:
749 		parse_addresses(ifa + 1, msg + ifa->ifam_msglen,
750 				ifa->ifam_addrs, &addr);
751 		myaddr_close_all_open((struct sockaddr *) &addr);
752 		break;
753 	case RTM_ADD:
754 	case RTM_DELETE:
755 	case RTM_CHANGE:
756 	case RTM_MISS:
757 	case RTM_IFINFO:
758 #ifdef RTM_OIFINFO
759 	case RTM_OIFINFO:
760 #endif
761 #ifdef RTM_NEWMADDR
762 	case RTM_NEWMADDR:
763 	case RTM_DELMADDR:
764 #endif
765 #ifdef RTM_IFANNOUNCE
766 	case RTM_IFANNOUNCE:
767 #endif
768 		break;
769 	default:
770 		plog(LLV_WARNING, LOCATION, NULL,
771 		     "unrecognized route message with rtm_type: %d",
772 		     rtm->rtm_type);
773 		break;
774 	}
775 }
776 
777 static int
kernel_receive(ctx,fd)778 kernel_receive(ctx, fd)
779 	void *ctx;
780 	int fd;
781 {
782 	char buf[16*1024];
783 	struct rt_msghdr *rtm = (struct rt_msghdr *) buf;
784 	int len;
785 
786 	len = read(fd, &buf, sizeof(buf));
787 	if (len <= 0) {
788 		if (len < 0 && errno != EWOULDBLOCK && errno != EAGAIN)
789 			plog(LLV_WARNING, LOCATION, NULL,
790 			     "routing socket error: %s", strerror(errno));
791 		return FALSE;
792 	}
793 
794 	if (rtm->rtm_msglen != len) {
795 		plog(LLV_WARNING, LOCATION, NULL,
796 		     "kernel_receive: rtm->rtm_msglen %d, len %d, type %d\n",
797 		     rtm->rtm_msglen, len, rtm->rtm_type);
798 		return FALSE;
799 	}
800 
801 	kernel_handle_message(buf);
802 	return TRUE;
803 }
804 
805 static int
kernel_open_socket()806 kernel_open_socket()
807 {
808 	int fd;
809 
810 	fd = socket(PF_ROUTE, SOCK_RAW, 0);
811 	if (fd < 0) {
812 		plog(LLV_ERROR, LOCATION, NULL,
813 			"socket(PF_ROUTE) failed: %s",
814 			strerror(errno));
815 		return -1;
816 	}
817 	close_on_exec(fd);
818 	if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
819 		plog(LLV_WARNING, LOCATION, NULL,
820 		     "failed to put socket in non-blocking mode\n");
821 
822 	return fd;
823 }
824 
825 static void
kernel_sync()826 kernel_sync()
827 {
828 	caddr_t ref, buf, end;
829 	size_t bufsiz;
830 	struct if_msghdr *ifm;
831 	struct interface *ifp;
832 
833 #define MIBSIZ 6
834 	int mib[MIBSIZ] = {
835 		CTL_NET,
836 		PF_ROUTE,
837 		0,
838 		0, /*  AF_INET & AF_INET6 */
839 		NET_RT_IFLIST,
840 		0
841 	};
842 
843 	if (sysctl(mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) {
844 		plog(LLV_WARNING, LOCATION, NULL,
845 		     "sysctl() error: %s", strerror(errno));
846 		return;
847 	}
848 
849 	ref = buf = racoon_malloc(bufsiz);
850 
851 	if (sysctl(mib, MIBSIZ, buf, &bufsiz, NULL, 0) >= 0) {
852 		/* Parse both interfaces and addresses. */
853 		for (end = buf + bufsiz; buf < end; buf += ifm->ifm_msglen) {
854 			ifm = (struct if_msghdr *) buf;
855 			kernel_handle_message(buf);
856 		}
857 	} else {
858 		plog(LLV_WARNING, LOCATION, NULL,
859 		     "sysctl() error: %s", strerror(errno));
860 	}
861 
862 	racoon_free(ref);
863 }
864 
865 #else
866 
867 #error No supported interface to monitor local addresses.
868 
869 #endif
870