diff options
author | rwatson <rwatson@FreeBSD.org> | 2009-04-20 13:45:39 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2009-04-20 13:45:39 +0000 |
commit | bb7780fc12a3d9a7f865f1f353dab01381958b66 (patch) | |
tree | 7136bd4fcb341d775b676f17c06c4a59ac30642f | |
parent | 518b993576747e5cd8b7bf89c8dde86eab336c02 (diff) | |
download | FreeBSD-src-bb7780fc12a3d9a7f865f1f353dab01381958b66.zip FreeBSD-src-bb7780fc12a3d9a7f865f1f353dab01381958b66.tar.gz |
In icmp_reflect(), acquire the inteface address list lock when
searching for a source address to use.
MFC after: 2 weeks
Reviewed by: bz
-rw-r--r-- | sys/netinet/ip_icmp.c | 40 |
1 files changed, 28 insertions, 12 deletions
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index fe06b9a..8c2ef26 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -650,7 +650,7 @@ icmp_reflect(struct mbuf *m) INIT_VNET_INET(curvnet); struct ip *ip = mtod(m, struct ip *); struct ifaddr *ifa; - struct ifnet *ifn; + struct ifnet *ifp; struct in_ifaddr *ia; struct in_addr t; struct mbuf *opts = 0; @@ -673,24 +673,32 @@ 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. */ - LIST_FOREACH(ia, INADDR_HASH(t.s_addr), ia_hash) - if (t.s_addr == IA_SIN(ia)->sin_addr.s_addr) + 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; goto match; + } + } /* * If the incoming packet was addressed to one of our broadcast * addresses, use the first non-broadcast address which corresponds * to the incoming interface. */ - if (m->m_pkthdr.rcvif != NULL && - m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST) { - TAILQ_FOREACH(ifa, &m->m_pkthdr.rcvif->if_addrhead, ifa_link) { + ifp = m->m_pkthdr.rcvif; + if (ifp != NULL && ifp->if_flags & IFF_BROADCAST) { + IF_ADDR_LOCK(ifp); + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != AF_INET) continue; ia = ifatoia(ifa); if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr == - t.s_addr) + t.s_addr) { + t = IA_SIN(ia)->sin_addr; + IF_ADDR_UNLOCK(ifp); goto match; + } } + IF_ADDR_UNLOCK(ifp); } /* * If the packet was transiting through us, use the address of @@ -698,13 +706,17 @@ icmp_reflect(struct mbuf *m) * doesn't have a suitable IP address, the normal selection * criteria apply. */ - if (V_icmp_rfi && m->m_pkthdr.rcvif != NULL) { - TAILQ_FOREACH(ifa, &m->m_pkthdr.rcvif->if_addrhead, ifa_link) { + if (V_icmp_rfi && ifp != NULL) { + IF_ADDR_LOCK(ifp); + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != AF_INET) continue; ia = ifatoia(ifa); + t = IA_SIN(ia)->sin_addr; + IF_ADDR_UNLOCK(ifp); goto match; } + IF_ADDR_UNLOCK(ifp); } /* * If the incoming packet was not addressed directly to us, use @@ -712,13 +724,17 @@ icmp_reflect(struct mbuf *m) * net.inet.icmp.reply_src (default not set). Otherwise continue * with normal source selection. */ - if (V_reply_src[0] != '\0' && (ifn = ifunit(V_reply_src))) { - TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) { + if (V_reply_src[0] != '\0' && (ifp = ifunit(V_reply_src))) { + IF_ADDR_LOCK(ifp); + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != AF_INET) continue; ia = ifatoia(ifa); + t = IA_SIN(ia)->sin_addr; + IF_ADDR_UNLOCK(ifp); goto match; } + IF_ADDR_UNLOCK(ifp); } /* * If the packet was transiting through us, use the address of @@ -732,11 +748,11 @@ icmp_reflect(struct mbuf *m) ICMPSTAT_INC(icps_noroute); goto done; } + t = IA_SIN(ia)->sin_addr; match: #ifdef MAC mac_netinet_icmp_replyinplace(m); #endif - t = IA_SIN(ia)->sin_addr; ip->ip_src = t; ip->ip_ttl = V_ip_defttl; |