Acquire interface address list lock around access to if_addrhead,
closing several writer-writer races, and some read-write races. MFC after: 2 weeks
This commit is contained in:
parent
f68ffa034b
commit
1e6a41398c
@ -1653,12 +1653,14 @@ in6ifa_ifpwithaddr(struct ifnet *ifp, struct in6_addr *addr)
|
|||||||
{
|
{
|
||||||
struct ifaddr *ifa;
|
struct ifaddr *ifa;
|
||||||
|
|
||||||
|
IF_ADDR_LOCK(ifp);
|
||||||
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_list) {
|
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_list) {
|
||||||
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)))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
IF_ADDR_UNLOCK(ifp);
|
||||||
|
|
||||||
return ((struct in6_ifaddr *)ifa);
|
return ((struct in6_ifaddr *)ifa);
|
||||||
}
|
}
|
||||||
|
@ -233,6 +233,7 @@ in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6)
|
|||||||
static u_int8_t allone[8] =
|
static u_int8_t allone[8] =
|
||||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||||
|
|
||||||
|
IF_ADDR_LOCK(ifp);
|
||||||
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_list) {
|
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_list) {
|
||||||
if (ifa->ifa_addr->sa_family != AF_LINK)
|
if (ifa->ifa_addr->sa_family != AF_LINK)
|
||||||
continue;
|
continue;
|
||||||
@ -244,6 +245,7 @@ in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6)
|
|||||||
|
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
|
IF_ADDR_UNLOCK(ifp);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -267,18 +269,24 @@ found:
|
|||||||
addrlen = 8;
|
addrlen = 8;
|
||||||
|
|
||||||
/* look at IEEE802/EUI64 only */
|
/* look at IEEE802/EUI64 only */
|
||||||
if (addrlen != 8 && addrlen != 6)
|
if (addrlen != 8 && addrlen != 6) {
|
||||||
|
IF_ADDR_UNLOCK(ifp);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* check for invalid MAC address - on bsdi, we see it a lot
|
* check for invalid MAC address - on bsdi, we see it a lot
|
||||||
* since wildboar configures all-zero MAC on pccard before
|
* since wildboar configures all-zero MAC on pccard before
|
||||||
* card insertion.
|
* card insertion.
|
||||||
*/
|
*/
|
||||||
if (bcmp(addr, allzero, addrlen) == 0)
|
if (bcmp(addr, allzero, addrlen) == 0) {
|
||||||
|
IF_ADDR_UNLOCK(ifp);
|
||||||
return -1;
|
return -1;
|
||||||
if (bcmp(addr, allone, addrlen) == 0)
|
}
|
||||||
|
if (bcmp(addr, allone, addrlen) == 0) {
|
||||||
|
IF_ADDR_UNLOCK(ifp);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* make EUI64 address */
|
/* make EUI64 address */
|
||||||
if (addrlen == 8)
|
if (addrlen == 8)
|
||||||
@ -296,10 +304,14 @@ found:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case IFT_ARCNET:
|
case IFT_ARCNET:
|
||||||
if (addrlen != 1)
|
if (addrlen != 1) {
|
||||||
|
IF_ADDR_UNLOCK(ifp);
|
||||||
return -1;
|
return -1;
|
||||||
if (!addr[0])
|
}
|
||||||
|
if (!addr[0]) {
|
||||||
|
IF_ADDR_UNLOCK(ifp);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
bzero(&in6->s6_addr[8], 8);
|
bzero(&in6->s6_addr[8], 8);
|
||||||
in6->s6_addr[15] = addr[0];
|
in6->s6_addr[15] = addr[0];
|
||||||
@ -321,15 +333,19 @@ found:
|
|||||||
* identifier source (can be renumbered).
|
* identifier source (can be renumbered).
|
||||||
* we don't do this.
|
* we don't do this.
|
||||||
*/
|
*/
|
||||||
|
IF_ADDR_UNLOCK(ifp);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
IF_ADDR_UNLOCK(ifp);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sanity check: g bit must not indicate "group" */
|
/* sanity check: g bit must not indicate "group" */
|
||||||
if (EUI64_GROUP(in6))
|
if (EUI64_GROUP(in6)) {
|
||||||
|
IF_ADDR_UNLOCK(ifp);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* convert EUI64 into IPv6 interface identifier */
|
/* convert EUI64 into IPv6 interface identifier */
|
||||||
EUI64_TO_IFID(in6);
|
EUI64_TO_IFID(in6);
|
||||||
@ -340,9 +356,11 @@ found:
|
|||||||
*/
|
*/
|
||||||
if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 &&
|
if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 &&
|
||||||
bcmp(&in6->s6_addr[9], allzero, 7) == 0) {
|
bcmp(&in6->s6_addr[9], allzero, 7) == 0) {
|
||||||
|
IF_ADDR_UNLOCK(ifp);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IF_ADDR_UNLOCK(ifp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -783,7 +801,9 @@ in6_ifdetach(struct ifnet *ifp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* remove from the linked list */
|
/* remove from the linked list */
|
||||||
|
IF_ADDR_LOCK(ifp);
|
||||||
TAILQ_REMOVE(&ifp->if_addrhead, (struct ifaddr *)ia, ifa_list);
|
TAILQ_REMOVE(&ifp->if_addrhead, (struct ifaddr *)ia, ifa_list);
|
||||||
|
IF_ADDR_UNLOCK(ifp);
|
||||||
IFAFREE(&ia->ia_ifa);
|
IFAFREE(&ia->ia_ifa);
|
||||||
|
|
||||||
/* also remove from the IPv6 address chain(itojun&jinmei) */
|
/* also remove from the IPv6 address chain(itojun&jinmei) */
|
||||||
|
@ -727,6 +727,7 @@ regen_tmpaddr(struct in6_ifaddr *ia6)
|
|||||||
struct in6_ifaddr *public_ifa6 = NULL;
|
struct in6_ifaddr *public_ifa6 = NULL;
|
||||||
|
|
||||||
ifp = ia6->ia_ifa.ifa_ifp;
|
ifp = ia6->ia_ifa.ifa_ifp;
|
||||||
|
IF_ADDR_LOCK(ifp);
|
||||||
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_list) {
|
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_list) {
|
||||||
struct in6_ifaddr *it6;
|
struct in6_ifaddr *it6;
|
||||||
|
|
||||||
@ -770,13 +771,16 @@ regen_tmpaddr(struct in6_ifaddr *ia6)
|
|||||||
int e;
|
int e;
|
||||||
|
|
||||||
if ((e = in6_tmpifadd(public_ifa6, 0, 0)) != 0) {
|
if ((e = in6_tmpifadd(public_ifa6, 0, 0)) != 0) {
|
||||||
|
IF_ADDR_UNLOCK(ifp);
|
||||||
log(LOG_NOTICE, "regen_tmpaddr: failed to create a new"
|
log(LOG_NOTICE, "regen_tmpaddr: failed to create a new"
|
||||||
" tmp addr,errno=%d\n", e);
|
" tmp addr,errno=%d\n", e);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
IF_ADDR_UNLOCK(ifp);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IF_ADDR_UNLOCK(ifp);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,14 +435,18 @@ static void
|
|||||||
nd6_rtmsg(int cmd, struct rtentry *rt)
|
nd6_rtmsg(int cmd, struct rtentry *rt)
|
||||||
{
|
{
|
||||||
struct rt_addrinfo info;
|
struct rt_addrinfo info;
|
||||||
|
struct ifnet *ifp;
|
||||||
|
|
||||||
bzero((caddr_t)&info, sizeof(info));
|
bzero((caddr_t)&info, sizeof(info));
|
||||||
info.rti_info[RTAX_DST] = rt_key(rt);
|
info.rti_info[RTAX_DST] = rt_key(rt);
|
||||||
info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
|
info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
|
||||||
info.rti_info[RTAX_NETMASK] = rt_mask(rt);
|
info.rti_info[RTAX_NETMASK] = rt_mask(rt);
|
||||||
if (rt->rt_ifp) {
|
ifp = rt->rt_ifp;
|
||||||
|
if (ifp != NULL) {
|
||||||
|
IF_ADDR_LOCK(ifp);
|
||||||
info.rti_info[RTAX_IFP] =
|
info.rti_info[RTAX_IFP] =
|
||||||
TAILQ_FIRST(&rt->rt_ifp->if_addrhead)->ifa_addr;
|
TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr;
|
||||||
|
IF_ADDR_UNLOCK(ifp);
|
||||||
info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
|
info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1120,6 +1124,7 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr,
|
|||||||
* consider autoconfigured addresses while RFC2462 simply said
|
* consider autoconfigured addresses while RFC2462 simply said
|
||||||
* "address".
|
* "address".
|
||||||
*/
|
*/
|
||||||
|
IF_ADDR_LOCK(ifp);
|
||||||
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_list) {
|
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_list) {
|
||||||
struct in6_ifaddr *ifa6;
|
struct in6_ifaddr *ifa6;
|
||||||
u_int32_t remaininglifetime;
|
u_int32_t remaininglifetime;
|
||||||
@ -1242,6 +1247,7 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr,
|
|||||||
ifa6->ia6_lifetime = lt6_tmp;
|
ifa6->ia6_lifetime = lt6_tmp;
|
||||||
ifa6->ia6_updatetime = time_second;
|
ifa6->ia6_updatetime = time_second;
|
||||||
}
|
}
|
||||||
|
IF_ADDR_UNLOCK(ifp);
|
||||||
if (ia6_match == NULL && new->ndpr_vltime) {
|
if (ia6_match == NULL && new->ndpr_vltime) {
|
||||||
int ifidlen;
|
int ifidlen;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user