Using the loopback interface with BPF
Robert Clipsham
robert at octarineparrot.com
Thu Jul 31 17:39:16 UTC 2014
Hi there,
I've been using BPF to read and write Ethernet packets from the network,
however I have encountered issues while writing a test suite for my code.
The
tests run on the loopback interface, however when calling write(), I
received
an EAFNOSUPPORT error (looutput: af=0 unexpected). When investigating
further
my findings were unexpected.
It seems there are three main functions involved with writing packets on the
loopback interface using BPF: looutput() from sys/net/if_loop.c; bpfwrite()
and
bpf_movein() from sys/net/bpf.c.
When write()ing, bpf_movein() generates a sockaddr which is later used in
looutput(). When using the loopback interface (DLT_NULL), the sa_family
field
is initialised to AF_UNSPEC, and it specifies a pseudo-header of 4 bytes
should
exist at the start of the buffer provided to write(). In bpfwrite(), after
bpf_movein() has been called, if BIOCSHDRCMPLT has been set, the sa_family
field is overwritten with pseudo_AF_HDRCMPLT.
After this initial setup, looutput() is called. It handles BPF calls
specially,
by checking if the sa_family is AF_UNSPEC, and if so treating sa_family as
whatever is stored in sa_data. There is then a switch statement, which only
handles AF_INET and AF_INET6 packets.
This has a number of consequences:
* When using BPF on the loopback interface, the first 4 bytes of the buffer
being sent are used for a pseudo-header. This pseudo-header remains
in-tact
when receiving, so the loopback interface must be special-cased for
sending/receiving (alternatively a corrupt packet is sent/received,
depending on how you look at it).
* The need for any kind of pseudo-header is undocumented in the BPF man
pages. It is mentioned briefly in the pcap man pages.
* When BIOSHDRCMPLT is set, BPF cannot work on the loopback interface
(since
looutput() checks for AF_UNSPEC, but sa_family is pseudo_AF_HDRCMPLT).
So my question is, what is the best way to test data link protocols with BPF
offline with FreeBSD? My current ideas:
* Special-case the loopback interface to add the pseudo-header and remove
the
BIOCSHDRCMPLT ioctl() (intresting note here: the ioctl() call does not
fail,
despite the option being invalid).
* Modify the loopback device to support data link protocols properly,
without
the need for a pseudo-header (of course this would break backwards
compatability).
* Create an additional type of loopback interface designed to emulate other
data link protocols.
Your input would be appreciated.
Thanks,
Robert
More information about the freebsd-net
mailing list