Subject: Re: adding an 802.11 data link type
To: None <wrstuden@netbsd.org>
From: Atsushi Onoe <onoe@sm.sony.co.jp>
List: tech-net
Date: 08/06/2002 09:44:59
	<Pine.NEB.4.33.0208051442050.16377-100000@vespasia.home-net.internetconnect.net>
References:
	<Pine.NEB.4.33.0208051442050.16377-100000@vespasia.home-net.internetconnect.net>
Mime-Version: 1.0
Content-Type: Text/Plain; charset=us-ascii

> > >  1) A driver supporting more than one DLT will call bpf with a new
> > >     procedure, bpfattach_multidlt, passing bpfattach_multidlt a mask
> > >     describing the DLTs the driver supports.
> >
> > Since the number of supported DLTs for a driver would be limited,
> > multiple calls to bpfattach_dlt() may be accepted.
> > This would help to implement streight forward implementation which splits
> > bpf_if for each DLT.
> 
> But do we want multiple bpf_if's? My original idea was there would be one
> bpf, just it could hand back different packet types.

Hmm, I've found my previous implementation.  I admit it is something like
ad hoc, but it works well and it has complete compatibility.

Atsushi Onoe

(not complete patch)
Index: net/bpf.c
===================================================================
RCS file: /cvsroot/syssrc/sys/net/bpf.c,v
retrieving revision 1.65
diff -u -r1.65 bpf.c
--- net/bpf.c	2002/06/06 23:54:47	1.65
+++ net/bpf.c	2002/08/05 07:02:30
@@ -746,6 +746,32 @@
 		break;
 
 	/*
+	 * Set device parameters.
+	 */
+	case BIOCSDLT:
+		if (d->bd_bif == 0)
+			error = EINVAL;
+		else if (d->bd_bif->bif_dlt != *(u_int *)addr) {
+			struct bpf_if *bp;
+
+			for (bp = bpf_iflist; bp != 0; bp = bp->bif_next) {
+				if (bp->bif_ifp == d->bd_bif->bif_ifp &&
+				    bp->bif_dlt == *(u_int *)addr)
+					break;
+			}
+			if (bp == 0)
+				error = EINVAL;
+			else {
+				s = splnet();
+				bpf_detachd(d);
+				bpf_attachd(d, bp);
+				reset_d(d);
+				splx(s);
+			}
+		}
+		break;
+
+	/*
 	 * Set interface name.
 	 */
 	case BIOCGETIF:
@@ -946,6 +972,9 @@
 		if (ifp == 0 ||
 		    strcmp(ifp->if_xname, ifr->ifr_name) != 0)
 			continue;
+		/* skip additional entry */
+		if (bp->bif_driverp != (struct bpf_if **)&ifp->if_bpf)
+			continue;
 		/*
 		 * We found the requested interface.
 		 * If it's not up, return an error.
@@ -1227,13 +1256,28 @@
 	struct ifnet *ifp;
 	u_int dlt, hdrlen;
 {
+
+	bpfattach2(ifp, dlt, hdrlen, &ifp->if_bpf);
+}
+
+/*
+ * Attach additional dlt for a interface to bpf.  dlt is the link layer type;
+ * hdrlen is the fixed size of the link header for the specified dlt
+ * (variable length headers not yet supported).
+ */
+void
+bpfattach2(ifp, dlt, hdrlen, driverp)
+	struct ifnet *ifp;
+	u_int dlt, hdrlen;
+	caddr_t *driverp;
+{
 	struct bpf_if *bp;
 	bp = (struct bpf_if *)malloc(sizeof(*bp), M_DEVBUF, M_DONTWAIT);
 	if (bp == 0)
 		panic("bpfattach");
 
 	bp->bif_dlist = 0;
-	bp->bif_driverp = (struct bpf_if **)&ifp->if_bpf;
+	bp->bif_driverp = (struct bpf_if **)driverp;
 	bp->bif_ifp = ifp;
 	bp->bif_dlt = dlt;
 
@@ -1288,12 +1332,13 @@
 		}
 	}
 
+  again:
 	for (bp = bpf_iflist, pbp = &bpf_iflist;
 	     bp != NULL; pbp = &bp->bif_next, bp = bp->bif_next) {
 		if (bp->bif_ifp == ifp) {
 			*pbp = bp->bif_next;
 			free(bp, M_DEVBUF);
-			break;
+			goto again;
 		}
 	}
 }
Index: net/if_ieee80211.h
===================================================================
RCS file: /cvsroot/syssrc/sys/net/if_ieee80211.h,v
retrieving revision 1.13
diff -u -r1.13 if_ieee80211.h
--- net/if_ieee80211.h	2002/08/05 06:55:05	1.13
+++ net/if_ieee80211.h	2002/08/05 07:29:50
@@ -308,6 +308,7 @@
 	struct ifqueue		ic_mgtq;
 	int			ic_flags;
 	enum ieee80211_state	ic_state;
+	caddr_t			ic_rawbpf;	/* packet filter structure */
 	struct ieee80211_bss	ic_bss;		/* information for this node */
 	int			ic_bss_privlen;	/* size for bs_private */
 	u_int8_t		ic_ibss_chan;
Index: net/if_ieee80211subr.c
===================================================================
RCS file: /cvsroot/syssrc/sys/net/if_ieee80211subr.c,v
retrieving revision 1.8
diff -u -r1.8 if_ieee80211subr.c
--- net/if_ieee80211subr.c	2002/08/05 06:55:06	1.8
+++ net/if_ieee80211subr.c	2002/08/05 07:04:53
@@ -129,6 +129,10 @@
 	int i, rate;
 
 	ether_ifattach(ifp, ic->ic_myaddr);
+#if NBPFILTER > 0
+	bpfattach2(ifp, DLT_IEEE802_11,
+	    sizeof(struct ieee80211_frame_addr4), &ic->ic_rawbpf);
+#endif
 	ieee80211_crc_init();
 	memcpy(ic->ic_chan_active, ic->ic_chan_avail,
 	    sizeof(ic->ic_chan_active));
@@ -236,6 +240,11 @@
 			goto err;
 		wh = mtod(m, struct ieee80211_frame *);
 	}
+#if NBPFILTER > 0
+	/* copy to listener after decrypt */
+	if (ic->ic_rawbpf)
+		bpf_mtap(ic->ic_rawbpf, m);
+#endif
 
 	dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
 
Index: dev/ic/awi.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/awi.c,v
retrieving revision 1.43
diff -u -r1.43 awi.c
--- dev/ic/awi.c	2002/08/05 06:55:07	1.43
+++ dev/ic/awi.c	2002/08/05 07:16:59
@@ -653,6 +653,10 @@
 				continue;
 			}
 		}
+#if NBPFILTER > 0
+		if (ic->ic_rawbpf)
+			bpf_mtap(ic->ic_rawbpf, m0);
+#endif
 		if (dowep) {
 			if ((m0 = ieee80211_wep_crypt(ifp, m0, 1)) == NULL) {
 				ifp->if_oerrors++;