[dhcp] don't crash on aliased infiniband interface (#996518)

Jiří Popelka jpopelka at fedoraproject.org
Mon Aug 26 10:25:42 UTC 2013


commit 63fcbf9a0a0ea575f075e3e0b20a4bfc0c8bbfbf
Author: Jiri Popelka <jpopelka at redhat.com>
Date:   Mon Aug 26 12:20:12 2013 +0200

    don't crash on aliased infiniband interface (#996518)

 dhcp-4.2.2-gpxe-cid.patch |   11 -----
 dhcp-4.2.5-lpf-ib.patch   |   92 ++++++++++++++++++++++++++++----------------
 dhcp.spec                 |    5 ++-
 3 files changed, 62 insertions(+), 46 deletions(-)
---
diff --git a/dhcp-4.2.2-gpxe-cid.patch b/dhcp-4.2.2-gpxe-cid.patch
index fd73b2c..fd6cb24 100644
--- a/dhcp-4.2.2-gpxe-cid.patch
+++ b/dhcp-4.2.2-gpxe-cid.patch
@@ -70,14 +70,3 @@ diff -up dhcp-4.2.2/client/dhclient.c.gpxe-cid dhcp-4.2.2/client/dhclient.c
  }
  
  /* Individual States:
-diff -up dhcp-4.2.2/common/lpf.c.gpxe-cid dhcp-4.2.2/common/lpf.c
---- dhcp-4.2.2/common/lpf.c.gpxe-cid	2011-09-16 18:23:20.183453996 +0200
-+++ dhcp-4.2.2/common/lpf.c	2011-09-16 18:25:28.235804421 +0200
-@@ -698,6 +698,7 @@ get_hw_addr(struct interface_info *info)
- 
- 			hw->hlen = 1;
- 			hw->hbuf[0] = HTYPE_INFINIBAND;
-+			memcpy(&hw->hbuf[1], &sll->sll_addr[sll->sll_halen - 8], 8);
- 			break;
- #if defined(ARPHRD_PPP)
- 		case ARPHRD_PPP:
diff --git a/dhcp-4.2.5-lpf-ib.patch b/dhcp-4.2.5-lpf-ib.patch
index c885331..58b924a 100644
--- a/dhcp-4.2.5-lpf-ib.patch
+++ b/dhcp-4.2.5-lpf-ib.patch
@@ -1,6 +1,6 @@
-diff -up dhcp-4.2.4-P2/client/dhclient.c.lpf-ib dhcp-4.2.4-P2/client/dhclient.c
---- dhcp-4.2.4-P2/client/dhclient.c.lpf-ib	2012-11-30 14:05:07.399394154 +0100
-+++ dhcp-4.2.4-P2/client/dhclient.c	2012-11-30 14:05:07.406394070 +0100
+diff -up dhcp-4.2.5/client/dhclient.c.lpf-ib dhcp-4.2.5/client/dhclient.c
+--- dhcp-4.2.5/client/dhclient.c.lpf-ib	2013-08-26 12:13:31.509170257 +0200
++++ dhcp-4.2.5/client/dhclient.c	2013-08-26 12:13:31.515170176 +0200
 @@ -113,6 +113,8 @@ static int check_domain_name_list(const
  static int check_option_values(struct universe *universe, unsigned int opt,
  			       const char *ptr, size_t len);
@@ -55,9 +55,9 @@ diff -up dhcp-4.2.4-P2/client/dhclient.c.lpf-ib dhcp-4.2.4-P2/client/dhclient.c
  /* Individual States:
   *
   * Each routine is called from the dhclient_state_machine() in one of
-diff -up dhcp-4.2.4-P2/common/bpf.c.lpf-ib dhcp-4.2.4-P2/common/bpf.c
---- dhcp-4.2.4-P2/common/bpf.c.lpf-ib	2012-11-30 14:05:07.394394214 +0100
-+++ dhcp-4.2.4-P2/common/bpf.c	2012-11-30 14:05:07.407394058 +0100
+diff -up dhcp-4.2.5/common/bpf.c.lpf-ib dhcp-4.2.5/common/bpf.c
+--- dhcp-4.2.5/common/bpf.c.lpf-ib	2013-08-26 12:13:31.503170337 +0200
++++ dhcp-4.2.5/common/bpf.c	2013-08-26 12:13:31.515170176 +0200
 @@ -198,11 +198,44 @@ struct bpf_insn dhcp_bpf_filter [] = {
  	BPF_STMT(BPF_RET+BPF_K, 0),
  };
@@ -103,10 +103,10 @@ diff -up dhcp-4.2.4-P2/common/bpf.c.lpf-ib dhcp-4.2.4-P2/common/bpf.c
  #if defined (HAVE_TR_SUPPORT)
  struct bpf_insn dhcp_bpf_tr_filter [] = {
          /* accept all token ring packets due to variable length header */
-diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
---- dhcp-4.2.4-P2/common/lpf.c.lpf-ib	2012-11-30 14:05:07.394394214 +0100
-+++ dhcp-4.2.4-P2/common/lpf.c	2012-11-30 14:19:27.211031532 +0100
-@@ -42,6 +42,7 @@
+diff -up dhcp-4.2.5/common/lpf.c.lpf-ib dhcp-4.2.5/common/lpf.c
+--- dhcp-4.2.5/common/lpf.c.lpf-ib	2013-08-26 12:13:31.503170337 +0200
++++ dhcp-4.2.5/common/lpf.c	2013-08-26 12:14:00.196783751 +0200
+@@ -43,6 +43,7 @@
  #include "includes/netinet/udp.h"
  #include "includes/netinet/if_ether.h"
  #include <net/if.h>
@@ -114,7 +114,7 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
  
  #ifndef PACKET_AUXDATA
  #define PACKET_AUXDATA 8
-@@ -59,6 +60,15 @@ struct tpacket_auxdata
+@@ -60,6 +61,15 @@ struct tpacket_auxdata
  /* Reinitializes the specified interface after an address change.   This
     is not required for packet-filter APIs. */
  
@@ -130,7 +130,7 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
  #ifdef USE_LPF_SEND
  void if_reinitialize_send (info)
  	struct interface_info *info;
-@@ -86,10 +96,21 @@ int if_register_lpf (info)
+@@ -87,10 +97,21 @@ int if_register_lpf (info)
  		struct sockaddr common;
  	} sa;
  	struct ifreq ifr;
@@ -154,7 +154,7 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
  		if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
  		    errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
  		    errno == EAFNOSUPPORT || errno == EINVAL) {
-@@ -112,6 +133,7 @@ int if_register_lpf (info)
+@@ -113,6 +134,7 @@ int if_register_lpf (info)
  	/* Bind to the interface name */
  	memset (&sa, 0, sizeof sa);
  	sa.ll.sll_family = AF_PACKET;
@@ -162,7 +162,7 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
  	sa.ll.sll_ifindex = ifr.ifr_ifindex;
  	if (bind (sock, &sa.common, sizeof sa)) {
  		if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
-@@ -127,8 +149,6 @@ int if_register_lpf (info)
+@@ -128,8 +150,6 @@ int if_register_lpf (info)
  		log_fatal ("Bind socket to interface: %m");
  	}
  
@@ -171,7 +171,7 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
  	return sock;
  }
  #endif /* USE_LPF_SEND || USE_LPF_RECEIVE */
-@@ -183,6 +203,8 @@ void if_deregister_send (info)
+@@ -184,6 +204,8 @@ void if_deregister_send (info)
     in bpf includes... */
  extern struct sock_filter dhcp_bpf_filter [];
  extern int dhcp_bpf_filter_len;
@@ -180,7 +180,7 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
  
  #if defined (HAVE_TR_SUPPORT)
  extern struct sock_filter dhcp_bpf_tr_filter [];
-@@ -200,11 +222,13 @@ void if_register_receive (info)
+@@ -201,11 +223,13 @@ void if_register_receive (info)
  	/* Open a LPF device and hang it on this interface... */
  	info -> rfdesc = if_register_lpf (info);
  
@@ -199,7 +199,7 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
  	}
  
  #if defined (HAVE_TR_SUPPORT)
-@@ -250,15 +274,28 @@ static void lpf_gen_filter_setup (info)
+@@ -251,15 +275,28 @@ static void lpf_gen_filter_setup (info)
  
  	memset(&p, 0, sizeof(p));
  
