Separate out address-detaching part of if_detach into if_purgeaddrs,
so if_tap doesn't need to rely on locally-rolled code to do same. The observable symptom of if_tap's bzero'ing the address details was a crash in "ifconfig tap0" after an if_tap device was closed. Reported By: Matti Saarinen (mjsaarin at cc dot helsinki dot fi)
This commit is contained in:
parent
08a94fbcf9
commit
45778b37b2
71
sys/net/if.c
71
sys/net/if.c
@ -529,6 +529,45 @@ if_attachdomain1(struct ifnet *ifp)
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove any network addresses from an interface.
|
||||
*/
|
||||
|
||||
void
|
||||
if_purgeaddrs(struct ifnet *ifp)
|
||||
{
|
||||
struct ifaddr *ifa, *next;
|
||||
|
||||
TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) {
|
||||
|
||||
if (ifa->ifa_addr->sa_family == AF_LINK)
|
||||
continue;
|
||||
#ifdef INET
|
||||
/* XXX: Ugly!! ad hoc just for INET */
|
||||
if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET) {
|
||||
struct ifaliasreq ifr;
|
||||
|
||||
bzero(&ifr, sizeof(ifr));
|
||||
ifr.ifra_addr = *ifa->ifa_addr;
|
||||
if (ifa->ifa_dstaddr)
|
||||
ifr.ifra_broadaddr = *ifa->ifa_dstaddr;
|
||||
if (in_control(NULL, SIOCDIFADDR, (caddr_t)&ifr, ifp,
|
||||
NULL) == 0)
|
||||
continue;
|
||||
}
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET6) {
|
||||
in6_purgeaddr(ifa);
|
||||
/* ifp_addrhead is already updated */
|
||||
continue;
|
||||
}
|
||||
#endif /* INET6 */
|
||||
TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
|
||||
IFAFREE(ifa);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Detach an interface, removing it from the
|
||||
* list of "active" interfaces.
|
||||
@ -536,7 +575,7 @@ if_attachdomain1(struct ifnet *ifp)
|
||||
void
|
||||
if_detach(struct ifnet *ifp)
|
||||
{
|
||||
struct ifaddr *ifa, *next;
|
||||
struct ifaddr *ifa;
|
||||
struct radix_node_head *rnh;
|
||||
int s;
|
||||
int i;
|
||||
@ -568,35 +607,7 @@ if_detach(struct ifnet *ifp)
|
||||
altq_detach(&ifp->if_snd);
|
||||
#endif
|
||||
|
||||
for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa; ifa = next) {
|
||||
next = TAILQ_NEXT(ifa, ifa_link);
|
||||
|
||||
if (ifa->ifa_addr->sa_family == AF_LINK)
|
||||
continue;
|
||||
#ifdef INET
|
||||
/* XXX: Ugly!! ad hoc just for INET */
|
||||
if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET) {
|
||||
struct ifaliasreq ifr;
|
||||
|
||||
bzero(&ifr, sizeof(ifr));
|
||||
ifr.ifra_addr = *ifa->ifa_addr;
|
||||
if (ifa->ifa_dstaddr)
|
||||
ifr.ifra_broadaddr = *ifa->ifa_dstaddr;
|
||||
if (in_control(NULL, SIOCDIFADDR, (caddr_t)&ifr, ifp,
|
||||
NULL) == 0)
|
||||
continue;
|
||||
}
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET6) {
|
||||
in6_purgeaddr(ifa);
|
||||
/* ifp_addrhead is already updated */
|
||||
continue;
|
||||
}
|
||||
#endif /* INET6 */
|
||||
TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
|
||||
IFAFREE(ifa);
|
||||
}
|
||||
if_purgeaddrs(ifp);
|
||||
|
||||
#ifdef INET6
|
||||
/*
|
||||
|
@ -408,6 +408,7 @@ tapclose(dev, foo, bar, td)
|
||||
int bar;
|
||||
struct thread *td;
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
struct tap_softc *tp = dev->si_drv1;
|
||||
struct ifnet *ifp = &tp->tap_if;
|
||||
int s;
|
||||
@ -426,24 +427,10 @@ tapclose(dev, foo, bar, td)
|
||||
s = splimp();
|
||||
if_down(ifp);
|
||||
if (ifp->if_flags & IFF_RUNNING) {
|
||||
/* find internet addresses and delete routes */
|
||||
struct ifaddr *ifa = NULL;
|
||||
|
||||
/* In desparate need of ifaddr locking. */
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
|
||||
if (ifa->ifa_addr->sa_family == AF_INET) {
|
||||
rtinit(ifa, (int)RTM_DELETE, 0);
|
||||
|
||||
/* remove address from interface */
|
||||
bzero(ifa->ifa_addr,
|
||||
sizeof(*(ifa->ifa_addr)));
|
||||
bzero(ifa->ifa_dstaddr,
|
||||
sizeof(*(ifa->ifa_dstaddr)));
|
||||
bzero(ifa->ifa_netmask,
|
||||
sizeof(*(ifa->ifa_netmask)));
|
||||
}
|
||||
rtinit(ifa, (int)RTM_DELETE, 0);
|
||||
}
|
||||
|
||||
if_purgeaddrs(ifp);
|
||||
ifp->if_flags &= ~IFF_RUNNING;
|
||||
}
|
||||
splx(s);
|
||||
|
@ -629,6 +629,7 @@ int if_allmulti(struct ifnet *, int);
|
||||
void if_attach(struct ifnet *);
|
||||
int if_delmulti(struct ifnet *, struct sockaddr *);
|
||||
void if_detach(struct ifnet *);
|
||||
void if_purgeaddrs(struct ifnet *);
|
||||
void if_down(struct ifnet *);
|
||||
void if_initname(struct ifnet *, const char *, int);
|
||||
void if_link_state_change(struct ifnet *, int);
|
||||
|
Loading…
Reference in New Issue
Block a user