diff -Nru isc-dhcp-4.3.1/debian/changelog isc-dhcp-4.3.1/debian/changelog --- isc-dhcp-4.3.1/debian/changelog 2015-01-15 12:02:07.000000000 +0000 +++ isc-dhcp-4.3.1/debian/changelog 2015-04-21 19:25:33.000000000 +0000 @@ -1,3 +1,10 @@ +isc-dhcp (4.3.1-5ubuntu2.1) vivid; urgency=medium + + * debian/patches/dhcp-getifaddrs.patch: use getifaddrs + for getting nic addresses rather than /proc/net (LP: #1446767) + + -- Scott Moser Tue, 21 Apr 2015 18:10:40 +0000 + isc-dhcp (4.3.1-5ubuntu2) vivid; urgency=medium * Add systemd units for -server and -relay. Note that we don't use the -q diff -Nru isc-dhcp-4.3.1/debian/patches/dhcp-getifaddrs.patch isc-dhcp-4.3.1/debian/patches/dhcp-getifaddrs.patch --- isc-dhcp-4.3.1/debian/patches/dhcp-getifaddrs.patch 1970-01-01 00:00:00.000000000 +0000 +++ isc-dhcp-4.3.1/debian/patches/dhcp-getifaddrs.patch 2015-04-21 19:24:24.000000000 +0000 @@ -0,0 +1,437 @@ +Description: read address info using getifaddrs rather than /proc/net + This fixes a race condition when network devices are being renamed + while dhclient is iterating over interfaces. See ubuntu bug for + recreate. +Origin: Fedora, http://pkgs.fedoraproject.org/cgit/dhcp.git/tree/dhcp-getifaddrs.patch?id=d12e0eb05e510268ce9b8dcb839e27d5eca9aff5 +Bug: https://bugs.launchpad.net/ubuntu/+source/isc-dhcp/+bug/1446767 +Fedora-Bug: https://bugzilla.redhat.com/show_bug.cgi?id=449946 + +Index: isc-dhcp-4.3.1/common/discover.c +=================================================================== +--- isc-dhcp-4.3.1.orig/common/discover.c ++++ isc-dhcp-4.3.1/common/discover.c +@@ -373,391 +373,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. +- */ +-#include +-/* +- * 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[IF_LINE_LENGTH]; +- int len; +- int i; +- +- ifaces->fp = fopen("/proc/net/dev", "r"); +- 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) { +- ifaces->fp6 = fopen("/proc/net/if_inet6", "r"); +- 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; +- } +- } +-#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[IF_LINE_LENGTH]; +- 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[IF_LINE_LENGTH]; +- 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)) { +- 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) { +- 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. +@@ -805,6 +427,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; +@@ -816,8 +440,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; diff -Nru isc-dhcp-4.3.1/debian/patches/series isc-dhcp-4.3.1/debian/patches/series --- isc-dhcp-4.3.1/debian/patches/series 2014-11-05 17:52:44.000000000 +0000 +++ isc-dhcp-4.3.1/debian/patches/series 2015-04-21 19:23:18.000000000 +0000 @@ -21,3 +21,4 @@ infiniband_lpf infiniband_improved_xid 64_time_large_lease.patch +dhcp-getifaddrs.patch