Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet6/in6.c
Show First 20 Lines • Show All 690 Lines • ▼ Show 20 Lines | if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) { | ||||
* Ignore failure of clearing the flag intentionally. | * Ignore failure of clearing the flag intentionally. | ||||
* The failure means address duplication was detected. | * The failure means address duplication was detected. | ||||
*/ | */ | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
case SIOCDIFADDR_IN6: | case SIOCDIFADDR_IN6: | ||||
{ | in6_purgeifaddr(ia); | ||||
struct nd_prefix *pr; | |||||
/* | |||||
* If the address being deleted is the only one that owns | |||||
* the corresponding prefix, expire the prefix as well. | |||||
* XXX: theoretically, we don't have to worry about such | |||||
* relationship, since we separate the address management | |||||
* and the prefix management. We do this, however, to provide | |||||
* as much backward compatibility as possible in terms of | |||||
* the ioctl operation. | |||||
* Note that in6_purgeaddr() will decrement ndpr_addrcnt. | |||||
*/ | |||||
pr = ia->ia6_ndpr; | |||||
in6_purgeaddr(&ia->ia_ifa); | |||||
if (pr != NULL && pr->ndpr_addrcnt == 0) { | |||||
ND6_WLOCK(); | |||||
nd6_prefix_unlink(pr, NULL); | |||||
ND6_WUNLOCK(); | |||||
nd6_prefix_del(pr); | |||||
} | |||||
EVENTHANDLER_INVOKE(ifaddr_event_ext, ifp, &ia->ia_ifa, | EVENTHANDLER_INVOKE(ifaddr_event_ext, ifp, &ia->ia_ifa, | ||||
IFADDR_EVENT_DEL); | IFADDR_EVENT_DEL); | ||||
break; | break; | ||||
} | |||||
default: | default: | ||||
if (ifp->if_ioctl == NULL) { | if (ifp->if_ioctl == NULL) { | ||||
error = EOPNOTSUPP; | error = EOPNOTSUPP; | ||||
goto out; | goto out; | ||||
} | } | ||||
error = (*ifp->if_ioctl)(ifp, cmd, data); | error = (*ifp->if_ioctl)(ifp, cmd, data); | ||||
goto out; | goto out; | ||||
▲ Show 20 Lines • Show All 626 Lines • ▼ Show 20 Lines | if (error != 0) | ||||
log(LOG_INFO, "%s: err=%d, destination address delete " | log(LOG_INFO, "%s: err=%d, destination address delete " | ||||
"failed\n", __func__, error); | "failed\n", __func__, error); | ||||
ia->ia_flags &= ~IFA_ROUTE; | ia->ia_flags &= ~IFA_ROUTE; | ||||
} | } | ||||
in6_newaddrmsg(ia, RTM_DELETE); | in6_newaddrmsg(ia, RTM_DELETE); | ||||
in6_unlink_ifa(ia, ifp); | in6_unlink_ifa(ia, ifp); | ||||
} | } | ||||
/* | |||||
* Removes @ia from the corresponding interfaces and unlinks corresponding | |||||
* prefix if no addresses are using it anymore. | |||||
*/ | |||||
void | |||||
in6_purgeifaddr(struct in6_ifaddr *ia) | |||||
{ | |||||
struct nd_prefix *pr; | |||||
/* | |||||
* If the address being deleted is the only one that owns | |||||
* the corresponding prefix, expire the prefix as well. | |||||
* XXX: theoretically, we don't have to worry about such | |||||
* relationship, since we separate the address management | |||||
* and the prefix management. We do this, however, to provide | |||||
* as much backward compatibility as possible in terms of | |||||
* the ioctl operation. | |||||
* Note that in6_purgeaddr() will decrement ndpr_addrcnt. | |||||
*/ | |||||
pr = ia->ia6_ndpr; | |||||
in6_purgeaddr(&ia->ia_ifa); | |||||
if (pr != NULL && pr->ndpr_addrcnt == 0) { | |||||
ND6_WLOCK(); | |||||
nd6_prefix_unlink(pr, NULL); | |||||
ND6_WUNLOCK(); | |||||
nd6_prefix_del(pr); | |||||
} | |||||
} | |||||
static void | static void | ||||
in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp) | in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp) | ||||
{ | { | ||||
char ip6buf[INET6_ADDRSTRLEN]; | char ip6buf[INET6_ADDRSTRLEN]; | ||||
int remove_lle; | int remove_lle; | ||||
IF_ADDR_WLOCK(ifp); | IF_ADDR_WLOCK(ifp); | ||||
▲ Show 20 Lines • Show All 1,218 Lines • Show Last 20 Lines |