summaryrefslogtreecommitdiff
path: root/sys/net/route.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net/route.c')
-rw-r--r--sys/net/route.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/sys/net/route.c b/sys/net/route.c
index a2a0a04c6f7..cdfb19120aa 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: route.c,v 1.68 2006/03/06 13:36:03 henning Exp $ */
+/* $OpenBSD: route.c,v 1.69 2006/03/20 10:03:49 henning Exp $ */
/* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */
/*
@@ -144,6 +144,7 @@ int okaytoclone(u_int, int);
int rtdeletemsg(struct rtentry *);
int rtflushclone1(struct radix_node *, void *);
void rtflushclone(struct radix_node_head *, struct rtentry *);
+int rt_if_remove_rtdelete(struct radix_node *, void *);
#define LABELID_MAX 50000
@@ -1230,3 +1231,46 @@ rtlabel_unref(u_int16_t id)
}
}
}
+
+void
+rt_if_remove(struct ifnet *ifp)
+{
+ int i;
+ struct radix_node_head *rnh;
+
+ for (i = 1; i <= AF_MAX; i++) {
+ rnh = rt_tables[i];
+ if (rnh)
+ while ((*rnh->rnh_walktree)(rnh,
+ rt_if_remove_rtdelete, ifp) == EAGAIN)
+ ;
+ }
+}
+
+/*
+ * Note that deleting a RTF_CLONING route can trigger the
+ * deletion of more entries, so we need to cancel the walk
+ * and return EAGAIN. The caller should restart the walk
+ * as long as EAGAIN is returned.
+ */
+int
+rt_if_remove_rtdelete(struct radix_node *rn, void *vifp)
+{
+ struct ifnet *ifp = vifp;
+ struct rtentry *rt = (struct rtentry *)rn;
+
+ if (rt->rt_ifp == ifp) {
+ int cloning = (rt->rt_flags & RTF_CLONING);
+
+ if (rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
+ rt_mask(rt), 0, NULL) == 0 && cloning)
+ return (EAGAIN);
+ }
+
+ /*
+ * XXX There should be no need to check for rt_ifa belonging to this
+ * interface, because then rt_ifp is set, right?
+ */
+
+ return (0);
+}