File dhcp-4.2.4-interface-discovery-using-getifaddrs.patch of Package dhcp

From 29ef7e3c25a709e8f0daadc41f34360ac6d88435 Mon Sep 17 00:00:00 2001
From: Marius Tomaschewski <mt@suse.de>
Date: Tue, 27 Nov 2012 17:44:06 +0100
References: bnc#791289
Upstream: sent [ISC-Bugs #31992]
Subject: [PATCH] Fixed linux interface discovery using getifaddrs

Unlike dhcp 3.x, dhcp 4.x scans interfaces from /proc/net/dev,
which provides only true interface names. When the address set
on the interface has a label assigned (linux 2.0 alias interface
compatibility), then the SIOCGIFADDR requires the label / alias
name as argument instead of the interface name to return this
address. When this is the only address assigned to an interface,
dhcp-server is unable to find any address and fails to start.

Changed to use getifaddrs() function, which retrieves all IP
addresses on linux systems and is available since GLIBC 2.3.

Signed-off-by: Marius Tomaschewski <mt@suse.de>
---
 common/discover.c |   51 ++++++++++++++++++++++++++++++++++++++++++++-------
 1 Datei geändert, 44 Zeilen hinzugefügt(+), 7 Zeilen entfernt(-)

diff --git a/common/discover.c b/common/discover.c
index 1d84219..cbcb1b9 100644
--- a/common/discover.c
+++ b/common/discover.c
@@ -379,7 +379,7 @@ end_iface_scan(struct iface_conf_list *ifaces) {
 	ifaces->sock = -1;
 }
 
-#elif __linux /* !HAVE_SIOCGLIFCONF */
+#elif __linux && !(defined(__GNUC_PREREQ) && __GNUC_PREREQ(2,3)) /* !HAVE_SIOCGLIFCONF */
 /* 
  * Linux support
  * -------------
@@ -388,6 +388,14 @@ end_iface_scan(struct iface_conf_list *ifaces) {
  * about interfaces, along with selected ioctl() calls.
  *
  * Linux low level access is documented in the netdevice man page.
+ *
+ * Note: Use getifaddrs instead
+ *   Unfortunately this discover discards all interfaces where the
+ *   only address has a label assigned (linux 2.0 alias interface
+ *   compatibility) as the SIOCGIFADDR requires the the alias name
+ *   (eth0:0) in ifr_name to fetch the address and /proc/net/dev
+ *   on linux > 2.0 lists only the interface names (eth0) without
+ *   any aliases.
  */
 
 /* 
@@ -760,11 +768,11 @@ end_iface_scan(struct iface_conf_list *ifaces) {
 #else
 
 /* 
- * BSD support
- * -----------
+ * BSD & Linux support
+ * -------------------
  *
  * FreeBSD, NetBSD, OpenBSD, and OS X all have the getifaddrs() 
- * function.
+ * function. Linux has it since glibc 2.3.
  *
  * The getifaddrs() man page describes the use.
  */
@@ -821,10 +829,39 @@ next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
 		*err = 1;
 		return 0;
 	}
-	strcpy(info->name, ifaces->next->ifa_name);
-	memcpy(&info->addr, ifaces->next->ifa_addr, 
-	       ifaces->next->ifa_addr->sa_len);
+	info->addr.ss_family = AF_UNSPEC;
 	info->flags = ifaces->next->ifa_flags;
+#ifdef __linux
+	if (strchr(ifaces->next->ifa_name, ':')) {
+		/*
+		 * the name contains a ':', which may
+		 * be a IPv4 "alias interface" label;
+		 * resolve to the true interface name
+		 */
+		if_indextoname(if_nametoindex(ifaces->next->ifa_name),
+				info->name);
+	} else {
+		strcpy(info->name, ifaces->next->ifa_name);
+	}
+
+	if (ifaces->next->ifa_addr != NULL) {
+		if (ifaces->next->ifa_addr->sa_family == AF_INET) {
+			memcpy(&info->addr, ifaces->next->ifa_addr,
+					sizeof(struct sockaddr_in));
+		} else
+		if (ifaces->next->ifa_addr->sa_family == AF_INET6) {
+			memcpy(&info->addr, ifaces->next->ifa_addr,
+					sizeof(struct sockaddr_in6));
+		}
+		/* else e.g. AF_PACKET / link layer address  */
+	}
+#else
+	strcpy(info->name, ifaces->next->ifa_name);
+	if (ifaces->next->ifa_addr != NULL) {
+		memcpy(&info->addr, ifaces->next->ifa_addr,
+		       ifaces->next->ifa_addr->sa_len);
+	}
+#endif
 	ifaces->next = ifaces->next->ifa_next;
 	*err = 0;
 	return 1;
-- 
1.7.10.4
openSUSE Build Service is sponsored by