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

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