Properly program the multicast filter in ndis_setmulti(),

and fix promisc mode in ndis_ioctl().
This commit is contained in:
Bill Paul 2004-01-19 07:03:46 +00:00
parent 575f4d3239
commit f98f50fcfd
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=124709

View File

@ -172,10 +172,71 @@ static void
ndis_setmulti(sc) ndis_setmulti(sc)
struct ndis_softc *sc; struct ndis_softc *sc;
{ {
#ifdef notyet struct ifnet *ifp;
uint32_t ndis_filter; struct ifmultiaddr *ifma;
int len; int len, mclistsz, error;
#endif uint8_t *mclist;
ifp = &sc->arpcom.ac_if;
if (!(ifp->if_flags & IFF_UP))
return;
if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
len = sizeof(sc->ndis_filter);
error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
&sc->ndis_filter, &len);
if (error)
device_printf (sc->ndis_dev,
"set filter failed: %d\n", error);
return;
}
len = sizeof(mclistsz);
ndis_get_info(sc, OID_802_3_MAXIMUM_LIST_SIZE, &mclistsz, &len);
mclist = malloc(ETHER_ADDR_LEN * mclistsz, M_TEMP, M_NOWAIT);
if (mclist == NULL) {
sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
goto out;
}
sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST;
len = 0;
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
mclist + (ETHER_ADDR_LEN * len), ETHER_ADDR_LEN);
len++;
if (len > mclistsz) {
sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
goto out;
}
}
len = len * ETHER_ADDR_LEN;
error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, mclist, &len);
if (error) {
device_printf (sc->ndis_dev, "set mclist failed: %d\n", error);
sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
}
out:
free(mclist, M_TEMP);
len = sizeof(sc->ndis_filter);
error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
&sc->ndis_filter, &len);
if (error)
device_printf (sc->ndis_dev, "set filter failed: %d\n", error);
return; return;
} }
@ -1149,9 +1210,6 @@ ndis_init(xsc)
struct ndis_softc *sc = xsc; struct ndis_softc *sc = xsc;
struct ifnet *ifp = &sc->arpcom.ac_if; struct ifnet *ifp = &sc->arpcom.ac_if;
int i, error; int i, error;
uint32_t ndis_filter = 0;
/*NDIS_LOCK(sc);*/
/* /*
* Cancel pending I/O and free all RX/TX buffers. * Cancel pending I/O and free all RX/TX buffers.
@ -1161,48 +1219,46 @@ ndis_init(xsc)
ndis_init_nic(sc); ndis_init_nic(sc);
/* Init our MAC address */ /* Init our MAC address */
#ifdef notdef
/*
* Program the multicast filter, if necessary.
*/
ndis_setmulti(sc);
#endif
/* Program the packet filter */ /* Program the packet filter */
ndis_filter = NDIS_PACKET_TYPE_DIRECTED; sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED;
if (ifp->if_flags & IFF_BROADCAST) if (ifp->if_flags & IFF_BROADCAST)
ndis_filter |= NDIS_PACKET_TYPE_BROADCAST; sc->ndis_filter |= NDIS_PACKET_TYPE_BROADCAST;
if (ifp->if_flags & IFF_PROMISC) if (ifp->if_flags & IFF_PROMISC)
ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS; sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
if (ifp->if_flags & IFF_MULTICAST) i = sizeof(sc->ndis_filter);
ndis_filter |= NDIS_PACKET_TYPE_MULTICAST;
i = sizeof(ndis_filter);
error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER, error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
&ndis_filter, &i); &sc->ndis_filter, &i);
sc->ndis_filter = ndis_filter;
if (error) if (error)
device_printf (sc->ndis_dev, "set filter failed: %d\n", error); device_printf (sc->ndis_dev, "set filter failed: %d\n", error);
sc->ndis_txidx = 0; /*
sc->ndis_txpending = sc->ndis_maxpkts; * Program the multicast filter, if necessary.
sc->ndis_link = 0; */
ndis_setmulti(sc);
ndis_enable_intr(sc); ndis_enable_intr(sc);
if (sc->ndis_80211) if (sc->ndis_80211)
ndis_setstate_80211(sc); ndis_setstate_80211(sc);
NDIS_LOCK(sc);
sc->ndis_txidx = 0;
sc->ndis_txpending = sc->ndis_maxpkts;
sc->ndis_link = 0;
ifp->if_flags |= IFF_RUNNING; ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE; ifp->if_flags &= ~IFF_OACTIVE;
NDIS_UNLOCK(sc);
/* /*
* Some drivers don't set this value. The NDIS spec says * Some drivers don't set this value. The NDIS spec says
* the default checkforhang timeout is approximately 2 * the default checkforhang timeout is approximately 2
@ -1215,8 +1271,6 @@ ndis_init(xsc)
sc->ndis_stat_ch = timeout(ndis_tick, sc, sc->ndis_stat_ch = timeout(ndis_tick, sc,
hz * sc->ndis_block.nmb_checkforhangsecs); hz * sc->ndis_block.nmb_checkforhangsecs);
/*NDIS_UNLOCK(sc);*/
return; return;
} }
@ -1665,7 +1719,6 @@ ndis_ioctl(ifp, command, data)
/*NDIS_LOCK(sc);*/ /*NDIS_LOCK(sc);*/
switch(command) { switch(command) {
case SIOCSIFFLAGS: case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) { if (ifp->if_flags & IFF_UP) {
@ -1674,7 +1727,8 @@ ndis_ioctl(ifp, command, data)
!(sc->ndis_if_flags & IFF_PROMISC)) { !(sc->ndis_if_flags & IFF_PROMISC)) {
sc->ndis_filter |= sc->ndis_filter |=
NDIS_PACKET_TYPE_PROMISCUOUS; NDIS_PACKET_TYPE_PROMISCUOUS;
ndis_set_info(sc, i = sizeof(sc->ndis_filter);
error = ndis_set_info(sc,
OID_GEN_CURRENT_PACKET_FILTER, OID_GEN_CURRENT_PACKET_FILTER,
&sc->ndis_filter, &i); &sc->ndis_filter, &i);
} else if (ifp->if_flags & IFF_RUNNING && } else if (ifp->if_flags & IFF_RUNNING &&
@ -1682,7 +1736,8 @@ ndis_ioctl(ifp, command, data)
sc->ndis_if_flags & IFF_PROMISC) { sc->ndis_if_flags & IFF_PROMISC) {
sc->ndis_filter &= sc->ndis_filter &=
~NDIS_PACKET_TYPE_PROMISCUOUS; ~NDIS_PACKET_TYPE_PROMISCUOUS;
ndis_set_info(sc, i = sizeof(sc->ndis_filter);
error = ndis_set_info(sc,
OID_GEN_CURRENT_PACKET_FILTER, OID_GEN_CURRENT_PACKET_FILTER,
&sc->ndis_filter, &i); &sc->ndis_filter, &i);
} else } else