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