xref: /netbsd-src/crypto/dist/ipsec-tools/src/racoon/grabmyaddr.c (revision 86811edb37e43f44504b192591c863c5d48f5e08)
1 /*	$NetBSD: grabmyaddr.c,v 1.3 2005/11/21 14:20:29 manu Exp $	*/
2 
3 /* Id: grabmyaddr.c,v 1.23.4.2 2005/07/16 04:41:01 monas Exp */
4 
5 /*
6  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the project nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include "config.h"
35 
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/socket.h>
39 #include <sys/ioctl.h>
40 
41 #include <net/if.h>
42 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
43 #include <net/if_var.h>
44 #endif
45 #if defined(__NetBSD__) || defined(__FreeBSD__)
46 #include <netinet/in.h>
47 #include <netinet6/in6_var.h>
48 #endif
49 #include <net/route.h>
50 
51 #include <stdlib.h>
52 #include <stdio.h>
53 #include <string.h>
54 #include <errno.h>
55 #ifdef HAVE_UNISTD_H
56 #include <unistd.h>
57 #endif
58 #include <netdb.h>
59 #ifdef HAVE_GETIFADDRS
60 #include <ifaddrs.h>
61 #include <net/if.h>
62 #endif
63 
64 #include "var.h"
65 #include "misc.h"
66 #include "vmbuf.h"
67 #include "plog.h"
68 #include "sockmisc.h"
69 #include "debug.h"
70 
71 #include "localconf.h"
72 #include "handler.h"
73 #include "grabmyaddr.h"
74 #include "sockmisc.h"
75 #include "isakmp_var.h"
76 #include "gcmalloc.h"
77 #include "nattraversal.h"
78 
79 #ifdef __linux__
80 #include <linux/types.h>
81 #include <linux/rtnetlink.h>
82 #ifndef HAVE_GETIFADDRS
83 #define HAVE_GETIFADDRS
84 #define NEED_LINUX_GETIFADDRS
85 #endif
86 #endif
87 
88 #ifndef HAVE_GETIFADDRS
89 static unsigned int if_maxindex __P((void));
90 #endif
91 static struct myaddrs *find_myaddr __P((struct myaddrs *, struct myaddrs *));
92 static int suitable_ifaddr __P((const char *, const struct sockaddr *));
93 #ifdef INET6
94 static int suitable_ifaddr6 __P((const char *, const struct sockaddr *));
95 #endif
96 
97 #ifdef NEED_LINUX_GETIFADDRS
98 
99 /* We could do this _much_ better. kame racoon in its current form
100  * will esentially die at frequent changes of address configuration.
101  */
102 
103 struct ifaddrs
104 {
105 	struct ifaddrs *ifa_next;
106 	char		ifa_name[16];
107 	int		ifa_ifindex;
108 	struct sockaddr *ifa_addr;
109 	struct sockaddr_storage ifa_addrbuf;
110 };
111 
112 static int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
113 {
114 	while (RTA_OK(rta, len)) {
115 		if (rta->rta_type <= max)
116 			tb[rta->rta_type] = rta;
117 		rta = RTA_NEXT(rta,len);
118 	}
119 	return 0;
120 }
121 
122 static void recvaddrs(int fd, struct ifaddrs **ifa, __u32 seq)
123 {
124 	char	buf[8192];
125 	struct sockaddr_nl nladdr;
126 	struct iovec iov = { buf, sizeof(buf) };
127 	struct ifaddrmsg *m;
128 	struct rtattr * rta_tb[IFA_MAX+1];
129 	struct ifaddrs *I;
130 
131 	while (1) {
132 		int status;
133 		struct nlmsghdr *h;
134 
135 		struct msghdr msg = {
136 			(void*)&nladdr, sizeof(nladdr),
137 			&iov,	1,
138 			NULL,	0,
139 			0
140 		};
141 
142 		status = recvmsg(fd, &msg, 0);
143 
144 		if (status < 0)
145 			continue;
146 
147 		if (status == 0)
148 			return;
149 
150 		if (nladdr.nl_pid) /* Message not from kernel */
151 			continue;
152 
153 		h = (struct nlmsghdr*)buf;
154 		while (NLMSG_OK(h, status)) {
155 			if (h->nlmsg_seq != seq)
156 				goto skip_it;
157 
158 			if (h->nlmsg_type == NLMSG_DONE)
159 				return;
160 
161 			if (h->nlmsg_type == NLMSG_ERROR)
162 				return;
163 
164 			if (h->nlmsg_type != RTM_NEWADDR)
165 				goto skip_it;
166 
167 			m = NLMSG_DATA(h);
168 
169 			if (m->ifa_family != AF_INET &&
170 			    m->ifa_family != AF_INET6)
171 				goto skip_it;
172 
173 			if (m->ifa_flags&IFA_F_TENTATIVE)
174 				goto skip_it;
175 
176 			memset(rta_tb, 0, sizeof(rta_tb));
177 			parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(m), h->nlmsg_len - NLMSG_LENGTH(sizeof(*m)));
178 
179 			if (rta_tb[IFA_LOCAL] == NULL)
180 				rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];
181 			if (rta_tb[IFA_LOCAL] == NULL)
182 				goto skip_it;
183 
184 			I = malloc(sizeof(struct ifaddrs));
185 			if (!I)
186 				return;
187 			memset(I, 0, sizeof(*I));
188 
189 			I->ifa_ifindex = m->ifa_index;
190 			I->ifa_addr = (struct sockaddr*)&I->ifa_addrbuf;
191 			I->ifa_addr->sa_family = m->ifa_family;
192 			if (m->ifa_family == AF_INET) {
193 				struct sockaddr_in *sin = (void*)I->ifa_addr;
194 				memcpy(&sin->sin_addr, RTA_DATA(rta_tb[IFA_LOCAL]), 4);
195 			} else {
196 				struct sockaddr_in6 *sin = (void*)I->ifa_addr;
197 				memcpy(&sin->sin6_addr, RTA_DATA(rta_tb[IFA_LOCAL]), 16);
198 				if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr))
199 					sin->sin6_scope_id = I->ifa_ifindex;
200 			}
201 			I->ifa_next = *ifa;
202 			*ifa = I;
203 
204 skip_it:
205 			h = NLMSG_NEXT(h, status);
206 		}
207 		if (msg.msg_flags & MSG_TRUNC)
208 			continue;
209 	}
210 	return;
211 }
212 
213 static int getifaddrs(struct ifaddrs **ifa0)
214 {
215 	struct {
216 		struct nlmsghdr nlh;
217 		struct rtgenmsg g;
218 	} req;
219 	struct sockaddr_nl nladdr;
220 	static __u32 seq;
221 	struct ifaddrs *i;
222 	int fd;
223 
224 	fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
225 	if (fd < 0)
226 		return -1;
227 
228 	memset(&nladdr, 0, sizeof(nladdr));
229 	nladdr.nl_family = AF_NETLINK;
230 
231 	req.nlh.nlmsg_len = sizeof(req);
232 	req.nlh.nlmsg_type = RTM_GETADDR;
233 	req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
234 	req.nlh.nlmsg_pid = 0;
235 	req.nlh.nlmsg_seq = ++seq;
236 	req.g.rtgen_family = AF_UNSPEC;
237 
238 	if (sendto(fd, (void*)&req, sizeof(req), 0, (struct sockaddr*)&nladdr, sizeof(nladdr)) < 0) {
239 		close(fd);
240 		return -1;
241 	}
242 
243 	*ifa0 = NULL;
244 
245 	recvaddrs(fd, ifa0, seq);
246 
247 	close(fd);
248 
249 	fd = socket(AF_INET, SOCK_DGRAM, 0);
250 
251 	for (i=*ifa0; i; i = i->ifa_next) {
252 		struct ifreq ifr;
253 		ifr.ifr_ifindex = i->ifa_ifindex;
254 		ioctl(fd, SIOCGIFNAME, (void*)&ifr);
255 		memcpy(i->ifa_name, ifr.ifr_name, 16);
256 	}
257 	close(fd);
258 
259 	return 0;
260 }
261 
262 static void freeifaddrs(struct ifaddrs *ifa0)
263 {
264         struct ifaddrs *i;
265 
266         while (ifa0) {
267                 i = ifa0;
268                 ifa0 = i->ifa_next;
269                 free(i);
270         }
271 }
272 
273 #endif
274 
275 #ifndef HAVE_GETIFADDRS
276 static unsigned int
277 if_maxindex()
278 {
279 	struct if_nameindex *p, *p0;
280 	unsigned int max = 0;
281 
282 	p0 = if_nameindex();
283 	for (p = p0; p && p->if_index && p->if_name; p++) {
284 		if (max < p->if_index)
285 			max = p->if_index;
286 	}
287 	if_freenameindex(p0);
288 	return max;
289 }
290 #endif
291 
292 void
293 clear_myaddr(db)
294 	struct myaddrs **db;
295 {
296 	struct myaddrs *p;
297 
298 	while (*db) {
299 		p = (*db)->next;
300 		delmyaddr(*db);
301 		*db = p;
302 	}
303 }
304 
305 static struct myaddrs *
306 find_myaddr(db, p)
307 	struct myaddrs *db;
308 	struct myaddrs *p;
309 {
310 	struct myaddrs *q;
311 	char h1[NI_MAXHOST], h2[NI_MAXHOST];
312 
313 	if (getnameinfo(p->addr, sysdep_sa_len(p->addr), h1, sizeof(h1), NULL, 0,
314 	    NI_NUMERICHOST | niflags) != 0)
315 		return NULL;
316 
317 	for (q = db; q; q = q->next) {
318 		if (p->addr->sa_family != q->addr->sa_family)
319 			continue;
320 		if (getnameinfo(q->addr, sysdep_sa_len(q->addr), h2, sizeof(h2),
321 		    NULL, 0, NI_NUMERICHOST | niflags) != 0)
322 			return NULL;
323 		if (strcmp(h1, h2) == 0)
324 			return q;
325 	}
326 
327 	return NULL;
328 }
329 
330 void
331 grab_myaddrs()
332 {
333 #ifdef HAVE_GETIFADDRS
334 	struct myaddrs *p, *q, *old;
335 	struct ifaddrs *ifa0, *ifap;
336 #ifdef INET6
337 	struct sockaddr_in6 *sin6;
338 #endif
339 
340 	char addr1[NI_MAXHOST];
341 
342 	if (getifaddrs(&ifa0)) {
343 		plog(LLV_ERROR, LOCATION, NULL,
344 			"getifaddrs failed: %s\n", strerror(errno));
345 		exit(1);
346 		/*NOTREACHED*/
347 	}
348 
349 	old = lcconf->myaddrs;
350 
351 	for (ifap = ifa0; ifap; ifap = ifap->ifa_next) {
352 		if (! ifap->ifa_addr)
353 			continue;
354 
355 		if (ifap->ifa_addr->sa_family != AF_INET
356 #ifdef INET6
357 		 && ifap->ifa_addr->sa_family != AF_INET6
358 #endif
359 		)
360 			continue;
361 
362 		if (!suitable_ifaddr(ifap->ifa_name, ifap->ifa_addr)) {
363 			plog(LLV_ERROR, LOCATION, NULL,
364 				"unsuitable address: %s %s\n",
365 				ifap->ifa_name,
366 				saddrwop2str(ifap->ifa_addr));
367 			continue;
368 		}
369 
370 		p = newmyaddr();
371 		if (p == NULL) {
372 			exit(1);
373 			/*NOTREACHED*/
374 		}
375 		p->addr = dupsaddr(ifap->ifa_addr);
376 		if (p->addr == NULL) {
377 			exit(1);
378 			/*NOTREACHED*/
379 		}
380 #ifdef INET6
381 #ifdef __KAME__
382 		if (ifap->ifa_addr->sa_family == AF_INET6) {
383 			sin6 = (struct sockaddr_in6 *)p->addr;
384 			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)
385 			 || IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
386 				sin6->sin6_scope_id =
387 					ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
388 				sin6->sin6_addr.s6_addr[2] = 0;
389 				sin6->sin6_addr.s6_addr[3] = 0;
390 			}
391 		}
392 #else /* !__KAME__ */
393 		if (ifap->ifa_addr->sa_family == AF_INET6) {
394 			sin6 = (struct sockaddr_in6 *)p->addr;
395 			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)
396 			 || IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
397 				sin6->sin6_scope_id =
398 					if_nametoindex(ifap->ifa_name);
399 			}
400 		}
401 
402 #endif
403 #endif
404 		if (getnameinfo(p->addr, sysdep_sa_len(p->addr),
405 				addr1, sizeof(addr1),
406 				NULL, 0,
407 				NI_NUMERICHOST | niflags))
408 		strlcpy(addr1, "(invalid)", sizeof(addr1));
409 		plog(LLV_DEBUG, LOCATION, NULL,
410 			"my interface: %s (%s)\n",
411 			addr1, ifap->ifa_name);
412 		q = find_myaddr(old, p);
413 		if (q)
414 			p->sock = q->sock;
415 		else
416 			p->sock = -1;
417 		p->next = lcconf->myaddrs;
418 		lcconf->myaddrs = p;
419 	}
420 
421 	freeifaddrs(ifa0);
422 
423 	clear_myaddr(&old);
424 
425 #else /*!HAVE_GETIFADDRS*/
426 	int s;
427 	unsigned int maxif;
428 	int len;
429 	struct ifreq *iflist;
430 	struct ifconf ifconf;
431 	struct ifreq *ifr, *ifr_end;
432 	struct myaddrs *p, *q, *old;
433 #ifdef INET6
434 #ifdef __KAME__
435 	struct sockaddr_in6 *sin6;
436 #endif
437 #endif
438 
439 	char addr1[NI_MAXHOST];
440 
441 	maxif = if_maxindex() + 1;
442 	len = maxif * sizeof(struct sockaddr_storage) * 4; /* guess guess */
443 
444 	iflist = (struct ifreq *)racoon_malloc(len);
445 	if (!iflist) {
446 		plog(LLV_ERROR, LOCATION, NULL,
447 			"failed to allocate buffer\n");
448 		exit(1);
449 		/*NOTREACHED*/
450 	}
451 
452 	if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
453 		plog(LLV_ERROR, LOCATION, NULL,
454 			"socket(SOCK_DGRAM) failed: %s\n",
455 			strerror(errno));
456 		exit(1);
457 		/*NOTREACHED*/
458 	}
459 	memset(&ifconf, 0, sizeof(ifconf));
460 	ifconf.ifc_req = iflist;
461 	ifconf.ifc_len = len;
462 	if (ioctl(s, SIOCGIFCONF, &ifconf) < 0) {
463 		plog(LLV_ERROR, LOCATION, NULL,
464 			"ioctl(SIOCGIFCONF) failed: %s\n",
465 			strerror(errno));
466 		exit(1);
467 		/*NOTREACHED*/
468 	}
469 	close(s);
470 
471 	old = lcconf->myaddrs;
472 
473 	/* Look for this interface in the list */
474 	ifr_end = (struct ifreq *) (ifconf.ifc_buf + ifconf.ifc_len);
475 
476 #define _IFREQ_LEN(p) \
477   (sizeof((p)->ifr_name) + sysdep_sa_len(&(p)->ifr_addr) > sizeof(struct ifreq) \
478     ? sizeof((p)->ifr_name) + sysdep_sa_len(&(p)->ifr_addr) : sizeof(struct ifreq))
479 
480 	for (ifr = ifconf.ifc_req;
481 	     ifr < ifr_end;
482 	     ifr = (struct ifreq *)((caddr_t)ifr + _IFREQ_LEN(ifr))) {
483 
484 		switch (ifr->ifr_addr.sa_family) {
485 		case AF_INET:
486 #ifdef INET6
487 		case AF_INET6:
488 #endif
489 			if (!suitable_ifaddr(ifr->ifr_name, &ifr->ifr_addr)) {
490 				plog(LLV_ERROR, LOCATION, NULL,
491 					"unsuitable address: %s %s\n",
492 					ifr->ifr_name,
493 					saddrwop2str(&ifr->ifr_addr));
494 				continue;
495 			}
496 
497 			p = newmyaddr();
498 			if (p == NULL) {
499 				exit(1);
500 				/*NOTREACHED*/
501 			}
502 			p->addr = dupsaddr(&ifr->ifr_addr);
503 			if (p->addr == NULL) {
504 				exit(1);
505 				/*NOTREACHED*/
506 			}
507 #ifdef INET6
508 #ifdef __KAME__
509 			sin6 = (struct sockaddr_in6 *)p->addr;
510 			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)
511 			 || IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
512 				sin6->sin6_scope_id =
513 					ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
514 				sin6->sin6_addr.s6_addr[2] = 0;
515 				sin6->sin6_addr.s6_addr[3] = 0;
516 			}
517 #endif
518 #endif
519 			if (getnameinfo(p->addr, sysdep_sa_len(p->addr),
520 					addr1, sizeof(addr1),
521 					NULL, 0,
522 					NI_NUMERICHOST | niflags))
523 			strlcpy(addr1, "(invalid)", sizeof(addr1));
524 			plog(LLV_DEBUG, LOCATION, NULL,
525 				"my interface: %s (%s)\n",
526 				addr1, ifr->ifr_name);
527 			q = find_myaddr(old, p);
528 			if (q)
529 				p->sock = q->sock;
530 			else
531 				p->sock = -1;
532 			p->next = lcconf->myaddrs;
533 			lcconf->myaddrs = p;
534 			break;
535 		default:
536 			break;
537 		}
538 	}
539 
540 	clear_myaddr(&old);
541 
542 	racoon_free(iflist);
543 #endif /*HAVE_GETIFADDRS*/
544 }
545 
546 /*
547  * check the interface is suitable or not
548  */
549 static int
550 suitable_ifaddr(ifname, ifaddr)
551 	const char *ifname;
552 	const struct sockaddr *ifaddr;
553 {
554 #ifdef ENABLE_HYBRID
555 	/* Exclude any address we got through ISAKMP mode config */
556 	if (exclude_cfg_addr(ifaddr) == 0)
557 		return 0;
558 #endif
559 	switch(ifaddr->sa_family) {
560 	case AF_INET:
561 		return 1;
562 #ifdef INET6
563 	case AF_INET6:
564 		return suitable_ifaddr6(ifname, ifaddr);
565 #endif
566 	default:
567 		return 0;
568 	}
569 	/*NOTREACHED*/
570 }
571 
572 #ifdef INET6
573 static int
574 suitable_ifaddr6(ifname, ifaddr)
575 	const char *ifname;
576 	const struct sockaddr *ifaddr;
577 {
578 #ifndef __linux__
579 	struct in6_ifreq ifr6;
580 	int s;
581 #endif
582 
583 	if (ifaddr->sa_family != AF_INET6)
584 		return 0;
585 
586 #ifndef __linux__
587 	s = socket(PF_INET6, SOCK_DGRAM, 0);
588 	if (s == -1) {
589 		plog(LLV_ERROR, LOCATION, NULL,
590 			"socket(SOCK_DGRAM) failed:%s\n", strerror(errno));
591 		return 0;
592 	}
593 
594 	memset(&ifr6, 0, sizeof(ifr6));
595 	strncpy(ifr6.ifr_name, ifname, strlen(ifname));
596 
597 	ifr6.ifr_addr = *(const struct sockaddr_in6 *)ifaddr;
598 
599 	if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
600 		plog(LLV_ERROR, LOCATION, NULL,
601 			"ioctl(SIOCGIFAFLAG_IN6) failed:%s\n", strerror(errno));
602 		close(s);
603 		return 0;
604 	}
605 
606 	close(s);
607 
608 	if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DUPLICATED
609 	 || ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DETACHED
610 	 || ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_ANYCAST)
611 		return 0;
612 #endif
613 
614 	/* suitable */
615 	return 1;
616 }
617 #endif
618 
619 int
620 update_myaddrs()
621 {
622 #ifdef __linux__
623 	char msg[BUFSIZ];
624 	int len;
625 	struct nlmsghdr *h = (void*)msg;
626 	len = read(lcconf->rtsock, msg, sizeof(msg));
627 	if (len < 0)
628 		return errno == ENOBUFS;
629 	if (len < sizeof(*h))
630 		return 0;
631 	if (h->nlmsg_pid) /* not from kernel! */
632 		return 0;
633 	if (h->nlmsg_type == RTM_NEWLINK)
634 		return 0;
635 	plog(LLV_DEBUG, LOCATION, NULL,
636 		"netlink signals update interface address list\n");
637 	return 1;
638 #else
639 	char msg[BUFSIZ];
640 	int len;
641 	struct rt_msghdr *rtm;
642 
643 	len = read(lcconf->rtsock, msg, sizeof(msg));
644 	if (len < 0) {
645 		plog(LLV_ERROR, LOCATION, NULL,
646 			"read(PF_ROUTE) failed: %s\n",
647 			strerror(errno));
648 		return 0;
649 	}
650 	rtm = (struct rt_msghdr *)msg;
651 	if (len < rtm->rtm_msglen) {
652 		plog(LLV_ERROR, LOCATION, NULL,
653 			"read(PF_ROUTE) short read\n");
654 		return 0;
655 	}
656 	if (rtm->rtm_version != RTM_VERSION) {
657 		plog(LLV_ERROR, LOCATION, NULL,
658 			"routing socket version mismatch\n");
659 		close(lcconf->rtsock);
660 		lcconf->rtsock = -1;
661 		return 0;
662 	}
663 	switch (rtm->rtm_type) {
664 	case RTM_NEWADDR:
665 	case RTM_DELADDR:
666 	case RTM_DELETE:
667 	case RTM_IFINFO:
668 		break;
669 	case RTM_MISS:
670 		/* ignore this message silently */
671 		return 0;
672 	default:
673 		plog(LLV_DEBUG, LOCATION, NULL,
674 			"msg %d not interesting\n", rtm->rtm_type);
675 		return 0;
676 	}
677 	/* XXX more filters here? */
678 
679 	plog(LLV_DEBUG, LOCATION, NULL,
680 		"caught rtm:%d, need update interface address list\n",
681 		rtm->rtm_type);
682 	return 1;
683 #endif /* __linux__ */
684 }
685 
686 /*
687  * initialize default port for ISAKMP to send, if no "listen"
688  * directive is specified in config file.
689  *
690  * DO NOT listen to wildcard addresses.  if you receive packets to
691  * wildcard address, you'll be in trouble (DoS attack possible by
692  * broadcast storm).
693  */
694 int
695 autoconf_myaddrsport()
696 {
697 	struct myaddrs *p;
698 	int n;
699 
700 	plog(LLV_DEBUG, LOCATION, NULL,
701 		"configuring default isakmp port.\n");
702 
703 #ifdef ENABLE_NATT
704 	if (natt_enabled_in_rmconf ()) {
705 		plog(LLV_NOTIFY, LOCATION, NULL, "NAT-T is enabled, autoconfiguring ports\n");
706 		for (p = lcconf->myaddrs; p; p = p->next) {
707 			struct myaddrs *new;
708 			if (! p->udp_encap) {
709 				new = dupmyaddr(p);
710 				new->udp_encap = 1;
711 			}
712 		}
713 	}
714 #endif
715 
716 	for (p = lcconf->myaddrs, n = 0; p; p = p->next, n++) {
717 		set_port (p->addr, p->udp_encap ? lcconf->port_isakmp_natt : lcconf->port_isakmp);
718 	}
719 	plog(LLV_DEBUG, LOCATION, NULL,
720 		"%d addrs are configured successfully\n", n);
721 
722 	return 0;
723 }
724 
725 /*
726  * get a port number to which racoon binded.
727  * NOTE: network byte order returned.
728  */
729 u_short
730 getmyaddrsport(local)
731 	struct sockaddr *local;
732 {
733 	struct myaddrs *p, *bestmatch = NULL;
734 	u_short bestmatch_port = PORT_ISAKMP;
735 
736 	/* get a relative port */
737 	for (p = lcconf->myaddrs; p; p = p->next) {
738 		if (!p->addr)
739 			continue;
740 		if (!cmpsaddrwop(local, p->addr)) {
741 			if (! bestmatch) {
742 				bestmatch = p;
743 				continue;
744 			}
745 
746 			switch (p->addr->sa_family) {
747 			case AF_INET:
748 				if (((struct sockaddr_in *)p->addr)->sin_port == PORT_ISAKMP) {
749 					bestmatch = p;
750 					bestmatch_port = ((struct sockaddr_in *)p->addr)->sin_port;
751 					break;
752 				}
753 				break;
754 #ifdef INET6
755 			case AF_INET6:
756 				if (((struct sockaddr_in6 *)p->addr)->sin6_port == PORT_ISAKMP) {
757 					bestmatch = p;
758 					bestmatch_port = ((struct sockaddr_in6 *)p->addr)->sin6_port;
759 					break;
760 				}
761 				break;
762 #endif
763 			default:
764 				plog(LLV_ERROR, LOCATION, NULL,
765 				     "unsupported AF %d\n", p->addr->sa_family);
766 				continue;
767 			}
768 		}
769 	}
770 
771 	return htons(bestmatch_port);
772 }
773 
774 struct myaddrs *
775 newmyaddr()
776 {
777 	struct myaddrs *new;
778 
779 	new = racoon_calloc(1, sizeof(*new));
780 	if (new == NULL) {
781 		plog(LLV_ERROR, LOCATION, NULL,
782 			"failed to allocate buffer for myaddrs.\n");
783 		return NULL;
784 	}
785 
786 	new->next = NULL;
787 	new->addr = NULL;
788 
789 	return new;
790 }
791 
792 struct myaddrs *
793 dupmyaddr(struct myaddrs *old)
794 {
795 	struct myaddrs *new;
796 
797 	new = racoon_calloc(1, sizeof(*new));
798 	if (new == NULL) {
799 		plog(LLV_ERROR, LOCATION, NULL,
800 			"failed to allocate buffer for myaddrs.\n");
801 		return NULL;
802 	}
803 
804 	/* Copy the whole structure and set the differences.  */
805 	memcpy (new, old, sizeof (*new));
806 	new->addr = dupsaddr (old->addr);
807 	new->next = old->next;
808 	old->next = new;
809 
810 	return new;
811 }
812 
813 void
814 insmyaddr(new, head)
815 	struct myaddrs *new;
816 	struct myaddrs **head;
817 {
818 	new->next = *head;
819 	*head = new;
820 }
821 
822 void
823 delmyaddr(myaddr)
824 	struct myaddrs *myaddr;
825 {
826 	if (myaddr->addr)
827 		racoon_free(myaddr->addr);
828 	racoon_free(myaddr);
829 }
830 
831 int
832 initmyaddr()
833 {
834 	/* initialize routing socket */
835 	lcconf->rtsock = socket(PF_ROUTE, SOCK_RAW, PF_UNSPEC);
836 	if (lcconf->rtsock < 0) {
837 		plog(LLV_ERROR, LOCATION, NULL,
838 			"socket(PF_ROUTE) failed: %s",
839 			strerror(errno));
840 		return -1;
841 	}
842 
843 #ifdef __linux__
844    {
845 	struct sockaddr_nl nl;
846 	u_int addr_len;
847 
848 	memset(&nl, 0, sizeof(nl));
849 	nl.nl_family = AF_NETLINK;
850 	nl.nl_groups = RTMGRP_IPV4_IFADDR|RTMGRP_LINK;
851 
852 	if (bind(lcconf->rtsock, (struct sockaddr*)&nl, sizeof(nl)) < 0) {
853 		plog(LLV_ERROR, LOCATION, NULL,
854 		     "bind(PF_NETLINK) failed: %s\n",
855 		     strerror(errno));
856 		return -1;
857 	}
858 	addr_len = sizeof(nl);
859 	if (getsockname(lcconf->rtsock, (struct sockaddr*)&nl, &addr_len) < 0) {
860 		plog(LLV_ERROR, LOCATION, NULL,
861 		     "getsockname(PF_NETLINK) failed: %s\n",
862 		     strerror(errno));
863 		return -1;
864 	}
865    }
866 #endif
867 
868 	if (lcconf->myaddrs == NULL && lcconf->autograbaddr == 1) {
869 		grab_myaddrs();
870 
871 		if (autoconf_myaddrsport() < 0)
872 			return -1;
873 	}
874 
875 	return 0;
876 }
877 
878 /* select the socket to be sent */
879 /* should implement other method. */
880 int
881 getsockmyaddr(my)
882 	struct sockaddr *my;
883 {
884 	struct myaddrs *p, *lastresort = NULL;
885 #if defined(INET6) && defined(__linux__)
886 	struct myaddrs *match_wo_scope_id = NULL;
887 	int check_wo_scope_id = (my->sa_family == AF_INET6) &&
888 		IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)my)->sin6_addr);
889 #endif
890 
891 	for (p = lcconf->myaddrs; p; p = p->next) {
892 		if (p->addr == NULL)
893 			continue;
894 		if (my->sa_family == p->addr->sa_family) {
895 			lastresort = p;
896 		} else continue;
897 		if (sysdep_sa_len(my) == sysdep_sa_len(p->addr)
898 		 && memcmp(my, p->addr, sysdep_sa_len(my)) == 0) {
899 			break;
900 		}
901 #if defined(INET6) && defined(__linux__)
902 		if (check_wo_scope_id && IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)p->addr)->sin6_addr) &&
903 			/* XXX: this depends on sin6_scope_id to be last
904 			 * item in struct sockaddr_in6 */
905 			memcmp(my, p->addr,
906 				sysdep_sa_len(my) - sizeof(uint32_t)) == 0) {
907 			match_wo_scope_id = p;
908 		}
909 #endif
910 	}
911 #if defined(INET6) && defined(__linux__)
912 	if (!p)
913 		p = match_wo_scope_id;
914 #endif
915 	if (!p)
916 		p = lastresort;
917 	if (!p) {
918 		plog(LLV_ERROR, LOCATION, NULL,
919 			"no socket matches address family %d\n",
920 			my->sa_family);
921 		return -1;
922 	}
923 
924 	return p->sock;
925 }
926