Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F157098189
D35307.id106314.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D35307.id106314.diff
View Options
Index: sys/net/if_llatbl.c
===================================================================
--- sys/net/if_llatbl.c
+++ sys/net/if_llatbl.c
@@ -708,6 +708,13 @@
lltable_unlink_entry(llt, lle);
IF_AFDATA_WUNLOCK(ifp);
+#ifdef INET6
+ /* Leave the solicited multicast group for dst. */
+ if ((lle->la_flags & (LLE_PUB | LLE_STATIC | LLE_IFADDR)) ==
+ (LLE_PUB | LLE_STATIC)
+ && l3addr->sa_family == AF_INET6)
+ in6_handle_proxy_ndp_mc(RTM_DELETE, ifp, l3addr);
+#endif
llt->llt_delete_entry(llt, lle);
@@ -978,6 +985,12 @@
&((struct sockaddr_in *)dst)->sin_addr,
(u_char *)LLADDR(dl));
#endif
+#ifdef INET6
+ /* Join the solicited multicast group for dst. */
+ if ((laflags & (LLE_PUB | LLE_STATIC)) == (LLE_PUB | LLE_STATIC)
+ && dst->sa_family == AF_INET6)
+ in6_handle_proxy_ndp_mc(rtm->rtm_type, ifp, dst);
+#endif
break;
Index: sys/netinet6/in6.c
===================================================================
--- sys/netinet6/in6.c
+++ sys/netinet6/in6.c
@@ -2614,3 +2614,116 @@
free(*nam, M_SONAME);
*nam = (struct sockaddr *)sin6_p;
}
+
+/*
+ * Join/leave the solicited multicast groups for proxy NDP entries.
+ */
+static struct mtx pndp_mc_list_mtx;
+MTX_SYSINIT(pndp_mc_list_mtx, &pndp_mc_list_mtx, "pndp_mc_listmtx", MTX_DEF);
+#define PNDP_MC_LIST_LOCK() mtx_lock(&pndp_mc_list_mtx)
+#define PNDP_MC_LIST_UNLOCK() mtx_unlock(&pndp_mc_list_mtx)
+
+static LIST_HEAD(in6_pndp_mc_list, in6_multi_mship) pndp_mc_list;
+
+static void in6_pndp_mc_list_add(struct in6_multi_mship *imm);
+static void in6_pndp_mc_list_delete(struct in6_multi *inm);
+
+void
+in6_handle_proxy_ndp_mc(int cmd, struct ifnet *ifp, const struct sockaddr *sa)
+{
+ const struct sockaddr_in6 *sin6;
+ struct in6_multi_mship *imm;
+ struct in6_multi *inm;
+ struct in6_addr mltaddr;
+ struct epoch_tracker et;
+ char ip6buf[INET6_ADDRSTRLEN];
+ int error;
+
+ sin6 = (const struct sockaddr_in6 *)sa;
+ bzero(&mltaddr, sizeof(struct in6_addr));
+ mltaddr.s6_addr32[0] = IPV6_ADDR_INT32_MLL;
+ mltaddr.s6_addr32[2] = htonl(1);
+ mltaddr.s6_addr32[3] = sin6->sin6_addr.s6_addr32[3];
+ mltaddr.s6_addr8[12] = 0xff;
+ if ((error = in6_setscope(&mltaddr, ifp, NULL)) != 0) {
+ nd6log((LOG_ERR, "%s: in6_setscope failed\n", __func__));
+ return;
+ }
+ if (cmd == RTM_ADD) {
+ imm = in6_joingroup_legacy(ifp, &mltaddr, &error, 0);
+ if (imm != NULL)
+ in6_pndp_mc_list_add(imm);
+ else {
+ nd6log((LOG_WARNING,
+ "%s: in6_joingroup_legacy failed for %s on %s "
+ "(errno=%d)\n", __func__,
+ ip6_sprintf(ip6buf, &mltaddr), if_name(ifp),
+ error));
+ return;
+ }
+ } else {
+ NET_EPOCH_ENTER(et);
+ inm = in6m_lookup(ifp, &mltaddr);
+ NET_EPOCH_EXIT(et);
+ if (inm != NULL) {
+ in6_pndp_mc_list_delete(inm);
+ in6_leavegroup(inm, NULL);
+ } else {
+ nd6log((LOG_WARNING,
+ "%s: in6_lookup failed for %s on %s\n",
+ __func__, ip6_sprintf(ip6buf, &mltaddr),
+ if_name(ifp)));
+ }
+ }
+}
+
+void
+in6_purge_proxy_ndp_mc(struct ifnet *ifp)
+{
+ struct in6_pndp_mc_list removed;
+ struct in6_multi_mship *imm;
+
+ LIST_INIT(&removed);
+ PNDP_MC_LIST_LOCK();
+ LIST_FOREACH(imm, &pndp_mc_list, i6mm_chain) {
+ if (imm->i6mm_maddr->in6m_ifp == ifp) {
+ LIST_REMOVE(imm, i6mm_chain);
+ LIST_INSERT_HEAD(&removed, imm, i6mm_chain);
+ }
+ }
+ PNDP_MC_LIST_UNLOCK();
+
+ while ((imm = LIST_FIRST(&removed)) != NULL) {
+ LIST_REMOVE(imm, i6mm_chain);
+ in6_leavegroup(imm->i6mm_maddr, NULL);
+ free(imm, M_IP6MADDR);
+ }
+}
+
+static void
+in6_pndp_mc_list_add(struct in6_multi_mship *imm)
+{
+ PNDP_MC_LIST_LOCK();
+ LIST_INSERT_HEAD(&pndp_mc_list, imm, i6mm_chain);
+ PNDP_MC_LIST_UNLOCK();
+}
+
+static void
+in6_pndp_mc_list_delete(struct in6_multi *inm)
+{
+ struct in6_multi_mship *imm;
+
+ PNDP_MC_LIST_LOCK();
+ LIST_FOREACH(imm, &pndp_mc_list, i6mm_chain) {
+ if (imm->i6mm_maddr == inm) {
+ LIST_REMOVE(imm, i6mm_chain);
+ break;
+ }
+ }
+ PNDP_MC_LIST_UNLOCK();
+ if (imm != NULL)
+ free(imm, M_IP6MADDR);
+ else
+ nd6log((LOG_WARNING,
+ "in6_multi %p not found on proxy ndp list.\n", inm));
+}
Index: sys/netinet6/in6_ifattach.c
===================================================================
--- sys/netinet6/in6_ifattach.c
+++ sys/netinet6/in6_ifattach.c
@@ -861,6 +861,7 @@
{
struct in6_multi_head inmh;
+ in6_purge_proxy_ndp_mc(ifp);
SLIST_INIT(&inmh);
IN6_MULTI_LOCK();
IN6_MULTI_LIST_LOCK();
Index: sys/netinet6/in6_var.h
===================================================================
--- sys/netinet6/in6_var.h
+++ sys/netinet6/in6_var.h
@@ -916,6 +916,9 @@
int in6_src_ioctl(u_long, caddr_t);
void in6_newaddrmsg(struct in6_ifaddr *, int);
+
+void in6_handle_proxy_ndp_mc(int, struct ifnet *, const struct sockaddr *);
+void in6_purge_proxy_ndp_mc(struct ifnet *);
/*
* Extended API for IPv6 FIB support.
*/
Index: sys/netinet6/nd6_nbr.c
===================================================================
--- sys/netinet6/nd6_nbr.c
+++ sys/netinet6/nd6_nbr.c
@@ -255,33 +255,29 @@
/* (2) check. */
proxy = 0;
if (ifa == NULL) {
- struct sockaddr_dl rt_gateway;
- struct rt_addrinfo info;
- struct sockaddr_in6 dst6;
-
- bzero(&dst6, sizeof(dst6));
- dst6.sin6_len = sizeof(struct sockaddr_in6);
- dst6.sin6_family = AF_INET6;
- dst6.sin6_addr = taddr6;
-
- bzero(&rt_gateway, sizeof(rt_gateway));
- rt_gateway.sdl_len = sizeof(rt_gateway);
- bzero(&info, sizeof(info));
- info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&rt_gateway;
-
- if (rib_lookup_info(ifp->if_fib, (struct sockaddr *)&dst6,
- 0, 0, &info) == 0) {
- if ((info.rti_flags & RTF_ANNOUNCE) != 0 &&
- rt_gateway.sdl_family == AF_LINK) {
- /*
- * proxy NDP for single entry
- */
- proxydl = *SDL(&rt_gateway);
+ struct llentry *ln;
+
+ ln = nd6_lookup(&taddr6, LLE_SF(AF_INET6, 0), ifp);
+ if (ln != NULL) {
+#define LLE_PROXY_ND (LLE_PUB | LLE_STATIC | LLE_VALID)
+ /*
+ * ifa == NULL here should be sufficient for proxy,
+ * but we can check by !LLE_IFADDR also.
+ */
+ if ((ln->la_flags & (LLE_PROXY_ND | LLE_IFADDR))
+ == LLE_PROXY_ND) {
+ link_init_sdl(ifp, (struct sockaddr *)&proxydl,
+ ifp->if_type);
+ proxydl.sdl_alen = ifp->if_addrlen;
+ bcopy(ln->ll_addr, &proxydl.sdl_data,
+ ifp->if_addrlen);
ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(
ifp, IN6_IFF_NOTREADY|IN6_IFF_ANYCAST);
if (ifa)
proxy = 1;
+#undef LLE_PROXY_ND
}
+ LLE_RUNLOCK(ln);
}
}
if (ifa == NULL) {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, May 19, 10:38 AM (20 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33308098
Default Alt Text
D35307.id106314.diff (6 KB)
Attached To
Mode
D35307: netinet6: fix proxy NDP
Attached
Detach File
Event Timeline
Log In to Comment