]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Linux systems without glibc-2.3 don't have getifaddrs, so we define our own.
authorRoy Marples <roy@marples.name>
Sun, 3 Dec 2006 10:28:57 +0000 (10:28 +0000)
committerRoy Marples <roy@marples.name>
Sun, 3 Dec 2006 10:28:57 +0000 (10:28 +0000)
ChangeLog
Makefile
interface.c

index 2704d6804d77773364e9bcd5b6fc88b26874f514..77f5750a9819d37964120aec22be6bc5023e28a6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,8 +1,10 @@
+dhcpcd-3.0.2
+Linux systems without glibc-2.3 don't have getifaddrs, so we define our own.
 Changed the default timeout to 20 seconds, allowing hme Sparc drivers to work.
 Set the rfds correctly so we can get a reply after re-sending a request.
 Set the seconds elasped and maximum message size correctly in DHCP messages.
 Now compiles on Linux 2.4 kernels. 
-xmalloc dhcp objects so we can swap pointer around easily.
+xmalloc dhcp objects so we can swap the pointers around easily.
 
 dhcpcd-3.0.1
 Quote all vars in the info file.
index 1c1992c9f15731d53cd95852b686139494e7ff2e..4dd51dcf81e69ae13a2eb8c1bd326fbb128e8245 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 # Should work for both GNU make and BSD mke
 
-VERSION = 3.0.2_pre1
+VERSION = 3.0.2
 
 INSTALL ?= install
 CFLAGS ?= -Wall -O2 -pedantic -std=gnu99
index 7631fafbc92416235729a781ce0e1bb10e406a09..c678e66d35069bec7a9ea7be20e54dde29c2ca77 100644 (file)
 /* Netlink suff */
 #ifdef __linux__ 
 #include <asm/types.h> /* Needed for 2.4 kernels */
+#include <features.h>
 #include <linux/netlink.h>
 #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) && __GLIBC_PREREQ (2,3)
+#define HAVE_IFADDRS_H
+#include <ifaddrs.h>
+#endif
 #else
 #include <net/if_dl.h>
 #include <net/if_types.h>
 #include <net/route.h>
 #include <netinet/in.h>
-#endif /* __linux__ */
+#define HAVE_IFADDRS_H
+#include <ifaddrs.h>
+#endif
 
 #include <errno.h>
-#include <ifaddrs.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -84,6 +91,8 @@ void free_route (route_t *routes)
     }
 }
 
+
+
 interface_t *read_interface (const char *ifname, int metric)
 {
   if (! ifname)
@@ -94,6 +103,7 @@ interface_t *read_interface (const char *ifname, int metric)
   interface_t *iface;
   unsigned char hwaddr[ETHER_ADDR_LEN];
 
+#ifndef __linux__
   struct ifaddrs *ifap;
   struct ifaddrs *p;
 
@@ -104,25 +114,16 @@ interface_t *read_interface (const char *ifname, int metric)
     {
       if (strcmp (p->ifa_name, ifname) != 0)
        continue;
-#ifdef __linux__
-      struct sockaddr_ll *sll = (struct sockaddr_ll*) p->ifa_addr;
-      if (p->ifa_addr->sa_family != AF_PACKET
-         || sll->sll_hatype != ARPHRD_ETHER)
-#else
-       struct sockaddr_dl *sdl = (struct sockaddr_dl *) p->ifa_addr;
+       
+      struct sockaddr_dl *sdl = (struct sockaddr_dl *) p->ifa_addr;
       if (p->ifa_addr->sa_family != AF_LINK || sdl->sdl_type != IFT_ETHER)
-#endif
        {
          logger (LOG_ERR, "not Ethernet");
          freeifaddrs (ifap);
          return NULL;
        }
 
-#ifdef __linux__
-      memcpy (hwaddr, sll->sll_addr, ETHER_ADDR_LEN);
-#else
       memcpy (hwaddr, sdl->sdl_data + sdl->sdl_nlen, ETHER_ADDR_LEN);
-#endif
       break;
     }
   freeifaddrs (ifap);
@@ -132,18 +133,33 @@ interface_t *read_interface (const char *ifname, int metric)
       logger (LOG_ERR, "could not find interface %s", ifname);
       return NULL;
     }
+#endif
 
   memset (&ifr, 0, sizeof (struct ifreq));
   strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
