]> git.saurik.com Git - apple/ipsec.git/blobdiff - ipsec-tools/racoon/grabmyaddr.c
ipsec-164.10.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / grabmyaddr.c
index 6afc4ef724d36f288c42bcab1fb50e5576f3f466..66f2457f17abfe7675246fbf835371d219e81b2f 100644 (file)
 #include <sys/ioctl.h>
 
 #include <net/if.h>
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
 #include <net/if_var.h>
-#endif
-#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__APPLE__)
 #include <netinet/in.h>
 #include <netinet6/in6_var.h>
-#endif
 #include <net/route.h>
 
 #include <stdlib.h>
@@ -58,6 +54,7 @@
 #include <ifaddrs.h>
 #include <net/if.h>
 #endif 
+#include <fcntl.h>
 
 #include "var.h"
 #include "misc.h"
 #include "gcmalloc.h"
 #include "nattraversal.h"
 
-#ifdef __linux__
-#include <linux/types.h>
-#include <linux/rtnetlink.h>
-#ifndef HAVE_GETIFADDRS
-#define HAVE_GETIFADDRS
-#define NEED_LINUX_GETIFADDRS
-#endif
-#endif
-
 #ifndef HAVE_GETIFADDRS
 static unsigned int if_maxindex __P((void));
 #endif
@@ -92,184 +80,6 @@ static int suitable_ifaddr __P((const char *, const struct sockaddr *));
 static int suitable_ifaddr6 __P((const char *, const struct sockaddr *));
 #endif
 
-#ifdef NEED_LINUX_GETIFADDRS
-
-/* We could do this _much_ better. kame racoon in its current form
- * will esentially die at frequent changes of address configuration.
- */
-
-struct ifaddrs
-{
-       struct ifaddrs *ifa_next;
-       char            ifa_name[16];
-       int             ifa_ifindex;
-       struct sockaddr *ifa_addr;
-       struct sockaddr_storage ifa_addrbuf;
-};
-
-static int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
-{
-       while (RTA_OK(rta, len)) {
-               if (rta->rta_type <= max)
-                       tb[rta->rta_type] = rta;
-               rta = RTA_NEXT(rta,len);
-       }
-       return 0;
-}
-
-static void recvaddrs(int fd, struct ifaddrs **ifa, __u32 seq)
-{
-       char    buf[8192];
-       struct sockaddr_nl nladdr;
-       struct iovec iov = { buf, sizeof(buf) };
-       struct ifaddrmsg *m;
-       struct rtattr * rta_tb[IFA_MAX+1];
-       struct ifaddrs *I;
-
-       while (1) {
-               int status;
-               struct nlmsghdr *h;
-
-               struct msghdr msg = {
-                       (void*)&nladdr, sizeof(nladdr),
-                       &iov,   1,
-                       NULL,   0,
-                       0
-               };
-
-               status = recvmsg(fd, &msg, 0);
-
-               if (status < 0)
-                       continue;
-
-               if (status == 0)
-                       return;
-
-               if (nladdr.nl_pid) /* Message not from kernel */
-                       continue;
-
-               h = (struct nlmsghdr*)buf;
-               while (NLMSG_OK(h, status)) {
-                       if (h->nlmsg_seq != seq)
-                               goto skip_it;
-
-                       if (h->nlmsg_type == NLMSG_DONE)
-                               return;
-
-                       if (h->nlmsg_type == NLMSG_ERROR)
-                               return;
-
-                       if (h->nlmsg_type != RTM_NEWADDR)
-                               goto skip_it;
-
-                       m = NLMSG_DATA(h);
-
-                       if (m->ifa_family != AF_INET &&
-                           m->ifa_family != AF_INET6)
-                               goto skip_it;
-
-                       if (m->ifa_flags&IFA_F_TENTATIVE)
-                               goto skip_it;
-
-                       memset(rta_tb, 0, sizeof(rta_tb));
-                       parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(m), h->nlmsg_len - NLMSG_LENGTH(sizeof(*m)));
-
-                       if (rta_tb[IFA_LOCAL] == NULL)
-                               rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];
-                       if (rta_tb[IFA_LOCAL] == NULL)
-                               goto skip_it;
-                       
-                       I = malloc(sizeof(struct ifaddrs));
-                       if (!I)
-                               return;
-                       memset(I, 0, sizeof(*I));
-
-                       I->ifa_ifindex = m->ifa_index;
-                       I->ifa_addr = (struct sockaddr*)&I->ifa_addrbuf;
-                       I->ifa_addr->sa_family = m->ifa_family;
-                       if (m->ifa_family == AF_INET) {
-                               struct sockaddr_in *sin = (void*)I->ifa_addr;
-                               memcpy(&sin->sin_addr, RTA_DATA(rta_tb[IFA_LOCAL]), 4);
-                       } else {
-                               struct sockaddr_in6 *sin = (void*)I->ifa_addr;
-                               memcpy(&sin->sin6_addr, RTA_DATA(rta_tb[IFA_LOCAL]), 16);
-                               if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr))
-                                       sin->sin6_scope_id = I->ifa_ifindex;
-                       }
-                       I->ifa_next = *ifa;
-                       *ifa = I;
-
-skip_it:
-                       h = NLMSG_NEXT(h, status);
-               }
-               if (msg.msg_flags & MSG_TRUNC)
-                       continue;
-       }
-       return;
-}
-
-static int getifaddrs(struct ifaddrs **ifa0)
-{
-       struct {
-               struct nlmsghdr nlh;
-               struct rtgenmsg g;
-       } req;
-       struct sockaddr_nl nladdr;
-       static __u32 seq;
-       struct ifaddrs *i;
-       int fd;
-
-       fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
-       if (fd < 0)
-               return -1;
-
-       memset(&nladdr, 0, sizeof(nladdr));
-       nladdr.nl_family = AF_NETLINK;
-
-       req.nlh.nlmsg_len = sizeof(req);
-       req.nlh.nlmsg_type = RTM_GETADDR;
-       req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
-       req.nlh.nlmsg_pid = 0;
-       req.nlh.nlmsg_seq = ++seq;
-       req.g.rtgen_family = AF_UNSPEC;
-
-       if (sendto(fd, (void*)&req, sizeof(req), 0, (struct sockaddr*)&nladdr, sizeof(nladdr)) < 0) {
-               close(fd);
-               return -1;
-       }
-
-       *ifa0 = NULL;
-
-       recvaddrs(fd, ifa0, seq);
-
-       close(fd);
-
-       fd = socket(AF_INET, SOCK_DGRAM, 0);
-
-       for (i=*ifa0; i; i = i->ifa_next) {
-               struct ifreq ifr;
-               ifr.ifr_ifindex = i->ifa_ifindex;
-               ioctl(fd, SIOCGIFNAME, (void*)&ifr);
-               memcpy(i->ifa_name, ifr.ifr_name, 16);
-       }
-       close(fd);
-
-       return 0;
-}
-
-static void freeifaddrs(struct ifaddrs *ifa0)
-{
-        struct ifaddrs *i;
-
-        while (ifa0) {
-                i = ifa0;
-                ifa0 = i->ifa_next;
-                free(i);
-        }
-}
-
-#endif
-
 #ifndef HAVE_GETIFADDRS
 static unsigned int
 if_maxindex()
