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