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