Subject: Re: problem with promiscous mode and vlans
To: None <tech-net@netbsd.org>
From: Manuel Bouyer <bouyer@antioche.eu.org>
List: tech-net
Date: 03/19/2003 20:04:08
--Nq2Wo0NMKNjxTN9z
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Wed, Mar 19, 2003 at 07:25:23PM +0100, Manuel Bouyer wrote:
> I've gone with solution b), but using one of the M_LINK flag instead of
> burning a new one (there's only one byte left in m_flags).
> See attached patch
> comments ?

Sorry, wrong diff, I sent an older one which is buggy (clearing M_PROMISC
at the wrong place). Here is the right one.

-- 
Manuel Bouyer <bouyer@antioche.eu.org>
     NetBSD: 24 ans d'experience feront toujours la difference
--

--Nq2Wo0NMKNjxTN9z
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diff

Index: if_ether.h
===================================================================
RCS file: /cvsroot/src/sys/net/if_ether.h,v
retrieving revision 1.29
diff -u -r1.29 if_ether.h
--- if_ether.h	2003/02/26 06:31:12	1.29
+++ if_ether.h	2003/03/19 19:01:33
@@ -103,7 +103,8 @@
 /*
  * Ethernet-specific mbuf flags.
  */
-#define	M_HASFCS	M_LINK0		/* FCS included at end of frame */
+#define	M_HASFCS	M_LINK0	/* FCS included at end of frame */
+#define	M_PROMISC	M_LINK1	/* this packet is not for us */
 
 #ifdef _KERNEL
 /*
Index: if_ethersubr.c
===================================================================
RCS file: /cvsroot/src/sys/net/if_ethersubr.c,v
retrieving revision 1.105
diff -u -r1.105 if_ethersubr.c
--- if_ethersubr.c	2003/03/02 10:50:14	1.105
+++ if_ethersubr.c	2003/03/19 19:01:33
@@ -728,6 +728,8 @@
 	 * process it locally.
 	 */
 	if (ifp->if_bridge) {
+		/* clear M_PROMISC, in case the packets comes from a vlan */
+		m->m_flags &= ~M_PROMISC;
 		m = bridge_input(ifp, m);
 		if (m == NULL)
 			return;
@@ -738,29 +740,27 @@
 		 * to "bridge" the packet locally.
 		 */
 		ifp = m->m_pkthdr.rcvif;
-	}
+	} else 
 #endif /* NBRIDGE > 0 */
-
-	/*
-	 * XXX This comparison is redundant if we are a bridge
-	 * XXX and processing the packet locally.
-	 */
-	if ((m->m_flags & (M_BCAST|M_MCAST)) == 0 &&
-	    (ifp->if_flags & IFF_PROMISC) != 0 &&
-	    memcmp(LLADDR(ifp->if_sadl), eh->ether_dhost,
-		   ETHER_ADDR_LEN) != 0) {
-		m_freem(m);
-		return;
+	{
+		if ((m->m_flags & (M_BCAST|M_MCAST)) == 0 &&
+		    (ifp->if_flags & IFF_PROMISC) != 0 &&
+		    memcmp(LLADDR(ifp->if_sadl), eh->ether_dhost,
+			   ETHER_ADDR_LEN) != 0) {
+			m->m_flags |= M_PROMISC;
+		}
 	}
 
 #ifdef PFIL_HOOKS
-	if (pfil_run_hooks(&ifp->if_pfil, &m, ifp, PFIL_IN) != 0)
-		return;
-	if (m == NULL)
-		return;
+	if ((m->m_flags & M_PROMISC) == 0) {
+		if (pfil_run_hooks(&ifp->if_pfil, &m, ifp, PFIL_IN) != 0)
+			return;
+		if (m == NULL)
+			return;
 
-	eh = mtod(m, struct ether_header *);
-	etype = ntohs(eh->ether_type);
+		eh = mtod(m, struct ether_header *);
+		etype = ntohs(eh->ether_type);
+	}
 #endif
 
 	/*
@@ -802,6 +802,10 @@
 #if NPPPOE > 0
 	case ETHERTYPE_PPPOEDISC:
 	case ETHERTYPE_PPPOE:
+		if (m->m_flags & M_PROMISC) {
+			m_freem(m);
+			return;
+		}
 #ifndef PPPOE_SERVER
 		if (m->m_flags & (M_MCAST | M_BCAST)) {
 			m_freem(m);
@@ -829,7 +833,10 @@
 		return;
 #endif /* NPPPOE > 0 */
 	default:
-		; /* Nothing. */
+		if (m->m_flags & M_PROMISC) {
+			m_freem(m);
+			return;
+		}
 	}
 
 	/* Strip off the Ethernet header. */

--Nq2Wo0NMKNjxTN9z--