ISC DHCP 4.4.3-P1
A reference DHCPv4 and DHCPv6 implementation
 
Loading...
Searching...
No Matches
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-2022 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 * PO Box 360
23 * Newmarket, NH 03857 USA
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"
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
68void if_reinitialize_send (info)
69 struct interface_info *info;
70{
71}
72#endif
73
74#ifdef USE_BPF_RECEIVE
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)
86int 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
126void 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
147void 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
174struct 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 */
205struct 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
236int 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 */
247struct 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)
272struct bpf_insn *bpf_fddi_filter = NULL;
273#endif
274
275int dhcp_bpf_filter_len = sizeof dhcp_bpf_filter / sizeof (struct bpf_insn);
276int dhcp_ib_bpf_filter_len = sizeof dhcp_ib_bpf_filter / sizeof (struct bpf_insn);
277#if defined (HAVE_TR_SUPPORT)
278struct 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
289int 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)
295void 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
410void 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
429ssize_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
474ssize_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
617{
618 isc_result_t status;
619 struct interface_info *fbi = (struct interface_info *)0;
620 if (setup_fallback (&fbi, MDL)) {
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)
634void
635get_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
char * print_hw_addr(int htype, const int hlen, const unsigned char *data) const
Definition print.c:171
u_int16_t local_port
Definition discover.c:48
#define HTYPE_RESERVED
Definition dhcp.h:81
#define HTYPE_IEEE802
Definition dhcp.h:76
#define HTYPE_FDDI
Definition dhcp.h:77
#define HTYPE_ETHER
Definition dhcp.h:75
void if_reinitialize_receive(struct interface_info *)
void maybe_setup_fallback(void)
int supports_multiple_interfaces(struct interface_info *)
void if_deregister_send(struct interface_info *)
void assemble_hw_header(struct interface_info *, unsigned char *, unsigned *, struct hardware *)
ssize_t decode_udp_ip_header(struct interface_info *, unsigned char *, unsigned, struct sockaddr_in *, unsigned, unsigned *, int)
void if_reinitialize_send(struct interface_info *)
isc_result_t fallback_discard(omapi_object_t *)
ssize_t send_packet(struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)
void assemble_udp_ip_header(struct interface_info *, unsigned char *, unsigned *, u_int32_t, u_int32_t, u_int32_t, unsigned char *, unsigned)
int can_receive_unicast_unconfigured(struct interface_info *)
ssize_t receive_packet(struct interface_info *, unsigned char *, size_t, struct sockaddr_in *, struct hardware *)
void get_hw_addr(struct interface_info *info)
void if_register_receive(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 can_unicast_without_arp(struct interface_info *)
void if_deregister_receive(struct interface_info *)
void if_register_fallback(struct interface_info *)
ssize_t decode_hw_header(struct interface_info *, unsigned char *, unsigned, struct hardware *)
void if_register_send(struct interface_info *)
u_int16_t relay_port
Definition discover.c:50
int local_family
Definition discover.c:59
int setup_fallback(struct interface_info **fp, const char *file, int line)
Definition discover.c:1059
int quiet_interface_discovery
Definition discover.c:47
int if_readsocket(omapi_object_t *h)
Definition discover.c:1048
isc_result_t dhcp_interface_remove(omapi_object_t *lp, omapi_object_t *id)
Definition discover.c:1469
#define ETHERTYPE_IP
Definition if_ether.h:57
#define ISC_R_SUCCESS
#define MDL
Definition omapip.h:567
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
struct __omapi_object omapi_object_t
Definition omapip.h:39
void * dmalloc(size_t, const char *, int)
Definition alloc.c:57
int log_error(const char *,...) __attribute__((__format__(__printf__
void log_fatal(const char *,...) __attribute__((__format__(__printf__
int int log_info(const char *,...) __attribute__((__format__(__printf__
#define BPF_FORMAT
Definition osdep.h:207
u_int8_t hlen
Definition dhcpd.h:492
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
Definition dhcpd.h:493
char name[IFNAMSIZ]
Definition dhcpd.h:1408
size_t rbuf_len
Definition dhcpd.h:1417
struct hardware anycast_mac_addr
Definition dhcpd.h:1438
struct ifreq * ifp
Definition dhcpd.h:1419
struct hardware hw_address
Definition dhcpd.h:1386
unsigned int rbuf_max
Definition dhcpd.h:1415
unsigned char * rbuf
Definition dhcpd.h:1414
size_t rbuf_offset
Definition dhcpd.h:1416
Definition ip.h:47