]> git.ipfire.org Git - people/ms/ipfire-3.x.git/blobdiff - dhcp/patches/dhcp-4.2.4-getifaddrs.patch
dhcp: Update to 4.2.4.
[people/ms/ipfire-3.x.git] / dhcp / patches / dhcp-4.2.4-getifaddrs.patch
diff --git a/dhcp/patches/dhcp-4.2.4-getifaddrs.patch b/dhcp/patches/dhcp-4.2.4-getifaddrs.patch
new file mode 100644 (file)
index 0000000..fe22da0
--- /dev/null
@@ -0,0 +1,431 @@
+diff -up dhcp-4.2.4rc2/common/discover.c.getifaddrs dhcp-4.2.4rc2/common/discover.c
+--- dhcp-4.2.4rc2/common/discover.c.getifaddrs 2012-05-25 18:05:29.592024035 +0200
++++ dhcp-4.2.4rc2/common/discover.c    2012-05-25 18:12:05.254266023 +0200
+@@ -379,394 +379,13 @@ end_iface_scan(struct iface_conf_list *i
+       ifaces->sock = -1;
+ }
+-#elif __linux /* !HAVE_SIOCGLIFCONF */
+-/* 
+- * Linux support
+- * -------------
+- *
+- * In Linux, we use the /proc pseudo-filesystem to get information
+- * about interfaces, along with selected ioctl() calls.
+- *
+- * Linux low level access is documented in the netdevice man page.
+- */
+-
+-/* 
+- * Structure holding state about the scan.
+- */
+-struct iface_conf_list {
+-      int sock;       /* file descriptor used to get information */
+-      FILE *fp;       /* input from /proc/net/dev */
+-#ifdef DHCPv6
+-      FILE *fp6;      /* input from /proc/net/if_inet6 */
+-#endif
+-};
+-
+-/* 
+- * Structure used to return information about a specific interface.
+- */
+-struct iface_info {
+-      char name[IFNAMSIZ];            /* name of the interface, e.g. "eth0" */
+-      struct sockaddr_storage addr;   /* address information */
+-      isc_uint64_t flags;             /* interface flags, e.g. IFF_LOOPBACK */
+-};
+-
+-/* 
+- * Start a scan of interfaces.
+- *
+- * The iface_conf_list structure maintains state for this process.
+- */
+-int 
+-begin_iface_scan(struct iface_conf_list *ifaces) {
+-      char buf[256];
+-      int len;
+-      int i;
+-
+-      ifaces->fp = fopen("/proc/net/dev", "re");
+-      if (ifaces->fp == NULL) {
+-              log_error("Error opening '/proc/net/dev' to list interfaces");
+-              return 0;
+-      }
+-
+-      /*
+-       * The first 2 lines are header information, so read and ignore them.
+-       */
+-      for (i=0; i<2; i++) {
+-              if (fgets(buf, sizeof(buf), ifaces->fp) == NULL) {
+-                      log_error("Error reading headers from '/proc/net/dev'");
+-                      fclose(ifaces->fp);
+-                      ifaces->fp = NULL;
+-                      return 0;
+-              }
+-              len = strlen(buf);
+-              if ((len <= 0) || (buf[len-1] != '\n')) { 
+-                      log_error("Bad header line in '/proc/net/dev'");
+-                      fclose(ifaces->fp);
+-                      ifaces->fp = NULL;
+-                      return 0;
+-              }
+-      }
+-
+-      ifaces->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+-      if (ifaces->sock < 0) {
+-              log_error("Error creating socket to list interfaces; %m");
+-              fclose(ifaces->fp);
+-              ifaces->fp = NULL;
+-              return 0;
+-      }
+-
+-#ifdef DHCPv6
+-      if ((local_family == AF_INET6) && !access("/proc/net/if_inet6", R_OK)) {
+-              ifaces->fp6 = fopen("/proc/net/if_inet6", "re");
+-              if (ifaces->fp6 == NULL) {
+-                      log_error("Error opening '/proc/net/if_inet6' to "
+-                                "list IPv6 interfaces; %m");
+-                      close(ifaces->sock);
+-                      ifaces->sock = -1;
+-                      fclose(ifaces->fp);
+-                      ifaces->fp = NULL;
+-                      return 0;
+-              }
+-      } else {
+-              ifaces->fp6 = NULL;
+-      }
+-#endif
+-
+-      return 1;
+-}
+-
+-/*
+- * Read our IPv4 interfaces from /proc/net/dev.
+- *
+- * The file looks something like this:
+- *
+- * Inter-|   Receive ...
+- *  face |bytes    packets errs drop fifo frame ...
+- *     lo: 1580562    4207    0    0    0     0 ...
+- *   eth0:       0       0    0    0    0     0 ...
+- *   eth1:1801552440   37895    0   14    0     ...
+- *
+- * We only care about the interface name, which is at the start of 
+- * each line.
+- *
+- * We use an ioctl() to get the address and flags for each interface.
+- */
+-static int
+-next_iface4(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
+-      char buf[256];
+-      int len;
+-      char *p;
+-      char *name;
+-      struct ifreq tmp;
+-
+-      /*
+-       * Loop exits when we find an interface that has an address, or 
+-       * when we run out of interfaces.
+-       */
+-      for (;;) {
+-              do {
+-                      /*
+-                       *  Read the next line in the file.
+-                       */
+-                      if (fgets(buf, sizeof(buf), ifaces->fp) == NULL) {
+-                              if (ferror(ifaces->fp)) {
+-                                      *err = 1;
+-                                      log_error("Error reading interface "
+-                                              "information");
+-                              } else {
+-                                      *err = 0;
+-                              }
+-                              return 0;
+-                      }
+-
+-                      /*
+-                       * Make sure the line is a nice, 
+-                       * newline-terminated line.
+-                       */
+-                      len = strlen(buf);
+-                      if ((len <= 0) || (buf[len-1] != '\n')) { 
+-                              log_error("Bad line reading interface "
+-                                        "information");
+-                              *err = 1;
+-                              return 0;
+-                      }
+-
+-                      /*
+-                       * Figure out our name.
+-                       */
+-                      p = strrchr(buf, ':');
+-                      if (p == NULL) {
+-                              log_error("Bad line reading interface "
+-                                        "information (no colon)");
+-                              *err = 1;
+-                              return 0;
+-                      }
+-                      *p = '\0';
+-                      name = buf;
+-                      while (isspace(*name)) {
+-                              name++;
+-                      }
+-
+-                      /* 
+-                       * Copy our name into our interface structure.
+-                       */
+-                      len = p - name;
+-                      if (len >= sizeof(info->name)) {
+-                              *err = 1;
+-                              log_error("Interface name '%s' too long", name);
+-                              return 0;
+-                      }
+-                      strcpy(info->name, name);
+-
+-#ifdef ALIAS_NAMED_PERMUTED
+-                      /* interface aliases look like "eth0:1" or "wlan1:3" */
+-                      s = strchr(info->name, ':');
+-                      if (s != NULL) {
+-                              *s = '\0';
+-                      }
+-#endif
+-
+-#ifdef SKIP_DUMMY_INTERFACES
+-              } while (strncmp(info->name, "dummy", 5) == 0);
+-#else
+-              } while (0);
+-#endif
+-
+-              memset(&tmp, 0, sizeof(tmp));
+-              strcpy(tmp.ifr_name, name);
+-              if (ioctl(ifaces->sock, SIOCGIFADDR, &tmp) < 0) {
+-                      if (errno == EADDRNOTAVAIL) {
+-                              continue;
+-                      }
+-                      log_error("Error getting interface address "
+-                                "for '%s'; %m", name);
+-                      *err = 1;
+-                      return 0;
+-              }
+-              memcpy(&info->addr, &tmp.ifr_addr, sizeof(tmp.ifr_addr));
+-
+-              memset(&tmp, 0, sizeof(tmp));
+-              strcpy(tmp.ifr_name, name);
+-              if (ioctl(ifaces->sock, SIOCGIFFLAGS, &tmp) < 0) {
+-                      log_error("Error getting interface flags for '%s'; %m", 
+-                              name);
+-                      *err = 1;
+-                      return 0;
+-              }
+-              info->flags = tmp.ifr_flags;
+-
+-              *err = 0;
+-              return 1;
+-      }
+-}
+-
+-#ifdef DHCPv6
+-/*
+- * Read our IPv6 interfaces from /proc/net/if_inet6.
+- *
+- * The file looks something like this:
+- *
+- * fe80000000000000025056fffec00008 05 40 20 80   vmnet8
+- * 00000000000000000000000000000001 01 80 10 80       lo
+- * fe80000000000000025056fffec00001 06 40 20 80   vmnet1
+- * 200108881936000202166ffffe497d9b 03 40 00 00     eth1
+- * fe8000000000000002166ffffe497d9b 03 40 20 80     eth1
+- *
+- * We get IPv6 address from the start, the interface name from the end, 
+- * and ioctl() to get flags.
+- */
+-static int
+-next_iface6(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
+-      char buf[256];
+-      int len;
+-      char *p;
+-      char *name;
+-      int i;
+-      struct sockaddr_in6 addr;
+-      struct ifreq tmp;
+-
+-      do {
+-              /*
+-               *  Read the next line in the file.
+-               */
+-              if (fgets(buf, sizeof(buf), ifaces->fp6) == NULL) {
+-                      if (ferror(ifaces->fp6)) {
+-                              *err = 1;
+-                              log_error("Error reading IPv6 "
+-                                        "interface information");
+-                      } else {
+-                              *err = 0;
+-                      }
+-                      return 0;
+-              }
+-
+-              /*
+-               * Make sure the line is a nice, newline-terminated line.
+-               */
+-              len = strlen(buf);
+-              if ((len <= 0) || (buf[len-1] != '\n')) { 
+-                      log_error("Bad line reading IPv6 "
+-                                "interface information");
+-                      *err = 1;
+-                      return 0;
+-              }
+-
+-              /*
+-               * Figure out our name.
+-               */
+-              buf[--len] = '\0';
+-              p = strrchr(buf, ' ');
+-              if (p == NULL) {
+-                      log_error("Bad line reading IPv6 interface "
+-                                "information (no space)");
+-                      *err = 1;
+-                      return 0;
+-              }
+-              name = p+1;
+-
+-              /* 
+-               * Copy our name into our interface structure.
+-               */
+-              len = strlen(name);
+-              if (len >= sizeof(info->name)) {
+-                      *err = 1;
+-                      log_error("IPv6 interface name '%s' too long", name);
+-                      return 0;
+-              }
+-              strcpy(info->name, name);
+-
+-#ifdef SKIP_DUMMY_INTERFACES
+-      } while (strncmp(info->name, "dummy", 5) == 0);
+-#else
+-      } while (0);
+-#endif
+-
+-      /*
+-       * Double-check we start with the IPv6 address.
+-       */
+-      for (i=0; i<32; i++) {
+-              if (!isxdigit(buf[i]) || isupper(buf[i])) {
+-                      *err = 1;
+-                      log_error("Bad line reading IPv6 interface address "
+-                                "for '%s'", name);
+-                      return 0;
+-              }
+-      }
+-
+-      /* 
+-       * Load our socket structure.
+-       */
+-      memset(&addr, 0, sizeof(addr));
+-      addr.sin6_family = AF_INET6;
+-      for (i=0; i<16; i++) {
+-              unsigned char byte;
+-                static const char hex[] = "0123456789abcdef";
+-                byte = ((index(hex, buf[i * 2]) - hex) << 4) |
+-                      (index(hex, buf[i * 2 + 1]) - hex);
+-              addr.sin6_addr.s6_addr[i] = byte;
+-      }
+-      memcpy(&info->addr, &addr, sizeof(addr));
+-
+-      /*
+-       * Get our flags.
+-       */
+-      memset(&tmp, 0, sizeof(tmp));
+-      strcpy(tmp.ifr_name, name);
+-      if (ioctl(ifaces->sock, SIOCGIFFLAGS, &tmp) < 0) {
+-              log_error("Error getting interface flags for '%s'; %m", name);
+-              *err = 1;
+-              return 0;
+-      }
+-      info->flags = tmp.ifr_flags;
+-
+-      *err = 0;
+-      return 1;
+-}
+-#endif /* DHCPv6 */
+-
+-/*
+- * Retrieve the next interface.
+- *
+- * Returns information in the info structure. 
+- * Sets err to 1 if there is an error, otherwise 0.
+- */
+-int
+-next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
+-      if (next_iface4(info, err, ifaces)) {
+-              return 1;
+-      }
+-#ifdef DHCPv6
+-      if (!(*err) && ifaces->fp6) {
+-              if (local_family == AF_INET6)
+-                      return next_iface6(info, err, ifaces);
+-      }
+-#endif
+-      return 0;
+-}
+-
+-/*
+- * End scan of interfaces.
+- */
+-void
+-end_iface_scan(struct iface_conf_list *ifaces) {
+-      fclose(ifaces->fp);
+-      ifaces->fp = NULL;
+-      close(ifaces->sock);
+-      ifaces->sock = -1;
+-#ifdef DHCPv6
+-      if (local_family == AF_INET6) {
+-              if (ifaces->fp6)
+-                      fclose(ifaces->fp6);
+-              ifaces->fp6 = NULL;
+-      }
+-#endif
+-}
+ #else
+ /* 
+  * BSD support
+  * -----------
+  *
+- * FreeBSD, NetBSD, OpenBSD, and OS X all have the getifaddrs() 
++ * FreeBSD, NetBSD, OpenBSD, OS X and Linux all have the getifaddrs() 
+  * function.
+  *
+  * The getifaddrs() man page describes the use.
+@@ -814,6 +433,8 @@ begin_iface_scan(struct iface_conf_list
+  */
+ int
+ next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
++      size_t sa_len = 0;
++
+       if (ifaces->next == NULL) {
+               *err = 0;
+               return 0;
+@@ -825,8 +446,20 @@ next_iface(struct iface_info *info, int
+               return 0;
+       }
+       strcpy(info->name, ifaces->next->ifa_name);
+-      memcpy(&info->addr, ifaces->next->ifa_addr, 
+-             ifaces->next->ifa_addr->sa_len);
++
++      memset(&info->addr, 0 , sizeof(info->addr));
++
++      if (ifaces->next->ifa_addr != NULL) {
++#ifdef HAVE_SA_LEN
++              sa_len = ifaces->next->ifa_addr->sa_len;
++#else
++              if (ifaces->next->ifa_addr->sa_family == AF_INET)
++                      sa_len = sizeof(struct sockaddr_in);
++              else if (ifaces->next->ifa_addr->sa_family == AF_INET6)
++                      sa_len = sizeof(struct sockaddr_in6);
++#endif
++              memcpy(&info->addr, ifaces->next->ifa_addr, sa_len);
++      }
+       info->flags = ifaces->next->ifa_flags;
+       ifaces->next = ifaces->next->ifa_next;
+       *err = 0;