summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2019-06-24 22:26:26 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2019-06-24 22:26:26 +0000
commit6fea75826081701a2b9e82e68e0642b68360acff (patch)
tree5b32c7dd83d996a12264da633c9f34e5aefc3992
parentd730ff1f811552cc4da4f8c6b7ca8a986ac0614b (diff)
Since the recent recursion fix in rtable_walk(), deleting an interface
address could trigger the "rt->rt_ifidx == ifp->if_index" assertion. In rtflushclone() the ifp that is passed to rtdeletemsg() has been changed from the route interface to the ifa interface. Restore the old behavior and get the route ifp. found by regress/sys/netinet/carp; OK mpi@
-rw-r--r--sys/net/route.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/sys/net/route.c b/sys/net/route.c
index b87a31ab789..2cc08bbe552 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: route.c,v 1.386 2019/06/21 17:11:42 mpi Exp $ */
+/* $OpenBSD: route.c,v 1.387 2019/06/24 22:26:25 bluhm Exp $ */
/* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */
/*
@@ -156,7 +156,7 @@ void rt_timer_init(void);
int rt_setgwroute(struct rtentry *, u_int);
void rt_putgwroute(struct rtentry *);
int rtflushclone1(struct rtentry *, void *, u_int);
-int rtflushclone(struct ifnet *ifp, struct rtentry *, unsigned int);
+int rtflushclone(struct rtentry *, unsigned int);
int rt_ifa_purge_walker(struct rtentry *, void *, unsigned int);
struct rtentry *rt_match(struct sockaddr *, uint32_t *, int, unsigned int);
int rt_clone(struct rtentry **, struct sockaddr *, unsigned int);
@@ -726,9 +726,10 @@ rtflushclone1(struct rtentry *rt, void *arg, u_int id)
}
int
-rtflushclone(struct ifnet *ifp, struct rtentry *parent, unsigned int rtableid)
+rtflushclone(struct rtentry *parent, unsigned int rtableid)
{
struct rtentry *rt = NULL;
+ struct ifnet *ifp;
int error;
#ifdef DIAGNOSTIC
@@ -740,9 +741,15 @@ rtflushclone(struct ifnet *ifp, struct rtentry *parent, unsigned int rtableid)
error = rtable_walk(rtableid, rt_key(parent)->sa_family, &rt,
rtflushclone1, parent);
if (rt != NULL && error == EEXIST) {
- error = rtdeletemsg(rt, ifp, rtableid);
- if (error == 0)
+ ifp = if_get(rt->rt_ifidx);
+ if (ifp == NULL) {
error = EAGAIN;
+ } else {
+ error = rtdeletemsg(rt, ifp, rtableid);
+ if (error == 0)
+ error = EAGAIN;
+ if_put(ifp);
+ }
}
rtfree(rt);
rt = NULL;
@@ -791,7 +798,7 @@ rtrequest_delete(struct rt_addrinfo *info, u_int8_t prio, struct ifnet *ifp,
/* Clean up any cloned children. */
if (ISSET(rt->rt_flags, RTF_CLONING))
- rtflushclone(ifp, rt, tableid);
+ rtflushclone(rt, tableid);
rtfree(rt->rt_parent);
rt->rt_parent = NULL;