Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 31 Jul 2014 17:46:19 +0100
From:      Robert Clipsham <robert@octarineparrot.com>
To:        freebsd-net@freebsd.org
Subject:   Using the loopback interface with BPF
Message-ID:  <CAJ9_%2BXK%2Bib3uei%2Ba-eaGmedpQXLm1dOCO5-Ez3EndFoNDpLwvQ@mail.gmail.com>

index | next in thread | raw e-mail

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


help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAJ9_%2BXK%2Bib3uei%2Ba-eaGmedpQXLm1dOCO5-Ez3EndFoNDpLwvQ>