Subject: Re: 802.11 libpcap support
To: Atsushi Onoe , Curt Sampson <cjs@cynic.net>
From: Bill Studenmund <wrstuden@netbsd.org>
List: tech-net
Date: 05/22/2002 11:50:39
On Wed, 22 May 2002, Curt Sampson wrote:

> On Wed, 22 May 2002, Atsushi Onoe wrote:

I've been meaning to EMail on this. The author of bsdairtools attends the
San Diego BSD group, and I've chatted with him about this at times.

One thing I'd like to suggest is that we fundamentally change how 802.11
interfaces hook to bpf. Yes, it's a bit of a tangent, but it's a
foundation for suggestions below.

Normally, interfaces build mbufs, pass them to bpf, and pass them to the
rest of the kernel. 802.11 is different in that there are multiple frame
types (802.3, 802.11, and driver-dependent ones). Given that frame set, we
will never be able to have one kernel interface that does all.

So my suggestion is for 802.11 interfaces (and any others that have
multiple frame types) to not send any packets to bpf by default. Instead,
it sends bpf packet types that bpf has asked for. Each driver keeps a mask
of types it supports (and identifiers for said bits, like bit 1 is 802.11,
bit 2 is 802.3, ...), and hands bpf packets bpf has a listener for.

Why do this? Because our kernel (and most other 802.11 kernels) really
only cares about the 802.3 encapsulated frames. If you want to do IPv4,
IPv6, IPX, Ethertalk, or anything else, you need the 802.3 frames. Unless
something is listening to a bpf and wants either an 802.11 or a
driver-specific frame, I see no point in building one to hand it to bpf
which will in turn do nothing with it. Especially since to cover all bases
(wihtout the change I have above) we'd have to build a packet of each type
bpf might want to see. :-|

Don't get me wrong; if there's a listener that wants 802.3, another one
that wants 802.11, and a third that wants HW-dependent frames, the driver
should make all of them & pass them to the respective listeners. Just we
shouldn't build packets listeners don't want.

Oh, and part of this proposal includes a new set of bpf/driver functions.
At least a new bpf_attach() variant. If you support multiple packet types
and want the bpf layer to tell you when to send (and stop sending)
packets, you use the new interface. If you are going to routinely send one
packet type up, you use the existing bpf attach routine.

Userland would open a bpf on an interface, and be able to ask the set of
frames it can get. By default it gets a standard one, 802.3 for this case.
It then can choose what it wants to get. It could make sense to get
multiple frame types.

We might also make "frame types" that are subsets. For instance I think it
would be interesting for tcpdump to show 802.3 frames and 802.11 frames
that aren't 802.3 encapsulations. The advantage I see over just getting
802.11 frames is that we will still have to make an 802.3 frame for the
kernel, so why take an input 802.11/802.3 frame and make an 802.11 frame
for bpf and a different 802.3 frame for the kernel?

> > 1. How to select raw 802.11 frame or ethernet compatible mode?
>
> I agree that the that the pseudo-interface thing is a bit ugly.
>
> It seems to me that making the default to be raw 802.11 mode, and having
> an explicit BIOCSDLT ioctol to let you turn on "Ethernet emulation" for
> that particular BPF device is the cleanest way to go.

I'd vote against this as most all of the traffic of bpf interest on an
802.11 net is encapsulation of 802.3 frames.

> Those things that refuse to work on non-Ethernet interfaces (rarpd
> and the like) will have to be modified to use this ioctl after
> opening the interface (but before checking the media type), but
> that's not a big or difficult change.

But why? Why make them pick a different packet type?

> > 2. The bpf packet format assumed by tcpdump is not so good.
> >
> > The current implmentation of tcpdump assumes 802.11 header immediately
> > followed by SNAP header and data (e.g. IP) packet.  But it confuses
> > libpcap to filter ip/tcp/... because 802.11 header is defined as
> > variable length.
>
> How does the tcpdump.org libpcap/tcpdump deal with this?
>
> > And there are no room to deliver useful information
> > such as RSSI or encoded rate, though it doesn't belong to actual header.
>
> Is this the "extra" stuff that some chipsets return (such as signal
> quality or whatever)? tcpdump.org just added more types: DLT_PRISM_HEADER
> and DLT_AIRONET_HEADER.

Not sure, but I don't think so. If it's after the 802.11 header, it should
be covered by the 802.11 spec. As I understand chipset-specific things,
they are all before the 802.11 header.

> Making generic versions of this available for those programs that can't
> handle the chipset-specific ones could be done with BIOCSDLT again.
>
> Here's a bit of a thought on how you might deal with this, actually.
> (But I've not thought about it much, so it may be rubbish.) You
> could start giving out the most generic DLT translation (i.e.,
> Ethernet in this case) so that older programs don't break. But you
> could add an ioctl to see what DLT the current device is translating
> from. Programs in the know can query that and, if they know that
> lower-level DLT, use BIOCSDLT to set the translation to that one.
> Then they repeat the process until they get down to a DLT they
> don't know. So tcpdump might do this:
>
>     1. open wi0;
>     2. ioctl: get current DLT; returns DLT_EN10MB
>     3. ioctl: get what we're translating from; returns DLT_IEEE802_11
>        We know how to interpret DLT_IEEE802_11.
>     4. ioctl: set current DLT to DLT_IEEE802_11
>
>        [Now we repeat steps 2-4 until we find something we don't know:]
>
>     5. ioctl: get current DLT; returns DLT_IEEE802_11
>     6. ioctl: get what we're translating from; returns DLT_PRISM_HEADER
>        We don't know how to interpret DLT_PRISM_HEADER, so we leave
>        it at DLT_IEEE802_11.

That's kinda what I suggested above, from the userland perspective. The
difference is I'd have the ioctl in step 3 list available packet types:
DLT_EN10MB, DLT_IEEE802_11, DLT_PRISM_HEADER, etc. so you can get it all
at once.

> > 3. How to handle WEP frame?  deliver undecrypted? or decrypted?
> > Most of the firmware automatically decrypt if WEP ICV matches.
>
> I'd say just deliver what the card gives you, since it's the card that
> does the decryption. If a user wants to (and is able to) put his card in
> a non-decrypt mode, presumably he has a userland program that can deal
> with it, and is going to be a bit careful about what else is using that
> interface at the same time. It would be a specialized enough application
> that I don't think that bpf or libpcap should deal with it.

Sounds good.

Take care,

Bill