Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 573612 Details for
Bug 803540
DHCP server fails to start if the subnet is not the primary subnet for a device
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
Use getifaddrs() for interface discovery code on Linux
dhcp-4.1.1-P1-getifaddrs.patch (text/plain), 10.28 KB, created by
Jiri Popelka
on 2012-03-29 10:09:10 UTC
(
hide
)
Description:
Use getifaddrs() for interface discovery code on Linux
Filename:
MIME Type:
Creator:
Jiri Popelka
Created:
2012-03-29 10:09:10 UTC
Size:
10.28 KB
patch
obsolete
>diff -up dhcp-4.1.1-P1/common/discover.c.getifaddrs dhcp-4.1.1-P1/common/discover.c >--- dhcp-4.1.1-P1/common/discover.c.getifaddrs 2012-03-21 16:08:18.535717842 +0100 >+++ dhcp-4.1.1-P1/common/discover.c 2012-03-21 16:09:04.079723354 +0100 >@@ -367,394 +367,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,24 @@ 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)); >+ /* >+ * getifaddrs() can on Linux with some interfaces like PPP or TEQL >+ * result in a record with no address (ifa_addr). >+ */ >+ if (ifaces->next->ifa_addr != NULL) { >+/* Linux lacks the sa_len member in struct sockaddr. */ >+#if defined(__linux) >+ 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); >+#else >+ sa_len = ifaces->next->ifa_addr->sa_len; >+#endif >+ memcpy(&info->addr, ifaces->next->ifa_addr, sa_len); >+ } > info->flags = ifaces->next->ifa_flags; > ifaces->next = ifaces->next->ifa_next; > *err = 0;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 803540
: 573612