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).
This commit is contained in:
wollman 1997-01-13 21:26:53 +00:00
parent 61b731410f
commit 42c104fc53
24 changed files with 425 additions and 893 deletions

View File

@ -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

View File

@ -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);
}
}

View File

@ -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 );
}

View File

@ -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:

View File

@ -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;
}
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;
bcopy(enm->enm_addrlo, &(ie->mcast_addrs[ie->mcast_count]), 6);
ie->mcast_count++;
ETHER_NEXT_MULTI(step, enm);
/* 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:

View File

@ -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:

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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 );
}

View File

@ -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;
}
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;
bcopy(enm->enm_addrlo, &(ie->mcast_addrs[ie->mcast_count]), 6);
ie->mcast_count++;
ETHER_NEXT_MULTI(step, enm);
/* 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:

View File

@ -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

View File

@ -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:

View File

@ -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);

View File

@ -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_
@ -123,6 +123,19 @@ struct ifa_msghdr {
int ifam_metric; /* value of ifa_metric */
};
/*
* 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

View File

@ -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 <sys/param.h>
@ -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

View File

@ -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 *));

View File

@ -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 <sys/param.h>
@ -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().

View File

@ -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 <net/ethernet.h>
#include <net/if_arp.h>
#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

View File

@ -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 <sys/param.h>
@ -55,18 +55,6 @@
#include <netinet/igmp_var.h>
/*
* 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);
}

View File

@ -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)

View File

@ -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) {

View File

@ -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

View File

@ -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:

View File

@ -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;
struct ifmultiaddr *ifma;
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--;
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);