]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Work better with signal handling, arp and send errors
authorRoy Marples <roy@marples.name>
Thu, 11 Oct 2007 13:21:57 +0000 (13:21 +0000)
committerRoy Marples <roy@marples.name>
Thu, 11 Oct 2007 13:21:57 +0000 (13:21 +0000)
interface.c

index 9a87687bd14b363b25cec67c220db68eb56cb385..9964ad360eaead8715d1c86acdbdbb4dc60a87ca 100644 (file)
@@ -259,8 +259,8 @@ interface_t *read_interface (const char *ifname, int metric)
 {
        int s;
        struct ifreq ifr;
-       interface_t *iface;
-       unsigned char hwaddr[20];
+       interface_t *iface = NULL;
+       unsigned char *hwaddr = NULL;
        int hwlen = 0;
        sa_family_t family = 0;
        unsigned short mtu;
@@ -286,8 +286,7 @@ interface_t *read_interface (const char *ifname, int metric)
        strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
        if (ioctl (s, SIOCGIFHWADDR, &ifr) == -1) {
                logger (LOG_ERR, "ioctl SIOCGIFHWADDR: %s", strerror (errno));
-               close (s);
-               return NULL;
+               goto exit;
        }
 
        switch (ifr.ifr_hwaddr.sa_family) {
@@ -302,10 +301,10 @@ interface_t *read_interface (const char *ifname, int metric)
                        break;
                default:
                        logger (LOG_ERR, "interface is not Ethernet, FireWire, InfiniBand or Token Ring");
-                       close (s);
-                       return NULL;
+                       goto exit;
        }
 
+       hwaddr = xmalloc (sizeof (unsigned char *) * HWADDR_LEN);
        memcpy (hwaddr, ifr.ifr_hwaddr.sa_data, hwlen);
        family = ifr.ifr_hwaddr.sa_family;
 #else
@@ -313,14 +312,13 @@ interface_t *read_interface (const char *ifname, int metric)
        strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
        if (ioctl (s, SIOCSIFMETRIC, &ifr) == -1) {
                logger (LOG_ERR, "ioctl SIOCSIFMETRIC: %s", strerror (errno));
-               close (s);
-               return NULL;
+               goto exit;
        }
-       
+
+       hwaddr = xmalloc (sizeof (unsigned char *) * HWADDR_LEN);
        if (_do_interface (ifname, hwaddr, &hwlen, NULL, false, false) != 1) {
                logger (LOG_ERR, "could not find interface %s", ifname);
-               close (s);
-               return NULL;
+               goto exit;
        }
 
        family = ARPHRD_ETHER;
@@ -329,8 +327,7 @@ interface_t *read_interface (const char *ifname, int metric)
        strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
        if (ioctl (s, SIOCGIFMTU, &ifr) == -1) {
                logger (LOG_ERR, "ioctl SIOCGIFMTU: %s", strerror (errno));
-               close (s);
-               return NULL;
+               goto exit;
        }
 
        if (ifr.ifr_mtu < MTU_MIN) {
@@ -339,8 +336,7 @@ interface_t *read_interface (const char *ifname, int metric)
                strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
                if (ioctl (s, SIOCSIFMTU, &ifr) == -1) {
                        logger (LOG_ERR, "ioctl SIOCSIFMTU,: %s", strerror (errno));
-                       close (s);
-                       return NULL;
+                       goto exit;
                }
        }
        mtu = ifr.ifr_mtu;
@@ -353,21 +349,17 @@ interface_t *read_interface (const char *ifname, int metric)
 #endif
        if (ioctl (s, SIOCGIFFLAGS, &ifr) == -1) {
                logger (LOG_ERR, "ioctl SIOCGIFFLAGS: %s", strerror (errno));
-               close (s);
-               return NULL;
+               goto exit;
        }
 
        if (! (ifr.ifr_flags & IFF_UP) || ! (ifr.ifr_flags & IFF_RUNNING)) {
                ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
                if (ioctl (s, SIOCSIFFLAGS, &ifr) == -1) {
                        logger (LOG_ERR, "ioctl SIOCSIFFLAGS: %s", strerror (errno));
-                       close (s);
-                       return NULL;
+                       goto exit;
                }
        }
 
-       close (s);
-
        iface = xmalloc (sizeof (interface_t));
        memset (iface, 0, sizeof (interface_t));
        strlcpy (iface->name, ifname, IF_NAMESIZE);
@@ -387,6 +379,9 @@ interface_t *read_interface (const char *ifname, int metric)
        /* 0 is a valid fd, so init to -1 */
        iface->fd = -1;
 
+exit:
+       close (s);
+       free (hwaddr);
        return iface;
 }
 
