Replace rtrequest(RTM_DELETE...) rtrequest_delete() and do not even
authormpi <mpi@openbsd.org>
Fri, 9 Jun 2017 12:56:43 +0000 (12:56 +0000)
committermpi <mpi@openbsd.org>
Fri, 9 Jun 2017 12:56:43 +0000 (12:56 +0000)
try to remove a route from the table if it is and invalid cache.

This is a step towards decoupling code dealing with userland and kernel
inserted routes.

ok bluhm@

sys/net/route.c
sys/net/route.h
sys/net/rtsock.c
sys/netinet/in_pcb.c
sys/netinet6/nd6_rtr.c

index c6cc952..45ec6e2 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: route.c,v 1.358 2017/06/07 13:28:02 mpi Exp $ */
+/*     $OpenBSD: route.c,v 1.359 2017/06/09 12:56:43 mpi Exp $ */
 /*     $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $      */
 
 /*
@@ -168,8 +168,6 @@ struct sockaddr *rt_plentosa(sa_family_t, int, struct sockaddr_in6 *);
 
 struct ifaddr *ifa_ifwithroute(int, struct sockaddr *, struct sockaddr *,
                    u_int);
-int    rtrequest_delete(struct rt_addrinfo *, u_int8_t, struct ifnet *,
-           struct rtentry **, u_int);
 
 #ifdef DDB
 void   db_print_sa(struct sockaddr *);
@@ -888,16 +886,8 @@ rtrequest_delete(struct rt_addrinfo *info, u_int8_t prio, struct ifnet *ifp,
 
        rt->rt_flags &= ~RTF_UP;
 
-       if (ifp == NULL) {
-               ifp = if_get(rt->rt_ifidx);
-               if (ifp != NULL) {
-                       ifp->if_rtrequest(ifp, RTM_DELETE, rt);
-                       if_put(ifp);
-               }
-       } else {
-               KASSERT(ifp->if_index == rt->rt_ifidx);
-               ifp->if_rtrequest(ifp, RTM_DELETE, rt);
-       }
+       KASSERT(ifp->if_index == rt->rt_ifidx);
+       ifp->if_rtrequest(ifp, RTM_DELETE, rt);
 
        atomic_inc_int(&rttrash);
 
@@ -932,10 +922,7 @@ rtrequest(int req, struct rt_addrinfo *info, u_int8_t prio,
                info->rti_info[RTAX_NETMASK] = NULL;
        switch (req) {
        case RTM_DELETE:
-               error = rtrequest_delete(info, prio, NULL, ret_nrt, tableid);
-               if (error)
-                       return (error);
-               break;
+               return (EINVAL);
 
        case RTM_RESOLVE:
                if (ret_nrt == NULL || (rt = *ret_nrt) == NULL)
@@ -1413,16 +1400,17 @@ rt_ifa_purge_walker(struct rtentry *rt, void *vifa, unsigned int rtableid)
 LIST_HEAD(, rttimer_queue)     rttimer_queue_head;
 static int                     rt_init_done = 0;
 
-#define RTTIMER_CALLOUT(r)     {                               \
-       if (r->rtt_func != NULL) {                              \
-               (*r->rtt_func)(r->rtt_rt, r);                   \
-       } else {                                                \
-               struct rt_addrinfo info;                        \
-               bzero(&info, sizeof(info));                     \
-               info.rti_info[RTAX_DST] = rt_key(r->rtt_rt);    \
-               rtrequest(RTM_DELETE, &info,                    \
-                   r->rtt_rt->rt_priority, NULL, r->rtt_tableid);      \
-       }                                                       \
+#define RTTIMER_CALLOUT(r)     {                                       \
+       if (r->rtt_func != NULL) {                                      \
+               (*r->rtt_func)(r->rtt_rt, r);                           \
+       } else {                                                        \
+               struct ifnet *ifp;                                      \
+                                                                       \
+               ifp = if_get(r->rtt_rt->rt_ifidx);                      \
+               if (ifp != NULL)                                        \
+                       rtdeletemsg(r->rtt_rt, ifp, r->rtt_tableid);    \
+               if_put(ifp);                                            \
+       }                                                               \
 }
 
 /*
index 07819d2..1e73d2d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: route.h,v 1.161 2017/05/21 16:33:53 jca Exp $ */
+/*     $OpenBSD: route.h,v 1.162 2017/06/09 12:56:43 mpi Exp $ */
 /*     $NetBSD: route.h,v 1.9 1996/02/13 22:00:49 christos Exp $       */
 
 /*
@@ -459,6 +459,8 @@ int  rt_ifa_dellocal(struct ifaddr *);
 void    rtredirect(struct sockaddr *, struct sockaddr *, struct sockaddr *, struct rtentry **, unsigned int);
 int     rtrequest(int, struct rt_addrinfo *, u_int8_t, struct rtentry **,
             u_int);
+int     rtrequest_delete(struct rt_addrinfo *, u_int8_t, struct ifnet *,
+            struct rtentry **, u_int);
 #ifndef SMALL_KERNEL
 void    rt_if_track(struct ifnet *);
 int     rt_if_linkstate_change(struct rtentry *, void *, u_int);
index 2fc8db5..f46a398 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rtsock.c,v 1.237 2017/04/19 15:21:54 bluhm Exp $      */
+/*     $OpenBSD: rtsock.c,v 1.238 2017/06/09 12:56:43 mpi Exp $        */
 /*     $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $  */
 
 /*
@@ -772,20 +772,26 @@ rtm_output(struct rt_msghdr *rtm, struct rtentry **prt,
                rt = rtable_lookup(tableid, info->rti_info[RTAX_DST],
                    info->rti_info[RTAX_NETMASK], info->rti_info[RTAX_GATEWAY],
                    prio);
+               if (rt == NULL) {
+                       error = ESRCH;
+                       break;
+               }
+
+               /* Detaching an interface requires the KERNEL_LOCK(). */
+               ifp = if_get(rt->rt_ifidx);
+               KASSERT(ifp != NULL);
 
                /*
                 * Invalidate the cache of automagically created and
                 * referenced L2 entries to make sure that ``rt_gwroute''
                 * pointer stays valid for other CPUs.
                 */
