From 9183d53dd706fc6cf2da442eac0d791630796da2 Mon Sep 17 00:00:00 2001 From: sam Date: Thu, 30 Oct 2003 23:02:51 +0000 Subject: Overhaul routing table entry cleanup by introducing a new rtexpunge routine that takes a locked routing table reference and removes all references to the entry in the various data structures. This eliminates instances of recursive locking and also closes races where the lock on the entry had to be dropped prior to calling rtrequest(RTM_DELETE). This also cleans up confusion where the caller held a reference to an entry that might have been reclaimed (and in some cases used that reference). Supported by: FreeBSD Foundation --- sys/netinet/in_rmx.c | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-) (limited to 'sys/netinet/in_rmx.c') diff --git a/sys/netinet/in_rmx.c b/sys/netinet/in_rmx.c index baa8c71..39f5eed 100644 --- a/sys/netinet/in_rmx.c +++ b/sys/netinet/in_rmx.c @@ -125,17 +125,12 @@ in_addroute(void *v_arg, void *n_arg, struct radix_node_head *head, rt2->rt_flags & RTF_HOST && rt2->rt_gateway && rt2->rt_gateway->sa_family == AF_LINK) { - /* NB: must unlock to avoid recursion */ - RT_UNLOCK(rt2); - rtrequest(RTM_DELETE, - (struct sockaddr *)rt_key(rt2), - rt2->rt_gateway, rt_mask(rt2), - rt2->rt_flags, 0); + rtexpunge(rt2); + RTFREE_LOCKED(rt2); ret = rn_addroute(v_arg, n_arg, head, treenodes); - RT_LOCK(rt2); - } - RTFREE_LOCKED(rt2); + } else + RTFREE_LOCKED(rt2); } } @@ -211,13 +206,7 @@ in_clsroute(struct radix_node *rn, struct radix_node_head *head) rt->rt_flags |= RTPRF_OURS; rt->rt_rmx.rmx_expire = time_second + rtq_reallyold; } else { - /* NB: must unlock to avoid recursion */ - RT_UNLOCK(rt); - rtrequest(RTM_DELETE, - (struct sockaddr *)rt_key(rt), - rt->rt_gateway, rt_mask(rt), - rt->rt_flags, 0); - RT_LOCK(rt); + rtexpunge(rt); } } @@ -385,8 +374,8 @@ in_ifadownkill(struct radix_node *rn, void *xap) { struct in_ifadown_arg *ap = xap; struct rtentry *rt = (struct rtentry *)rn; - int err; + RT_LOCK(rt); if (rt->rt_ifa == ap->ifa && (ap->del || !(rt->rt_flags & RTF_STATIC))) { /* @@ -397,15 +386,11 @@ in_ifadownkill(struct radix_node *rn, void *xap) * the routes that rtrequest() would have in any case, * so that behavior is not needed there. */ - RT_LOCK(rt); rt->rt_flags &= ~(RTF_CLONING | RTF_PRCLONING); + rtexpunge(rt); + RTFREE_LOCKED(rt); + } else RT_UNLOCK(rt); - err = rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt), - rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0); - if (err) { - log(LOG_WARNING, "in_ifadownkill: error %d\n", err); - } - } return 0; } -- cgit v1.1