summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
authorbms <bms@FreeBSD.org>2009-04-29 19:19:13 +0000
committerbms <bms@FreeBSD.org>2009-04-29 19:19:13 +0000
commit32a71137f08bc028578417de36a241d7e6011f58 (patch)
tree51d9a006ee48417962ce45f044b7e5603910fe13 /sys/netinet
parent51a4d1c4a3d279a3638c0b40f351aa93f965c7df (diff)
downloadFreeBSD-src-32a71137f08bc028578417de36a241d7e6011f58.zip
FreeBSD-src-32a71137f08bc028578417de36a241d7e6011f58.tar.gz
Bite the bullet, and make the IPv6 SSM and MLDv2 mega-commit:
import from p4 bms_netdev. Summary of changes: * Connect netinet6/in6_mcast.c to build. The legacy KAME KPIs are mostly preserved. * Eliminate now dead code from ip6_output.c. Don't do mbuf bingo, we are not going to do RFC 2292 style CMSG tricks for multicast options as they are not required by any current IPv6 normative reference. * Refactor transports (UDP, raw_ip6) to do own mcast filtering. SCTP, TCP unaffected by this change. * Add ip6_msource, in6_msource structs to in6_var.h. * Hookup mld_ifinfo state to in6_ifextra, allocate from domifattach path. * Eliminate IN6_LOOKUP_MULTI(), it is no longer referenced. Kernel consumers which need this should use in6m_lookup(). * Refactor IPv6 socket group memberships to use a vector (like IPv4). * Update ifmcstat(8) for IPv6 SSM. * Add witness lock order for IN6_MULTI_LOCK. * Move IN6_MULTI_LOCK out of lower ip6_output()/ip6_input() paths. * Introduce IP6STAT_ADD/SUB/INC/DEC as per rwatson's IPv4 cleanup. * Update carp(4) for new IPv6 SSM KPIs. * Virtualize ip6_mrouter socket. Changes mostly localized to IPv6 MROUTING. * Don't do a local group lookup in MROUTING. * Kill unused KAME prototypes in6_purgemkludge(), in6_restoremkludge(). * Preserve KAME DAD timer jitter behaviour in MLDv1 compatibility mode. * Bump __FreeBSD_version to 800084. * Update UPDATING. NOTE WELL: * This code hasn't been tested against real MLDv2 queriers (yet), although the on-wire protocol has been verified in Wireshark. * There are a few unresolved issues in the socket layer APIs to do with scope ID propagation. * There is a LOR present in ip6_output()'s use of in6_setscope() which needs to be resolved. See comments in mld6.c. This is believed to be benign and can't be avoided for the moment without re-introducing an indirect netisr. This work was mostly derived from the IGMPv3 implementation, and has been sponsored by a third party.
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/ip_carp.c68
1 files changed, 37 insertions, 31 deletions
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c
index b2922fc..fa0726a 100644
--- a/sys/netinet/ip_carp.c
+++ b/sys/netinet/ip_carp.c
@@ -400,15 +400,20 @@ carp_clone_create(struct if_clone *ifc, int unit, caddr_t params)
sc->sc_advskew = 0;
sc->sc_init_counter = 1;
sc->sc_naddrs = sc->sc_naddrs6 = 0; /* M_ZERO? */
-#ifdef INET6
- sc->sc_im6o.im6o_multicast_hlim = CARP_DFLTTL;
-#endif
sc->sc_imo.imo_membership = (struct in_multi **)malloc(
(sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_CARP,
M_WAITOK);
sc->sc_imo.imo_mfilters = NULL;
sc->sc_imo.imo_max_memberships = IP_MIN_MEMBERSHIPS;
sc->sc_imo.imo_multicast_vif = -1;
+#ifdef INET6
+ sc->sc_im6o.im6o_membership = (struct in6_multi **)malloc(
+ (sizeof(struct in6_multi *) * IPV6_MIN_MEMBERSHIPS), M_CARP,
+ M_WAITOK);
+ sc->sc_im6o.im6o_mfilters = NULL;
+ sc->sc_im6o.im6o_max_memberships = IPV6_MIN_MEMBERSHIPS;
+ sc->sc_im6o.im6o_multicast_hlim = CARP_DFLTTL;
+#endif
callout_init(&sc->sc_ad_tmo, CALLOUT_MPSAFE);
callout_init(&sc->sc_md_tmo, CALLOUT_MPSAFE);
@@ -448,6 +453,9 @@ carp_clone_destroy(struct ifnet *ifp)
if_detach(ifp);
if_free_type(ifp, IFT_ETHER);
free(sc->sc_imo.imo_membership, M_CARP);
+#ifdef INET6
+ free(sc->sc_im6o.im6o_membership, M_CARP);
+#endif
free(sc, M_CARP);
}
@@ -1449,14 +1457,17 @@ static void
carp_multicast6_cleanup(struct carp_softc *sc)
{
struct ip6_moptions *im6o = &sc->sc_im6o;
+ u_int16_t n = im6o->im6o_num_memberships;
- while (!LIST_EMPTY(&im6o->im6o_memberships)) {
- struct in6_multi_mship *imm =
- LIST_FIRST(&im6o->im6o_memberships);
-
- LIST_REMOVE(imm, i6mm_chain);
- in6_leavegroup(imm);
+ while (n-- > 0) {
+ if (im6o->im6o_membership[n] != NULL) {
+ in6_mc_leave(im6o->im6o_membership[n], NULL);
+ im6o->im6o_membership[n] = NULL;
+ }
}
+ KASSERT(im6o->im6o_mfilters == NULL,
+ ("%s: im6o_mfilters != NULL", __func__));
+ im6o->im6o_num_memberships = 0;
im6o->im6o_multicast_ifp = NULL;
}
#endif
@@ -1635,10 +1646,11 @@ carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6)
struct carp_if *cif;
struct in6_ifaddr *ia, *ia_if;
struct ip6_moptions *im6o = &sc->sc_im6o;
- struct in6_multi_mship *imm;
struct in6_addr in6;
int own, error;
+ error = 0;
+
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
if (!(SC2IFP(sc)->if_flags & IFF_UP))
carp_set_state(sc, INIT);
@@ -1686,6 +1698,8 @@ carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6)
return (EADDRNOTAVAIL);
if (!sc->sc_naddrs6) {
+ struct in6_multi *in6m;
+
im6o->im6o_multicast_ifp = ifp;
/* join CARP multicast address */
@@ -1694,9 +1708,12 @@ carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6)
in6.s6_addr8[15] = 0x12;
if (in6_setscope(&in6, ifp, NULL) != 0)
goto cleanup;
- if ((imm = in6_joingroup(ifp, &in6, &error, 0)) == NULL)
+ in6m = NULL;
+ error = in6_mc_join(ifp, &in6, NULL, &in6m, 0);
+ if (error)
goto cleanup;
- LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain);
+ im6o->im6o_membership[0] = in6m;
+ im6o->im6o_num_memberships++;
/* join solicited multicast address */
bzero(&in6, sizeof(in6));
@@ -1707,9 +1724,12 @@ carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6)
in6.s6_addr8[12] = 0xff;
if (in6_setscope(&in6, ifp, NULL) != 0)
goto cleanup;
- if ((imm = in6_joingroup(ifp, &in6, &error, 0)) == NULL)
+ in6m = NULL;
+ error = in6_mc_join(ifp, &in6, NULL, &in6m, 0);
+ if (error)
goto cleanup;
- LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain);
+ im6o->im6o_membership[1] = in6m;
+ im6o->im6o_num_memberships++;
}
if (!ifp->if_carp) {
@@ -1781,14 +1801,8 @@ carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6)
return (0);
cleanup:
- /* clean up multicast memberships */
- if (!sc->sc_naddrs6) {
- while (!LIST_EMPTY(&im6o->im6o_memberships)) {
- imm = LIST_FIRST(&im6o->im6o_memberships);
- LIST_REMOVE(imm, i6mm_chain);
- in6_leavegroup(imm);
- }
- }
+ if (!sc->sc_naddrs6)
+ carp_multicast6_cleanup(sc);
return (error);
}
@@ -1799,21 +1813,13 @@ carp_del_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6)
if (!--sc->sc_naddrs6) {
struct carp_if *cif = (struct carp_if *)sc->sc_carpdev->if_carp;
- struct ip6_moptions *im6o = &sc->sc_im6o;
CARP_LOCK(cif);
callout_stop(&sc->sc_ad_tmo);
SC2IFP(sc)->if_flags &= ~IFF_UP;
SC2IFP(sc)->if_drv_flags &= ~IFF_DRV_RUNNING;
sc->sc_vhid = -1;
- while (!LIST_EMPTY(&im6o->im6o_memberships)) {
- struct in6_multi_mship *imm =
- LIST_FIRST(&im6o->im6o_memberships);
-
- LIST_REMOVE(imm, i6mm_chain);
- in6_leavegroup(imm);
- }
- im6o->im6o_multicast_ifp = NULL;
+ carp_multicast6_cleanup(sc);
TAILQ_REMOVE(&cif->vhif_vrs, sc, sc_list);
if (!--cif->vhif_nvrs) {
CARP_LOCK_DESTROY(cif);
OpenPOWER on IntegriCloud