Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 10 Feb 2007 21:17:52 +0000
From:      Bruce M Simpson <bms@incunabulum.net>
To:        freebsd-net@freebsd.org
Subject:   [PATCH] Introduce M_PROMISC to lower part of Ethernet code
Message-ID:  <45CE3680.2010103@incunabulum.net>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------030408010207040301060400
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Hi,

Thunderbird keeps crashing whenever I draft these messages, which is 
frustrating.

Can we discuss this change? I would like to get it in as we get the 
following wins:

1. Potentially cleaner code in ether_demux()/ether_input()
2. Ways of detecting and preventing L2/L3 forwarding loops
3. Being able to do more with promiscuous mode in general e.g. using it 
to emulate broken IFF_ALLMULTI with network cards which can't support 
multicast routing properly.

Feedback eagerly looked forward to; this is not a complete change; this 
is strictly development quality at the moment.

Regards,
BMS

--------------030408010207040301060400
Content-Type: text/x-patch;
 name="promisc2.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="promisc2.diff"

Index: net/if_ethersubr.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_ethersubr.c,v
retrieving revision 1.222
diff -u -p -r1.222 if_ethersubr.c
--- net/if_ethersubr.c	24 Dec 2006 08:52:13 -0000	1.222
+++ net/if_ethersubr.c	10 Feb 2007 20:59:39 -0000
@@ -582,6 +582,7 @@ ether_input(struct ifnet *ifp, struct mb
 	if (IFP2AC(ifp)->ac_netgraph != NULL) {
 		KASSERT(ng_ether_input_p != NULL,
 		    ("ng_ether_input_p is NULL"));
+		m->m_flags &= ~M_PROMISC;
 		(*ng_ether_input_p)(ifp, &m);
 		if (m == NULL)
 			return;
@@ -598,6 +599,7 @@ ether_input(struct ifnet *ifp, struct mb
 	 * at the src/sys/netgraph/ng_ether.c:ng_ether_rcv_upper()
 	 */
 	if (ifp->if_bridge) {
+		m->m_flags &= ~M_PROMISC;
 		BRIDGE_INPUT(ifp, m);
 		if (m == NULL)
 			return;
@@ -634,6 +636,14 @@ ether_demux(struct ifnet *ifp, struct mb
 	if (rule)	/* packet was already bridged */
 		goto post_stats;
 #endif
+	/*
+	 * If the frame was received promiscuously, mark it as such.
+	 */
+	if ((ifp->if_flags & IFF_PROMISC) &&
+	    !ETHER_IS_MULTICAST(eh->ether_dhost) &&
+	    bcmp(eh->ether_dhost, IF_LLADDR(ifp), ETHER_ADDR_LEN) != 0) {
+		m->m_flags |= M_PROMISC;
+	}
 
 	if (!(ifp->if_bridge) &&
 	    !((ether_type == ETHERTYPE_VLAN || m->m_flags & M_VLANTAG) &&
@@ -648,8 +658,10 @@ ether_demux(struct ifnet *ifp, struct mb
 		 * evaluation, to see if the carp ether_dhost values break any
 		 * of these checks!
 		 */
-		if (ifp->if_carp && carp_forus(ifp->if_carp, eh->ether_dhost))
+		if (ifp->if_carp && carp_forus(ifp->if_carp, eh->ether_dhost)) {
+			m->m_flags &= ~M_PROMISC;
 			goto pre_stats;
+		}
 #endif
 		/*
 		 * Discard packet if upper layers shouldn't see it because it
@@ -662,14 +674,16 @@ ether_demux(struct ifnet *ifp, struct mb
 		 * give them a chance to consider it as well (e. g. in case
 		 * bridging is only active on a VLAN).  They will drop it if
 		 * it's undesired.
+		 *
+		 * XXX: There is no way this check can be invoked if
+		 * there are no VLANs attached to this parent interface,
+		 * which is likely to cause recursion if we're acting
+		 * as an IP forwarder...
 		 */
-		if ((ifp->if_flags & IFF_PROMISC) != 0
-		    && !ETHER_IS_MULTICAST(eh->ether_dhost)
-		    && bcmp(eh->ether_dhost,
-		      IF_LLADDR(ifp), ETHER_ADDR_LEN) != 0
-		    && (ifp->if_flags & IFF_PPROMISC) == 0) {
-			    m_freem(m);
-			    return;
+		if ((m->m_flags & M_PROMISC) &&
+		    (ifp->if_flags & IFF_PPROMISC) == 0) {
+			m_freem(m);
+			return;
 		}
 	}
 
@@ -720,6 +734,7 @@ post_stats:
 		 * or drop the packet.
 		 */
 		KASSERT(vlan_input_p != NULL,("ether_input: VLAN not loaded!"));
+		m->m_flags &= ~M_PROMISC;
 		(*vlan_input_p)(ifp, m);
 		return;
 	}
@@ -732,6 +747,7 @@ post_stats:
 	case ETHERTYPE_VLAN:
 		if (ifp->if_vlantrunk != NULL) {
 			KASSERT(vlan_input_p,("ether_input: VLAN not loaded!"));
+			m->m_flags &= ~M_PROMISC;
 			(*vlan_input_p)(ifp, m);
 		} else {
 			ifp->if_noproto++;
Index: sys/mbuf.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/mbuf.h,v
retrieving revision 1.202
diff -u -p -r1.202 mbuf.h
--- sys/mbuf.h	25 Jan 2007 01:05:23 -0000	1.202
+++ sys/mbuf.h	10 Feb 2007 20:59:40 -0000
@@ -182,6 +182,7 @@ struct mbuf {
 #define	M_FIRSTFRAG	0x1000	/* packet is first fragment */
 #define	M_LASTFRAG	0x2000	/* packet is last fragment */
 #define	M_VLANTAG	0x10000	/* ether_vtag is valid */
+#define	M_PROMISC	0x20000	/* packet was not for us */
 
 /*
  * External buffer types: identify ext_buf type.
@@ -203,7 +204,7 @@ struct mbuf {
 #define	M_COPYFLAGS	(M_PKTHDR|M_EOR|M_RDONLY|M_PROTO1|M_PROTO1|M_PROTO2|\
 			    M_PROTO3|M_PROTO4|M_PROTO5|M_SKIP_FIREWALL|\
 			    M_BCAST|M_MCAST|M_FRAG|M_FIRSTFRAG|M_LASTFRAG|\
-			    M_VLANTAG)
+			    M_VLANTAG|M_PROMISC)
 
 /*
  * Flags to purge when crossing layers.

--------------030408010207040301060400--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?45CE3680.2010103>