From nobody  Thu Jul  2 04:43:18 1998
Received: (from nobody@localhost)
          by hub.freebsd.org (8.8.8/8.8.8) id EAA05311;
          Thu, 2 Jul 1998 04:43:18 -0700 (PDT)
          (envelope-from nobody)
Message-Id: <199807021143.EAA05311@hub.freebsd.org>
Date: Thu, 2 Jul 1998 04:43:18 -0700 (PDT)
From: max@cca.usart.ru
To: freebsd-gnats-submit@freebsd.org
Subject: WaveLAN interface moves packets to uper layer while dst addr does not belong to that interface (even while not in allmulti/promisc mode)
X-Send-Pr-Version: www-1.0

>Number:         7144
>Category:       kern
>Synopsis:       WaveLAN interface moves packets to uper layer while dst addr does not belong to that interface (even while not in allmulti/promisc mode)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jul  2 04:50:01 PDT 1998
>Closed-Date:    Wed Aug 19 22:50:17 PDT 1998
>Last-Modified:  Thu Aug 20 00:30:00 PDT 1998
>Originator:     Max Gotlib
>Release:        2.2.5-RELEASE ... 3.0-Current
>Organization:
Urals State Academy Of Railway Transport
>Environment:
FreeBSD wavegw1.usart.ru 2.2.6-RELEASE FreeBSD 2.2.6-RELEASE #4: Thu Jul  2 16:43:14 ESS 1998     root@relay.usart.ru:/usr/src/sys/compile/WGW  i386

