Subject: if_ed.c: promiscuous mode doesn't work
To: None <netbsd-bugs@sun-lamp.cs.berkeley.edu>
From: Havard Eidnes <Havard.Eidnes@runit.sintef.no>
List: netbsd-bugs
Date: 01/09/1994 16:44:04
Hi,
after the reshuffling of the ioctl() code for the support of multicast,
turning the interface into promiscuous mode via BPF no longer works. The
entry into ed_ioctl() is via bpf.c:
/*
* Put interface into promiscuous mode.
*/
case BIOCPROMISC:
...
error = ifpromisc(d->bd_bif->bif_ifp, 1);
...
int
ifpromisc(ifp, pswitch)
struct ifnet *ifp;
int pswitch;
{
...
if (pswitch) {
if (ifp->if_pcount++ != 0)
return (0);
ifp->if_flags |= IFF_PROMISC;
} else {
if (--ifp->if_pcount > 0)
return (0);
ifp->if_flags &= ~IFF_PROMISC;
}
ifr.ifr_flags = ifp->if_flags;
return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
}
and that turns into a call to ed_ioctl(), but now the flipping of the
hardware flags happen in ed_init(), and the call to ed_init() under
SIOCSIFFLAGS is now conditional, so that promiscuous mode isn't being
turned on in the hardware when the interface is already started:
int
ed_ioctl(ifp, command, data)
register struct ifnet *ifp;
int command;
caddr_t data;
{
...
case SIOCSIFFLAGS:
/*
* If interface is marked down and it is running, then stop it
*/
if (((ifp->if_flags & IFF_UP) == 0) &&
(ifp->if_flags & IFF_RUNNING)) {
ed_stop(ifp->if_unit);
ifp->if_flags &= ~IFF_RUNNING;
} 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);
}
/*
* NB: There was a bunch of code here that's now in ed_init.
*/
break;
It may seem that the call to ed_init() needs to be unconditional in the
second branch above. However, that may prove to be undesireable, as it
introduces a (short) time period when the interface is effectively dead.
- Havard
------------------------------------------------------------------------------