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"
54 #include "includes/netinet/if_ether.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
if_reinitialize_send(info)68 void if_reinitialize_send (info)
69 	struct interface_info *info;
70 {
71 }
72 #endif
73 
74 #ifdef USE_BPF_RECEIVE
if_reinitialize_receive(info)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)
if_register_bpf(info)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, 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
if_register_send(info)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
136 	if (!quiet_interface_discovery)
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 
if_deregister_send(info)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 
157 	if (!quiet_interface_discovery)
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 #if defined (DEC_FDDI)
241 struct bpf_insn *bpf_fddi_filter = NULL;
242 #endif
243 
244 int dhcp_bpf_filter_len = sizeof dhcp_bpf_filter / sizeof (struct bpf_insn);
245 #if defined (HAVE_TR_SUPPORT)
246 struct bpf_insn dhcp_bpf_tr_filter [] = {
247         /* accept all token ring packets due to variable length header */
248         /* if we want to get clever, insert the program here */
249 
250 	/* If we passed all the tests, ask for the whole packet. */
251 	BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
252 
253 	/* Otherwise, drop it. */
254 	BPF_STMT(BPF_RET+BPF_K, 0),
255 };
256 
257 int dhcp_bpf_tr_filter_len = (sizeof dhcp_bpf_tr_filter /
258 			      sizeof (struct bpf_insn));
259 #endif /* HAVE_TR_SUPPORT */
260 #endif /* USE_LPF_RECEIVE || USE_BPF_RECEIVE */
261 
262 #if defined (USE_BPF_RECEIVE)
if_register_receive(info)263 void if_register_receive (info)
264 	struct interface_info *info;
265 {
266 	int flag = 1;
267 	struct bpf_version v;
268 	struct bpf_program p;
269 #ifdef NEED_OSF_PFILT_HACKS
270 	u_int32_t bits;
271 #endif
272 #ifdef DEC_FDDI
273 	int link_layer;
274 #endif /* DEC_FDDI */
275 
276 	/* Open a BPF device and hang it on this interface... */
277 	info -> rfdesc = if_register_bpf (info);
278 
279 	/* Make sure the BPF version is in range... */
280 	if (ioctl (info -> rfdesc, BIOCVERSION, &v) < 0)
281 		log_fatal ("Can't get BPF version: %m");
282 
283 	if (v.bv_major != BPF_MAJOR_VERSION ||
284 	    v.bv_minor < BPF_MINOR_VERSION)
285 		log_fatal ("BPF version mismatch - recompile DHCP!");
286 
287 	/* Set immediate mode so that reads return as soon as a packet
288 	   comes in, rather than waiting for the input buffer to fill with
289 	   packets. */
290 	if (ioctl (info -> rfdesc, BIOCIMMEDIATE, &flag) < 0)
291 		log_fatal ("Can't set immediate mode on bpf device: %m");
292 
293 #ifdef NEED_OSF_PFILT_HACKS
294 	/* Allow the copyall flag to be set... */
295 	if (ioctl(info -> rfdesc, EIOCALLOWCOPYALL, &flag) < 0)
296 		log_fatal ("Can't set ALLOWCOPYALL: %m");
297 
298 	/* Clear all the packet filter mode bits first... */
299 	bits = 0;
300 	if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0)
301 		log_fatal ("Can't clear pfilt bits: %m");
302 
303 	/* Set the ENBATCH, ENCOPYALL, ENBPFHDR bits... */
304 	bits = ENBATCH | ENCOPYALL | ENBPFHDR;
305 	if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0)
306 		log_fatal ("Can't set ENBATCH|ENCOPYALL|ENBPFHDR: %m");
307 #endif
308 	/* Get the required BPF buffer length from the kernel. */
309 	if (ioctl (info -> rfdesc, BIOCGBLEN, &info -> rbuf_max) < 0)
310 		log_fatal ("Can't get bpf buffer length: %m");
311 	info -> rbuf = dmalloc (info -> rbuf_max, MDL);
312 	if (!info -> rbuf)
313 		log_fatal ("Can't allocate %ld bytes for bpf input buffer.",
314 			   (long)(info -> rbuf_max));
315 	info -> rbuf_offset = 0;
316 	info -> rbuf_len = 0;
317 
318 	/* Set up the bpf filter program structure. */
319 	p.bf_len = dhcp_bpf_filter_len;
320 
321 #ifdef DEC_FDDI
322 	/* See if this is an FDDI interface, flag it for later. */
323 	if (ioctl(info -> rfdesc, BIOCGDLT, &link_layer) >= 0 &&
324 	    link_layer == DLT_FDDI) {
325 		if (!bpf_fddi_filter) {
326 			bpf_fddi_filter = dmalloc (sizeof dhcp_bpf_filter,
327 						    MDL);
328 			if (!bpf_fddi_filter)
329 				log_fatal ("No memory for FDDI filter.");
330 			memcpy (bpf_fddi_filter,
331 				dhcp_bpf_filter, sizeof dhcp_bpf_filter);
332 			/* Patch the BPF program to account for the difference
333 			   in length between ethernet headers (14), FDDI and
334 			   802.2 headers (16 +8=24, +10).
335 			   XXX changes to filter program may require changes to
336 			   XXX the insn number(s) used below! */
337 			bpf_fddi_filter[0].k += 10;
338 			bpf_fddi_filter[2].k += 10;
339 			bpf_fddi_filter[4].k += 10;
340 			bpf_fddi_filter[6].k += 10;
341 			bpf_fddi_filter[7].k += 10;
342 		}
343 		p.bf_insns = bpf_fddi_filter;
344 	} else
345 #endif /* DEC_FDDI */
346 	p.bf_insns = dhcp_bpf_filter;
347 
348         /* Patch the server port into the BPF  program...
349 	   XXX changes to filter program may require changes
350 	   to the insn number(s) used below! XXX */
351 #if defined(RELAY_PORT)
352 	if (relay_port) {
353 		/*
354 		 * If user defined relay UDP port, we need to filter
355 		 * also on the user UDP port.
356 		 */
357 		p.bf_len = dhcp_bpf_relay_filter_len;
358 		p.bf_insns = dhcp_bpf_relay_filter;
359 
360 		dhcp_bpf_relay_filter [10].k = ntohs (relay_port);
361 	}
362 #endif
363 	p.bf_insns [8].k = ntohs (local_port);
364 
365 	if (ioctl (info -> rfdesc, BIOCSETF, &p) < 0)
366 		log_fatal ("Can't install packet filter program: %m");
367 	if (!quiet_interface_discovery)
368 		log_info ("Listening on BPF/%s/%s%s%s",
369 		      info -> name,
370 		      print_hw_addr (info -> hw_address.hbuf [0],
371 				     info -> hw_address.hlen - 1,
372 				     &info -> hw_address.hbuf [1]),
373 		      (info -> shared_network ? "/" : ""),
374 		      (info -> shared_network ?
375 		       info -> shared_network -> name : ""));
376 }
377 
if_deregister_receive(info)378 void if_deregister_receive (info)
379 	struct interface_info *info;
380 {
381 	close (info -> rfdesc);
382 	info -> rfdesc = -1;
383 
384 	if (!quiet_interface_discovery)
385 		log_info ("Disabling input on BPF/%s/%s%s%s",
386 		      info -> name,
387 		      print_hw_addr (info -> hw_address.hbuf [0],
388 				     info -> hw_address.hlen - 1,
389 				     &info -> hw_address.hbuf [1]),
390 		      (info -> shared_network ? "/" : ""),
391 		      (info -> shared_network ?
392 		       info -> shared_network -> name : ""));
393 }
394 #endif /* USE_BPF_RECEIVE */
395 
396 #ifdef USE_BPF_SEND
send_packet(interface,packet,raw,len,from,to,hto)397 ssize_t send_packet (interface, packet, raw, len, from, to, hto)
398 	struct interface_info *interface;
399 	struct packet *packet;
400 	struct dhcp_packet *raw;
401 	size_t len;
402 	struct in_addr from;
403 	struct sockaddr_in *to;
404 	struct hardware *hto;
405 {
406 	unsigned hbufp = 0, ibufp = 0;
407 	double hw [4];
408 	double ip [32];
409 	struct iovec iov [3];
410 	int result;
411 
412 	if (!strcmp (interface -> name, "fallback"))
413 		return send_fallback (interface, packet, raw,
414 				      len, from, to, hto);
415 
416 	if (hto == NULL && interface->anycast_mac_addr.hlen)
417 		hto = &interface->anycast_mac_addr;
418 
419 	/* Assemble the headers... */
420 	assemble_hw_header (interface, (unsigned char *)hw, &hbufp, hto);
421 	assemble_udp_ip_header (interface,
422 				(unsigned char *)ip, &ibufp, from.s_addr,
423 				to -> sin_addr.s_addr, to -> sin_port,
424 				(unsigned char *)raw, len);
425 
426 	/* Fire it off */
427 	iov [0].iov_base = ((char *)hw);
428 	iov [0].iov_len = hbufp;
429 	iov [1].iov_base = ((char *)ip);
430 	iov [1].iov_len = ibufp;
431 	iov [2].iov_base = (char *)raw;
432 	iov [2].iov_len = len;
433 
434 	result = writev(interface -> wfdesc, iov, 3);
435 	if (result < 0)
436 		log_error ("send_packet: %m");
437 	return result;
438 }
439 #endif /* USE_BPF_SEND */
440 
441 #ifdef USE_BPF_RECEIVE
receive_packet(interface,buf,len,from,hfrom)442 ssize_t receive_packet (interface, buf, len, from, hfrom)
443 	struct interface_info *interface;
444 	unsigned char *buf;
445 	size_t len;
446 	struct sockaddr_in *from;
447 	struct hardware *hfrom;
448 {
449 	int length = 0;
450 	int offset = 0;
451 	struct bpf_hdr hdr;
452 	unsigned paylen;
453 
454 	/* All this complexity is because BPF doesn't guarantee
455 	   that only one packet will be returned at a time.   We're
456 	   getting what we deserve, though - this is a terrible abuse
457 	   of the BPF interface.   Sigh. */
458 
459 	/* Process packets until we get one we can return or until we've
460 	   done a read and gotten nothing we can return... */
461 
462 	/* If the buffer is empty, fill it. */
463 	if (interface->rbuf_offset >= interface->rbuf_len) {
464 		length = read(interface->rfdesc, interface->rbuf,
465 			      (size_t)interface->rbuf_max);
466 		if (length <= 0) {
467 #ifdef __FreeBSD__
468 			if (errno == ENXIO) {
469 #else
470 			if (errno == EIO) {
471 #endif
472 				dhcp_interface_remove
473 					((omapi_object_t *)interface, NULL);
474 			}
475 			return (length);
476 		}
477 		interface->rbuf_offset = 0;
478 		interface->rbuf_len = BPF_WORDALIGN(length);
479 	}
480 
481 	do {
482 		/* If there isn't room for a whole bpf header, something went
483 		   wrong, but we'll ignore it and hope it goes away... XXX */
484 		if (interface->rbuf_len -
485 		    interface->rbuf_offset < sizeof hdr) {
486 			interface->rbuf_offset = interface->rbuf_len;
487 			continue;
488 		}
489 
490 		/* Copy out a bpf header... */
491 		memcpy(&hdr, &interface->rbuf[interface->rbuf_offset],
492 		       sizeof hdr);
493 
494 		/* If the bpf header plus data doesn't fit in what's left
495 		   of the buffer, stick head in sand yet again... */
496 		if (interface->rbuf_offset +
497 		    hdr.bh_hdrlen + hdr.bh_caplen > interface->rbuf_len) {
498 			interface->rbuf_offset = interface->rbuf_len;
499 			continue;
500 		}
501 
502 		/* If the captured data wasn't the whole packet, or if
503 		   the packet won't fit in the input buffer, all we
504 		   can do is drop it. */
505 		if (hdr.bh_caplen != hdr.bh_datalen) {
506 			interface->rbuf_offset =
507 				BPF_WORDALIGN(interface->rbuf_offset +
508 					      hdr.bh_hdrlen + hdr.bh_caplen);
509 			continue;
510 		}
511 
512 		/* Skip over the BPF header... */
513 		interface->rbuf_offset += hdr.bh_hdrlen;
514 
515 		/* Decode the physical header... */
516 		offset = decode_hw_header(interface, interface->rbuf,
517 					  interface->rbuf_offset, hfrom);
518 
519 		/* If a physical layer checksum failed (dunno of any
520 		   physical layer that supports this, but WTH), skip this
521 		   packet. */
522 		if (offset < 0) {
523 			interface->rbuf_offset =
524 				BPF_WORDALIGN(interface->rbuf_offset +
525 					      hdr.bh_caplen);
526 			continue;
527 		}
528 		interface->rbuf_offset += offset;
529 		hdr.bh_caplen -= offset;
530 
531 		/* Decode the IP and UDP headers... */
532 		offset = decode_udp_ip_header(interface, interface->rbuf,
533 					      interface->rbuf_offset,
534                                               from, hdr.bh_caplen, &paylen, 1);
535 
536 		/* If the IP or UDP checksum was bad, skip the packet... */
537 		if (offset < 0) {
538 			interface->rbuf_offset =
539 				BPF_WORDALIGN(interface->rbuf_offset +
540 					      hdr.bh_caplen);
541 			continue;
542 		}
543 		interface->rbuf_offset = interface->rbuf_offset + offset;
544 		hdr.bh_caplen -= offset;
545 
546 		/* If there's not enough room to stash the packet data,
547 		   we have to skip it (this shouldn't happen in real
548 		   life, though). */
549 		if (hdr.bh_caplen > len) {
550 			interface->rbuf_offset =
551 				BPF_WORDALIGN(interface->rbuf_offset +
552 					       hdr.bh_caplen);
553 			continue;
554 		}
555 
556 		/* Copy out the data in the packet... */
557 		memcpy(buf, interface->rbuf + interface->rbuf_offset, paylen);
558 		interface->rbuf_offset =
559 			BPF_WORDALIGN(interface->rbuf_offset + hdr.bh_caplen);
560 		return paylen;
561 	} while (interface->rbuf_offset < interface->rbuf_len);
562 
563 	return (0);
564 }
565 
can_unicast_without_arp(ip)566 int can_unicast_without_arp (ip)
567 	struct interface_info *ip;
568 {
569 	return 1;
570 }
571 
can_receive_unicast_unconfigured(ip)572 int can_receive_unicast_unconfigured (ip)
573 	struct interface_info *ip;
574 {
575 	return 1;
576 }
577 
supports_multiple_interfaces(ip)578 int supports_multiple_interfaces (ip)
579 	struct interface_info *ip;
580 {
581 	return 1;
582 }
583 
maybe_setup_fallback()584 void maybe_setup_fallback ()
585 {
586 	isc_result_t status;
587 	struct interface_info *fbi = (struct interface_info *)0;
588 	if (setup_fallback (&fbi, MDL)) {
589 		if_register_fallback (fbi);
590 		status = omapi_register_io_object ((omapi_object_t *)fbi,
591 						   if_readsocket, 0,
592 						   fallback_discard, 0, 0);
593 		if (status != ISC_R_SUCCESS)
594 			log_fatal ("Can't register I/O handle for %s: %s",
595 				   fbi -> name, isc_result_totext (status));
596 		interface_dereference (&fbi, MDL);
597 	}
598 }
599 #endif
600 
601 #if defined(USE_BPF_RECEIVE) || defined(USE_BPF_HWADDR)
602 void
get_hw_addr(const char * name,struct hardware * hw)603 get_hw_addr(const char *name, struct hardware *hw) {
604 	struct ifaddrs *ifa;
605 	struct ifaddrs *p;
606 	struct sockaddr_dl *sa;
607 
608 	if (getifaddrs(&ifa) != 0) {
609 		log_fatal("Error getting interface information; %m");
610 	}
611 
612 	/*
613 	 * Loop through our interfaces finding a match.
614 	 */
615 	sa = NULL;
616 	for (p=ifa; (p != NULL) && (sa == NULL); p = p->ifa_next) {
617 		if ((p->ifa_addr->sa_family == AF_LINK) &&
618 		    !strcmp(p->ifa_name, name)) {
619 		    	sa = (struct sockaddr_dl *)p->ifa_addr;
620 		}
621 	}
622 	if (sa == NULL) {
623 		log_fatal("No interface called '%s'", name);
624 	}
625 
626 	/*
627 	 * Pull out the appropriate information.
628 	 */
629         switch (sa->sdl_type) {
630                 case IFT_ETHER:
631 #if defined (IFT_L2VLAN)
632 		case IFT_L2VLAN:
633 #endif
634                         hw->hlen = sa->sdl_alen + 1;
635                         hw->hbuf[0] = HTYPE_ETHER;
636                         memcpy(&hw->hbuf[1], LLADDR(sa), sa->sdl_alen);
637                         break;
638 		case IFT_ISO88023:
639 		case IFT_ISO88024: /* "token ring" */
640 		case IFT_ISO88025:
641 		case IFT_ISO88026:
642                         hw->hlen = sa->sdl_alen + 1;
643                         hw->hbuf[0] = HTYPE_IEEE802;
644                         memcpy(&hw->hbuf[1], LLADDR(sa), sa->sdl_alen);
645                         break;
646 #ifdef IFT_FDDI
647                 case IFT_FDDI:
648                         hw->hlen = sa->sdl_alen + 1;
649                         hw->hbuf[0] = HTYPE_FDDI;
650                         memcpy(&hw->hbuf[1], LLADDR(sa), sa->sdl_alen);
651                         break;
652 #endif /* IFT_FDDI */
653                 default:
654                         log_fatal("Unsupported device type %d for \"%s\"",
655                                   sa->sdl_type, name);
656         }
657 
658 	freeifaddrs(ifa);
659 }
660 #endif
661