summaryrefslogtreecommitdiffstats
path: root/sys/netinet/in.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/in.c')
-rw-r--r--sys/netinet/in.c61
1 files changed, 46 insertions, 15 deletions
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 2b6fd18..b9db746 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -100,15 +100,23 @@ in_localaddr(struct in_addr in)
register u_long i = ntohl(in.s_addr);
register struct in_ifaddr *ia;
+ IN_IFADDR_RLOCK();
if (V_subnetsarelocal) {
- TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link)
- if ((i & ia->ia_netmask) == ia->ia_net)
+ TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
+ if ((i & ia->ia_netmask) == ia->ia_net) {
+ IN_IFADDR_RUNLOCK();
return (1);
+ }
+ }
} else {
- TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link)
- if ((i & ia->ia_subnetmask) == ia->ia_subnet)
+ TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
+ if ((i & ia->ia_subnetmask) == ia->ia_subnet) {
+ IN_IFADDR_RUNLOCK();
return (1);
+ }
+ }
}
+ IN_IFADDR_RUNLOCK();
return (0);
}
@@ -122,10 +130,14 @@ in_localip(struct in_addr in)
INIT_VNET_INET(curvnet);
struct in_ifaddr *ia;
+ IN_IFADDR_RLOCK();
LIST_FOREACH(ia, INADDR_HASH(in.s_addr), ia_hash) {
- if (IA_SIN(ia)->sin_addr.s_addr == in.s_addr)
+ if (IA_SIN(ia)->sin_addr.s_addr == in.s_addr) {
+ IN_IFADDR_RUNLOCK();
return (1);
+ }
}
+ IN_IFADDR_RUNLOCK();
return (0);
}
@@ -222,7 +234,7 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
struct in_ifinfo *ii;
struct in_aliasreq *ifra = (struct in_aliasreq *)data;
struct sockaddr_in oldaddr;
- int error, hostIsNew, iaIsNew, maskIsNew, s;
+ int error, hostIsNew, iaIsNew, maskIsNew;
int iaIsFirst;
ia = NULL;
@@ -313,6 +325,7 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
* first one on the interface, if possible.
*/
dst = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
+ IN_IFADDR_RLOCK();
LIST_FOREACH(iap, INADDR_HASH(dst.s_addr), ia_hash) {
if (iap->ia_ifp == ifp &&
iap->ia_addr.sin_addr.s_addr == dst.s_addr) {
@@ -324,6 +337,7 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
}
if (ia != NULL)
ifa_ref(&ia->ia_ifa);
+ IN_IFADDR_RUNLOCK();
if (ia == NULL) {
IF_ADDR_LOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
@@ -351,6 +365,7 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
if (ifra->ifra_addr.sin_family == AF_INET) {
struct in_ifaddr *oia;
+ IN_IFADDR_RLOCK();
for (oia = ia; ia; ia = TAILQ_NEXT(ia, ia_link)) {
if (ia->ia_ifp == ifp &&
ia->ia_addr.sin_addr.s_addr ==
@@ -361,6 +376,7 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
ifa_ref(&ia->ia_ifa);
if (oia != NULL && ia != oia)
ifa_free(&oia->ia_ifa);
+ IN_IFADDR_RUNLOCK();
if ((ifp->if_flags & IFF_POINTOPOINT)
&& (cmd == SIOCAIFADDR)
&& (ifra->ifra_dstaddr.sin_addr.s_addr
@@ -405,9 +421,9 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
IF_ADDR_UNLOCK(ifp);
ifa_ref(ifa); /* in_ifaddrhead */
- s = splnet();
+ IN_IFADDR_WLOCK();
TAILQ_INSERT_TAIL(&V_in_ifaddrhead, ia, ia_link);
- splx(s);
+ IN_IFADDR_WUNLOCK();
iaIsNew = 1;
}
break;
@@ -578,13 +594,14 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
IF_ADDR_UNLOCK(ifp);
ifa_free(&ia->ia_ifa); /* if_addrhead */
- s = splnet();
+
+ IN_IFADDR_WLOCK();
TAILQ_REMOVE(&V_in_ifaddrhead, ia, ia_link);
- ifa_free(&ia->ia_ifa); /* in_ifaddrhead */
if (ia->ia_addr.sin_family == AF_INET) {
struct in_ifaddr *if_ia;
LIST_REMOVE(ia, ia_hash);
+ IN_IFADDR_WUNLOCK();
/*
* If this is the last IPv4 address configured on this
* interface, leave the all-hosts group.
@@ -603,8 +620,9 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
IN_MULTI_UNLOCK();
} else
ifa_free(&if_ia->ia_ifa);
- }
- splx(s);
+ } else
+ IN_IFADDR_WUNLOCK();
+ ifa_free(&ia->ia_ifa); /* in_ifaddrhead */
out:
if (ia != NULL)
ifa_free(&ia->ia_ifa);
@@ -811,9 +829,12 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
if (oldaddr.sin_family == AF_INET)
LIST_REMOVE(ia, ia_hash);
ia->ia_addr = *sin;
- if (ia->ia_addr.sin_family == AF_INET)
+ if (ia->ia_addr.sin_family == AF_INET) {
+ IN_IFADDR_WLOCK();
LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
ia, ia_hash);
+ IN_IFADDR_WUNLOCK();
+ }
/*
* Give the interface a chance to initialize
* if this is its first address,
@@ -825,6 +846,7 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
splx(s);
/* LIST_REMOVE(ia, ia_hash) is done in in_control */
ia->ia_addr = oldaddr;
+ IN_IFADDR_WLOCK();
if (ia->ia_addr.sin_family == AF_INET)
LIST_INSERT_HEAD(INADDR_HASH(
ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
@@ -836,6 +858,7 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
* with bogus ia entries in hash
*/
LIST_REMOVE(ia, ia_hash);
+ IN_IFADDR_WUNLOCK();
return (error);
}
}
@@ -943,6 +966,7 @@ in_addprefix(struct in_ifaddr *target, int flags)
prefix.s_addr &= mask.s_addr;
}
+ IN_IFADDR_RLOCK();
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
if (rtinitflags(ia)) {
p = ia->ia_addr.sin_addr;
@@ -966,12 +990,16 @@ in_addprefix(struct in_ifaddr *target, int flags)
if (ia->ia_flags & IFA_ROUTE) {
if (V_sameprefixcarponly &&
target->ia_ifp->if_type != IFT_CARP &&
- ia->ia_ifp->if_type != IFT_CARP)
+ ia->ia_ifp->if_type != IFT_CARP) {
+ IN_IFADDR_RUNLOCK();
return (EEXIST);
- else
+ } else {
+ IN_IFADDR_RUNLOCK();
return (0);
+ }
}
}
+ IN_IFADDR_RUNLOCK();
/*
* No-one seem to have this prefix route, so we try to insert it.
@@ -1031,6 +1059,7 @@ in_scrubprefix(struct in_ifaddr *target)
arp_ifscrub(target->ia_ifp, IA_SIN(target)->sin_addr.s_addr);
}
+ IN_IFADDR_RLOCK();
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
if (rtinitflags(ia))
p = ia->ia_dstaddr.sin_addr;
@@ -1054,6 +1083,7 @@ in_scrubprefix(struct in_ifaddr *target)
&& (ia->ia_ifp->if_type != IFT_CARP)
#endif
) {
+ IN_IFADDR_RUNLOCK();
rtinit(&(target->ia_ifa), (int)RTM_DELETE,
rtinitflags(target));
target->ia_flags &= ~IFA_ROUTE;
@@ -1065,6 +1095,7 @@ in_scrubprefix(struct in_ifaddr *target)
return (error);
}
}
+ IN_IFADDR_RUNLOCK();
/*
* remove all L2 entries on the given prefix
OpenPOWER on IntegriCloud