ISC DHCP  4.3.6
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;
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  struct iovec iov = {
497  .iov_base = ibuf,
498  .iov_len = sizeof ibuf,
499  };
500 #ifdef PACKET_AUXDATA
501  /*
502  * We only need cmsgbuf if we are getting the aux data and we
503  * only get the auxdata if it is actually defined
504  */
505  unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
506  struct msghdr msg = {
507  .msg_iov = &iov,
508  .msg_iovlen = 1,
509  .msg_control = cmsgbuf,
510  .msg_controllen = sizeof(cmsgbuf),
511  };
512 #else
513  struct msghdr msg = {
514  .msg_iov = &iov,
515  .msg_iovlen = 1,
516  .msg_control = NULL,
517  .msg_controllen = 0,
518  };
519 #endif /* PACKET_AUXDATA */
520 
521  if (interface->hw_address.hbuf[0] == HTYPE_INFINIBAND) {
522  return receive_packet_ib(interface, buf, len, from, hfrom);
523  }
524 
525  length = recvmsg (interface->rfdesc, &msg, 0);
526  if (length <= 0)
527  return length;
528 
529 #ifdef PACKET_AUXDATA
530  {
531  /* Use auxiliary packet data to:
532  *
533  * a. Weed out extraneous VLAN-tagged packets - If the NIC driver is
534  * handling VLAN encapsulation (i.e. stripping/adding VLAN tags),
535  * then an inbound VLAN packet will be seen twice: Once by
536  * the parent interface (e.g. eth0) with a VLAN tag != 0; and once
537  * by the vlan interface (e.g. eth0.n) with a VLAN tag of 0 (i.e none).
538  * We want to discard the packet sent to the parent and thus respond
539  * only over the vlan interface. (Drivers for Intel PRO/1000 series
540  * NICs perform VLAN encapsulation, while drivers for PCnet series
541  * do not, for example. The linux kernel makes stripped vlan info
542  * visible to user space via CMSG/auxdata, this appears to not be
543  * true for BSD OSs.). NOTE: this is only supported on linux flavors
544  * which define the tpacket_auxdata.tp_vlan_tci.
545  *
546  * b. Determine if checksum is valid for use. It may not be if
547  * checksum offloading is enabled on the interface. */
548  struct cmsghdr *cmsg;
549 
550  for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
551  if (cmsg->cmsg_level == SOL_PACKET &&
552  cmsg->cmsg_type == PACKET_AUXDATA) {
553  struct tpacket_auxdata *aux = (void *)CMSG_DATA(cmsg);
554 #ifdef VLAN_TCI_PRESENT
555  /* Discard packets with stripped vlan id */
556  /* VLAN ID is only bottom 12-bits of TCI */
557  if (aux->tp_vlan_tci & 0x0fff)
558  return 0;
559 #endif
560 
561  csum_ready = ((aux->tp_status & TP_STATUS_CSUMNOTREADY)
562  ? 0 : 1);
563  }
564  }
565 
566  }
567 #endif /* PACKET_AUXDATA */
568 
569  bufix = 0;
570  /* Decode the physical header... */
571  offset = decode_hw_header (interface, ibuf, bufix, hfrom);
572 
573  /* If a physical layer checksum failed (dunno of any
574  physical layer that supports this, but WTH), skip this
575  packet. */
576  if (offset < 0) {
577  return 0;
578  }
579 
580  bufix += offset;
581  length -= offset;
582 
583  /* Decode the IP and UDP headers... */
584  offset = decode_udp_ip_header (interface, ibuf, bufix, from,
585  (unsigned)length, &paylen, csum_ready);
586 
587  /* If the IP or UDP checksum was bad, skip the packet... */
588  if (offset < 0)
589  return 0;
590 
591  bufix += offset;
592  length -= offset;
593 
594  if (length < paylen)
595  log_fatal("Internal inconsistency at %s:%d.", MDL);
596 
597  /* Copy out the data in the packet... */
598  memcpy(buf, &ibuf[bufix], paylen);
599  return paylen;
600 }
601 
603  struct interface_info *ip;
604 {
605  return 1;
606 }
607 
609  struct interface_info *ip;
610 {
611  return 1;
612 }
613 
615  struct interface_info *ip;
616 {
617  return 1;
618 }
619 
620 void maybe_setup_fallback ()
621 {
622  isc_result_t status;
623  struct interface_info *fbi = (struct interface_info *)0;
624  if (setup_fallback (&fbi, MDL)) {
625  if_register_fallback (fbi);
626  status = omapi_register_io_object ((omapi_object_t *)fbi,
627  if_readsocket, 0,
628  fallback_discard, 0, 0);
629  if (status != ISC_R_SUCCESS)
630  log_fatal ("Can't register I/O handle for \"%s\": %s",
631  fbi -> name, isc_result_totext (status));
632  interface_dereference (&fbi, MDL);
633  }
634 }
635 #endif
636 
637 #if defined (USE_LPF_RECEIVE) || defined (USE_LPF_HWADDR)
638 struct sockaddr_ll *
639 get_ll (struct ifaddrs *ifaddrs, struct ifaddrs **ifa, char *name)
640 {
641  for (*ifa = ifaddrs; *ifa != NULL; *ifa = (*ifa)->ifa_next) {
642  if ((*ifa)->ifa_addr == NULL)
643  continue;
644 
645  if ((*ifa)->ifa_addr->sa_family != AF_PACKET)
646  continue;
647 
648  if ((*ifa)->ifa_flags & IFF_LOOPBACK)
649  continue;
650 
651  if (strcmp((*ifa)->ifa_name, name) == 0)
652  return (struct sockaddr_ll *)(void *)(*ifa)->ifa_addr;
653  }
654  *ifa = NULL;
655  return NULL;
656 }
657 
658 struct sockaddr_ll *
659 ioctl_get_ll(char *name)
660 {
661  int sock;
662  struct ifreq tmp;
663  struct sockaddr *sa = NULL;
664  struct sockaddr_ll *sll = NULL;
665 
666  if (strlen(name) >= sizeof(tmp.ifr_name)) {
667  log_fatal("Device name too long: \"%s\"", name);
668  }
669 
670  sock = socket(AF_INET, SOCK_DGRAM, 0);
671  if (sock < 0) {
672  log_fatal("Can't create socket for \"%s\": %m", name);
673  }
674 
675  memset(&tmp, 0, sizeof(tmp));
676  strcpy(tmp.ifr_name, name);
677  if (ioctl(sock, SIOCGIFHWADDR, &tmp) < 0) {
678  log_fatal("Error getting hardware address for \"%s\": %m",
679  name);
680  }
681  close(sock);
682 
683  sa = &tmp.ifr_hwaddr;
684  // needs to be freed outside this function
685  sll = dmalloc (sizeof (struct sockaddr_ll), MDL);
686  if (!sll)
687  log_fatal("Unable to allocate memory for link layer address");
688  memcpy(&sll->sll_hatype, &sa->sa_family, sizeof (sll->sll_hatype));
689  memcpy(sll->sll_addr, sa->sa_data, sizeof (sll->sll_addr));
690  switch (sll->sll_hatype) {
691  case ARPHRD_INFINIBAND:
692  sll->sll_halen = HARDWARE_ADDR_LEN_IOCTL;
693  break;
694  default:
695  break;
696  }
697  return sll;
698 }
699 
700 void
701 get_hw_addr(struct interface_info *info)
702 {
703  struct hardware *hw = &info->hw_address;
704  char *name = info->name;
705  struct ifaddrs *ifaddrs = NULL;
706  struct ifaddrs *ifa = NULL;
707  struct sockaddr_ll *sll = NULL;
708  int sll_allocated = 0;
709  char *dup = NULL;
710  char *colon = NULL;
711 
712  if (getifaddrs(&ifaddrs) == -1)
713  log_fatal("Failed to get interfaces");
714 
715  if ((sll = get_ll(ifaddrs, &ifa, name)) == NULL) {
716  /*
717  * We were unable to get link-layer address for name.
718  * Fall back to ioctl(SIOCGIFHWADDR).
719  */
720  sll = ioctl_get_ll(name);
721  if (sll != NULL)
722  sll_allocated = 1;
723  else
724  // shouldn't happen
725  log_fatal("Unexpected internal error");
726  }
727 
728  switch (sll->sll_hatype) {
729  case ARPHRD_ETHER:
730  hw->hlen = 7;
731  hw->hbuf[0] = HTYPE_ETHER;
732  memcpy(&hw->hbuf[1], sll->sll_addr, 6);
733  break;
734  case ARPHRD_IEEE802:
735 #ifdef ARPHRD_IEEE802_TR
736  case ARPHRD_IEEE802_TR:
737 #endif /* ARPHRD_IEEE802_TR */
738  hw->hlen = 7;
739  hw->hbuf[0] = HTYPE_IEEE802;
740  memcpy(&hw->hbuf[1], sll->sll_addr, 6);
741  break;
742  case ARPHRD_FDDI:
743  hw->hlen = 7;
744  hw->hbuf[0] = HTYPE_FDDI;
745  memcpy(&hw->hbuf[1], sll->sll_addr, 6);
746  break;
747  case ARPHRD_INFINIBAND:
748  dup = strdup(name);
749  /* Aliased infiniband interface is special case where
750  * neither get_ll() nor ioctl_get_ll() get's correct hw
751  * address, so we have to truncate the :0 and run
752  * get_ll() again for the rest.
753  */
754  if ((colon = strchr(dup, ':')) != NULL) {
755  *colon = '\0';
756  if ((sll = get_ll(ifaddrs, &ifa, dup)) == NULL)
757  log_fatal("Error getting hardware address for \"%s\": %m", name);
758  }
759  free (dup);
760  /* For Infiniband, save the broadcast address and store
761  * the port GUID into the hardware address.
762  */
763  if (ifa && (ifa->ifa_flags & IFF_BROADCAST)) {
764  struct sockaddr_ll *bll;
765 
766  bll = (struct sockaddr_ll *)ifa->ifa_broadaddr;
767  memcpy(&info->bcast_addr, bll->sll_addr, 20);
768  } else {
769  memcpy(&info->bcast_addr, default_ib_bcast_addr,
770  20);
771  }
772 
773  hw->hlen = HARDWARE_ADDR_LEN_IOCTL + 1;
774  hw->hbuf[0] = HTYPE_INFINIBAND;
775  memcpy(&hw->hbuf[1],
776  &sll->sll_addr[sll->sll_halen - HARDWARE_ADDR_LEN_IOCTL],
778  break;
779 #if defined(ARPHRD_PPP)
780  case ARPHRD_PPP:
781  if (local_family != AF_INET6)
782  log_fatal("local_family != AF_INET6 for \"%s\"",
783  name);
784  hw->hlen = 0;
785  hw->hbuf[0] = HTYPE_RESERVED;
786  /* 0xdeadbeef should never occur on the wire,
787  * and is a signature that something went wrong.
788  */
789  hw->hbuf[1] = 0xde;
790  hw->hbuf[2] = 0xad;
791  hw->hbuf[3] = 0xbe;
792  hw->hbuf[4] = 0xef;
793  break;
794 #endif
795  default:
796  freeifaddrs(ifaddrs);
797  log_fatal("Unsupported device type %hu for \"%s\"",
798  sll->sll_hatype, name);
799  }
800 
801  if (sll_allocated)
802  dfree(sll, MDL);
803  freeifaddrs(ifaddrs);
804 }
805 #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:489
int if_readsocket(omapi_object_t *h)
Definition: discover.c:996
char name[IFNAMSIZ]
Definition: dhcpd.h:1375
void if_reinitialize_send(struct interface_info *)
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:1007
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:92
Definition: dhcpd.h:405
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:1354
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:145
struct hardware hw_address
Definition: dhcpd.h:1353
#define HARDWARE_ADDR_LEN_IOCTL
Definition: dhcpd.h:486
int int log_info(const char *,...) __attribute__((__format__(__printf__
void * dmalloc(size_t, const char *, int)
Definition: alloc.c:57
int local_family
Definition: discover.c:55
int quiet_interface_discovery
Definition: discover.c:44
#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:490
struct hardware anycast_mac_addr
Definition: dhcpd.h:1404
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 *)