]>
git.saurik.com Git - apple/network_cmds.git/blob - racoon.tproj/grabmyaddr.c
1 /* $KAME: grabmyaddr.c,v 1.35 2003/01/14 07:07:36 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 char addr1
[NI_MAXHOST
];
149 if (getifaddrs(&ifa0
)) {
150 plog(LLV_ERROR
, LOCATION
, NULL
,
151 "getifaddrs failed: %s\n", strerror(errno
));
156 old
= lcconf
->myaddrs
;
158 for (ifap
= ifa0
; ifap
; ifap
= ifap
->ifa_next
) {
160 if (ifap
->ifa_addr
->sa_family
!= AF_INET
162 && ifap
->ifa_addr
->sa_family
!= AF_INET6
167 if (!suitable_ifaddr(ifap
->ifa_name
, ifap
->ifa_addr
)) {
168 plog(LLV_ERROR
, LOCATION
, NULL
,
169 "unsuitable address: %s %s\n",
171 saddrwop2str(ifap
->ifa_addr
));
180 p
->addr
= dupsaddr(ifap
->ifa_addr
);
181 if (p
->addr
== NULL
) {
187 if (ifap
->ifa_addr
->sa_family
== AF_INET6
) {
188 sin6
= (struct sockaddr_in6
*)p
->addr
;
189 if (IN6_IS_ADDR_LINKLOCAL(&sin6
->sin6_addr
)
190 || IN6_IS_ADDR_SITELOCAL(&sin6
->sin6_addr
)) {
191 sin6
->sin6_scope_id
=
192 ntohs(*(u_int16_t
*)&sin6
->sin6_addr
.s6_addr
[2]);
193 sin6
->sin6_addr
.s6_addr
[2] = 0;
194 sin6
->sin6_addr
.s6_addr
[3] = 0;
199 if (getnameinfo(p
->addr
, p
->addr
->sa_len
,
200 addr1
, sizeof(addr1
),
202 NI_NUMERICHOST
| niflags
))
203 strlcpy(addr1
, "(invalid)", sizeof(addr1
));
204 plog(LLV_DEBUG
, LOCATION
, NULL
,
205 "my interface: %s (%s)\n",
206 addr1
, ifap
->ifa_name
);
207 q
= find_myaddr(old
, p
);
211 p
->nattsock
= q
->nattsock
;
219 p
->next
= lcconf
->myaddrs
;
227 #else /*!HAVE_GETIFADDRS*/
231 struct ifreq
*iflist
;
232 struct ifconf ifconf
;
233 struct ifreq
*ifr
, *ifr_end
;
234 struct myaddrs
*p
, *q
, *old
;
237 struct sockaddr_in6
*sin6
;
241 char addr1
[NI_MAXHOST
];
243 maxif
= if_maxindex() + 1;
244 len
= maxif
* sizeof(struct sockaddr_storage
) * 4; /* guess guess */
246 iflist
= (struct ifreq
*)racoon_malloc(len
);
248 plog(LLV_ERROR
, LOCATION
, NULL
,
249 "failed to allocate buffer\n");
254 if ((s
= socket(PF_INET
, SOCK_DGRAM
, 0)) < 0) {
255 plog(LLV_ERROR
, LOCATION
, NULL
,
256 "socket(SOCK_DGRAM) failed: %s\n",
261 memset(&ifconf
, 0, sizeof(ifconf
));
262 ifconf
.ifc_req
= iflist
;
263 ifconf
.ifc_len
= len
;
264 if (ioctl(s
, SIOCGIFCONF
, &ifconf
) < 0) {
265 plog(LLV_ERROR
, LOCATION
, NULL
,
266 "ioctl(SIOCGIFCONF) failed: %s\n",
273 old
= lcconf
->myaddrs
;
275 /* Look for this interface in the list */
276 ifr_end
= (struct ifreq
*) (ifconf
.ifc_buf
+ ifconf
.ifc_len
);
278 #define _IFREQ_LEN(p) \
279 (sizeof((p)->ifr_name) + (p)->ifr_addr.sa_len > sizeof(struct ifreq) \
280 ? sizeof((p)->ifr_name) + (p)->ifr_addr.sa_len : sizeof(struct ifreq))
282 for (ifr
= ifconf
.ifc_req
;
284 ifr
= (struct ifreq
*)((caddr_t
)ifr
+ _IFREQ_LEN(ifr
))) {
286 switch (ifr
->ifr_addr
.sa_family
) {
291 if (!suitable_ifaddr(ifr
->ifr_name
, &ifr
->ifr_addr
)) {
292 plog(LLV_ERROR
, LOCATION
, NULL
,
293 "unsuitable address: %s %s\n",
295 saddrwop2str(&ifr
->ifr_addr
));
304 p
->addr
= dupsaddr(&ifr
->ifr_addr
);
305 if (p
->addr
== NULL
) {
311 sin6
= (struct sockaddr_in6
*)p
->addr
;
312 if (IN6_IS_ADDR_LINKLOCAL(&sin6
->sin6_addr
)
313 || IN6_IS_ADDR_SITELOCAL(&sin6
->sin6_addr
)) {
314 sin6
->sin6_scope_id
=
315 ntohs(*(u_int16_t
*)&sin6
->sin6_addr
.s6_addr
[2]);
316 sin6
->sin6_addr
.s6_addr
[2] = 0;
317 sin6
->sin6_addr
.s6_addr
[3] = 0;
321 if (getnameinfo(p
->addr
, p
->addr
->sa_len
,
322 addr1
, sizeof(addr1
),
324 NI_NUMERICHOST
| niflags
))
325 strlcpy(addr1
, "(invalid)", sizeof(addr1
));
326 plog(LLV_DEBUG
, LOCATION
, NULL
,
327 "my interface: %s (%s)\n",
328 addr1
, ifr
->ifr_name
);
329 q
= find_myaddr(old
, p
);
334 p
->next
= lcconf
->myaddrs
;
345 #endif /*HAVE_GETIFADDRS*/
349 * check the interface is suitable or not
352 suitable_ifaddr(ifname
, ifaddr
)
354 const struct sockaddr
*ifaddr
;
356 switch(ifaddr
->sa_family
) {
361 return suitable_ifaddr6(ifname
, ifaddr
);
371 suitable_ifaddr6(ifname
, ifaddr
)
373 const struct sockaddr
*ifaddr
;
375 struct in6_ifreq ifr6
;
378 if (ifaddr
->sa_family
!= AF_INET6
)
381 s
= socket(PF_INET6
, SOCK_DGRAM
, 0);
383 plog(LLV_ERROR
, LOCATION
, NULL
,
384 "socket(SOCK_DGRAM) failed:%s\n", strerror(errno
));
388 memset(&ifr6
, 0, sizeof(ifr6
));
389 strncpy(ifr6
.ifr_name
, ifname
, strlen(ifname
));
391 ifr6
.ifr_addr
= *(const struct sockaddr_in6
*)ifaddr
;
393 if (ioctl(s
, SIOCGIFAFLAG_IN6
, &ifr6
) < 0) {
394 plog(LLV_ERROR
, LOCATION
, NULL
,
395 "ioctl(SIOCGIFAFLAG_IN6) failed:%s\n", strerror(errno
));
402 if (ifr6
.ifr_ifru
.ifru_flags6
& IN6_IFF_DUPLICATED
403 || ifr6
.ifr_ifru
.ifru_flags6
& IN6_IFF_DETACHED
)
416 struct rt_msghdr
*rtm
;
418 len
= read(lcconf
->rtsock
, msg
, sizeof(msg
));
420 plog(LLV_ERROR
, LOCATION
, NULL
,
421 "read(PF_ROUTE) failed: %s\n",
425 rtm
= (struct rt_msghdr
*)msg
;
426 if (len
< rtm
->rtm_msglen
) {
427 plog(LLV_ERROR
, LOCATION
, NULL
,
428 "read(PF_ROUTE) short read\n");
431 if (rtm
->rtm_version
!= RTM_VERSION
) {
432 plog(LLV_ERROR
, LOCATION
, NULL
,
433 "routing socket version mismatch\n");
434 close(lcconf
->rtsock
);
438 switch (rtm
->rtm_type
) {
445 /* ignore this message silently */
448 plog(LLV_DEBUG
, LOCATION
, NULL
,
449 "msg %d not interesting\n", rtm
->rtm_type
);
452 /* XXX more filters here? */
454 plog(LLV_DEBUG
, LOCATION
, NULL
,
455 "caught rtm:%d, need update interface address list\n",
461 * initialize default port for ISAKMP to send, if no "listen"
462 * directive is specified in config file.
464 * DO NOT listen to wildcard addresses. if you receive packets to
465 * wildcard address, you'll be in trouble (DoS attack possible by
469 autoconf_myaddrsport()
472 struct sockaddr_in
*sin4
;
474 struct sockaddr_in6
*sin6
;
478 plog(LLV_DEBUG
, LOCATION
, NULL
,
479 "configuring default isakmp port.\n");
481 for (p
= lcconf
->myaddrs
; p
; p
= p
->next
) {
482 switch (p
->addr
->sa_family
) {
484 sin4
= (struct sockaddr_in
*)p
->addr
;
485 sin4
->sin_port
= htons(lcconf
->port_isakmp
);
489 sin6
= (struct sockaddr_in6
*)p
->addr
;
490 sin6
->sin6_port
= htons(lcconf
->port_isakmp
);
494 plog(LLV_ERROR
, LOCATION
, NULL
,
495 "unsupported AF %d\n", p
->addr
->sa_family
);
500 plog(LLV_DEBUG
, LOCATION
, NULL
,
501 "%d addrs are configured successfully\n", n
);
505 plog(LLV_ERROR
, LOCATION
, NULL
, "address autoconfiguration failed\n");
510 * get a port number to which racoon binded.
511 * NOTE: network byte order returned.
514 getmyaddrsport(local
)
515 struct sockaddr
*local
;
519 /* get a relative port */
520 for (p
= lcconf
->myaddrs
; p
; p
= p
->next
) {
523 if (!cmpsaddrwop(local
, p
->addr
)) {
524 switch (p
->addr
->sa_family
) {
526 return ((struct sockaddr_in
*)p
->addr
)->sin_port
;
529 return ((struct sockaddr_in6
*)p
->addr
)->sin6_port
;
532 plog(LLV_ERROR
, LOCATION
, NULL
,
533 "invalid family: %d\n",
541 return htons(PORT_ISAKMP
);
549 new = racoon_calloc(1, sizeof(*new));
551 plog(LLV_ERROR
, LOCATION
, NULL
,
552 "failed to allocate buffer for myaddrs.\n");
565 struct myaddrs
**head
;
573 struct myaddrs
*myaddr
;
576 racoon_free(myaddr
->addr
);
583 /* initialize routing socket */
584 lcconf
->rtsock
= socket(PF_ROUTE
, SOCK_RAW
, PF_UNSPEC
);
585 if (lcconf
->rtsock
< 0) {
586 plog(LLV_ERROR
, LOCATION
, NULL
,
587 "socket(PF_ROUTE) failed: %s",
592 if (lcconf
->myaddrs
== NULL
&& lcconf
->autograbaddr
== 1) {
595 if (autoconf_myaddrsport() < 0)
602 /* select the socket to be sent */
603 /* should implement other method. */
608 struct myaddrs
*p
, *lastresort
= NULL
;
610 for (p
= lcconf
->myaddrs
; p
; p
= p
->next
) {
613 if (my
->sa_family
== p
->addr
->sa_family
)
615 if (my
->sa_len
== p
->addr
->sa_len
616 && memcmp(my
, p
->addr
, my
->sa_len
) == 0) {
620 if (my
->sa_family
== p
->addr
->sa_family
&&
621 my
->sa_family
== AF_INET
&&
622 ((struct sockaddr_in
*)my
)->sin_addr
.s_addr
==
623 ((struct sockaddr_in
*)p
->addr
)->sin_addr
.s_addr
&&
624 ((struct sockaddr_in
*)my
)->sin_port
== htons(PORT_ISAKMP_NATT
))
626 plog(LLV_DEBUG
, LOCATION
, NULL
,
627 "picked natt socket (%d - %s) for sending\n",
628 p
->nattsock
, saddr2str(my
));
636 plog(LLV_ERROR
, LOCATION
, NULL
,
637 "no socket matches address family %d\n",