diff options
author | imp <imp@FreeBSD.org> | 1999-12-17 06:46:07 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 1999-12-17 06:46:07 +0000 |
commit | 06daa0588c5008f52dd233d9818aea50790a7ff8 (patch) | |
tree | 02e7151f06fd28fc3815cbe1eec84c1332d9ba9f /sys | |
parent | 3daedb32dd08a81bb3c8fef3347be8125ea239dd (diff) | |
download | FreeBSD-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')
-rw-r--r-- | sys/net/if.c | 65 |
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); } /* |