Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/ip_carp.c
Show First 20 Lines • Show All 1,365 Lines • ▼ Show 20 Lines | carp_multicast_setup(struct carp_if *cif, sa_family_t sa) | ||||
struct ifnet *ifp = cif->cif_ifp; | struct ifnet *ifp = cif->cif_ifp; | ||||
int error = 0; | int error = 0; | ||||
switch (sa) { | switch (sa) { | ||||
#ifdef INET | #ifdef INET | ||||
case AF_INET: | case AF_INET: | ||||
{ | { | ||||
struct ip_moptions *imo = &cif->cif_imo; | struct ip_moptions *imo = &cif->cif_imo; | ||||
struct in_mfilter *imf; | |||||
struct in_addr addr; | struct in_addr addr; | ||||
if (imo->imo_membership) | if (ip_first_mfilter(&imo->imo_head) != NULL) | ||||
return (0); | return (0); | ||||
imo->imo_membership = (struct in_multi **)malloc( | imf = ip_alloc_mfilter(M_WAITOK, 0, 0); | ||||
(sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_CARP, | STAILQ_INIT(&imo->imo_head); | ||||
M_WAITOK); | |||||
imo->imo_mfilters = NULL; | |||||
imo->imo_max_memberships = IP_MIN_MEMBERSHIPS; | |||||
imo->imo_multicast_vif = -1; | imo->imo_multicast_vif = -1; | ||||
addr.s_addr = htonl(INADDR_CARP_GROUP); | addr.s_addr = htonl(INADDR_CARP_GROUP); | ||||
if ((error = in_joingroup(ifp, &addr, NULL, | if ((error = in_joingroup(ifp, &addr, NULL, | ||||
&imo->imo_membership[0])) != 0) { | &imf->imf_inm)) != 0) { | ||||
free(imo->imo_membership, M_CARP); | ip_free_mfilter(imf); | ||||
break; | break; | ||||
} | } | ||||
imo->imo_num_memberships++; | |||||
ip_insert_mfilter(&imo->imo_head, imf); | |||||
imo->imo_multicast_ifp = ifp; | imo->imo_multicast_ifp = ifp; | ||||
imo->imo_multicast_ttl = CARP_DFLTTL; | imo->imo_multicast_ttl = CARP_DFLTTL; | ||||
imo->imo_multicast_loop = 0; | imo->imo_multicast_loop = 0; | ||||
break; | break; | ||||
} | } | ||||
#endif | #endif | ||||
#ifdef INET6 | #ifdef INET6 | ||||
case AF_INET6: | case AF_INET6: | ||||
{ | { | ||||
struct ip6_moptions *im6o = &cif->cif_im6o; | struct ip6_moptions *im6o = &cif->cif_im6o; | ||||
struct in6_mfilter *im6f[2]; | |||||
struct in6_addr in6; | struct in6_addr in6; | ||||
struct in6_multi *in6m; | |||||
if (im6o->im6o_membership) | if (ip6_first_mfilter(&im6o->im6o_head)) | ||||
return (0); | return (0); | ||||
im6o->im6o_membership = (struct in6_multi **)malloc( | im6f[0] = ip6_alloc_mfilter(M_WAITOK, 0, 0); | ||||
(sizeof(struct in6_multi *) * IPV6_MIN_MEMBERSHIPS), M_CARP, | im6f[1] = ip6_alloc_mfilter(M_WAITOK, 0, 0); | ||||
M_ZERO | M_WAITOK); | |||||
im6o->im6o_mfilters = NULL; | STAILQ_INIT(&im6o->im6o_head); | ||||
im6o->im6o_max_memberships = IPV6_MIN_MEMBERSHIPS; | |||||
im6o->im6o_multicast_hlim = CARP_DFLTTL; | im6o->im6o_multicast_hlim = CARP_DFLTTL; | ||||
im6o->im6o_multicast_ifp = ifp; | im6o->im6o_multicast_ifp = ifp; | ||||
/* Join IPv6 CARP multicast group. */ | /* Join IPv6 CARP multicast group. */ | ||||
bzero(&in6, sizeof(in6)); | bzero(&in6, sizeof(in6)); | ||||
in6.s6_addr16[0] = htons(0xff02); | in6.s6_addr16[0] = htons(0xff02); | ||||
in6.s6_addr8[15] = 0x12; | in6.s6_addr8[15] = 0x12; | ||||
if ((error = in6_setscope(&in6, ifp, NULL)) != 0) { | if ((error = in6_setscope(&in6, ifp, NULL)) != 0) { | ||||
free(im6o->im6o_membership, M_CARP); | ip6_free_mfilter(im6f[0]); | ||||
ip6_free_mfilter(im6f[1]); | |||||
break; | break; | ||||
} | } | ||||
in6m = NULL; | if ((error = in6_joingroup(ifp, &in6, NULL, &im6f[0]->im6f_in6m, 0)) != 0) { | ||||
if ((error = in6_joingroup(ifp, &in6, NULL, &in6m, 0)) != 0) { | ip6_free_mfilter(im6f[0]); | ||||
free(im6o->im6o_membership, M_CARP); | ip6_free_mfilter(im6f[1]); | ||||
break; | break; | ||||
} | } | ||||
in6m_acquire(in6m); | |||||
im6o->im6o_membership[0] = in6m; | |||||
im6o->im6o_num_memberships++; | |||||
/* Join solicited multicast address. */ | /* Join solicited multicast address. */ | ||||
bzero(&in6, sizeof(in6)); | bzero(&in6, sizeof(in6)); | ||||
in6.s6_addr16[0] = htons(0xff02); | in6.s6_addr16[0] = htons(0xff02); | ||||
in6.s6_addr32[1] = 0; | in6.s6_addr32[1] = 0; | ||||
in6.s6_addr32[2] = htonl(1); | in6.s6_addr32[2] = htonl(1); | ||||
in6.s6_addr32[3] = 0; | in6.s6_addr32[3] = 0; | ||||
in6.s6_addr8[12] = 0xff; | in6.s6_addr8[12] = 0xff; | ||||
if ((error = in6_setscope(&in6, ifp, NULL)) != 0) { | if ((error = in6_setscope(&in6, ifp, NULL)) != 0) { | ||||
in6_leavegroup(im6o->im6o_membership[0], NULL); | ip6_free_mfilter(im6f[0]); | ||||
free(im6o->im6o_membership, M_CARP); | ip6_free_mfilter(im6f[1]); | ||||
break; | break; | ||||
} | } | ||||
in6m = NULL; | |||||
if ((error = in6_joingroup(ifp, &in6, NULL, &in6m, 0)) != 0) { | if ((error = in6_joingroup(ifp, &in6, NULL, &im6f[1]->im6f_in6m, 0)) != 0) { | ||||
in6_leavegroup(im6o->im6o_membership[0], NULL); | in6_leavegroup(im6f[0]->im6f_in6m, NULL); | ||||
free(im6o->im6o_membership, M_CARP); | ip6_free_mfilter(im6f[0]); | ||||
ip6_free_mfilter(im6f[1]); | |||||
break; | break; | ||||
} | } | ||||
in6m_acquire(in6m); | ip6_insert_mfilter(&im6o->im6o_head, im6f[0]); | ||||
im6o->im6o_membership[1] = in6m; | ip6_insert_mfilter(&im6o->im6o_head, im6f[1]); | ||||
im6o->im6o_num_memberships++; | |||||
break; | break; | ||||
} | } | ||||
#endif | #endif | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Free multicast structures. | * Free multicast structures. | ||||
*/ | */ | ||||
static void | static void | ||||
carp_multicast_cleanup(struct carp_if *cif, sa_family_t sa) | carp_multicast_cleanup(struct carp_if *cif, sa_family_t sa) | ||||
{ | { | ||||
sx_assert(&carp_sx, SA_XLOCKED); | sx_assert(&carp_sx, SA_XLOCKED); | ||||
switch (sa) { | switch (sa) { | ||||
#ifdef INET | #ifdef INET | ||||
case AF_INET: | case AF_INET: | ||||
if (cif->cif_naddrs == 0) { | if (cif->cif_naddrs == 0) { | ||||
struct ip_moptions *imo = &cif->cif_imo; | struct ip_moptions *imo = &cif->cif_imo; | ||||
struct in_mfilter *imf; | |||||
in_leavegroup(imo->imo_membership[0], NULL); | while ((imf = ip_first_mfilter(&imo->imo_head)) != NULL) { | ||||
KASSERT(imo->imo_mfilters == NULL, | ip_remove_mfilter(&imo->imo_head, imf); | ||||
("%s: imo_mfilters != NULL", __func__)); | in_leavegroup(imf->imf_inm, NULL); | ||||
free(imo->imo_membership, M_CARP); | ip_free_mfilter(imf); | ||||
imo->imo_membership = NULL; | |||||
} | } | ||||
markj: This line is too long, ditto below. | |||||
} | |||||
break; | break; | ||||
#endif | #endif | ||||
#ifdef INET6 | #ifdef INET6 | ||||
case AF_INET6: | case AF_INET6: | ||||
if (cif->cif_naddrs6 == 0) { | if (cif->cif_naddrs6 == 0) { | ||||
struct ip6_moptions *im6o = &cif->cif_im6o; | struct ip6_moptions *im6o = &cif->cif_im6o; | ||||
struct in6_mfilter *im6f; | |||||
in6_leavegroup(im6o->im6o_membership[0], NULL); | while ((im6f = ip6_first_mfilter(&im6o->im6o_head)) != NULL) { | ||||
in6_leavegroup(im6o->im6o_membership[1], NULL); | ip6_remove_mfilter(&im6o->im6o_head, im6f); | ||||
KASSERT(im6o->im6o_mfilters == NULL, | in6_leavegroup(im6f->im6f_in6m, NULL); | ||||
("%s: im6o_mfilters != NULL", __func__)); | ip6_free_mfilter(im6f); | ||||
free(im6o->im6o_membership, M_CARP); | } | ||||
im6o->im6o_membership = NULL; | |||||
} | } | ||||
break; | break; | ||||
#endif | #endif | ||||
} | } | ||||
} | } | ||||
int | int | ||||
carp_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *sa) | carp_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *sa) | ||||
▲ Show 20 Lines • Show All 813 Lines • Show Last 20 Lines |
This line is too long, ditto below.