ISC DHCP  4.3.3
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  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  /* Discard packets with stripped vlan id */
555 
556 #ifdef VLAN_TCI_PRESENT
557  /* VLAN ID is only bottom 12-bits of TCI */
558  if (aux->tp_vlan_tci & 0x0fff)
559  return 0;
560 #endif
561 
562  csum_ready = ((aux->tp_status & TP_STATUS_CSUMNOTREADY)
563  ? 0 : 1);
564  }
565  }
566 
567  }
568 #endif /* PACKET_AUXDATA */
569 
570  bufix = 0;
571  /* Decode the physical header... */
572  offset = decode_hw_header (interface, ibuf, bufix, hfrom);
573 
574  /* If a physical layer checksum failed (dunno of any
575  physical layer that supports this, but WTH), skip this
576  packet. */
577  if (offset < 0) {
578  return 0;
579  }
580 
581  bufix += offset;
582  length -= offset;
583 
584  /* Decode the IP and UDP headers... */
585  offset = decode_udp_ip_header (interface, ibuf, bufix, from,
586  (unsigned)length, &paylen, csum_ready);
587 
588  /* If the IP or UDP checksum was bad, skip the packet... */
589  if (offset < 0)
590  return 0;
591 
592  bufix += offset;
593  length -= offset;
594 
595  if (length < paylen)
596  log_fatal("Internal inconsistency at %s:%d.", MDL);
597 
598  /* Copy out the data in the packet... */
599  memcpy(buf, &ibuf[bufix], paylen);
600  return paylen;
601 }
602 
604  struct interface_info *ip;
605 {
606  return 1;
607 }
608 
610  struct interface_info *ip;
611 {
612  return 1;
613 }
614 
616  struct interface_info *ip;
617 {
618  return 1;
619 }
620 
621 void maybe_setup_fallback ()
622 {
623  isc_result_t status;
624  struct interface_info *fbi = (struct interface_info *)0;
625  if (setup_fallback (&fbi, MDL)) {
626  if_register_fallback (fbi);
627  status = omapi_register_io_object ((omapi_object_t *)fbi,
628  if_readsocket, 0,
629  fallback_discard, 0, 0);
630  if (status != ISC_R_SUCCESS)
631  log_fatal ("Can't register I/O handle for \"%s\": %s",
632  fbi -> name, isc_result_totext (status));
633  interface_dereference (&fbi, MDL);
634  }
635 }
636 #endif
637 
638 #if defined (USE_LPF_RECEIVE) || defined (USE_LPF_HWADDR)
639 struct sockaddr_ll *
640 get_ll (struct ifaddrs *ifaddrs, struct ifaddrs **ifa, char *name)
641 {
642  for (*ifa = ifaddrs; *ifa != NULL; *ifa = (*ifa)->ifa_next) {
643  if ((*ifa)->ifa_addr == NULL)
644  continue;
645 
646  if ((*ifa)->ifa_addr->sa_family != AF_PACKET)
647  continue;
648 
649  if ((*ifa)->ifa_flags & IFF_LOOPBACK)
650  continue;
651 
652  if (strcmp((*ifa)->ifa_name, name) == 0)
653  return (struct sockaddr_ll *)(void *)(*ifa)->ifa_addr;
654  }
655  *ifa = NULL;
656  return NULL;
657 }
658 
659 struct sockaddr_ll *
660 ioctl_get_ll(char *name)
661 {
662  int sock;
663  struct ifreq tmp;
664  struct sockaddr *sa = NULL;
665  struct sockaddr_ll *sll = NULL;
666 
667  if (strlen(name) >= sizeof(tmp.ifr_name)) {
668  log_fatal("Device name too long: \"%s\"", name);
669  }
670 
671  sock = socket(AF_INET, SOCK_DGRAM, 0);
672  if (sock < 0) {
673  log_fatal("Can't create socket for \"%s\": %m", name);
674  }
675 
676  memset(&tmp, 0, sizeof(tmp));
677  strcpy(tmp.ifr_name, name);
678  if (ioctl(sock, SIOCGIFHWADDR, &tmp) < 0) {
679  log_fatal("Error getting hardware address for \"%s\": %m",
680  name);
681  }
682  close(sock);
683 
684  sa = &tmp.ifr_hwaddr;
685  // needs to be freed outside this function
686  sll = dmalloc (sizeof (struct sockaddr_ll), MDL);
687  if (!sll)
688  log_fatal("Unable to allocate memory for link layer address");
689  memcpy(&sll->sll_hatype, &sa->sa_family, sizeof (sll->sll_hatype));
690  memcpy(sll->sll_addr, sa->sa_data, sizeof (sll->sll_addr));
691  switch (sll->sll_hatype) {
692  case ARPHRD_INFINIBAND:
693  sll->sll_halen = HARDWARE_ADDR_LEN_IOCTL;
694  break;
695  default:
696  break;
697  }
698  return sll;
699 }
700 
701 void
702 get_hw_addr(struct interface_info *info)
703 {
704  struct hardware *hw = &info->hw_address;
705  char *name = info->name;
706  struct ifaddrs *ifaddrs = NULL;
707  struct ifaddrs *ifa = NULL;
708  struct sockaddr_ll *sll = NULL;
709  int sll_allocated = 0;
710  char *dup = NULL;
711  char *colon = NULL;
712 
713  if (getifaddrs(&ifaddrs) == -1)
714  log_fatal("Failed to get interfaces");
715 
716  if ((sll = get_ll(ifaddrs, &ifa, name)) == NULL) {
717  /*
718  * We were unable to get link-layer address for name.
719  * Fall back to ioctl(SIOCGIFHWADDR).
720  */
721  sll = ioctl_get_ll(name);
722  if (sll != NULL)
723  sll_allocated = 1;
724  else
725  // shouldn't happen
726  log_fatal("Unexpected internal error");
727  }
728 
729  switch (sll->sll_hatype) {
730  case ARPHRD_ETHER:
731  hw->hlen = 7;
732  hw->hbuf[0] = HTYPE_ETHER;
733  memcpy(&hw->hbuf[1], sll->sll_addr, 6);
734  break;
735  case ARPHRD_IEEE802:
736 #ifdef ARPHRD_IEEE802_TR
737  case ARPHRD_IEEE802_TR:
738 #endif /* ARPHRD_IEEE802_TR */
739  hw->hlen = 7;
740  hw->hbuf[0] = HTYPE_IEEE802;
741  memcpy(&hw->hbuf[1], sll->sll_addr, 6);
742  break;
743  case ARPHRD_FDDI:
744  hw->hlen = 7;
745  hw->hbuf[0] = HTYPE_FDDI;
746  memcpy(&hw->hbuf[1], sll->sll_addr, 6);
747  break;
748  case ARPHRD_INFINIBAND:
749  dup = strdup(name);
750  /* Aliased infiniband interface is special case where
751  * neither get_ll() nor ioctl_get_ll() get's correct hw
752  * address, so we have to truncate the :0 and run
753  * get_ll() again for the rest.
754  */
755  if ((colon = strchr(dup, ':')) != NULL) {
756  *colon = '\0';
757  if ((sll = get_ll(ifaddrs, &ifa, dup)) == NULL)
758  log_fatal("Error getting hardware address for \"%s\": %m", name);
759  }
760  free (dup);
761  /* For Infiniband, save the broadcast address and store
762  * the port GUID into the hardware address.
763  */
764  if (ifa && (ifa->ifa_flags & IFF_BROADCAST)) {
765  struct sockaddr_ll *bll;
766 
767  bll = (struct sockaddr_ll *)ifa->ifa_broadaddr;
768  memcpy(&info->bcast_addr, bll->sll_addr, 20);
769  } else {
770  memcpy(&info->bcast_addr, default_ib_bcast_addr,
771  20);
772  }
773 
774  hw->hlen = HARDWARE_ADDR_LEN_IOCTL + 1;
775  hw->hbuf[0] = HTYPE_INFINIBAND;
776  memcpy(&hw->hbuf[1],
777  &sll->sll_addr[sll->sll_halen - HARDWARE_ADDR_LEN_IOCTL],
779  break;
780 #if defined(ARPHRD_PPP)
781  case ARPHRD_PPP:
782  if (local_family != AF_INET6)
783  log_fatal("local_family != AF_INET6 for \"%s\"",
784  name);
785  hw->hlen = 0;
786  hw->hbuf[0] = HTYPE_RESERVED;
787  /* 0xdeadbeef should never occur on the wire,
788  * and is a signature that something went wrong.
789  */
790  hw->hbuf[1] = 0xde;
791  hw->hbuf[2] = 0xad;
792  hw->hbuf[3] = 0xbe;
793  hw->hbuf[4] = 0xef;
794  break;
795 #endif
796  default:
797  freeifaddrs(ifaddrs);
798  log_fatal("Unsupported device type %hu for \"%s\"",
799  sll->sll_hatype, name);
800  }
801 
802  if (sll_allocated)
803  dfree(sll, MDL);
804  freeifaddrs(ifaddrs);
805 }
806 #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:483
int if_readsocket(omapi_object_t *h)
Definition: discover.c:964
char name[IFNAMSIZ]
Definition: dhcpd.h:1351
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: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:1330
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:1329
#define HARDWARE_ADDR_LEN_IOCTL
Definition: dhcpd.h:480
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:484
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 *)