]>
git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/grabmyaddr.c
1 /* $Id: grabmyaddr.c,v 1.23.4.2 2005/07/16 04:41:01 monas 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
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
37 #include <sys/ioctl.h>
40 #include <net/if_var.h>
41 #include <netinet/in.h>
42 #include <netinet6/in6_var.h>
43 #include <net/route.h>
53 #ifdef HAVE_GETIFADDRS
66 #include "localconf.h"
68 #include "grabmyaddr.h"
70 #include "isakmp_var.h"
72 #include "nattraversal.h"
74 #ifndef HAVE_GETIFADDRS
75 static unsigned int if_maxindex
__P((void));
78 static int suitable_ifaddr
__P((const char *, const struct sockaddr
*));
80 static int suitable_ifaddr6
__P((const char *, const struct sockaddr
*));
83 #ifndef HAVE_GETIFADDRS
87 struct if_nameindex
*p
, *p0
;
91 for (p
= p0
; p
&& p
->if_index
&& p
->if_name
; p
++) {
92 if (max
< p
->if_index
)
104 struct myaddrs
*p
, *next
;
106 for (p
= lcconf
->myaddrs
; p
; p
= next
) {
112 lcconf
->myaddrs
= NULL
;
118 find_myaddr(addr
, udp_encap
)
119 struct sockaddr
*addr
;
123 char h1
[NI_MAXHOST
], h2
[NI_MAXHOST
];
125 if (getnameinfo(addr
, sysdep_sa_len(addr
), h1
, sizeof(h1
), NULL
, 0,
126 NI_NUMERICHOST
| niflags
) != 0)
129 for (q
= lcconf
->myaddrs
; q
; q
= q
->next
) {
132 if (q
->udp_encap
&& !udp_encap
133 || !q
->udp_encap
&& udp_encap
)
135 if (addr
->sa_family
!= q
->addr
->ss_family
)
137 if (getnameinfo((struct sockaddr
*)q
->addr
, sysdep_sa_len((struct sockaddr
*)q
->addr
), h2
, sizeof(h2
),
138 NULL
, 0, NI_NUMERICHOST
| niflags
) != 0)
140 if (strcmp(h1
, h2
) == 0)
148 // modified to avoid closing and opening sockets for
149 // all interfaces each time an interface change occurs.
150 // on return: addrcount = zero indicates address no longer used
151 // sock = -1 indicates a new address - no socket opened yet.
155 #ifdef HAVE_GETIFADDRS
156 struct myaddrs
*p
, *q
;
157 struct ifaddrs
*ifa0
, *ifap
;
159 char addr1
[NI_MAXHOST
];
161 if (getifaddrs(&ifa0
)) {
162 plog(LLV_ERROR2
, LOCATION
, NULL
,
163 "getifaddrs failed: %s\n", strerror(errno
));
168 // clear the in_use flag for each address in the list
169 for (p
= lcconf
->myaddrs
; p
; p
= p
->next
)
172 for (ifap
= ifa0
; ifap
; ifap
= ifap
->ifa_next
) {
174 if (ifap
->ifa_addr
->sa_family
!= AF_INET
176 && ifap
->ifa_addr
->sa_family
!= AF_INET6
181 if (!suitable_ifaddr(ifap
->ifa_name
, ifap
->ifa_addr
)) {
182 plog(LLV_DEBUG2
, LOCATION
, NULL
,
183 "unsuitable address: %s %s\n",
185 saddrwop2str(ifap
->ifa_addr
));
189 p
= find_myaddr(ifap
->ifa_addr
, 0);
193 q
= find_myaddr(ifap
->ifa_addr
, 1);
200 plog(LLV_ERROR2
, LOCATION
, NULL
,
201 "unable to allocate space for addr.\n");
205 p
->addr
= dupsaddr(ifap
->ifa_addr
);
206 if (p
->addr
== NULL
) {
207 plog(LLV_ERROR2
, LOCATION
, NULL
,
208 "unable to duplicate addr.\n");
212 p
->ifname
= racoon_strdup(ifap
->ifa_name
);
213 if (p
->ifname
== NULL
) {
214 plog(LLV_ERROR2
, LOCATION
, NULL
,
215 "unable to duplicate ifname.\n");
223 if (getnameinfo((struct sockaddr
*)p
->addr
, p
->addr
->ss_len
,
224 addr1
, sizeof(addr1
),
226 NI_NUMERICHOST
| niflags
))
227 strlcpy(addr1
, "(invalid)", sizeof(addr1
));
228 plog(LLV_DEBUG
, LOCATION
, NULL
,
229 "my interface: %s (%s)\n",
230 addr1
, ifap
->ifa_name
);
232 p
->next
= lcconf
->myaddrs
;
236 if (natt_enabled_in_rmconf ()) {
239 plog(LLV_ERROR2
, LOCATION
, NULL
,
240 "unable to allocate space for natt addr.\n");
253 #else /*!HAVE_GETIFADDRS*/
254 #error "NOT SUPPORTED"
255 #endif /*HAVE_GETIFADDRS*/
260 * check the interface is suitable or not
263 suitable_ifaddr(ifname
, ifaddr
)
265 const struct sockaddr
*ifaddr
;
267 #if 0 //we need to be able to do nested ipsec for BTMM... stub out ifdef ENABLE_HYBRID
268 /* Exclude any address we got through ISAKMP mode config */
269 if (exclude_cfg_addr(ifaddr
) == 0)
272 switch(ifaddr
->sa_family
) {
277 return suitable_ifaddr6(ifname
, ifaddr
);
287 suitable_ifaddr6(ifname
, ifaddr
)
289 const struct sockaddr
*ifaddr
;
291 struct in6_ifreq ifr6
;
294 if (ifaddr
->sa_family
!= AF_INET6
)
297 s
= socket(PF_INET6
, SOCK_DGRAM
, 0);
299 plog(LLV_ERROR
, LOCATION
, NULL
,
300 "socket(SOCK_DGRAM) failed:%s\n", strerror(errno
));
304 if (fcntl(s
, F_SETFL
, O_NONBLOCK
) == -1) {
305 plog(LLV_ERROR
, LOCATION
, NULL
,
306 "failed to put IPv6 socket in non-blocking mode\n");
309 memset(&ifr6
, 0, sizeof(ifr6
));
310 strlcpy(ifr6
.ifr_name
, ifname
, sizeof(ifr6
.ifr_name
));
312 memcpy(&ifr6
.ifr_addr
, ifaddr
, sizeof(struct sockaddr_in6
)); // Wcast-align fix - copy instread of assign with cast
314 if (ioctl(s
, SIOCGIFAFLAG_IN6
, &ifr6
) < 0) {
315 plog(LLV_ERROR
, LOCATION
, NULL
,
316 "ioctl(SIOCGIFAFLAG_IN6) failed:%s\n", strerror(errno
));
323 if (ifr6
.ifr_ifru
.ifru_flags6
& IN6_IFF_DUPLICATED
324 || ifr6
.ifr_ifru
.ifru_flags6
& IN6_IFF_DETACHED
325 || ifr6
.ifr_ifru
.ifru_flags6
& IN6_IFF_ANYCAST
)
336 struct rtmessage
{ // Wcast-align fix - force alignment
337 struct rt_msghdr rtm
;
338 char discard
[BUFSIZ
];
343 while((len
= read(lcconf
->rtsock
, &msg
, sizeof(msg
))) < 0) {
346 plog(LLV_ERROR
, LOCATION
, NULL
,
347 "read(PF_ROUTE) failed: %s\n",
351 if (len
< msg
.rtm
.rtm_msglen
) {
352 plog(LLV_ERROR
, LOCATION
, NULL
,
353 "read(PF_ROUTE) short read\n");
356 if (msg
.rtm
.rtm_version
!= RTM_VERSION
) {
357 plog(LLV_ERROR
, LOCATION
, NULL
,
358 "routing socket version mismatch\n");
359 close(lcconf
->rtsock
);
363 switch (msg
.rtm
.rtm_type
) {
370 /* ignore this message silently */
373 //plog(LLV_DEBUG, LOCATION, NULL,
374 // "msg %d not interesting\n", msg.rtm.rtm_type);
377 /* XXX more filters here? */
379 //plog(LLV_DEBUG, LOCATION, NULL,
380 // "caught rtm:%d, need update interface address list\n",
381 // msg.rtm.rtm_type);
387 * initialize default port for ISAKMP to send, if no "listen"
388 * directive is specified in config file.
390 * DO NOT listen to wildcard addresses. if you receive packets to
391 * wildcard address, you'll be in trouble (DoS attack possible by
395 autoconf_myaddrsport()
400 plog(LLV_DEBUG
, LOCATION
, NULL
,
401 "configuring default isakmp port.\n");
403 for (p
= lcconf
->myaddrs
, n
= 0; p
; p
= p
->next
, n
++) {
404 set_port (p
->addr
, p
->udp_encap
? lcconf
->port_isakmp_natt
: lcconf
->port_isakmp
);
406 plog(LLV_DEBUG
, LOCATION
, NULL
,
407 "%d addrs are configured successfully\n", n
);
413 * get a port number to which racoon binded.
414 * NOTE: network byte order returned.
417 getmyaddrsport(local
)
418 struct sockaddr_storage
*local
;
420 struct myaddrs
*p
, *bestmatch
= NULL
;
421 u_short bestmatch_port
= PORT_ISAKMP
;
423 /* get a relative port */
424 for (p
= lcconf
->myaddrs
; p
; p
= p
->next
) {
427 if (!cmpsaddrwop(local
, p
->addr
)) {
433 switch (p
->addr
->ss_family
) {
435 if (((struct sockaddr_in
*)p
->addr
)->sin_port
== PORT_ISAKMP
) {
437 bestmatch_port
= ((struct sockaddr_in
*)p
->addr
)->sin_port
;
443 if (((struct sockaddr_in6
*)p
->addr
)->sin6_port
== PORT_ISAKMP
) {
445 bestmatch_port
= ((struct sockaddr_in6
*)p
->addr
)->sin6_port
;
451 plog(LLV_ERROR
, LOCATION
, NULL
,
452 "unsupported AF %d\n", p
->addr
->ss_family
);
458 return htons(bestmatch_port
);
466 new = racoon_calloc(1, sizeof(*new));
468 plog(LLV_ERROR
, LOCATION
, NULL
,
469 "failed to allocate buffer for myaddrs.\n");
483 dupmyaddr(struct myaddrs
*old
)
487 new = racoon_calloc(1, sizeof(*new));
489 plog(LLV_ERROR
, LOCATION
, NULL
,
490 "failed to allocate buffer for myaddrs.\n");
494 /* Copy the whole structure and set the differences. */
495 memcpy (new, old
, sizeof (*new));
496 new->addr
= dupsaddr ((struct sockaddr
*)old
->addr
);
497 if (new->addr
== NULL
) {
498 plog(LLV_ERROR
, LOCATION
, NULL
,
499 "failed to allocate buffer for duplicate addr.\n");
504 new->ifname
= racoon_strdup(old
->ifname
);
505 if (new->ifname
== NULL
) {
506 plog(LLV_ERROR
, LOCATION
, NULL
,
507 "failed to allocate buffer for duplicate ifname.\n");
508 racoon_free(new->addr
);
514 new->next
= old
->next
;
523 struct myaddrs
**head
;
531 struct myaddrs
*myaddr
;
534 racoon_free(myaddr
->addr
);
536 racoon_free(myaddr
->ifname
);
543 /* initialize routing socket */
544 lcconf
->rtsock
= socket(PF_ROUTE
, SOCK_RAW
, PF_UNSPEC
);
545 if (lcconf
->rtsock
< 0) {
546 plog(LLV_ERROR
, LOCATION
, NULL
,
547 "socket(PF_ROUTE) failed: %s",
552 if (fcntl(lcconf
->rtsock
, F_SETFL
, O_NONBLOCK
) == -1) {
553 plog(LLV_ERROR
, LOCATION
, NULL
,
554 "failed to put PF_ROUTE socket in non-blocking mode\n");
557 if (lcconf
->myaddrs
== NULL
&& lcconf
->autograbaddr
== 1) {
560 if (autoconf_myaddrsport() < 0)
567 /* select the socket to be sent */
568 /* should implement other method. */
573 struct myaddrs
*p
, *lastresort
= NULL
;
575 for (p
= lcconf
->myaddrs
; p
; p
= p
->next
) {
578 if (my
->sa_family
== p
->addr
->ss_family
) {
581 if (sysdep_sa_len(my
) == sysdep_sa_len((struct sockaddr
*)p
->addr
)
582 && memcmp(my
, p
->addr
, sysdep_sa_len(my
)) == 0) {
589 plog(LLV_ERROR
, LOCATION
, NULL
,
590 "no socket matches address family %d\n",