[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bpf "filter drop" implementation



hi,

the following diff implements the missing parts for the "filter drop"
option in bpf. packets matching any bpf filters will be dropped if the
fildrop option is set.

i would like to get test reports, especially for the fildrop-enabled
dhclient. the initial implementation from last year caused problems
with dhclient running on a bridge.

thanks in advance,
reyk

Index: sbin/dhclient/bpf.c
===================================================================
RCS file: /cvs/src/sbin/dhclient/bpf.c,v
retrieving revision 1.14
diff -u -p -r1.14 bpf.c
--- sbin/dhclient/bpf.c	29 Jul 2005 17:26:28 -0000	1.14
+++ sbin/dhclient/bpf.c	13 Oct 2005 16:43:31 -0000
@@ -195,6 +195,9 @@ if_register_receive(struct interface_inf
 	if (ioctl(info->rfdesc, BIOCIMMEDIATE, &flag) < 0)
 		error("Can't set immediate mode on bpf device: %m");
 
+	if (ioctl(info->rfdesc, BIOCSFILDROP, &flag) < 0)
+		error("Can't set filter-drop mode on bpf device: %m");
+
 	/* Get the required BPF buffer length from the kernel. */
 	if (ioctl(info->rfdesc, BIOCGBLEN, &sz) < 0)
 		error("Can't get bpf buffer length: %m");
Index: share/man/man4/bpf.4
===================================================================
RCS file: /cvs/src/share/man/man4/bpf.4,v
retrieving revision 1.26
diff -u -p -r1.26 bpf.4
--- share/man/man4/bpf.4	13 Oct 2005 11:59:49 -0000	1.26
+++ share/man/man4/bpf.4	13 Oct 2005 16:43:27 -0000
@@ -405,14 +405,14 @@ automatically by the interface output ro
 Set to one if the link level source address will be written,
 as provided, to the wire.
 This flag is initialized to zero by default.
-.\" .Pp
-.\" .It Dv BIOCGFILDROP Fa "u_int *"
-.\" .It Dv BIOCSFILDROP Fa "u_int *"
-.\" Get or set the status of the
-.\" .Dq filter drop
-.\" flag.
-.\" If non-zero, packets matching any filters will be reported to the
-.\" associated interface so that they can be dropped.
+.Pp
+.It Dv BIOCGFILDROP Fa "u_int *"
+.It Dv BIOCSFILDROP Fa "u_int *"
+Get or set the status of the
+.Dq filter drop
+flag.
+If non-zero, packets matching any filters will be reported to the
+associated interface so that they can be dropped.
 .El
 .Ss Standard ioctls
 .Nm
Index: sys/sys/mbuf.h
===================================================================
RCS file: /cvs/src/sys/sys/mbuf.h,v
retrieving revision 1.82
diff -u -p -r1.82 mbuf.h
--- sys/sys/mbuf.h	26 May 2005 01:49:15 -0000	1.82
+++ sys/sys/mbuf.h	13 Oct 2005 16:43:28 -0000
@@ -143,10 +143,11 @@ struct mbuf {
 #define M_ANYCAST6	0x4000	/* received as IPv6 anycast */
 #define M_LINK0		0x8000	/* link layer specific flag */
 #define M_LOOP		0x0040	/* for Mbuf statistics */
+#define M_FILDROP	0x0080	/* dropped by bpf filter */
 
 /* flags copied when copying m_pkthdr */
 #define	M_COPYFLAGS	(M_PKTHDR|M_EOR|M_PROTO1|M_BCAST|M_MCAST|M_CONF|\
-			 M_AUTH|M_ANYCAST6|M_LOOP|M_TUNNEL|M_LINK0)
+			 M_AUTH|M_ANYCAST6|M_LOOP|M_TUNNEL|M_LINK0|M_FILDROP)
 
 /* Checksumming flags */
 #define	M_IPV4_CSUM_OUT		0x0001	/* IPv4 checksum needed */
Index: sys/net/bpf.c
===================================================================
RCS file: /cvs/src/sys/net/bpf.c,v
retrieving revision 1.59
diff -u -p -r1.59 bpf.c
--- sys/net/bpf.c	31 Jul 2005 03:52:18 -0000	1.59
+++ sys/net/bpf.c	13 Oct 2005 16:43:28 -0000
@@ -1157,17 +1157,16 @@ bpf_mcopy(const void *src_arg, void *dst
 /*
  * Incoming linkage from device drivers, when packet is in an mbuf chain.
  */
-int
+void
 bpf_mtap(caddr_t arg, struct mbuf *m)
 {
 	struct bpf_if *bp = (struct bpf_if *)arg;
 	struct bpf_d *d;
 	size_t pktlen, slen;
 	struct mbuf *m0;
-	int drop = 0;
 
 	if (m == NULL)
-		return (0);
+		return;
 
 	pktlen = 0;
 	for (m0 = m; m0 != 0; m0 = m0->m_next)
@@ -1182,10 +1181,8 @@ bpf_mtap(caddr_t arg, struct mbuf *m)
 
 		bpf_catchpacket(d, (u_char *)m, pktlen, slen, bpf_mcopy);
 		if (d->bd_fildrop)
-			drop++;
+			m->m_flags |= M_FILDROP;
 	}
-
-	return (drop);
 }
 
 /*
@@ -1197,7 +1194,7 @@ bpf_mtap(caddr_t arg, struct mbuf *m)
  * fields in this header that we initialize, and will not try to free
  * it or keep a pointer to it.
  */
-int
+void
 bpf_mtap_hdr(caddr_t arg, caddr_t data, u_int dlen, struct mbuf *m)
 {
 	struct m_hdr mh;
@@ -1207,7 +1204,8 @@ bpf_mtap_hdr(caddr_t arg, caddr_t data, 
 	mh.mh_len = dlen;
 	mh.mh_data = data;
 
-	return bpf_mtap(arg, (struct mbuf *) &mh);
+	bpf_mtap(arg, (struct mbuf *) &mh);
+	m->m_flags |= mh.mh_flags & M_FILDROP;
 }
 
 /*
@@ -1219,7 +1217,7 @@ bpf_mtap_hdr(caddr_t arg, caddr_t data, 
  * fields in this header that we initialize, and will not try to free
  * it or keep a pointer to it.
  */
-int
+void
 bpf_mtap_af(caddr_t arg, u_int32_t af, struct mbuf *m)
 {
 	struct m_hdr mh;
@@ -1229,7 +1227,8 @@ bpf_mtap_af(caddr_t arg, u_int32_t af, s
 	mh.mh_len = 4;
 	mh.mh_data = (caddr_t)&af;
 
-	return bpf_mtap(arg, (struct mbuf *) &mh);
+	bpf_mtap(arg, (struct mbuf *) &mh);
+	m->m_flags |= mh.mh_flags & M_FILDROP;
 }
 
 /*
Index: sys/net/bpf.h
===================================================================
RCS file: /cvs/src/sys/net/bpf.h,v
retrieving revision 1.31
diff -u -p -r1.31 bpf.h
--- sys/net/bpf.h	31 Jul 2005 03:52:18 -0000	1.31
+++ sys/net/bpf.h	13 Oct 2005 16:43:29 -0000
@@ -261,9 +261,9 @@ struct bpf_dltlist {
 #ifdef _KERNEL
 int	 bpf_validate(struct bpf_insn *, int);
 int	 bpf_tap(caddr_t, u_char *, u_int);
-int	 bpf_mtap(caddr_t, struct mbuf *);
-int	 bpf_mtap_hdr(caddr_t, caddr_t, u_int, struct mbuf *);
-int	 bpf_mtap_af(caddr_t, u_int32_t, struct mbuf *);
+void	 bpf_mtap(caddr_t, struct mbuf *);
+void	 bpf_mtap_hdr(caddr_t, caddr_t, u_int, struct mbuf *);
+void	 bpf_mtap_af(caddr_t, u_int32_t, struct mbuf *);
 void	 bpfattach(caddr_t *, struct ifnet *, u_int, u_int);
 void	 bpfdetach(struct ifnet *);
 void	 bpfilterattach(int);
Index: sys/net/if_ethersubr.c
===================================================================
RCS file: /cvs/src/sys/net/if_ethersubr.c,v
retrieving revision 1.97
diff -u -p -r1.97 if_ethersubr.c
--- sys/net/if_ethersubr.c	30 Sep 2005 02:39:24 -0000	1.97
+++ sys/net/if_ethersubr.c	13 Oct 2005 16:43:30 -0000
@@ -610,6 +610,14 @@ ether_input(ifp, eh, m)
 	ac = (struct arpcom *)ifp;
 
 	/*
+	 * If packet has been filtered by the bpf listener, drop it now.
+	 */
+	if (m->m_flags & M_FILDROP) {
+		m_freem(m);
+		return;
+	}
+
+	/*
 	 * If packet is unicast and we're in promiscuous mode, make sure it
 	 * is for us.  Drop otherwise.
 	 */
Index: sys/net80211/ieee80211_input.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_input.c,v
retrieving revision 1.11
diff -u -p -r1.11 ieee80211_input.c
--- sys/net80211/ieee80211_input.c	13 Sep 2005 12:11:03 -0000	1.11
+++ sys/net80211/ieee80211_input.c	13 Oct 2005 16:43:27 -0000
@@ -408,6 +408,15 @@ ieee80211_input(struct ifnet *ifp, struc
 #if NBPFILTER > 0
 		if (ic->ic_rawbpf)
 			bpf_mtap(ic->ic_rawbpf, m);
+		/*
+		 * Drop mbuf if it was filtered by bpf. Normally, this is
+		 * done in ether_input() but IEEE 802.11 management frames
+		 * are a special case.
+		 */
+		if (m->m_flags & M_FILDROP) {
+			m_freem(m);
+			return;
+		}			
 #endif
 		(*ic->ic_recv_mgmt)(ic, m, ni, subtype, rssi, rstamp);
 		m_freem(m);