void if_register_receive(struct interface_info *info) { struct bpf_version v; struct bpf_program p; int flag = 1, sz, cmplt = 0; /* Open a BPF device and hang it on this interface... */ info->rfdesc = if_register_bpf(info); /* Make sure the BPF version is in range... */ if (ioctl(info->rfdesc, BIOCVERSION, &v) == -1) error("Can't get BPF version: %m"); if (v.bv_major != BPF_MAJOR_VERSION || v.bv_minor < BPF_MINOR_VERSION) error("Kernel BPF version out of range - recompile dhcpd!"); /* * Set immediate mode so that reads return as soon as a packet * comes in, rather than waiting for the input buffer to fill * with packets. */ if (ioctl(info->rfdesc, BIOCIMMEDIATE, &flag) == -1) error("Can't set immediate mode on bpf device: %m"); /* make sure kernel fills in the source ethernet address */ if (ioctl(info->rfdesc, BIOCSHDRCMPLT, &cmplt) == -1) error("Can't set header complete flag on bpf device: %m"); /* Get the required BPF buffer length from the kernel. */ if (ioctl(info->rfdesc, BIOCGBLEN, &sz) == -1) error("Can't get bpf buffer length: %m"); info->rbuf_max = sz; info->rbuf = malloc(info->rbuf_max); if (!info->rbuf) error("Can't allocate %lu bytes for bpf input buffer.", (unsigned long)info->rbuf_max); info->rbuf_offset = 0; info->rbuf_len = 0; /* Set up the bpf filter program structure. */ if (info->hw_address.htype == HTYPE_IPSEC_TUNNEL) { p.bf_len = dhcp_bpf_efilter_len; p.bf_insns = dhcp_bpf_efilter; } else { p.bf_len = dhcp_bpf_filter_len; p.bf_insns = dhcp_bpf_filter; } if (ioctl(info->rfdesc, BIOCSETF, &p) == -1) error("Can't install packet filter program: %m"); /* Set up the bpf write filter program structure. */ p.bf_len = dhcp_bpf_wfilter_len; p.bf_insns = dhcp_bpf_wfilter; if (ioctl(info->rfdesc, BIOCSETWF, &p) == -1) error("Can't install write filter program: %m"); /* make sure these settings cannot be changed after dropping privs */ if (ioctl(info->rfdesc, BIOCLOCK) == -1) error("Failed to lock bpf descriptor: %m"); }
void if_register_receive(struct interface_info *info) { struct bpf_version v; struct bpf_program p; int flag = 1, sz; /* Open a BPF device and hang it on this interface... */ info->rfdesc = if_register_bpf(info); /* Make sure the BPF version is in range... */ if (ioctl(info->rfdesc, BIOCVERSION, &v) < 0) error("Can't get BPF version: %m"); if (v.bv_major != BPF_MAJOR_VERSION || v.bv_minor < BPF_MINOR_VERSION) error("Kernel BPF version out of range - recompile dhcpd!"); /* * Set immediate mode so that reads return as soon as a packet * comes in, rather than waiting for the input buffer to fill * with packets. */ if (ioctl(info->rfdesc, BIOCIMMEDIATE, &flag) < 0) error("Can't set immediate mode on bpf device: %m"); /* Get the required BPF buffer length from the kernel. */ if (ioctl(info->rfdesc, BIOCGBLEN, &sz) < 0) error("Can't get bpf buffer length: %m"); info->rbuf_max = sz; info->rbuf = malloc(info->rbuf_max); if (!info->rbuf) error("Can't allocate %lu bytes for bpf input buffer.", (unsigned long)info->rbuf_max); info->rbuf_offset = 0; info->rbuf_len = 0; /* Set up the bpf filter program structure. */ p.bf_len = dhcp_bpf_filter_len; p.bf_insns = dhcp_bpf_filter; /* Patch the server port into the BPF program... * * XXX: changes to filter program may require changes to the * insn number(s) used below! */ dhcp_bpf_filter[8].k = LOCAL_PORT; if (ioctl(info->rfdesc, BIOCSETF, &p) < 0) error("Can't install packet filter program: %m"); /* Set up the bpf write filter program structure. */ p.bf_len = dhcp_bpf_wfilter_len; p.bf_insns = dhcp_bpf_wfilter; if (dhcp_bpf_wfilter[7].k == 0x1fff) dhcp_bpf_wfilter[7].k = htons(IP_MF|IP_OFFMASK); if (ioctl(info->rfdesc, BIOCSETWF, &p) < 0) error("Can't install write filter program: %m"); if (ioctl(info->rfdesc, BIOCLOCK, NULL) < 0) error("Cannot lock bpf"); }