Пример #1
0
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");
}
Пример #2
0
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");
}