]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Remove getifaddrs code and instead just use ioctls.
authorRoy Marples <roy@marples.name>
Wed, 25 Jul 2007 21:01:10 +0000 (21:01 +0000)
committerRoy Marples <roy@marples.name>
Wed, 25 Jul 2007 21:01:10 +0000 (21:01 +0000)
ChangeLog
Makefile
arp.c
common.c
duid.c
duid.h
interface.c
interface.h

index 7e3052ce4a3a31d32b253f96862882a845f5e5ab..ec94d638a795f4c9cf7ff9b872250add1c3262f4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,5 @@
+Remove getifaddrs code and instead just use ioctls.
+
 dhcpcd-3.1.0
 Add new socket code to try and support InfiniBand better.
 Support RFC 3361 SIP Servers.
index 2e90efe1b7f615bf6ad57d08d07780996627d2d4..9377c600529cfcc07a0dfcc4699bb72d3933959d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-VERSION = 3.1.0
+VERSION = 3.1.1_pre1
 CFLAGS ?= -O2 -pipe
 
 # Should work for both GNU make and BSD make
diff --git a/arp.c b/arp.c
index 8f09d1de01e4562875c5401ad73568555743b6a9..c770e26805915aa3e774a00bfe420ddb04f9dea0 100644 (file)
--- a/arp.c
+++ b/arp.c
@@ -190,9 +190,6 @@ int arp_claim (interface_t *iface, struct in_addr address)
                                continue;
                        if (reply->ar_pln != sizeof (struct in_addr))
                                continue;
-
-                       if (reply->ar_hln != ETHER_ADDR_LEN)
-                               continue;
                        if ((unsigned) bytes < sizeof (reply) + 
                                2 * (4 + reply->ar_hln))
                                continue;
@@ -200,7 +197,8 @@ int arp_claim (interface_t *iface, struct in_addr address)
                        rp.c = (unsigned char *) ar_spa (reply);
                        rh.c = (unsigned char *) ar_sha (reply);
                        logger (LOG_ERR, "ARPOP_REPLY received from %s (%s)",
-                                       inet_ntoa (*rp.a), ether_ntoa (rh.a));
+                                       inet_ntoa (*rp.a),
+                                       hwaddr_ntoa (rh.a, reply->ar_hln));
                        retval = -1;
                        goto eexit;
                }
index df2f709dd21e91a9c3095e699526a981d5982bb5..b699dd613b9089daf8f131a32965c0ef4b52ba04 100644 (file)
--- a/common.c
+++ b/common.c
@@ -52,7 +52,7 @@ void srandomdev (void) {
 
 /* strlcpy is nice, shame glibc does not define it */
 #ifdef __GLIBC__
-#  if ! defined(__UCLIBC__) && ! defined (__dietlibc__)
+#  if ! defined (__UCLIBC__) && ! defined (__dietlibc__)
 size_t strlcpy (char *dst, const char *src, size_t size)
 {
        const char *s = src;
@@ -73,7 +73,7 @@ size_t strlcpy (char *dst, const char *src, size_t size)
 
        return (src - s - 1);
 }
-#endif
+#  endif
 #endif
 
 /* This requires us to link to rt on glibc, so we use sysinfo instead */
diff --git a/duid.c b/duid.c
index 78f02034813e197442603a78a51d8f13d191ed9c..8ddbf2cafab51c371ba9b8d960f144d5ee4fcfcc 100644 (file)
--- a/duid.c
+++ b/duid.c
@@ -33,7 +33,6 @@
 #include "logger.h"
 
 #ifdef ENABLE_DUID
-#define DUID_LEN                   130
 
 #define THIRTY_YEARS_IN_SECONDS    946707779
 
diff --git a/duid.h b/duid.h
index d12aacf146795223affac02c0f107bdf69b88eca..a00661a4919ed5eb835cceafa5bc6930174dbbc0 100644 (file)
--- a/duid.h
+++ b/duid.h
@@ -25,8 +25,8 @@
 #include "config.h"
 
 #ifdef ENABLE_DUID
-#ifndef DUID_LENGTH_MAX
-#define DUID_LENGTH_MAX 128 + 2
+#ifndef DUID_LEN
+#  define DUID_LEN 128 + 2
 #endif
 
 #include "interface.h"
index 24a9ab080092c9f69cc5926b27dffe3a72bf8b24..7aa39f45dea8f7a7b6c08d34e59f339e3cb41cbf 100644 (file)
 #include <linux/rtnetlink.h>
 #include <netinet/ether.h>
 #include <netpacket/packet.h>
-/* Only glibc-2.3 ships with ifaddrs.h */
-#if defined (__GLIBC__) && defined (__GLIBC_PREREQ)
-#  if  __GLIBC_PREREQ (2,3)
-#    define HAVE_IFADDRS_H
-#    include <ifaddrs.h>
-#  endif
-#endif
 #else
-#include <net/if_arp.h> /*dietlibc requires this - normally from
-                                                 netinet/ether.h */
 #include <net/if_dl.h>
 #include <net/if_types.h>
 #include <net/route.h>
 #include <netinet/in.h>
-#define HAVE_IFADDRS_H
-#  include <ifaddrs.h>
 #endif
 
 #include <errno.h>
@@ -166,70 +155,129 @@ char *hwaddr_ntoa (const unsigned char *hwaddr, int hwlen)
        return (buffer);
 }
 
