Module Name:    src
Committed By:   martin
Date:           Sat Apr 14 10:16:19 UTC 2018

Modified Files:
        src/sys/net [netbsd-8]: if.h route.c route.h rtsock.c

Log Message:
Pull up following revision(s) (requested by ozaki-r in ticket #749):

        sys/net/if.h: revision 1.259
        sys/net/route.c: revision 1.209
        sys/net/route.h: revision 1.118
        sys/net/rtsock.c: revision 1.240

Resolve tangled lock dependencies in route.c

This change sweeps remaining lock decisions based on if locked or not by
moving utility functions of rtentry updates from rtsock.c and ensuring
holding the rt_lock.
It also improves the atomicity of a update of a rtentry.


To generate a diff of this commit:
cvs rdiff -u -r1.239.2.4 -r1.239.2.5 src/sys/net/if.h
cvs rdiff -u -r1.194.6.8 -r1.194.6.9 src/sys/net/route.c
cvs rdiff -u -r1.112.4.3 -r1.112.4.4 src/sys/net/route.h
cvs rdiff -u -r1.213.2.8 -r1.213.2.9 src/sys/net/rtsock.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.h
diff -u src/sys/net/if.h:1.239.2.4 src/sys/net/if.h:1.239.2.5
--- src/sys/net/if.h:1.239.2.4	Sun Feb 11 21:17:34 2018
+++ src/sys/net/if.h	Sat Apr 14 10:16:19 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: if.h,v 1.239.2.4 2018/02/11 21:17:34 snj Exp $	*/
+/*	$NetBSD: if.h,v 1.239.2.5 2018/04/14 10:16:19 martin Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -1145,8 +1145,6 @@ struct	ifaddr *ifa_ifwithnet(const struc
 struct	ifaddr *ifa_ifwithnet_psref(const struct sockaddr *, struct psref *);
 struct	ifaddr *ifa_ifwithladdr(const struct sockaddr *);
 struct	ifaddr *ifa_ifwithladdr_psref(const struct sockaddr *, struct psref *);
-struct	ifaddr *ifa_ifwithroute_psref(int, const struct sockaddr *,
-	    const struct sockaddr *, struct psref *);
 struct	ifaddr *ifaof_ifpforaddr(const struct sockaddr *, struct ifnet *);
 struct	ifaddr *ifaof_ifpforaddr_psref(const struct sockaddr *, struct ifnet *,
 	    struct psref *);

Index: src/sys/net/route.c
diff -u src/sys/net/route.c:1.194.6.8 src/sys/net/route.c:1.194.6.9
--- src/sys/net/route.c:1.194.6.8	Thu Apr  5 14:41:07 2018
+++ src/sys/net/route.c	Sat Apr 14 10:16:19 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: route.c,v 1.194.6.8 2018/04/05 14:41:07 martin Exp $	*/
+/*	$NetBSD: route.c,v 1.194.6.9 2018/04/14 10:16:19 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.8 2018/04/05 14:41:07 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.194.6.9 2018/04/14 10:16:19 martin Exp $");
 
 #include <sys/param.h>
 #ifdef RTFLUSH_DEBUG
@@ -130,6 +130,8 @@ __KERNEL_RCSID(0, "$NetBSD: route.c,v 1.
 #include <netinet/in.h>
 #include <netinet/in_var.h>
 
+#define	PRESERVED_RTF	(RTF_UP | RTF_GATEWAY | RTF_HOST | RTF_DONE | RTF_MASK)
+
 #ifdef RTFLUSH_DEBUG
 #define	rtcache_debug() __predict_false(_rtcache_debug)
 #else /* RTFLUSH_DEBUG */
@@ -224,13 +226,13 @@ static krwlock_t		rt_lock __cacheline_al
 #define RT_RLOCK()		rw_enter(&rt_lock, RW_READER)
 #define RT_WLOCK()		rw_enter(&rt_lock, RW_WRITER)
 #define RT_UNLOCK()		rw_exit(&rt_lock)
-#define RT_LOCKED()		rw_lock_held(&rt_lock)
+#define RT_WLOCKED()		rw_write_held(&rt_lock)
 #define	RT_ASSERT_WLOCK()	KASSERT(rw_write_held(&rt_lock))
 #else
 #define RT_RLOCK()		do {} while (0)
 #define RT_WLOCK()		do {} while (0)
 #define RT_UNLOCK()		do {} while (0)
-#define RT_LOCKED()		false
+#define RT_WLOCKED()		true
 #define	RT_ASSERT_WLOCK()	do {} while (0)
 #endif
 
@@ -280,6 +282,11 @@ static void rt_ref(struct rtentry *);
 static struct rtentry *
     rtalloc1_locked(const struct sockaddr *, int, bool, bool);
 
+static struct ifaddr *rt_getifa(struct rt_addrinfo *, struct psref *);
+static struct ifnet *rt_getifp(struct rt_addrinfo *, struct psref *);
+static struct ifaddr *ifa_ifwithroute_psref(int, const struct sockaddr *,
+    const struct sockaddr *, struct psref *);
+
 static void rtcache_ref(struct rtentry *, struct route *);
 
 #ifdef NET_MPSAFE
@@ -884,11 +891,13 @@ rtredirect(const struct sockaddr *dst, c
 			error = rt_update_prepare(rt);
 			if (error == 0) {
 #endif
+				RT_WLOCK();
 				error = rt_setgate(rt, gateway);
 				if (error == 0) {
 					rt->rt_flags |= RTF_MODIFIED;
 					flags |= RTF_MODIFIED;
 				}
+				RT_UNLOCK();
 #ifdef NET_MPSAFE
 				rt_update_finish(rt);
 			} else {
@@ -952,9 +961,9 @@ rtdeletemsg(struct rtentry *rt)
 	return error;
 }
 
-struct ifaddr *
+static struct ifaddr *
 ifa_ifwithroute_psref(int flags, const struct sockaddr *dst,
-	const struct sockaddr *gateway, struct psref *psref)
+    const struct sockaddr *gateway, struct psref *psref)
 {
 	struct ifaddr *ifa = NULL;
 
@@ -984,11 +993,7 @@ ifa_ifwithroute_psref(int flags, const s
 		int s;
 		struct rtentry *rt;
 
-		/* XXX we cannot call rtalloc1 if holding the rt lock */
-		if (RT_LOCKED())
-			rt = rtalloc1_locked(gateway, 0, true, true);
-		else
-			rt = rtalloc1(gateway, 0);
+		rt = rtalloc1_locked(gateway, 0, true, true);
 		if (rt == NULL)
 			return NULL;
 		if (rt->rt_flags & RTF_GATEWAY) {
@@ -1074,7 +1079,7 @@ rtrequest_newmsg(const int req, const st
 	return 0;
 }
 
-struct ifnet *
+static struct ifnet *
 rt_getifp(struct rt_addrinfo *info, struct psref *psref)
 {
 	const struct sockaddr *ifpaddr = info->rti_info[RTAX_IFP];
@@ -1099,7 +1104,7 @@ rt_getifp(struct rt_addrinfo *info, stru
 	return info->rti_ifp;
 }
 
-struct ifaddr *
+static struct ifaddr *
 rt_getifa(struct rt_addrinfo *info, struct psref *psref)
 {
 	struct ifaddr *ifa = NULL;
@@ -1331,6 +1336,7 @@ rt_setgate(struct rtentry *rt, const str
 {
 	struct sockaddr *new, *old;
 
+	KASSERT(RT_WLOCKED());
 	KASSERT(rt->_rt_key != NULL);
 	RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
 
@@ -1349,11 +1355,7 @@ rt_setgate(struct rtentry *rt, const str
 	if (rt->rt_flags & RTF_GATEWAY) {
 		struct rtentry *gwrt;
 
-		/* XXX we cannot call rtalloc1 if holding the rt lock */
-		if (RT_LOCKED())
-			gwrt = rtalloc1_locked(gate, 1, false, true);
-		else
-			gwrt = rtalloc1(gate, 1);
+		gwrt = rtalloc1_locked(gate, 1, false, true);
 		/*
 		 * If we switched gateways, grab the MTU from the new
 		 * gateway route if the current MTU, if the current MTU is
@@ -1377,6 +1379,154 @@ rt_setgate(struct rtentry *rt, const str
 	return 0;
 }
 
+static struct ifaddr *
+rt_update_get_ifa(const struct rt_addrinfo info, const struct rtentry *rt,
+    struct ifnet **ifp, struct psref *psref_ifp, struct psref *psref)
+{
+	struct ifaddr *ifa = NULL;
+
+	*ifp = NULL;
+	if (info.rti_info[RTAX_IFP] != NULL) {
+		ifa = ifa_ifwithnet_psref(info.rti_info[RTAX_IFP], psref);
+		if (ifa == NULL)
+			goto next;
+		*ifp = ifa->ifa_ifp;
+		if_acquire(*ifp, psref_ifp);
+		if (info.rti_info[RTAX_IFA] == NULL &&
+		    info.rti_info[RTAX_GATEWAY] == NULL)
+			goto next;
+		ifa_release(ifa, psref);
+		if (info.rti_info[RTAX_IFA] == NULL) {
+			/* route change <dst> <gw> -ifp <if> */
+			ifa = ifaof_ifpforaddr_psref(info.rti_info[RTAX_GATEWAY],
+			    *ifp, psref);
+		} else {
+			/* route change <dst> -ifp <if> -ifa <addr> */
+			ifa = ifa_ifwithaddr_psref(info.rti_info[RTAX_IFA], psref);
+			if (ifa != NULL)
+				goto out;
+			ifa = ifaof_ifpforaddr_psref(info.rti_info[RTAX_IFA],
+			    *ifp, psref);
+		}
+		goto out;
+	}
+next:
+	if (info.rti_info[RTAX_IFA] != NULL) {
+		/* route change <dst> <gw> -ifa <addr> */
+		ifa = ifa_ifwithaddr_psref(info.rti_info[RTAX_IFA], psref);
+		if (ifa != NULL)
+			goto out;
+	}
+	if (info.rti_info[RTAX_GATEWAY] != NULL) {
+		/* route change <dst> <gw> */
+		ifa = ifa_ifwithroute_psref(rt->rt_flags, rt_getkey(rt),
+		    info.rti_info[RTAX_GATEWAY], psref);
+	}
+out:
+	if (ifa != NULL && *ifp == NULL) {
+		*ifp = ifa->ifa_ifp;
+		if_acquire(*ifp, psref_ifp);
+	}
+	if (ifa == NULL && *ifp != NULL) {
+		if_put(*ifp, psref_ifp);
+		*ifp = NULL;
+	}
+	return ifa;
+}
+
+int
+rt_update(struct rtentry *rt, struct rt_addrinfo *info, void *rtm)
+{
+	int error = 0;
+	struct ifnet *ifp = NULL, *new_ifp = NULL;
+	struct ifaddr *ifa = NULL, *new_ifa;
+	struct psref psref_ifa, psref_new_ifa, psref_ifp, psref_new_ifp;
+	bool newgw, ifp_changed = false;
+
+	RT_WLOCK();
+	/*
+	 * New gateway could require new ifaddr, ifp;
+	 * flags may also be different; ifp may be specified
+	 * by ll sockaddr when protocol address is ambiguous
+	 */
+	newgw = info->rti_info[RTAX_GATEWAY] != NULL &&
+	    sockaddr_cmp(info->rti_info[RTAX_GATEWAY], rt->rt_gateway) != 0;
+
+	if (newgw || info->rti_info[RTAX_IFP] != NULL ||
+	    info->rti_info[RTAX_IFA] != NULL) {
+		ifp = rt_getifp(info, &psref_ifp);
+		/* info refers ifp so we need to keep a reference */
+		ifa = rt_getifa(info, &psref_ifa);
+		if (ifa == NULL) {
+			error = ENETUNREACH;
+			goto out;
+		}
+	}
+	if (newgw) {
+		error = rt_setgate(rt, info->rti_info[RTAX_GATEWAY]);
+		if (error != 0)
+			goto out;
+	}
+	if (info->rti_info[RTAX_TAG]) {
+		const struct sockaddr *tag;
+		tag = rt_settag(rt, info->rti_info[RTAX_TAG]);
+		if (tag == NULL) {
+			error = ENOBUFS;
+			goto out;
+		}
+	}
+	/*
+	 * New gateway could require new ifaddr, ifp;
+	 * flags may also be different; ifp may be specified
+	 * by ll sockaddr when protocol address is ambiguous
+	 */
+	new_ifa = rt_update_get_ifa(*info, rt, &new_ifp, &psref_new_ifp,
+	    &psref_new_ifa);
+	if (new_ifa != NULL) {
+		ifa_release(ifa, &psref_ifa);
+		ifa = new_ifa;
+	}
+	if (ifa) {
+		struct ifaddr *oifa = rt->rt_ifa;
+		if (oifa != ifa && !ifa_is_destroying(ifa) &&
+		    new_ifp != NULL && !if_is_deactivated(new_ifp)) {
+			if (oifa && oifa->ifa_rtrequest)
+				oifa->ifa_rtrequest(RTM_DELETE, rt, info);
+			rt_replace_ifa(rt, ifa);
+			rt->rt_ifp = new_ifp;
+			ifp_changed = true;
+		}
+		if (new_ifa == NULL)
+			ifa_release(ifa, &psref_ifa);
+	}
+	ifa_release(new_ifa, &psref_new_ifa);
+	if (new_ifp && rt->rt_ifp != new_ifp && !if_is_deactivated(new_ifp)) {
+		rt->rt_ifp = new_ifp;
+		ifp_changed = true;
+	}
+	rt_setmetrics(rtm, rt);
+	if (rt->rt_flags != info->rti_flags) {
+		rt->rt_flags = (info->rti_flags & ~PRESERVED_RTF) |
+		    (rt->rt_flags & PRESERVED_RTF);
+	}
+	if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
+		rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, info);
+#if defined(INET) || defined(INET6)
+	if (ifp_changed && rt_mask(rt) != NULL)
+		lltable_prefix_free(rt_getkey(rt)->sa_family, rt_getkey(rt),
+		    rt_mask(rt), 0);
+#else
+	(void)ifp_changed; /* XXX gcc */
+#endif
+out:
+	if_put(new_ifp, &psref_new_ifp);
+	if_put(ifp, &psref_ifp);
+
+	RT_UNLOCK();
+
+	return error;
+}
+
 static void
 rt_maskedcopy(const struct sockaddr *src, struct sockaddr *dst,
 	const struct sockaddr *netmask)

Index: src/sys/net/route.h
diff -u src/sys/net/route.h:1.112.4.3 src/sys/net/route.h:1.112.4.4
--- src/sys/net/route.h:1.112.4.3	Sat Jan 13 22:10:55 2018
+++ src/sys/net/route.h	Sat Apr 14 10:16:19 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: route.h,v 1.112.4.3 2018/01/13 22:10:55 snj Exp $	*/
+/*	$NetBSD: route.h,v 1.112.4.4 2018/04/14 10:16:19 martin Exp $	*/
 
 /*
  * Copyright (c) 1980, 1986, 1993
@@ -397,6 +397,7 @@ void	rt_timer_queue_destroy(struct rttim
 void	rt_free(struct rtentry *);
 void	rt_unref(struct rtentry *);
 
+int	rt_update(struct rtentry *, struct rt_addrinfo *, void *);
 int	rt_update_prepare(struct rtentry *);
 void	rt_update_finish(struct rtentry *);
 
@@ -418,10 +419,6 @@ int	rt_ifa_addlocal(struct ifaddr *);
 int	rt_ifa_remlocal(struct ifaddr *, struct ifaddr *);
 struct ifaddr *
 	rt_get_ifa(struct rtentry *);
-struct ifaddr *
-	rt_getifa(struct rt_addrinfo *, struct psref *);
-struct ifnet *
-	rt_getifp(struct rt_addrinfo *, struct psref *);
 void	rt_replace_ifa(struct rtentry *, struct ifaddr *);
 int	rt_setgate(struct rtentry *, const struct sockaddr *);
 
@@ -504,6 +501,8 @@ struct llentry;
 void	rt_clonedmsg(const struct sockaddr *, const struct ifnet *,
 	    const struct rtentry *);
 
+void	rt_setmetrics(void *, struct rtentry *);
+
 /* rtbl */
 int	rt_addaddr(rtbl_t *, struct rtentry *, const struct sockaddr *);
 void	rt_assert_inactive(const struct rtentry *);

Index: src/sys/net/rtsock.c
diff -u src/sys/net/rtsock.c:1.213.2.8 src/sys/net/rtsock.c:1.213.2.9
--- src/sys/net/rtsock.c:1.213.2.8	Mon Apr  9 13:34:10 2018
+++ src/sys/net/rtsock.c	Sat Apr 14 10:16:19 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: rtsock.c,v 1.213.2.8 2018/04/09 13:34:10 bouyer Exp $	*/
+/*	$NetBSD: rtsock.c,v 1.213.2.9 2018/04/14 10:16:19 martin Exp $	*/
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.213.2.8 2018/04/09 13:34:10 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.213.2.9 2018/04/14 10:16:19 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -159,8 +159,6 @@ struct route_info COMPATNAME(route_info)
 	.ri_maxqlen = IFQ_MAXLEN,
 };
 
-#define	PRESERVED_RTF	(RTF_UP | RTF_GATEWAY | RTF_HOST | RTF_DONE | RTF_MASK)
-
 static void COMPATNAME(route_init)(void);
 static int COMPATNAME(route_output)(struct mbuf *, struct socket *);
 
@@ -168,7 +166,7 @@ static int rt_xaddrs(u_char, const char 
 static struct mbuf *rt_makeifannouncemsg(struct ifnet *, int, int,
     struct rt_addrinfo *);
 static int rt_msg2(int, struct rt_addrinfo *, void *, struct rt_walkarg *, int *);
-static void rt_setmetrics(int, const struct rt_xmsghdr *, struct rtentry *);
+static void _rt_setmetrics(int, const struct rt_xmsghdr *, struct rtentry *);
 static void rtm_setmetrics(const struct rtentry *, struct rt_xmsghdr *);
 static void sysctl_net_route_setup(struct sysctllog **);
 static int sysctl_dumpentry(struct rtentry *, void *);
@@ -610,152 +608,6 @@ route_output_report(struct rtentry *rt, 
 	return 0;
 }
 
-static struct ifaddr *
-route_output_get_ifa(const struct rt_addrinfo info, const struct rtentry *rt,
-    struct ifnet **ifp, struct psref *psref_ifp, struct psref *psref)
-{
-	struct ifaddr *ifa = NULL;
-
-	*ifp = NULL;
-	if (info.rti_info[RTAX_IFP] != NULL) {
-		ifa = ifa_ifwithnet_psref(info.rti_info[RTAX_IFP], psref);
-		if (ifa == NULL)
-			goto next;
-		*ifp = ifa->ifa_ifp;
-		if_acquire(*ifp, psref_ifp);
-		if (info.rti_info[RTAX_IFA] == NULL &&
-		    info.rti_info[RTAX_GATEWAY] == NULL)
-			goto next;
-		ifa_release(ifa, psref);
-		if (info.rti_info[RTAX_IFA] == NULL) {
-			/* route change <dst> <gw> -ifp <if> */
-			ifa = ifaof_ifpforaddr_psref(info.rti_info[RTAX_GATEWAY],
-			    *ifp, psref);
-		} else {
-			/* route change <dst> -ifp <if> -ifa <addr> */
-			ifa = ifa_ifwithaddr_psref(info.rti_info[RTAX_IFA], psref);
-			if (ifa != NULL)
-				goto out;
-			ifa = ifaof_ifpforaddr_psref(info.rti_info[RTAX_IFA],
-			    *ifp, psref);
-		}
-		goto out;
-	}
-next:
-	if (info.rti_info[RTAX_IFA] != NULL) {
-		/* route change <dst> <gw> -ifa <addr> */
-		ifa = ifa_ifwithaddr_psref(info.rti_info[RTAX_IFA], psref);
-		if (ifa != NULL)
-			goto out;
-	}
-	if (info.rti_info[RTAX_GATEWAY] != NULL) {
-		/* route change <dst> <gw> */
-		ifa = ifa_ifwithroute_psref(rt->rt_flags, rt_getkey(rt),
-		    info.rti_info[RTAX_GATEWAY], psref);
-	}
-out:
-	if (ifa != NULL && *ifp == NULL) {
-		*ifp = ifa->ifa_ifp;
-		if_acquire(*ifp, psref_ifp);
-	}
-	if (ifa == NULL && *ifp != NULL) {
-		if_put(*ifp, psref_ifp);
-		*ifp = NULL;
-	}
-	return ifa;
-}
-
-static int
-route_output_change(struct rtentry *rt, struct rt_addrinfo *info,
-    struct rt_xmsghdr *rtm)
-{
-	int error = 0;
-	struct ifnet *ifp = NULL, *new_ifp = NULL;
-	struct ifaddr *ifa = NULL, *new_ifa;
-	struct psref psref_ifa, psref_new_ifa, psref_ifp, psref_new_ifp;
-	bool newgw, ifp_changed = false;
-
-	/*
-	 * New gateway could require new ifaddr, ifp;
-	 * flags may also be different; ifp may be specified
-	 * by ll sockaddr when protocol address is ambiguous
-	 */
-	newgw = info->rti_info[RTAX_GATEWAY] != NULL &&
-	    sockaddr_cmp(info->rti_info[RTAX_GATEWAY], rt->rt_gateway) != 0;
-
-	if (newgw || info->rti_info[RTAX_IFP] != NULL ||
-	    info->rti_info[RTAX_IFA] != NULL) {
-		ifp = rt_getifp(info, &psref_ifp);
-		/* info refers ifp so we need to keep a reference */
-		ifa = rt_getifa(info, &psref_ifa);
-		if (ifa == NULL) {
-			error = ENETUNREACH;
-			goto out;
-		}
-	}
-	if (newgw) {
-		error = rt_setgate(rt, info->rti_info[RTAX_GATEWAY]);
-		if (error != 0)
-			goto out;
-	}
-	if (info->rti_info[RTAX_TAG]) {
-		const struct sockaddr *tag;
-		tag = rt_settag(rt, info->rti_info[RTAX_TAG]);
-		if (tag == NULL) {
-			error = ENOBUFS;
-			goto out;
-		}
-	}
-	/*
-	 * New gateway could require new ifaddr, ifp;
-	 * flags may also be different; ifp may be specified
-	 * by ll sockaddr when protocol address is ambiguous
-	 */
-	new_ifa = route_output_get_ifa(*info, rt, &new_ifp, &psref_new_ifp,
-	    &psref_new_ifa);
-	if (new_ifa != NULL) {
-		ifa_release(ifa, &psref_ifa);
-		ifa = new_ifa;
-	}
-	if (ifa) {
-		struct ifaddr *oifa = rt->rt_ifa;
-		if (oifa != ifa && !ifa_is_destroying(ifa) &&
-		    new_ifp != NULL && !if_is_deactivated(new_ifp)) {
-			if (oifa && oifa->ifa_rtrequest)
-				oifa->ifa_rtrequest(RTM_DELETE, rt, info);
-			rt_replace_ifa(rt, ifa);
-			rt->rt_ifp = new_ifp;
-			ifp_changed = true;
-		}
-		if (new_ifa == NULL)
-			ifa_release(ifa, &psref_ifa);
-	}
-	ifa_release(new_ifa, &psref_new_ifa);
-	if (new_ifp && rt->rt_ifp != new_ifp && !if_is_deactivated(new_ifp)) {
-		rt->rt_ifp = new_ifp;
-		ifp_changed = true;
-	}
-	rt_setmetrics(rtm->rtm_inits, rtm, rt);
-	if (rt->rt_flags != info->rti_flags) {
-		rt->rt_flags = (info->rti_flags & ~PRESERVED_RTF) |
-		    (rt->rt_flags & PRESERVED_RTF);
-	}
-	if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
-		rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, info);
-#if defined(INET) || defined(INET6)
-	if (ifp_changed && rt_mask(rt) != NULL)
-		lltable_prefix_free(rt_getkey(rt)->sa_family, rt_getkey(rt),
-		    rt_mask(rt), 0);
-#else
-	(void)ifp_changed; /* XXX gcc */
-#endif
-out:
-	if_put(new_ifp, &psref_new_ifp);
-	if_put(ifp, &psref_ifp);
-
-	return error;
-}
-
 /*ARGSUSED*/
 int
 COMPATNAME(route_output)(struct mbuf *m, struct socket *so)
@@ -905,7 +757,7 @@ COMPATNAME(route_output)(struct mbuf *m,
 #endif /* defined(INET) || defined(INET6) */
 		error = rtrequest1(rtm->rtm_type, &info, &saved_nrt);
 		if (error == 0) {
-			rt_setmetrics(rtm->rtm_inits, rtm, saved_nrt);
+			_rt_setmetrics(rtm->rtm_inits, rtm, saved_nrt);
 			rt_unref(saved_nrt);
 		}
 		break;
@@ -1035,7 +887,7 @@ COMPATNAME(route_output)(struct mbuf *m,
 
 			error = rt_update_prepare(rt);
 			if (error == 0) {
-				error = route_output_change(rt, &info, rtm);
+				error = rt_update(rt, &info, rtm);
 				rt_update_finish(rt);
 			}
 
@@ -1043,7 +895,7 @@ COMPATNAME(route_output)(struct mbuf *m,
 			rt_updating = false;
 			cv_broadcast(&rt_update_cv);
 #else
-			error = route_output_change(rt, &info, rtm);
+			error = rt_update(rt, &info, rtm);
 #endif
 			if (error != 0)
 				goto flush;
@@ -1171,7 +1023,7 @@ route_ctloutput(int op, struct socket *s
 }
 
 static void
-rt_setmetrics(int which, const struct rt_xmsghdr *in, struct rtentry *out)
+_rt_setmetrics(int which, const struct rt_xmsghdr *in, struct rtentry *out)
 {
 #define metric(f, e) if (which & (f)) out->rt_rmx.e = in->rtm_rmx.e;
 	metric(RTV_RPIPE, rmx_recvpipe);
@@ -1188,6 +1040,19 @@ rt_setmetrics(int which, const struct rt
 	}
 }
 
+#ifndef COMPAT_RTSOCK
+/*
+ * XXX avoid using void * once msghdr compat disappears.
+ */
+void
+rt_setmetrics(void *in, struct rtentry *out)
+{
+	const struct rt_xmsghdr *rtm = in;
+
+	_rt_setmetrics(rtm->rtm_inits, rtm, out);
+}
+#endif
+
 static void
 rtm_setmetrics(const struct rtentry *in, struct rt_xmsghdr *out)
 {

Reply via email to