Do not hold ifaddr reference for the whole icmp6_reflect() exec time.
Copy source address, calculate hlim and release refcount instead.
This commit is contained in:
parent
290bc19b5b
commit
ab861e6c06
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=293632
@ -2114,13 +2114,13 @@ icmp6_rip6_input(struct mbuf **mp, int off)
|
||||
void
|
||||
icmp6_reflect(struct mbuf *m, size_t off)
|
||||
{
|
||||
struct in6_addr src, *srcp = NULL;
|
||||
struct in6_addr src6, *srcp;
|
||||
struct ip6_hdr *ip6;
|
||||
struct icmp6_hdr *icmp6;
|
||||
struct in6_ifaddr *ia = NULL;
|
||||
struct ifnet *outif = NULL;
|
||||
int plen;
|
||||
int type, code;
|
||||
int type, code, hlim;
|
||||
|
||||
/* too short to reflect */
|
||||
if (off < sizeof(struct ip6_hdr)) {
|
||||
@ -2166,6 +2166,8 @@ icmp6_reflect(struct mbuf *m, size_t off)
|
||||
icmp6 = (struct icmp6_hdr *)(ip6 + 1);
|
||||
type = icmp6->icmp6_type; /* keep type for statistics */
|
||||
code = icmp6->icmp6_code; /* ditto. */
|
||||
hlim = 0;
|
||||
srcp = NULL;
|
||||
|
||||
/*
|
||||
* If the incoming packet was addressed directly to us (i.e. unicast),
|
||||
@ -2177,8 +2179,18 @@ icmp6_reflect(struct mbuf *m, size_t off)
|
||||
if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
|
||||
ia = in6ifa_ifwithaddr(&ip6->ip6_dst, 0 /* XXX */);
|
||||
if (ia != NULL && !(ia->ia6_flags &
|
||||
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)))
|
||||
srcp = &ia->ia_addr.sin6_addr;
|
||||
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY))) {
|
||||
src6 = ia->ia_addr.sin6_addr;
|
||||
srcp = &src6;
|
||||
|
||||
if (m->m_pkthdr.rcvif != NULL) {
|
||||
/* XXX: This may not be the outgoing interface */
|
||||
hlim = ND_IFINFO(m->m_pkthdr.rcvif)->chlim;
|
||||
} else
|
||||
hlim = V_ip6_defhlim;
|
||||
}
|
||||
if (ia != NULL)
|
||||
ifa_free(&ia->ia_ifa);
|
||||
}
|
||||
|
||||
if (srcp == NULL) {
|
||||
@ -2195,16 +2207,16 @@ icmp6_reflect(struct mbuf *m, size_t off)
|
||||
sin6.sin6_len = sizeof(sin6);
|
||||
sin6.sin6_addr = ip6->ip6_dst; /* zone ID should be embedded */
|
||||
|
||||
e = in6_selectsrc(&sin6, NULL, NULL, NULL, &outif, &src);
|
||||
e = in6_selectsrc(&sin6, NULL, NULL, NULL, &outif, &src6);
|
||||
if (e) {
|
||||
char ip6buf[INET6_ADDRSTRLEN];
|
||||
nd6log((LOG_DEBUG,
|
||||
"icmp6_reflect: source can't be determined: "
|
||||
"dst=%s, error=%d\n",
|
||||
ip6_sprintf(ip6buf, &sin6.sin6_addr), e));
|
||||
ip6_sprintf(ip6buf, &ip6->ip6_dst), e));
|
||||
goto bad;
|
||||
}
|
||||
srcp = &src;
|
||||
srcp = &src6;
|
||||
}
|
||||
/*
|
||||
* ip6_input() drops a packet if its src is multicast.
|
||||
@ -2218,11 +2230,8 @@ icmp6_reflect(struct mbuf *m, size_t off)
|
||||
ip6->ip6_nxt = IPPROTO_ICMPV6;
|
||||
if (outif)
|
||||
ip6->ip6_hlim = ND_IFINFO(outif)->chlim;
|
||||
else if (m->m_pkthdr.rcvif) {
|
||||
/* XXX: This may not be the outgoing interface */
|
||||
ip6->ip6_hlim = ND_IFINFO(m->m_pkthdr.rcvif)->chlim;
|
||||
} else
|
||||
ip6->ip6_hlim = V_ip6_defhlim;
|
||||
else
|
||||
ip6->ip6_hlim = hlim;
|
||||
|
||||
icmp6->icmp6_cksum = 0;
|
||||
icmp6->icmp6_cksum = in6_cksum(m, IPPROTO_ICMPV6,
|
||||
@ -2238,13 +2247,9 @@ icmp6_reflect(struct mbuf *m, size_t off)
|
||||
if (outif)
|
||||
icmp6_ifoutstat_inc(outif, type, code);
|
||||
|
||||
if (ia != NULL)
|
||||
ifa_free(&ia->ia_ifa);
|
||||
return;
|
||||
|
||||
bad:
|
||||
if (ia != NULL)
|
||||
ifa_free(&ia->ia_ifa);
|
||||
m_freem(m);
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user