Subject: port-i386/128: promiscuous mode doesn't work with (relatively) new if_ed
To: None <gnats-admin>
From: Havard Eidnes <Havard.Eidnes@runit.sintef.no>
List: netbsd-bugs
Date: 02/12/1994 16:05:02
>Number:         128
>Category:       port-i386
>Synopsis:       promiscuous mode doesn't work in if_ed driver
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    gnats-admin (GNATS administrator)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Feb 12 16:05:01 1994
>Originator:     Havard Eidnes
>Organization:
"SINTEF RUNIT"
>Release:        NetBSD-current
>Environment:
	i486, WD8013EPC
System: NetBSD rype.runit.sintef.no 0.9a RYPE#40 i386

>Description:
	Previously reported as bugid 99, this is a fix.

	Several problems:
	 - promiscuous mode won't be set in driver through BPF ioctls
	 - multicast address filters are fiddled when the wrong page
	   on the ethernet chip is active (the big boo-boo)
	 - the test for "mine?" while in promiscuous mode can now be
	   simplified since multicast is no longer optional
	 - there's no need to test non-nullness of "sc" inside ed_init...
	 - the previous code set "accept runts and packets with CRC errors"
	   when promiscuous mode was enabled.  Runts will produce error
	   messages later in the driver, so that should be removed.  I also
	   fail to see the usefullness in capturing packets with CRC errors,
	   so I removed that flag as well.

>How-To-Repeat:
	Try running tcpdump and see that only packets to or from yourself are
	being seen.  With the proposed fix in problem report 99, watch that
	no packets are being sent (!) nor received when the enclosed fix there
	is implemented.
>Fix:

	The following diffs fix all of the problems mentioned above.

*** if_ed.c.orig	Wed Feb  2 12:16:19 1994
--- if_ed.c	Sun Feb 13 00:52:49 1994
***************
*** 171,174 ****
--- 171,175 ----
  	u_char	rec_page_stop;	/* last page of RX ring-buffer */
  	u_char	next_packet;	/* pointer to next unread RX packet */
+ 	short	old_if_flags;	/* old value of corresponding if_flags */
  } ed_softc[NED];
  
***************
*** 1121,1125 ****
  	struct ed_softc *sc = &ed_softc[unit];
  	struct ifnet *ifp = &sc->arpcom.ac_if;
! 	int i, s;
  	u_char	command;
  
--- 1122,1126 ----
  	struct ed_softc *sc = &ed_softc[unit];
  	struct ifnet *ifp = &sc->arpcom.ac_if;
! 	int i, s, recv_mode;
  	u_char	command;
  
***************
*** 1225,1229 ****
  
  	/* set up multicast addresses and filter modes */
