Changeset View
Changeset View
Standalone View
Standalone View
head/sys/netinet/in.c
Show First 20 Lines • Show All 626 Lines • ▼ Show 20 Lines | in_difaddr_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, struct thread *td) | ||||
* If this is the last IPv4 address configured on this | * If this is the last IPv4 address configured on this | ||||
* interface, leave the all-hosts group. | * interface, leave the all-hosts group. | ||||
* No state-change report need be transmitted. | * No state-change report need be transmitted. | ||||
*/ | */ | ||||
if (iaIsLast && (ifp->if_flags & IFF_MULTICAST)) { | if (iaIsLast && (ifp->if_flags & IFF_MULTICAST)) { | ||||
struct in_ifinfo *ii; | struct in_ifinfo *ii; | ||||
ii = ((struct in_ifinfo *)ifp->if_afdata[AF_INET]); | ii = ((struct in_ifinfo *)ifp->if_afdata[AF_INET]); | ||||
IN_MULTI_LOCK(); | |||||
if (ii->ii_allhosts) { | if (ii->ii_allhosts) { | ||||
(void)in_leavegroup_locked(ii->ii_allhosts, NULL); | (void)in_leavegroup(ii->ii_allhosts, NULL); | ||||
ii->ii_allhosts = NULL; | ii->ii_allhosts = NULL; | ||||
} | } | ||||
IN_MULTI_UNLOCK(); | |||||
} | } | ||||
IF_ADDR_WLOCK(ifp); | IF_ADDR_WLOCK(ifp); | ||||
if (callout_stop(&ia->ia_garp_timer) == 1) { | if (callout_stop(&ia->ia_garp_timer) == 1) { | ||||
ifa_free(&ia->ia_ifa); | ifa_free(&ia->ia_ifa); | ||||
} | } | ||||
IF_ADDR_WUNLOCK(ifp); | IF_ADDR_WUNLOCK(ifp); | ||||
▲ Show 20 Lines • Show All 340 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
* On interface removal, clean up IPv4 data structures hung off of the ifnet. | * On interface removal, clean up IPv4 data structures hung off of the ifnet. | ||||
*/ | */ | ||||
void | void | ||||
in_ifdetach(struct ifnet *ifp) | in_ifdetach(struct ifnet *ifp) | ||||
{ | { | ||||
IN_MULTI_LOCK(); | |||||
in_pcbpurgeif0(&V_ripcbinfo, ifp); | in_pcbpurgeif0(&V_ripcbinfo, ifp); | ||||
in_pcbpurgeif0(&V_udbinfo, ifp); | in_pcbpurgeif0(&V_udbinfo, ifp); | ||||
in_pcbpurgeif0(&V_ulitecbinfo, ifp); | in_pcbpurgeif0(&V_ulitecbinfo, ifp); | ||||
in_purgemaddrs(ifp); | in_purgemaddrs(ifp); | ||||
IN_MULTI_UNLOCK(); | |||||
} | } | ||||
/* | /* | ||||
* Delete all IPv4 multicast address records, and associated link-layer | * Delete all IPv4 multicast address records, and associated link-layer | ||||
* multicast address records, associated with ifp. | * multicast address records, associated with ifp. | ||||
* XXX It looks like domifdetach runs AFTER the link layer cleanup. | * XXX It looks like domifdetach runs AFTER the link layer cleanup. | ||||
* XXX This should not race with ifma_protospec being set during | * XXX This should not race with ifma_protospec being set during | ||||
* a new allocation, if it does, we have bigger problems. | * a new allocation, if it does, we have bigger problems. | ||||
*/ | */ | ||||
static void | static void | ||||
in_purgemaddrs(struct ifnet *ifp) | in_purgemaddrs(struct ifnet *ifp) | ||||
{ | { | ||||
LIST_HEAD(,in_multi) purgeinms; | struct in_multi_head purgeinms; | ||||
struct in_multi *inm, *tinm; | struct in_multi *inm; | ||||
struct ifmultiaddr *ifma; | struct ifmultiaddr *ifma; | ||||
LIST_INIT(&purgeinms); | SLIST_INIT(&purgeinms); | ||||
IN_MULTI_LOCK(); | IN_MULTI_LIST_LOCK(); | ||||
/* | /* | ||||
* Extract list of in_multi associated with the detaching ifp | * Extract list of in_multi associated with the detaching ifp | ||||
* which the PF_INET layer is about to release. | * which the PF_INET layer is about to release. | ||||
* We need to do this as IF_ADDR_LOCK() may be re-acquired | * We need to do this as IF_ADDR_LOCK() may be re-acquired | ||||
* by code further down. | * by code further down. | ||||
*/ | */ | ||||
IF_ADDR_RLOCK(ifp); | IF_ADDR_RLOCK(ifp); | ||||
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { | TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { | ||||
if (ifma->ifma_addr->sa_family != AF_INET || | if (ifma->ifma_addr->sa_family != AF_INET || | ||||
ifma->ifma_protospec == NULL) | ifma->ifma_protospec == NULL) | ||||
continue; | continue; | ||||
#if 0 | #if 0 | ||||
KASSERT(ifma->ifma_protospec != NULL, | KASSERT(ifma->ifma_protospec != NULL, | ||||
("%s: ifma_protospec is NULL", __func__)); | ("%s: ifma_protospec is NULL", __func__)); | ||||
#endif | #endif | ||||
inm = (struct in_multi *)ifma->ifma_protospec; | inm = (struct in_multi *)ifma->ifma_protospec; | ||||
LIST_INSERT_HEAD(&purgeinms, inm, inm_link); | inm_rele_locked(&purgeinms, inm); | ||||
} | } | ||||
IF_ADDR_RUNLOCK(ifp); | IF_ADDR_RUNLOCK(ifp); | ||||
LIST_FOREACH_SAFE(inm, &purgeinms, inm_link, tinm) { | inm_release_list_deferred(&purgeinms); | ||||
LIST_REMOVE(inm, inm_link); | |||||
inm_release_locked(inm); | |||||
} | |||||
igmp_ifdetach(ifp); | igmp_ifdetach(ifp); | ||||
IN_MULTI_LIST_UNLOCK(); | |||||
IN_MULTI_UNLOCK(); | |||||
} | } | ||||
struct in_llentry { | struct in_llentry { | ||||
struct llentry base; | struct llentry base; | ||||
}; | }; | ||||
#define IN_LLTBL_DEFAULT_HSIZE 32 | #define IN_LLTBL_DEFAULT_HSIZE 32 | ||||
#define IN_LLTBL_HASH(k, h) \ | #define IN_LLTBL_HASH(k, h) \ | ||||
▲ Show 20 Lines • Show All 458 Lines • Show Last 20 Lines |