31: bpf: bsd packet filter Berkeley Packet Filter - "taps" network interface open /dev/bpf0 and bind to interface /dev/bpf0, /dev/bpf1 ... # tcpdump does this # tcpdump -n -i xl0 host 131.252.215.7 note: (www.tcpdump.org provides tcpdump and libpcap for access to bpf or e.g., linux packet socket) note: tcpdump comes installed on freebsd, but it may be behind the times. tcpdump opens /dev/bpf devices in turn until it finds out that is not E_BUSY ethernet/slip/ppp/loopback all provide it packets including ethernet headers may be read *and* written to it go around the stack ... FYI: more on the bpf 1. BPF usenix paper: McCanne/Jacobson 1993 2. man 4 bpf on bsd box for true details 3. pcap(3) man page for "libpcap" ... which offers a high-level interface for using this stuff. linux note: uses "packet socket" results are similar. both use libpcap library note: jrb's "ourmon" has wierd mish-mash of bpf and libpcap, not all libpcap. 31.2 code intro net/bpf.h - constants net/bpfdes.h - structures net/bpf.c - device driver now: bpf.c bpf.h bpf_compat.h bpf_filter.c bpfdesc.h bpf_filter.c has bpf interpretive engine in it. bpf_compat.h - sunos/bsd compatibility hacks global variables bpf_iflist - bpf capable devices bpf_dtab - array of bpf descriptor structure bpf_bufsize - default size of bpf buffers stats: bpf_d structure bd_rcount # pkts NOT dropped bd_dcount # pkts dropped because no bpf buffer space 31.3 bpf_if structure bpf_iflist pts to 1st structure in list struct bpf_if - sample structg bif_next - next structure bpf_d bif_dlist - descriptor list (up pointer) bpf_if - pointer to softc of interface bif_dlt - int to proclaim interface type bif_hdrlen - length of header struct ifnet *bif_ifp - pointer to if part of interface types may include: DLT_EN10MB - ethernet DLT_SLIP - slip DLT_NULL - loopback why ... different kinds of link headers is why bpf prepends a bpf header in front of link header. bif_hdrlen is size of that. bpf_hdr timeval --- timestamp caplen - length of data actually captured (may be smaller) bh_datalen - length of original packet bh_hdrlen - length of bpf header Figure 31.7 bpf_iflist setup for 3 sample interfaces drivers call bpfattach at attach time see figure 31.8 (note: for ethernet drivers, this function has been kicked upstairs to net/if_ethersubr.c/ether_ifattach) if (bpf) bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); in fact: on input, driver work is fairly trivial at this point: rx function ... the end looks like this: /* Handle BPF listeners. */ if (ifp->if_bpf) bpf_mtap(ifp, m); note: console message only printed now if boot verbose mode set 31.4 bpf_d structure process opens bpf device, issues ioctl commands to select interface, read buffer size, and to spec a bpf filter. i/o + filter spec bpf device has bpf_d structure for storing i/o info plus filter each network interface may have more than one bpf device ... # hostname dumpme.cs.pdx.edu # tcpdump -n -i xl0 net 131.252.1.0/24 # tcpdump -n -i xl0 net 131.252.2.0/24 bpf_d has 2 packet buffers bpf_sbuf - incoming bpf_fbuf - free OR bpf_hbuf - hold buffer, packets being read by a process bd_slen - store buffer length in bytes bd_hlen - hold buffer length in bytes bd_bufsize records the size of the two buffer associated with the device note: current bsd sysctl -a | grep bpf debug.bpf_bufsize: 4096 debug.bpf_maxbufsize: 524288 bpfopen function allocate bpf_d return E_BUSY is desired minor dev is not free crw------- 1 root wheel 23, 0 Mar 21 20:50 /dev/bpf0 crw------- 1 root wheel 23, 1 Mar 19 13:14 /dev/bpf1 crw------- 1 root wheel 23, 2 Mar 19 13:06 /dev/bpf2 crw------- 1 root wheel 23, 3 Dec 3 04:39 /dev/bpf3 zero out, and set default bufsize note classic use of character device switch: #define CDEV_MAJOR 23 static struct cdevsw bpf_cdevsw = { /* open */ bpfopen, /* close */ bpfclose, /* read */ bpfread, /* write */ bpfwrite, /* ioctl */ bpfioctl, /* poll */ bpfpoll, /* mmap */ nommap, /* strategy */ nostrategy, /* name */ "bpf", /* maj */ CDEV_MAJOR, /* dump */ nodump, /* psize */ nopsize, /* flags */ 0, /* bmaj */ -1 }; bpfioctl function ioctl used to call this ... once device is open p. 1038 bpf_setif function associate bpf descriptor with network interface based on string name of interface; e.g., "xl0" separate name into xl 0 search ifs that support bpf to see if this is one of them. bpf_d is associated and reset (any pending buffers cleared) ENXIO returned if no interface 31.5 bpf_input read system call used to read bpf "matching" buffers note string expression to bpf could be net 1/8 or net 192.1.0/22 or udp or "" bpf collects *copies* of packets ... bpf_tap function called by driver (or bpf_mtap) figure 31.18 traverse the list of bpf devices attached to the interface in question count the packet as a READ slen = bpf_filter ... run expression returns match count or 0 if match count catchpacket function ... catchpacket snaplen - number of bytes to save from the packet note that bpf header is copied in here note that drop count is incremented, but nothing is done to undo read count note that immediate causes wakeup bpfread function this is top-half code read on bpf device to here at this time, timed read (with timeout) could be done with BIOCSRTIMEOUT ... can now be done with select too reader must have read buffer that is side of hold buffer read returns when store buffer becomes full store buffer becomes hold buffer, return hold buffer bpf device continues to collect data in store buffer bpfread block device with splimp if nothing in hold buffer, timed sleep or wait until packets fill store buffer wait for data if data in hold buffer skip loop at 385 uiomove ... data in hold buffer (hopefully) hold buffer becomes free buffer note tendency here if possible to move bd_bufsize full of snaplen packets 31.6 bpf output bpf_movein to copyh data in interface output function called if_output may be ether_output which in turn will call device output function note: ethernet header may or may not be supplied. however if supplied, note that ioctl specified in bpf(4) must be set.