>Description:
This problem can be detected in case several WaveLAN boards equipped
(I detect the problem with ISA full-length WaveLAN-AT/2.4 board)
machines with unidirectional ant.kits are looking at omnidirctional
antenna (WavePoint for example). In that case the WaveLAN boards
will be bombed with retranslated packets (destination eth. address
will be _nither_for_this_board_nor_multicast_nor_broadcast_. But
dui to i82586 architecture, WaveLAN boards are not capable to dial
with ALLMILTY mode (which is emulated via promisc mode by the WaveLAN
driver). And, because of the driver's code, this packets could
be raised to upper layer and confuse the whole protocol-stack.
But, dui to the driver's code, this will not happend if there is
at least one BPF listener on that interface (the propper software
filters will kick that packets off after they are checked by the BPF).

>How-To-Repeat:
In the following network topology:

A -(     ()      )-B---D
          |
          C
(X-( means station X with unidirectional ant., and () meand omnidirectional)
try to "traceroute" station A from station D, while keeping ipfw
aimed to drop all packets with src address of B-D subnet, that are
captured fron wavelan interface (on B station). In that case
B will catch packets, retraslated by C for A, ipfw will drop them, and
the ICMP message will be sent to D (and at least in case, D is
powered with Linux OS, it will ignore "the real traceroute
packets" that will also be delivered to it).
>Fix:
Here is a patch against 2.2.6-RELEASE /sys/i386/isa/if_wl.c:
/***************CUT*******************/
--- if_wl.c-orig        Tue Aug 26 04:34:25 1997
+++ if_wl.c             Thu Jul  2 17:39:09 1998
@@ -1080,7 +1080,6 @@

     m->m_pkthdr.len = clen;

-#ifdef NOTYET
     /* due to fact that controller does not support
      * all multicast mode, we must filter out unicast packets
      * that are not for us.
@@ -1091,13 +1090,23 @@
      *
      * TBD: also discard packets where NWID does not match.
      */
-    if ( (sc->mode & MOD_ENAL) && ((sc->mode & MOD_PROM) != 0) &&
+    if (((sc->mode & MOD_PROM) == 0) &&
         ((eh.ether_dhost[0] & 1) == 0) /* !mcast and !bcast */ &&
         (bcmp(eh.ether_dhost, sc->wl_ac.ac_enaddr,
         sizeof(eh.ether_dhost)) != 0) ) {
         m_freem(m);
         return 1;
     }
+#ifdef MULTICAST
+    /* extra check for multicasts */
+    if (((sc->mode & MOD_PROM) == 0)   && /* !promisc mode */
+        (eh.ether_dhost[0] & 1)        && /* multicast or broadcast */
+         bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh.ether_dhost,
+               sizeof(etherbroadcastaddr)) &&
+         !ether_matchmulti(&sc->wl_ac, eh.ether_dhost)) {
+        m_freem(m);
+        return 1;
+    }
 #endif
 #if NBPFILTER > 0
     /*
@@ -1132,6 +1141,16 @@
            m_freem(m);
            return 1;
        }+#ifdef MULTICAST
+        /* extra check for multicasts */
+        if ((eh.ether_dhost[0] & 1) &&
+            bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh.ether_dhost,
+                 sizeof(etherbroadcastaddr)) &&
+            !ether_matchmulti(&sc->wl_ac, eh.ether_dhost)) {
+            m_freem(m);
+            return 1;
+        }
+#endif
     }
 #endif
/***************CUT***************/
The idea is to enable commented out filter, but to rise it against
in case of non multicast, non broadcast packets with not our's
dst ethernet address while interface is not in promisc mode
(in the last case it will be dropped after the BPF listenet, if one,
will be notified). Several multicast checks were added (following
INRIA's implementation).

>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->suspended 
State-Changed-By: phk 
State-Changed-When: Fri Jul 3 01:12:21 PDT 1998 
State-Changed-Why:  
awaiting committer 

From: Greg Troxel <gdt@ir.bbn.com>
To: freebsd-gnats-submit@freebsd.org, max@cca.usart.ru
Cc: Jim Binkley <jrb@cs.pdx.edu>, Mike Smith <mike@smith.net.au>
Subject: Re: kern/7144: WaveLAN interface moves packets to uper layer while dst addr does not belong to that interface (even while not in allmulti/promisc mode)
Date: Wed, 19 Aug 1998 11:40:20 -0400

 I had just about the same problem, with 915 MHz ISA wavelans cards and
 no wavepoints.  Running mrouted, which set IFF_ALLMULTI caused unicast
 packets with a mac address not matching the local machine to be
 forwarded.  My fix is different, and I believe makes bpf work
 correctly.
 
 The check for dropping unicast packets not sent to our ethernet
 address is after the bpf tap, but not conditioned on it.  All packets
 received should get handed to bpf, and unicast packets not to us (mac)
 should get dropped whether or not there is a bpf listener.  I believe
 that the common optimization that the interface is in hw promisc mode
 iff there is a bpf listener is in general wrong, but more frequently
 so on wavelans.
 
 I think Max's fix makes bpf listeners not see unicast packets sent to
 others, but I'm not sure.
 
 One can argue that checking on MOD_ENAL is wrong, but the code only
 drops packets that shouldn't be received.  The correctness condition
 is that it be run whenever unicast packets without our mac address can
 be received.
 
 Index: if_wl.c
 ===================================================================
 RCS file: /OBS-CVS/FreeBSD/src/sys/i386/isa/if_wl.c,v
 retrieving revision 1.1
 retrieving revision 1.3
 diff -u -r1.1 -r1.3
 @@ -1080,25 +1089,6 @@
  
      m->m_pkthdr.len = clen;
  
 -#ifdef NOTYET
 -    /* due to fact that controller does not support
 -     * all multicast mode, we must filter out unicast packets
 -     * that are not for us. 
 -     *
 -     * if we are in all multicast mode and not promiscuous mode
 -     * and packet is unicast and not for us, 
 -     * 		toss the packet 
 -     *
 -     * TBD: also discard packets where NWID does not match.
 -     */
 -    if ( (sc->mode & MOD_ENAL) && ((sc->mode & MOD_PROM) != 0) &&
 -        ((eh.ether_dhost[0] & 1) == 0) /* !mcast and !bcast */ &&
 -        (bcmp(eh.ether_dhost, sc->wl_ac.ac_enaddr,
 -    	 sizeof(eh.ether_dhost)) != 0) ) {
 -        m_freem(m);
 -        return 1;
 -    }
 -#endif
  #if NBPFILTER > 0
      /*
       * Check if there's a BPF listener on this interface. If so, hand off
 @@ -1116,24 +1106,35 @@
  
  	bpf_mtap(ifp, &m0);
  	
 -	/*
 -	 * point of this code is that even though we are in promiscuous
 -	 * mode, and due to fact that bpf got packet already, we
 -	 * do toss unicast packet not to us so that stacks upstairs
 -	 * do not need to weed it out
 -	 *
 -	 * logic: if promiscuous mode AND not multicast/bcast AND
 -	 *	not to us, throw away
 -	 */
 -	if ((sc->wl_ac.ac_if.if_flags & IFF_PROMISC) &&
 -	    (eh.ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
 -	    bcmp(eh.ether_dhost, sc->wl_ac.ac_enaddr,
 -		 sizeof(eh.ether_dhost)) != 0 ) {
 -	    m_freem(m);
 -	    return 1;
 -	}
      }
  #endif
 +    /*
 +     * If hw is in promiscuous mode (note that I said hardware, not if
 +     * IFF_PROMISC is set in ifnet flags), then if this is a unicast
 +     * packet and the MAC dst is not us, drop it.  This check was formerly
 +     * inside the bpf if, above, but IFF_MULTI causes hw promisc without
 +     * a bpf listener, so this is wrong.
 +     *		Greg Troxel <gdt@ir.bbn.com>, 1998-08-07
 +     */
 +    /*
 +     * TBD: also discard packets where NWID does not match.
 +     * However, there does not appear to be a way to read the nwid
 +     * for a received packet.  -gdt 1998-08-07
 +     */
 +    if (
 +#ifdef WL_USE_IFNET_PROMISC_CHECK /* not defined */
 +	(sc->wl_ac.ac_if.if_flags & (IFF_PROMISC|IFF_ALLMULTI))
 +#else
 +	/* hw is in promisc mode if this is true */
 +	(sc->mode & (MOD_PROM | MOD_ENAL))
 +#endif
 +	&&
 +	(eh.ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
 +	bcmp(eh.ether_dhost, sc->wl_ac.ac_enaddr,
 +	     sizeof(eh.ether_dhost)) != 0 ) {
 +      m_freem(m);
 +      return 1;
 +    }
  
  #ifdef WLDEBUG
      if (sc->wl_if.if_flags & IFF_DEBUG)
State-Changed-From-To: suspended->closed 
State-Changed-By: msmith 
State-Changed-When: Wed Aug 19 22:50:17 PDT 1998 
State-Changed-Why:  
Improved fix submitted by Greg Troxel <gdt@ir.bbn.com> was adopted. 

From: Mike Smith <mike@smith.net.au>
To: Greg Troxel <gdt@ir.bbn.com>
Cc: freebsd-gnats-submit@freebsd.org, max@cca.usart.ru,
        Jim Binkley <jrb@cs.pdx.edu>, Mike Smith <mike@smith.net.au>
Subject: Re: kern/7144: WaveLAN interface moves packets to uper layer while dst addr does not belong to that interface (even while not in allmulti/promisc mode) 
Date: Wed, 19 Aug 1998 22:51:40 +0000

 > 
 > I had just about the same problem, with 915 MHz ISA wavelans cards and
 > no wavepoints.  Running mrouted, which set IFF_ALLMULTI caused unicast
 > packets with a mac address not matching the local machine to be
 > forwarded.  My fix is different, and I believe makes bpf work
 > correctly.
 
 I can't test this, but it looks good.  I've committed it to both 2.2.6 
 and -current; any feedback would be greatly appreciated.
 
 -- 
 \\  Sometimes you're ahead,       \\  Mike Smith
 \\  sometimes you're behind.      \\  mike@smith.net.au
 \\  The race is long, and in the  \\  msmith@freebsd.org
 \\  end it's only with yourself.  \\  msmith@cdrom.com
 
 

From: Max Gotlib <max@cca.usart.ru>
To: Greg Troxel <gdt@ir.bbn.com>
Cc: freebsd-gnats-submit@freebsd.org, Jim Binkley <jrb@cs.pdx.edu>,
        Mike Smith <mike@smith.net.au>
Subject: Re: kern/7144: WaveLAN interface moves packets to uper layer while dst addr does not belong to that interface (even while not in allmulti/promisc mode)
Date: Thu, 20 Aug 1998 12:55:39 +0600 (ESD)

 Hi!
 
 Glad too see that wavelan technology is of a particular interest ...
 And as for suggested patch - totally agreed :)))
 
 And one Q. more - I sent another patch (kern/7044) that fixed
 (at least for me) wavelan board initialization process...
 Can you test it on your board, please, and if the results 
 will be successfull - i would be glad to see it (or it's variant)
 in the FreeBSD source tree...
 
 With best regards,
 Max.
 
 On Wed, 19 Aug 1998, Greg Troxel wrote:
 
 > I had just about the same problem, with 915 MHz ISA wavelans cards and
 > no wavepoints.  Running mrouted, which set IFF_ALLMULTI caused unicast
 > packets with a mac address not matching the local machine to be
 > forwarded.  My fix is different, and I believe makes bpf work
 > correctly.
 > 
 > The check for dropping unicast packets not sent to our ethernet
 > address is after the bpf tap, but not conditioned on it.  All packets
 > received should get handed to bpf, and unicast packets not to us (mac)
 > should get dropped whether or not there is a bpf listener.  I believe
 > that the common optimization that the interface is in hw promisc mode
 > iff there is a bpf listener is in general wrong, but more frequently
 > so on wavelans.
 > 
 > I think Max's fix makes bpf listeners not see unicast packets sent to
 > others, but I'm not sure.
 > 
 > One can argue that checking on MOD_ENAL is wrong, but the code only
 > drops packets that shouldn't be received.  The correctness condition
 > is that it be run whenever unicast packets without our mac address can
 > be received.
 

From: Mike Smith <mike@smith.net.au>
To: Max Gotlib <max@cca.usart.ru>
Cc: Greg Troxel <gdt@ir.bbn.com>, freebsd-gnats-submit@freebsd.org,
        Jim Binkley <jrb@cs.pdx.edu>, Mike Smith <mike@smith.net.au>
Subject: Re: kern/7144: WaveLAN interface moves packets to uper layer while dst addr does not belong to that interface (even while not in allmulti/promisc mode) 
Date: Thu, 20 Aug 1998 00:18:06 +0000

 Please make sure you copy me on the results of this; if it works OK 
 then I'll commit it (but otherwise I am going to forget).  Please also 
 mention the PR number when you do.
 
 Thanks.
 
 > Hi!
 > 
 > Glad too see that wavelan technology is of a particular interest ...
 > And as for suggested patch - totally agreed :)))
 > 
 > And one Q. more - I sent another patch (kern/7044) that fixed
 > (at least for me) wavelan board initialization process...
 > Can you test it on your board, please, and if the results 
 > will be successfull - i would be glad to see it (or it's variant)
 > in the FreeBSD source tree...
 > 
 > With best regards,
 > Max.
 > 
 > On Wed, 19 Aug 1998, Greg Troxel wrote:
 > 
 > > I had just about the same problem, with 915 MHz ISA wavelans cards and
 > > no wavepoints.  Running mrouted, which set IFF_ALLMULTI caused unicast
 > > packets with a mac address not matching the local machine to be
 > > forwarded.  My fix is different, and I believe makes bpf work
 > > correctly.
 > > 
 > > The check for dropping unicast packets not sent to our ethernet
 > > address is after the bpf tap, but not conditioned on it.  All packets
 > > received should get handed to bpf, and unicast packets not to us (mac)
 > > should get dropped whether or not there is a bpf listener.  I believe
 > > that the common optimization that the interface is in hw promisc mode
 > > iff there is a bpf listener is in general wrong, but more frequently
 > > so on wavelans.
 > > 
 > > I think Max's fix makes bpf listeners not see unicast packets sent to
 > > others, but I'm not sure.
 > > 
 > > One can argue that checking on MOD_ENAL is wrong, but the code only
 > > drops packets that shouldn't be received.  The correctness condition
 > > is that it be run whenever unicast packets without our mac address can
 > > be received.
 > 
 > 
 
 -- 
 \\  Sometimes you're ahead,       \\  Mike Smith
 \\  sometimes you're behind.      \\  mike@smith.net.au
 \\  The race is long, and in the  \\  msmith@freebsd.org
 \\  end it's only with yourself.  \\  msmith@cdrom.com
 
 
>Unformatted:
