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? */

Reply via email to