-               if ((rt != NULL) && (ISSET(rt->rt_flags, RTF_CACHED))) {
-                       ifp = if_get(rt->rt_ifidx);
-                       KASSERT(ifp != NULL);
+               if ((ISSET(rt->rt_flags, RTF_CACHED))) {
                        ifp->if_rtrequest(ifp, RTM_INVALIDATE, rt);
-                       if_put(ifp);
                        /* Reset the MTU of the gateway route. */
                        rtable_walk(tableid, rt_key(rt)->sa_family,
                            route_cleargateway, rt);
+                       if_put(ifp);
                        break;
                }
 
@@ -793,8 +799,8 @@ rtm_output(struct rt_msghdr *rtm, struct rtentry **prt,
                 * Make sure that local routes are only modified by the
                 * kernel.
                 */
-               if ((rt != NULL) &&
-                   ISSET(rt->rt_flags, RTF_LOCAL|RTF_BROADCAST)) {
+               if (ISSET(rt->rt_flags, RTF_LOCAL|RTF_BROADCAST)) {
+                       if_put(ifp);
                        error = EINVAL;
                        break;
                }
@@ -802,9 +808,8 @@ rtm_output(struct rt_msghdr *rtm, struct rtentry **prt,
                rtfree(rt);
                rt = NULL;
 
-               error = rtrequest(RTM_DELETE, info, prio, &rt, tableid);
-               if (error != 0)
-                       break;
+               error = rtrequest_delete(info, prio, ifp, &rt, tableid);
+               if_put(ifp);
                break;
        case RTM_CHANGE:
        case RTM_LOCK:
index 533ed7f..81dac0f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: in_pcb.c,v 1.221 2017/06/07 13:28:02 mpi Exp $        */
+/*     $OpenBSD: in_pcb.c,v 1.222 2017/06/09 12:56:43 mpi Exp $        */
 /*     $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $     */
 
 /*
@@ -721,9 +721,22 @@ in_losing(struct inpcb *inp)
                rtm_miss(RTM_LOSING, &info, rt->rt_flags, rt->rt_priority,
                    rt->rt_ifidx, 0, inp->inp_rtableid);
                KERNEL_UNLOCK();
-               if (rt->rt_flags & RTF_DYNAMIC)
-                       (void)rtrequest(RTM_DELETE, &info, rt->rt_priority,
-                           NULL, inp->inp_rtableid);
+               if (rt->rt_flags & RTF_DYNAMIC) {
+                       struct ifnet *ifp;
+
+                       ifp = if_get(rt->rt_ifidx);
+                       /*
+                        * If the interface is gone, all its attached
+                        * route entries have been removed from the table,
+                        * so we're dealing with a stale cache and have
+                        * nothing to do.
+                        */
+                       if (ifp != NULL) {
+                               rtrequest_delete(&info, rt->rt_priority, ifp,
+                                   NULL, inp->inp_rtableid);
+                       }
+                       if_put(ifp);
+               }
                /*
                 * A new route can be allocated
                 * the next time output is attempted.
index ec22c1c..ff087ae 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: nd6_rtr.c,v 1.160 2017/06/07 13:28:02 mpi Exp $       */
+/*     $OpenBSD: nd6_rtr.c,v 1.161 2017/06/09 12:56:44 mpi Exp $       */
 /*     $KAME: nd6_rtr.c,v 1.97 2001/02/07 11:09:13 itojun Exp $        */
 
 /*
@@ -716,7 +716,7 @@ defrouter_delreq(struct nd_defrouter *dr)
        info.rti_info[RTAX_GATEWAY] = sin6tosa(&gw);
        info.rti_info[RTAX_NETMASK] = sin6tosa(&mask);
 
-       error = rtrequest(RTM_DELETE, &info, RTP_DEFAULT, &rt,
+       error = rtrequest_delete(&info, RTP_DEFAULT, dr->ifp, &rt,
            dr->ifp->if_rdomain);
        if (error == 0) {
                KERNEL_LOCK();
@@ -2040,10 +2040,11 @@ rt6_flush(struct in6_addr *gateway, struct ifnet *ifp)
 int
 rt6_deleteroute(struct rtentry *rt, void *arg, unsigned int id)
 {
+       struct ifnet *ifp;
        struct rt_addrinfo info;
        struct in6_addr *gate = (struct in6_addr *)arg;
        struct sockaddr_in6 sa_mask;
-       int error;
+       int error = 0;
 
        if (rt->rt_gateway == NULL || rt->rt_gateway->sa_family != AF_INET6)
                return (0);
@@ -2066,14 +2067,16 @@ rt6_deleteroute(struct rtentry *rt, void *arg, unsigned int id)
        if ((rt->rt_flags & RTF_HOST) == 0)
                return (0);
 
-       bzero(&info, sizeof(info));
-       info.rti_flags =  rt->rt_flags;
-       info.rti_info[RTAX_DST] = rt_key(rt);
-       info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
-       info.rti_info[RTAX_NETMASK] = rt_plen2mask(rt, &sa_mask);
-       error = rtrequest(RTM_DELETE, &info, RTP_ANY, NULL, id);
-       if (error != 0)
-               return (error);
+       ifp = if_get(rt->rt_ifidx);
+       if (ifp != NULL) {
+               bzero(&info, sizeof(info));
+               info.rti_flags =  rt->rt_flags;
+               info.rti_info[RTAX_DST] = rt_key(rt);
+               info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
+               info.rti_info[RTAX_NETMASK] = rt_plen2mask(rt, &sa_mask);
+               error = rtrequest_delete(&info, RTP_ANY, ifp, NULL, id);
+       }
+       if_put(ifp);
 
-       return (EAGAIN);
+       return (error != 0 ? error : EAGAIN);
 }