ether_input: Defer promiscous packet discarding until vlan is processed
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Sun, 5 Apr 2009 03:38:23 +0000 (11:38 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Sun, 5 Apr 2009 03:38:23 +0000 (11:38 +0800)
This is the one of the precondition to make vlan/bridge work: preventing
packets from being dropped prematurely by vlan's parent interface.

sys/net/if_ethersubr.c

index 26b14be..5a18bc4 100644 (file)
@@ -1091,7 +1091,7 @@ void
 ether_demux_oncpu(struct ifnet *ifp, struct mbuf *m)
 {
        struct ether_header *eh;
-       int isr, redispatch;
+       int isr, redispatch, discard = 0;
        u_short ether_type;
        struct ip_fw *rule = NULL;
 #ifdef NETATALK
@@ -1144,20 +1144,20 @@ ether_demux_oncpu(struct ifnet *ifp, struct mbuf *m)
 #endif
 
        /*
-        * Discard packet if upper layers shouldn't see it because
-        * it was unicast to a different Ethernet address.  If the
-        * driver is working properly, then this situation can only
-        * happen when the interface is in promiscuous mode.
+        * We got a packet which was unicast to a different Ethernet
+        * address.  If the driver is working properly, then this
+        * situation can only happen when the interface is in
+        * promiscuous mode.  We defer the packet discarding until the
+        * vlan processing is done, so that vlan/bridge or vlan/netgraph
+        * could work.
         */
        if (((ifp->if_flags & (IFF_PROMISC | IFF_PPROMISC)) == IFF_PROMISC) &&
            !ETHER_IS_MULTICAST(eh->ether_dhost) &&
-           bcmp(eh->ether_dhost, IFP2AC(ifp)->ac_enaddr, ETHER_ADDR_LEN)) {
-               m_freem(m);
-               return;
-       }
+           bcmp(eh->ether_dhost, IFP2AC(ifp)->ac_enaddr, ETHER_ADDR_LEN))
+               discard = 1;
 
 post_stats:
-       if (IPFW_LOADED && ether_ipfw != 0) {
+       if (IPFW_LOADED && ether_ipfw != 0 && !discard) {
                struct ether_header save_eh = *eh;
 
                /* XXX old crufty stuff, needs to be removed */
@@ -1191,6 +1191,16 @@ post_stats:
        }
 
        /*
+        * If we have been asked to discard this packet
+        * (e.g. not for us), drop it before entering
+        * the upper layer.
+        */
+       if (discard) {
+               m_freem(m);
+               return;
+       }
+
+       /*
         * Clear protocol specific flags,
         * before entering the upper layer.
         */