@@ -237,7 +237,7 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
  
  	if (setsockopt (info -> rfdesc, SOL_SOCKET, SO_ATTACH_FILTER, &p,
  			sizeof p) < 0) {
-@@ -315,6 +352,54 @@ static void lpf_tr_filter_setup (info)
+@@ -316,6 +353,54 @@ static void lpf_tr_filter_setup (info)
  #endif /* USE_LPF_RECEIVE */
  
  #ifdef USE_LPF_SEND
@@ -292,7 +292,7 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
  ssize_t send_packet (interface, packet, raw, len, from, to, hto)
  	struct interface_info *interface;
  	struct packet *packet;
-@@ -335,6 +420,11 @@ ssize_t send_packet (interface, packet,
+@@ -336,6 +421,11 @@ ssize_t send_packet (interface, packet,
  		return send_fallback (interface, packet, raw,
  				      len, from, to, hto);
  
@@ -304,7 +304,7 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
  	if (hto == NULL && interface->anycast_mac_addr.hlen)
  		hto = &interface->anycast_mac_addr;
  
-@@ -356,6 +446,42 @@ ssize_t send_packet (interface, packet,
+@@ -357,6 +447,42 @@ ssize_t send_packet (interface, packet,
  #endif /* USE_LPF_SEND */
  
  #ifdef USE_LPF_RECEIVE
@@ -347,7 +347,7 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
  ssize_t receive_packet (interface, buf, len, from, hfrom)
  	struct interface_info *interface;
  	unsigned char *buf;
-@@ -382,6 +508,10 @@ ssize_t receive_packet (interface, buf,
+@@ -383,6 +509,10 @@ ssize_t receive_packet (interface, buf,
  	};
  	struct cmsghdr *cmsg;
  
@@ -358,7 +358,7 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
  	length = recvmsg (interface -> rfdesc, &msg, 0);
  	if (length <= 0)
  		return length;
-@@ -461,11 +591,32 @@ void maybe_setup_fallback ()
+@@ -462,11 +592,33 @@ void maybe_setup_fallback ()
  	}
  }
  
@@ -380,6 +380,7 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
 +		if (strcmp((*ifa)->ifa_name, name) == 0)
 +			return (struct sockaddr_ll *)(void *)(*ifa)->ifa_addr;
 +	}
++	*ifa = NULL;
 +	return NULL;
 +}
 +
@@ -394,7 +395,7 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
  
  	if (strlen(name) >= sizeof(tmp.ifr_name)) {
  		log_fatal("Device name too long: \"%s\"", name);
-@@ -479,16 +630,52 @@ get_hw_addr(const char *name, struct har
+@@ -480,16 +632,62 @@ get_hw_addr(const char *name, struct har
  	memset(&tmp, 0, sizeof(tmp));
  	strcpy(tmp.ifr_name, name);
  	if (ioctl(sock, SIOCGIFHWADDR, &tmp) < 0) {
@@ -412,6 +413,14 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
 +		log_fatal("Unable to allocate memory for link layer address");
 +	memcpy(&sll->sll_hatype, &sa->sa_family, sizeof (sll->sll_hatype));
 +	memcpy(sll->sll_addr, sa->sa_data, sizeof (sll->sll_addr));
++	switch (sll->sll_hatype) {
++		case ARPHRD_INFINIBAND:
++			/* ioctl limits hardware addresses to 8 bytes */
++			sll->sll_halen = 8;
++			break;
++		default:
++			break;
++	}
 +	return sll;
 +}
 +
@@ -424,6 +433,8 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
 +	struct ifaddrs *ifa = NULL;
 +	struct sockaddr_ll *sll = NULL;
 +	int sll_allocated = 0;
++	char *dup = NULL;
++	char *colon = NULL;
 +
 +	if (getifaddrs(&ifaddrs) == -1)
 +		log_fatal("Failed to get interfaces");
@@ -437,7 +448,7 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
 +		if (sll != NULL)
 +			sll_allocated = 1;
 +		else
-+			// shouldn't happed
++			// shouldn't happen
 +			log_fatal("Unexpected internal error");
 +	}
 +
@@ -450,7 +461,7 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
  			break;
  		case ARPHRD_IEEE802:
  #ifdef ARPHRD_IEEE802_TR
-@@ -496,18 +683,35 @@ get_hw_addr(const char *name, struct har
+@@ -497,18 +695,48 @@ get_hw_addr(const char *name, struct har
  #endif /* ARPHRD_IEEE802_TR */
  			hw->hlen = 7;
  			hw->hbuf[0] = HTYPE_IEEE802;
@@ -464,10 +475,22 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
 +			memcpy(&hw->hbuf[1], sll->sll_addr, 6);
 +			break;
 +		case ARPHRD_INFINIBAND:
++			dup = strdup(name);
++			/* Aliased infiniband interface is special case where
++			 * neither get_ll() nor ioctl_get_ll() get's correct hw
++			 * address, so we have to truncate the :0 and run
++			 * get_ll() again for the rest.
++			*/
++			if ((colon = strchr(dup, ':')) != NULL) {
++				*colon = '\0';
++				if ((sll = get_ll(ifaddrs, &ifa, dup)) == NULL)
++					log_fatal("Error getting hardware address for \"%s\": %m", name);
++			}
++			free (dup);
 +			/* For Infiniband, save the broadcast address and store
 +			 * the port GUID into the hardware address.
 +			 */
-+			if (ifa->ifa_flags & IFF_BROADCAST) {
++			if (ifa && (ifa->ifa_flags & IFF_BROADCAST)) {
 +				struct sockaddr_ll *bll;
 +
 +				bll = (struct sockaddr_ll *)ifa->ifa_broadaddr;
@@ -479,6 +502,7 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
 +
 +			hw->hlen = 1;
 +			hw->hbuf[0] = HTYPE_INFINIBAND;
++			memcpy(&hw->hbuf[1], &sll->sll_addr[sll->sll_halen - 8], 8);
  			break;
  #if defined(ARPHRD_PPP)
  		case ARPHRD_PPP:
@@ -490,7 +514,7 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
  			hw->hlen = 0;
  			hw->hbuf[0] = HTYPE_RESERVED;
  			/* 0xdeadbeef should never occur on the wire,
-@@ -520,10 +724,13 @@ get_hw_addr(const char *name, struct har
+@@ -521,10 +749,13 @@ get_hw_addr(const char *name, struct har
  			break;
  #endif
  		default:
@@ -507,9 +531,9 @@ diff -up dhcp-4.2.4-P2/common/lpf.c.lpf-ib dhcp-4.2.4-P2/common/lpf.c
 +	freeifaddrs(ifaddrs);
  }
  #endif
-diff -up dhcp-4.2.4-P2/common/socket.c.lpf-ib dhcp-4.2.4-P2/common/socket.c
---- dhcp-4.2.4-P2/common/socket.c.lpf-ib	2012-08-24 21:11:21.000000000 +0200
-+++ dhcp-4.2.4-P2/common/socket.c	2012-11-30 14:05:07.408394046 +0100
+diff -up dhcp-4.2.5/common/socket.c.lpf-ib dhcp-4.2.5/common/socket.c
+--- dhcp-4.2.5/common/socket.c.lpf-ib	2013-01-03 01:02:24.000000000 +0100
++++ dhcp-4.2.5/common/socket.c	2013-08-26 12:13:31.516170162 +0200
 @@ -325,7 +325,7 @@ void if_register_send (info)
  	info->wfdesc = if_register_socket(info, AF_INET, 0);
  	/* If this is a normal IPv4 address, get the hardware address. */
@@ -537,9 +561,9 @@ diff -up dhcp-4.2.4-P2/common/socket.c.lpf-ib dhcp-4.2.4-P2/common/socket.c
  
  	if (!quiet_interface_discovery) {
  		if (info->shared_network != NULL) {
-diff -up dhcp-4.2.4-P2/includes/dhcpd.h.lpf-ib dhcp-4.2.4-P2/includes/dhcpd.h
---- dhcp-4.2.4-P2/includes/dhcpd.h.lpf-ib	2012-11-30 14:05:07.400394142 +0100
-+++ dhcp-4.2.4-P2/includes/dhcpd.h	2012-11-30 14:05:07.409394034 +0100
+diff -up dhcp-4.2.5/includes/dhcpd.h.lpf-ib dhcp-4.2.5/includes/dhcpd.h
+--- dhcp-4.2.5/includes/dhcpd.h.lpf-ib	2013-08-26 12:13:31.510170243 +0200
++++ dhcp-4.2.5/includes/dhcpd.h	2013-08-26 12:13:31.517170149 +0200
 @@ -1249,6 +1249,7 @@ struct interface_info {
  	struct shared_network *shared_network;
  				/* Networks connected to this interface. */
@@ -548,7 +572,7 @@ diff -up dhcp-4.2.4-P2/includes/dhcpd.h.lpf-ib dhcp-4.2.4-P2/includes/dhcpd.h
  	struct in_addr *addresses;	/* Addresses associated with this
  					 * interface.
  					 */
-@@ -2368,7 +2369,7 @@ void print_dns_status (int, struct dhcp_
+@@ -2372,7 +2373,7 @@ void print_dns_status (int, struct dhcp_
  #endif
  const char *print_time(TIME);
  
diff --git a/dhcp.spec b/dhcp.spec
index 191743c..82b1439 100644
--- a/dhcp.spec
+++ b/dhcp.spec
@@ -18,7 +18,7 @@
 Summary:  Dynamic host configuration protocol software
 Name:     dhcp
 Version:  4.2.5
-Release:  18%{?dist}
+Release:  19%{?dist}
 # NEVER CHANGE THE EPOCH on this package.  The previous maintainer (prior to
 # dcantrell maintaining the package) made incorrect use of the epoch and
 # that's why it is at 12 now.  It should have never been used, but it was.
@@ -610,6 +610,9 @@ done
 
 
 %changelog
+* Mon Aug 26 2013 Jiri Popelka <jpopelka at redhat.com> - 12:4.2.5-19
+- don't crash on aliased infiniband interface (#996518)
+
 * Sun Aug 04 2013 Jiri Popelka <jpopelka at redhat.com> - 12:4.2.5-18
 - BuildRequires: systemd due to  %%{_unitdir}
 


More information about the scm-commits mailing list