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
43# include <sys/ioctl.h>
46# if defined (NEED_OSF_PFILT_HACKS)
47# include <net/pfilt.h>
51#include <netinet/in_systm.h>
57#if defined(USE_BPF_SEND) || defined(USE_BPF_RECEIVE) || defined(USE_BPF_HWADDR)
58#include <net/if_types.h>
85#if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE)
86int if_register_bpf (info)
97 sock = open (filename, O_RDWR | O_CLOEXEC, 0);
104 " Please read the README",
105 " section for your operating",
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);
131#ifndef USE_BPF_RECEIVE
132 info ->
wfdesc = if_register_bpf (info, interface);
137 log_info (
"Sending on BPF/%s/%s%s%s",
152#ifndef USE_BPF_RECEIVE
158 log_info (
"Disabling output on BPF/%s/%s%s%s",
169#if defined (USE_BPF_RECEIVE) || defined (USE_LPF_RECEIVE)
174struct bpf_insn dhcp_bpf_filter [] = {
176 BPF_STMT (BPF_LD + BPF_H + BPF_ABS, 12),
177 BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K,
ETHERTYPE_IP, 0, 8),
180 BPF_STMT (BPF_LD + BPF_B + BPF_ABS, 23),
181 BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
184 BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20),
185 BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
188 BPF_STMT (BPF_LDX + BPF_B + BPF_MSH, 14),
191 BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16),
192 BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1),
195 BPF_STMT (BPF_RET + BPF_K, (u_int)-1),
198 BPF_STMT (BPF_RET + BPF_K, 0),
201#if defined(RELAY_PORT)
205struct bpf_insn dhcp_bpf_relay_filter [] = {
207 BPF_STMT (BPF_LD + BPF_H + BPF_ABS, 12),
208 BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K,
ETHERTYPE_IP, 0, 10),
211 BPF_STMT (BPF_LD + BPF_B + BPF_ABS, 23),
212 BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 8),
215 BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20),
216 BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 6, 0),
219 BPF_STMT (BPF_LDX + BPF_B + BPF_MSH, 14),
222 BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16),
223 BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 2, 0),
226 BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16),
227 BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1),
230 BPF_STMT (BPF_RET + BPF_K, (u_int)-1),
233 BPF_STMT (BPF_RET + BPF_K, 0),
236int dhcp_bpf_relay_filter_len =
237 sizeof dhcp_bpf_relay_filter /
sizeof (
struct bpf_insn);
247struct bpf_insn dhcp_ib_bpf_filter [] = {
250 BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 9),
251 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
254 BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 6),
255 BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
258 BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 0),
261 BPF_STMT(BPF_LD + BPF_H + BPF_IND, 2),
262 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1),
265 BPF_STMT(BPF_RET + BPF_K, (u_int)-1),
268 BPF_STMT(BPF_RET + BPF_K, 0),
271#if defined (DEC_FDDI)
272struct bpf_insn *bpf_fddi_filter = NULL;
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 [] = {
283 BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
286 BPF_STMT(BPF_RET+BPF_K, 0),
289int dhcp_bpf_tr_filter_len = (
sizeof dhcp_bpf_tr_filter /
290 sizeof (
struct bpf_insn));
294#if defined (USE_BPF_RECEIVE)
299 struct bpf_version v;
300 struct bpf_program p;
301#ifdef NEED_OSF_PFILT_HACKS
309 info -> rfdesc = if_register_bpf (info);
312 if (ioctl (info -> rfdesc, BIOCVERSION, &v) < 0)
315 if (v.bv_major != BPF_MAJOR_VERSION ||
316 v.bv_minor < BPF_MINOR_VERSION)
317 log_fatal (
"BPF version mismatch - recompile DHCP!");
322 if (ioctl (info -> rfdesc, BIOCIMMEDIATE, &flag) < 0)
323 log_fatal (
"Can't set immediate mode on bpf device: %m");
325#ifdef NEED_OSF_PFILT_HACKS
327 if (ioctl(info -> rfdesc, EIOCALLOWCOPYALL, &flag) < 0)
328 log_fatal (
"Can't set ALLOWCOPYALL: %m");
332 if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0)
333 log_fatal (
"Can't clear pfilt bits: %m");
336 bits = ENBATCH | ENCOPYALL | ENBPFHDR;
337 if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0)
338 log_fatal (
"Can't set ENBATCH|ENCOPYALL|ENBPFHDR: %m");
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);
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;
351 p.bf_len = dhcp_bpf_filter_len;
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,
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);
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;
375 p.bf_insns = bpf_fddi_filter;
378 p.bf_insns = dhcp_bpf_filter;
383#if defined(RELAY_PORT)
389 p.bf_len = dhcp_bpf_relay_filter_len;
390 p.bf_insns = dhcp_bpf_relay_filter;
392 dhcp_bpf_relay_filter [10].k = ntohs (
relay_port);
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",
403 info -> hw_address.hlen - 1,
404 &info -> hw_address.hbuf [1]),
417 log_info (
"Disabling input on BPF/%s/%s%s%s",
435 struct sockaddr_in *to;
438 unsigned hbufp = 0, ibufp = 0;
441 struct iovec iov [3];
444 if (!strcmp (interface -> name,
"fallback"))
454 (
unsigned char *)
ip, &ibufp, from.s_addr,
455 to -> sin_addr.s_addr, to -> sin_port,
456 (
unsigned char *)raw, len);
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;
466 result = writev(interface -> wfdesc, iov, 3);
473#ifdef USE_BPF_RECEIVE
478 struct sockaddr_in *from;
496 length = read(interface->
rfdesc, interface->
rbuf,
500 if (errno == ENXIO) {
510 interface->
rbuf_len = BPF_WORDALIGN(length);
529 hdr.bh_hdrlen + hdr.bh_caplen > interface->
rbuf_len) {
537 if (hdr.bh_caplen != hdr.bh_datalen) {
540 hdr.bh_hdrlen + hdr.bh_caplen);
561 hdr.bh_caplen -= offset;
566 from, hdr.bh_caplen, &paylen, 1);
576 hdr.bh_caplen -= offset;
581 if (hdr.bh_caplen > len) {
591 BPF_WORDALIGN(interface->
rbuf_offset + hdr.bh_caplen);
626 log_fatal (
"Can't register I/O handle for %s: %s",
627 fbi ->
name, isc_result_totext (status));
628 interface_dereference (&fbi,
MDL);
633#if defined(USE_BPF_RECEIVE) || defined(USE_BPF_HWADDR)
638 struct sockaddr_dl *sa;
640 if (getifaddrs(&ifa) != 0) {
641 log_fatal(
"Error getting interface information; %m");
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;
655 log_fatal(
"No interface called '%s'", name);
661 switch (sa->sdl_type) {
663#if defined (IFT_L2VLAN)
666 hw->
hlen = sa->sdl_alen + 1;
668 memcpy(&hw->
hbuf[1], LLADDR(sa), sa->sdl_alen);
674 hw->
hlen = sa->sdl_alen + 1;
676 memcpy(&hw->
hbuf[1], LLADDR(sa), sa->sdl_alen);
680 hw->
hlen = sa->sdl_alen + 1;
682 memcpy(&hw->
hbuf[1], LLADDR(sa), sa->sdl_alen);
688 log_fatal(
"Unsupported device type %d for \"%s\"",
702 log_fatal(
"Unsupported device type %d for \"%s\"",
char * print_hw_addr(int htype, const int hlen, const unsigned char *data) const
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 *)
int setup_fallback(struct interface_info **fp, const char *file, int line)
int quiet_interface_discovery
int if_readsocket(omapi_object_t *h)
isc_result_t dhcp_interface_remove(omapi_object_t *lp, omapi_object_t *id)
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 *))
struct __omapi_object omapi_object_t
void * dmalloc(size_t, const char *, int)
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__
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
struct hardware anycast_mac_addr
struct hardware hw_address