Subject: Re: adding an 802.11 data link type
To: None <tech-net@netbsd.org>
From: David Young <dyoung@ojctech.com>
List: tech-net
Date: 08/08/2002 14:39:31
Here is the way it works.
I posit three 802.11 DLTs. Two are hardware-specific:
DLT_PRISM2_IEEE802_11 for Prism2.x, DLT_ORINOCO_IEEE802_11 for Lucent
WaveLAN. For plain 802.11, there is DLT_IEEE802_11.
I add to the wi_softc two fields,
struct bpf_if *sc_bpf80211;
struct bpf_if *sc_bpf80211plus;
In wi_attach, I register as a tap for 802.3 and plain 802.11 frames:
bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
bpfattach2(ifp, DLT_IEEE802_11, sizeof(struct ieee80211_frame_addr4),
(caddr_t*) &sc->sc_bpf80211);
Depending what firmware I detect---Intersil, Symbol (is only a divergence
from Prism reference design, I think), or Lucent---I register as a tap
for either Prism or Lucent hardware-specific frames, also:
if (sc->sc_firmware_type == WI_INTERSIL ||
sc->sc_firmware_type == WI_SYMBOL) {
bpfattach2(ifp, DLT_PRISM2_IEEE802_11, sizeof(struct wi_frame),
(caddr_t*) &sc->sc_bpf80211plus);
} else if (sc->sc_firmware_type == WI_LUCENT) {
bpfattach2(ifp, DLT_ORINOCO_IEEE802_11, sizeof(struct wi_frame),
(caddr_t*) &sc->sc_bpf80211plus);
}
I add to wi(4) two subroutine to tap frames. One takes an mbuf chain
containing an 802.11 mgmt/ctrl frame w/ hardware-specific extensions,
and hands up either an 802.11 frame, an 802.11 frame w/ extensions,
both, or neither:
STATIC void
wi_tap_802_11_plus(struct wi_softc *sc, struct mbuf *m,
struct wi_frame *hwframe)
{
struct mbuf *m2;
if (sc->sc_bpf80211plus) {
bpf_mtap((caddr_t) sc->sc_bpf80211plus, m);
}
if (sc->sc_bpf80211) {
m2 = m_copym(m, WI_802_11_OFFSET_HDR, M_COPYALL, M_DONTWAIT);
if (m2) {
bpf_mtap((caddr_t) sc->sc_bpf80211, m);
m_freem(m2);
}
}
}
The second subroutine takes an mbuf chain containing an 802.3 frame,
and augments it with an 802.11 header, an 802.11 header w/ extensions,
both, or neither:
STATIC void
wi_tap_802_3(struct wi_softc *sc, struct mbuf *m, struct wi_frame *hwframe)
{
struct mbuf *m2 = 0;
/* hand up 802.3 frame */
if (sc->sc_ifp->if_bpf) {
bpf_mtap(sc->sc_ifp->if_bpf, m);
}
/* hand up hardware-specific frame */
if (sc->sc_bpf80211plus) {
if (!(m2 = m_copym(m, 0, M_COPYALL, M_DONTWAIT))) {
goto bpf80211plus_failure;
}
M_PREPEND(m2, WI_802_3_OFFSET, M_DONTWAIT);
if (!m2) {
goto bpf80211plus_failure;
}
m_copyback(m2, 0, WI_802_3_OFFSET, (caddr_t) &hwframe);
bpf_mtap((caddr_t) sc->sc_bpf80211plus, m2);
m_freem(m2);
}
bpf80211plus_failure:
/* hand up 802.11 frame */
if (sc->sc_bpf80211) {
/* TBD optimize when m2 contains extended 802.11 frame */
if (!(m2 = m_copym(m, 0, M_COPYALL, M_DONTWAIT))) {
goto bpf80211_failure;
}
M_PREPEND(m2, WI_802_3_OFFSET - WI_802_11_OFFSET_HDR,
M_DONTWAIT);
if (!m2) {
goto bpf80211_failure;
}
m_copyback(m2, 0, WI_802_3_OFFSET - WI_802_11_OFFSET_HDR,
(caddr_t) &hwframe + WI_802_11_OFFSET_HDR);
bpf_mtap((caddr_t) sc->sc_bpf80211, m2);
m_freem(m2);
}
bpf80211_failure:
return;
}
BPF writes a pointer to a bpf_if into each of ifp->if_bpf,
sc->sc_bpf80211, or sc->sc_bpf80211plus as the first subscriber for
the associated DLT attaches. It writes a NULL to each of ifp->if_bpf,
sc->sc_bpf80211, or sc->sc_bpf80211plus, as the last subscriber detaches.
Because the tap subroutines check for a non-zero bpf_if pointer before
they produce or tap a frame, no frame will be built or handed up to BPF,
if a subscriber does not listen for it.
Questions? Criticisms?
Dave
On Thu, Aug 08, 2002 at 10:08:24AM -0700, Bill Studenmund wrote:
> On Thu, 8 Aug 2002, Atsushi Onoe wrote:
>
> > > So if I understand your code right, (ic->ic_rawbpf) is a necessary but not
> > > sufficient condition to hand the packet off to bpf_mtap. The bpf system
> > > would have had to ask for that packet type too. So something like:
> > > if ((ic->ic_rawbpf) && (ic->ic_raw_bpfcount))
> > > bpf_mtap(ic->ic_rawbpf, m0);
> >
> > Please note that this interface is very similar to existing bpf hook.
> > So the value of ic->ic_rawbpf remains NULL unless someone issues BPFSETIF
> > and BIOCSDLT, and recovered to NULL when the bpf listener closes bpf.
> > The number of opening listeners are counted in bpf itself.
>
> How does bpf communicate what kind of packets it wants to the driver?
>
> Take care,
>
> Bill
--
David Young OJC Technologies
dyoung@onthejob.net Engineering from the Right Brain
Urbana, IL * (217) 278-3933