@@ -600,12 +595,13 @@ static int do_route (const char *ifname,
                gateway.s_addr == INADDR_ANY)
        {
                /* Make us a link layer socket */
-               unsigned char hwaddr[HWADDR_LEN];
+               unsigned char *hwaddr;
                int hwlen = 0;
 
                if (netmask.s_addr == INADDR_BROADCAST) 
                        rtm.hdr.rtm_flags |= RTF_HOST;
 
+               hwaddr = xmalloc (sizeof (unsigned char *) * HWADDR_LEN);
                _do_interface (ifname, hwaddr, &hwlen, NULL, false, false);
                memset (&su, 0, sizeof (struct sockaddr_storage));
                su.sdl.sdl_len = sizeof (struct sockaddr_dl);
@@ -619,6 +615,7 @@ static int do_route (const char *ifname,
                l = SA_SIZE (&(su.sa));
                memcpy (bp, &su, l);
                bp += l;
+               free (hwaddr);
        } else {
                rtm.hdr.rtm_flags |= RTF_GATEWAY;
                ADDADDR (gateway);
@@ -650,6 +647,7 @@ static int do_route (const char *ifname,
    This blatently taken from libnetlink.c from the iproute2 package
    which is the only good source of netlink code.
    */
+#define BUFFERLEN 256
 static int send_netlink(struct nlmsghdr *hdr)
 {
        int s;
@@ -658,7 +656,7 @@ static int send_netlink(struct nlmsghdr *hdr)
        struct iovec iov;
        struct msghdr msg;
        static unsigned int seq;
-       char buffer[256];
+       char *buffer;
        int bytes;
        union
        {
@@ -699,11 +697,12 @@ static int send_netlink(struct nlmsghdr *hdr)
                return -1;
        }
 
-       memset (buffer, 0, sizeof (buffer));
+       buffer = xmalloc (sizeof (char *) * BUFFERLEN);
+       memset (buffer, 0, BUFFERLEN);
        iov.iov_base = buffer;
 
        while (1) {
-               iov.iov_len = sizeof (buffer);
+               iov.iov_len = BUFFERLEN;
                bytes = recvmsg (s, &msg, 0);
 
                if (bytes == -1) {
@@ -749,6 +748,7 @@ static int send_netlink(struct nlmsghdr *hdr)
                                        errno = -err->error;
                                        if (errno == 0) {
                                                close (s);
+                                               free (buffer);
                                                return 0;
                                        }
 
@@ -778,6 +778,7 @@ next:
 
 eexit:
        close (s);
+       free (buffer);
        return -1;
 }
 
@@ -824,47 +825,61 @@ static int add_attr_32(struct nlmsghdr *n, unsigned int maxlen, int type,
        return 0;
 }
 
+struct nlma
+{
+       struct nlmsghdr hdr;
+       struct ifaddrmsg ifa; 
+       char buffer[64];
+};
+
+struct nlmr
+{
+       struct nlmsghdr hdr;
+       struct rtmsg rt;
+       char buffer[256];
+};
+
 static int do_address(const char *ifname,
                                          struct in_addr address, struct in_addr netmask,
                                          struct in_addr broadcast, int del)
 {
-       struct
-       {
-               struct nlmsghdr hdr;
-               struct ifaddrmsg ifa;
-               char buffer[64];
-       }
-       nlm;
+       struct nlma *nlm;
+       int retval;
 
        if (!ifname)
                return -1;
 
-       memset (&nlm, 0, sizeof (nlm));
+       nlm = xmalloc (sizeof (struct nlma));
+       memset (nlm, 0, sizeof (struct nlma));
 
-       nlm.hdr.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg));
-       nlm.hdr.nlmsg_flags = NLM_F_REQUEST;
+       nlm->hdr.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg));
+       nlm->hdr.nlmsg_flags = NLM_F_REQUEST;
        if (! del)
-               nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
-       nlm.hdr.nlmsg_type = del ? RTM_DELADDR : RTM_NEWADDR;
-       if (! (nlm.ifa.ifa_index = if_nametoindex (ifname))) {
+               nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
+       nlm->hdr.nlmsg_type = del ? RTM_DELADDR : RTM_NEWADDR;
+       if (! (nlm->ifa.ifa_index = if_nametoindex (ifname))) {
                logger (LOG_ERR, "if_nametoindex: Couldn't find index for interface `%s'",
                                ifname);
+               free (nlm);
                return -1;
        }
-       nlm.ifa.ifa_family = AF_INET;
+       nlm->ifa.ifa_family = AF_INET;
 
-       nlm.ifa.ifa_prefixlen = inet_ntocidr (netmask);
+       nlm->ifa.ifa_prefixlen = inet_ntocidr (netmask);
 
        /* This creates the aliased interface */
-       add_attr_l (&nlm.hdr, sizeof (nlm), IFA_LABEL, ifname, strlen (ifname) + 1);
+       add_attr_l (&nlm->hdr, sizeof (struct nlma), IFA_LABEL,
+                               ifname, strlen (ifname) + 1);
 
-       add_attr_l (&nlm.hdr, sizeof (nlm), IFA_LOCAL, &address.s_addr,
-                               sizeof (address.s_addr));
+       add_attr_l (&nlm->hdr, sizeof (struct nlma), IFA_LOCAL,
+                               &address.s_addr, sizeof (address.s_addr));
        if (! del)
-               add_attr_l (&nlm.hdr, sizeof (nlm), IFA_BROADCAST, &broadcast.s_addr,
-                                       sizeof (broadcast.s_addr));
+               add_attr_l (&nlm->hdr, sizeof (struct nlma), IFA_BROADCAST,
+                                       &broadcast.s_addr, sizeof (broadcast.s_addr));
 
-       return send_netlink (&nlm.hdr);
+       retval = send_netlink (&nlm->hdr);
+       free (nlm);
+       return retval;
 }
 
 static int do_route (const char *ifname,
@@ -873,63 +888,61 @@ static int do_route (const char *ifname,
                                         struct in_addr gateway,
                                         int metric, int change, int del)
 {
+       struct nlmr *nlm;
        unsigned int ifindex;
-       struct
-       {
-               struct nlmsghdr hdr;
-               struct rtmsg rt;
-               char buffer[256];
-       }
-       nlm;
+       int retval;
 
        if (! ifname)
                return -1;
 
        log_route (destination, netmask, gateway, metric, change, del);
 
-       memset (&nlm, 0, sizeof (nlm));
+       if (! (ifindex = if_nametoindex (ifname))) {
+               logger (LOG_ERR, "if_nametoindex: Couldn't find index for interface `%s'",
+                               ifname);
+               return -1;
+       }
+
+       nlm = xmalloc (sizeof (struct nlmr));
+       memset (nlm, 0, sizeof (struct nlmr));
 
-       nlm.hdr.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
+       nlm->hdr.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
        if (change)
-               nlm.hdr.nlmsg_flags = NLM_F_REPLACE;
+               nlm->hdr.nlmsg_flags = NLM_F_REPLACE;
        else if (! del)
-               nlm.hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL;
-       nlm.hdr.nlmsg_flags |= NLM_F_REQUEST;
-       nlm.hdr.nlmsg_type = del ? RTM_DELROUTE : RTM_NEWROUTE;
-       nlm.rt.rtm_family = AF_INET;
-       nlm.rt.rtm_table = RT_TABLE_MAIN;
+               nlm->hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL;
+       nlm->hdr.nlmsg_flags |= NLM_F_REQUEST;
+       nlm->hdr.nlmsg_type = del ? RTM_DELROUTE : RTM_NEWROUTE;
+       nlm->rt.rtm_family = AF_INET;
+       nlm->rt.rtm_table = RT_TABLE_MAIN;
 
        if (del)
-               nlm.rt.rtm_scope = RT_SCOPE_NOWHERE;
+               nlm->rt.rtm_scope = RT_SCOPE_NOWHERE;
        else {
-               nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
-               nlm.rt.rtm_protocol = RTPROT_BOOT;
+               nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
+               nlm->rt.rtm_protocol = RTPROT_BOOT;
                if (netmask.s_addr == INADDR_BROADCAST ||
                        gateway.s_addr == INADDR_ANY)
-                       nlm.rt.rtm_scope = RT_SCOPE_LINK;
+                       nlm->rt.rtm_scope = RT_SCOPE_LINK;
                else
-                       nlm.rt.rtm_scope = RT_SCOPE_UNIVERSE;
-               nlm.rt.rtm_type = RTN_UNICAST;
+                       nlm->rt.rtm_scope = RT_SCOPE_UNIVERSE;
+               nlm->rt.rtm_type = RTN_UNICAST;
        }
 
-       nlm.rt.rtm_dst_len = inet_ntocidr (netmask);
-       add_attr_l (&nlm.hdr, sizeof (nlm), RTA_DST, &destination.s_addr,
-                               sizeof (destination.s_addr));
+       nlm->rt.rtm_dst_len = inet_ntocidr (netmask);
+       add_attr_l (&nlm->hdr, sizeof (struct nlmr), RTA_DST,
+                               &destination.s_addr, sizeof (destination.s_addr));
        if (netmask.s_addr != INADDR_BROADCAST &&
                destination.s_addr != gateway.s_addr)
-               add_attr_l (&nlm.hdr, sizeof (nlm), RTA_GATEWAY, &gateway.s_addr,
-                                       sizeof (gateway.s_addr));
+               add_attr_l (&nlm->hdr, sizeof (struct nlmr), RTA_GATEWAY,
+                                       &gateway.s_addr, sizeof (gateway.s_addr));
 
-       if (! (ifindex = if_nametoindex (ifname))) {
-               logger (LOG_ERR, "if_nametoindex: Couldn't find index for interface `%s'",
-                               ifname);
-               return -1;
-       }
+       add_attr_32 (&nlm->hdr, sizeof (struct nlmr), RTA_OIF, ifindex);
+       add_attr_32 (&nlm->hdr, sizeof (struct nlmr), RTA_PRIORITY, metric);
 
-       add_attr_32 (&nlm.hdr, sizeof (nlm), RTA_OIF, ifindex);
-       add_attr_32 (&nlm.hdr, sizeof (nlm), RTA_PRIORITY, metric);
-
-       return send_netlink (&nlm.hdr);
+       retval = send_netlink (&nlm->hdr);
+       free (nlm);
+       return retval;
 }
 
 #else