if bpf fd's select()able?

Dmitry Morozovsky marck at rinet.ru
Mon Sep 8 00:40:09 PDT 2003


On Sun, 7 Sep 2003, Lev Walkin wrote:

LW> > [all below is for 4-STABLE]
LW> >
LW> > I'm trying to write effective arp scanner for multi-interface router (esp.
LW> > multi-vlan); I plan to use multiple bpf devices attached to different
LW> > interfaces emitting ARP requests and filters listening to ARP replies; the most
LW> > natural way to multiplex them for me is select().
LW> >
LW> > However, my tests show that select()ing bpf fd does not lead to trigger packets
LW> > available to bpf filter; the process hangs in select state while parallel
LW> > tcpdump process shows packets desired *and* is in bpf state.
LW> >
LW> > Am I missing something "base"? References (surely, I'd already read
LW> > manpages for bpf, pcap and related -- but did I still missed something
LW> > serious?) would be greatly appreciated.
LW>
LW> Yes, you're missing the interactive mode.
LW> Refer to BIOCIMMEDIATE in the bpf(4) manual page.

Unfortunately not ;-)

My test program chich I suppose should catch any ARP packets around
attached.

Sincerely,
D.Marck                                     [DM5020, MCK-RIPE, DM3-RIPN]
------------------------------------------------------------------------
*** Dmitry Morozovsky --- D.Marck --- Wild Woozle --- marck at rinet.ru ***
------------------------------------------------------------------------
-------------- next part --------------
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>

#include <net/bpf.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/ethernet.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>

#include <err.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>

/* bpf FSM to filter only ARP requests */
/*
struct bpf_insn insns[] = {
	BPF_STMT(BPF_LD+BPF_H+BPF_ABS, ETHER_ADDR_LEN*2),
	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_ARP, 0, 3),
	BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 20),
	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARPOP_REQUEST, 0, 1),
	BPF_STMT(BPF_RET+BPF_K, sizeof(struct ether_arp) +
		sizeof(struct ether_header)),
	BPF_STMT(BPF_RET+BPF_K, 0),
};*/
struct bpf_insn insns[] = {
	BPF_STMT(BPF_LD+BPF_H+BPF_ABS, ETHER_ADDR_LEN*2),
	BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_ARP, 0, 1),
	BPF_STMT(BPF_RET+BPF_K, sizeof(struct ether_arp) +
		sizeof(struct ether_header)),
	BPF_STMT(BPF_RET+BPF_K, 0),
};

struct bpf_program  bpf_arpreply = {
	sizeof(insns) / sizeof(struct bpf_insn),
	insns
};

#define BUFSZ 4096
static char buf[BUFSZ];

int main(int argc, char *argv[])
{
	int fd, sz;
	u_int yes;
	char *bpfn, *ifname;
	fd_set fds;
	struct ifreq ifr;

	bpfn = "/dev/bpf1";
	ifname = "rl0";

	if ((fd = open(bpfn, O_RDWR)) == -1)
		err(1, "can't open %s", bpfn);
	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
	if (ioctl(fd, BIOCSETIF, &ifr) == -1)
		err(1, "can't attach to %s", ifname);
	if (ioctl(fd, BIOCSETF, &bpf_arpreply) == -1)
		err(1, "can't set ARP reply filter");

	if (ioctl(fd, BIOCPROMISC, NULL) == -1)
		err(1, "can't set promisc mode");
	if (ioctl(fd, BIOCIMMEDIATE, &yes) == -1)
		err(1, "can't set IMMEDIATE mode");

	FD_ZERO(&fds);
	FD_SET(fd, &fds);
	while (select(1, &fds, NULL, NULL, NULL) != -1) {
		/* FD_ISSET(fd, fds) is always 1 here */
		printf("we have packet to read!");
		sz = read(fd, buf, BUFSZ);
		printf(" its len is %d bytes!\n", sz);
	}

	close(fd);
	return 0;
}


More information about the freebsd-hackers mailing list