-  if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+  if ((s = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
     {
       logger (LOG_ERR, "socket: %s", strerror (errno));
       return NULL;
     }
 
-#ifndef __linux__
+#ifdef __linux__
+  if (ioctl (s, SIOCGIFHWADDR, &ifr) <0)
+    {
+      logger (LOG_ERR, "ioctl SIOCGIFHWADDR: %s", strerror(errno));
+      close (s);
+      return NULL;
+    }
+  if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER)
+    {
+      logger (LOG_ERR, "interface is not Ethernet");
+      close (s);
+      return NULL;
+    }
+  memcpy (&hwaddr, &ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
+#else
   ifr.ifr_metric = metric;
-  if (ioctl(s, SIOCSIFMETRIC, &ifr) < 0)
+  if (ioctl (s, SIOCSIFMETRIC, &ifr) < 0)
     {
       logger (LOG_ERR, "ioctl SIOCSIFMETRIC: %s", strerror (errno));
       close (s);
@@ -637,7 +653,25 @@ int del_address (const char *ifname, struct in_addr address)
   return (do_address (ifname, address, t, t, 1));
 }
 
-/* This should work on all platforms */
+int add_route (const char *ifname, struct in_addr destination,
+              struct in_addr netmask, struct in_addr gateway, int metric)
+{
+  return (do_route (ifname, destination, netmask, gateway, metric, 0, 0));
+}
+
+int change_route (const char *ifname, struct in_addr destination,
+                 struct in_addr netmask, struct in_addr gateway, int metric)
+{
+  return (do_route (ifname, destination, netmask, gateway, metric, 1, 0));
+}
+
+int del_route (const char *ifname, struct in_addr destination,
+              struct in_addr netmask, struct in_addr gateway, int metric)
+{
+  return (do_route (ifname, destination, netmask, gateway, metric, 0, 1));
+}
+
+#ifdef HAVE_IFADDRS_H
 int flush_addresses (const char *ifname)
 {
   if (! ifname)
@@ -649,6 +683,7 @@ int flush_addresses (const char *ifname)
   if (getifaddrs (&ifap) != 0)
     return -1;
 
+  int retval = 0;
   for (p = ifap; p; p = p->ifa_next)
     {
       if (strcmp (p->ifa_name, ifname) != 0)
@@ -656,28 +691,61 @@ int flush_addresses (const char *ifname)
 
       struct sockaddr_in *sin = (struct sockaddr_in*) p->ifa_addr;
       if (sin->sin_family == AF_INET)
-       del_address (ifname, sin->sin_addr);
+       if (del_address (ifname, sin->sin_addr) < 0)
+         retval = -1;
     }
   freeifaddrs (ifap);
 
-  return 0;
+  return retval;
 }
-
-int add_route (const char *ifname, struct in_addr destination,
-              struct in_addr netmask, struct in_addr gateway, int metric)
+#else
+int flush_addresses (const char *ifname)
 {
-  return (do_route (ifname, destination, netmask, gateway, metric, 0, 0));
-}
+  int s;
+  if ((s = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
+    {
+      logger (LOG_ERR, "socket: %s", strerror (errno));
+      return -1;
+    }
 
-int change_route (const char *ifname, struct in_addr destination,
-                 struct in_addr netmask, struct in_addr gateway, int metric)
-{
-  return (do_route (ifname, destination, netmask, gateway, metric, 1, 0));
-}
+  struct ifconf ifc;
+  memset (&ifc, 0, sizeof (struct ifconf));
+  ifc.ifc_buf = NULL;
+  if (ioctl (s, SIOCGIFCONF, &ifc) < 0)
+    {
+      logger (LOG_ERR, "ioctl SIOCGIFCONF: %s", strerror (errno));
+      close (s);
+    }
 
-int del_route (const char *ifname, struct in_addr destination,
-              struct in_addr netmask, struct in_addr gateway, int metric)
-{
-  return (do_route (ifname, destination, netmask, gateway, metric, 0, 1));
-}
+  void *ifrs = xmalloc (ifc.ifc_len);
+  ifc.ifc_buf = ifrs;
+  if (ioctl (s, SIOCGIFCONF, &ifc) < 0)
+    {
+      logger (LOG_ERR, "ioctl SIOCGIFCONF: %s", strerror (errno));
+      close (s);
+      free (ifrs);
+      return -1;
+    }
+
+  close (s);
+
+  int nifs = ifc.ifc_len / sizeof (struct ifreq);
+  struct ifreq *ifr = ifrs;
+  int retval = 0;
+  int i;
+  for (i = 0; i < nifs; i++)
+    {
+      if (ifr->ifr_addr.sa_family != AF_INET
+         || strcmp (ifname, ifr->ifr_name) != 0)
+       continue;
+
+      struct sockaddr_in *in = (struct sockaddr_in *) &ifr->ifr_addr;
+      if (del_address (ifname, in->sin_addr) < 0)
+       retval = -1;
+      ifr++;
+    }
 
+  free (ifrs);
+  return retval;
+}
+#endif