From da42a81b2a6e179d34ae260f7d3433c2bfedb431 Mon Sep 17 00:00:00 2001 From: mpi Date: Fri, 9 Jun 2017 12:56:43 +0000 Subject: [PATCH] Replace rtrequest(RTM_DELETE...) rtrequest_delete() and do not even 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 | 42 +++++++++++++++--------------------------- sys/net/route.h | 4 +++- sys/net/rtsock.c | 25 +++++++++++++++---------- sys/netinet/in_pcb.c | 21 +++++++++++++++++---- sys/netinet6/nd6_rtr.c | 27 +++++++++++++++------------ 5 files changed, 65 insertions(+), 54 deletions(-) diff --git a/sys/net/route.c b/sys/net/route.c index c6cc952654d..45ec6e23b8d 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -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); \ + } \ } /* diff --git a/sys/net/route.h b/sys/net/route.h index 07819d2fddc..1e73d2d1dfb 100644 --- a/sys/net/route.h +++ b/sys/net/route.h @@ -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); diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 2fc8db5550c..f46a398e94a 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -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: diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 533ed7fa37e..81dac0fffff 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -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. diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c index ec22c1c71df..ff087ae81b8 100644 --- a/sys/netinet6/nd6_rtr.c +++ b/sys/netinet6/nd6_rtr.c @@ -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); } -- 2.20.1