From 19e2ac904f46e8d37d7cd3d2b1186258b4e8f73b Mon Sep 17 00:00:00 2001 From: wollman Date: Mon, 13 Jan 1997 21:26:53 +0000 Subject: Use the new if_multiaddrs list for multicast addresses rather than the previous hackery involving struct in_ifaddr and arpcom. Get rid of the abominable multi_kludge. Update all network interfaces to use the new machanism. Distressingly few Ethernet drivers program the multicast filter properly (assuming the hardware has one, which it usually does). --- sys/dev/de/if_de.c | 110 ++++++++++++-------------- sys/dev/ed/if_ed.c | 39 +++------ sys/dev/fe/if_fe.c | 45 ++++------- sys/dev/fxp/if_fxp.c | 20 ++--- sys/dev/ie/if_ie.c | 44 +++++------ sys/dev/lnc/if_lnc.c | 33 ++------ sys/dev/vx/if_vx.c | 24 +++--- sys/i386/isa/if_ed.c | 39 +++------ sys/i386/isa/if_fe.c | 45 ++++------- sys/i386/isa/if_ie.c | 44 +++++------ sys/i386/isa/if_le.c | 45 +++-------- sys/i386/isa/if_lnc.c | 33 ++------ sys/net/if.c | 31 ++++++-- sys/net/if.h | 15 +++- sys/net/if_ethersubr.c | 184 +----------------------------------------- sys/net/route.h | 8 +- sys/net/rtsock.c | 41 +++++++++- sys/netinet/if_ether.h | 74 +---------------- sys/netinet/in.c | 206 ++++++++++++------------------------------------ sys/netinet/in_var.h | 56 ++++++------- sys/netinet/ip_mroute.c | 10 +-- sys/pci/if_de.c | 110 ++++++++++++-------------- sys/pci/if_fxp.c | 20 ++--- sys/pci/if_pdq.c | 48 ++++++----- 24 files changed, 428 insertions(+), 896 deletions(-) (limited to 'sys') diff --git a/sys/dev/de/if_de.c b/sys/dev/de/if_de.c index c5d7f5a..95bc095 100644 --- a/sys/dev/de/if_de.c +++ b/sys/dev/de/if_de.c @@ -21,7 +21,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: if_de.c,v 1.55 1996/11/10 13:36:46 davidg Exp $ + * $Id: if_de.c,v 1.56 1996/12/01 06:01:00 rgrimes Exp $ * */ @@ -3287,62 +3287,63 @@ tulip_addr_filter( tulip_softc_t * const sc) { u_int32_t *sp = sc->tulip_setupdata; - struct ether_multistep step; - struct ether_multi *enm; + struct ifmultiaddr *ifma; int i = 0; + u_char *addrp; + unsigned hash; + + ifma = sc->tulip_if.if_multiaddrs.lh_first; sc->tulip_flags &= ~TULIP_WANTHASH; sc->tulip_flags |= TULIP_WANTSETUP; sc->tulip_cmdmode &= ~TULIP_CMD_RXRUN; sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED; - if (sc->tulip_ac.ac_multicnt > 14) { - unsigned hash; - /* - * If we have more than 14 multicasts, we have - * go into hash perfect mode (512 bit multicast - * hash and one perfect hardware). - */ - bzero(sc->tulip_setupdata, sizeof(sc->tulip_setupdata)); - hash = tulip_mchash(etherbroadcastaddr); - sp[hash >> 4] |= 1 << (hash & 0xF); - ETHER_FIRST_MULTI(step, &sc->tulip_ac, enm); - while (enm != NULL) { - hash = tulip_mchash(enm->enm_addrlo); - sp[hash >> 4] |= 1 << (hash & 0xF); - ETHER_NEXT_MULTI(step, enm); - } - sc->tulip_flags |= TULIP_WANTHASH; - sp[39] = ((u_int16_t *) sc->tulip_ac.ac_enaddr)[0]; - sp[40] = ((u_int16_t *) sc->tulip_ac.ac_enaddr)[1]; - sp[41] = ((u_int16_t *) sc->tulip_ac.ac_enaddr)[2]; - } else { - /* - * Else can get perfect filtering for 16 addresses. - */ - ETHER_FIRST_MULTI(step, &sc->tulip_ac, enm); - for (; enm != NULL; i++) { - *sp++ = ((u_int16_t *) enm->enm_addrlo)[0]; - *sp++ = ((u_int16_t *) enm->enm_addrlo)[1]; - *sp++ = ((u_int16_t *) enm->enm_addrlo)[2]; - ETHER_NEXT_MULTI(step, enm); - } - /* - * Add the broadcast address. - */ - i++; - *sp++ = 0xFFFF; - *sp++ = 0xFFFF; - *sp++ = 0xFFFF; - /* - * Pad the rest with our hardware address - */ - for (; i < 16; i++) { + for (ifma = sc->tulip_if.if_multiaddrs.lh_first; ifma; + ifma = ifma->ifma_link.le_next) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + if (i > 14) + goto musthash; + addrp = LLADDR((struct sockaddr_dl *)ifma->ifma_addr); + *sp++ = ((u_int16_t *) addrp)[0]; + *sp++ = ((u_int16_t *) addrp)[1]; + *sp++ = ((u_int16_t *) addrp)[2]; + i++; + } + /* + * Add the broadcast address. + */ + i++; + *sp++ = 0xFFFF; + *sp++ = 0xFFFF; + *sp++ = 0xFFFF; + /* + * Pad the rest with our hardware address + */ + for (; i < 16; i++) { *sp++ = ((u_int16_t *) sc->tulip_ac.ac_enaddr)[0]; *sp++ = ((u_int16_t *) sc->tulip_ac.ac_enaddr)[1]; *sp++ = ((u_int16_t *) sc->tulip_ac.ac_enaddr)[2]; - } } + return; + +musthash: + bzero(sc->tulip_setupdata, sizeof(sc->tulip_setupdata)); + hash = tulip_mchash(etherbroadcastaddr); + sp[hash >> 4] |= 1 << (hash & 0xF); + for (ifma = sc->tulip_if.if_multiaddrs.lh_first; ifma; + ifma = ifma->ifma_link.le_next) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + + hash = tulip_mchash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); + sp[hash >> 4] |= 1 << (hash & 0xF); + } + sc->tulip_flags |= TULIP_WANTHASH; + sp[39] = ((u_int16_t *) sc->tulip_ac.ac_enaddr)[0]; + sp[40] = ((u_int16_t *) sc->tulip_ac.ac_enaddr)[1]; + sp[41] = ((u_int16_t *) sc->tulip_ac.ac_enaddr)[2]; } /* @@ -3395,22 +3396,15 @@ tulip_ifioctl( } case SIOCADDMULTI: - case SIOCDELMULTI: { + case SIOCDELMULTI: /* * Update multicast listeners */ - if (cmd == SIOCADDMULTI) - error = ether_addmulti(ifr, &sc->tulip_ac); - else - error = ether_delmulti(ifr, &sc->tulip_ac); - - if (error == ENETRESET) { - tulip_addr_filter(sc); /* reset multicast filtering */ - tulip_init(sc); - error = 0; - } + tulip_addr_filter(sc); /* reset multicast filtering */ + tulip_init(sc); + error = 0; break; - } + #if defined(SIOCSIFMTU) #if !defined(ifr_mtu) #define ifr_mtu ifr_metric diff --git a/sys/dev/ed/if_ed.c b/sys/dev/ed/if_ed.c index 95a4859..e0b59b4 100644 --- a/sys/dev/ed/if_ed.c +++ b/sys/dev/ed/if_ed.c @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_ed.c,v 1.110 1996/12/10 07:29:39 davidg Exp $ + * $Id: if_ed.c,v 1.111 1996/12/13 21:28:19 wollman Exp $ */ /* @@ -2673,21 +2673,11 @@ ed_ioctl(ifp, command, data) case SIOCADDMULTI: case SIOCDELMULTI: /* - * Update out multicast list. + * Multicast list has changed; set the hardware filter + * accordingly. */ - error = (command == SIOCADDMULTI) ? - ether_addmulti(ifr, &sc->arpcom) : - ether_delmulti(ifr, &sc->arpcom); - - if (error == ENETRESET) { - - /* - * Multicast list has changed; set the hardware filter - * accordingly. - */ - ed_setrcr(sc); - error = 0; - } + ed_setrcr(sc); + error = 0; break; default: @@ -3420,22 +3410,17 @@ ds_getmcaf(sc, mcaf) { register u_int index; register u_char *af = (u_char *) mcaf; - register struct ether_multi *enm; - register struct ether_multistep step; + struct ifmultiaddr *ifma; mcaf[0] = 0; mcaf[1] = 0; - ETHER_FIRST_MULTI(step, &sc->arpcom, enm); - while (enm != NULL) { - if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) { - mcaf[0] = 0xffffffff; - mcaf[1] = 0xffffffff; - return; - } - index = ds_crc(enm->enm_addrlo) >> 26; + for (ifma = sc->arpcom.ac_if.if_multiaddrs.lh_first; ifma; + ifma = ifma->ifma_link.le_next) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + index = ds_crc(LLADDR((struct sockaddr_dl *)ifma->ifma_addr)) + >> 26; af[index >> 3] |= 1 << (index & 7); - - ETHER_NEXT_MULTI(step, enm); } } diff --git a/sys/dev/fe/if_fe.c b/sys/dev/fe/if_fe.c index 9c2cf8e..c714734 100644 --- a/sys/dev/fe/if_fe.c +++ b/sys/dev/fe/if_fe.c @@ -21,7 +21,7 @@ */ /* - * $Id: if_fe.c,v 1.21 1996/11/15 16:15:56 wollman Exp $ + * $Id: if_fe.c,v 1.22 1996/12/13 21:28:22 wollman Exp $ * * Device driver for Fujitsu MB86960A/MB86965A based Ethernet cards. * To be used with FreeBSD 2.x @@ -2623,27 +2623,13 @@ fe_ioctl ( struct ifnet * ifp, int command, caddr_t data ) #ifdef SIOCADDMULTI case SIOCADDMULTI: case SIOCDELMULTI: - { - /* - * Update out multicast list. - */ - struct ifreq * ifr = ( struct ifreq * )data; - - error = ( command == SIOCADDMULTI ) - ? ether_addmulti( ifr, &sc->arpcom ) - : ether_delmulti( ifr, &sc->arpcom ); - - if ( error == ENETRESET ) { - /* - * Multicast list has changed; set the hardware filter - * accordingly. - */ - fe_setmode( sc ); - error = 0; - } - - break; - } + /* + * Multicast list has changed; set the hardware filter + * accordingly. + */ + fe_setmode( sc ); + error = 0; + break; #endif #ifdef SIOCSIFMTU @@ -2955,23 +2941,20 @@ fe_mcaf ( struct fe_softc *sc ) { int index; struct fe_filter filter; - struct ether_multi *enm; - struct ether_multistep step; + struct ifmultiaddr *ifma; filter = fe_filter_nothing; - ETHER_FIRST_MULTI(step, &sc->arpcom, enm); - while ( enm != NULL) { - if ( bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN) ) { - return ( fe_filter_all ); - } - index = fe_hash( enm->enm_addrlo ); + for (ifma = sc->arpcom.ac_if.if_multiaddrs.lh_first; ifma; + ifma = ifma->ifma_link.le_next) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + index = fe_hash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); #if FE_DEBUG >= 4 log( LOG_INFO, "fe%d: hash(%6D) == %d\n", sc->sc_unit, enm->enm_addrlo , ":", index ); #endif filter.data[index >> 3] |= 1 << (index & 7); - ETHER_NEXT_MULTI(step, enm); } return ( filter ); } diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c index 61cb065..eed4623 100644 --- a/sys/dev/fxp/if_fxp.c +++ b/sys/dev/fxp/if_fxp.c @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_fxp.c,v 1.22 1996/11/18 02:45:46 davidg Exp $ + * $Id: if_fxp.c,v 1.23 1996/12/10 07:29:50 davidg Exp $ */ /* @@ -1055,21 +1055,11 @@ fxp_ioctl(ifp, command, data) case SIOCADDMULTI: case SIOCDELMULTI: /* - * Update out multicast list. + * Multicast list has changed; set the hardware filter + * accordingly. */ - error = (command == SIOCADDMULTI) ? - ether_addmulti(ifr, &sc->arpcom) : - ether_delmulti(ifr, &sc->arpcom); - - if (error == ENETRESET) { - /* - * Multicast list has changed; set the hardware filter - * accordingly. - */ - fxp_init(sc); - - error = 0; - } + fxp_init(sc); + error = 0; break; default: diff --git a/sys/dev/ie/if_ie.c b/sys/dev/ie/if_ie.c index 4c8cf8d..6795bf1 100644 --- a/sys/dev/ie/if_ie.c +++ b/sys/dev/ie/if_ie.c @@ -43,7 +43,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_ie.c,v 1.35 1996/06/25 20:30:13 bde Exp $ + * $Id: if_ie.c,v 1.36 1996/09/06 23:07:36 phk Exp $ */ /* @@ -1932,15 +1932,9 @@ ieioctl(ifp, command, data) /* * Update multicast listeners */ - error = ((command == SIOCADDMULTI) - ? ether_addmulti(ifr, &ie->arpcom) - : ether_delmulti(ifr, &ie->arpcom)); - - if(error == ENETRESET) { - /* reset multicast filtering */ - ie_mc_reset(ifp->if_unit); - error = 0; - } + /* reset multicast filtering */ + ie_mc_reset(ifp->if_unit); + error = 0; break; case SIOCSIFMTU: @@ -1964,25 +1958,27 @@ ieioctl(ifp, command, data) static void ie_mc_reset(int unit) { struct ie_softc *ie = &ie_softc[unit]; - struct ether_multi *enm; - struct ether_multistep step; + struct ifmultiaddr *ifma; /* * Step through the list of addresses. */ ie->mcast_count = 0; - ETHER_FIRST_MULTI(step, &ie->arpcom, enm); - while(enm) { - if(ie->mcast_count >= MAXMCAST - || bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) { - ie->arpcom.ac_if.if_flags |= IFF_ALLMULTI; - ieioctl(&ie->arpcom.ac_if, SIOCSIFFLAGS, (void *)0); - goto setflag; - } - - bcopy(enm->enm_addrlo, &(ie->mcast_addrs[ie->mcast_count]), 6); - ie->mcast_count++; - ETHER_NEXT_MULTI(step, enm); + for (ifma = ie->arpcom.ac_if.if_multiaddrs.lh_first; ifma; + ifma = ifma->ifma_link.le_next) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + + /* XXX - this is broken... */ + if(ie->mcast_count >= MAXMCAST) { + ie->arpcom.ac_if.if_flags |= IFF_ALLMULTI; + ieioctl(&ie->arpcom.ac_if, SIOCSIFFLAGS, (void *)0); + goto setflag; + } + + bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), + &(ie->mcast_addrs[ie->mcast_count]), 6); + ie->mcast_count++; } setflag: diff --git a/sys/dev/lnc/if_lnc.c b/sys/dev/lnc/if_lnc.c index 0df6bbe..51d77b1 100644 --- a/sys/dev/lnc/if_lnc.c +++ b/sys/dev/lnc/if_lnc.c @@ -226,8 +226,7 @@ static void lnc_setladrf(struct lnc_softc *sc) { struct ifnet *ifp = &sc->arpcom.ac_if; - struct ether_multistep step; - struct ether_multi *enm; + struct ifmultiaddr *ifma; u_long index; int i; @@ -247,24 +246,12 @@ lnc_setladrf(struct lnc_softc *sc) */ bzero(sc->init_block->ladrf, MULTICAST_FILTER_LEN); - ETHER_FIRST_MULTI(step, &sc->arpcom, enm); - while (enm != NULL) { - if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN) != 0) { - /* - * A range of multicast addresses should be accepted but - * but for now just accept all multicasts. Only currently - * used by multicast routing where the range would require - * all bits to be set anyway. - */ - ifp->if_flags |= IFF_ALLMULTI; - for (i = 0; i < MULTICAST_FILTER_LEN; i++) - sc->init_block->ladrf[i] = 0xff; - return; - } - + for (ifma = ifp->if_multiaddrs.lh_first; ifma; + ifma = ifma->ifma_link.le_next) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; index = ether_crc(enm->enm_addrlo) >> 26; sc->init_block->ladrf[index >> 3] |= 1 << (index & 7); - ETHER_NEXT_MULTI(step, enm); } } #endif /* LNC_MULTICAST */ @@ -1735,14 +1722,8 @@ lnc_ioctl(struct ifnet * ifp, int command, caddr_t data) #ifdef LNC_MULTICAST case SIOCADDMULTI: case SIOCDELMULTI: - error = (command == SIOCADDMULTI) ? - ether_addmulti(ifr, &sc->arpcom) : - ether_delmulti(ifr, &sc->arpcom); - - if (error == ENETRESET) { - lnc_setladrf(sc); - error = 0; - } + lnc_setladrf(sc); + error = 0; break; #endif case SIOCSIFMTU: diff --git a/sys/dev/vx/if_vx.c b/sys/dev/vx/if_vx.c index 6125ff8..a4a29cd 100644 --- a/sys/dev/vx/if_vx.c +++ b/sys/dev/vx/if_vx.c @@ -311,11 +311,11 @@ vxsetfilter(sc) struct vx_softc *sc; { register struct ifnet *ifp = &sc->arpcom.ac_if; - + GO_WINDOW(1); /* Window 1 is operating window */ outw(BASE + VX_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | FIL_BRDCST | - ((sc->arpcom.ac_multicnt > 0) ? FIL_MULTICAST : 0 ) | - ((ifp->if_flags & IFF_PROMISC) ? FIL_PROMISC : 0 )); + FIL_MULTICAST | + ((ifp->if_flags & IFF_PROMISC) ? FIL_PROMISC : 0 )); } static void @@ -967,18 +967,12 @@ vxioctl(ifp, cmd, data) case SIOCADDMULTI: case SIOCDELMULTI: - error = ((u_int) cmd == SIOCADDMULTI) ? - ether_addmulti(ifr, &sc->arpcom) : - ether_delmulti(ifr, &sc->arpcom); - - if (error == ENETRESET) { - /* - * Multicast list has changed; set the hardware filter - * accordingly. - */ - vxreset(sc); - error = 0; - } + /* + * Multicast list has changed; set the hardware filter + * accordingly. + */ + vxreset(sc); + error = 0; break; diff --git a/sys/i386/isa/if_ed.c b/sys/i386/isa/if_ed.c index 95a4859..e0b59b4 100644 --- a/sys/i386/isa/if_ed.c +++ b/sys/i386/isa/if_ed.c @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_ed.c,v 1.110 1996/12/10 07:29:39 davidg Exp $ + * $Id: if_ed.c,v 1.111 1996/12/13 21:28:19 wollman Exp $ */ /* @@ -2673,21 +2673,11 @@ ed_ioctl(ifp, command, data) case SIOCADDMULTI: case SIOCDELMULTI: /* - * Update out multicast list. + * Multicast list has changed; set the hardware filter + * accordingly. */ - error = (command == SIOCADDMULTI) ? - ether_addmulti(ifr, &sc->arpcom) : - ether_delmulti(ifr, &sc->arpcom); - - if (error == ENETRESET) { - - /* - * Multicast list has changed; set the hardware filter - * accordingly. - */ - ed_setrcr(sc); - error = 0; - } + ed_setrcr(sc); + error = 0; break; default: @@ -3420,22 +3410,17 @@ ds_getmcaf(sc, mcaf) { register u_int index; register u_char *af = (u_char *) mcaf; - register struct ether_multi *enm; - register struct ether_multistep step; + struct ifmultiaddr *ifma; mcaf[0] = 0; mcaf[1] = 0; - ETHER_FIRST_MULTI(step, &sc->arpcom, enm); - while (enm != NULL) { - if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) { - mcaf[0] = 0xffffffff; - mcaf[1] = 0xffffffff; - return; - } - index = ds_crc(enm->enm_addrlo) >> 26; + for (ifma = sc->arpcom.ac_if.if_multiaddrs.lh_first; ifma; + ifma = ifma->ifma_link.le_next) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + index = ds_crc(LLADDR((struct sockaddr_dl *)ifma->ifma_addr)) + >> 26; af[index >> 3] |= 1 << (index & 7); - - ETHER_NEXT_MULTI(step, enm); } } diff --git a/sys/i386/isa/if_fe.c b/sys/i386/isa/if_fe.c index 9c2cf8e..c714734 100644 --- a/sys/i386/isa/if_fe.c +++ b/sys/i386/isa/if_fe.c @@ -21,7 +21,7 @@ */ /* - * $Id: if_fe.c,v 1.21 1996/11/15 16:15:56 wollman Exp $ + * $Id: if_fe.c,v 1.22 1996/12/13 21:28:22 wollman Exp $ * * Device driver for Fujitsu MB86960A/MB86965A based Ethernet cards. * To be used with FreeBSD 2.x @@ -2623,27 +2623,13 @@ fe_ioctl ( struct ifnet * ifp, int command, caddr_t data ) #ifdef SIOCADDMULTI case SIOCADDMULTI: case SIOCDELMULTI: - { - /* - * Update out multicast list. - */ - struct ifreq * ifr = ( struct ifreq * )data; - - error = ( command == SIOCADDMULTI ) - ? ether_addmulti( ifr, &sc->arpcom ) - : ether_delmulti( ifr, &sc->arpcom ); - - if ( error == ENETRESET ) { - /* - * Multicast list has changed; set the hardware filter - * accordingly. - */ - fe_setmode( sc ); - error = 0; - } - - break; - } + /* + * Multicast list has changed; set the hardware filter + * accordingly. + */ + fe_setmode( sc ); + error = 0; + break; #endif #ifdef SIOCSIFMTU @@ -2955,23 +2941,20 @@ fe_mcaf ( struct fe_softc *sc ) { int index; struct fe_filter filter; - struct ether_multi *enm; - struct ether_multistep step; + struct ifmultiaddr *ifma; filter = fe_filter_nothing; - ETHER_FIRST_MULTI(step, &sc->arpcom, enm); - while ( enm != NULL) { - if ( bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN) ) { - return ( fe_filter_all ); - } - index = fe_hash( enm->enm_addrlo ); + for (ifma = sc->arpcom.ac_if.if_multiaddrs.lh_first; ifma; + ifma = ifma->ifma_link.le_next) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + index = fe_hash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); #if FE_DEBUG >= 4 log( LOG_INFO, "fe%d: hash(%6D) == %d\n", sc->sc_unit, enm->enm_addrlo , ":", index ); #endif filter.data[index >> 3] |= 1 << (index & 7); - ETHER_NEXT_MULTI(step, enm); } return ( filter ); } diff --git a/sys/i386/isa/if_ie.c b/sys/i386/isa/if_ie.c index 4c8cf8d..6795bf1 100644 --- a/sys/i386/isa/if_ie.c +++ b/sys/i386/isa/if_ie.c @@ -43,7 +43,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_ie.c,v 1.35 1996/06/25 20:30:13 bde Exp $ + * $Id: if_ie.c,v 1.36 1996/09/06 23:07:36 phk Exp $ */ /* @@ -1932,15 +1932,9 @@ ieioctl(ifp, command, data) /* * Update multicast listeners */ - error = ((command == SIOCADDMULTI) - ? ether_addmulti(ifr, &ie->arpcom) - : ether_delmulti(ifr, &ie->arpcom)); - - if(error == ENETRESET) { - /* reset multicast filtering */ - ie_mc_reset(ifp->if_unit); - error = 0; - } + /* reset multicast filtering */ + ie_mc_reset(ifp->if_unit); + error = 0; break; case SIOCSIFMTU: @@ -1964,25 +1958,27 @@ ieioctl(ifp, command, data) static void ie_mc_reset(int unit) { struct ie_softc *ie = &ie_softc[unit]; - struct ether_multi *enm; - struct ether_multistep step; + struct ifmultiaddr *ifma; /* * Step through the list of addresses. */ ie->mcast_count = 0; - ETHER_FIRST_MULTI(step, &ie->arpcom, enm); - while(enm) { - if(ie->mcast_count >= MAXMCAST - || bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) { - ie->arpcom.ac_if.if_flags |= IFF_ALLMULTI; - ieioctl(&ie->arpcom.ac_if, SIOCSIFFLAGS, (void *)0); - goto setflag; - } - - bcopy(enm->enm_addrlo, &(ie->mcast_addrs[ie->mcast_count]), 6); - ie->mcast_count++; - ETHER_NEXT_MULTI(step, enm); + for (ifma = ie->arpcom.ac_if.if_multiaddrs.lh_first; ifma; + ifma = ifma->ifma_link.le_next) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + + /* XXX - this is broken... */ + if(ie->mcast_count >= MAXMCAST) { + ie->arpcom.ac_if.if_flags |= IFF_ALLMULTI; + ieioctl(&ie->arpcom.ac_if, SIOCSIFFLAGS, (void *)0); + goto setflag; + } + + bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), + &(ie->mcast_addrs[ie->mcast_count]), 6); + ie->mcast_count++; } setflag: diff --git a/sys/i386/isa/if_le.c b/sys/i386/isa/if_le.c index ccad397..91946d1 100644 --- a/sys/i386/isa/if_le.c +++ b/sys/i386/isa/if_le.c @@ -21,7 +21,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: if_le.c,v 1.33 1996/06/18 01:22:23 bde Exp $ + * $Id: if_le.c,v 1.34 1996/09/06 23:07:40 phk Exp $ */ /* @@ -590,22 +590,13 @@ le_ioctl( } case SIOCADDMULTI: - case SIOCDELMULTI: { + case SIOCDELMULTI: /* * Update multicast listeners */ - if (cmd == SIOCADDMULTI) - error = ether_addmulti((struct ifreq *)data, &sc->le_ac); - else - error = ether_delmulti((struct ifreq *)data, &sc->le_ac); - - if (error == ENETRESET) { - /* reset multicast filtering */ (*sc->if_init)(ifp->if_unit); error = 0; - } - break; - } + break; default: { error = EINVAL; @@ -682,11 +673,7 @@ static void le_multi_filter( le_softc_t *sc) { - struct ether_multistep step; - struct ether_multi *enm; -#ifdef ISO - extern char all_es_snpa[]; -#endif + struct ifmultiaddr *ifma; MEMSET(sc->le_mctbl, 0, (sc->le_mcmask + 1) / 8); @@ -699,23 +686,17 @@ le_multi_filter( le_multi_op(sc, etherbroadcastaddr, TRUE); sc->le_flags |= LE_BRDCSTONLY|IFF_MULTICAST; /* } */ -#ifdef ISO - le_multi_op(sc, all_es_snpa, TRUE); -#endif - ETHER_FIRST_MULTI(step, &sc->le_ac, enm); - if (enm != NULL) - sc->le_flags |= IFF_MULTICAST; - while (enm != NULL) { - if (MEMCMP(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) { - sc->le_flags |= IFF_ALLMULTI; - return; - } - le_multi_op(sc, enm->enm_addrlo, TRUE); - ETHER_NEXT_MULTI(step, enm); - sc->le_flags &= ~LE_BRDCSTONLY; + sc->le_flags |= IFF_MULTICAST; + + for (ifma = sc->le_ac.ac_if.if_multiaddrs.lh_first; ifma; + ifma = ifma->ifma_link.le_next) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + + le_multi_op(sc, LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 1); + sc->le_flags &= ~LE_BRDCSTONLY; } - sc->le_flags &= ~IFF_ALLMULTI; } static void diff --git a/sys/i386/isa/if_lnc.c b/sys/i386/isa/if_lnc.c index 0df6bbe..51d77b1 100644 --- a/sys/i386/isa/if_lnc.c +++ b/sys/i386/isa/if_lnc.c @@ -226,8 +226,7 @@ static void lnc_setladrf(struct lnc_softc *sc) { struct ifnet *ifp = &sc->arpcom.ac_if; - struct ether_multistep step; - struct ether_multi *enm; + struct ifmultiaddr *ifma; u_long index; int i; @@ -247,24 +246,12 @@ lnc_setladrf(struct lnc_softc *sc) */ bzero(sc->init_block->ladrf, MULTICAST_FILTER_LEN); - ETHER_FIRST_MULTI(step, &sc->arpcom, enm); - while (enm != NULL) { - if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN) != 0) { - /* - * A range of multicast addresses should be accepted but - * but for now just accept all multicasts. Only currently - * used by multicast routing where the range would require - * all bits to be set anyway. - */ - ifp->if_flags |= IFF_ALLMULTI; - for (i = 0; i < MULTICAST_FILTER_LEN; i++) - sc->init_block->ladrf[i] = 0xff; - return; - } - + for (ifma = ifp->if_multiaddrs.lh_first; ifma; + ifma = ifma->ifma_link.le_next) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; index = ether_crc(enm->enm_addrlo) >> 26; sc->init_block->ladrf[index >> 3] |= 1 << (index & 7); - ETHER_NEXT_MULTI(step, enm); } } #endif /* LNC_MULTICAST */ @@ -1735,14 +1722,8 @@ lnc_ioctl(struct ifnet * ifp, int command, caddr_t data) #ifdef LNC_MULTICAST case SIOCADDMULTI: case SIOCDELMULTI: - error = (command == SIOCADDMULTI) ? - ether_addmulti(ifr, &sc->arpcom) : - ether_delmulti(ifr, &sc->arpcom); - - if (error == ENETRESET) { - lnc_setladrf(sc); - error = 0; - } + lnc_setladrf(sc); + error = 0; break; #endif case SIOCSIFMTU: diff --git a/sys/net/if.c b/sys/net/if.c index b382d48..29e7aca 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -576,12 +576,24 @@ ifioctl(so, cmd, data, p) error = suser(p->p_ucred, &p->p_acflag); if (error) return (error); - if (ifp->if_ioctl == NULL) - return (EOPNOTSUPP); - error = (*ifp->if_ioctl)(ifp, cmd, data); - if (error == 0 ) - microtime(&ifp->if_lastchange); - return(error); + + /* Don't allow group membership on non-multicast interfaces. */ + if ((ifp->if_flags & IFF_MULTICAST) == 0) + return EOPNOTSUPP; + + /* Don't let users screw up protocols' entries. */ + if (ifr->ifr_addr.sa_family != AF_LINK) + return EINVAL; + + if (cmd == SIOCADDMULTI) { + struct ifmultiaddr *ifma; + error = if_addmulti(ifp, &ifr->ifr_addr, &ifma); + } else { + error = if_delmulti(ifp, &ifr->ifr_addr); + } + if (error == 0) + microtime(&ifp->if_lastchange); + return error; default: if (so->so_proto == 0) @@ -835,6 +847,7 @@ if_addmulti(ifp, sa, retifma) ifma->ifma_ifp = ifp; ifma->ifma_refcount = 1; ifma->ifma_protospec = 0; + rt_newmaddrmsg(RTM_NEWMADDR, ifma); /* * Some network interfaces can scan the address list at @@ -856,7 +869,10 @@ if_addmulti(ifp, sa, retifma) } else { MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma, M_IFMADDR, M_WAITOK); - ifma->ifma_addr = llsa; + MALLOC(dupsa, struct sockaddr *, llsa->sa_len, + M_IFMADDR, M_WAITOK); + bcopy(llsa, dupsa, llsa->sa_len); + ifma->ifma_addr = dupsa; ifma->ifma_ifp = ifp; ifma->ifma_refcount = 1; } @@ -899,6 +915,7 @@ if_delmulti(ifp, sa) return 0; } + rt_newmaddrmsg(RTM_DELMADDR, ifma); sa = ifma->ifma_lladdr; s = splimp(); LIST_REMOVE(ifma, ifma_link); diff --git a/sys/net/if.h b/sys/net/if.h index 86e4384..4160868 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)if.h 8.1 (Berkeley) 6/10/93 - * $Id: if.h,v 1.41 1996/12/13 21:28:37 wollman Exp $ + * $Id: if.h,v 1.42 1997/01/03 19:50:25 wollman Exp $ */ #ifndef _NET_IF_H_ @@ -124,6 +124,19 @@ struct ifa_msghdr { }; /* + * Message format for use in obtaining information about multicast addresses + * from the routing socket + */ +struct ifma_msghdr { + u_short ifmam_msglen; /* to skip over non-understood messages */ + u_char ifmam_version; /* future binary compatability */ + u_char ifmam_type; /* message type */ + int ifmam_addrs; /* like rtm_addrs */ + int ifmam_flags; /* value of ifa_flags */ + u_short ifmam_index; /* index for associated ifp */ +}; + +/* * Interface request structure used for socket * ioctl's. All interface ioctl's must have parameter * definitions which begin with ifr_name. The diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 38d4911..2dcfde4 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93 - * $Id: if_ethersubr.c,v 1.29 1996/12/13 21:28:38 wollman Exp $ + * $Id: if_ethersubr.c,v 1.30 1997/01/07 19:15:30 wollman Exp $ */ #include @@ -667,188 +667,6 @@ ether_ifattach(ifp) bcopy(((struct arpcom *)ifp)->ac_enaddr, LLADDR(sdl), ifp->if_addrlen); } -static u_char ether_ipmulticast_min[6] = - { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; -static u_char ether_ipmulticast_max[6] = - { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff }; -/* - * Add an Ethernet multicast address or range of addresses to the list for a - * given interface. - */ -int -ether_addmulti(ifr, ac) - struct ifreq *ifr; - register struct arpcom *ac; -{ - register struct ether_multi *enm; - struct sockaddr_in *sin; - u_char addrlo[6]; - u_char addrhi[6]; - int set_allmulti = 0; - int s = splimp(); - - switch (ifr->ifr_addr.sa_family) { - - case AF_UNSPEC: - bcopy(ifr->ifr_addr.sa_data, addrlo, 6); - bcopy(addrlo, addrhi, 6); - break; - -#ifdef INET - case AF_INET: - sin = (struct sockaddr_in *)&(ifr->ifr_addr); - if (sin->sin_addr.s_addr == INADDR_ANY) { - /* - * An IP address of INADDR_ANY means listen to all - * of the Ethernet multicast addresses used for IP. - * (This is for the sake of IP multicast routers.) - */ - bcopy(ether_ipmulticast_min, addrlo, 6); - bcopy(ether_ipmulticast_max, addrhi, 6); - set_allmulti = 1; - } - else { - ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); - bcopy(addrlo, addrhi, 6); - } - break; -#endif - - default: - splx(s); - return (EAFNOSUPPORT); - } - - /* - * Verify that we have valid Ethernet multicast addresses. - */ - if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) { - splx(s); - return (EINVAL); - } - /* - * See if the address range is already in the list. - */ - ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); - if (enm != NULL) { - /* - * Found it; just increment the reference count. - */ - ++enm->enm_refcount; - splx(s); - return (0); - } - /* - * New address or range; malloc a new multicast record - * and link it into the interface's multicast list. - */ - enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT); - if (enm == NULL) { - splx(s); - return (ENOBUFS); - } - bcopy(addrlo, enm->enm_addrlo, 6); - bcopy(addrhi, enm->enm_addrhi, 6); - enm->enm_ac = ac; - enm->enm_refcount = 1; - enm->enm_next = ac->ac_multiaddrs; - ac->ac_multiaddrs = enm; - ac->ac_multicnt++; - splx(s); - if (set_allmulti) - ac->ac_if.if_flags |= IFF_ALLMULTI; - - /* - * Return ENETRESET to inform the driver that the list has changed - * and its reception filter should be adjusted accordingly. - */ - return (ENETRESET); -} - -/* - * Delete a multicast address record. - */ -int -ether_delmulti(ifr, ac) - struct ifreq *ifr; - register struct arpcom *ac; -{ - register struct ether_multi *enm; - register struct ether_multi **p; - struct sockaddr_in *sin; - u_char addrlo[6]; - u_char addrhi[6]; - int unset_allmulti = 0; - int s = splimp(); - - switch (ifr->ifr_addr.sa_family) { - - case AF_UNSPEC: - bcopy(ifr->ifr_addr.sa_data, addrlo, 6); - bcopy(addrlo, addrhi, 6); - break; - -#ifdef INET - case AF_INET: - sin = (struct sockaddr_in *)&(ifr->ifr_addr); - if (sin->sin_addr.s_addr == INADDR_ANY) { - /* - * An IP address of INADDR_ANY means stop listening - * to the range of Ethernet multicast addresses used - * for IP. - */ - bcopy(ether_ipmulticast_min, addrlo, 6); - bcopy(ether_ipmulticast_max, addrhi, 6); - unset_allmulti = 1; - } - else { - ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); - bcopy(addrlo, addrhi, 6); - } - break; -#endif - - default: - splx(s); - return (EAFNOSUPPORT); - } - - /* - * Look up the address in our list. - */ - ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); - if (enm == NULL) { - splx(s); - return (ENXIO); - } - if (--enm->enm_refcount != 0) { - /* - * Still some claims to this record. - */ - splx(s); - return (0); - } - /* - * No remaining claims to this record; unlink and free it. - */ - for (p = &enm->enm_ac->ac_multiaddrs; - *p != enm; - p = &(*p)->enm_next) - continue; - *p = (*p)->enm_next; - free(enm, M_IFMADDR); - ac->ac_multicnt--; - splx(s); - if (unset_allmulti) - ac->ac_if.if_flags &= ~IFF_ALLMULTI; - - /* - * Return ENETRESET to inform the driver that the list has changed - * and its reception filter should be adjusted accordingly. - */ - return (ENETRESET); -} - SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet"); int diff --git a/sys/net/route.h b/sys/net/route.h index 0b518df..31fbcae 100644 --- a/sys/net/route.h +++ b/sys/net/route.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)route.h 8.3 (Berkeley) 4/19/94 - * $Id: route.h,v 1.22 1996/08/26 22:04:47 julian Exp $ + * $Id: route.h,v 1.23 1996/10/09 18:35:10 wollman Exp $ */ #ifndef _NET_ROUTE_H_ @@ -203,6 +203,8 @@ struct rt_msghdr { #define RTM_NEWADDR 0xc /* address being added to iface */ #define RTM_DELADDR 0xd /* address being removed from iface */ #define RTM_IFINFO 0xe /* iface going up/down etc. */ +#define RTM_NEWMADDR 0xf /* mcast group membership being added to if */ +#define RTM_DELMADDR 0x10 /* mcast group membership being deleted */ #define RTV_MTU 0x1 /* init or lock _mtu */ #define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */ @@ -262,10 +264,14 @@ extern struct route_cb route_cb; extern struct rtstat rtstat; extern struct radix_node_head *rt_tables[AF_MAX+1]; +/* forward declaration for rt_newmaddrmsg() */ +struct ifmultiaddr; + void route_init __P((void)); void rt_ifmsg __P((struct ifnet *)); void rt_missmsg __P((int, struct rt_addrinfo *, int, int)); void rt_newaddrmsg __P((int, struct ifaddr *, int, struct rtentry *)); +void rt_newmaddrmsg __P((int, struct ifmultiaddr *)); int rt_setgate __P((struct rtentry *, struct sockaddr *, struct sockaddr *)); void rtalloc __P((struct route *)); diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index eb786fa..e831d67 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)rtsock.c 8.5 (Berkeley) 11/2/94 - * $Id: rtsock.c,v 1.21 1996/12/11 20:38:16 wollman Exp $ + * $Id: rtsock.c,v 1.22 1996/12/13 21:28:41 wollman Exp $ */ #include @@ -416,6 +416,11 @@ rt_msg1(type, rtinfo) len = sizeof(struct ifa_msghdr); break; + case RTM_DELMADDR: + case RTM_NEWMADDR: + len = sizeof(struct ifma_msghdr); + break; + case RTM_IFINFO: len = sizeof(struct if_msghdr); break; @@ -637,6 +642,40 @@ rt_newaddrmsg(cmd, ifa, error, rt) } } +/* + * This is the analogue to the rt_newaddrmsg which performs the same + * function but for multicast group memberhips. This is easier since + * there is no route state to worry about. + */ +void +rt_newmaddrmsg(cmd, ifma) + int cmd; + struct ifmultiaddr *ifma; +{ + struct rt_addrinfo info; + struct mbuf *m = 0; + struct ifnet *ifp = ifma->ifma_ifp; + struct ifma_msghdr *ifmam; + + if (route_cb.any_count == 0) + return; + + bzero((caddr_t)&info, sizeof(info)); + ifaaddr = ifma->ifma_addr; + ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr; + /* + * If a link-layer address is present, present it as a ``gateway'' + * (similarly to how ARP entries, e.g., are presented). + */ + gate = ifma->ifma_lladdr; + if ((m = rt_msg1(cmd, &info)) == NULL) + return; + ifmam = mtod(m, struct ifma_msghdr *); + ifmam->ifmam_index = ifp->if_index; + ifmam->ifmam_addrs = info.rti_addrs; + route_proto.sp_protocol = ifma->ifma_addr->sa_family; + raw_input(m, &route_proto, &route_src, &route_dst); +} /* * This is used in dumping the kernel table via sysctl(). diff --git a/sys/netinet/if_ether.h b/sys/netinet/if_ether.h index c4f56c8..155cb3f 100644 --- a/sys/netinet/if_ether.h +++ b/sys/netinet/if_ether.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)if_ether.h 8.3 (Berkeley) 5/2/95 - * $Id: if_ether.h,v 1.16 1996/12/11 17:46:33 wollman Exp $ + * $Id: if_ether.h,v 1.17 1997/01/03 19:51:54 wollman Exp $ */ #ifndef _NETINET_IF_ETHER_H_ @@ -40,7 +40,6 @@ #include #include -#ifdef KERNEL /* * Macro to map an IP multicast address to an Ethernet multicast address. * The high-order 25 bits of the Ethernet address are statically assigned, @@ -57,7 +56,6 @@ (enaddr)[4] = ((u_char *)ipaddr)[2]; \ (enaddr)[5] = ((u_char *)ipaddr)[3]; \ } -#endif /* * Ethernet Address Resolution Protocol. @@ -91,7 +89,6 @@ struct arpcom { */ struct ifnet ac_if; /* network-visible interface */ u_char ac_enaddr[ETHER_ADDR_LEN]; /* ethernet hardware address */ - struct ether_multi *ac_multiaddrs; /* list of ether multicast addrs */ int ac_multicnt; /* length of ac_multiaddrs list */ }; @@ -120,75 +117,6 @@ extern struct ifqueue arpintrq; int arpresolve __P((struct arpcom *, struct rtentry *, struct mbuf *, struct sockaddr *, u_char *, struct rtentry *)); void arp_ifinit __P((struct arpcom *, struct ifaddr *)); -int ether_addmulti __P((struct ifreq *, struct arpcom *)); -int ether_delmulti __P((struct ifreq *, struct arpcom *)); - -/* - * Ethernet multicast address structure. There is one of these for each - * multicast address or range of multicast addresses that we are supposed - * to listen to on a particular interface. They are kept in a linked list, - * rooted in the interface's arpcom structure. (This really has nothing to - * do with ARP, or with the Internet address family, but this appears to be - * the minimally-disrupting place to put it.) - */ -struct ether_multi { - u_char enm_addrlo[ETHER_ADDR_LEN]; /* low or only address of range */ - u_char enm_addrhi[ETHER_ADDR_LEN]; /* high or only address of range */ - struct arpcom *enm_ac; /* back pointer to arpcom */ - u_int enm_refcount; /* no. claims to this addr/range */ - struct ether_multi *enm_next; /* ptr to next ether_multi */ -}; - -/* - * Structure used by macros below to remember position when stepping through - * all of the ether_multi records. - */ -struct ether_multistep { - struct ether_multi *e_enm; -}; - -/* - * Macro for looking up the ether_multi record for a given range of Ethernet - * multicast addresses connected to a given arpcom structure. If no matching - * record is found, "enm" returns NULL. - */ -#define ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm) \ - /* u_char addrlo[ETHER_ADDR_LEN]; */ \ - /* u_char addrhi[ETHER_ADDR_LEN]; */ \ - /* struct arpcom *ac; */ \ - /* struct ether_multi *enm; */ \ -{ \ - for ((enm) = (ac)->ac_multiaddrs; \ - (enm) != NULL && \ - (bcmp((enm)->enm_addrlo, (addrlo), ETHER_ADDR_LEN) != 0 || \ - bcmp((enm)->enm_addrhi, (addrhi), ETHER_ADDR_LEN) != 0); \ - (enm) = (enm)->enm_next); \ -} - -/* - * Macro to step through all of the ether_multi records, one at a time. - * The current position is remembered in "step", which the caller must - * provide. ETHER_FIRST_MULTI(), below, must be called to initialize "step" - * and get the first record. Both macros return a NULL "enm" when there - * are no remaining records. - */ -#define ETHER_NEXT_MULTI(step, enm) \ - /* struct ether_multistep step; */ \ - /* struct ether_multi *enm; */ \ -{ \ - if (((enm) = (step).e_enm) != NULL) \ - (step).e_enm = (enm)->enm_next; \ -} - -#define ETHER_FIRST_MULTI(step, ac, enm) \ - /* struct ether_multistep step; */ \ - /* struct arpcom *ac; */ \ - /* struct ether_multi *enm; */ \ -{ \ - (step).e_enm = (ac)->ac_multiaddrs; \ - ETHER_NEXT_MULTI((step), (enm)); \ -} - #endif #endif diff --git a/sys/netinet/in.c b/sys/netinet/in.c index f200860..015783e 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)in.c 8.4 (Berkeley) 1/9/95 - * $Id: in.c,v 1.26 1996/12/13 21:28:52 wollman Exp $ + * $Id: in.c,v 1.27 1996/12/15 22:44:00 wollman Exp $ */ #include @@ -55,18 +55,6 @@ #include -/* - * This structure is used to keep track of in_multi chains which belong to - * deleted interface addresses. - */ -static LIST_HEAD(, multi_kludge) in_mk; /* XXX BSS initialization */ - -struct multi_kludge { - LIST_ENTRY(multi_kludge) mk_entry; - struct ifnet *mk_ifp; - struct in_multihead mk_head; -}; - static void in_socktrim __P((struct sockaddr_in *)); static int in_ifinit __P((struct ifnet *, struct in_ifaddr *, struct sockaddr_in *, int)); @@ -75,6 +63,9 @@ static void in_ifscrub __P((struct ifnet *, struct in_ifaddr *)); static int subnetsarelocal = 0; SYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW, &subnetsarelocal, 0, ""); + +struct in_multihead in_multihead; /* XXX BSS initialization */ + /* * Return 1 if an internet address is for a ``local'' host * (one to which we have a connection). If subnetsarelocal @@ -164,7 +155,6 @@ in_control(so, cmd, data, ifp) struct sockaddr_in oldaddr; int error, hostIsNew, maskIsNew, s; u_long i; - struct multi_kludge *mk; /* * Find address for this interface, if it exists. @@ -350,10 +340,6 @@ in_control(so, cmd, data, ifp) return (error); case SIOCDIFADDR: - mk = malloc(sizeof *mk, M_IPMADDR, M_WAITOK); - if (!mk) - return ENOBUFS; - in_ifscrub(ifp, ia); /* * Protect from ipintr() traversing address list @@ -365,51 +351,7 @@ in_control(so, cmd, data, ifp) TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link); oia = ia; TAILQ_REMOVE(&in_ifaddrhead, oia, ia_link); - if (!oia->ia_multiaddrs.lh_first) { - IFAFREE(&oia->ia_ifa); - FREE(mk, M_IPMADDR); - splx(s); - break; - } - - /* - * Multicast address kludge: - * If there were any multicast addresses attached to this - * interface address, either move them to another address - * on this interface, or save them until such time as this - * interface is reconfigured for IP. - */ - IFP_TO_IA(oia->ia_ifp, ia); - if (ia) { /* there is another address */ - struct in_multi *inm; - for(inm = oia->ia_multiaddrs.lh_first; inm; - inm = inm->inm_entry.le_next) { - IFAFREE(&inm->inm_ia->ia_ifa); - ia->ia_ifa.ifa_refcnt++; - inm->inm_ia = ia; - LIST_INSERT_HEAD(&ia->ia_multiaddrs, inm, - inm_entry); - } - FREE(mk, M_IPMADDR); - } else { /* last address on this if deleted, save */ - struct in_multi *inm; - - LIST_INIT(&mk->mk_head); - mk->mk_ifp = ifp; - - for(inm = oia->ia_multiaddrs.lh_first; inm; - inm = inm->inm_entry.le_next) { - LIST_INSERT_HEAD(&mk->mk_head, inm, inm_entry); - } - - if (mk->mk_head.lh_first) { - LIST_INSERT_HEAD(&in_mk, mk, mk_entry); - } else { - FREE(mk, M_IPMADDR); - } - } - - IFAFREE((&oia->ia_ifa)); + IFAFREE(&oia->ia_ifa); splx(s); break; @@ -453,7 +395,6 @@ in_ifinit(ifp, ia, sin, scrub) register u_long i = ntohl(sin->sin_addr.s_addr); struct sockaddr_in oldaddr; int s = splimp(), flags = RTF_UP, error; - struct multi_kludge *mk; oldaddr = ia->ia_addr; ia->ia_addr = *sin; @@ -513,7 +454,6 @@ in_ifinit(ifp, ia, sin, scrub) if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0) ia->ia_flags |= IFA_ROUTE; - LIST_INIT(&ia->ia_multiaddrs); /* * If the interface supports multicast, join the "all hosts" * multicast group on that interface. @@ -521,30 +461,6 @@ in_ifinit(ifp, ia, sin, scrub) if (ifp->if_flags & IFF_MULTICAST) { struct in_addr addr; - /* - * Continuation of multicast address hack: - * If there was a multicast group list previously saved - * for this interface, then we re-attach it to the first - * address configured on the i/f. - */ - for(mk = in_mk.lh_first; mk; mk = mk->mk_entry.le_next) { - if(mk->mk_ifp == ifp) { - struct in_multi *inm; - - for(inm = mk->mk_head.lh_first; inm; - inm = inm->inm_entry.le_next) { - IFAFREE(&inm->inm_ia->ia_ifa); - ia->ia_ifa.ifa_refcnt++; - inm->inm_ia = ia; - LIST_INSERT_HEAD(&ia->ia_multiaddrs, - inm, inm_entry); - } - LIST_REMOVE(mk, mk_entry); - free(mk, M_IPMADDR); - break; - } - } - addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); in_addmulti(&addr, ifp); } @@ -602,63 +518,52 @@ in_addmulti(ap, ifp) register struct ifnet *ifp; { register struct in_multi *inm; - struct ifreq ifr; - struct in_ifaddr *ia; + int error; + struct sockaddr_in sin; + struct ifmultiaddr *ifma; int s = splnet(); /* - * See if address already in list. + * Call generic routine to add membership or increment + * refcount. It wants addresses in the form of a sockaddr, + * so we build one here (being careful to zero the unused bytes). */ - IN_LOOKUP_MULTI(*ap, ifp, inm); - if (inm != NULL) { - /* - * Found it; just increment the reference count. - */ - ++inm->inm_refcount; + bzero(&sin, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_len = sizeof sin; + sin.sin_addr = *ap; + error = if_addmulti(ifp, (struct sockaddr *)&sin, &ifma); + if (error) { + splx(s); + return 0; } - else { - /* - * New address; allocate a new multicast record - * and link it into the interface's multicast list. - */ - inm = (struct in_multi *)malloc(sizeof(*inm), - M_IPMADDR, M_NOWAIT); - if (inm == NULL) { - splx(s); - return (NULL); - } - inm->inm_addr = *ap; - inm->inm_ifp = ifp; - inm->inm_refcount = 1; - IFP_TO_IA(ifp, ia); - if (ia == NULL) { - free(inm, M_IPMADDR); - splx(s); - return (NULL); - } - inm->inm_ia = ia; - ia->ia_ifa.ifa_refcnt++; /* gain a reference */ - LIST_INSERT_HEAD(&ia->ia_multiaddrs, inm, inm_entry); - /* - * Ask the network driver to update its multicast reception - * filter appropriately for the new address. - */ - ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET; - ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = *ap; - if ((ifp->if_ioctl == NULL) || - (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) { - LIST_REMOVE(inm, inm_entry); - IFAFREE(&ia->ia_ifa); /* release reference */ - free(inm, M_IPMADDR); - splx(s); - return (NULL); - } - /* - * Let IGMP know that we have joined a new IP multicast group. - */ - igmp_joingroup(inm); + /* + * If ifma->ifma_protospec is null, then if_addmulti() created + * a new record. Otherwise, we are done. + */ + if (ifma->ifma_protospec != 0) + return ifma->ifma_protospec; + + /* XXX - if_addmulti uses M_WAITOK. Can this really be called + at interrupt time? If so, need to fix if_addmulti. XXX */ + inm = (struct in_multi *)malloc(sizeof(*inm), M_IPMADDR, M_NOWAIT); + if (inm == NULL) { + splx(s); + return (NULL); } + + bzero(inm, sizeof *inm); + inm->inm_addr = *ap; + inm->inm_ifp = ifp; + inm->inm_ifma = ifma; + ifma->ifma_protospec = inm; + LIST_INSERT_HEAD(&in_multihead, inm, inm_link); + + /* + * Let IGMP know that we have joined a new IP multicast group. + */ + igmp_joingroup(inm); splx(s); return (inm); } @@ -670,31 +575,20 @@ void in_delmulti(inm) register struct in_multi *inm; { - struct ifreq ifr; + struct ifmultiaddr *ifma = inm->inm_ifma; int s = splnet(); - if (--inm->inm_refcount == 0) { + if (ifma->ifma_refcount == 1) { /* * No remaining claims to this record; let IGMP know that * we are leaving the multicast group. */ igmp_leavegroup(inm); - /* - * Unlink from list. - */ - LIST_REMOVE(inm, inm_entry); - IFAFREE(&inm->inm_ia->ia_ifa); /* release reference */ - - /* - * Notify the network driver to update its multicast reception - * filter. - */ - ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; - ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr = - inm->inm_addr; - (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI, - (caddr_t)&ifr); + ifma->ifma_protospec = 0; + LIST_REMOVE(inm, inm_link); free(inm, M_IPMADDR); } + /* XXX - should be separate API for when we have an ifma? */ + if_delmulti(ifma->ifma_ifp, ifma->ifma_addr); splx(s); } diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h index 03aa446..af7e54c 100644 --- a/sys/netinet/in_var.h +++ b/sys/netinet/in_var.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)in_var.h 8.2 (Berkeley) 1/9/95 - * $Id: in_var.h,v 1.18 1996/12/13 21:28:54 wollman Exp $ + * $Id: in_var.h,v 1.19 1996/12/15 20:46:39 wollman Exp $ */ #ifndef _NETINET_IN_VAR_H_ @@ -41,7 +41,7 @@ /* * Interface address, Internet version. One of these structures - * is allocated for each interface with an Internet address. + * is allocated for each Internet address on an interface. * The ifaddr structure contains the protocol-independent part * of the structure and is assumed to be first. */ @@ -60,8 +60,6 @@ struct in_ifaddr { struct sockaddr_in ia_dstaddr; /* reserve space for broadcast addr */ #define ia_broadaddr ia_dstaddr struct sockaddr_in ia_sockmask; /* reserve space for general netmask */ - LIST_HEAD(in_multihead, in_multi) ia_multiaddrs; - /* list of multicast addresses */ }; struct in_aliasreq { @@ -146,49 +144,51 @@ struct router_info { /* * Internet multicast address structure. There is one of these for each IP * multicast group to which this host belongs on a given network interface. - * They are kept in a linked list, rooted in the interface's in_ifaddr - * structure. + * For every entry on the interface's if_multiaddrs list which represents + * an IP multicast group, there is one of these structures. They are also + * kept on a system-wide list to make it easier to keep our legacy IGMP code + * compatible with the rest of the world (see IN_FIRST_MULTI et al, below). */ struct in_multi { - LIST_ENTRY(in_multi) inm_entry; /* list glue */ - struct in_addr inm_addr; /* IP multicast address */ + LIST_ENTRY(in_multi) inm_link; /* queue macro glue */ + struct in_addr inm_addr; /* IP multicast address, convenience */ struct ifnet *inm_ifp; /* back pointer to ifnet */ - struct in_ifaddr *inm_ia; /* back pointer to in_ifaddr */ - u_int inm_refcount; /* no. membership claims by sockets */ + struct ifmultiaddr *inm_ifma; /* back pointer to ifmultiaddr */ u_int inm_timer; /* IGMP membership report timer */ u_int inm_state; /* state of the membership */ struct router_info *inm_rti; /* router info*/ }; #ifdef KERNEL +extern LIST_HEAD(in_multihead, in_multi) in_multihead; + /* * Structure used by macros below to remember position when stepping through * all of the in_multi records. */ struct in_multistep { - struct in_ifaddr *i_ia; struct in_multi *i_inm; }; /* * Macro for looking up the in_multi record for a given IP multicast address - * on a given interface. If no matching record is found, "inm" returns NULL. + * on a given interface. If no matching record is found, "inm" is set null. */ #define IN_LOOKUP_MULTI(addr, ifp, inm) \ /* struct in_addr addr; */ \ /* struct ifnet *ifp; */ \ /* struct in_multi *inm; */ \ do { \ - register struct in_ifaddr *ia; \ + register struct ifmultiaddr *ifma; \ \ - IFP_TO_IA((ifp), ia); \ - if (ia == NULL) \ - (inm) = NULL; \ - else \ - for ((inm) = ia->ia_multiaddrs.lh_first; \ - (inm) != NULL && (inm)->inm_addr.s_addr != (addr).s_addr; \ - (inm) = inm->inm_entry.le_next) \ - continue; \ + for (ifma = (ifp)->if_multiaddrs.lh_first; ifma; \ + ifma = ifma->ifma_link.le_next) { \ + if (ifma->ifma_addr->sa_family == AF_INET \ + && ((struct sockaddr_in *)ifma)->sin_addr.s_addr == \ + (addr).s_addr) \ + break; \ + } \ + (inm) = ifma ? ifma->ifma_protospec : 0; \ } while(0) /* @@ -203,24 +203,14 @@ do { \ /* struct in_multi *inm; */ \ do { \ if (((inm) = (step).i_inm) != NULL) \ - (step).i_inm = (inm)->inm_entry.le_next; \ - else \ - while ((step).i_ia != NULL) { \ - (inm) = (step).i_ia->ia_multiaddrs.lh_first; \ - (step).i_ia = (step).i_ia->ia_link.tqe_next; \ - if ((inm) != NULL) { \ - (step).i_inm = (inm)->inm_entry.le_next; \ - break; \ - } \ - } \ + (step).i_inm = (step).i_inm->inm_link.le_next; \ } while(0) #define IN_FIRST_MULTI(step, inm) \ /* struct in_multistep step; */ \ /* struct in_multi *inm; */ \ do { \ - (step).i_ia = in_ifaddrhead.tqh_first; \ - (step).i_inm = NULL; \ + (step).i_inm = in_multihead.lh_first; \ IN_NEXT_MULTI((step), (inm)); \ } while(0) diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c index bc5b3cc..44566ab 100644 --- a/sys/netinet/ip_mroute.c +++ b/sys/netinet/ip_mroute.c @@ -9,7 +9,7 @@ * Modified by Bill Fenner, PARC, April 1995 * * MROUTING Revision: 3.5 - * $Id: ip_mroute.c,v 1.34 1996/07/12 17:22:32 fenner Exp $ + * $Id: ip_mroute.c,v 1.35 1996/11/23 19:07:02 fenner Exp $ */ #include "opt_mrouting.h" @@ -576,7 +576,7 @@ X_ip_mrouter_done() ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr = INADDR_ANY; ifp = viftable[vifi].v_ifp; - (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr); + if_allmulti(ifp, 0); } } bzero((caddr_t)tbftable, sizeof(tbftable)); @@ -728,10 +728,8 @@ add_vif(vifcp) return EOPNOTSUPP; /* Enable promiscuous reception of all IP multicasts from the if */ - ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; - ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr = INADDR_ANY; s = splnet(); - error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr); + if_allmulti(ifp, 1); splx(s); if (error) return error; @@ -800,7 +798,7 @@ del_vif(vifip) ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr = INADDR_ANY; ifp = vifp->v_ifp; - (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr); + if_allmulti(ifp, 0); } if (vifp == last_encap_vif) { diff --git a/sys/pci/if_de.c b/sys/pci/if_de.c index c5d7f5a..95bc095 100644 --- a/sys/pci/if_de.c +++ b/sys/pci/if_de.c @@ -21,7 +21,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: if_de.c,v 1.55 1996/11/10 13:36:46 davidg Exp $ + * $Id: if_de.c,v 1.56 1996/12/01 06:01:00 rgrimes Exp $ * */ @@ -3287,62 +3287,63 @@ tulip_addr_filter( tulip_softc_t * const sc) { u_int32_t *sp = sc->tulip_setupdata; - struct ether_multistep step; - struct ether_multi *enm; + struct ifmultiaddr *ifma; int i = 0; + u_char *addrp; + unsigned hash; + + ifma = sc->tulip_if.if_multiaddrs.lh_first; sc->tulip_flags &= ~TULIP_WANTHASH; sc->tulip_flags |= TULIP_WANTSETUP; sc->tulip_cmdmode &= ~TULIP_CMD_RXRUN; sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED; - if (sc->tulip_ac.ac_multicnt > 14) { - unsigned hash; - /* - * If we have more than 14 multicasts, we have - * go into hash perfect mode (512 bit multicast - * hash and one perfect hardware). - */ - bzero(sc->tulip_setupdata, sizeof(sc->tulip_setupdata)); - hash = tulip_mchash(etherbroadcastaddr); - sp[hash >> 4] |= 1 << (hash & 0xF); - ETHER_FIRST_MULTI(step, &sc->tulip_ac, enm); - while (enm != NULL) { - hash = tulip_mchash(enm->enm_addrlo); - sp[hash >> 4] |= 1 << (hash & 0xF); - ETHER_NEXT_MULTI(step, enm); - } - sc->tulip_flags |= TULIP_WANTHASH; - sp[39] = ((u_int16_t *) sc->tulip_ac.ac_enaddr)[0]; - sp[40] = ((u_int16_t *) sc->tulip_ac.ac_enaddr)[1]; - sp[41] = ((u_int16_t *) sc->tulip_ac.ac_enaddr)[2]; - } else { - /* - * Else can get perfect filtering for 16 addresses. - */ - ETHER_FIRST_MULTI(step, &sc->tulip_ac, enm); - for (; enm != NULL; i++) { - *sp++ = ((u_int16_t *) enm->enm_addrlo)[0]; - *sp++ = ((u_int16_t *) enm->enm_addrlo)[1]; - *sp++ = ((u_int16_t *) enm->enm_addrlo)[2]; - ETHER_NEXT_MULTI(step, enm); - } - /* - * Add the broadcast address. - */ - i++; - *sp++ = 0xFFFF; - *sp++ = 0xFFFF; - *sp++ = 0xFFFF; - /* - * Pad the rest with our hardware address - */ - for (; i < 16; i++) { + for (ifma = sc->tulip_if.if_multiaddrs.lh_first; ifma; + ifma = ifma->ifma_link.le_next) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + if (i > 14) + goto musthash; + addrp = LLADDR((struct sockaddr_dl *)ifma->ifma_addr); + *sp++ = ((u_int16_t *) addrp)[0]; + *sp++ = ((u_int16_t *) addrp)[1]; + *sp++ = ((u_int16_t *) addrp)[2]; + i++; + } + /* + * Add the broadcast address. + */ + i++; + *sp++ = 0xFFFF; + *sp++ = 0xFFFF; + *sp++ = 0xFFFF; + /* + * Pad the rest with our hardware address + */ + for (; i < 16; i++) { *sp++ = ((u_int16_t *) sc->tulip_ac.ac_enaddr)[0]; *sp++ = ((u_int16_t *) sc->tulip_ac.ac_enaddr)[1]; *sp++ = ((u_int16_t *) sc->tulip_ac.ac_enaddr)[2]; - } } + return; + +musthash: + bzero(sc->tulip_setupdata, sizeof(sc->tulip_setupdata)); + hash = tulip_mchash(etherbroadcastaddr); + sp[hash >> 4] |= 1 << (hash & 0xF); + for (ifma = sc->tulip_if.if_multiaddrs.lh_first; ifma; + ifma = ifma->ifma_link.le_next) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + + hash = tulip_mchash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); + sp[hash >> 4] |= 1 << (hash & 0xF); + } + sc->tulip_flags |= TULIP_WANTHASH; + sp[39] = ((u_int16_t *) sc->tulip_ac.ac_enaddr)[0]; + sp[40] = ((u_int16_t *) sc->tulip_ac.ac_enaddr)[1]; + sp[41] = ((u_int16_t *) sc->tulip_ac.ac_enaddr)[2]; } /* @@ -3395,22 +3396,15 @@ tulip_ifioctl( } case SIOCADDMULTI: - case SIOCDELMULTI: { + case SIOCDELMULTI: /* * Update multicast listeners */ - if (cmd == SIOCADDMULTI) - error = ether_addmulti(ifr, &sc->tulip_ac); - else - error = ether_delmulti(ifr, &sc->tulip_ac); - - if (error == ENETRESET) { - tulip_addr_filter(sc); /* reset multicast filtering */ - tulip_init(sc); - error = 0; - } + tulip_addr_filter(sc); /* reset multicast filtering */ + tulip_init(sc); + error = 0; break; - } + #if defined(SIOCSIFMTU) #if !defined(ifr_mtu) #define ifr_mtu ifr_metric diff --git a/sys/pci/if_fxp.c b/sys/pci/if_fxp.c index 61cb065..eed4623 100644 --- a/sys/pci/if_fxp.c +++ b/sys/pci/if_fxp.c @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_fxp.c,v 1.22 1996/11/18 02:45:46 davidg Exp $ + * $Id: if_fxp.c,v 1.23 1996/12/10 07:29:50 davidg Exp $ */ /* @@ -1055,21 +1055,11 @@ fxp_ioctl(ifp, command, data) case SIOCADDMULTI: case SIOCDELMULTI: /* - * Update out multicast list. + * Multicast list has changed; set the hardware filter + * accordingly. */ - error = (command == SIOCADDMULTI) ? - ether_addmulti(ifr, &sc->arpcom) : - ether_delmulti(ifr, &sc->arpcom); - - if (error == ENETRESET) { - /* - * Multicast list has changed; set the hardware filter - * accordingly. - */ - fxp_init(sc); - - error = 0; - } + fxp_init(sc); + error = 0; break; default: diff --git a/sys/pci/if_pdq.c b/sys/pci/if_pdq.c index 619d22d..3fda4f9 100644 --- a/sys/pci/if_pdq.c +++ b/sys/pci/if_pdq.c @@ -21,7 +21,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: if_pdq.c,v 1.17 1996/09/06 23:08:53 phk Exp $ + * $Id: if_pdq.c,v 1.18 1996/09/10 08:31:31 bde Exp $ * */ @@ -287,17 +287,19 @@ pdq_os_addr_fill( size_t num_addrs) { pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx; - struct ether_multistep step; - struct ether_multi *enm; - - ETHER_FIRST_MULTI(step, &sc->sc_ac, enm); - while (enm != NULL && num_addrs > 0) { - ((u_short *) addr->lanaddr_bytes)[0] = ((u_short *) enm->enm_addrlo)[0]; - ((u_short *) addr->lanaddr_bytes)[1] = ((u_short *) enm->enm_addrlo)[1]; - ((u_short *) addr->lanaddr_bytes)[2] = ((u_short *) enm->enm_addrlo)[2]; - ETHER_NEXT_MULTI(step, enm); - addr++; - num_addrs--; + struct ifmultiaddr *ifma; + + for (ifma = sc->sc_if.if_multiaddrs.lh_first; ifma && num_addrs > 0; + ifma = ifma->ifma_link.le_next) { + char *mcaddr; + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + mcaddr = LLADDR((struct sockaddr_dl *)ifma->ifma_addr); + ((u_short *) addr->lanaddr_bytes)[0] = ((u_short *) mcaddr)[0]; + ((u_short *) addr->lanaddr_bytes)[1] = ((u_short *) mcaddr)[1]; + ((u_short *) addr->lanaddr_bytes)[2] = ((u_short *) mcaddr)[2]; + addr++; + num_addrs--; } } @@ -366,22 +368,14 @@ pdq_ifioctl( } case SIOCADDMULTI: - case SIOCDELMULTI: { - /* - * Update multicast listeners - */ - if (cmd == SIOCADDMULTI) - error = ether_addmulti((struct ifreq *)data, &sc->sc_ac); - else - error = ether_delmulti((struct ifreq *)data, &sc->sc_ac); - - if (error == ENETRESET) { + case SIOCDELMULTI: + /* + * Update multicast listeners + */ if (sc->sc_if.if_flags & IFF_RUNNING) - pdq_run(sc->sc_pdq); + pdq_run(sc->sc_pdq); error = 0; - } - break; - } + break; default: { error = EINVAL; @@ -411,6 +405,8 @@ pdq_ifattach( ifp->if_ioctl = pdq_ifioctl; ifp->if_output = fddi_output; ifp->if_start = pdq_ifstart; +#warning "Implement fddi_resolvemulti!" +/* ifp->if_resolvemulti = ether_resolvemulti; XXX */ if_attach(ifp); fddi_ifattach(ifp); -- cgit v1.1