tl;dr
This diff stop (ab)using the actual SIOC{ADD,DEL}MULTI ioctls with a
magic value for the whole range of multicast addresses used for IPv4/6
to turn the interface into promiscuous mode.
Long story
Ethernet multicast records are currently represented by the ``struct
ether_multi'' as range of addresses between enm_addrlo and enm_addrlhi.
But most of the time this range represents a single address (lo == hi),
and the only cases where this is not true are changed below.
What happens in our drivers, is that as soon as the list of Ethernet
multicast records associated to an interface contains a range, we set
the IFF_ALLMULTI flag which turns the promiscuous mode on. So the
diff below directly set the interface into promiscuous mode instead
of relying on this overcomplicated feature.
Apart from helping me to reduce the complexity of the multicast
representation, which could be represented as one address instead of a
range, this diff has another benefit. With it, the IFF_ALLMULTI flag
is now set on an interface only if we try to configure more multicast
filters than it can handle (hardware limit).
I'm not using mrouted(8) myself, so tests would be appreciated!
Comments, ok?
Index: netinet/ip_mroute.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_mroute.c,v
retrieving revision 1.61
diff -u -p -r1.61 ip_mroute.c
--- netinet/ip_mroute.c 2 May 2013 11:54:10 -0000 1.61
+++ netinet/ip_mroute.c 4 Oct 2013 09:59:49 -0000
@@ -786,7 +786,6 @@ add_vif(struct mbuf *m)
struct vif *vifp;
struct ifaddr *ifa;
struct ifnet *ifp;
- struct ifreq ifr;
int error, s;
if (m == NULL || m->m_len < sizeof(struct vifctl))
@@ -846,10 +845,7 @@ add_vif(struct mbuf *m)
return (EOPNOTSUPP);
/* Enable promiscuous reception of all IP multicasts. */
- satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);
- satosin(&ifr.ifr_addr)->sin_family = AF_INET;
- satosin(&ifr.ifr_addr)->sin_addr = zeroin_addr;
- error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr);
+ error = ifpromisc(ifp, 1);
if (error)
return (error);
}
@@ -890,9 +886,6 @@ add_vif(struct mbuf *m)
void
reset_vif(struct vif *vifp)
{
- struct ifnet *ifp;
- struct ifreq ifr;
-
if (vifp->v_flags & VIFF_TUNNEL) {
/* empty */
} else if (vifp->v_flags & VIFF_REGISTER) {
@@ -900,11 +893,7 @@ reset_vif(struct vif *vifp)
reg_vif_num = VIFI_INVALID;
#endif
} else {
- satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);
- satosin(&ifr.ifr_addr)->sin_family = AF_INET;
- satosin(&ifr.ifr_addr)->sin_addr = zeroin_addr;
- ifp = vifp->v_ifp;
- (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
+ ifpromisc(vifp->v_ifp, 0);
}
bzero((caddr_t)vifp, sizeof(*vifp));
}
Index: netinet6/ip6_mroute.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/ip6_mroute.c,v
retrieving revision 1.62
diff -u -p -r1.62 ip6_mroute.c
--- netinet6/ip6_mroute.c 31 May 2013 15:04:24 -0000 1.62
+++ netinet6/ip6_mroute.c 4 Oct 2013 09:59:49 -0000
@@ -447,7 +447,6 @@ ip6_mrouter_done(void)
mifi_t mifi;
int i;
struct ifnet *ifp;
- struct in6_ifreq ifr;
struct mf6c *rt;
struct rtdetq *rte;
int s;
@@ -473,18 +472,13 @@ ip6_mrouter_done(void)
for (mifi = 0; mifi < nummifs; mifi++) {
if (mif6table[mifi].m6_ifp &&
!(mif6table[mifi].m6_flags & MIFF_REGISTER)) {
- ifr.ifr_addr.sin6_family = AF_INET6;
- ifr.ifr_addr.sin6_addr= in6addr_any;
ifp = mif6table[mifi].m6_ifp;
- (*ifp->if_ioctl)(ifp, SIOCDELMULTI,
- (caddr_t)&ifr);
+
+ ifpromisc(ifp, 0);
}
}
}
-#ifdef notyet
- bzero((caddr_t)qtable, sizeof(qtable));
- bzero((caddr_t)tbftable, sizeof(tbftable));
-#endif
+
bzero((caddr_t)mif6table, sizeof(mif6table));
nummifs = 0;
@@ -572,7 +566,6 @@ add_m6if(struct mif6ctl *mifcp)
{
struct mif6 *mifp;
struct ifnet *ifp;
- struct in6_ifreq ifr;
int error, s;
#ifdef notyet
struct tbf *m_tbf = tbftable + mifcp->mif6c_mifi;
@@ -605,17 +598,8 @@ add_m6if(struct mif6ctl *mifcp)
if ((ifp->if_flags & IFF_MULTICAST) == 0)
return EOPNOTSUPP;
- s = splsoftnet();
-
- /*
- * Enable promiscuous reception of all IPv6 multicasts
- * from the interface.
- */
- ifr.ifr_addr.sin6_family = AF_INET6;
- ifr.ifr_addr.sin6_addr = in6addr_any;
- error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr);
-
- splx(s);
+ /* Enable promiscuous reception of all IPv6 multicasts. */
+ error = ifpromisc(ifp, 1);
if (error)
return error;
}
@@ -658,8 +642,6 @@ del_m6if(mifi_t *mifip)
{
struct mif6 *mifp = mif6table + *mifip;
mifi_t mifi;
- struct ifnet *ifp;
- struct in6_ifreq ifr;
int s;
if (*mifip >= nummifs)
@@ -674,17 +656,9 @@ del_m6if(mifi_t *mifip)
* XXX: what if there is yet IPv4 multicast daemon
* using the interface?
*/
- ifp = mifp->m6_ifp;
-
- ifr.ifr_addr.sin6_family = AF_INET6;
- ifr.ifr_addr.sin6_addr = in6addr_any;
- (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
+ ifpromisc(mifp->m6_ifp, 0);
}
-#ifdef notyet
- bzero((caddr_t)qtable[*mifip], sizeof(qtable[*mifip]));
- bzero((caddr_t)mifp->m6_tbf, sizeof(*(mifp->m6_tbf)));
-#endif
bzero((caddr_t)mifp, sizeof (*mifp));
/* Adjust nummifs down */