-interface_t *read_interface (const char *ifname, int metric)
+static int _do_interface (const char *ifname,
+                                                 unsigned char *hwaddr, int *hwlen,
+                                                 struct in_addr *addr,
+                                                 bool flush, bool get)
 {
-
        int s;
-       struct ifreq ifr;
-       interface_t *iface;
-       unsigned char hwaddr[16];
-       int hwlen = 0;
-       sa_family_t family = 0;
-       unsigned short mtu;
+       struct ifconf ifc;
+       int retval = 0;
+       int len = 10 * sizeof (struct ifreq);
+       int lastlen = 0;
+       char *p;
+
+       if ((s = socket (AF_INET, SOCK_DGRAM, 0)) == -1) {
+               logger (LOG_ERR, "socket: %s", strerror (errno));
+               return -1;
+       }
+
+       /* Not all implementations return the needed buffer size for
+        * SIOGIFCONF so we loop like so for all until it works */
+       memset (&ifc, 0, sizeof (struct ifconf));
+       while (1) {
+               ifc.ifc_len = len;
+               ifc.ifc_buf = xmalloc (len);
+               if (ioctl (s, SIOCGIFCONF, &ifc) == -1) {
+                       if (errno != EINVAL || lastlen != 0) {
+                               logger (LOG_ERR, "ioctl SIOCGIFCONF: %s", strerror (errno));
+                               close (s);
+                               free (ifc.ifc_buf);     
+                               return -1;
+                       }
+               } else {
+                       if (ifc.ifc_len == lastlen)
+                               break;
+                       lastlen = ifc.ifc_len;
+               }
+
+               free (ifc.ifc_buf);
+               ifc.ifc_buf = NULL;
+               len *= 2;
+       }
+
+       for (p = ifc.ifc_buf; p < ifc.ifc_buf + ifc.ifc_len;) {
+               struct ifreq *ifr = (struct ifreq *) p;
+               struct sockaddr_in address;
 
 #ifdef __linux__
-       char *p;
+               p += sizeof (struct ifreq);
 #else
-       struct ifaddrs *ifap;
-       struct ifaddrs *p;
+               p += sizeof (ifr->ifr_name) +
+                       MAX (ifr->ifr_addr.sa_len, sizeof (struct sockaddr));
 #endif
 
-       if (! ifname)
-               return NULL;
-
-       memset (hwaddr, sizeof (hwaddr), 0);
+               if (strcmp (ifname, ifr->ifr_name) != 0)
+                       continue;
 
-#ifndef __linux__
-       if (getifaddrs (&ifap) != 0)
-               return NULL;
+#ifdef __linux__
+               /* Do something with the values at least */
+               if (hwaddr && hwlen)
+                       *hwlen = 0;
+#else
+               if (hwaddr && hwlen && ifr->ifr_addr.sa_family == AF_LINK) {
+                       struct sockaddr_dl sdl;
 
-       for (p = ifap; p; p = p->ifa_next) {
-               union {
-                       struct sockaddr *sa;
-                       struct sockaddr_dl *sdl;
-               } us;
+                       memcpy (&sdl, &ifr->ifr_addr, sizeof (struct sockaddr_dl));
+                       *hwlen = sdl.sdl_alen;
+                       memcpy (hwaddr, sdl.sdl_data + sdl.sdl_nlen, sdl.sdl_alen);
+                       retval = 1;
+                       break;
+               }
+#endif
 
-               if (strcmp (p->ifa_name, ifname) != 0)
-                       continue;
+               if (ifr->ifr_addr.sa_family == AF_INET) {
+                       memcpy (&address, &ifr->ifr_addr, sizeof (struct sockaddr_in));
+                       if (flush) {
+                               struct sockaddr_in netmask;
 
-               us.sa = p->ifa_addr;
+                               if (ioctl (s, SIOCGIFNETMASK, ifr) == -1) {
+                                       logger (LOG_ERR, "ioctl SIOCGIFNETMASK: %s",
+                                                       strerror (errno));
+                                       continue;
+                               }
+                               memcpy (&netmask, &ifr->ifr_addr, sizeof (struct sockaddr_in));
 
-               if (p->ifa_addr->sa_family != AF_LINK
-                       || (us.sdl->sdl_type != IFT_ETHER))
-                       /*
-                          && us.sdl->sdl_type != IFT_ISO88025))
-                          */
-               {
-                       logger (LOG_ERR, "interface is not Ethernet");
-                       freeifaddrs (ifap);
-                       return NULL;
+                               if (del_address (ifname,
+                                                                address.sin_addr, netmask.sin_addr) == -1)
+                                       retval = -1;
+                       } else if (get) {
+                               addr->s_addr = address.sin_addr.s_addr;
+                               retval = 1;
+                               break;
+                       } else if (address.sin_addr.s_addr == addr->s_addr) {
+                               retval = 1;
+                               break;
+                       }
                }
 
-               memcpy (hwaddr, us.sdl->sdl_data + us.sdl->sdl_nlen, ETHER_ADDR_LEN);
-               family = ARPHRD_ETHER;
-               hwlen = ETHER_ADDR_LEN;
-               break;
        }
-       freeifaddrs (ifap);
 
-       if (! p) {
-               logger (LOG_ERR, "could not find interface %s", ifname);
-               return NULL;
-       }
+       close (s);
+       free (ifc.ifc_buf);
+       return retval;
+}
+
+interface_t *read_interface (const char *ifname, int metric)
+{
+       int s;
+       struct ifreq ifr;
+       interface_t *iface;
+       unsigned char hwaddr[20];
+       int hwlen = 0;
+       sa_family_t family = 0;
+       unsigned short mtu;
+#ifdef __linux__
+       char *p;
 #endif
 
+       if (! ifname)
+               return NULL;
+
+       memset (hwaddr, sizeof (hwaddr), 0);
        memset (&ifr, 0, sizeof (struct ifreq));
        strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+
        if ((s = socket (AF_INET, SOCK_DGRAM, 0)) == -1) {
                logger (LOG_ERR, "socket: %s", strerror (errno));
                return NULL;
@@ -271,6 +319,14 @@ interface_t *read_interface (const char *ifname, int metric)
                close (s);
                return NULL;
        }
+       
+       if (_do_interface (ifname, hwaddr, &hwlen, NULL, false, false) != 1) {
+               logger (LOG_ERR, "could not find interface %s", ifname);
+               close (s);
+               return NULL;
+       }
+
+       family = ARPHRD_ETHER;
 #endif
 
        strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
@@ -512,27 +568,23 @@ static int do_route (const char *ifname,
        ADDADDR (destination);
 
        if (netmask.s_addr == INADDR_BROADCAST) {
-               struct ifaddrs *ifap, *ifa;
-
-               if (getifaddrs (&ifap)) {
-                       logger (LOG_ERR, "getifaddrs: %s", strerror (errno));
-                       close (s);
-                       return -1;
-               }
-
-               for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
-                       if (ifa->ifa_addr->sa_family != AF_LINK)
-                               continue;
-
-                       if (strcmp (ifname, ifa->ifa_name))
-                               continue;
-
-                       l = SA_SIZE (ifa->ifa_addr);
-                       memcpy (bp, ifa->ifa_addr, l);
-                       bp += l;
-                       break;
-               }
-               freeifaddrs (ifap);
+               /* Make us a link layer socket */
+               unsigned char hwaddr[HWADDR_LEN];
+               int hwlen = 0;
+
+               _do_interface (ifname, hwaddr, &hwlen, NULL, false, false);
+               memset (&su, 0, sizeof (struct sockaddr_storage));
+               su.sdl.sdl_len = sizeof (struct sockaddr_dl);
+               su.sdl.sdl_family = AF_LINK;
+               su.sdl.sdl_nlen = strlen (ifname);
+               memcpy (&su.sdl.sdl_data, ifname, su.sdl.sdl_nlen);
+               su.sdl.sdl_alen = hwlen;
+               memcpy (((unsigned char *) &su.sdl.sdl_data) + su.sdl.sdl_nlen,
+                               hwaddr, su.sdl.sdl_alen);
+
+               l = SA_SIZE (&(su.sa));
+               memcpy (bp, &su, l);
+               bp += l;
        } else {
                ADDADDR (gateway);
        }
@@ -910,128 +962,26 @@ int del_route (const char *ifname, struct in_addr destination,
        return (do_route (ifname, destination, netmask, gateway, metric, 0, 1));
 }
 
-#ifdef HAVE_IFADDRS_H
-static int _do_addresses (const char *ifname, struct in_addr *addr, bool flush, bool get)
-{
-       struct ifaddrs *ifap;
-       struct ifaddrs *p;
-       int retval = 0;
-
-       if (! ifname)
-               return -1;
-       if (getifaddrs (&ifap) != 0)
-               return -1;
-
-       for (p = ifap; p; p = p->ifa_next) {
-               union
-               {
-                       struct sockaddr *sa;
-                       struct sockaddr_in *sin;
-               } us_a, us_m;
-
-               if (strcmp (p->ifa_name, ifname) != 0)
-                       continue;
-
-               us_a.sa = p->ifa_addr;
-               us_m.sa = p->ifa_netmask;
-
-               if (us_a.sin->sin_family == AF_INET) {
-                       if (flush) {
-                               if (del_address (ifname, us_a.sin->sin_addr, us_m.sin->sin_addr)
-                                       == -1)
-                                       retval = -1;
-                       } else if (get) {
-                               addr->s_addr = us_a.sin->sin_addr.s_addr;
-                               retval = 1;
-                               break;
-                       } else {
-                               if (us_a.sin->sin_addr.s_addr == addr->s_addr) {
-                                       retval = 1;
-                                       break;
-                               }
-                       }
-               }
-       }
-       freeifaddrs (ifap);
-
-       return retval;
-}
-
-#else
-static int _do_addresses (const char *ifname, struct in_addr address, bool flush)
-{
-       int s;
-       struct ifconf ifc;
-       int retval = 0;
-       int i;
-       void *ifrs;
-       int nifs;
-       struct ifreq *ifr;
-
-       if ((s = socket (AF_INET, SOCK_DGRAM, 0)) == -1) {
-               logger (LOG_ERR, "socket: %s", strerror (errno));
-               return -1;
-       }
-
-       memset (&ifc, 0, sizeof (struct ifconf));
-       ifc.ifc_buf = NULL;
-       if (ioctl (s, SIOCGIFCONF, &ifc) == -1) {
-               logger (LOG_ERR, "ioctl SIOCGIFCONF: %s", strerror (errno));
-               close (s);
-       }
-
-       ifrs = xmalloc (ifc.ifc_len);
-       ifc.ifc_buf = ifrs;
-       if (ioctl (s, SIOCGIFCONF, &ifc) == -1) {
-               logger (LOG_ERR, "ioctl SIOCGIFCONF: %s", strerror (errno));
-               close (s);
-               free (ifrs);
-               return -1;
-       }
-
-       close (s);
-
-       nifs = ifc.ifc_len / sizeof (struct ifreq);
-       ifr = ifrs;
-       for (i = 0; i < nifs; i++) {
-               struct sockaddr_in *addr = (struct sockaddr_in *) &ifr->ifr_addr;
-               struct sockaddr_in *netm = (struct sockaddr_in *) &ifr->ifr_netmask;
-
-               if (ifr->ifr_addr.sa_family == AF_INET
-                       && strcmp (ifname, ifr->ifr_name) == 0)
-               {
-                       if (flush) {
-                               if (del_address (ifname, addr->sin_addr, netm->sin_addr) == -1)
-                                       retval = -1;
-                       } else if (addr->sin_addr.s_addr == address.s_addr) {
-                               retval = 1;
-                               break;
-                       }
-               }
-               ifr++;
-       }
-
-       free (ifrs);
-       return retval;
-}
-#endif
 
 int flush_addresses (const char *ifname)
 {
        struct in_addr address;
-       return (_do_addresses (ifname, &address, true, false));
+       unsigned char buf[1024];
+       int len = 0;
+
+       memset (buf, 0, 1023);
+       return (_do_interface (ifname, buf, &len, &address, true, false));
 }
 
 unsigned long get_address (const char *ifname)
 {
        struct in_addr address;
-       if (_do_addresses (ifname, &address, false, true) > 0)
+       if (_do_interface (ifname, NULL, NULL, &address, false, true) > 0)
                return (address.s_addr);
        return (0);
 }
 
 int has_address (const char *ifname, struct in_addr address)
 {
-       return (_do_addresses (ifname, &address, false, false));
+       return (_do_interface (ifname, NULL, NULL, &address, false, false));
 }
-
index dd07988186f1b711d980fc236eb34d3cb9125f20..eae71dd5cedaef40ca5b5750d08456e2f05e15e8 100644 (file)
@@ -33,8 +33,8 @@
 
 #include "config.h"
 #ifdef ENABLE_DUID
-#ifndef DUID_LENGTH_MAX
-#define DUID_LENGTH_MAX 128 + 2
+#ifndef DUID_LEN
+#  define DUID_LEN                             128 + 2
 #endif
 #endif
 
@@ -51,6 +51,8 @@
 #  define ARPHRD_INFINIBAND            27
 #endif
 
+#define HWADDR_LEN                             20      
+
 typedef struct route_t
 {
        struct in_addr destination; 
@@ -69,7 +71,7 @@ typedef struct interface_t
 {
        char name[IF_NAMESIZE];
        sa_family_t family;
-       unsigned char hwaddr[20];
+       unsigned char hwaddr[HWADDR_LEN];
        int hwlen;
        bool arpable;
        unsigned short mtu;
@@ -91,7 +93,7 @@ typedef struct interface_t
        long start_uptime;
 
 #ifdef ENABLE_DUID
-       unsigned char duid[DUID_LENGTH_MAX];
+       unsigned char duid[DUID_LEN];
        int duid_length;
 #endif
 } interface_t;