]>
git.saurik.com Git - apple/network_cmds.git/blob - racoon.tproj/grabmyaddr.c
1 /* $KAME: grabmyaddr.c,v 1.28 2001/12/12 15:29:12 sakane Exp $ */
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/socket.h>
35 #include <sys/ioctl.h>
38 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
39 #include <net/if_var.h>
41 #include <net/route.h>
42 #include <netkey/key_var.h>
43 #include <netinet/in.h>
44 #include <netinet6/in6_var.h>
54 #ifdef HAVE_GETIFADDRS
65 #include "localconf.h"
66 #include "grabmyaddr.h"
68 #include "isakmp_var.h"
71 #ifndef HAVE_GETIFADDRS
72 static unsigned int if_maxindex
__P((void));
74 static struct myaddrs
*find_myaddr
__P((struct myaddrs
*, struct myaddrs
*));
75 static int suitable_ifaddr
__P((const char *, const struct sockaddr
*));
77 static int suitable_ifaddr6
__P((const char *, const struct sockaddr
*));
80 #ifndef HAVE_GETIFADDRS
84 struct if_nameindex
*p
, *p0
;
88 for (p
= p0
; p
&& p
->if_index
&& p
->if_name
; p
++) {
89 if (max
< p
->if_index
)
110 static struct myaddrs
*
116 char h1
[NI_MAXHOST
], h2
[NI_MAXHOST
];
118 if (getnameinfo(p
->addr
, p
->addr
->sa_len
, h1
, sizeof(h1
), NULL
, 0,
119 NI_NUMERICHOST
| niflags
) != 0)
122 for (q
= db
; q
; q
= q
->next
) {
123 if (p
->addr
->sa_len
!= q
->addr
->sa_len
)
125 if (getnameinfo(q
->addr
, q
->addr
->sa_len
, h2
, sizeof(h2
),
126 NULL
, 0, NI_NUMERICHOST
| niflags
) != 0)
128 if (strcmp(h1
, h2
) == 0)
138 #ifdef HAVE_GETIFADDRS
139 struct myaddrs
*p
, *q
, *old
;
140 struct ifaddrs
*ifa0
, *ifap
;
143 struct sockaddr_in6
*sin6
;
147 #if defined(YIPS_DEBUG)
148 char _addr1_
[NI_MAXHOST
];
151 if (getifaddrs(&ifa0
)) {
152 plog(LLV_ERROR
, LOCATION
, NULL
,
153 "getifaddrs failed: %s\n", strerror(errno
));
158 old
= lcconf
->myaddrs
;
160 for (ifap
= ifa0
; ifap
; ifap
= ifap
->ifa_next
) {
162 if (ifap
->ifa_addr
->sa_family
!= AF_INET
164 && ifap
->ifa_addr
->sa_family
!= AF_INET6
169 if (!suitable_ifaddr(ifap
->ifa_name
, ifap
->ifa_addr
)) {
170 plog(LLV_ERROR
, LOCATION
, NULL
,
171 "unsuitable ifaddr: %s\n",
172 saddr2str(ifap
->ifa_addr
));
181 p
->addr
= dupsaddr(ifap
->ifa_addr
);
182 if (p
->addr
== NULL
) {
188 if (ifap
->ifa_addr
->sa_family
== AF_INET6
) {
189 sin6
= (struct sockaddr_in6
*)p
->addr
;
190 if (IN6_IS_ADDR_LINKLOCAL(&sin6
->sin6_addr
)
191 || IN6_IS_ADDR_SITELOCAL(&sin6
->sin6_addr
)) {
192 sin6
->sin6_scope_id
=
193 ntohs(*(u_int16_t
*)&sin6
->sin6_addr
.s6_addr
[2]);
194 sin6
->sin6_addr
.s6_addr
[2] = 0;
195 sin6
->sin6_addr
.s6_addr
[3] = 0;
200 if (getnameinfo(p
->addr
, p
->addr
->sa_len
,
201 _addr1_
, sizeof(_addr1_
),
203 NI_NUMERICHOST
| niflags
))
204 strcpy(_addr1_
, "(invalid)");
205 plog(LLV_DEBUG
, LOCATION
, NULL
,
206 "my interface: %s (%s)\n",
207 _addr1_
, ifap
->ifa_name
);
208 q
= find_myaddr(old
, p
);
213 p
->next
= lcconf
->myaddrs
;
221 #else /*!HAVE_GETIFADDRS*/
225 struct ifreq
*iflist
;
226 struct ifconf ifconf
;
227 struct ifreq
*ifr
, *ifr_end
;
228 struct myaddrs
*p
, *q
, *old
;
231 struct sockaddr_in6
*sin6
;
235 #if defined(YIPS_DEBUG)
236 char _addr1_
[NI_MAXHOST
];
239 maxif
= if_maxindex() + 1;
240 len
= maxif
* sizeof(struct sockaddr_storage
) * 4; /* guess guess */
242 iflist
= (struct ifreq
*)racoon_malloc(len
);
244 plog(LLV_ERROR
, LOCATION
, NULL
,
245 "failed to allocate buffer\n");
250 if ((s
= socket(PF_INET
, SOCK_DGRAM
, 0)) < 0) {
251 plog(LLV_ERROR
, LOCATION
, NULL
,
252 "socket(SOCK_DGRAM) failed: %s\n",
257 memset(&ifconf
, 0, sizeof(ifconf
));
258 ifconf
.ifc_req
= iflist
;
259 ifconf
.ifc_len
= len
;
260 if (ioctl(s
, SIOCGIFCONF
, &ifconf
) < 0) {
261 plog(LLV_ERROR
, LOCATION
, NULL
,
262 "ioctl(SIOCGIFCONF) failed: %s\n",
269 old
= lcconf
->myaddrs
;
271 /* Look for this interface in the list */
272 ifr_end
= (struct ifreq
*) (ifconf
.ifc_buf
+ ifconf
.ifc_len
);
274 #define _IFREQ_LEN(p) \
275 (sizeof((p)->ifr_name) + (p)->ifr_addr.sa_len > sizeof(struct ifreq) \
276 ? sizeof((p)->ifr_name) + (p)->ifr_addr.sa_len : sizeof(struct ifreq))
278 for (ifr
= ifconf
.ifc_req
;
280 ifr
= (struct ifreq
*)((caddr_t
)ifr
+ _IFREQ_LEN(ifr
))) {
282 switch (ifr
->ifr_addr
.sa_family
) {
287 if (!suitable_ifaddr(ifr
->ifr_name
, &ifr
->ifr_addr
)) {
288 plog(LLV_DEBUG
, LOCATION
, NULL
,
289 "unsuitable ifaddr %s\n");
298 p
->addr
= dupsaddr(&ifr
->ifr_addr
);
299 if (p
->addr
== NULL
) {
305 sin6
= (struct sockaddr_in6
*)p
->addr
;
306 if (IN6_IS_ADDR_LINKLOCAL(&sin6
->sin6_addr
)
307 || IN6_IS_ADDR_SITELOCAL(&sin6
->sin6_addr
)) {
308 sin6
->sin6_scope_id
=
309 ntohs(*(u_int16_t
*)&sin6
->sin6_addr
.s6_addr
[2]);
310 sin6
->sin6_addr
.s6_addr
[2] = 0;
311 sin6
->sin6_addr
.s6_addr
[3] = 0;
315 if (getnameinfo(p
->addr
, p
->addr
->sa_len
,
316 _addr1_
, sizeof(_addr1_
),
318 NI_NUMERICHOST
| niflags
))
319 strcpy(_addr1_
, "(invalid)");
320 plog(LLV_DEBUG
, LOCATION
, NULL
,
321 "my interface: %s (%s)\n",
322 _addr1_
, ifr
->ifr_name
);
323 q
= find_myaddr(old
, p
);
328 p
->next
= lcconf
->myaddrs
;
339 #endif /*HAVE_GETIFADDRS*/
343 * check the interface is suitable or not
346 suitable_ifaddr(ifname
, ifaddr
)
348 const struct sockaddr
*ifaddr
;
350 switch(ifaddr
->sa_family
) {
355 return suitable_ifaddr6(ifname
, ifaddr
);
365 suitable_ifaddr6(ifname
, ifaddr
)
367 const struct sockaddr
*ifaddr
;
369 struct in6_ifreq ifr6
;
372 if (ifaddr
->sa_family
!= AF_INET6
)
375 s
= socket(PF_INET6
, SOCK_DGRAM
, 0);
377 plog(LLV_ERROR
, LOCATION
, NULL
,
378 "socket(SOCK_DGRAM) failed:%s\n", strerror(errno
));
382 memset(&ifr6
, 0, sizeof(ifr6
));
383 strncpy(ifr6
.ifr_name
, ifname
, strlen(ifname
));
385 ifr6
.ifr_addr
= *(const struct sockaddr_in6
*)ifaddr
;
387 if (ioctl(s
, SIOCGIFAFLAG_IN6
, &ifr6
) < 0) {
388 plog(LLV_ERROR
, LOCATION
, NULL
,
389 "ioctl(SIOCGIFAFLAG_IN6) failed:%s\n", strerror(errno
));
396 if (ifr6
.ifr_ifru
.ifru_flags6
& IN6_IFF_DUPLICATED
397 || ifr6
.ifr_ifru
.ifru_flags6
& IN6_IFF_DETACHED
)
410 struct rt_msghdr
*rtm
;
412 len
= read(lcconf
->rtsock
, msg
, sizeof(msg
));
414 plog(LLV_ERROR
, LOCATION
, NULL
,
415 "read(PF_ROUTE) failed: %s\n",
419 rtm
= (struct rt_msghdr
*)msg
;
420 if (len
< rtm
->rtm_msglen
) {
421 plog(LLV_ERROR
, LOCATION
, NULL
,
422 "read(PF_ROUTE) short read\n");
425 if (rtm
->rtm_version
!= RTM_VERSION
) {
426 plog(LLV_ERROR
, LOCATION
, NULL
,
427 "routing socket version mismatch\n");
428 close(lcconf
->rtsock
);
432 switch (rtm
->rtm_type
) {
439 /* ignore this message silently */
442 plog(LLV_DEBUG
, LOCATION
, NULL
,
443 "msg %d not interesting\n", rtm
->rtm_type
);
446 /* XXX more filters here? */
448 plog(LLV_DEBUG
, LOCATION
, NULL
,
449 "caught rtm:%d, need update interface address list\n",
455 * initialize default port for ISAKMP to send, if no "listen"
456 * directive is specified in config file.
458 * DO NOT listen to wildcard addresses. if you receive packets to
459 * wildcard address, you'll be in trouble (DoS attack possible by
463 autoconf_myaddrsport()
466 struct sockaddr_in
*sin4
;
468 struct sockaddr_in6
*sin6
;
472 plog(LLV_DEBUG
, LOCATION
, NULL
,
473 "configuring default isakmp port.\n");
475 for (p
= lcconf
->myaddrs
; p
; p
= p
->next
) {
476 switch (p
->addr
->sa_family
) {
478 sin4
= (struct sockaddr_in
*)p
->addr
;
479 sin4
->sin_port
= htons(lcconf
->port_isakmp
);
483 sin6
= (struct sockaddr_in6
*)p
->addr
;
484 sin6
->sin6_port
= htons(lcconf
->port_isakmp
);
488 plog(LLV_ERROR
, LOCATION
, NULL
,
489 "unsupported AF %d\n", p
->addr
->sa_family
);
494 plog(LLV_DEBUG
, LOCATION
, NULL
,
495 "%d addrs are configured successfully\n", n
);
499 plog(LLV_ERROR
, LOCATION
, NULL
, "address autoconfiguration failed\n");
504 * get a port number to which racoon binded.
505 * NOTE: network byte order returned.
508 getmyaddrsport(local
)
509 struct sockaddr
*local
;
513 /* get a relative port */
514 for (p
= lcconf
->myaddrs
; p
; p
= p
->next
) {
517 if (!cmpsaddrwop(local
, p
->addr
)) {
518 switch (p
->addr
->sa_family
) {
520 return ((struct sockaddr_in
*)p
->addr
)->sin_port
;
523 return ((struct sockaddr_in6
*)p
->addr
)->sin6_port
;
526 plog(LLV_ERROR
, LOCATION
, NULL
,
527 "invalid family: %d\n",
535 return htons(PORT_ISAKMP
);
543 new = racoon_calloc(1, sizeof(*new));
545 plog(LLV_ERROR
, LOCATION
, NULL
,
546 "failed to allocate buffer for myaddrs.\n");
559 struct myaddrs
**head
;
567 struct myaddrs
*myaddr
;
570 racoon_free(myaddr
->addr
);
577 /* initialize routing socket */
578 lcconf
->rtsock
= socket(PF_ROUTE
, SOCK_RAW
, PF_UNSPEC
);
579 if (lcconf
->rtsock
< 0) {
580 plog(LLV_ERROR
, LOCATION
, NULL
,
581 "socket(PF_ROUTE) failed: %s",
586 if (lcconf
->myaddrs
== NULL
&& lcconf
->autograbaddr
== 1) {
589 if (autoconf_myaddrsport() < 0)
596 /* select the socket to be sent */
597 /* should implement other method. */
602 struct myaddrs
*p
, *lastresort
= NULL
;
604 for (p
= lcconf
->myaddrs
; p
; p
= p
->next
) {
607 if (my
->sa_family
== p
->addr
->sa_family
)
609 if (my
->sa_len
== p
->addr
->sa_len
610 && memcmp(my
, p
->addr
, my
->sa_len
) == 0) {
617 plog(LLV_ERROR
, LOCATION
, NULL
,
618 "no socket matches address family %d\n",