]> git.ipfire.org Git - people/arne_f/ipfire-3.x.git/blame - dhcp/patches/0020-dhcp-lpf-ib.patch
dhcp: Update to 4.3.5b1
[people/arne_f/ipfire-3.x.git] / dhcp / patches / 0020-dhcp-lpf-ib.patch
CommitLineData
d8feb2d7
SS
1diff -up dhcp-4.3.4/client/dhclient.c.lpf-ib dhcp-4.3.4/client/dhclient.c
2--- dhcp-4.3.4/client/dhclient.c.lpf-ib 2016-05-02 14:37:36.945128001 +0200
3+++ dhcp-4.3.4/client/dhclient.c 2016-05-02 14:37:36.952128005 +0200
4@@ -163,6 +163,8 @@ static const char use_noarg[] = "No argu
5 static const char use_v6command[] = "Command not used for DHCPv4: %s";
6 #endif
6df985df
SS
7
8+static void setup_ib_interface(struct interface_info *ip);
9+
d8feb2d7
SS
10 static void
11 usage(const char *sfmt, const char *sarg)
12 {
13@@ -1066,6 +1068,13 @@ main(int argc, char **argv) {
6df985df
SS
14 }
15 srandom(seed + cur_time + (unsigned)getpid());
16
17+ /* Setup specific Infiniband options */
18+ for (ip = interfaces; ip; ip = ip->next) {
19+ if (ip->client &&
20+ (ip->hw_address.hbuf[0] == HTYPE_INFINIBAND)) {
21+ setup_ib_interface(ip);
22+ }
23+ }
d8feb2d7
SS
24
25 /*
26 * Establish a default DUID. We always do so for v6 and
27@@ -1361,6 +1370,29 @@ int find_subnet (struct subnet **sp,
6df985df
SS
28 return 0;
29 }
30
31+static void setup_ib_interface(struct interface_info *ip)
32+{
33+ struct group *g;
34+
35+ /* Set the broadcast flag */
36+ ip->client->config->bootp_broadcast_always = 1;
37+
38+ /*
39+ * Find out if a dhcp-client-identifier option was specified either
40+ * in the config file or on the command line
41+ */
42+ for (g = ip->client->config->on_transmission; g != NULL; g = g->next) {
43+ if ((g->statements != NULL) &&
44+ (strcmp(g->statements->data.option->option->name,
45+ "dhcp-client-identifier") == 0)) {
46+ return;
47+ }
48+ }
49+
50+ /* No client ID specified */
51+ log_fatal("dhcp-client-identifier must be specified for InfiniBand");
52+}
53+
54 /* Individual States:
55 *
56 * Each routine is called from the dhclient_state_machine() in one of
d8feb2d7
SS
57diff -up dhcp-4.3.4/common/bpf.c.lpf-ib dhcp-4.3.4/common/bpf.c
58--- dhcp-4.3.4/common/bpf.c.lpf-ib 2016-05-02 14:37:36.946128001 +0200
59+++ dhcp-4.3.4/common/bpf.c 2016-05-02 14:37:36.952128005 +0200
60@@ -198,11 +198,43 @@ struct bpf_insn dhcp_bpf_filter [] = {
6df985df
SS
61 BPF_STMT(BPF_RET+BPF_K, 0),
62 };
63
64+/* Packet filter program for DHCP over Infiniband.
65+ *
66+ * XXX
67+ * Changes to the filter program may require changes to the constant offsets
68+ * used in lpf_gen_filter_setup to patch the port in the BPF program!
69+ * XXX
70+ */
71+struct bpf_insn dhcp_ib_bpf_filter [] = {
72+ /* Packet filter for Infiniband */
73+ /* Make sure it's a UDP packet... */
74+ BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 9),
75+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
76+
77+ /* Make sure this isn't a fragment... */
78+ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 6),
79+ BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
80+
81+ /* Get the IP header length... */
82+ BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 0),
83+
84+ /* Make sure it's to the right port... */
85+ BPF_STMT(BPF_LD + BPF_H + BPF_IND, 2),
86+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1),
87+
88+ /* If we passed all the tests, ask for the whole packet. */
89+ BPF_STMT(BPF_RET + BPF_K, (u_int)-1),
90+
91+ /* Otherwise, drop it. */
92+ BPF_STMT(BPF_RET + BPF_K, 0),
93+};
94+
95 #if defined (DEC_FDDI)
d8feb2d7 96 struct bpf_insn *bpf_fddi_filter = NULL;
6df985df
SS
97 #endif
98
99 int dhcp_bpf_filter_len = sizeof dhcp_bpf_filter / sizeof (struct bpf_insn);
100+int dhcp_ib_bpf_filter_len = sizeof dhcp_ib_bpf_filter / sizeof (struct bpf_insn);
6df985df
SS
101 #if defined (HAVE_TR_SUPPORT)
102 struct bpf_insn dhcp_bpf_tr_filter [] = {
103 /* accept all token ring packets due to variable length header */
d8feb2d7
SS
104diff -up dhcp-4.3.4/common/discover.c.lpf-ib dhcp-4.3.4/common/discover.c
105--- dhcp-4.3.4/common/discover.c.lpf-ib 2016-03-22 14:16:51.000000000 +0100
106+++ dhcp-4.3.4/common/discover.c 2016-05-02 14:38:08.257147982 +0200
107@@ -1235,7 +1235,7 @@ discover_interfaces(int state) {
108 if_register_send(tmp);
109 } else {
110 /* get_hw_addr() was called by register. */
111- get_hw_addr(tmp->name, &tmp->hw_address);
112+ get_hw_addr(tmp);
113 }
114 break;
115 #ifdef DHCPv6
116@@ -1248,7 +1248,7 @@ discover_interfaces(int state) {
117 so now we have to call it explicitly
118 to not leave the hardware address unknown
119 (some code expects it cannot be. */
120- get_hw_addr(tmp->name, &tmp->hw_address);
121+ get_hw_addr(tmp);
122 } else {
123 if_register_linklocal6(tmp);
124 }
125diff -up dhcp-4.3.4/common/lpf.c.lpf-ib dhcp-4.3.4/common/lpf.c
126--- dhcp-4.3.4/common/lpf.c.lpf-ib 2016-05-02 14:37:36.947128002 +0200
127+++ dhcp-4.3.4/common/lpf.c 2016-05-02 14:37:36.953128006 +0200
128@@ -47,6 +47,17 @@
129 #include <sys/ioctl.h>
130 #include <sys/socket.h>
6df985df
SS
131 #include <net/if.h>
132+#include <ifaddrs.h>
d8feb2d7 133+
6df985df
SS
134+/* Default broadcast address for IPoIB */
135+static unsigned char default_ib_bcast_addr[20] = {
136+ 0x00, 0xff, 0xff, 0xff,
137+ 0xff, 0x12, 0x40, 0x1b,
138+ 0x00, 0x00, 0x00, 0x00,
139+ 0x00, 0x00, 0x00, 0x00,
140+ 0xff, 0xff, 0xff, 0xff
141+};
142+
d8feb2d7
SS
143 #endif
144
145 #if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE)
146@@ -80,10 +91,20 @@ int if_register_lpf (info)
6df985df 147 struct sockaddr common;
d8feb2d7 148 } sa;
6df985df
SS
149 struct ifreq ifr;
150+ int type;
151+ int protocol;
6df985df 152+
d8feb2d7 153+ get_hw_addr(info);
6df985df
SS
154+ if (info->hw_address.hbuf[0] == HTYPE_INFINIBAND) {
155+ type = SOCK_DGRAM;
156+ protocol = ETHERTYPE_IP;
157+ } else {
158+ type = SOCK_RAW;
159+ protocol = ETH_P_ALL;
160+ }
d8feb2d7
SS
161
162 /* Make an LPF socket. */
163- if ((sock = socket(PF_PACKET, SOCK_RAW,
164- htons((short)ETH_P_ALL))) < 0) {
6df985df
SS
165+ if ((sock = socket(PF_PACKET, type, htons((short)protocol))) < 0) {
166 if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
167 errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
168 errno == EAFNOSUPPORT || errno == EINVAL) {
d8feb2d7 169@@ -106,6 +127,7 @@ int if_register_lpf (info)
6df985df
SS
170 /* Bind to the interface name */
171 memset (&sa, 0, sizeof sa);
172 sa.ll.sll_family = AF_PACKET;
173+ sa.ll.sll_protocol = htons(protocol);
174 sa.ll.sll_ifindex = ifr.ifr_ifindex;
175 if (bind (sock, &sa.common, sizeof sa)) {
176 if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
d8feb2d7
SS
177@@ -122,8 +144,6 @@ int if_register_lpf (info)
178
6df985df
SS
179 }
180
181- get_hw_addr(info->name, &info->hw_address);
182-
183 return sock;
184 }
185 #endif /* USE_LPF_SEND || USE_LPF_RECEIVE */
d8feb2d7 186@@ -178,6 +198,8 @@ void if_deregister_send (info)
6df985df
SS
187 in bpf includes... */
188 extern struct sock_filter dhcp_bpf_filter [];
189 extern int dhcp_bpf_filter_len;
190+extern struct sock_filter dhcp_ib_bpf_filter [];
191+extern int dhcp_ib_bpf_filter_len;
192
193 #if defined (HAVE_TR_SUPPORT)
194 extern struct sock_filter dhcp_bpf_tr_filter [];
d8feb2d7
SS
195@@ -196,11 +218,12 @@ void if_register_receive (info)
196 #ifdef PACKET_AUXDATA
197 {
198 int val = 1;
199-
200- if (setsockopt(info->rfdesc, SOL_PACKET, PACKET_AUXDATA,
201- &val, sizeof(val)) < 0) {
202- if (errno != ENOPROTOOPT) {
6df985df
SS
203- log_fatal ("Failed to set auxiliary packet data: %m");
204+ if (info->hw_address.hbuf[0] != HTYPE_INFINIBAND) {
d8feb2d7
SS
205+ if (setsockopt(info->rfdesc, SOL_PACKET, PACKET_AUXDATA,
206+ &val, sizeof(val)) < 0) {
207+ if (errno != ENOPROTOOPT) {
6df985df 208+ log_fatal ("Failed to set auxiliary packet data: %m");
d8feb2d7
SS
209+ }
210 }
6df985df 211 }
d8feb2d7
SS
212 }
213@@ -250,15 +273,28 @@ static void lpf_gen_filter_setup (info)
6df985df
SS
214
215 memset(&p, 0, sizeof(p));
216
217- /* Set up the bpf filter program structure. This is defined in
218- bpf.c */
219- p.len = dhcp_bpf_filter_len;
220- p.filter = dhcp_bpf_filter;
221-
222- /* Patch the server port into the LPF program...
223- XXX changes to filter program may require changes
224- to the insn number(s) used below! XXX */
225- dhcp_bpf_filter [8].k = ntohs ((short)local_port);
226+ if (info->hw_address.hbuf[0] == HTYPE_INFINIBAND) {
227+ /* Set up the bpf filter program structure. */
228+ p.len = dhcp_ib_bpf_filter_len;
229+ p.filter = dhcp_ib_bpf_filter;
230+
231+ /* Patch the server port into the LPF program...
232+ XXX
233+ changes to filter program may require changes
234+ to the insn number(s) used below!
235+ XXX */
236+ dhcp_ib_bpf_filter[6].k = ntohs ((short)local_port);
237+ } else {
238+ /* Set up the bpf filter program structure.
239+ This is defined in bpf.c */
240+ p.len = dhcp_bpf_filter_len;
241+ p.filter = dhcp_bpf_filter;
242+
243+ /* Patch the server port into the LPF program...
244+ XXX changes to filter program may require changes
245+ to the insn number(s) used below! XXX */
246+ dhcp_bpf_filter [8].k = ntohs ((short)local_port);
247+ }
248
249 if (setsockopt (info -> rfdesc, SOL_SOCKET, SO_ATTACH_FILTER, &p,
250 sizeof p) < 0) {
d8feb2d7 251@@ -315,6 +351,54 @@ static void lpf_tr_filter_setup (info)
6df985df
SS
252 #endif /* USE_LPF_RECEIVE */
253
254 #ifdef USE_LPF_SEND
255+ssize_t send_packet_ib(interface, packet, raw, len, from, to, hto)
256+ struct interface_info *interface;
257+ struct packet *packet;
258+ struct dhcp_packet *raw;
259+ size_t len;
260+ struct in_addr from;
261+ struct sockaddr_in *to;
262+ struct hardware *hto;
263+{
264+ unsigned ibufp = 0;
265+ double ih [1536 / sizeof (double)];
266+ unsigned char *buf = (unsigned char *)ih;
267+ ssize_t result;
268+
269+ union sockunion {
270+ struct sockaddr sa;
271+ struct sockaddr_ll sll;
272+ struct sockaddr_storage ss;
273+ } su;
274+
275+ assemble_udp_ip_header (interface, buf, &ibufp, from.s_addr,
276+ to->sin_addr.s_addr, to->sin_port,
277+ (unsigned char *)raw, len);
278+ memcpy (buf + ibufp, raw, len);
279+
280+ memset(&su, 0, sizeof(su));
281+ su.sll.sll_family = AF_PACKET;
282+ su.sll.sll_protocol = htons(ETHERTYPE_IP);
283+
284+ if (!(su.sll.sll_ifindex = if_nametoindex(interface->name))) {
285+ errno = ENOENT;
286+ log_error ("send_packet_ib: %m - failed to get if index");
287+ return -1;
288+ }
289+
290+ su.sll.sll_hatype = htons(HTYPE_INFINIBAND);
291+ su.sll.sll_halen = sizeof(interface->bcast_addr);
292+ memcpy(&su.sll.sll_addr, interface->bcast_addr, 20);
293+
294+ result = sendto(interface->wfdesc, buf, ibufp + len, 0,
295+ &su.sa, sizeof(su));
296+
297+ if (result < 0)
298+ log_error ("send_packet_ib: %m");
299+
300+ return result;
301+}
302+
303 ssize_t send_packet (interface, packet, raw, len, from, to, hto)
304 struct interface_info *interface;
305 struct packet *packet;
d8feb2d7 306@@ -335,6 +419,11 @@ ssize_t send_packet (interface, packet,
6df985df
SS
307 return send_fallback (interface, packet, raw,
308 len, from, to, hto);
309
310+ if (interface->hw_address.hbuf[0] == HTYPE_INFINIBAND) {
311+ return send_packet_ib(interface, packet, raw, len, from,
312+ to, hto);
313+ }
314+
315 if (hto == NULL && interface->anycast_mac_addr.hlen)
316 hto = &interface->anycast_mac_addr;
317
d8feb2d7 318@@ -355,6 +444,42 @@ ssize_t send_packet (interface, packet,
6df985df
SS
319 #endif /* USE_LPF_SEND */
320
321 #ifdef USE_LPF_RECEIVE
322+ssize_t receive_packet_ib (interface, buf, len, from, hfrom)
323+ struct interface_info *interface;
324+ unsigned char *buf;
325+ size_t len;
326+ struct sockaddr_in *from;
327+ struct hardware *hfrom;
328+{
329+ int length = 0;
330+ int offset = 0;
331+ unsigned char ibuf [1536];
332+ unsigned bufix = 0;
333+ unsigned paylen;
334+
335+ length = read(interface->rfdesc, ibuf, sizeof(ibuf));
336+
337+ if (length <= 0)
338+ return length;
339+
340+ offset = decode_udp_ip_header(interface, ibuf, bufix, from,
341+ (unsigned)length, &paylen, 0);
342+
343+ if (offset < 0)
344+ return 0;
345+
346+ bufix += offset;
347+ length -= offset;
348+
349+ if (length < paylen)
350+ log_fatal("Internal inconsistency at %s:%d.", MDL);
351+
352+ /* Copy out the data in the packet... */
353+ memcpy(buf, &ibuf[bufix], paylen);
354+
355+ return (ssize_t)paylen;
356+}
357+
358 ssize_t receive_packet (interface, buf, len, from, hfrom)
359 struct interface_info *interface;
360 unsigned char *buf;
d8feb2d7 361@@ -393,6 +518,10 @@ ssize_t receive_packet (interface, buf,
6df985df 362 };
d8feb2d7 363 #endif /* PACKET_AUXDATA */
6df985df
SS
364
365+ if (interface->hw_address.hbuf[0] == HTYPE_INFINIBAND) {
366+ return receive_packet_ib(interface, buf, len, from, hfrom);
367+ }
368+
d8feb2d7 369 length = recvmsg (interface->rfdesc, &msg, 0);
6df985df
SS
370 if (length <= 0)
371 return length;
d8feb2d7
SS
372@@ -506,11 +635,33 @@ void maybe_setup_fallback ()
373 #endif
6df985df 374
d8feb2d7 375 #if defined (USE_LPF_RECEIVE) || defined (USE_LPF_HWADDR)
444c1184 376-void
6df985df 377-get_hw_addr(const char *name, struct hardware *hw) {
444c1184
MT
378+struct sockaddr_ll *
379+get_ll (struct ifaddrs *ifaddrs, struct ifaddrs **ifa, char *name)
6df985df 380+{
444c1184
MT
381+ for (*ifa = ifaddrs; *ifa != NULL; *ifa = (*ifa)->ifa_next) {
382+ if ((*ifa)->ifa_addr == NULL)
6df985df
SS
383+ continue;
384+
444c1184 385+ if ((*ifa)->ifa_addr->sa_family != AF_PACKET)
6df985df
SS
386+ continue;
387+
444c1184 388+ if ((*ifa)->ifa_flags & IFF_LOOPBACK)
6df985df
SS
389+ continue;
390+
444c1184
MT
391+ if (strcmp((*ifa)->ifa_name, name) == 0)
392+ return (struct sockaddr_ll *)(void *)(*ifa)->ifa_addr;
393+ }
d8feb2d7 394+ *ifa = NULL;
444c1184
MT
395+ return NULL;
396+}
397+
398+struct sockaddr_ll *
399+ioctl_get_ll(char *name)
400+{
401 int sock;
402 struct ifreq tmp;
403- struct sockaddr *sa;
404+ struct sockaddr *sa = NULL;
405+ struct sockaddr_ll *sll = NULL;
6df985df 406
444c1184
MT
407 if (strlen(name) >= sizeof(tmp.ifr_name)) {
408 log_fatal("Device name too long: \"%s\"", name);
d8feb2d7 409@@ -524,16 +675,61 @@ get_hw_addr(const char *name, struct har
444c1184
MT
410 memset(&tmp, 0, sizeof(tmp));
411 strcpy(tmp.ifr_name, name);
412 if (ioctl(sock, SIOCGIFHWADDR, &tmp) < 0) {
6df985df 413- log_fatal("Error getting hardware address for \"%s\": %m",
444c1184
MT
414+ log_fatal("Error getting hardware address for \"%s\": %m",
415 name);
6df985df 416 }
177b938a 417+ close(sock);
6df985df 418
444c1184 419 sa = &tmp.ifr_hwaddr;
6df985df 420- switch (sa->sa_family) {
177b938a 421+ // needs to be freed outside this function
444c1184
MT
422+ sll = dmalloc (sizeof (struct sockaddr_ll), MDL);
423+ if (!sll)
424+ log_fatal("Unable to allocate memory for link layer address");
425+ memcpy(&sll->sll_hatype, &sa->sa_family, sizeof (sll->sll_hatype));
426+ memcpy(sll->sll_addr, sa->sa_data, sizeof (sll->sll_addr));
d8feb2d7
SS
427+ switch (sll->sll_hatype) {
428+ case ARPHRD_INFINIBAND:
429+ sll->sll_halen = HARDWARE_ADDR_LEN_IOCTL;
430+ break;
431+ default:
432+ break;
433+ }
444c1184
MT
434+ return sll;
435+}
436+
437+void
438+get_hw_addr(struct interface_info *info)
439+{
440+ struct hardware *hw = &info->hw_address;
441+ char *name = info->name;
442+ struct ifaddrs *ifaddrs = NULL;
443+ struct ifaddrs *ifa = NULL;
444+ struct sockaddr_ll *sll = NULL;
177b938a 445+ int sll_allocated = 0;
d8feb2d7
SS
446+ char *dup = NULL;
447+ char *colon = NULL;
444c1184
MT
448+
449+ if (getifaddrs(&ifaddrs) == -1)
450+ log_fatal("Failed to get interfaces");
451+
452+ if ((sll = get_ll(ifaddrs, &ifa, name)) == NULL) {
453+ /*
454+ * We were unable to get link-layer address for name.
455+ * Fall back to ioctl(SIOCGIFHWADDR).
456+ */
457+ sll = ioctl_get_ll(name);
177b938a
MT
458+ if (sll != NULL)
459+ sll_allocated = 1;
460+ else
d8feb2d7 461+ // shouldn't happen
177b938a 462+ log_fatal("Unexpected internal error");
444c1184
MT
463+ }
464+
6df985df
SS
465+ switch (sll->sll_hatype) {
466 case ARPHRD_ETHER:
467 hw->hlen = 7;
468 hw->hbuf[0] = HTYPE_ETHER;
469- memcpy(&hw->hbuf[1], sa->sa_data, 6);
470+ memcpy(&hw->hbuf[1], sll->sll_addr, 6);
471 break;
472 case ARPHRD_IEEE802:
473 #ifdef ARPHRD_IEEE802_TR
d8feb2d7 474@@ -541,18 +737,50 @@ get_hw_addr(const char *name, struct har
6df985df
SS
475 #endif /* ARPHRD_IEEE802_TR */
476 hw->hlen = 7;
477 hw->hbuf[0] = HTYPE_IEEE802;
478- memcpy(&hw->hbuf[1], sa->sa_data, 6);
479+ memcpy(&hw->hbuf[1], sll->sll_addr, 6);
480 break;
481 case ARPHRD_FDDI:
177b938a 482 hw->hlen = 7;
6df985df 483 hw->hbuf[0] = HTYPE_FDDI;
177b938a
MT
484- memcpy(&hw->hbuf[1], sa->sa_data, 6);
485+ memcpy(&hw->hbuf[1], sll->sll_addr, 6);
6df985df
SS
486+ break;
487+ case ARPHRD_INFINIBAND:
d8feb2d7
SS
488+ dup = strdup(name);
489+ /* Aliased infiniband interface is special case where
490+ * neither get_ll() nor ioctl_get_ll() get's correct hw
491+ * address, so we have to truncate the :0 and run
492+ * get_ll() again for the rest.
493+ */
494+ if ((colon = strchr(dup, ':')) != NULL) {
495+ *colon = '\0';
496+ if ((sll = get_ll(ifaddrs, &ifa, dup)) == NULL)
497+ log_fatal("Error getting hardware address for \"%s\": %m", name);
498+ }
499+ free (dup);
6df985df
SS
500+ /* For Infiniband, save the broadcast address and store
501+ * the port GUID into the hardware address.
502+ */
d8feb2d7 503+ if (ifa && (ifa->ifa_flags & IFF_BROADCAST)) {
6df985df
SS
504+ struct sockaddr_ll *bll;
505+
506+ bll = (struct sockaddr_ll *)ifa->ifa_broadaddr;
507+ memcpy(&info->bcast_addr, bll->sll_addr, 20);
508+ } else {
509+ memcpy(&info->bcast_addr, default_ib_bcast_addr,
510+ 20);
511+ }
512+
d8feb2d7 513+ hw->hlen = HARDWARE_ADDR_LEN_IOCTL + 1;
6df985df 514+ hw->hbuf[0] = HTYPE_INFINIBAND;
d8feb2d7
SS
515+ memcpy(&hw->hbuf[1],
516+ &sll->sll_addr[sll->sll_halen - HARDWARE_ADDR_LEN_IOCTL],
517+ HARDWARE_ADDR_LEN_IOCTL);
6df985df
SS
518 break;
519 #if defined(ARPHRD_PPP)
520 case ARPHRD_PPP:
521 if (local_family != AF_INET6)
522- log_fatal("Unsupported device type %d for \"%s\"",
523- sa->sa_family, name);
444c1184
MT
524+ log_fatal("local_family != AF_INET6 for \"%s\"",
525+ name);
6df985df
SS
526 hw->hlen = 0;
527 hw->hbuf[0] = HTYPE_RESERVED;
528 /* 0xdeadbeef should never occur on the wire,
d8feb2d7 529@@ -565,10 +793,13 @@ get_hw_addr(const char *name, struct har
6df985df
SS
530 break;
531 #endif
532 default:
444c1184 533- log_fatal("Unsupported device type %ld for \"%s\"",
6df985df 534- (long int)sa->sa_family, name);
444c1184 535+ freeifaddrs(ifaddrs);
d8feb2d7 536+ log_fatal("Unsupported device type %hu for \"%s\"",
444c1184 537+ sll->sll_hatype, name);
6df985df
SS
538 }
539
540- close(sock);
177b938a
MT
541+ if (sll_allocated)
542+ dfree(sll, MDL);
6df985df
SS
543+ freeifaddrs(ifaddrs);
544 }
545 #endif
d8feb2d7
SS
546diff -up dhcp-4.3.4/common/socket.c.lpf-ib dhcp-4.3.4/common/socket.c
547--- dhcp-4.3.4/common/socket.c.lpf-ib 2016-03-22 14:16:51.000000000 +0100
548+++ dhcp-4.3.4/common/socket.c 2016-05-02 14:37:36.953128006 +0200
549@@ -328,7 +328,7 @@ void if_register_send (info)
550 info->wfdesc = if_register_socket(info, AF_INET, 0, NULL);
6df985df
SS
551 /* If this is a normal IPv4 address, get the hardware address. */
552 if (strcmp(info->name, "fallback") != 0)
553- get_hw_addr(info->name, &info->hw_address);
554+ get_hw_addr(info);
555 #if defined (USE_SOCKET_FALLBACK)
556 /* Fallback only registers for send, but may need to receive as
557 well. */
d8feb2d7 558@@ -391,7 +391,7 @@ void if_register_receive (info)
6df985df
SS
559 #endif /* IP_PKTINFO... */
560 /* If this is a normal IPv4 address, get the hardware address. */
561 if (strcmp(info->name, "fallback") != 0)
562- get_hw_addr(info->name, &info->hw_address);
563+ get_hw_addr(info);
564
565 if (!quiet_interface_discovery)
566 log_info ("Listening on Socket/%s%s%s",
d8feb2d7 567@@ -505,7 +505,7 @@ if_register6(struct interface_info *info
6df985df
SS
568 if (req_multi)
569 if_register_multicast(info);
570
571- get_hw_addr(info->name, &info->hw_address);
572+ get_hw_addr(info);
573
574 if (!quiet_interface_discovery) {
575 if (info->shared_network != NULL) {
d8feb2d7
SS
576@@ -561,7 +561,7 @@ if_register_linklocal6(struct interface_
577 info->rfdesc = sock;
578 info->wfdesc = sock;
579
580- get_hw_addr(info->name, &info->hw_address);
581+ get_hw_addr(info);
582
583 if (!quiet_interface_discovery) {
584 if (info->shared_network != NULL) {
585diff -up dhcp-4.3.4/includes/dhcpd.h.lpf-ib dhcp-4.3.4/includes/dhcpd.h
586--- dhcp-4.3.4/includes/dhcpd.h.lpf-ib 2016-05-02 14:37:36.948128002 +0200
587+++ dhcp-4.3.4/includes/dhcpd.h 2016-05-02 14:37:36.954128006 +0200
588@@ -482,6 +482,9 @@ struct packet {
589
590 #define HARDWARE_ADDR_LEN 20
591
592+/* ioctl limits hardware addresses to 8 bytes */
593+#define HARDWARE_ADDR_LEN_IOCTL 8
594+
595 struct hardware {
596 u_int8_t hlen;
597 u_int8_t hbuf[HARDWARE_ADDR_LEN + 1];
598@@ -1343,6 +1346,7 @@ struct interface_info {
6df985df
SS
599 struct shared_network *shared_network;
600 /* Networks connected to this interface. */
601 struct hardware hw_address; /* Its physical address. */
602+ u_int8_t bcast_addr[20]; /* Infiniband broadcast address */
603 struct in_addr *addresses; /* Addresses associated with this
604 * interface.
605 */
d8feb2d7 606@@ -2580,7 +2584,7 @@ void print_dns_status (int, struct dhcp_
6df985df
SS
607 #endif
608 const char *print_time(TIME);
609
610-void get_hw_addr(const char *name, struct hardware *hw);
611+void get_hw_addr(struct interface_info *info);
d8feb2d7
SS
612 char *buf_to_hex (const unsigned char *s, unsigned len,
613 const char *file, int line);
614 char *format_lease_id(const unsigned char *s, unsigned len, int format,