Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 8 Sep 2003 11:40:06 +0400 (MSD)
From:      Dmitry Morozovsky <marck@rinet.ru>
To:        Lev Walkin <vlm@netli.com>
Cc:        hackers@freebsd.org
Subject:   Re: if bpf fd's select()able?
Message-ID:  <20030908113632.R55683@woozle.rinet.ru>
In-Reply-To: <3F5BB991.2050601@netli.com>
References:  <20030907233940.M18589@woozle.rinet.ru> <3F5BB991.2050601@netli.com>

next in thread | previous in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
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@rinet.ru ***
------------------------------------------------------------------------

[-- Attachment #2 --]
#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;
}

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030908113632.R55683>