ISC DHCP  4.4.2b1
A reference DHCPv4 and DHCPv6 implementation
bpf.c
Go to the documentation of this file.
1 /* bpf.c
2 
3  BPF socket interface code, originally contributed by Archie Cobbs. */
4 
5 /*
6  * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
7  * Copyright (c) 1996-2003 by Internet Software Consortium
8  *
9  * This Source Code Form is subject to the terms of the Mozilla Public
10  * License, v. 2.0. If a copy of the MPL was not distributed with this
11  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  *
21  * Internet Systems Consortium, Inc.
22  * 950 Charter Street
23  * Redwood City, CA 94063
24  * <info@isc.org>
25  * https://www.isc.org/
26  *
27  * This software was contributed to Internet Systems Consortium
28  * by Archie Cobbs.
29  *
30  * Patches for FDDI support on Digital Unix were written by Bill
31  * Stapleton, and maintained for a while by Mike Meredith before he
32  * managed to get me to integrate them.
33  */
34 
35 #include "dhcpd.h"
36 #if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE) \
37  || defined (USE_LPF_RECEIVE)
38 # if defined (USE_LPF_RECEIVE)
39 # include <asm/types.h>
40 # include <linux/filter.h>
41 # define bpf_insn sock_filter /* Linux: dare to be gratuitously different. */
42 # else
43 # include <sys/ioctl.h>
44 # include <sys/uio.h>
45 # include <net/bpf.h>
46 # if defined (NEED_OSF_PFILT_HACKS)
47 # include <net/pfilt.h>
48 # endif
49 # endif
50 
51 #include <netinet/in_systm.h>
52 #include "includes/netinet/ip.h"
53 #include "includes/netinet/udp.h"
55 #endif
56 
57 #if defined(USE_BPF_SEND) || defined(USE_BPF_RECEIVE) || defined(USE_BPF_HWADDR)
58 #include <net/if_types.h>
59 #include <ifaddrs.h>
60 #endif
61 
62 #include <errno.h>
63 
64 /* Reinitializes the specified interface after an address change. This
65  is not required for packet-filter APIs. */
66 
67 #ifdef USE_BPF_SEND
68 void if_reinitialize_send (info)
69  struct interface_info *info;
70 {
71 }
72 #endif
73 
74 #ifdef USE_BPF_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 #if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE)
86 int if_register_bpf (info)
87  struct interface_info *info;
88 {
89  int sock;
90  char filename[50];
91  int b;
92 
93  /* Open a BPF device */
94  for (b = 0; 1; b++) {
95  /* %Audit% 31 bytes max. %2004.06.17,Safe% */
96  sprintf(filename, BPF_FORMAT, b);
97  sock = open (filename, O_RDWR | O_CLOEXEC, 0);
98  if (sock < 0) {
99  if (errno == EBUSY) {
100  continue;
101  } else {
102  if (!b)
103  log_fatal ("No bpf devices.%s%s%s",
104  " Please read the README",
105  " section for your operating",
106  " system.");
107  log_fatal ("Can't find free bpf: %m");
108  }
109  } else {
110  break;
111  }
112  }
113 
114  /* Set the BPF device to point at this interface. */
115  if (ioctl (sock, BIOCSETIF, info -> ifp) < 0)
116  log_fatal ("Can't attach interface %s to bpf device %s: %m",
117  info -> name, filename);
118 
119  get_hw_addr(info->name, &info->hw_address);
120 
121  return sock;
122 }
123 #endif /* USE_BPF_SEND || USE_BPF_RECEIVE */
124 
125 #ifdef USE_BPF_SEND
126 void if_register_send (info)
127  struct interface_info *info;
128 {
129  /* If we're using the bpf API for sending and receiving,
130  we don't need to register this interface twice. */
131 #ifndef USE_BPF_RECEIVE
132  info -> wfdesc = if_register_bpf (info, interface);
133 #else
134  info -> wfdesc = info -> rfdesc;
135 #endif
137  log_info ("Sending on BPF/%s/%s%s%s",
138  info -> name,
139  print_hw_addr (info -> hw_address.hbuf [0],
140  info -> hw_address.hlen - 1,
141  &info -> hw_address.hbuf [1]),
142  (info -> shared_network ? "/" : ""),
143  (info -> shared_network ?
144  info -> shared_network -> name : ""));
145 }
146 
147 void if_deregister_send (info)
148  struct interface_info *info;
149 {
150  /* If we're using the bpf API for sending and receiving,
151  we don't need to register this interface twice. */
152 #ifndef USE_BPF_RECEIVE
153  close (info -> wfdesc);
154 #endif
155  info -> wfdesc = -1;
156 
158  log_info ("Disabling output on BPF/%s/%s%s%s",
159  info -> name,
160  print_hw_addr (info -> hw_address.hbuf [0],
161  info -> hw_address.hlen - 1,
162  &info -> hw_address.hbuf [1]),
163  (info -> shared_network ? "/" : ""),
164  (info -> shared_network ?
165  info -> shared_network -> name : ""));
166 }
167 #endif /* USE_BPF_SEND */
168 
169 #if defined (USE_BPF_RECEIVE) || defined (USE_LPF_RECEIVE)
170 /* Packet filter program...
171  XXX Changes to the filter program may require changes to the constant
172  offsets used in if_register_send to patch the BPF program! XXX */
173 
174 struct bpf_insn dhcp_bpf_filter [] = {
175  /* Make sure this is an IP packet... */
176  BPF_STMT (BPF_LD + BPF_H + BPF_ABS, 12),
177  BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8),
178 
179  /* Make sure it's a UDP packet... */
180  BPF_STMT (BPF_LD + BPF_B + BPF_ABS, 23),
181  BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
182 
183  /* Make sure this isn't a fragment... */
184  BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20),
185  BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
186 
187  /* Get the IP header length... */
188  BPF_STMT (BPF_LDX + BPF_B + BPF_MSH, 14),
189 
190  /* Make sure it's to the right port... */
191  BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16),
192  BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1), /* patch */
193 
194  /* If we passed all the tests, ask for the whole packet. */
195  BPF_STMT (BPF_RET + BPF_K, (u_int)-1),
196 
197  /* Otherwise, drop it. */
198  BPF_STMT (BPF_RET + BPF_K, 0),
199 };
200 
201 #if defined(RELAY_PORT)
202 /*
203  * For relay port extension
204  */
205 struct bpf_insn dhcp_bpf_relay_filter [] = {
206  /* Make sure this is an IP packet... */
207  BPF_STMT (BPF_LD + BPF_H + BPF_ABS, 12),
208  BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 10),
209 
210  /* Make sure it's a UDP packet... */
211  BPF_STMT (BPF_LD + BPF_B + BPF_ABS, 23),
212  BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 8),
213 
214  /* Make sure this isn't a fragment... */
215  BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20),
216  BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 6, 0),
217 
218  /* Get the IP header length... */
219  BPF_STMT (BPF_LDX + BPF_B + BPF_MSH, 14),
220 
221  /* Make sure it's to the right port... */
222  BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16),
223  BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 2, 0), /* patch */
224 
225  /* relay can have an alternative port... */
226  BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16),
227  BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1), /* patch */
228 
229  /* If we passed all the tests, ask for the whole packet. */
230  BPF_STMT (BPF_RET + BPF_K, (u_int)-1),
231 
232  /* Otherwise, drop it. */
233  BPF_STMT (BPF_RET + BPF_K, 0),
234 };
235 
236 int dhcp_bpf_relay_filter_len =
237  sizeof dhcp_bpf_relay_filter / sizeof (struct bpf_insn);
238 #endif
239 
240 /* Packet filter program for DHCP over Infiniband.
241  *
242  * XXX
243  * Changes to the filter program may require changes to the constant offsets
244  * used in lpf_gen_filter_setup to patch the port in the BPF program!
245  * XXX
246  */
247 struct bpf_insn dhcp_ib_bpf_filter [] = {
248  /* Packet filter for Infiniband */
249  /* Make sure it's a UDP packet... */
250  BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 9),
251  BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
252 
253  /* Make sure this isn't a fragment... */
254  BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 6),
255  BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
256 
257  /* Get the IP header length... */
258  BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 0),
259 
260  /* Make sure it's to the right port... */
261  BPF_STMT(BPF_LD + BPF_H + BPF_IND, 2),
262  BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1),
263 
264  /* If we passed all the tests, ask for the whole packet. */
265  BPF_STMT(BPF_RET + BPF_K, (u_int)-1),
266 
267  /* Otherwise, drop it. */
268  BPF_STMT(BPF_RET + BPF_K, 0),
269 };
270 
271 #if defined (DEC_FDDI)
272 struct bpf_insn *bpf_fddi_filter = NULL;
273 #endif
274 
275 int dhcp_bpf_filter_len = sizeof dhcp_bpf_filter / sizeof (struct bpf_insn);
276 int dhcp_ib_bpf_filter_len = sizeof dhcp_ib_bpf_filter / sizeof (struct bpf_insn);
277 #if defined (HAVE_TR_SUPPORT)
278 struct bpf_insn dhcp_bpf_tr_filter [] = {
279  /* accept all token ring packets due to variable length header */
280  /* if we want to get clever, insert the program here */
281 
282  /* If we passed all the tests, ask for the whole packet. */
283  BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
284 
285  /* Otherwise, drop it. */
286  BPF_STMT(BPF_RET+BPF_K, 0),
287 };
288 
289 int dhcp_bpf_tr_filter_len = (sizeof dhcp_bpf_tr_filter /
290  sizeof (struct bpf_insn));
291 #endif /* HAVE_TR_SUPPORT */
292 #endif /* USE_LPF_RECEIVE || USE_BPF_RECEIVE */
293 
294 #if defined (USE_BPF_RECEIVE)
295 void if_register_receive (info)
296  struct interface_info *info;
297 {
298  int flag = 1;
299  struct bpf_version v;
300  struct bpf_program p;
301 #ifdef NEED_OSF_PFILT_HACKS
302  u_int32_t bits;
303 #endif
304 #ifdef DEC_FDDI
305  int link_layer;
306 #endif /* DEC_FDDI */
307 
308  /* Open a BPF device and hang it on this interface... */
309  info -> rfdesc = if_register_bpf (info);
310 
311  /* Make sure the BPF version is in range... */
312  if (ioctl (info -> rfdesc, BIOCVERSION, &v) < 0)
313  log_fatal ("Can't get BPF version: %m");
314 
315  if (v.bv_major != BPF_MAJOR_VERSION ||
316  v.bv_minor < BPF_MINOR_VERSION)
317  log_fatal ("BPF version mismatch - recompile DHCP!");
318 
319  /* Set immediate mode so that reads return as soon as a packet
320  comes in, rather than waiting for the input buffer to fill with
321  packets. */
322  if (ioctl (info -> rfdesc, BIOCIMMEDIATE, &flag) < 0)
323  log_fatal ("Can't set immediate mode on bpf device: %m");
324 
325 #ifdef NEED_OSF_PFILT_HACKS
326  /* Allow the copyall flag to be set... */
327  if (ioctl(info -> rfdesc, EIOCALLOWCOPYALL, &flag) < 0)
328  log_fatal ("Can't set ALLOWCOPYALL: %m");
329 
330  /* Clear all the packet filter mode bits first... */
331  bits = 0;
332  if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0)
333  log_fatal ("Can't clear pfilt bits: %m");
334 
335  /* Set the ENBATCH, ENCOPYALL, ENBPFHDR bits... */
336  bits = ENBATCH | ENCOPYALL | ENBPFHDR;
337  if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0)
338  log_fatal ("Can't set ENBATCH|ENCOPYALL|ENBPFHDR: %m");
339 #endif
340  /* Get the required BPF buffer length from the kernel. */
341  if (ioctl (info -> rfdesc, BIOCGBLEN, &info -> rbuf_max) < 0)
342  log_fatal ("Can't get bpf buffer length: %m");
343  info -> rbuf = dmalloc (info -> rbuf_max, MDL);
344  if (!info -> rbuf)
345  log_fatal ("Can't allocate %ld bytes for bpf input buffer.",
346  (long)(info -> rbuf_max));
347  info -> rbuf_offset = 0;
348  info -> rbuf_len = 0;
349 
350  /* Set up the bpf filter program structure. */
351  p.bf_len = dhcp_bpf_filter_len;
352 
353 #ifdef DEC_FDDI
354  /* See if this is an FDDI interface, flag it for later. */
355  if (ioctl(info -> rfdesc, BIOCGDLT, &link_layer) >= 0 &&
356  link_layer == DLT_FDDI) {
357  if (!bpf_fddi_filter) {
358  bpf_fddi_filter = dmalloc (sizeof dhcp_bpf_filter,
359  MDL);
360  if (!bpf_fddi_filter)
361  log_fatal ("No memory for FDDI filter.");
362  memcpy (bpf_fddi_filter,
363  dhcp_bpf_filter, sizeof dhcp_bpf_filter);
364  /* Patch the BPF program to account for the difference
365  in length between ethernet headers (14), FDDI and
366  802.2 headers (16 +8=24, +10).
367  XXX changes to filter program may require changes to
368  XXX the insn number(s) used below! */
369  bpf_fddi_filter[0].k += 10;
370  bpf_fddi_filter[2].k += 10;
371  bpf_fddi_filter[4].k += 10;
372  bpf_fddi_filter[6].k += 10;
373  bpf_fddi_filter[7].k += 10;
374  }
375  p.bf_insns = bpf_fddi_filter;
376  } else
377 #endif /* DEC_FDDI */
378  p.bf_insns = dhcp_bpf_filter;
379 
380  /* Patch the server port into the BPF program...
381  XXX changes to filter program may require changes
382  to the insn number(s) used below! XXX */
383 #if defined(RELAY_PORT)
384  if (relay_port) {
385  /*
386  * If user defined relay UDP port, we need to filter
387  * also on the user UDP port.
388  */
389  p.bf_len = dhcp_bpf_relay_filter_len;
390  p.bf_insns = dhcp_bpf_relay_filter;
391 
392  dhcp_bpf_relay_filter [10].k = ntohs (relay_port);
393  }
394 #endif
395  p.bf_insns [8].k = ntohs (local_port);
396 
397  if (ioctl (info -> rfdesc, BIOCSETF, &p) < 0)
398  log_fatal ("Can't install packet filter program: %m");
400  log_info ("Listening on BPF/%s/%s%s%s",
401  info -> name,
402  print_hw_addr (info -> hw_address.hbuf [0],
403  info -> hw_address.hlen - 1,
404  &info -> hw_address.hbuf [1]),
405  (info -> shared_network ? "/" : ""),
406  (info -> shared_network ?
407  info -> shared_network -> name : ""));
408 }
409 
410 void if_deregister_receive (info)
411  struct interface_info *info;
412 {
413  close (info -> rfdesc);
414  info -> rfdesc = -1;
415 
417  log_info ("Disabling input on BPF/%s/%s%s%s",
418  info -> name,
419  print_hw_addr (info -> hw_address.hbuf [0],
420  info -> hw_address.hlen - 1,
421  &info -> hw_address.hbuf [1]),
422  (info -> shared_network ? "/" : ""),
423  (info -> shared_network ?
424  info -> shared_network -> name : ""));
425 }
426 #endif /* USE_BPF_RECEIVE */
427 
428 #ifdef USE_BPF_SEND
429 ssize_t send_packet (interface, packet, raw, len, from, to, hto)
430  struct interface_info *interface;
431  struct packet *packet;
432  struct dhcp_packet *raw;
433  size_t len;
434  struct in_addr from;
435  struct sockaddr_in *to;
436  struct hardware *hto;
437 {
438  unsigned hbufp = 0, ibufp = 0;
439  double hw [4];
440  double ip [32];
441  struct iovec iov [3];
442  int result;
443 
444  if (!strcmp (interface -> name, "fallback"))
445  return send_fallback (interface, packet, raw,
446  len, from, to, hto);
447 
448  if (hto == NULL && interface->anycast_mac_addr.hlen)
449  hto = &interface->anycast_mac_addr;
450 
451  /* Assemble the headers... */
452  assemble_hw_header (interface, (unsigned char *)hw, &hbufp, hto);
453  assemble_udp_ip_header (interface,
454  (unsigned char *)ip, &ibufp, from.s_addr,
455  to -> sin_addr.s_addr, to -> sin_port,
456  (unsigned char *)raw, len);
457 
458  /* Fire it off */
459  iov [0].iov_base = ((char *)hw);
460  iov [0].iov_len = hbufp;
461  iov [1].iov_base = ((char *)ip);
462  iov [1].iov_len = ibufp;
463  iov [2].iov_base = (char *)raw;
464  iov [2].iov_len = len;
465 
466  result = writev(interface -> wfdesc, iov, 3);
467  if (result < 0)
468  log_error ("send_packet: %m");
469  return result;
470 }
471 #endif /* USE_BPF_SEND */
472 
473 #ifdef USE_BPF_RECEIVE
474 ssize_t receive_packet (interface, buf, len, from, hfrom)
475  struct interface_info *interface;
476  unsigned char *buf;
477  size_t len;
478  struct sockaddr_in *from;
479  struct hardware *hfrom;
480 {
481  int length = 0;
482  int offset = 0;
483  struct bpf_hdr hdr;
484  unsigned paylen;
485 
486  /* All this complexity is because BPF doesn't guarantee
487  that only one packet will be returned at a time. We're
488  getting what we deserve, though - this is a terrible abuse
489  of the BPF interface. Sigh. */
490 
491  /* Process packets until we get one we can return or until we've
492  done a read and gotten nothing we can return... */
493 
494  /* If the buffer is empty, fill it. */
495  if (interface->rbuf_offset >= interface->rbuf_len) {
496  length = read(interface->rfdesc, interface->rbuf,
497  (size_t)interface->rbuf_max);
498  if (length <= 0) {
499 #ifdef __FreeBSD__
500  if (errno == ENXIO) {
501 #else
502  if (errno == EIO) {
503 #endif
505  ((omapi_object_t *)interface, NULL);
506  }
507  return (length);
508  }
509  interface->rbuf_offset = 0;
510  interface->rbuf_len = BPF_WORDALIGN(length);
511  }
512 
513  do {
514  /* If there isn't room for a whole bpf header, something went
515  wrong, but we'll ignore it and hope it goes away... XXX */
516  if (interface->rbuf_len -
517  interface->rbuf_offset < sizeof hdr) {
518  interface->rbuf_offset = interface->rbuf_len;
519  continue;
520  }
521 
522  /* Copy out a bpf header... */
523  memcpy(&hdr, &interface->rbuf[interface->rbuf_offset],
524  sizeof hdr);
525 
526  /* If the bpf header plus data doesn't fit in what's left
527  of the buffer, stick head in sand yet again... */
528  if (interface->rbuf_offset +
529  hdr.bh_hdrlen + hdr.bh_caplen > interface->rbuf_len) {
530  interface->rbuf_offset = interface->rbuf_len;
531  continue;
532  }
533 
534  /* If the captured data wasn't the whole packet, or if
535  the packet won't fit in the input buffer, all we
536  can do is drop it. */
537  if (hdr.bh_caplen != hdr.bh_datalen) {
538  interface->rbuf_offset =
539  BPF_WORDALIGN(interface->rbuf_offset +
540  hdr.bh_hdrlen + hdr.bh_caplen);
541  continue;
542  }
543 
544  /* Skip over the BPF header... */
545  interface->rbuf_offset += hdr.bh_hdrlen;
546 
547  /* Decode the physical header... */
548  offset = decode_hw_header(interface, interface->rbuf,
549  interface->rbuf_offset, hfrom);
550 
551  /* If a physical layer checksum failed (dunno of any
552  physical layer that supports this, but WTH), skip this
553  packet. */
554  if (offset < 0) {
555  interface->rbuf_offset =
556  BPF_WORDALIGN(interface->rbuf_offset +
557  hdr.bh_caplen);
558  continue;
559  }
560  interface->rbuf_offset += offset;
561  hdr.bh_caplen -= offset;
562 
563  /* Decode the IP and UDP headers... */
564  offset = decode_udp_ip_header(interface, interface->rbuf,
565  interface->rbuf_offset,
566  from, hdr.bh_caplen, &paylen, 1);
567 
568  /* If the IP or UDP checksum was bad, skip the packet... */
569  if (offset < 0) {
570  interface->rbuf_offset =
571  BPF_WORDALIGN(interface->rbuf_offset +
572  hdr.bh_caplen);
573  continue;
574  }
575  interface->rbuf_offset = interface->rbuf_offset + offset;
576  hdr.bh_caplen -= offset;
577 
578  /* If there's not enough room to stash the packet data,
579  we have to skip it (this shouldn't happen in real
580  life, though). */
581  if (hdr.bh_caplen > len) {
582  interface->rbuf_offset =
583  BPF_WORDALIGN(interface->rbuf_offset +
584  hdr.bh_caplen);
585  continue;
586  }
587 
588  /* Copy out the data in the packet... */
589  memcpy(buf, interface->rbuf + interface->rbuf_offset, paylen);
590  interface->rbuf_offset =
591  BPF_WORDALIGN(interface->rbuf_offset + hdr.bh_caplen);
592  return paylen;
593  } while (interface->rbuf_offset < interface->rbuf_len);
594 
595  return (0);
596 }
597 
599  struct interface_info *ip;
600 {
601  return 1;
602 }
603 
605  struct interface_info *ip;
606 {
607  return 1;
608 }
609 
611  struct interface_info *ip;
612 {
613  return 1;
614 }
615 
616 void maybe_setup_fallback ()
617 {
618  isc_result_t status;
619  struct interface_info *fbi = (struct interface_info *)0;
620  if (setup_fallback (&fbi, MDL)) {
621  if_register_fallback (fbi);
622  status = omapi_register_io_object ((omapi_object_t *)fbi,
623  if_readsocket, 0,
624  fallback_discard, 0, 0);
625  if (status != ISC_R_SUCCESS)
626  log_fatal ("Can't register I/O handle for %s: %s",
627  fbi -> name, isc_result_totext (status));
628  interface_dereference (&fbi, MDL);
629  }
630 }
631 #endif
632 
633 #if defined(USE_BPF_RECEIVE) || defined(USE_BPF_HWADDR)
634 void
635 get_hw_addr(const char *name, struct hardware *hw) {
636  struct ifaddrs *ifa;
637  struct ifaddrs *p;
638  struct sockaddr_dl *sa;
639 
640  if (getifaddrs(&ifa) != 0) {
641  log_fatal("Error getting interface information; %m");
642  }
643 
644  /*
645  * Loop through our interfaces finding a match.
646  */
647  sa = NULL;
648  for (p=ifa; (p != NULL) && (sa == NULL); p = p->ifa_next) {
649  if ((p->ifa_addr->sa_family == AF_LINK) &&
650  !strcmp(p->ifa_name, name)) {
651  sa = (struct sockaddr_dl *)p->ifa_addr;
652  }
653  }
654  if (sa == NULL) {
655  log_fatal("No interface called '%s'", name);
656  }
657 
658  /*
659  * Pull out the appropriate information.
660  */
661  switch (sa->sdl_type) {
662  case IFT_ETHER:
663 #if defined (IFT_L2VLAN)
664  case IFT_L2VLAN:
665 #endif
666  hw->hlen = sa->sdl_alen + 1;
667  hw->hbuf[0] = HTYPE_ETHER;
668  memcpy(&hw->hbuf[1], LLADDR(sa), sa->sdl_alen);
669  break;
670  case IFT_ISO88023:
671  case IFT_ISO88024: /* "token ring" */
672  case IFT_ISO88025:
673  case IFT_ISO88026:
674  hw->hlen = sa->sdl_alen + 1;
675  hw->hbuf[0] = HTYPE_IEEE802;
676  memcpy(&hw->hbuf[1], LLADDR(sa), sa->sdl_alen);
677  break;
678 #ifdef IFT_FDDI
679  case IFT_FDDI:
680  hw->hlen = sa->sdl_alen + 1;
681  hw->hbuf[0] = HTYPE_FDDI;
682  memcpy(&hw->hbuf[1], LLADDR(sa), sa->sdl_alen);
683  break;
684 #endif /* IFT_FDDI */
685 #if defined(IFT_PPP)
686  case IFT_PPP:
687  if (local_family != AF_INET6)
688  log_fatal("Unsupported device type %d for \"%s\"",
689  sa->sdl_type, name);
690  hw->hlen = 0;
691  hw->hbuf[0] = HTYPE_RESERVED;
692  /* 0xdeadbeef should never occur on the wire,
693  * and is a signature that something went wrong.
694  */
695  hw->hbuf[1] = 0xde;
696  hw->hbuf[2] = 0xad;
697  hw->hbuf[3] = 0xbe;
698  hw->hbuf[4] = 0xef;
699  break;
700 #endif
701  default:
702  log_fatal("Unsupported device type %d for \"%s\"",
703  sa->sdl_type, name);
704  }
705 
706  freeifaddrs(ifa);
707 }
708 #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::name
char name[IFNAMSIZ]
Definition: dhcpd.h:1403
log_fatal
void log_fatal(const char *,...) __attribute__((__format__(__printf__
interface_info::ifp
struct ifreq * ifp
Definition: dhcpd.h:1414
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
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
interface_info::rbuf_offset
size_t rbuf_offset
Definition: dhcpd.h:1411
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
interface_info::rbuf_len
size_t rbuf_len
Definition: dhcpd.h:1412
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 *)
local_family
int local_family
Definition: discover.c:56
MDL
#define MDL
Definition: omapip.h:567
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__
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)
dhcp_interface_remove
isc_result_t dhcp_interface_remove(omapi_object_t *lp, omapi_object_t *id)
Definition: discover.c:1466
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)
interface_info::rbuf_max
unsigned int rbuf_max
Definition: dhcpd.h:1410
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
BPF_FORMAT
#define BPF_FORMAT
Definition: osdep.h:207
interface_info::rbuf
unsigned char * rbuf
Definition: dhcpd.h:1409
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:81
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
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 *)