1 diff -up dhcp-4.3.1b1/client/dhclient.c.bmgpWV dhcp-4.3.1b1/client/dhclient.c
2 --- dhcp-4.3.1b1/client/dhclient.c.bmgpWV 2014-07-10 17:50:26.922402550 +0200
3 +++ dhcp-4.3.1b1/client/dhclient.c 2014-07-10 17:53:43.629623477 +0200
4 @@ -114,6 +114,8 @@ static int check_domain_name_list(const
5 static int check_option_values(struct universe *universe, unsigned int opt,
6 const char *ptr, size_t len);
8 +static void setup_ib_interface(struct interface_info *ip);
12 main(int argc, char **argv) {
13 @@ -937,6 +939,13 @@ main(int argc, char **argv) {
15 srandom(seed + cur_time + (unsigned)getpid());
17 + /* Setup specific Infiniband options */
18 + for (ip = interfaces; ip; ip = ip->next) {
20 + (ip->hw_address.hbuf[0] == HTYPE_INFINIBAND)) {
21 + setup_ib_interface(ip);
26 * Establish a default DUID. We always do so for v6 and
27 @@ -1230,6 +1239,29 @@ int find_subnet (struct subnet **sp,
31 +static void setup_ib_interface(struct interface_info *ip)
35 + /* Set the broadcast flag */
36 + ip->client->config->bootp_broadcast_always = 1;
39 + * Find out if a dhcp-client-identifier option was specified either
40 + * in the config file or on the command line
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)) {
50 + /* No client ID specified */
51 + log_fatal("dhcp-client-identifier must be specified for InfiniBand");
56 * Each routine is called from the dhclient_state_machine() in one of
57 diff -up dhcp-4.3.1b1/common/bpf.c.bmgpWV dhcp-4.3.1b1/common/bpf.c
58 --- dhcp-4.3.1b1/common/bpf.c.bmgpWV 2014-07-10 17:48:03.797424616 +0200
59 +++ dhcp-4.3.1b1/common/bpf.c 2014-07-10 17:52:57.705272295 +0200
60 @@ -199,11 +199,44 @@ struct bpf_insn dhcp_bpf_filter [] = {
61 BPF_STMT(BPF_RET+BPF_K, 0),
64 +/* Packet filter program for DHCP over Infiniband.
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!
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),
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),
81 + /* Get the IP header length... */
82 + BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 0),
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),
88 + /* If we passed all the tests, ask for the whole packet. */
89 + BPF_STMT(BPF_RET + BPF_K, (u_int)-1),
91 + /* Otherwise, drop it. */
92 + BPF_STMT(BPF_RET + BPF_K, 0),
95 #if defined (DEC_FDDI)
96 struct bpf_insn *bpf_fddi_filter;
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);
102 #if defined (HAVE_TR_SUPPORT)
103 struct bpf_insn dhcp_bpf_tr_filter [] = {
104 /* accept all token ring packets due to variable length header */
105 diff -up dhcp-4.3.1b1/common/lpf.c.bmgpWV dhcp-4.3.1b1/common/lpf.c
106 --- dhcp-4.3.1b1/common/lpf.c.bmgpWV 2014-07-10 17:48:03.797424616 +0200
107 +++ dhcp-4.3.1b1/common/lpf.c 2014-07-10 17:52:57.706272281 +0200
109 #if defined (USE_LPF_RECEIVE) || defined (USE_LPF_HWADDR)
110 #include <sys/ioctl.h>
112 +#include <ifaddrs.h>
114 +/* Default broadcast address for IPoIB */
115 +static unsigned char default_ib_bcast_addr[20] = {
116 + 0x00, 0xff, 0xff, 0xff,
117 + 0xff, 0x12, 0x40, 0x1b,
118 + 0x00, 0x00, 0x00, 0x00,
119 + 0x00, 0x00, 0x00, 0x00,
120 + 0xff, 0xff, 0xff, 0xff
125 #if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE)
126 @@ -92,10 +103,21 @@ int if_register_lpf (info)
127 struct sockaddr common;
133 /* Make an LPF socket. */
134 - if ((sock = socket(PF_PACKET, SOCK_RAW,
135 - htons((short)ETH_P_ALL))) < 0) {
138 + if (info->hw_address.hbuf[0] == HTYPE_INFINIBAND) {
140 + protocol = ETHERTYPE_IP;
143 + protocol = ETH_P_ALL;
146 + if ((sock = socket(PF_PACKET, type, htons((short)protocol))) < 0) {
147 if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
148 errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
149 errno == EAFNOSUPPORT || errno == EINVAL) {
150 @@ -118,6 +140,7 @@ int if_register_lpf (info)
151 /* Bind to the interface name */
152 memset (&sa, 0, sizeof sa);
153 sa.ll.sll_family = AF_PACKET;
154 + sa.ll.sll_protocol = htons(protocol);
155 sa.ll.sll_ifindex = ifr.ifr_ifindex;
156 if (bind (sock, &sa.common, sizeof sa)) {
157 if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
158 @@ -133,8 +156,6 @@ int if_register_lpf (info)
159 log_fatal ("Bind socket to interface: %m");
162 - get_hw_addr(info->name, &info->hw_address);
166 #endif /* USE_LPF_SEND || USE_LPF_RECEIVE */
167 @@ -189,6 +210,8 @@ void if_deregister_send (info)
168 in bpf includes... */
169 extern struct sock_filter dhcp_bpf_filter [];
170 extern int dhcp_bpf_filter_len;
171 +extern struct sock_filter dhcp_ib_bpf_filter [];
172 +extern int dhcp_ib_bpf_filter_len;
174 #if defined (HAVE_TR_SUPPORT)
175 extern struct sock_filter dhcp_bpf_tr_filter [];
176 @@ -206,11 +229,13 @@ void if_register_receive (info)
177 /* Open a LPF device and hang it on this interface... */
178 info -> rfdesc = if_register_lpf (info);
181 - if (setsockopt (info -> rfdesc, SOL_PACKET, PACKET_AUXDATA, &val,
183 - if (errno != ENOPROTOOPT)
184 - log_fatal ("Failed to set auxiliary packet data: %m");
185 + if (info->hw_address.hbuf[0] != HTYPE_INFINIBAND) {
187 + if (setsockopt (info -> rfdesc, SOL_PACKET, PACKET_AUXDATA,
188 + &val, sizeof val) < 0) {
189 + if (errno != ENOPROTOOPT)
190 + log_fatal ("Failed to set auxiliary packet data: %m");
194 #if defined (HAVE_TR_SUPPORT)
195 @@ -256,15 +281,28 @@ static void lpf_gen_filter_setup (info)
197 memset(&p, 0, sizeof(p));
199 - /* Set up the bpf filter program structure. This is defined in
201 - p.len = dhcp_bpf_filter_len;
202 - p.filter = dhcp_bpf_filter;
204 - /* Patch the server port into the LPF program...
205 - XXX changes to filter program may require changes
206 - to the insn number(s) used below! XXX */
207 - dhcp_bpf_filter [8].k = ntohs ((short)local_port);
208 + if (info->hw_address.hbuf[0] == HTYPE_INFINIBAND) {
209 + /* Set up the bpf filter program structure. */
210 + p.len = dhcp_ib_bpf_filter_len;
211 + p.filter = dhcp_ib_bpf_filter;
213 + /* Patch the server port into the LPF program...
215 + changes to filter program may require changes
216 + to the insn number(s) used below!
218 + dhcp_ib_bpf_filter[6].k = ntohs ((short)local_port);
220 + /* Set up the bpf filter program structure.
221 + This is defined in bpf.c */
222 + p.len = dhcp_bpf_filter_len;
223 + p.filter = dhcp_bpf_filter;
225 + /* Patch the server port into the LPF program...
226 + XXX changes to filter program may require changes
227 + to the insn number(s) used below! XXX */
228 + dhcp_bpf_filter [8].k = ntohs ((short)local_port);
231 if (setsockopt (info -> rfdesc, SOL_SOCKET, SO_ATTACH_FILTER, &p,
233 @@ -321,6 +359,54 @@ static void lpf_tr_filter_setup (info)
234 #endif /* USE_LPF_RECEIVE */
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;
242 + struct in_addr from;
243 + struct sockaddr_in *to;
244 + struct hardware *hto;
246 + unsigned ibufp = 0;
247 + double ih [1536 / sizeof (double)];
248 + unsigned char *buf = (unsigned char *)ih;
252 + struct sockaddr sa;
253 + struct sockaddr_ll sll;
254 + struct sockaddr_storage ss;
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);
262 + memset(&su, 0, sizeof(su));
263 + su.sll.sll_family = AF_PACKET;
264 + su.sll.sll_protocol = htons(ETHERTYPE_IP);
266 + if (!(su.sll.sll_ifindex = if_nametoindex(interface->name))) {
268 + log_error ("send_packet_ib: %m - failed to get if index");
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);
276 + result = sendto(interface->wfdesc, buf, ibufp + len, 0,
277 + &su.sa, sizeof(su));
280 + log_error ("send_packet_ib: %m");
285 ssize_t send_packet (interface, packet, raw, len, from, to, hto)
286 struct interface_info *interface;
287 struct packet *packet;
288 @@ -341,6 +427,11 @@ ssize_t send_packet (interface, packet,
289 return send_fallback (interface, packet, raw,
292 + if (interface->hw_address.hbuf[0] == HTYPE_INFINIBAND) {
293 + return send_packet_ib(interface, packet, raw, len, from,
297 if (hto == NULL && interface->anycast_mac_addr.hlen)
298 hto = &interface->anycast_mac_addr;
300 @@ -362,6 +453,42 @@ ssize_t send_packet (interface, packet,
301 #endif /* USE_LPF_SEND */
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;
308 + struct sockaddr_in *from;
309 + struct hardware *hfrom;
313 + unsigned char ibuf [1536];
314 + unsigned bufix = 0;
317 + length = read(interface->rfdesc, ibuf, sizeof(ibuf));
322 + offset = decode_udp_ip_header(interface, ibuf, bufix, from,
323 + (unsigned)length, &paylen, 0);
331 + if (length < paylen)
332 + log_fatal("Internal inconsistency at %s:%d.", MDL);
334 + /* Copy out the data in the packet... */
335 + memcpy(buf, &ibuf[bufix], paylen);
337 + return (ssize_t)paylen;
340 ssize_t receive_packet (interface, buf, len, from, hfrom)
341 struct interface_info *interface;
343 @@ -388,6 +515,10 @@ ssize_t receive_packet (interface, buf,
345 struct cmsghdr *cmsg;
347 + if (interface->hw_address.hbuf[0] == HTYPE_INFINIBAND) {
348 + return receive_packet_ib(interface, buf, len, from, hfrom);
351 length = recvmsg (interface -> rfdesc, &msg, 0);
354 @@ -469,11 +600,33 @@ void maybe_setup_fallback ()
357 #if defined (USE_LPF_RECEIVE) || defined (USE_LPF_HWADDR)
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)
363 + for (*ifa = ifaddrs; *ifa != NULL; *ifa = (*ifa)->ifa_next) {
364 + if ((*ifa)->ifa_addr == NULL)
367 + if ((*ifa)->ifa_addr->sa_family != AF_PACKET)
370 + if ((*ifa)->ifa_flags & IFF_LOOPBACK)
373 + if (strcmp((*ifa)->ifa_name, name) == 0)
374 + return (struct sockaddr_ll *)(void *)(*ifa)->ifa_addr;
380 +struct sockaddr_ll *
381 +ioctl_get_ll(char *name)
385 - struct sockaddr *sa;
386 + struct sockaddr *sa = NULL;
387 + struct sockaddr_ll *sll = NULL;
389 if (strlen(name) >= sizeof(tmp.ifr_name)) {
390 log_fatal("Device name too long: \"%s\"", name);
391 @@ -487,16 +640,62 @@ get_hw_addr(const char *name, struct har
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",
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);
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 + /* ioctl limits hardware addresses to 8 bytes */
412 + sll->sll_halen = 8;
421 +get_hw_addr(struct interface_info *info)
423 + struct hardware *hw = &info->hw_address;
424 + char *name = info->name;
425 + struct ifaddrs *ifaddrs = NULL;
426 + struct ifaddrs *ifa = NULL;
427 + struct sockaddr_ll *sll = NULL;
428 + int sll_allocated = 0;
430 + char *colon = NULL;
432 + if (getifaddrs(&ifaddrs) == -1)
433 + log_fatal("Failed to get interfaces");
435 + if ((sll = get_ll(ifaddrs, &ifa, name)) == NULL) {
437 + * We were unable to get link-layer address for name.
438 + * Fall back to ioctl(SIOCGIFHWADDR).
440 + sll = ioctl_get_ll(name);
444 + // shouldn't happen
445 + log_fatal("Unexpected internal error");
448 + switch (sll->sll_hatype) {
451 hw->hbuf[0] = HTYPE_ETHER;
452 - memcpy(&hw->hbuf[1], sa->sa_data, 6);
453 + memcpy(&hw->hbuf[1], sll->sll_addr, 6);
456 #ifdef ARPHRD_IEEE802_TR
457 @@ -504,18 +703,48 @@ get_hw_addr(const char *name, struct har
458 #endif /* ARPHRD_IEEE802_TR */
460 hw->hbuf[0] = HTYPE_IEEE802;
461 - memcpy(&hw->hbuf[1], sa->sa_data, 6);
462 + memcpy(&hw->hbuf[1], sll->sll_addr, 6);
466 hw->hbuf[0] = HTYPE_FDDI;
467 - memcpy(&hw->hbuf[1], sa->sa_data, 6);
468 + memcpy(&hw->hbuf[1], sll->sll_addr, 6);
470 + case ARPHRD_INFINIBAND:
471 + dup = strdup(name);
472 + /* Aliased infiniband interface is special case where
473 + * neither get_ll() nor ioctl_get_ll() get's correct hw
474 + * address, so we have to truncate the :0 and run
475 + * get_ll() again for the rest.
477 + if ((colon = strchr(dup, ':')) != NULL) {
479 + if ((sll = get_ll(ifaddrs, &ifa, dup)) == NULL)
480 + log_fatal("Error getting hardware address for \"%s\": %m", name);
483 + /* For Infiniband, save the broadcast address and store
484 + * the port GUID into the hardware address.
486 + if (ifa && (ifa->ifa_flags & IFF_BROADCAST)) {
487 + struct sockaddr_ll *bll;
489 + bll = (struct sockaddr_ll *)ifa->ifa_broadaddr;
490 + memcpy(&info->bcast_addr, bll->sll_addr, 20);
492 + memcpy(&info->bcast_addr, default_ib_bcast_addr,
497 + hw->hbuf[0] = HTYPE_INFINIBAND;
498 + memcpy(&hw->hbuf[1], &sll->sll_addr[sll->sll_halen - 8], 8);
500 #if defined(ARPHRD_PPP)
502 if (local_family != AF_INET6)
503 - log_fatal("Unsupported device type %d for \"%s\"",
504 - sa->sa_family, name);
505 + log_fatal("local_family != AF_INET6 for \"%s\"",
508 hw->hbuf[0] = HTYPE_RESERVED;
509 /* 0xdeadbeef should never occur on the wire,
510 @@ -528,10 +757,13 @@ get_hw_addr(const char *name, struct har
514 - log_fatal("Unsupported device type %ld for \"%s\"",
515 - (long int)sa->sa_family, name);
516 + freeifaddrs(ifaddrs);
517 + log_fatal("Unsupported device type %hu for \"%s\"",
518 + sll->sll_hatype, name);
524 + freeifaddrs(ifaddrs);
527 diff -up dhcp-4.3.1b1/common/socket.c.bmgpWV dhcp-4.3.1b1/common/socket.c
528 --- dhcp-4.3.1b1/common/socket.c.bmgpWV 2014-07-02 19:58:38.000000000 +0200
529 +++ dhcp-4.3.1b1/common/socket.c 2014-07-10 17:52:57.706272281 +0200
530 @@ -322,7 +322,7 @@ void if_register_send (info)
531 info->wfdesc = if_register_socket(info, AF_INET, 0, NULL);
532 /* If this is a normal IPv4 address, get the hardware address. */
533 if (strcmp(info->name, "fallback") != 0)
534 - get_hw_addr(info->name, &info->hw_address);
536 #if defined (USE_SOCKET_FALLBACK)
537 /* Fallback only registers for send, but may need to receive as
539 @@ -385,7 +385,7 @@ void if_register_receive (info)
540 #endif /* IP_PKTINFO... */
541 /* If this is a normal IPv4 address, get the hardware address. */
542 if (strcmp(info->name, "fallback") != 0)
543 - get_hw_addr(info->name, &info->hw_address);
546 if (!quiet_interface_discovery)
547 log_info ("Listening on Socket/%s%s%s",
548 @@ -499,7 +499,7 @@ if_register6(struct interface_info *info
550 if_register_multicast(info);
552 - get_hw_addr(info->name, &info->hw_address);
555 if (!quiet_interface_discovery) {
556 if (info->shared_network != NULL) {
557 @@ -555,7 +555,7 @@ if_register_linklocal6(struct interface_
561 - get_hw_addr(info->name, &info->hw_address);
564 if (!quiet_interface_discovery) {
565 if (info->shared_network != NULL) {
566 diff -up dhcp-4.3.1b1/includes/dhcpd.h.bmgpWV dhcp-4.3.1b1/includes/dhcpd.h
567 --- dhcp-4.3.1b1/includes/dhcpd.h.bmgpWV 2014-07-10 17:50:26.923402536 +0200
568 +++ dhcp-4.3.1b1/includes/dhcpd.h 2014-07-10 17:52:57.707272266 +0200
569 @@ -1248,6 +1248,7 @@ struct interface_info {
570 struct shared_network *shared_network;
571 /* Networks connected to this interface. */
572 struct hardware hw_address; /* Its physical address. */
573 + u_int8_t bcast_addr[20]; /* Infiniband broadcast address */
574 struct in_addr *addresses; /* Addresses associated with this
577 @@ -2439,7 +2440,7 @@ void print_dns_status (int, struct dhcp_
579 const char *print_time(TIME);
581 -void get_hw_addr(const char *name, struct hardware *hw);
582 +void get_hw_addr(struct interface_info *info);
585 #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_RECEIVE) \