summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>1999-12-17 06:46:07 +0000
committerimp <imp@FreeBSD.org>1999-12-17 06:46:07 +0000
commit06daa0588c5008f52dd233d9818aea50790a7ff8 (patch)
tree02e7151f06fd28fc3815cbe1eec84c1332d9ba9f /sys/net
parent3daedb32dd08a81bb3c8fef3347be8125ea239dd (diff)
downloadFreeBSD-src-06daa0588c5008f52dd233d9818aea50790a7ff8.zip
FreeBSD-src-06daa0588c5008f52dd233d9818aea50790a7ff8.tar.gz
Two more fixes to if_detach. These are generic to all interfaces and
do not pollute the interface further. o Run if_detach at splnet(). o Creatively swipe the relevant parts of the netatm atm_nif_detach which will delete the relevant references to the interface going away.
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if.c65
1 files changed, 63 insertions, 2 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index 5329c6d..afbad05 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -53,6 +53,7 @@
#include <net/if.h>
#include <net/if_dl.h>
#include <net/radix.h>
+#include <net/route.h>
#ifdef INET6
/*XXX*/
@@ -68,6 +69,7 @@ static void ifinit __P((void *));
static void if_qflush __P((struct ifqueue *));
static void if_slowtimo __P((void *));
static void link_rtrequest __P((int, struct rtentry *, struct sockaddr *));
+static int if_rtdel __P((struct radix_node *, void *));
SYSINIT(interfaces, SI_SUB_PROTO_IF, SI_ORDER_FIRST, ifinit, NULL)
@@ -217,10 +219,14 @@ if_detach(ifp)
struct ifnet *ifp;
{
struct ifaddr *ifa;
+ struct radix_node_head *rnh;
+ int s;
+ int i;
/*
* Remove routes and flush queues.
*/
+ s = splnet();
if_down(ifp);
/*
@@ -233,7 +239,6 @@ if_detach(ifp)
for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa;
ifa = TAILQ_FIRST(&ifp->if_addrhead)) {
-#if 1 /* ONOE */
/* XXX: Ugly!! ad hoc just for INET */
if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET) {
struct ifaliasreq ifr;
@@ -247,12 +252,68 @@ if_detach(ifp)
NULL) == 0)
continue;
}
-#endif /* ONOE */
TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
IFAFREE(ifa);
}
+ /*
+ * Delete all remaining routes using this interface
+ * Unfortuneatly the only way to do this is to slog through
+ * the entire routing table looking for routes which point
+ * to this interface...oh well...
+ */
+ for (i = 1; i <= AF_MAX; i++) {
+ if ((rnh = rt_tables[i]) == NULL)
+ continue;
+ (void) rnh->rnh_walktree(rnh, if_rtdel, ifp);
+ }
+
TAILQ_REMOVE(&ifnet, ifp, if_link);
+ splx(s);
+}
+
+/*
+ * Delete Routes for a Network Interface
+ *
+ * Called for each routing entry via the rnh->rnh_walktree() call above
+ * to delete all route entries referencing a detaching network interface.
+ *
+ * Arguments:
+ * rn pointer to node in the routing table
+ * arg argument passed to rnh->rnh_walktree() - detaching interface
+ *
+ * Returns:
+ * 0 successful
+ * errno failed - reason indicated
+ *
+ */
+static int
+if_rtdel(rn, arg)
+ struct radix_node *rn;
+ void *arg;
+{
+ struct rtentry *rt = (struct rtentry *)rn;
+ struct ifnet *ifp = arg;
+ int err;
+
+ if (rt->rt_ifp == ifp) {
+
+ /*
+ * Protect (sorta) against walktree recursion problems
+ * with cloned routes
+ */
+ if ((rt->rt_flags & RTF_UP) == 0)
+ return (0);
+
+ err = rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
+ rt_mask(rt), rt->rt_flags,
+ (struct rtentry **) NULL);
+ if (err) {
+ log(LOG_WARNING, "if_rtdel: error %d\n", err);
+ }
+ }
+
+ return (0);
}
/*
OpenPOWER on IntegriCloud