• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
parse_rtattr(struct rtattr * tb[],int max,struct rtattr * rta,int len)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 
recvaddrs(int fd,struct ifaddrs ** ifa,__u32 seq)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 
getifaddrs(struct ifaddrs ** ifa0)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 
freeifaddrs(struct ifaddrs * ifa0)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
if_maxindex()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
clear_myaddr(db)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 *
find_myaddr(db,p)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
grab_myaddrs()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
suitable_ifaddr(ifname,ifaddr)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
suitable_ifaddr6(ifname,ifaddr)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
update_myaddrs()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
autoconf_myaddrsport()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
getmyaddrsport(local)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 *
newmyaddr()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 *
dupmyaddr(struct myaddrs * old)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
insmyaddr(new,head)806 insmyaddr(new, head)
807 	struct myaddrs *new;
808 	struct myaddrs **head;
809 {
810 	new->next = *head;
811 	*head = new;
812 }
813 
814 void
delmyaddr(myaddr)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
initmyaddr()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
getsockmyaddr(my)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