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