Author: melifaro Date: Sun Jan 10 11:59:55 2016 New Revision: 293632 URL: https://svnweb.freebsd.org/changeset/base/293632
Log: Do not hold ifaddr reference for the whole icmp6_reflect() exec time. Copy source address, calculate hlim and release refcount instead. Modified: head/sys/netinet6/icmp6.c Modified: head/sys/netinet6/icmp6.c ============================================================================== --- head/sys/netinet6/icmp6.c Sun Jan 10 08:41:01 2016 (r293631) +++ head/sys/netinet6/icmp6.c Sun Jan 10 11:59:55 2016 (r293632) @@ -2114,13 +2114,13 @@ icmp6_rip6_input(struct mbuf **mp, int o 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; } _______________________________________________ svn-src-head@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"