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:47:02
It is important I mention that except for my mods to wi.c and, adding
BIOCGDLTLIST, Atsushi Onoe deserves credit for the code.

I will make some mods to libpcap and tcpdump Monday, and I hope to put
802.11 DLTs to the test on Wednesday.

Dave

On Thu, Aug 08, 2002 at 02:39:31PM -0500, David Young wrote:
> 
> 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

-- 
David Young             OJC Technologies
dyoung@onthejob.net     Engineering from the Right Brain
                        Urbana, IL * (217) 278-3933