Module Name: src Committed By: martin Date: Tue Nov 6 14:38:58 UTC 2018
Modified Files: src/sys/net [netbsd-8]: if.c route.c route.h src/sys/netinet [netbsd-8]: if_arp.c src/sys/netinet6 [netbsd-8]: in6.c nd6.c Log Message: Pull up following revision(s) (requested by ozaki-r in ticket #1080): sys/netinet6/nd6.c: revision 1.251 sys/netinet/if_arp.c: revision 1.276 sys/net/if.c: revision 1.438 sys/net/if.c: revision 1.439 sys/net/route.c: revision 1.214 sys/net/route.c: revision 1.215 sys/net/route.c: revision 1.216 sys/netinet6/in6.c: revision 1.270 sys/net/route.h: revision 1.120 sys/net/if.c: revision 1.440 Remove a wrong assertion in ifaref - Doing ifref on an ifa with IFA_DESTROYING is not a problem; the reference should be dropped during the destruction of the ifa. - Use atomic operations for ifa_refcnt - Avoid a dangling pointer during rt_replace_ifa - Avoid double rt_replace_ifa on rtrequest1(RTM_ADD) Some callers of rtrequest1(RTM_ADD) adjust rt_ifa of an rtentry created by rtrequest1 that may change rt_ifa (in ifa_rtrequest) with another ifa that is different from requested one. It's wasteful and even worse introduces a race condition. rtrequest1 should just use a passed ifa as is if a caller hopes so. - Use rt_update framework on updating a rtentry To generate a diff of this commit: cvs rdiff -u -r1.394.2.14 -r1.394.2.15 src/sys/net/if.c cvs rdiff -u -r1.194.6.11 -r1.194.6.12 src/sys/net/route.c cvs rdiff -u -r1.112.4.4 -r1.112.4.5 src/sys/net/route.h cvs rdiff -u -r1.250.2.8 -r1.250.2.9 src/sys/netinet/if_arp.c cvs rdiff -u -r1.245.2.11 -r1.245.2.12 src/sys/netinet6/in6.c cvs rdiff -u -r1.232.2.8 -r1.232.2.9 src/sys/netinet6/nd6.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/net/if.c diff -u src/sys/net/if.c:1.394.2.14 src/sys/net/if.c:1.394.2.15 --- src/sys/net/if.c:1.394.2.14 Mon Aug 27 07:49:11 2018 +++ src/sys/net/if.c Tue Nov 6 14:38:58 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if.c,v 1.394.2.14 2018/08/27 07:49:11 martin Exp $ */ +/* $NetBSD: if.c,v 1.394.2.15 2018/11/06 14:38:58 martin Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc. @@ -90,7 +90,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.394.2.14 2018/08/27 07:49:11 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.394.2.15 2018/11/06 14:38:58 martin Exp $"); #if defined(_KERNEL_OPT) #include "opt_inet.h" @@ -1777,8 +1777,8 @@ ifa_psref_init(struct ifaddr *ifa) void ifaref(struct ifaddr *ifa) { - KASSERT(!ISSET(ifa->ifa_flags, IFA_DESTROYING)); - ifa->ifa_refcnt++; + + atomic_inc_uint(&ifa->ifa_refcnt); } void @@ -1787,7 +1787,7 @@ ifafree(struct ifaddr *ifa) KASSERT(ifa != NULL); KASSERT(ifa->ifa_refcnt > 0); - if (--ifa->ifa_refcnt == 0) { + if (atomic_dec_uint_nv(&ifa->ifa_refcnt) == 0) { free(ifa, M_IFADDR); } } @@ -2177,7 +2177,8 @@ link_rtrequest(int cmd, struct rtentry * struct psref psref; if (cmd != RTM_ADD || (ifa = rt->rt_ifa) == NULL || - (ifp = ifa->ifa_ifp) == NULL || (dst = rt_getkey(rt)) == NULL) + (ifp = ifa->ifa_ifp) == NULL || (dst = rt_getkey(rt)) == NULL || + ISSET(info->rti_flags, RTF_DONTCHANGEIFA)) return; if ((ifa = ifaof_ifpforaddr_psref(dst, ifp, &psref)) != NULL) { rt_replace_ifa(rt, ifa); @@ -2431,6 +2432,9 @@ p2p_rtrequest(int req, struct rtentry *r rt->rt_ifp = lo0ifp; + if (ISSET(info->rti_flags, RTF_DONTCHANGEIFA)) + break; + IFADDR_READER_FOREACH(ifa, ifp) { if (equal(rt_getkey(rt), ifa->ifa_addr)) break; Index: src/sys/net/route.c diff -u src/sys/net/route.c:1.194.6.11 src/sys/net/route.c:1.194.6.12 --- src/sys/net/route.c:1.194.6.11 Fri Sep 7 12:31:30 2018 +++ src/sys/net/route.c Tue Nov 6 14:38:58 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: route.c,v 1.194.6.11 2018/09/07 12:31:30 martin Exp $ */ +/* $NetBSD: route.c,v 1.194.6.12 2018/11/06 14:38:58 martin Exp $ */ /*- * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc. @@ -97,7 +97,7 @@ #endif #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.194.6.11 2018/09/07 12:31:30 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.194.6.12 2018/11/06 14:38:58 martin Exp $"); #include <sys/param.h> #ifdef RTFLUSH_DEBUG @@ -406,6 +406,11 @@ rt_ifa_connected(const struct rtentry *r void rt_replace_ifa(struct rtentry *rt, struct ifaddr *ifa) { + struct ifaddr *old; + + if (rt->rt_ifa == ifa) + return; + if (rt->rt_ifa && rt->rt_ifa != ifa && rt->rt_ifa->ifa_flags & IFA_ROUTE && @@ -424,8 +429,9 @@ rt_replace_ifa(struct rtentry *rt, struc } ifaref(ifa); - ifafree(rt->rt_ifa); + old = rt->rt_ifa; rt_set_ifa1(rt, ifa); + ifafree(old); } static void @@ -1236,7 +1242,7 @@ rtrequest1(int req, struct rt_addrinfo * if (rt == NULL) senderr(ENOBUFS); memset(rt, 0, sizeof(*rt)); - rt->rt_flags = RTF_UP | flags; + rt->rt_flags = RTF_UP | (flags & ~RTF_DONTCHANGEIFA); LIST_INIT(&rt->rt_timer); RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); @@ -1599,7 +1605,7 @@ rtinit(struct ifaddr *ifa, int cmd, int } memset(&info, 0, sizeof(info)); info.rti_ifa = ifa; - info.rti_flags = flags | ifa->ifa_flags; + info.rti_flags = flags | ifa->ifa_flags | RTF_DONTCHANGEIFA; info.rti_info[RTAX_DST] = dst; info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; @@ -1630,40 +1636,7 @@ rtinit(struct ifaddr *ifa, int cmd, int rt_unref(rt); break; case RTM_ADD: - /* - * XXX it looks just reverting rt_ifa replaced by ifa_rtrequest - * called via rtrequest1. Can we just prevent the replacement - * somehow and remove the following code? And also doesn't - * calling ifa_rtrequest(RTM_ADD) replace rt_ifa again? - */ - if (rt->rt_ifa != ifa) { - printf("rtinit: wrong ifa (%p) was (%p)\n", ifa, - rt->rt_ifa); -#ifdef NET_MPSAFE - KASSERT(!cpu_softintr_p()); - - error = rt_update_prepare(rt); - if (error == 0) { -#endif - if (rt->rt_ifa->ifa_rtrequest != NULL) { - rt->rt_ifa->ifa_rtrequest(RTM_DELETE, - rt, &info); - } - rt_replace_ifa(rt, ifa); - rt->rt_ifp = ifa->ifa_ifp; - if (ifa->ifa_rtrequest != NULL) - ifa->ifa_rtrequest(RTM_ADD, rt, &info); -#ifdef NET_MPSAFE - rt_update_finish(rt); - } else { - /* - * If error != 0, the rtentry is being - * destroyed, so doing nothing doesn't - * matter. - */ - } -#endif - } + KASSERT(rt->rt_ifa == ifa); rt_newmsg(cmd, rt); rt_unref(rt); RT_REFCNT_TRACE(rt); @@ -1695,17 +1668,16 @@ rt_ifa_addlocal(struct ifaddr *ifa) struct rtentry *nrt; memset(&info, 0, sizeof(info)); - info.rti_flags = RTF_HOST | RTF_LOCAL; + info.rti_flags = RTF_HOST | RTF_LOCAL | RTF_DONTCHANGEIFA; info.rti_info[RTAX_DST] = ifa->ifa_addr; info.rti_info[RTAX_GATEWAY] = (const struct sockaddr *)ifa->ifa_ifp->if_sadl; info.rti_ifa = ifa; nrt = NULL; e = rtrequest1(RTM_ADD, &info, &nrt); - if (nrt && ifa != nrt->rt_ifa) - rt_replace_ifa(nrt, ifa); rt_newaddrmsg(RTM_ADD, ifa, e, nrt); if (nrt != NULL) { + KASSERT(nrt->rt_ifa == ifa); #ifdef RT_DEBUG dump_rt(nrt); #endif @@ -1758,7 +1730,21 @@ rt_ifa_remlocal(struct ifaddr *ifa, stru } rt_newaddrmsg(RTM_DELADDR, ifa, 0, NULL); } else { +#ifdef NET_MPSAFE + int error = rt_update_prepare(rt); + if (error == 0) { + rt_replace_ifa(rt, alt_ifa); + rt_update_finish(rt); + } else { + /* + * If error != 0, the rtentry is being + * destroyed, so doing nothing doesn't + * matter. + */ + } +#else rt_replace_ifa(rt, alt_ifa); +#endif rt_newmsg(RTM_CHANGE, rt); } } else Index: src/sys/net/route.h diff -u src/sys/net/route.h:1.112.4.4 src/sys/net/route.h:1.112.4.5 --- src/sys/net/route.h:1.112.4.4 Sat Apr 14 10:16:19 2018 +++ src/sys/net/route.h Tue Nov 6 14:38:58 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: route.h,v 1.112.4.4 2018/04/14 10:16:19 martin Exp $ */ +/* $NetBSD: route.h,v 1.112.4.5 2018/11/06 14:38:58 martin Exp $ */ /* * Copyright (c) 1980, 1986, 1993 @@ -172,6 +172,11 @@ struct ortentry { #define RTF_LOCAL 0x40000 /* route represents a local address */ #define RTF_BROADCAST 0x80000 /* route represents a bcast address */ #define RTF_UPDATING 0x100000 /* route is updating */ +/* + * The flag is nevert set to rt_flags. It just tells rtrequest1 to set a passed + * ifa to rt_ifa (via rti_ifa) and not replace rt_ifa in ifa_rtrequest. + */ +#define RTF_DONTCHANGEIFA 0x200000 /* suppress rt_ifa replacement */ /* * Routing statistics. Index: src/sys/netinet/if_arp.c diff -u src/sys/netinet/if_arp.c:1.250.2.8 src/sys/netinet/if_arp.c:1.250.2.9 --- src/sys/netinet/if_arp.c:1.250.2.8 Mon Apr 2 08:54:35 2018 +++ src/sys/netinet/if_arp.c Tue Nov 6 14:38:58 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if_arp.c,v 1.250.2.8 2018/04/02 08:54:35 martin Exp $ */ +/* $NetBSD: if_arp.c,v 1.250.2.9 2018/11/06 14:38:58 martin Exp $ */ /*- * Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc. @@ -68,7 +68,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.250.2.8 2018/04/02 08:54:35 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.250.2.9 2018/11/06 14:38:58 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_ddb.h" @@ -603,6 +603,11 @@ arp_rtrequest(int req, struct rtentry *r rt->rt_rmx.rmx_mtu = 0; } rt->rt_flags |= RTF_LOCAL; + + if (ISSET(info->rti_flags, RTF_DONTCHANGEIFA)) { + pserialize_read_exit(s); + goto out; + } /* * make sure to set rt->rt_ifa to the interface * address we are using, otherwise we will have trouble Index: src/sys/netinet6/in6.c diff -u src/sys/netinet6/in6.c:1.245.2.11 src/sys/netinet6/in6.c:1.245.2.12 --- src/sys/netinet6/in6.c:1.245.2.11 Thu Jun 7 17:48:31 2018 +++ src/sys/netinet6/in6.c Tue Nov 6 14:38:58 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: in6.c,v 1.245.2.11 2018/06/07 17:48:31 martin Exp $ */ +/* $NetBSD: in6.c,v 1.245.2.12 2018/11/06 14:38:58 martin Exp $ */ /* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */ /* @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.245.2.11 2018/06/07 17:48:31 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.245.2.12 2018/11/06 14:38:58 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -869,8 +869,23 @@ in6_join_mcastgroups(struct in6_aliasreq ntohs(mltaddr.sin6_addr.s6_addr16[1]), satocsin6(rt_getkey(rt))->sin6_addr.s6_addr16[0], satocsin6(rt_getkey(rt))->sin6_addr.s6_addr16[1]); +#ifdef NET_MPSAFE + error = rt_update_prepare(rt); + if (error == 0) { + rt_replace_ifa(rt, &ia->ia_ifa); + rt->rt_ifp = ifp; + rt_update_finish(rt); + } else { + /* + * If error != 0, the rtentry is being + * destroyed, so doing nothing doesn't + * matter. + */ + } +#else rt_replace_ifa(rt, &ia->ia_ifa); rt->rt_ifp = ifp; +#endif } } if (!rt) { @@ -953,8 +968,23 @@ in6_join_mcastgroups(struct in6_aliasreq ntohs(mltaddr.sin6_addr.s6_addr16[1]), satocsin6(rt_getkey(rt))->sin6_addr.s6_addr16[0], satocsin6(rt_getkey(rt))->sin6_addr.s6_addr16[1]); +#ifdef NET_MPSAFE + error = rt_update_prepare(rt); + if (error == 0) { + rt_replace_ifa(rt, &ia->ia_ifa); + rt->rt_ifp = ifp; + rt_update_finish(rt); + } else { + /* + * If error != 0, the rtentry is being + * destroyed, so doing nothing doesn't + * matter. + */ + } +#else rt_replace_ifa(rt, &ia->ia_ifa); rt->rt_ifp = ifp; +#endif } } if (!rt) { Index: src/sys/netinet6/nd6.c diff -u src/sys/netinet6/nd6.c:1.232.2.8 src/sys/netinet6/nd6.c:1.232.2.9 --- src/sys/netinet6/nd6.c:1.232.2.8 Thu Jun 7 17:48:31 2018 +++ src/sys/netinet6/nd6.c Tue Nov 6 14:38:58 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: nd6.c,v 1.232.2.8 2018/06/07 17:48:31 martin Exp $ */ +/* $NetBSD: nd6.c,v 1.232.2.9 2018/11/06 14:38:58 martin Exp $ */ /* $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $ */ /* @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.232.2.8 2018/06/07 17:48:31 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.232.2.9 2018/11/06 14:38:58 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_net_mpsafe.h" @@ -1567,7 +1567,8 @@ nd6_rtrequest(int req, struct rtentry *r * that the rt_ifa points to the address instead * of the loopback address. */ - if (ifa != rt->rt_ifa) + if (!ISSET(info->rti_flags, RTF_DONTCHANGEIFA) + && ifa != rt->rt_ifa) rt_replace_ifa(rt, ifa); } } else if (rt->rt_flags & RTF_ANNOUNCE) {