]> git.saurik.com Git - apple/network_cmds.git/blobdiff - rtadvd.tproj/if.c
network_cmds-543.270.1.tar.gz
[apple/network_cmds.git] / rtadvd.tproj / if.c
index 5fb644eb29ee24a97d2ac84d70c63220447a6e4a..082714cbfad2b0836cf42516fd9fcc22f429a60d 100644 (file)
@@ -45,7 +45,6 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
-#include <syslog.h>
 #include "rtadvd.h"
 #include "if.h"
 
                                                 sizeof(uint32_t)) :\
                                                 sizeof(uint32_t)))
 
-struct if_msghdr **iflist;
-int iflist_init_ok;
+/* Interface list */
+TAILQ_HEAD(ifilist_head_t, ifinfo);
+struct ifilist_head_t ifilist = TAILQ_HEAD_INITIALIZER(ifilist);
 size_t ifblock_size;
 char *ifblock;
 
 static void get_iflist(char **buf, size_t *size);
-static void parse_iflist(struct if_msghdr ***ifmlist_p, char *buf,
-                      size_t bufsize);
+static void parse_iflist(char *buf, size_t bufsize);
+static void purge_iflist();
 
 static void
 get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
@@ -186,14 +186,14 @@ if_getflags(int ifindex, int oifflags)
        int s;
 
        if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
-               syslog(LOG_ERR, "<%s> socket: %s", __func__,
+               errorlog("<%s> socket: %s", __func__,
                       strerror(errno));
                return (oifflags & ~IFF_UP);
        }
 
        if_indextoname(ifindex, ifr.ifr_name);
        if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
-               syslog(LOG_ERR, "<%s> ioctl:SIOCGIFFLAGS: failed for %s",
+               errorlog("<%s> ioctl:SIOCGIFFLAGS: failed for %s",
                       __func__, ifr.ifr_name);
                close(s);
                return (oifflags & ~IFF_UP);
@@ -228,7 +228,7 @@ lladdropt_fill(struct sockaddr_dl *sdl, struct nd_opt_hdr *ndopt)
                memcpy(addr, LLADDR(sdl), ETHER_ADDR_LEN);
                break;
        default:
-               syslog(LOG_ERR, "<%s> unsupported link type(%d)",
+               errorlog("<%s> unsupported link type(%d)",
                    __func__, sdl->sdl_type);
                exit(1);
        }
@@ -265,7 +265,7 @@ get_next_msg(char *buf, char *lim, int ifindex, size_t *lenp, int filter)
             rtm = (struct rt_msghdr *)(((char *)rtm) + rtm->rtm_msglen)) {
                /* just for safety */
                if (!rtm->rtm_msglen) {
-                       syslog(LOG_WARNING, "<%s> rtm_msglen is 0 "
+                       errorlog("<%s> rtm_msglen is 0 "
                                "(buf=%p lim=%p rtm=%p)", __func__,
                                buf, lim, rtm);
                        break;
@@ -484,59 +484,71 @@ get_iflist(char **buf, size_t *size)
        mib[5] = 0;
 
        if (sysctl(mib, 6, NULL, size, NULL, 0) < 0) {
-               syslog(LOG_ERR, "<%s> sysctl: iflist size get failed",
+               errorlog("<%s> sysctl: iflist size get failed",
                       __func__);
                exit(1);
        }
        if ((*buf = malloc(*size)) == NULL) {
-               syslog(LOG_ERR, "<%s> malloc failed", __func__);
+               errorlog("<%s> malloc failed", __func__);
                exit(1);
        }
        if (sysctl(mib, 6, *buf, size, NULL, 0) < 0) {
-               syslog(LOG_ERR, "<%s> sysctl: iflist get failed",
+               errorlog("<%s> sysctl: iflist get failed",
                       __func__);
                exit(1);
        }
        return;
 }
 
+struct if_msghdr *
+get_interface_entry(int if_index)
+{
+       struct ifinfo *ifi = NULL;
+       struct if_msghdr *ifm = NULL;
+
+       TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
+               if (if_index == ifi->ifm->ifm_index) {
+                       ifm = ifi->ifm;
+                       break;
+               }
+       }
+       return ifm;
+}
+
 /*
  * alloc buffer and parse if_msghdrs block passed as arg,
  * and init the buffer as list of pointers ot each of the if_msghdr.
  */
 static void
-parse_iflist(struct if_msghdr ***ifmlist_p, char *buf, size_t bufsize)
+parse_iflist(char *buf, size_t bufsize)
 {
-       int iflentry_size, malloc_size;
        struct if_msghdr *ifm;
        struct ifa_msghdr *ifam;
        char *lim;
 
-       /*
-        * Estimate least size of an iflist entry, to be obtained from kernel.
-        * Should add sizeof(sockaddr) ??
-        */
-       iflentry_size = sizeof(struct if_msghdr);
-       /* roughly estimate max list size of pointers to each if_msghdr */
-       malloc_size = (bufsize/iflentry_size) * sizeof(size_t);
-       if ((*ifmlist_p = (struct if_msghdr **)malloc(malloc_size)) == NULL) {
-               syslog(LOG_ERR, "<%s> malloc failed", __func__);
-               exit(1);
-       }
-
        lim = buf + bufsize;
        for (ifm = (struct if_msghdr *)buf; ifm < (struct if_msghdr *)lim;) {
                if (ifm->ifm_msglen == 0) {
-                       syslog(LOG_WARNING, "<%s> ifm_msglen is 0 "
+                       errorlog("<%s> ifm_msglen is 0 "
                               "(buf=%p lim=%p ifm=%p)", __func__,
                               buf, lim, ifm);
                        return;
                }
 
                if (ifm->ifm_type == RTM_IFINFO) {
-                       (*ifmlist_p)[ifm->ifm_index] = ifm;
+                       struct ifinfo *ifi = NULL;
+
+                       if (get_interface_entry(ifm->ifm_index) != NULL) {
+                               debuglog("Interface entry is already present for "
+                                   "interface index: %d. Skipping.", ifm->ifm_index);
+                               continue;
+                       }
+
+                       ELM_MALLOC(ifi, exit(1));
+                       ifi->ifm = ifm;
+                       TAILQ_INSERT_TAIL(&ifilist, ifi, ifi_next);
                } else {
-                       syslog(LOG_ERR, "out of sync parsing NET_RT_IFLIST\n"
+                       errorlog("out of sync parsing NET_RT_IFLIST\n"
                               "expected %d, got %d\n msglen = %d\n"
                               "buf:%p, ifm:%p, lim:%p\n",
                               RTM_IFINFO, ifm->ifm_type, ifm->ifm_msglen,
@@ -550,7 +562,7 @@ parse_iflist(struct if_msghdr ***ifmlist_p, char *buf, size_t bufsize)
                        ((char *)ifam + ifam->ifam_msglen)) {
                        /* just for safety */
                        if (!ifam->ifam_msglen) {
-                               syslog(LOG_WARNING, "<%s> ifa_msglen is 0 "
+                               errorlog("<%s> ifa_msglen is 0 "
                                       "(buf=%p lim=%p ifam=%p)", __func__,
                                       buf, lim, ifam);
                                return;
@@ -562,18 +574,31 @@ parse_iflist(struct if_msghdr ***ifmlist_p, char *buf, size_t bufsize)
        }
 }
 
+static void
+purge_iflist()
+{
+       struct ifinfo *ifi = NULL;
+       if (!TAILQ_EMPTY(&ifilist)) {
+               while ((ifi = TAILQ_FIRST(&ifilist)) != NULL) {
+                       TAILQ_REMOVE(&ifilist, ifi, ifi_next);
+                       free(ifi);
+               }
+       }
+}
+
 void
 init_iflist()
 {
+       purge_iflist();
+
        if (ifblock) {
                free(ifblock);
                ifblock_size = 0;
        }
-       if (iflist)
-               free(iflist);
+
        /* get iflist block from kernel */
        get_iflist(&ifblock, &ifblock_size);
 
        /* make list of pointers to each if_msghdr */
-       parse_iflist(&iflist, ifblock, ifblock_size);
+       parse_iflist(ifblock, ifblock_size);
 }