! 	if (sc != 0 && (ifp->if_flags & IFF_MULTICAST) != 0) {
  		u_long mcaf[2];
  
--- 1226,1230 ----
  
  	/* set up multicast addresses and filter modes */
! 	if ((ifp->if_flags & IFF_MULTICAST) != 0) {
  		u_long mcaf[2];
  
***************
*** 1240,1243 ****
--- 1241,1258 ----
  		      outb(sc->nic_addr + ED_P1_MAR0 + i, ((u_char *)mcaf)[i]);
  	}
+ 
+ 	recv_mode = ED_RCR_AB|ED_RCR_AM;
+ 	if ((ifp->if_flags & IFF_PROMISC) != 0) {
+ 		/*
+ 		 * Set promiscuous mode.
+ 		 * Also reconfigure the multicast filter.
+ 		 */
+ 		int j;
+ 
+ 		recv_mode |= ED_RCR_PRO;
+ 		for (j = 0; j < 8; j++)
+ 			outb(sc->nic_addr + ED_P1_MAR0 + j, 0xff);
+ 	}
+ 
  	/*
  	 * Set Current Page pointer to next_packet (initialized above)
***************
*** 1273,1292 ****
  	}
  
! 	i = ED_RCR_AB;
! 	if (sc != 0) {
! 		if ((ifp->if_flags & IFF_PROMISC) != 0) {
! 			/*
! 			 * Set promiscuous mode.
! 			 * Also reconfigure the multicast filter.
! 			 */
! 			int j;
! 
! 			i |= ED_RCR_PRO|ED_RCR_AM|ED_RCR_AR|ED_RCR_SEP;
! 			for (j = 0; j < 8; j++)
! 				outb(sc->nic_addr + ED_P1_MAR0 + j, 0xff);
! 		}
! 		i |= ED_RCR_AM;
! 	}
! 	outb(sc->nic_addr + ED_P0_RCR, i);
  
  	/*
--- 1288,1292 ----
  	}
  
! 	outb(sc->nic_addr + ED_P0_RCR, recv_mode);
  
  	/*
***************
*** 1296,1299 ****
--- 1296,1302 ----
  	ifp->if_flags &= ~IFF_OACTIVE;
  
+ 	/* Remember for next SIOCSIFFLAGS ioctl */
+ 	sc->old_if_flags = ifp->if_flags;
+ 
  	/*
  	 * ...and attempt to start output
***************
*** 1926,1934 ****
  		} else {
  		/*
! 		 * If interface is marked up and it is stopped, then start it
  		 */
  			if ((ifp->if_flags & IFF_UP) &&
! 		    	    ((ifp->if_flags & IFF_RUNNING) == 0))
! 				ed_init(ifp->if_unit);
  		}
  		/*
--- 1929,1942 ----
  		} else {
  		/*
! 		 * If interface is marked up and it is either stopped or some
! 		 * some of the changeable flags changed, then reinitialize it
  		 */
  			if ((ifp->if_flags & IFF_UP) &&
! 		    	    ((ifp->if_flags & IFF_RUNNING) == 0) ||
! 		    	     ((ifp->if_flags & ~IFF_CANTCHANGE) !=
! 		    	      (sc->old_if_flags & ~IFF_CANTCHANGE)))
! 			{
! 			 	ed_reset(ifp->if_unit);
! 			}
  		}
  		/*
***************
*** 1948,1956 ****
  		if (error == ENETRESET) {
  			/*
! 			 * Multicast list has changed; set the hardware filter
! 			 * accordingly.
  			 */
! 			ed_stop(ifp->if_unit); /* XXX for ds_setmcaf? */
! 			ed_init(ifp->if_unit);
  			error = 0;
  		}
--- 1956,1963 ----
  		if (error == ENETRESET) {
  			/*
! 			 * Multicast list has changed; (re)set the hardware
! 			 * filter accordingly.
  			 */
! 			ed_reset(ifp->if_unit);
  			error = 0;
  		}
***************
*** 2084,2094 ****
  		 * there are no BPF listeners.  And if we are in promiscuous
  		 * mode, we have to check if this packet is really ours.
  		 */
  		if ((sc->arpcom.ac_if.if_flags & IFF_PROMISC) &&
! 		    (eh->ether_dhost[0] & 1) == 0 &&
! 		    bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr,
! 			 sizeof(eh->ether_dhost)) != 0 &&
! 		    bcmp(eh->ether_dhost, etherbroadcastaddr,
! 			 sizeof(eh->ether_dhost)) != 0) {
  			m_freem(head);
  			return;
--- 2091,2103 ----
  		 * there are no BPF listeners.  And if we are in promiscuous
  		 * mode, we have to check if this packet is really ours.
+ 		 * It's not for us if it's neither a multicast nor broadcast
+ 		 * (covered by same test) or the destination address is not
+ 		 * our own.
  		 */
  		if ((sc->arpcom.ac_if.if_flags & IFF_PROMISC) &&
! 		    ((eh->ether_dhost[0] & 1) == 0) &&
! 		    (bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr,
! 			 sizeof(eh->ether_dhost)) != 0))
! 		{
  			m_freem(head);
  			return;
>Audit-Trail:
>Unformatted:


------------------------------------------------------------------------------