mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-17 10:26:15 +00:00
Add a new global rwlock, in_ifaddr_lock, which will synchronize use of the
in_ifaddrhead and INADDR_HASH address lists. Previously, these lists were used unsynchronized as they were effectively never changed in steady state, but we've seen increasing reports of writer-writer races on very busy VPN servers as core count has gone up (and similar configurations where address lists change frequently and concurrently). For the time being, use rwlocks rather than rmlocks in order to take advantage of their better lock debugging support. As a result, we don't enable ip_input()'s read-locking of INADDR_HASH until an rmlock conversion is complete and a performance analysis has been done. This means that one class of reader-writer races still exists. MFC after: 6 weeks Reviewed by: bz
This commit is contained in:
parent
51500a4872
commit
2d9cfabad4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=194951
@ -1400,11 +1400,15 @@ nfs_create(struct vop_create_args *ap)
|
||||
CURVNET_SET(P_TO_VNET(&proc0));
|
||||
#ifdef INET
|
||||
INIT_VNET_INET(curvnet);
|
||||
IN_IFADDR_RLOCK();
|
||||
if (!TAILQ_EMPTY(&V_in_ifaddrhead))
|
||||
cverf.lval[0] = IA_SIN(TAILQ_FIRST(&V_in_ifaddrhead))->sin_addr.s_addr;
|
||||
else
|
||||
#endif
|
||||
cverf.lval[0] = create_verf;
|
||||
#ifdef INET
|
||||
IN_IFADDR_RUNLOCK();
|
||||
#endif
|
||||
cverf.lval[1] = ++create_verf;
|
||||
CURVNET_RESTORE();
|
||||
error = nfsrpc_create(dvp, cnp->cn_nameptr, cnp->cn_namelen,
|
||||
|
@ -4973,8 +4973,10 @@ sppp_set_ip_addr(struct sppp *sp, u_long src)
|
||||
/* set new address */
|
||||
si->sin_addr.s_addr = htonl(src);
|
||||
ia = ifatoia(ifa);
|
||||
IN_IFADDR_WLOCK();
|
||||
LIST_REMOVE(ia, ia_hash);
|
||||
LIST_INSERT_HEAD(INADDR_HASH(si->sin_addr.s_addr), ia, ia_hash);
|
||||
IN_IFADDR_WUNLOCK();
|
||||
|
||||
/* add new route */
|
||||
error = rtinit(ifa, (int)RTM_ADD, RTF_HOST);
|
||||
|
@ -620,15 +620,19 @@ stf_checkaddr4(sc, in, inifp)
|
||||
/*
|
||||
* reject packets with broadcast
|
||||
*/
|
||||
IN_IFADDR_RLOCK();
|
||||
for (ia4 = TAILQ_FIRST(&V_in_ifaddrhead);
|
||||
ia4;
|
||||
ia4 = TAILQ_NEXT(ia4, ia_link))
|
||||
{
|
||||
if ((ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST) == 0)
|
||||
continue;
|
||||
if (in->s_addr == ia4->ia_broadaddr.sin_addr.s_addr)
|
||||
if (in->s_addr == ia4->ia_broadaddr.sin_addr.s_addr) {
|
||||
IN_IFADDR_RUNLOCK();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
IN_IFADDR_RUNLOCK();
|
||||
|
||||
/*
|
||||
* perform ingress filter
|
||||
|
@ -509,11 +509,13 @@ in_arpinput(struct mbuf *m)
|
||||
* request for the virtual host ip.
|
||||
* XXX: This is really ugly!
|
||||
*/
|
||||
IN_IFADDR_RLOCK();
|
||||
LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) {
|
||||
if (((bridged && ia->ia_ifp->if_bridge != NULL) ||
|
||||
ia->ia_ifp == ifp) &&
|
||||
itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) {
|
||||
ifa_ref(&ia->ia_ifa);
|
||||
IN_IFADDR_RUNLOCK();
|
||||
goto match;
|
||||
}
|
||||
#ifdef DEV_CARP
|
||||
@ -522,6 +524,7 @@ in_arpinput(struct mbuf *m)
|
||||
itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) {
|
||||
carp_match = 1;
|
||||
ifa_ref(&ia->ia_ifa);
|
||||
IN_IFADDR_RUNLOCK();
|
||||
goto match;
|
||||
}
|
||||
#endif
|
||||
@ -531,6 +534,7 @@ in_arpinput(struct mbuf *m)
|
||||
ia->ia_ifp == ifp) &&
|
||||
isaddr.s_addr == ia->ia_addr.sin_addr.s_addr) {
|
||||
ifa_ref(&ia->ia_ifa);
|
||||
IN_IFADDR_RUNLOCK();
|
||||
goto match;
|
||||
}
|
||||
|
||||
@ -549,11 +553,13 @@ in_arpinput(struct mbuf *m)
|
||||
if (BDG_MEMBER_MATCHES_ARP(itaddr.s_addr, ifp, ia)) {
|
||||
ifa_ref(&ia->ia_ifa);
|
||||
ifp = ia->ia_ifp;
|
||||
IN_IFADDR_RUNLOCK();
|
||||
goto match;
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef BDG_MEMBER_MATCHES_ARP
|
||||
IN_IFADDR_RUNLOCK();
|
||||
|
||||
/*
|
||||
* No match, use the first inet address on the receive interface
|
||||
@ -572,9 +578,13 @@ in_arpinput(struct mbuf *m)
|
||||
/*
|
||||
* If bridging, fall back to using any inet address.
|
||||
*/
|
||||
if (!bridged || (ia = TAILQ_FIRST(&V_in_ifaddrhead)) == NULL)
|
||||
IN_IFADDR_RLOCK();
|
||||
if (!bridged || (ia = TAILQ_FIRST(&V_in_ifaddrhead)) == NULL) {
|
||||
IN_IFADDR_RUNLOCK();
|
||||
goto drop;
|
||||
}
|
||||
ifa_ref(&ia->ia_ifa);
|
||||
IN_IFADDR_RUNLOCK();
|
||||
match:
|
||||
if (!enaddr)
|
||||
enaddr = (u_int8_t *)IF_LLADDR(ifp);
|
||||
|
@ -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
|
||||
|
@ -387,13 +387,19 @@ gif_validate4(const struct ip *ip, struct gif_softc *sc, struct ifnet *ifp)
|
||||
case 0: case 127: case 255:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* reject packets with broadcast on source */
|
||||
/* XXXRW: should use hash lists? */
|
||||
IN_IFADDR_RLOCK();
|
||||
TAILQ_FOREACH(ia4, &V_in_ifaddrhead, ia_link) {
|
||||
if ((ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST) == 0)
|
||||
continue;
|
||||
if (ip->ip_src.s_addr == ia4->ia_broadaddr.sin_addr.s_addr)
|
||||
if (ip->ip_src.s_addr == ia4->ia_broadaddr.sin_addr.s_addr) {
|
||||
IN_IFADDR_RUNLOCK();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
IN_IFADDR_RUNLOCK();
|
||||
|
||||
/* ingress filters on outer source */
|
||||
if ((GIF2IFP(sc)->if_flags & IFF_LINK2) == 0 && ifp) {
|
||||
|
@ -1834,6 +1834,7 @@ inp_lookup_mcast_ifp(const struct inpcb *inp,
|
||||
struct ifnet *mifp;
|
||||
|
||||
mifp = NULL;
|
||||
IN_IFADDR_RLOCK();
|
||||
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
|
||||
mifp = ia->ia_ifp;
|
||||
if (!(mifp->if_flags & IFF_LOOPBACK) &&
|
||||
@ -1842,6 +1843,7 @@ inp_lookup_mcast_ifp(const struct inpcb *inp,
|
||||
break;
|
||||
}
|
||||
}
|
||||
IN_IFADDR_RUNLOCK();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -813,16 +813,21 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam,
|
||||
* choose the broadcast address for that interface.
|
||||
*/
|
||||
if (faddr.s_addr == INADDR_ANY) {
|
||||
IN_IFADDR_RLOCK();
|
||||
faddr =
|
||||
IA_SIN(TAILQ_FIRST(&V_in_ifaddrhead))->sin_addr;
|
||||
IN_IFADDR_RUNLOCK();
|
||||
if (cred != NULL &&
|
||||
(error = prison_get_ip4(cred, &faddr)) != 0)
|
||||
return (error);
|
||||
} else if (faddr.s_addr == (u_long)INADDR_BROADCAST &&
|
||||
(TAILQ_FIRST(&V_in_ifaddrhead)->ia_ifp->if_flags &
|
||||
IFF_BROADCAST))
|
||||
faddr = satosin(&TAILQ_FIRST(
|
||||
&V_in_ifaddrhead)->ia_broadaddr)->sin_addr;
|
||||
} else if (faddr.s_addr == (u_long)INADDR_BROADCAST) {
|
||||
IN_IFADDR_RLOCK();
|
||||
if (TAILQ_FIRST(&V_in_ifaddrhead)->ia_ifp->if_flags &
|
||||
IFF_BROADCAST)
|
||||
faddr = satosin(&TAILQ_FIRST(
|
||||
&V_in_ifaddrhead)->ia_broadaddr)->sin_addr;
|
||||
IN_IFADDR_RUNLOCK();
|
||||
}
|
||||
}
|
||||
if (laddr.s_addr == INADDR_ANY) {
|
||||
error = in_pcbladdr(inp, &faddr, &laddr, cred);
|
||||
@ -842,12 +847,16 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam,
|
||||
imo = inp->inp_moptions;
|
||||
if (imo->imo_multicast_ifp != NULL) {
|
||||
ifp = imo->imo_multicast_ifp;
|
||||
IN_IFADDR_RLOCK();
|
||||
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link)
|
||||
if (ia->ia_ifp == ifp)
|
||||
break;
|
||||
if (ia == NULL)
|
||||
if (ia == NULL) {
|
||||
IN_IFADDR_RUNLOCK();
|
||||
return (EADDRNOTAVAIL);
|
||||
}
|
||||
laddr = ia->ia_addr.sin_addr;
|
||||
IN_IFADDR_RUNLOCK();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -114,6 +114,17 @@ extern u_long in_ifaddrhmask; /* mask for hash table */
|
||||
#define INADDR_HASH(x) \
|
||||
(&V_in_ifaddrhashtbl[INADDR_HASHVAL(x) & V_in_ifaddrhmask])
|
||||
|
||||
extern struct rwlock in_ifaddr_lock;
|
||||
|
||||
#define IN_IFADDR_LOCK_INIT() rw_init(&in_ifaddr_lock, "in_ifaddr_lock")
|
||||
#define IN_IFADDR_LOCK_ASSERT() rw_assert(&in_ifaddr_lock, RA_LOCKED)
|
||||
#define IN_IFADDR_RLOCK() rw_rlock(&in_ifaddr_lock)
|
||||
#define IN_IFADDR_RLOCK_ASSERT() rw_assert(&in_ifaddr_lock, RA_RLOCKED)
|
||||
#define IN_IFADDR_RUNLOCK() rw_runlock(&in_ifaddr_lock)
|
||||
#define IN_IFADDR_WLOCK() rw_wlock(&in_ifaddr_lock)
|
||||
#define IN_IFADDR_WLOCK_ASSERT() rw_assert(&in_ifaddr_lock, RA_WLOCKED)
|
||||
#define IN_IFADDR_WUNLOCK() rw_wunlock(&in_ifaddr_lock)
|
||||
|
||||
/*
|
||||
* Macro for finding the internet address structure (in_ifaddr)
|
||||
* corresponding to one of our IP addresses (in_addr).
|
||||
|
@ -1500,6 +1500,7 @@ carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin)
|
||||
|
||||
/* we have to do it by hands to check we won't match on us */
|
||||
ia_if = NULL; own = 0;
|
||||
IN_IFADDR_RLOCK();
|
||||
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
|
||||
/* and, yeah, we need a multicast-capable iface too */
|
||||
if (ia->ia_ifp != SC2IFP(sc) &&
|
||||
@ -1513,20 +1514,30 @@ carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin)
|
||||
}
|
||||
}
|
||||
|
||||
if (!ia_if)
|
||||
if (!ia_if) {
|
||||
IN_IFADDR_RUNLOCK();
|
||||
return (EADDRNOTAVAIL);
|
||||
}
|
||||
|
||||
ia = ia_if;
|
||||
ifa_ref(&ia->ia_ifa);
|
||||
IN_IFADDR_RUNLOCK();
|
||||
|
||||
ifp = ia->ia_ifp;
|
||||
|
||||
if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0 ||
|
||||
(imo->imo_multicast_ifp && imo->imo_multicast_ifp != ifp))
|
||||
(imo->imo_multicast_ifp && imo->imo_multicast_ifp != ifp)) {
|
||||
ifa_free(&ia->ia_ifa);
|
||||
return (EADDRNOTAVAIL);
|
||||
}
|
||||
|
||||
if (imo->imo_num_memberships == 0) {
|
||||
addr.s_addr = htonl(INADDR_CARP_GROUP);
|
||||
if ((imo->imo_membership[0] = in_addmulti(&addr, ifp)) == NULL)
|
||||
if ((imo->imo_membership[0] = in_addmulti(&addr, ifp)) ==
|
||||
NULL) {
|
||||
ifa_free(&ia->ia_ifa);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
imo->imo_num_memberships++;
|
||||
imo->imo_multicast_ifp = ifp;
|
||||
imo->imo_multicast_ttl = CARP_DFLTTL;
|
||||
@ -1601,11 +1612,13 @@ carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin)
|
||||
carp_setrun(sc, 0);
|
||||
|
||||
CARP_UNLOCK(cif);
|
||||
ifa_free(&ia->ia_ifa); /* XXXRW: should hold reference for softc. */
|
||||
|
||||
return (0);
|
||||
|
||||
cleanup:
|
||||
in_delmulti(imo->imo_membership[--imo->imo_num_memberships]);
|
||||
ifa_free(&ia->ia_ifa);
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
@ -675,12 +675,16 @@ icmp_reflect(struct mbuf *m)
|
||||
* If the incoming packet was addressed directly to one of our
|
||||
* own addresses, use dst as the src for the reply.
|
||||
*/
|
||||
IN_IFADDR_RLOCK();
|
||||
LIST_FOREACH(ia, INADDR_HASH(t.s_addr), ia_hash) {
|
||||
if (t.s_addr == IA_SIN(ia)->sin_addr.s_addr) {
|
||||
t = IA_SIN(ia)->sin_addr;
|
||||
IN_IFADDR_RUNLOCK();
|
||||
goto match;
|
||||
}
|
||||
}
|
||||
IN_IFADDR_RUNLOCK();
|
||||
|
||||
/*
|
||||
* If the incoming packet was addressed to one of our broadcast
|
||||
* addresses, use the first non-broadcast address which corresponds
|
||||
|
@ -117,6 +117,7 @@ static int maxfragsperpacket;
|
||||
int ipstealth;
|
||||
static int nipq; /* Total # of reass queues */
|
||||
#endif
|
||||
struct rwlock in_ifaddr_lock;
|
||||
|
||||
SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_ip, IPCTL_FORWARDING,
|
||||
forwarding, CTLFLAG_RW, ipforwarding, 0,
|
||||
@ -325,6 +326,7 @@ ip_init(void)
|
||||
|
||||
TAILQ_INIT(&V_in_ifaddrhead);
|
||||
V_in_ifaddrhashtbl = hashinit(INADDR_NHASH, M_IFADDR, &V_in_ifaddrhmask);
|
||||
IN_IFADDR_LOCK_INIT();
|
||||
|
||||
/* Initialize IP reassembly queue. */
|
||||
for (i = 0; i < IPREASS_NHASH; i++)
|
||||
@ -615,6 +617,7 @@ ip_input(struct mbuf *m)
|
||||
/*
|
||||
* Check for exact addresses in the hash bucket.
|
||||
*/
|
||||
/* IN_IFADDR_RLOCK(); */
|
||||
LIST_FOREACH(ia, INADDR_HASH(ip->ip_dst.s_addr), ia_hash) {
|
||||
/*
|
||||
* If the address matches, verify that the packet
|
||||
@ -624,9 +627,12 @@ ip_input(struct mbuf *m)
|
||||
if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr &&
|
||||
(!checkif || ia->ia_ifp == ifp)) {
|
||||
ifa_ref(&ia->ia_ifa);
|
||||
/* IN_IFADDR_RUNLOCK(); */
|
||||
goto ours;
|
||||
}
|
||||
}
|
||||
/* IN_IFADDR_RUNLOCK(); */
|
||||
|
||||
/*
|
||||
* Check for broadcast addresses.
|
||||
*
|
||||
|
@ -678,9 +678,12 @@ rip_ctlinput(int cmd, struct sockaddr *sa, void *vip)
|
||||
|
||||
switch (cmd) {
|
||||
case PRC_IFDOWN:
|
||||
IN_IFADDR_RLOCK();
|
||||
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
|
||||
if (ia->ia_ifa.ifa_addr == sa
|
||||
&& (ia->ia_flags & IFA_ROUTE)) {
|
||||
ifa_ref(&ia->ia_ifa);
|
||||
IN_IFADDR_RUNLOCK();
|
||||
/*
|
||||
* in_ifscrub kills the interface route.
|
||||
*/
|
||||
@ -692,18 +695,26 @@ rip_ctlinput(int cmd, struct sockaddr *sa, void *vip)
|
||||
* routing process they will come back.
|
||||
*/
|
||||
in_ifadown(&ia->ia_ifa, 0);
|
||||
ifa_free(&ia->ia_ifa);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ia == NULL) /* If ia matched, already unlocked. */
|
||||
IN_IFADDR_RUNLOCK();
|
||||
break;
|
||||
|
||||
case PRC_IFUP:
|
||||
IN_IFADDR_RLOCK();
|
||||
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
|
||||
if (ia->ia_ifa.ifa_addr == sa)
|
||||
break;
|
||||
}
|
||||
if (ia == 0 || (ia->ia_flags & IFA_ROUTE))
|
||||
if (ia == NULL || (ia->ia_flags & IFA_ROUTE)) {
|
||||
IN_IFADDR_RUNLOCK();
|
||||
return;
|
||||
}
|
||||
ifa_ref(&ia->ia_ifa);
|
||||
IN_IFADDR_RUNLOCK();
|
||||
flags = RTF_UP;
|
||||
ifp = ia->ia_ifa.ifa_ifp;
|
||||
|
||||
@ -714,6 +725,7 @@ rip_ctlinput(int cmd, struct sockaddr *sa, void *vip)
|
||||
err = rtinit(&ia->ia_ifa, RTM_ADD, flags);
|
||||
if (err == 0)
|
||||
ia->ia_flags |= IFA_ROUTE;
|
||||
ifa_free(&ia->ia_ifa);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -3939,6 +3939,7 @@ key_ismyaddr(sa)
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
sin = (struct sockaddr_in *)sa;
|
||||
IN_IFADDR_RLOCK();
|
||||
for (ia = V_in_ifaddrhead.tqh_first; ia;
|
||||
ia = ia->ia_link.tqe_next)
|
||||
{
|
||||
@ -3946,9 +3947,11 @@ key_ismyaddr(sa)
|
||||
sin->sin_len == ia->ia_addr.sin_len &&
|
||||
sin->sin_addr.s_addr == ia->ia_addr.sin_addr.s_addr)
|
||||
{
|
||||
IN_IFADDR_RUNLOCK();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
IN_IFADDR_RUNLOCK();
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
|
@ -1553,11 +1553,15 @@ nfs_create(struct vop_create_args *ap)
|
||||
tl = nfsm_build(u_int32_t *, NFSX_V3CREATEVERF);
|
||||
#ifdef INET
|
||||
INIT_VNET_INET(curvnet);
|
||||
IN_IFADDR_RLOCK();
|
||||
if (!TAILQ_EMPTY(&V_in_ifaddrhead))
|
||||
*tl++ = IA_SIN(TAILQ_FIRST(&V_in_ifaddrhead))->sin_addr.s_addr;
|
||||
else
|
||||
#endif
|
||||
*tl++ = create_verf;
|
||||
#ifdef INET
|
||||
IN_IFADDR_RUNLOCK();
|
||||
#endif
|
||||
*tl = ++create_verf;
|
||||
} else {
|
||||
*tl = txdr_unsigned(NFSV3CREATE_UNCHECKED);
|
||||
|
Loading…
Reference in New Issue
Block a user