This is the next logical step after bluhm@'s retrequest1(9) unification.
The idea is to always return a route with an incremented reference count
when the ``rtp'' argument of rtrequest1(9) is non-NULL. Apart from the
code simplification this will prevent ``rt'' to be freed by another CPU
between the return of rtrequest1(9) and the actual rtfree(9).
Ok?
Index: net/route.c
===================================================================
RCS file: /cvs/src/sys/net/route.c,v
retrieving revision 1.223
diff -u -p -r1.223 route.c
--- net/route.c 19 Aug 2015 13:27:38 -0000 1.223
+++ net/route.c 20 Aug 2015 11:25:54 -0000
@@ -570,12 +570,8 @@ rtdeletemsg(struct rtentry *rt, u_int ta
info.rti_flags = rt->rt_flags;
ifp = rt->rt_ifp;
error = rtrequest1(RTM_DELETE, &info, rt->rt_priority, &rt, tableid);
-
rt_missmsg(RTM_DELETE, &info, info.rti_flags, ifp, error, tableid);
-
- /* Adjust the refcount */
- if (error == 0 && rt->rt_refcnt <= 0) {
- rt->rt_refcnt++;
+ if (error == 0) {
rtfree(rt);
}
return (error);
@@ -820,12 +816,11 @@ rtrequest1(int req, struct rt_addrinfo *
ifa->ifa_rtrequest(RTM_DELETE, rt);
rttrash++;
- if (ret_nrt)
+ rt->rt_refcnt++;
+ if (ret_nrt != NULL)
*ret_nrt = rt;
- else if (rt->rt_refcnt <= 0) {
- rt->rt_refcnt++;
+ else
rtfree(rt);
- }
break;
case RTM_RESOLVE:
@@ -1269,10 +1264,7 @@ rt_ifa_del(struct ifaddr *ifa, int flags
rt_sendmsg(rt, RTM_DELETE, rtableid);
if (flags & RTF_LOCAL)
rt_sendaddrmsg(rt, RTM_DELADDR);
- if (rt->rt_refcnt <= 0) {
- rt->rt_refcnt++;
- rtfree(rt);
- }
+ rtfree(rt);
}
if (m != NULL)
m_free(m);
Index: net/rtsock.c
===================================================================
RCS file: /cvs/src/sys/net/rtsock.c,v
retrieving revision 1.168
diff -u -p -r1.168 rtsock.c
--- net/rtsock.c 19 Aug 2015 13:27:38 -0000 1.168
+++ net/rtsock.c 20 Aug 2015 11:25:54 -0000
@@ -593,8 +593,7 @@ route_output(struct mbuf *m, ...)
error = EINVAL;
goto flush;
}
- error = rtrequest1(rtm->rtm_type, &info, prio, &saved_nrt,
- tableid);
+ error = rtrequest1(RTM_ADD, &info, prio, &saved_nrt, tableid);
if (error == 0) {
rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
&saved_nrt->rt_rmx);
@@ -606,12 +605,9 @@ route_output(struct mbuf *m, ...)
}
break;
case RTM_DELETE:
- error = rtrequest1(rtm->rtm_type, &info, prio, &saved_nrt,
- tableid);
- if (error == 0) {
- (rt = saved_nrt)->rt_refcnt++;
+ error = rtrequest1(RTM_DELETE, &info, prio, &rt, tableid);
+ if (error == 0)
goto report;
- }
break;
case RTM_GET:
case RTM_CHANGE:
Index: netinet6/nd6_rtr.c
===================================================================
RCS file: /cvs/src/sys/netinet6/nd6_rtr.c,v
retrieving revision 1.116
diff -u -p -r1.116 nd6_rtr.c
--- netinet6/nd6_rtr.c 19 Aug 2015 13:27:38 -0000 1.116
+++ netinet6/nd6_rtr.c 20 Aug 2015 11:25:54 -0000
@@ -732,14 +732,7 @@ defrouter_delreq(struct nd_defrouter *dr
dr->ifp->if_rdomain);
if (error == 0) {
rt_sendmsg(rt, RTM_DELETE, dr->ifp->if_rdomain);
- if (rt->rt_refcnt <= 0) {
- /*
- * XXX: borrowed from the RTM_DELETE case of
- * rtrequest1().
- */
- rt->rt_refcnt++;
- rtfree(rt);
- }
+ rtfree(rt);
}
dr->installed = 0;
@@ -1902,10 +1895,10 @@ nd6_prefix_offlink(struct nd_prefix *pr)
error = rtrequest1(RTM_DELETE, &info, RTP_CONNECTED, &rt,
ifp->if_rdomain);
if (error == 0) {
- pr->ndpr_stateflags &= ~NDPRF_ONLINK;
-
- /* report the route deletion to the routing socket. */
rt_sendmsg(rt, RTM_DELETE, ifp->if_rdomain);
+ rtfree(rt);
+
+ pr->ndpr_stateflags &= ~NDPRF_ONLINK;
/*
* There might be the same prefix on another interface,
@@ -1945,12 +1938,6 @@ nd6_prefix_offlink(struct nd_prefix *pr)
opr->ndpr_ifp->if_xname, e));
}
}
- }
-
- if (rt->rt_refcnt <= 0) {
- /* XXX: we should free the entry ourselves. */
- rt->rt_refcnt++;
- rtfree(rt);
}
} else {
/* XXX: can we still set the NDPRF_ONLINK flag? */