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