Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet6/in6.c
Show First 20 Lines • Show All 1,112 Lines • ▼ Show 20 Lines | in6_alloc_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra, int flags) | ||||
ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask; | ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask; | ||||
if (ifra->ifra_prefixmask.sin6_len != 0) { | if (ifra->ifra_prefixmask.sin6_len != 0) { | ||||
ia->ia_prefixmask.sin6_family = AF_INET6; | ia->ia_prefixmask.sin6_family = AF_INET6; | ||||
ia->ia_prefixmask.sin6_len = ifra->ifra_prefixmask.sin6_len; | ia->ia_prefixmask.sin6_len = ifra->ifra_prefixmask.sin6_len; | ||||
ia->ia_prefixmask.sin6_addr = ifra->ifra_prefixmask.sin6_addr; | ia->ia_prefixmask.sin6_addr = ifra->ifra_prefixmask.sin6_addr; | ||||
} | } | ||||
ia->ia_ifp = ifp; | ia->ia_ifp = ifp; | ||||
ifa_ref(&ia->ia_ifa); /* if_addrhead */ | if (ifa_ref(&ia->ia_ifa) != 0) { | ||||
IF_ADDR_WLOCK(ifp); | IF_ADDR_WLOCK(ifp); | ||||
CK_STAILQ_INSERT_TAIL(&ifp->if_addrhead, &ia->ia_ifa, ifa_link); | CK_STAILQ_INSERT_TAIL(&ifp->if_addrhead, &ia->ia_ifa, ifa_link); | ||||
IF_ADDR_WUNLOCK(ifp); | IF_ADDR_WUNLOCK(ifp); | ||||
} | |||||
ifa_ref(&ia->ia_ifa); /* in6_ifaddrhead */ | if (ifa_ref(&ia->ia_ifa) != 0) { | ||||
IN6_IFADDR_WLOCK(); | IN6_IFADDR_WLOCK(); | ||||
CK_STAILQ_INSERT_TAIL(&V_in6_ifaddrhead, ia, ia_link); | CK_STAILQ_INSERT_TAIL(&V_in6_ifaddrhead, ia, ia_link); | ||||
CK_LIST_INSERT_HEAD(IN6ADDR_HASH(&ia->ia_addr.sin6_addr), ia, ia6_hash); | CK_LIST_INSERT_HEAD(IN6ADDR_HASH(&ia->ia_addr.sin6_addr), ia, ia6_hash); | ||||
IN6_IFADDR_WUNLOCK(); | IN6_IFADDR_WUNLOCK(); | ||||
} | |||||
return (ia); | return (ia); | ||||
} | } | ||||
/* | /* | ||||
* Update/configure interface address parameters: | * Update/configure interface address parameters: | ||||
* | * | ||||
* 1) Update lifetime | * 1) Update lifetime | ||||
* 2) Update interface metric ad flags | * 2) Update interface metric ad flags | ||||
▲ Show 20 Lines • Show All 312 Lines • ▼ Show 20 Lines | error = ifa_add_loopback_route((struct ifaddr *)ia, | ||||
(struct sockaddr *)&ia->ia_addr); | (struct sockaddr *)&ia->ia_addr); | ||||
if (error == 0) | if (error == 0) | ||||
ia->ia_flags |= IFA_RTSELF; | ia->ia_flags |= IFA_RTSELF; | ||||
} | } | ||||
done: | done: | ||||
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, | WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, | ||||
"Invoking IPv6 network device address event may sleep"); | "Invoking IPv6 network device address event may sleep"); | ||||
ifa_ref(&ia->ia_ifa); | if (ifa_ref(&ia->ia_ifa) != 0) { | ||||
EVENTHANDLER_INVOKE(ifaddr_event_ext, ifp, &ia->ia_ifa, | EVENTHANDLER_INVOKE(ifaddr_event_ext, ifp, &ia->ia_ifa, | ||||
IFADDR_EVENT_ADD); | IFADDR_EVENT_ADD); | ||||
ifa_free(&ia->ia_ifa); | ifa_free(&ia->ia_ifa); | ||||
} | |||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Find an IPv6 interface link-local address specific to an interface. | * Find an IPv6 interface link-local address specific to an interface. | ||||
* ifaddr is returned referenced. | * ifaddr is returned referenced. | ||||
*/ | */ | ||||
struct in6_ifaddr * | struct in6_ifaddr * | ||||
in6ifa_ifpforlinklocal(struct ifnet *ifp, int ignoreflags) | in6ifa_ifpforlinklocal(struct ifnet *ifp, int ignoreflags) | ||||
{ | { | ||||
struct ifaddr *ifa; | struct ifaddr *ifa; | ||||
IF_ADDR_RLOCK(ifp); | IF_ADDR_RLOCK(ifp); | ||||
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { | CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { | ||||
if (ifa->ifa_addr->sa_family != AF_INET6) | if (ifa->ifa_addr->sa_family != AF_INET6) | ||||
continue; | continue; | ||||
if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa))) { | if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa))) { | ||||
if ((((struct in6_ifaddr *)ifa)->ia6_flags & | if ((((struct in6_ifaddr *)ifa)->ia6_flags & | ||||
ignoreflags) != 0) | ignoreflags) == 0 && ifa_ref(ifa) != 0) | ||||
continue; | |||||
ifa_ref(ifa); | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
IF_ADDR_RUNLOCK(ifp); | IF_ADDR_RUNLOCK(ifp); | ||||
return ((struct in6_ifaddr *)ifa); | return ((struct in6_ifaddr *)ifa); | ||||
} | } | ||||
/* | /* | ||||
* find the interface address corresponding to a given IPv6 address. | * find the interface address corresponding to a given IPv6 address. | ||||
* ifaddr is returned referenced. | * ifaddr is returned referenced. | ||||
*/ | */ | ||||
struct in6_ifaddr * | struct in6_ifaddr * | ||||
in6ifa_ifwithaddr(const struct in6_addr *addr, uint32_t zoneid) | in6ifa_ifwithaddr(const struct in6_addr *addr, uint32_t zoneid) | ||||
{ | { | ||||
struct rm_priotracker in6_ifa_tracker; | struct rm_priotracker in6_ifa_tracker; | ||||
struct in6_ifaddr *ia; | struct in6_ifaddr *ia; | ||||
IN6_IFADDR_RLOCK(&in6_ifa_tracker); | IN6_IFADDR_RLOCK(&in6_ifa_tracker); | ||||
CK_LIST_FOREACH(ia, IN6ADDR_HASH(addr), ia6_hash) { | CK_LIST_FOREACH(ia, IN6ADDR_HASH(addr), ia6_hash) { | ||||
if (IN6_ARE_ADDR_EQUAL(IA6_IN6(ia), addr)) { | if (IN6_ARE_ADDR_EQUAL(IA6_IN6(ia), addr)) { | ||||
if (zoneid != 0 && | if (zoneid != 0 && | ||||
zoneid != ia->ia_addr.sin6_scope_id) | zoneid != ia->ia_addr.sin6_scope_id) | ||||
continue; | continue; | ||||
ifa_ref(&ia->ia_ifa); | if (ifa_ref(&ia->ia_ifa) != 0) | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
IN6_IFADDR_RUNLOCK(&in6_ifa_tracker); | IN6_IFADDR_RUNLOCK(&in6_ifa_tracker); | ||||
return (ia); | return (ia); | ||||
} | } | ||||
/* | /* | ||||
* find the internet address corresponding to a given interface and address. | * find the internet address corresponding to a given interface and address. | ||||
* ifaddr is returned referenced. | * ifaddr is returned referenced. | ||||
*/ | */ | ||||
struct in6_ifaddr * | struct in6_ifaddr * | ||||
in6ifa_ifpwithaddr(struct ifnet *ifp, const struct in6_addr *addr) | in6ifa_ifpwithaddr(struct ifnet *ifp, const struct in6_addr *addr) | ||||
{ | { | ||||
struct ifaddr *ifa; | struct ifaddr *ifa; | ||||
IF_ADDR_RLOCK(ifp); | IF_ADDR_RLOCK(ifp); | ||||
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { | CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { | ||||
if (ifa->ifa_addr->sa_family != AF_INET6) | if (ifa->ifa_addr->sa_family != AF_INET6) | ||||
continue; | continue; | ||||
if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa))) { | if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa)) && | ||||
ifa_ref(ifa); | ifa_ref(ifa) != 0) | ||||
break; | break; | ||||
} | } | ||||
} | |||||
IF_ADDR_RUNLOCK(ifp); | IF_ADDR_RUNLOCK(ifp); | ||||
return ((struct in6_ifaddr *)ifa); | return ((struct in6_ifaddr *)ifa); | ||||
} | } | ||||
/* | /* | ||||
* Find a link-local scoped address on ifp and return it if any. | * Find a link-local scoped address on ifp and return it if any. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 314 Lines • ▼ Show 20 Lines | if (dst_scope == in6_addrscope(IFA_IN6(ifa))) { | ||||
if (tlen > blen) { | if (tlen > blen) { | ||||
blen = tlen; | blen = tlen; | ||||
besta = (struct in6_ifaddr *)ifa; | besta = (struct in6_ifaddr *)ifa; | ||||
} | } | ||||
} else | } else | ||||
besta = (struct in6_ifaddr *)ifa; | besta = (struct in6_ifaddr *)ifa; | ||||
} | } | ||||
} | } | ||||
if (besta) { | if (besta && ifa_ref(&besta->ia_ifa) != 0) { | ||||
ifa_ref(&besta->ia_ifa); | |||||
IF_ADDR_RUNLOCK(ifp); | IF_ADDR_RUNLOCK(ifp); | ||||
return (besta); | return (besta); | ||||
} | } | ||||
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { | CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { | ||||
if (ifa->ifa_addr->sa_family != AF_INET6) | if (ifa->ifa_addr->sa_family != AF_INET6) | ||||
continue; | continue; | ||||
if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST) | if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST) | ||||
continue; /* XXX: is there any case to allow anycast? */ | continue; /* XXX: is there any case to allow anycast? */ | ||||
if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY) | if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY) | ||||
continue; /* don't use this interface */ | continue; /* don't use this interface */ | ||||
if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED) | if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED) | ||||
continue; | continue; | ||||
if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) { | if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) { | ||||
if (V_ip6_use_deprecated) | if (V_ip6_use_deprecated) | ||||
dep[1] = (struct in6_ifaddr *)ifa; | dep[1] = (struct in6_ifaddr *)ifa; | ||||
continue; | continue; | ||||
} | } | ||||
if (ifa_ref(ifa) == 0) | |||||
if (ifa != NULL) | continue; | ||||
ifa_ref(ifa); | |||||
IF_ADDR_RUNLOCK(ifp); | IF_ADDR_RUNLOCK(ifp); | ||||
return (struct in6_ifaddr *)ifa; | return (struct in6_ifaddr *)ifa; | ||||
} | } | ||||
/* use the last-resort values, that are, deprecated addresses */ | /* use the last-resort values, that are, deprecated addresses */ | ||||
if (dep[0]) { | if (dep[0] && ifa_ref((struct ifaddr *)dep[0]) != 0) { | ||||
ifa_ref((struct ifaddr *)dep[0]); | |||||
IF_ADDR_RUNLOCK(ifp); | IF_ADDR_RUNLOCK(ifp); | ||||
return dep[0]; | return dep[0]; | ||||
} | } | ||||
if (dep[1]) { | if (dep[1] && ifa_ref((struct ifaddr *)dep[1]) != 0) { | ||||
ifa_ref((struct ifaddr *)dep[1]); | |||||
IF_ADDR_RUNLOCK(ifp); | IF_ADDR_RUNLOCK(ifp); | ||||
return dep[1]; | return dep[1]; | ||||
} | } | ||||
IF_ADDR_RUNLOCK(ifp); | IF_ADDR_RUNLOCK(ifp); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 648 Lines • Show Last 20 Lines |