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