ISC DHCP  4.3.2
A reference DHCPv4 and DHCPv6 implementation
lpf.c
Go to the documentation of this file.
1 /* lpf.c
2 
3  Linux packet filter code, contributed by Brian Murrel at Interlinx
4  Support Services in Vancouver, B.C. */
5 
6 /*
7  * Copyright (c) 2014-2015 by Internet Systems Consortium, Inc. ("ISC")
8  * Copyright (c) 2009,2012 by Internet Systems Consortium, Inc. ("ISC")
9  * Copyright (c) 2004,2007 by Internet Systems Consortium, Inc. ("ISC")
10  * Copyright (c) 1996-2003 by Internet Software Consortium
11  *
12  * Permission to use, copy, modify, and distribute this software for any
13  * purpose with or without fee is hereby granted, provided that the above
14  * copyright notice and this permission notice appear in all copies.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
17  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
19  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
21  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
22  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23  *
24  * Internet Systems Consortium, Inc.
25  * 950 Charter Street
26  * Redwood City, CA 94063
27  * <info@isc.org>
28  * https://www.isc.org/
29  */
30 
31 #include "dhcpd.h"
32 #if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE)
33 #include <sys/uio.h>
34 #include <errno.h>
35 
36 #include <asm/types.h>
37 #include <linux/filter.h>
38 #include <linux/if_ether.h>
39 #include <linux/if_packet.h>
40 #include <netinet/in_systm.h>
41 #include "includes/netinet/ip.h"
42 #include "includes/netinet/udp.h"
44 #endif
45 
46 #if defined (USE_LPF_RECEIVE) || defined (USE_LPF_HWADDR)
47 #include <sys/ioctl.h>
48 #include <sys/socket.h>
49 #include <net/if.h>
50 #include <ifaddrs.h>
51 
52 /* Default broadcast address for IPoIB */
53 static unsigned char default_ib_bcast_addr[20] = {
54  0x00, 0xff, 0xff, 0xff,
55  0xff, 0x12, 0x40, 0x1b,
56  0x00, 0x00, 0x00, 0x00,
57  0x00, 0x00, 0x00, 0x00,
58  0xff, 0xff, 0xff, 0xff
59 };
60 
61 #endif
62 
63 #if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE)
64 /* Reinitializes the specified interface after an address change. This
65  is not required for packet-filter APIs. */
66 
67 #ifdef USE_LPF_SEND
68 void if_reinitialize_send (info)
69  struct interface_info *info;
70 {
71 }
72 #endif
73 
74 #ifdef USE_LPF_RECEIVE
75 void if_reinitialize_receive (info)
76  struct interface_info *info;
77 {
78 }
79 #endif
80 
81 /* Called by get_interface_list for each interface that's discovered.
82  Opens a packet filter for each interface and adds it to the select
83  mask. */
84 
85 int if_register_lpf (info)
86  struct interface_info *info;
87 {
88  int sock;
89  union {
90  struct sockaddr_ll ll;
91  struct sockaddr common;
92  } sa;
93  struct ifreq ifr;
94  int type;
95  int protocol;
96 
97  get_hw_addr(info);
98  if (info->hw_address.hbuf[0] == HTYPE_INFINIBAND) {
99  type = SOCK_DGRAM;
100  protocol = ETHERTYPE_IP;
101  } else {
102  type = SOCK_RAW;
103  protocol = ETH_P_ALL;
104  }
105 
106  /* Make an LPF socket. */
107  if ((sock = socket(PF_PACKET, type, htons((short)protocol))) < 0) {
108  if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
109  errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
110  errno == EAFNOSUPPORT || errno == EINVAL) {
111  log_error ("socket: %m - make sure");
112  log_error ("CONFIG_PACKET (Packet socket) %s",
113  "and CONFIG_FILTER");
114  log_error ("(Socket Filtering) are enabled %s",
115  "in your kernel");
116  log_fatal ("configuration!");
117  }
118  log_fatal ("Open a socket for LPF: %m");
119  }
120 
121  memset (&ifr, 0, sizeof ifr);
122  strncpy (ifr.ifr_name, (const char *)info -> ifp, sizeof ifr.ifr_name);
123  ifr.ifr_name[IFNAMSIZ-1] = '\0';
124  if (ioctl (sock, SIOCGIFINDEX, &ifr))
125  log_fatal ("Failed to get interface index: %m");
126 
127  /* Bind to the interface name */
128  memset (&sa, 0, sizeof sa);
129  sa.ll.sll_family = AF_PACKET;
130  sa.ll.sll_protocol = htons(protocol);
131  sa.ll.sll_ifindex = ifr.ifr_ifindex;
132  if (bind (sock, &sa.common, sizeof sa)) {
133  if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
134  errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
135  errno == EAFNOSUPPORT || errno == EINVAL) {
136  log_error ("socket: %m - make sure");
137  log_error ("CONFIG_PACKET (Packet socket) %s",
138  "and CONFIG_FILTER");
139  log_error ("(Socket Filtering) are enabled %s",
140  "in your kernel");
141  log_fatal ("configuration!");
142  }
143  log_fatal ("Bind socket to interface: %m");
144 
145  }
146 
147  return sock;
148 }
149 #endif /* USE_LPF_SEND || USE_LPF_RECEIVE */
150 
151 #ifdef USE_LPF_SEND
152 void if_register_send (info)
153  struct interface_info *info;
154 {
155  /* If we're using the lpf API for sending and receiving,
156  we don't need to register this interface twice. */
157 #ifndef USE_LPF_RECEIVE
158  info -> wfdesc = if_register_lpf (info);
159 #else
160  info -> wfdesc = info -> rfdesc;
161 #endif
163  log_info ("Sending on LPF/%s/%s%s%s",
164  info -> name,
165  print_hw_addr (info -> hw_address.hbuf [0],
166  info -> hw_address.hlen - 1,
167  &info -> hw_address.hbuf [1]),
168  (info -> shared_network ? "/" : ""),
169  (info -> shared_network ?
170  info -> shared_network -> name : ""));
171 }
172 
173 void if_deregister_send (info)
174  struct interface_info *info;
175 {
176  /* don't need to close twice if we are using lpf for sending and
177  receiving */
178 #ifndef USE_LPF_RECEIVE
179  /* for LPF this is simple, packet filters are removed when sockets
180  are closed */
181  close (info -> wfdesc);
182 #endif
183  info -> wfdesc = -1;
185  log_info ("Disabling output on LPF/%s/%s%s%s",
186  info -> name,
187  print_hw_addr (info -> hw_address.hbuf [0],
188  info -> hw_address.hlen - 1,
189  &info -> hw_address.hbuf [1]),
190  (info -> shared_network ? "/" : ""),
191  (info -> shared_network ?
192  info -> shared_network -> name : ""));
193 }
194 #endif /* USE_LPF_SEND */
195 
196 #ifdef USE_LPF_RECEIVE
197 /* Defined in bpf.c. We can't extern these in dhcpd.h without pulling
198  in bpf includes... */
199 extern struct sock_filter dhcp_bpf_filter [];
200 extern int dhcp_bpf_filter_len;
201 extern struct sock_filter dhcp_ib_bpf_filter [];
202 extern int dhcp_ib_bpf_filter_len;
203 
204 #if defined (HAVE_TR_SUPPORT)
205 extern struct sock_filter dhcp_bpf_tr_filter [];
206 extern int dhcp_bpf_tr_filter_len;
207 static void lpf_tr_filter_setup (struct interface_info *);
208 #endif
209 
210 static void lpf_gen_filter_setup (struct interface_info *);
211 
212 void if_register_receive (info)
213  struct interface_info *info;
214 {
215  /* Open a LPF device and hang it on this interface... */
216  info -> rfdesc = if_register_lpf (info);
217 
218 #ifdef PACKET_AUXDATA
219  {
220  int val = 1;
221  if (info->hw_address.hbuf[0] != HTYPE_INFINIBAND) {
222  if (setsockopt(info->rfdesc, SOL_PACKET, PACKET_AUXDATA,
223  &val, sizeof(val)) < 0) {
224  if (errno != ENOPROTOOPT) {
225  log_fatal ("Failed to set auxiliary packet data: %m");
226  }
227  }
228  }
229  }
230 #endif
231 
232 
233 #if defined (HAVE_TR_SUPPORT)
234  if (info -> hw_address.hbuf [0] == HTYPE_IEEE802)
235  lpf_tr_filter_setup (info);
236  else
237 #endif
238  lpf_gen_filter_setup (info);
239 
241  log_info ("Listening on LPF/%s/%s%s%s",
242  info -> name,
243  print_hw_addr (info -> hw_address.hbuf [0],
244  info -> hw_address.hlen - 1,
245  &info -> hw_address.hbuf [1]),
246  (info -> shared_network ? "/" : ""),
247  (info -> shared_network ?
248  info -> shared_network -> name : ""));
249 }
250 
251 void if_deregister_receive (info)
252  struct interface_info *info;
253 {
254  /* for LPF this is simple, packet filters are removed when sockets
255  are closed */
256  close (info -> rfdesc);
257  info -> rfdesc = -1;
259  log_info ("Disabling input on LPF/%s/%s%s%s",
260  info -> name,
261  print_hw_addr (info -> hw_address.hbuf [0],
262  info -> hw_address.hlen - 1,
263  &info -> hw_address.hbuf [1]),
264  (info -> shared_network ? "/" : ""),
265  (info -> shared_network ?
266  info -> shared_network -> name : ""));
267 }
268 
269 static void lpf_gen_filter_setup (info)
270  struct interface_info *info;
271 {
272  struct sock_fprog p;
273 
274  memset(&p, 0, sizeof(p));
275 
276  if (info->hw_address.hbuf[0] == HTYPE_INFINIBAND) {
277  /* Set up the bpf filter program structure. */
278  p.len = dhcp_ib_bpf_filter_len;
279  p.filter = dhcp_ib_bpf_filter;
280 
281  /* Patch the server port into the LPF program...
282  XXX
283  changes to filter program may require changes
284  to the insn number(s) used below!
285  XXX */
286  dhcp_ib_bpf_filter[6].k = ntohs ((short)local_port);
287  } else {
288  /* Set up the bpf filter program structure.
289  This is defined in bpf.c */
290  p.len = dhcp_bpf_filter_len;
291  p.filter = dhcp_bpf_filter;
292 
293  /* Patch the server port into the LPF program...
294  XXX changes to filter program may require changes
295  to the insn number(s) used below! XXX */
296  dhcp_bpf_filter [8].k = ntohs ((short)local_port);
297  }
298 
299  if (setsockopt (info -> rfdesc, SOL_SOCKET, SO_ATTACH_FILTER, &p,
300  sizeof p) < 0) {
301  if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
302  errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
303  errno == EAFNOSUPPORT) {
304  log_error ("socket: %m - make sure");
305  log_error ("CONFIG_PACKET (Packet socket) %s",
306  "and CONFIG_FILTER");
307  log_error ("(Socket Filtering) are enabled %s",
308  "in your kernel");
309  log_fatal ("configuration!");
310  }
311  log_fatal ("Can't install packet filter program: %m");
312  }
313 }
314 
315 #if defined (HAVE_TR_SUPPORT)
316 static void lpf_tr_filter_setup (info)
317  struct interface_info *info;
318 {
319  struct sock_fprog p;
320 
321  memset(&p, 0, sizeof(p));
322 
323  /* Set up the bpf filter program structure. This is defined in
324  bpf.c */
325  p.len = dhcp_bpf_tr_filter_len;
326  p.filter = dhcp_bpf_tr_filter;
327 
328  /* Patch the server port into the LPF program...
329  XXX changes to filter program may require changes
330  XXX to the insn number(s) used below!
331  XXX Token ring filter is null - when/if we have a filter
332  XXX that's not, we'll need this code.
333  XXX dhcp_bpf_filter [?].k = ntohs (local_port); */
334 
335  if (setsockopt (info -> rfdesc, SOL_SOCKET, SO_ATTACH_FILTER, &p,
336  sizeof p) < 0) {
337  if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
338  errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
339  errno == EAFNOSUPPORT) {
340  log_error ("socket: %m - make sure");
341  log_error ("CONFIG_PACKET (Packet socket) %s",
342  "and CONFIG_FILTER");
343  log_error ("(Socket Filtering) are enabled %s",
344  "in your kernel");
345  log_fatal ("configuration!");
346  }
347  log_fatal ("Can't install packet filter program: %m");
348  }
349 }
350 #endif /* HAVE_TR_SUPPORT */
351 #endif /* USE_LPF_RECEIVE */
352 
353 #ifdef USE_LPF_SEND
354 ssize_t send_packet_ib(interface, packet, raw, len, from, to, hto)
355  struct interface_info *interface;
356  struct packet *packet;
357  struct dhcp_packet *raw;
358  size_t len;
359  struct in_addr from;
360  struct sockaddr_in *to;
361  struct hardware *hto;
362 {
363  unsigned ibufp = 0;
364  double ih [1536 / sizeof (double)];
365  unsigned char *buf = (unsigned char *)ih;
366  ssize_t result;
367 
368  union sockunion {
369  struct sockaddr sa;
370  struct sockaddr_ll sll;
371  struct sockaddr_storage ss;
372  } su;
373 
374  assemble_udp_ip_header (interface, buf, &ibufp, from.s_addr,
375  to->sin_addr.s_addr, to->sin_port,
376  (unsigned char *)raw, len);
377  memcpy (buf + ibufp, raw, len);
378 
379  memset(&su, 0, sizeof(su));
380  su.sll.sll_family = AF_PACKET;
381  su.sll.sll_protocol = htons(ETHERTYPE_IP);
382 
383  if (!(su.sll.sll_ifindex = if_nametoindex(interface->name))) {
384  errno = ENOENT;
385  log_error ("send_packet_ib: %m - failed to get if index");
386  return -1;
387  }
388 
389  su.sll.sll_hatype = htons(HTYPE_INFINIBAND);
390  su.sll.sll_halen = sizeof(interface->bcast_addr);
391  memcpy(&su.sll.sll_addr, interface->bcast_addr, 20);
392 
393  result = sendto(interface->wfdesc, buf, ibufp + len, 0,
394  &su.sa, sizeof(su));
395 
396  if (result < 0)
397  log_error ("send_packet_ib: %m");
398 
399  return result;
400 }
401 
402 ssize_t send_packet (interface, packet, raw, len, from, to, hto)
403  struct interface_info *interface;
404  struct packet *packet;
405  struct dhcp_packet *raw;
406  size_t len;
407  struct in_addr from;
408  struct sockaddr_in *to;
409  struct hardware *hto;
410 {
411  unsigned hbufp = 0, ibufp = 0;
412  double hh [16];
413  double ih [1536 / sizeof (double)];
414  unsigned char *buf = (unsigned char *)ih;
415  int result;
416  int fudge;
417 
418  if (!strcmp (interface -> name, "fallback"))
419  return send_fallback (interface, packet, raw,
420  len, from, to, hto);
421 
422  if (interface->hw_address.hbuf[0] == HTYPE_INFINIBAND) {
423  return send_packet_ib(interface, packet, raw, len, from,
424  to, hto);
425  }
426 
427  if (hto == NULL && interface->anycast_mac_addr.hlen)
428  hto = &interface->anycast_mac_addr;
429 
430  /* Assemble the headers... */
431  assemble_hw_header (interface, (unsigned char *)hh, &hbufp, hto);
432  fudge = hbufp % 4; /* IP header must be word-aligned. */
433  memcpy (buf + fudge, (unsigned char *)hh, hbufp);
434  ibufp = hbufp + fudge;
435  assemble_udp_ip_header (interface, buf, &ibufp, from.s_addr,
436  to -> sin_addr.s_addr, to -> sin_port,
437  (unsigned char *)raw, len);
438  memcpy (buf + ibufp, raw, len);
439  result = write(interface->wfdesc, buf + fudge, ibufp + len - fudge);
440  if (result < 0)
441  log_error ("send_packet: %m");
442  return result;
443 }
444 #endif /* USE_LPF_SEND */
445 
446 #ifdef USE_LPF_RECEIVE
447 ssize_t receive_packet_ib (interface, buf, len, from, hfrom)
448  struct interface_info *interface;
449  unsigned char *buf;
450  size_t len;
451  struct sockaddr_in *from;
452  struct hardware *hfrom;
453 {
454  int length = 0;
455  int offset = 0;
456  unsigned char ibuf [1536];
457  unsigned bufix = 0;
458  unsigned paylen;
459 
460  length = read(interface->rfdesc, ibuf, sizeof(ibuf));
461 
462  if (length <= 0)
463  return length;
464 
465  offset = decode_udp_ip_header(interface, ibuf, bufix, from,
466  (unsigned)length, &paylen, 0);
467 
468  if (offset < 0)
469  return 0;
470 
471  bufix += offset;
472  length -= offset;
473 
474  if (length < paylen)
475  log_fatal("Internal inconsistency at %s:%d.", MDL);
476 
477  /* Copy out the data in the packet... */
478  memcpy(buf, &ibuf[bufix], paylen);
479 
480  return (ssize_t)paylen;
481 }
482 
483 ssize_t receive_packet (interface, buf, len, from, hfrom)
484  struct interface_info *interface;
485  unsigned char *buf;
486  size_t len;
487  struct sockaddr_in *from;
488  struct hardware *hfrom;
489 {
490  int length = 0;
491  int offset = 0;
492  int csum_ready = 1;
493  unsigned char ibuf [1536];
494  unsigned bufix = 0;
495  unsigned paylen;
496  unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
497  struct iovec iov = {
498  .iov_base = ibuf,
499  .iov_len = sizeof ibuf,
500  };
501  struct msghdr msg = {
502  .msg_iov = &iov,
503  .msg_iovlen = 1,
504  .msg_control = cmsgbuf,
505  .msg_controllen = sizeof(cmsgbuf),
506  };
507 
508  if (interface->hw_address.hbuf[0] == HTYPE_INFINIBAND) {
509  return receive_packet_ib(interface, buf, len, from, hfrom);
510  }
511 
512  length = recvmsg (interface->rfdesc, &msg, 0);
513  if (length <= 0)
514  return length;
515 
516 #ifdef PACKET_AUXDATA
517  {
518  /* Use auxiliary packet data to:
519  *
520  * a. Weed out extraneous VLAN-tagged packets - If the NIC driver is
521  * handling VLAN encapsulation (i.e. stripping/adding VLAN tags),
522  * then an inbound VLAN packet will be seen twice: Once by
523  * the parent interface (e.g. eth0) with a VLAN tag != 0; and once
524  * by the vlan interface (e.g. eth0.n) with a VLAN tag of 0 (i.e none).
525  * We want to discard the packet sent to the parent and thus respond
526  * only over the vlan interface. (Drivers for Intel PRO/1000 series
527  * NICs perform VLAN encapsulation, while drivers for PCnet series
528  * do not, for example. The linux kernel makes stripped vlan info
529  * visible to user space via CMSG/auxdata, this appears to not be
530  * true for BSD OSs.). NOTE: this is only supported on linux flavors
531  * which define the tpacket_auxdata.tp_vlan_tci.
532  *
533  * b. Determine if checksum is valid for use. It may not be if
534  * checksum offloading is enabled on the interface. */
535  struct cmsghdr *cmsg;
536 
537  for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
538  if (cmsg->cmsg_level == SOL_PACKET &&
539  cmsg->cmsg_type == PACKET_AUXDATA) {
540  struct tpacket_auxdata *aux = (void *)CMSG_DATA(cmsg);
541  /* Discard packets with stripped vlan id */
542 
543 #ifdef VLAN_TCI_PRESENT
544  if (aux->tp_vlan_tci != 0)
545  return 0;
546 #endif
547 
548  csum_ready = ((aux->tp_status & TP_STATUS_CSUMNOTREADY)
549  ? 0 : 1);
550  }
551  }
552 
553  }
554 #endif
555 
556  bufix = 0;
557  /* Decode the physical header... */
558  offset = decode_hw_header (interface, ibuf, bufix, hfrom);
559 
560  /* If a physical layer checksum failed (dunno of any
561  physical layer that supports this, but WTH), skip this
562  packet. */
563  if (offset < 0) {
564  return 0;
565  }
566 
567  bufix += offset;
568  length -= offset;
569 
570  /* Decode the IP and UDP headers... */
571  offset = decode_udp_ip_header (interface, ibuf, bufix, from,
572  (unsigned)length, &paylen, csum_ready);
573 
574  /* If the IP or UDP checksum was bad, skip the packet... */
575  if (offset < 0)
576  return 0;
577 
578  bufix += offset;
579  length -= offset;
580 
581  if (length < paylen)
582  log_fatal("Internal inconsistency at %s:%d.", MDL);
583 
584  /* Copy out the data in the packet... */
585  memcpy(buf, &ibuf[bufix], paylen);
586  return paylen;
587 }
588 
590  struct interface_info *ip;
591 {
592  return 1;
593 }
594 
596  struct interface_info *ip;
597 {
598  return 1;
599 }
600 
602  struct interface_info *ip;
603 {
604  return 1;
605 }
606 
607 void maybe_setup_fallback ()
608 {
609  isc_result_t status;
610  struct interface_info *fbi = (struct interface_info *)0;
611  if (setup_fallback (&fbi, MDL)) {
612  if_register_fallback (fbi);
613  status = omapi_register_io_object ((omapi_object_t *)fbi,
614  if_readsocket, 0,
615  fallback_discard, 0, 0);
616  if (status != ISC_R_SUCCESS)
617  log_fatal ("Can't register I/O handle for \"%s\": %s",
618  fbi -> name, isc_result_totext (status));
619  interface_dereference (&fbi, MDL);
620  }
621 }
622 #endif
623 
624 #if defined (USE_LPF_RECEIVE) || defined (USE_LPF_HWADDR)
625 struct sockaddr_ll *
626 get_ll (struct ifaddrs *ifaddrs, struct ifaddrs **ifa, char *name)
627 {
628  for (*ifa = ifaddrs; *ifa != NULL; *ifa = (*ifa)->ifa_next) {
629  if ((*ifa)->ifa_addr == NULL)
630  continue;
631 
632  if ((*ifa)->ifa_addr->sa_family != AF_PACKET)
633  continue;
634 
635  if ((*ifa)->ifa_flags & IFF_LOOPBACK)
636  continue;
637 
638  if (strcmp((*ifa)->ifa_name, name) == 0)
639  return (struct sockaddr_ll *)(void *)(*ifa)->ifa_addr;
640  }
641  *ifa = NULL;
642  return NULL;
643 }
644 
645 struct sockaddr_ll *
646 ioctl_get_ll(char *name)
647 {
648  int sock;
649  struct ifreq tmp;
650  struct sockaddr *sa = NULL;
651  struct sockaddr_ll *sll = NULL;
652 
653  if (strlen(name) >= sizeof(tmp.ifr_name)) {
654  log_fatal("Device name too long: \"%s\"", name);
655  }
656 
657  sock = socket(AF_INET, SOCK_DGRAM, 0);
658  if (sock < 0) {
659  log_fatal("Can't create socket for \"%s\": %m", name);
660  }
661 
662  memset(&tmp, 0, sizeof(tmp));
663  strcpy(tmp.ifr_name, name);
664  if (ioctl(sock, SIOCGIFHWADDR, &tmp) < 0) {
665  log_fatal("Error getting hardware address for \"%s\": %m",
666  name);
667  }
668  close(sock);
669 
670  sa = &tmp.ifr_hwaddr;
671  // needs to be freed outside this function
672  sll = dmalloc (sizeof (struct sockaddr_ll), MDL);
673  if (!sll)
674  log_fatal("Unable to allocate memory for link layer address");
675  memcpy(&sll->sll_hatype, &sa->sa_family, sizeof (sll->sll_hatype));
676  memcpy(sll->sll_addr, sa->sa_data, sizeof (sll->sll_addr));
677  switch (sll->sll_hatype) {
678  case ARPHRD_INFINIBAND:
679  sll->sll_halen = HARDWARE_ADDR_LEN_IOCTL;
680  break;
681  default:
682  break;
683  }
684  return sll;
685 }
686 
687 void
688 get_hw_addr(struct interface_info *info)
689 {
690  struct hardware *hw = &info->hw_address;
691  char *name = info->name;
692  struct ifaddrs *ifaddrs = NULL;
693  struct ifaddrs *ifa = NULL;
694  struct sockaddr_ll *sll = NULL;
695  int sll_allocated = 0;
696  char *dup = NULL;
697  char *colon = NULL;
698 
699  if (getifaddrs(&ifaddrs) == -1)
700  log_fatal("Failed to get interfaces");
701 
702  if ((sll = get_ll(ifaddrs, &ifa, name)) == NULL) {
703  /*
704  * We were unable to get link-layer address for name.
705  * Fall back to ioctl(SIOCGIFHWADDR).
706  */
707  sll = ioctl_get_ll(name);
708  if (sll != NULL)
709  sll_allocated = 1;
710  else
711  // shouldn't happen
712  log_fatal("Unexpected internal error");
713  }
714 
715  switch (sll->sll_hatype) {
716  case ARPHRD_ETHER:
717  hw->hlen = 7;
718  hw->hbuf[0] = HTYPE_ETHER;
719  memcpy(&hw->hbuf[1], sll->sll_addr, 6);
720  break;
721  case ARPHRD_IEEE802:
722 #ifdef ARPHRD_IEEE802_TR
723  case ARPHRD_IEEE802_TR:
724 #endif /* ARPHRD_IEEE802_TR */
725  hw->hlen = 7;
726  hw->hbuf[0] = HTYPE_IEEE802;
727  memcpy(&hw->hbuf[1], sll->sll_addr, 6);
728  break;
729  case ARPHRD_FDDI:
730  hw->hlen = 7;
731  hw->hbuf[0] = HTYPE_FDDI;
732  memcpy(&hw->hbuf[1], sll->sll_addr, 6);
733  break;
734  case ARPHRD_INFINIBAND:
735  dup = strdup(name);
736  /* Aliased infiniband interface is special case where
737  * neither get_ll() nor ioctl_get_ll() get's correct hw
738  * address, so we have to truncate the :0 and run
739  * get_ll() again for the rest.
740  */
741  if ((colon = strchr(dup, ':')) != NULL) {
742  *colon = '\0';
743  if ((sll = get_ll(ifaddrs, &ifa, dup)) == NULL)
744  log_fatal("Error getting hardware address for \"%s\": %m", name);
745  }
746  free (dup);
747  /* For Infiniband, save the broadcast address and store
748  * the port GUID into the hardware address.
749  */
750  if (ifa && (ifa->ifa_flags & IFF_BROADCAST)) {
751  struct sockaddr_ll *bll;
752 
753  bll = (struct sockaddr_ll *)ifa->ifa_broadaddr;
754  memcpy(&info->bcast_addr, bll->sll_addr, 20);
755  } else {
756  memcpy(&info->bcast_addr, default_ib_bcast_addr,
757  20);
758  }
759 
760  hw->hlen = HARDWARE_ADDR_LEN_IOCTL + 1;
761  hw->hbuf[0] = HTYPE_INFINIBAND;
762  memcpy(&hw->hbuf[1],
763  &sll->sll_addr[sll->sll_halen - HARDWARE_ADDR_LEN_IOCTL],
765  break;
766 #if defined(ARPHRD_PPP)
767  case ARPHRD_PPP:
768  if (local_family != AF_INET6)
769  log_fatal("local_family != AF_INET6 for \"%s\"",
770  name);
771  hw->hlen = 0;
772  hw->hbuf[0] = HTYPE_RESERVED;
773  /* 0xdeadbeef should never occur on the wire,
774  * and is a signature that something went wrong.
775  */
776  hw->hbuf[1] = 0xde;
777  hw->hbuf[2] = 0xad;
778  hw->hbuf[3] = 0xbe;
779  hw->hbuf[4] = 0xef;
780  break;
781 #endif
782  default:
783  freeifaddrs(ifaddrs);
784  log_fatal("Unsupported device type %hu for \"%s\"",
785  sll->sll_hatype, name);
786  }
787 
788  if (sll_allocated)
789  dfree(sll, MDL);
790  freeifaddrs(ifaddrs);
791 }
792 #endif
void if_register_send(struct interface_info *)
isc_result_t omapi_register_io_object(omapi_object_t *, int(*)(omapi_object_t *), int(*)(omapi_object_t *), isc_result_t(*)(omapi_object_t *), isc_result_t(*)(omapi_object_t *), isc_result_t(*)(omapi_object_t *))
Definition: dispatch.c:199
void assemble_udp_ip_header(struct interface_info *, unsigned char *, unsigned *, u_int32_t, u_int32_t, u_int32_t, unsigned char *, unsigned)
#define ETHERTYPE_IP
Definition: if_ether.h:57
u_int8_t hlen
Definition: dhcpd.h:454
int if_readsocket(omapi_object_t *h)
Definition: discover.c:964
char name[IFNAMSIZ]
Definition: dhcpd.h:1305
void if_reinitialize_send(struct interface_info *)
void * dmalloc(unsigned, const char *, int)
Definition: alloc.c:56
ssize_t decode_udp_ip_header(struct interface_info *, unsigned char *, unsigned, struct sockaddr_in *, unsigned, unsigned *, int)
#define HTYPE_RESERVED
Definition: dhcp.h:84
#define MDL
Definition: omapip.h:568
int can_receive_unicast_unconfigured(struct interface_info *)
int setup_fallback(struct interface_info **fp, const char *file, int line)
Definition: discover.c:975
int log_error(const char *,...) __attribute__((__format__(__printf__
void if_deregister_receive(struct interface_info *)
void get_hw_addr(struct interface_info *info)
void maybe_setup_fallback(void)
void if_deregister_send(struct interface_info *)
void log_fatal(const char *,...) __attribute__((__format__(__printf__
#define HTYPE_ETHER
Definition: dhcp.h:76
#define HTYPE_INFINIBAND
Definition: dhcp.h:79
u_int16_t local_port
Definition: dhclient.c:88
Definition: dhcpd.h:376
void assemble_hw_header(struct interface_info *, unsigned char *, unsigned *, struct hardware *)
int if_register_lpf(struct interface_info *)
u_int8_t bcast_addr[20]
Definition: dhcpd.h:1284
Definition: ip.h:47
ssize_t send_packet(struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)
void dfree(void *, const char *, int)
Definition: alloc.c:131
struct hardware hw_address
Definition: dhcpd.h:1283
#define HARDWARE_ADDR_LEN_IOCTL
Definition: dhcpd.h:451
int int log_info(const char *,...) __attribute__((__format__(__printf__
int local_family
Definition: discover.c:55
int quiet_interface_discovery
Definition: discover.c:45
#define HTYPE_FDDI
Definition: dhcp.h:78
void if_register_fallback(struct interface_info *)
ssize_t send_fallback(struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)
int supports_multiple_interfaces(struct interface_info *)
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
Definition: dhcpd.h:455
ssize_t receive_packet(struct interface_info *, unsigned char *, size_t, struct sockaddr_in *, struct hardware *)
#define HTYPE_IEEE802
Definition: dhcp.h:77
ssize_t decode_hw_header(struct interface_info *, unsigned char *, unsigned, struct hardware *)
void if_reinitialize_receive(struct interface_info *)
int can_unicast_without_arp(struct interface_info *)
void if_register_receive(struct interface_info *)
isc_result_t fallback_discard(omapi_object_t *)