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@
-/* $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 $ */
/*
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 *);
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);
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)
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); \
+ } \
}
/*
-/* $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 $ */
/*
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);
-/* $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 $ */
/*
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;
}
* 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;
}
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:
-/* $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 $ */
/*
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.
-/* $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 $ */
/*
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();
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);
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);
}