37 #if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE) \
38 || defined (USE_LPF_RECEIVE)
39 # if defined (USE_LPF_RECEIVE)
40 # include <asm/types.h>
41 # include <linux/filter.h>
42 # define bpf_insn sock_filter
44 # include <sys/ioctl.h>
47 # if defined (NEED_OSF_PFILT_HACKS)
48 # include <net/pfilt.h>
52 #include <netinet/in_systm.h>
58 #if defined(USE_BPF_SEND) || defined(USE_BPF_RECEIVE) || defined(USE_BPF_HWADDR)
59 #include <net/if_types.h>
75 #ifdef USE_BPF_RECEIVE
86 #if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE)
87 int if_register_bpf (info)
98 sock = open (filename, O_RDWR | O_CLOEXEC, 0);
100 if (errno == EBUSY) {
105 " Please read the README",
106 " section for your operating",
116 if (ioctl (sock, BIOCSETIF, info -> ifp) < 0)
117 log_fatal (
"Can't attach interface %s to bpf device %s: %m",
118 info -> name, filename);
132 #ifndef USE_BPF_RECEIVE
133 info -> wfdesc = if_register_bpf (info, interface);
135 info -> wfdesc = info -> rfdesc;
138 log_info (
"Sending on BPF/%s/%s%s%s",
141 info -> hw_address.hlen - 1,
142 &info -> hw_address.hbuf [1]),
153 #ifndef USE_BPF_RECEIVE
154 close (info -> wfdesc);
159 log_info (
"Disabling output on BPF/%s/%s%s%s",
162 info -> hw_address.hlen - 1,
163 &info -> hw_address.hbuf [1]),
170 #if defined (USE_BPF_RECEIVE) || defined (USE_LPF_RECEIVE)
175 struct bpf_insn dhcp_bpf_filter [] = {
177 BPF_STMT (BPF_LD + BPF_H + BPF_ABS, 12),
178 BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K,
ETHERTYPE_IP, 0, 8),
181 BPF_STMT (BPF_LD + BPF_B + BPF_ABS, 23),
182 BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
185 BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20),
186 BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
189 BPF_STMT (BPF_LDX + BPF_B + BPF_MSH, 14),
192 BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16),
193 BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1),
196 BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
199 BPF_STMT(BPF_RET+BPF_K, 0),
209 struct bpf_insn dhcp_ib_bpf_filter [] = {
212 BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 9),
213 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
216 BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 6),
217 BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
220 BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 0),
223 BPF_STMT(BPF_LD + BPF_H + BPF_IND, 2),
224 BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1),
227 BPF_STMT(BPF_RET + BPF_K, (u_int)-1),
230 BPF_STMT(BPF_RET + BPF_K, 0),
233 #if defined (DEC_FDDI)
234 struct bpf_insn *bpf_fddi_filter;
237 int dhcp_bpf_filter_len =
sizeof dhcp_bpf_filter /
sizeof (
struct bpf_insn);
238 int dhcp_ib_bpf_filter_len =
sizeof dhcp_ib_bpf_filter /
sizeof (
struct bpf_insn);
240 #if defined (HAVE_TR_SUPPORT)
241 struct bpf_insn dhcp_bpf_tr_filter [] = {
246 BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
249 BPF_STMT(BPF_RET+BPF_K, 0),
252 int dhcp_bpf_tr_filter_len = (
sizeof dhcp_bpf_tr_filter /
253 sizeof (
struct bpf_insn));
257 #if defined (USE_BPF_RECEIVE)
262 struct bpf_version v;
263 struct bpf_program p;
264 #ifdef NEED_OSF_PFILT_HACKS
272 info -> rfdesc = if_register_bpf (info);
275 if (ioctl (info -> rfdesc, BIOCVERSION, &v) < 0)
278 if (v.bv_major != BPF_MAJOR_VERSION ||
279 v.bv_minor < BPF_MINOR_VERSION)
280 log_fatal (
"BPF version mismatch - recompile DHCP!");
285 if (ioctl (info -> rfdesc, BIOCIMMEDIATE, &flag) < 0)
286 log_fatal (
"Can't set immediate mode on bpf device: %m");
288 #ifdef NEED_OSF_PFILT_HACKS
290 if (ioctl(info -> rfdesc, EIOCALLOWCOPYALL, &flag) < 0)
291 log_fatal (
"Can't set ALLOWCOPYALL: %m");
295 if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0)
296 log_fatal (
"Can't clear pfilt bits: %m");
299 bits = ENBATCH | ENCOPYALL | ENBPFHDR;
300 if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0)
301 log_fatal (
"Can't set ENBATCH|ENCOPYALL|ENBPFHDR: %m");
304 if (ioctl (info -> rfdesc, BIOCGBLEN, &info -> rbuf_max) < 0)
305 log_fatal (
"Can't get bpf buffer length: %m");
306 info -> rbuf =
dmalloc (info -> rbuf_max,
MDL);
308 log_fatal (
"Can't allocate %ld bytes for bpf input buffer.",
309 (
long)(info -> rbuf_max));
310 info -> rbuf_offset = 0;
311 info -> rbuf_len = 0;
314 p.bf_len = dhcp_bpf_filter_len;
318 if (ioctl(info -> rfdesc, BIOCGDLT, &link_layer) >= 0 &&
319 link_layer == DLT_FDDI) {
320 if (!bpf_fddi_filter) {
321 bpf_fddi_filter =
dmalloc (
sizeof bpf_fddi_filter,
323 if (!bpf_fddi_filter)
324 log_fatal (
"No memory for FDDI filter.");
325 memcpy (bpf_fddi_filter,
326 dhcp_bpf_filter,
sizeof dhcp_bpf_filter);
332 bpf_fddi_filter[0].k += 10;
333 bpf_fddi_filter[2].k += 10;
334 bpf_fddi_filter[4].k += 10;
335 bpf_fddi_filter[6].k += 10;
336 bpf_fddi_filter[7].k += 10;
338 p.bf_insns = bpf_fddi_filter;
341 p.bf_insns = dhcp_bpf_filter;
348 if (ioctl (info -> rfdesc, BIOCSETF, &p) < 0)
349 log_fatal (
"Can't install packet filter program: %m");
351 log_info (
"Listening on BPF/%s/%s%s%s",
354 info -> hw_address.hlen - 1,
355 &info -> hw_address.hbuf [1]),
364 close (info -> rfdesc);
368 log_info (
"Disabling input on BPF/%s/%s%s%s",
371 info -> hw_address.hlen - 1,
372 &info -> hw_address.hbuf [1]),
386 struct sockaddr_in *to;
389 unsigned hbufp = 0, ibufp = 0;
392 struct iovec iov [3];
395 if (!strcmp (interface -> name,
"fallback"))
399 if (hto == NULL && interface->anycast_mac_addr.
hlen)
400 hto = &interface->anycast_mac_addr;
405 (
unsigned char *)ip, &ibufp, from.s_addr,
406 to -> sin_addr.s_addr, to -> sin_port,
407 (
unsigned char *)raw, len);
410 iov [0].iov_base = ((
char *)hw);
411 iov [0].iov_len = hbufp;
412 iov [1].iov_base = ((
char *)ip);
413 iov [1].iov_len = ibufp;
414 iov [2].iov_base = (
char *)raw;
415 iov [2].iov_len = len;
417 result = writev(interface -> wfdesc, iov, 3);
424 #ifdef USE_BPF_RECEIVE
429 struct sockaddr_in *from;
446 if (interface->rbuf_offset >= interface->rbuf_len) {
447 length = read(interface->rfdesc, interface->rbuf,
448 (
size_t)interface->rbuf_max);
451 if (errno == ENXIO) {
460 interface->rbuf_offset = 0;
461 interface->rbuf_len = BPF_WORDALIGN(length);
467 if (interface->rbuf_len -
468 interface->rbuf_offset <
sizeof hdr) {
469 interface->rbuf_offset = interface->rbuf_len;
474 memcpy(&hdr, &interface->rbuf[interface->rbuf_offset],
479 if (interface->rbuf_offset +
480 hdr.bh_hdrlen + hdr.bh_caplen > interface->rbuf_len) {
481 interface->rbuf_offset = interface->rbuf_len;
488 if (hdr.bh_caplen != hdr.bh_datalen) {
489 interface->rbuf_offset =
490 BPF_WORDALIGN(interface->rbuf_offset +
491 hdr.bh_hdrlen + hdr.bh_caplen);
496 interface->rbuf_offset += hdr.bh_hdrlen;
500 interface->rbuf_offset, hfrom);
506 interface->rbuf_offset =
507 BPF_WORDALIGN(interface->rbuf_offset +
511 interface->rbuf_offset += offset;
512 hdr.bh_caplen -= offset;
516 interface->rbuf_offset,
517 from, hdr.bh_caplen, &paylen, 1);
521 interface->rbuf_offset =
522 BPF_WORDALIGN(interface->rbuf_offset +
526 interface->rbuf_offset = interface->rbuf_offset + offset;
527 hdr.bh_caplen -= offset;
532 if (hdr.bh_caplen > len) {
533 interface->rbuf_offset =
534 BPF_WORDALIGN(interface->rbuf_offset +
540 memcpy(buf, interface->rbuf + interface->rbuf_offset, paylen);
541 interface->rbuf_offset =
542 BPF_WORDALIGN(interface->rbuf_offset + hdr.bh_caplen);
544 }
while (interface->rbuf_offset < interface->rbuf_len);
576 if (status != ISC_R_SUCCESS)
577 log_fatal (
"Can't register I/O handle for %s: %s",
578 fbi ->
name, isc_result_totext (status));
579 interface_dereference (&fbi,
MDL);
584 #if defined(USE_BPF_RECEIVE) || defined(USE_BPF_HWADDR)
589 struct sockaddr_dl *sa;
591 if (getifaddrs(&ifa) != 0) {
592 log_fatal(
"Error getting interface information; %m");
599 for (p=ifa; (p != NULL) && (sa == NULL); p = p->ifa_next) {
600 if ((p->ifa_addr->sa_family == AF_LINK) &&
601 !strcmp(p->ifa_name, name)) {
602 sa = (
struct sockaddr_dl *)p->ifa_addr;
606 log_fatal(
"No interface called '%s'", name);
612 switch (sa->sdl_type) {
614 #if defined (IFT_L2VLAN)
617 hw->
hlen = sa->sdl_alen + 1;
619 memcpy(&hw->
hbuf[1], LLADDR(sa), sa->sdl_alen);
625 hw->
hlen = sa->sdl_alen + 1;
627 memcpy(&hw->
hbuf[1], LLADDR(sa), sa->sdl_alen);
631 hw->
hlen = sa->sdl_alen + 1;
633 memcpy(&hw->
hbuf[1], LLADDR(sa), sa->sdl_alen);
639 log_fatal(
"Unsupported device type %d for \"%s\"",
653 log_fatal(
"Unsupported device type %d for \"%s\"",
void if_register_send(struct interface_info *)
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 *))
void assemble_udp_ip_header(struct interface_info *, unsigned char *, unsigned *, u_int32_t, u_int32_t, u_int32_t, unsigned char *, unsigned)
int if_readsocket(omapi_object_t *h)
void if_reinitialize_send(struct interface_info *)
void * dmalloc(unsigned, const char *, int)
char * print_hw_addr(int htype, const int hlen, const unsigned char *data) const
ssize_t decode_udp_ip_header(struct interface_info *, unsigned char *, unsigned, struct sockaddr_in *, unsigned, unsigned *, int)
int can_receive_unicast_unconfigured(struct interface_info *)
isc_result_t dhcp_interface_remove(omapi_object_t *lp, omapi_object_t *id)
int setup_fallback(struct interface_info **fp, const char *file, int line)
int log_error(const char *,...) __attribute__((__format__(__printf__
void if_deregister_receive(struct interface_info *)
void get_hw_addr(struct interface_info *info)
void maybe_setup_fallback(void)
void if_deregister_send(struct interface_info *)
void log_fatal(const char *,...) __attribute__((__format__(__printf__
void assemble_hw_header(struct interface_info *, unsigned char *, unsigned *, struct hardware *)
ssize_t send_packet(struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)
int int log_info(const char *,...) __attribute__((__format__(__printf__
int quiet_interface_discovery
void if_register_fallback(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 supports_multiple_interfaces(struct interface_info *)
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
ssize_t receive_packet(struct interface_info *, unsigned char *, size_t, struct sockaddr_in *, struct hardware *)
ssize_t decode_hw_header(struct interface_info *, unsigned char *, unsigned, struct hardware *)
void if_reinitialize_receive(struct interface_info *)
int can_unicast_without_arp(struct interface_info *)
void if_register_receive(struct interface_info *)
isc_result_t fallback_discard(omapi_object_t *)