@@ -322,9 +132,9 @@ find_myaddr(addr, udp_encap)
                if (q->udp_encap && !udp_encap
                        || !q->udp_encap && udp_encap)
                        continue;
-               if (addr->sa_family != q->addr->sa_family)
+               if (addr->sa_family != q->addr->ss_family)
                        continue;
-               if (getnameinfo(q->addr, sysdep_sa_len(q->addr), h2, sizeof(h2),
+               if (getnameinfo((struct sockaddr *)q->addr, sysdep_sa_len((struct sockaddr *)q->addr), h2, sizeof(h2),
                    NULL, 0, NI_NUMERICHOST | niflags) != 0)
                        return NULL;
                if (strcmp(h1, h2) == 0)
@@ -345,9 +155,6 @@ grab_myaddrs()
 #ifdef HAVE_GETIFADDRS
        struct myaddrs *p, *q;
        struct ifaddrs *ifa0, *ifap;
-#ifdef INET6
-       struct sockaddr_in6 *sin6;
-#endif
 
        char addr1[NI_MAXHOST];
 
@@ -413,7 +220,7 @@ grab_myaddrs()
                        p->sock = -1;
                        p->in_use = 1;
 
-                       if (getnameinfo(p->addr, p->addr->sa_len,
+                       if (getnameinfo((struct sockaddr *)p->addr, p->addr->ss_len,
                                        addr1, sizeof(addr1),
                                        NULL, 0,
                                        NI_NUMERICHOST | niflags))
@@ -457,7 +264,7 @@ suitable_ifaddr(ifname, ifaddr)
        const char *ifname;
        const struct sockaddr *ifaddr;
 {
-#ifdef ENABLE_HYBRID
+#if 0 //we need to be able to do nested ipsec for BTMM... stub out ifdef ENABLE_HYBRID
        /* Exclude any address we got through ISAKMP mode config */
        if (exclude_cfg_addr(ifaddr) == 0)
                return 0;
@@ -481,15 +288,12 @@ suitable_ifaddr6(ifname, ifaddr)
        const char *ifname;
        const struct sockaddr *ifaddr;
 {
-#ifndef __linux__
        struct in6_ifreq ifr6;
        int s;
-#endif
 
        if (ifaddr->sa_family != AF_INET6)
                return 0;
 
-#ifndef __linux__
        s = socket(PF_INET6, SOCK_DGRAM, 0);
        if (s == -1) {
                plog(LLV_ERROR, LOCATION, NULL,
@@ -497,10 +301,15 @@ suitable_ifaddr6(ifname, ifaddr)
                return 0;
        }
 
+       if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
+               plog(LLV_ERROR, LOCATION, NULL,
+                        "failed to put IPv6 socket in non-blocking mode\n");
+       }
+
        memset(&ifr6, 0, sizeof(ifr6));
        strlcpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name));
 
-       ifr6.ifr_addr = *(const struct sockaddr_in6 *)ifaddr;
+       memcpy(&ifr6.ifr_addr, ifaddr, sizeof(struct sockaddr_in6));    // Wcast-align fix - copy instread of assign with cast
 
        if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
                plog(LLV_ERROR, LOCATION, NULL,
@@ -515,7 +324,6 @@ suitable_ifaddr6(ifname, ifaddr)
         || ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DETACHED
         || ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_ANYCAST)
                return 0;
-#endif
 
        /* suitable */
        return 1;
@@ -524,49 +332,35 @@ suitable_ifaddr6(ifname, ifaddr)
 
 int
 update_myaddrs()
-{
-#ifdef __linux__
-       char msg[BUFSIZ];
+{   
+    struct rtmessage {          // Wcast-align fix - force alignment
+        struct rt_msghdr rtm;  
+        char discard[BUFSIZ];
+    } msg;
+       
        int len;
-       struct nlmsghdr *h = (void*)msg;
-       len = read(lcconf->rtsock, msg, sizeof(msg));
-       if (len < 0)
-               return errno == ENOBUFS;
-       if (len < sizeof(*h))
-               return 0;
-       if (h->nlmsg_pid) /* not from kernel! */
-               return 0;
-       if (h->nlmsg_type == RTM_NEWLINK)
-               return 0;
-       plog(LLV_DEBUG, LOCATION, NULL,
-               "netlink signals update interface address list\n");
-       return 1;
-#else
-       char msg[BUFSIZ];
-       int len;
-       struct rt_msghdr *rtm;
 
-       len = read(lcconf->rtsock, msg, sizeof(msg));
-       if (len < 0) {
+       while((len = read(lcconf->rtsock, &msg, sizeof(msg))) < 0) {
+               if (errno == EINTR)
+                       continue;
                plog(LLV_ERROR, LOCATION, NULL,
                        "read(PF_ROUTE) failed: %s\n",
                        strerror(errno));
                return 0;
        }
-       rtm = (struct rt_msghdr *)msg;
-       if (len < rtm->rtm_msglen) {
+       if (len < msg.rtm.rtm_msglen) {
                plog(LLV_ERROR, LOCATION, NULL,
                        "read(PF_ROUTE) short read\n");
                return 0;
        }
-       if (rtm->rtm_version != RTM_VERSION) {
+       if (msg.rtm.rtm_version != RTM_VERSION) {
                plog(LLV_ERROR, LOCATION, NULL,
                        "routing socket version mismatch\n");
                close(lcconf->rtsock);
                lcconf->rtsock = -1;
                return 0;
        }
-       switch (rtm->rtm_type) {
+       switch (msg.rtm.rtm_type) {
        case RTM_NEWADDR:
        case RTM_DELADDR:
        case RTM_DELETE:
@@ -576,18 +370,17 @@ update_myaddrs()
                /* ignore this message silently */
                return 0;
        default:
-               plog(LLV_DEBUG, LOCATION, NULL,
-                       "msg %d not interesting\n", rtm->rtm_type);
+               //plog(LLV_DEBUG, LOCATION, NULL,
+               //      "msg %d not interesting\n", msg.rtm.rtm_type);
                return 0;
        }
        /* XXX more filters here? */
 
-       plog(LLV_DEBUG, LOCATION, NULL,
-               "caught rtm:%d, need update interface address list\n",
-               rtm->rtm_type);
+       //plog(LLV_DEBUG, LOCATION, NULL,
+       //      "caught rtm:%d, need update interface address list\n",
+       //      msg.rtm.rtm_type);
 
        return 1;
-#endif /* __linux__ */
 }
 
 /*
@@ -622,7 +415,7 @@ autoconf_myaddrsport()
  */
 u_short
 getmyaddrsport(local)
-       struct sockaddr *local;
+       struct sockaddr_storage *local;
 {
        struct myaddrs *p, *bestmatch = NULL;
        u_short bestmatch_port = PORT_ISAKMP;
@@ -637,7 +430,7 @@ getmyaddrsport(local)
                                continue;
                        }
                        
-                       switch (p->addr->sa_family) {
+                       switch (p->addr->ss_family) {
                        case AF_INET:
                                if (((struct sockaddr_in *)p->addr)->sin_port == PORT_ISAKMP) {
                                        bestmatch = p;
@@ -656,7 +449,7 @@ getmyaddrsport(local)
 #endif
                        default:
                                plog(LLV_ERROR, LOCATION, NULL,
-                                    "unsupported AF %d\n", p->addr->sa_family);
+                                    "unsupported AF %d\n", p->addr->ss_family);
                                continue;
                        }
                }
@@ -700,7 +493,7 @@ dupmyaddr(struct myaddrs *old)
 
        /* Copy the whole structure and set the differences.  */
        memcpy (new, old, sizeof (*new));
-       new->addr = dupsaddr (old->addr);
+       new->addr = dupsaddr ((struct sockaddr *)old->addr);
        if (new->addr == NULL) {
                plog(LLV_ERROR, LOCATION, NULL,
                        "failed to allocate buffer for duplicate addr.\n");
@@ -739,10 +532,8 @@ delmyaddr(myaddr)
 {
        if (myaddr->addr)
                racoon_free(myaddr->addr);
-#ifdef __APPLE__
        if (myaddr->ifname)
                racoon_free(myaddr->ifname);
-#endif
        racoon_free(myaddr);
 }
 
@@ -757,31 +548,11 @@ initmyaddr()
                        strerror(errno));
                return -1;
        }
-
-#ifdef __linux__
-   {
-       struct sockaddr_nl nl;
-       u_int addr_len;
-
-       memset(&nl, 0, sizeof(nl));
-       nl.nl_family = AF_NETLINK;
-       nl.nl_groups = RTMGRP_IPV4_IFADDR|RTMGRP_LINK;
-
-       if (bind(lcconf->rtsock, (struct sockaddr*)&nl, sizeof(nl)) < 0) {
-               plog(LLV_ERROR, LOCATION, NULL,
-                    "bind(PF_NETLINK) failed: %s\n",
-                    strerror(errno));
-               return -1;
-       }
-       addr_len = sizeof(nl);
-       if (getsockname(lcconf->rtsock, (struct sockaddr*)&nl, &addr_len) < 0) {
+    
+       if (fcntl(lcconf->rtsock, F_SETFL, O_NONBLOCK) == -1) {
                plog(LLV_ERROR, LOCATION, NULL,
-                    "getsockname(PF_NETLINK) failed: %s\n",
-                    strerror(errno));
-               return -1;
+                        "failed to put PF_ROUTE socket in non-blocking mode\n");
        }
-   }
-#endif
 
        if (lcconf->myaddrs == NULL && lcconf->autograbaddr == 1) {
                grab_myaddrs();
@@ -800,36 +571,18 @@ getsockmyaddr(my)
        struct sockaddr *my;
 {
        struct myaddrs *p, *lastresort = NULL;
-#if defined(INET6) && defined(__linux__)
-       struct myaddrs *match_wo_scope_id = NULL;
-       int check_wo_scope_id = (my->sa_family == AF_INET6) && 
-               IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)my)->sin6_addr);
-#endif
 
        for (p = lcconf->myaddrs; p; p = p->next) {
                if (p->addr == NULL)
                        continue;
-               if (my->sa_family == p->addr->sa_family) {
+               if (my->sa_family == p->addr->ss_family) {
                        lastresort = p;
                } else continue;
-               if (sysdep_sa_len(my) == sysdep_sa_len(p->addr)
+               if (sysdep_sa_len(my) == sysdep_sa_len((struct sockaddr *)p->addr)
                 && memcmp(my, p->addr, sysdep_sa_len(my)) == 0) {
                        break;
                }
-#if defined(INET6) && defined(__linux__)
-               if (check_wo_scope_id && IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)p->addr)->sin6_addr) &&
-                       /* XXX: this depends on sin6_scope_id to be last
-                        * item in struct sockaddr_in6 */
-                       memcmp(my, p->addr, 
-                               sysdep_sa_len(my) - sizeof(uint32_t)) == 0) {
-                       match_wo_scope_id = p;
-               }
-#endif
        }
-#if defined(INET6) && defined(__linux__)
-       if (!p)
-               p = match_wo_scope_id;
-#endif
        if (!p)
                p = lastresort;
        if (!p) {