Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet6/in6.c
Show First 20 Lines • Show All 156 Lines • ▼ Show 20 Lines | static int in6_validate_ifra(struct ifnet *, struct in6_aliasreq *, | ||||||||||||||||||
struct in6_ifaddr *, int); | struct in6_ifaddr *, int); | ||||||||||||||||||
static struct in6_ifaddr *in6_alloc_ifa(struct ifnet *, | static struct in6_ifaddr *in6_alloc_ifa(struct ifnet *, | ||||||||||||||||||
struct in6_aliasreq *, int flags); | struct in6_aliasreq *, int flags); | ||||||||||||||||||
static int in6_update_ifa_internal(struct ifnet *, struct in6_aliasreq *, | static int in6_update_ifa_internal(struct ifnet *, struct in6_aliasreq *, | ||||||||||||||||||
struct in6_ifaddr *, int, int); | struct in6_ifaddr *, int, int); | ||||||||||||||||||
static int in6_broadcast_ifa(struct ifnet *, struct in6_aliasreq *, | static int in6_broadcast_ifa(struct ifnet *, struct in6_aliasreq *, | ||||||||||||||||||
struct in6_ifaddr *, int); | struct in6_ifaddr *, int); | ||||||||||||||||||
static void in6_join_proxy_ndp_mc(struct ifnet *, const struct in6_addr *); | |||||||||||||||||||
static void in6_leave_proxy_ndp_mc(struct ifnet *, const struct in6_addr *); | |||||||||||||||||||
#define ifa2ia6(ifa) ((struct in6_ifaddr *)(ifa)) | #define ifa2ia6(ifa) ((struct in6_ifaddr *)(ifa)) | ||||||||||||||||||
#define ia62ifa(ia6) (&((ia6)->ia_ifa)) | #define ia62ifa(ia6) (&((ia6)->ia_ifa)) | ||||||||||||||||||
void | void | ||||||||||||||||||
in6_newaddrmsg(struct in6_ifaddr *ia, int cmd) | in6_newaddrmsg(struct in6_ifaddr *ia, int cmd) | ||||||||||||||||||
{ | { | ||||||||||||||||||
struct rt_addrinfo info; | struct rt_addrinfo info; | ||||||||||||||||||
struct ifaddr *ifa; | struct ifaddr *ifa; | ||||||||||||||||||
▲ Show 20 Lines • Show All 563 Lines • ▼ Show 20 Lines | in6_joingroup_legacy(struct ifnet *ifp, const struct in6_addr *mcaddr, | ||||||||||||||||||
if (error) { | if (error) { | ||||||||||||||||||
*errorp = error; | *errorp = error; | ||||||||||||||||||
free(imm, M_IP6MADDR); | free(imm, M_IP6MADDR); | ||||||||||||||||||
return (NULL); | return (NULL); | ||||||||||||||||||
} | } | ||||||||||||||||||
return (imm); | return (imm); | ||||||||||||||||||
} | } | ||||||||||||||||||
static int | |||||||||||||||||||
in6_solicited_node_maddr(struct in6_addr *maddr, | |||||||||||||||||||
struct ifnet *ifp, const struct in6_addr *base) | |||||||||||||||||||
{ | |||||||||||||||||||
int error; | |||||||||||||||||||
bzero(maddr, sizeof(struct in6_addr)); | |||||||||||||||||||
maddr->s6_addr32[0] = IPV6_ADDR_INT32_MLL; | |||||||||||||||||||
maddr->s6_addr32[2] = htonl(1); | |||||||||||||||||||
maddr->s6_addr32[3] = base->s6_addr32[3]; | |||||||||||||||||||
maddr->s6_addr8[12] = 0xff; | |||||||||||||||||||
if ((error = in6_setscope(maddr, ifp, NULL)) != 0) { | |||||||||||||||||||
/* XXX: should not happen */ | |||||||||||||||||||
log(LOG_ERR, "%s: in6_setscope failed\n", __func__); | |||||||||||||||||||
} | |||||||||||||||||||
return error; | |||||||||||||||||||
} | |||||||||||||||||||
/* | /* | ||||||||||||||||||
* Join necessary multicast groups. Factored out from in6_update_ifa(). | * Join necessary multicast groups. Factored out from in6_update_ifa(). | ||||||||||||||||||
* This entire work should only be done once, for the default FIB. | * This entire work should only be done once, for the default FIB. | ||||||||||||||||||
*/ | */ | ||||||||||||||||||
static int | static int | ||||||||||||||||||
in6_update_ifa_join_mc(struct ifnet *ifp, struct in6_aliasreq *ifra, | in6_update_ifa_join_mc(struct ifnet *ifp, struct in6_aliasreq *ifra, | ||||||||||||||||||
struct in6_ifaddr *ia, int flags, struct in6_multi **in6m_sol) | struct in6_ifaddr *ia, int flags, struct in6_multi **in6m_sol) | ||||||||||||||||||
{ | { | ||||||||||||||||||
char ip6buf[INET6_ADDRSTRLEN]; | char ip6buf[INET6_ADDRSTRLEN]; | ||||||||||||||||||
struct in6_addr mltaddr; | struct in6_addr mltaddr; | ||||||||||||||||||
struct in6_multi_mship *imm; | struct in6_multi_mship *imm; | ||||||||||||||||||
int delay, error; | int delay, error; | ||||||||||||||||||
KASSERT(in6m_sol != NULL, ("%s: in6m_sol is NULL", __func__)); | KASSERT(in6m_sol != NULL, ("%s: in6m_sol is NULL", __func__)); | ||||||||||||||||||
/* Join solicited multicast addr for new host id. */ | /* Join solicited multicast addr for new host id. */ | ||||||||||||||||||
bzero(&mltaddr, sizeof(struct in6_addr)); | if ((error = in6_solicited_node_maddr(&mltaddr, ifp, | ||||||||||||||||||
mltaddr.s6_addr32[0] = IPV6_ADDR_INT32_MLL; | &ifra->ifra_addr.sin6_addr)) != 0) | ||||||||||||||||||
mltaddr.s6_addr32[2] = htonl(1); | |||||||||||||||||||
mltaddr.s6_addr32[3] = ifra->ifra_addr.sin6_addr.s6_addr32[3]; | |||||||||||||||||||
mltaddr.s6_addr8[12] = 0xff; | |||||||||||||||||||
if ((error = in6_setscope(&mltaddr, ifp, NULL)) != 0) { | |||||||||||||||||||
/* XXX: should not happen */ | |||||||||||||||||||
log(LOG_ERR, "%s: in6_setscope failed\n", __func__); | |||||||||||||||||||
goto cleanup; | goto cleanup; | ||||||||||||||||||
} | |||||||||||||||||||
delay = error = 0; | delay = error = 0; | ||||||||||||||||||
if ((flags & IN6_IFAUPDATE_DADDELAY)) { | if ((flags & IN6_IFAUPDATE_DADDELAY)) { | ||||||||||||||||||
/* | /* | ||||||||||||||||||
* We need a random delay for DAD on the address being | * We need a random delay for DAD on the address being | ||||||||||||||||||
* configured. It also means delaying transmission of the | * configured. It also means delaying transmission of the | ||||||||||||||||||
* corresponding MLD report to avoid report collision. | * corresponding MLD report to avoid report collision. | ||||||||||||||||||
* [RFC 4861, Section 6.3.7] | * [RFC 4861, Section 6.3.7] | ||||||||||||||||||
*/ | */ | ||||||||||||||||||
▲ Show 20 Lines • Show All 1,502 Lines • ▼ Show 20 Lines | in6_lltable_find_dst(struct lltable *llt, const struct in6_addr *dst) | ||||||||||||||||||
return (lle); | return (lle); | ||||||||||||||||||
} | } | ||||||||||||||||||
static void | static void | ||||||||||||||||||
in6_lltable_delete_entry(struct lltable *llt, struct llentry *lle) | in6_lltable_delete_entry(struct lltable *llt, struct llentry *lle) | ||||||||||||||||||
{ | { | ||||||||||||||||||
lle->la_flags |= LLE_DELETED; | lle->la_flags |= LLE_DELETED; | ||||||||||||||||||
/* Leave the solicited multicast group. */ | |||||||||||||||||||
if ((lle->la_flags & LLE_PUB) != 0) | |||||||||||||||||||
in6_leave_proxy_ndp_mc(llt->llt_ifp, &lle->r_l3addr.addr6); | |||||||||||||||||||
EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_DELETED); | EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_DELETED); | ||||||||||||||||||
#ifdef DIAGNOSTIC | #ifdef DIAGNOSTIC | ||||||||||||||||||
log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle); | log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle); | ||||||||||||||||||
#endif | #endif | ||||||||||||||||||
llentry_free(lle); | llentry_free(lle); | ||||||||||||||||||
} | } | ||||||||||||||||||
static struct llentry * | static struct llentry * | ||||||||||||||||||
▲ Show 20 Lines • Show All 162 Lines • ▼ Show 20 Lines | #endif | ||||||||||||||||||
error = SYSCTL_OUT(wr, &ndpc, sizeof(ndpc)); | error = SYSCTL_OUT(wr, &ndpc, sizeof(ndpc)); | ||||||||||||||||||
return (error); | return (error); | ||||||||||||||||||
} | } | ||||||||||||||||||
static void | static void | ||||||||||||||||||
in6_lltable_post_resolved(struct lltable *llt, struct llentry *lle) | in6_lltable_post_resolved(struct lltable *llt, struct llentry *lle) | ||||||||||||||||||
{ | { | ||||||||||||||||||
/* Handle proxy NDP entries (not yet). */ | /* Join the solicited multicast group for dst. */ | ||||||||||||||||||
if ((lle->la_flags & LLE_PUB) == LLE_PUB) | |||||||||||||||||||
in6_join_proxy_ndp_mc(llt->llt_ifp, &lle->r_l3addr.addr6); | |||||||||||||||||||
} | } | ||||||||||||||||||
static struct lltable * | static struct lltable * | ||||||||||||||||||
in6_lltattach(struct ifnet *ifp) | in6_lltattach(struct ifnet *ifp) | ||||||||||||||||||
{ | { | ||||||||||||||||||
struct lltable *llt; | struct lltable *llt; | ||||||||||||||||||
llt = lltable_allocate_htbl(IN6_LLTBL_DEFAULT_HSIZE); | llt = lltable_allocate_htbl(IN6_LLTBL_DEFAULT_HSIZE); | ||||||||||||||||||
▲ Show 20 Lines • Show All 140 Lines • ▼ Show 20 Lines | in6_sin_2_v4mapsin6_in_sock(struct sockaddr **nam) | ||||||||||||||||||
struct sockaddr_in *sin_p; | struct sockaddr_in *sin_p; | ||||||||||||||||||
struct sockaddr_in6 *sin6_p; | struct sockaddr_in6 *sin6_p; | ||||||||||||||||||
sin6_p = malloc(sizeof *sin6_p, M_SONAME, M_WAITOK); | sin6_p = malloc(sizeof *sin6_p, M_SONAME, M_WAITOK); | ||||||||||||||||||
sin_p = (struct sockaddr_in *)*nam; | sin_p = (struct sockaddr_in *)*nam; | ||||||||||||||||||
in6_sin_2_v4mapsin6(sin_p, sin6_p); | in6_sin_2_v4mapsin6(sin_p, sin6_p); | ||||||||||||||||||
free(*nam, M_SONAME); | free(*nam, M_SONAME); | ||||||||||||||||||
*nam = (struct sockaddr *)sin6_p; | *nam = (struct sockaddr *)sin6_p; | ||||||||||||||||||
} | |||||||||||||||||||
/* | |||||||||||||||||||
* Join/leave the solicited multicast groups for proxy NDP entries. | |||||||||||||||||||
melifaro: I'd prefer using existing bits&pieces that we have instead of introducing another layer of… | |||||||||||||||||||
Done Inline Actions
I have submitted D35323 to prepare for adding the member. Could you review it?
I'll try to change the code as you proposed. takahiro.kurosawa_gmail.com: > I'd suggest doing the following:
> * mark lltable (for example, by introducing special… | |||||||||||||||||||
Done Inline ActionsI've added lltable_flags_free() for purging LLEs on if_detach case. If I miss the point, let me know. takahiro.kurosawa_gmail.com: I've added lltable_flags_free() for purging LLEs on if_detach case. If I miss the point, let… | |||||||||||||||||||
*/ | |||||||||||||||||||
static void | |||||||||||||||||||
in6_join_proxy_ndp_mc(struct ifnet *ifp, const struct in6_addr *dst) | |||||||||||||||||||
{ | |||||||||||||||||||
struct in6_multi *inm; | |||||||||||||||||||
struct in6_addr mltaddr; | |||||||||||||||||||
char ip6buf[INET6_ADDRSTRLEN]; | |||||||||||||||||||
int error; | |||||||||||||||||||
if (in6_solicited_node_maddr(&mltaddr, ifp, dst) != 0) | |||||||||||||||||||
return; /* error logged in in6_solicited_node_maddr. */ | |||||||||||||||||||
error = in6_joingroup(ifp, &mltaddr, NULL, &inm, 0); | |||||||||||||||||||
if (error != 0) { | |||||||||||||||||||
nd6log((LOG_WARNING, | |||||||||||||||||||
"%s: in6_joingroup failed for %s on %s (errno=%d)\n", | |||||||||||||||||||
__func__, ip6_sprintf(ip6buf, &mltaddr), if_name(ifp), | |||||||||||||||||||
error)); | |||||||||||||||||||
} | |||||||||||||||||||
} | |||||||||||||||||||
Not Done Inline ActionsProbably worth splitting add&delete use cases to the separation functions as they don't share anything except 1 line (in6_solicited_node_maddr). melifaro: Probably worth splitting add&delete use cases to the separation functions as they don't share… | |||||||||||||||||||
Done Inline ActionsApplied, thanks! takahiro.kurosawa_gmail.com: Applied, thanks! | |||||||||||||||||||
static void | |||||||||||||||||||
in6_leave_proxy_ndp_mc(struct ifnet *ifp, const struct in6_addr *dst) | |||||||||||||||||||
{ | |||||||||||||||||||
struct epoch_tracker et; | |||||||||||||||||||
struct in6_multi *inm; | |||||||||||||||||||
struct in6_addr mltaddr; | |||||||||||||||||||
char ip6buf[INET6_ADDRSTRLEN]; | |||||||||||||||||||
if (in6_solicited_node_maddr(&mltaddr, ifp, dst) != 0) | |||||||||||||||||||
return; /* error logged in in6_solicited_node_maddr. */ | |||||||||||||||||||
NET_EPOCH_ENTER(et); | |||||||||||||||||||
inm = in6m_lookup(ifp, &mltaddr); | |||||||||||||||||||
NET_EPOCH_EXIT(et); | |||||||||||||||||||
if (inm != NULL) | |||||||||||||||||||
in6_leavegroup(inm, NULL); | |||||||||||||||||||
else | |||||||||||||||||||
nd6log((LOG_WARNING, "%s: in6m_lookup failed for %s on %s\n", | |||||||||||||||||||
__func__, ip6_sprintf(ip6buf, &mltaddr), if_name(ifp))); | |||||||||||||||||||
} | |||||||||||||||||||
static bool | |||||||||||||||||||
Not Done Inline ActionsCould you factor out this code from in6_update_ifa_join_mc() into a separate function, which can be used both here and in in6_update_ifa_join_mc() so we don't duplicate the logic? melifaro: Could you factor out this code from `in6_update_ifa_join_mc()` into a separate function, which… | |||||||||||||||||||
Done Inline ActionsI've added in6_solicited_node_maddr() for factoring out the common part. takahiro.kurosawa_gmail.com: I've added in6_solicited_node_maddr() for factoring out the common part. | |||||||||||||||||||
in6_lle_match_pub(struct lltable *llt, struct llentry *lle, void *farg) | |||||||||||||||||||
{ | |||||||||||||||||||
return ((lle->la_flags & LLE_PUB) != 0); | |||||||||||||||||||
} | |||||||||||||||||||
void | |||||||||||||||||||
in6_purge_proxy_ndp(struct ifnet *ifp) | |||||||||||||||||||
{ | |||||||||||||||||||
struct lltable *llt; | |||||||||||||||||||
bool need_purge; | |||||||||||||||||||
llt = LLTABLE6(ifp); | |||||||||||||||||||
IF_AFDATA_WLOCK(ifp); | |||||||||||||||||||
need_purge = ((llt->llt_flags & LLT_ADDEDPROXY) != 0); | |||||||||||||||||||
IF_AFDATA_WUNLOCK(ifp); | |||||||||||||||||||
/* | |||||||||||||||||||
* Ever added proxy ndp entries, leave solicited node multicast | |||||||||||||||||||
* before deleting the llentry. | |||||||||||||||||||
*/ | |||||||||||||||||||
if (need_purge) | |||||||||||||||||||
lltable_delete_conditional(llt, in6_lle_match_pub, NULL); | |||||||||||||||||||
} | } | ||||||||||||||||||
Not Done Inline Actions
Nit: probably be a bit simpler. melifaro: Nit: probably be a bit simpler. | |||||||||||||||||||
Done Inline ActionsApplied. takahiro.kurosawa_gmail.com: Applied. |
I'd prefer using existing bits&pieces that we have instead of introducing another layer of locking.
I'd suggest doing the following: