diff options
author | suz <suz@FreeBSD.org> | 2006-03-24 16:20:12 +0000 |
---|---|---|
committer | suz <suz@FreeBSD.org> | 2006-03-24 16:20:12 +0000 |
commit | 0f0a98fed88d1f3b6c70ffa9b1ce7142f85e8e78 (patch) | |
tree | d41d3db54ad758916fded9fea396ce780e07b3b1 /sys/netinet6/nd6.c | |
parent | beb8ed1d59dd3b6f3ad8bdda8f32d9b46f54e220 (diff) | |
download | FreeBSD-src-0f0a98fed88d1f3b6c70ffa9b1ce7142f85e8e78.zip FreeBSD-src-0f0a98fed88d1f3b6c70ffa9b1ce7142f85e8e78.tar.gz |
fixed a memory leak when net.inet6.icmp6.nd6_maxqueuelen is greater than 1
Obtained from: KAME
MFC after: 3 days
Diffstat (limited to 'sys/netinet6/nd6.c')
-rw-r--r-- | sys/netinet6/nd6.c | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index 303d947..3ff8b22 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -114,6 +114,7 @@ static void nd6_slowtimo __P((void *)); static int regen_tmpaddr __P((struct in6_ifaddr *)); static struct llinfo_nd6 *nd6_free __P((struct rtentry *, int)); static void nd6_llinfo_timer __P((void *)); +static void clear_llinfo_pqueue __P((struct llinfo_nd6 *)); struct callout nd6_slowtimo_ch; struct callout nd6_timer_ch; @@ -460,13 +461,19 @@ nd6_llinfo_timer(arg) } else { struct mbuf *m = ln->ln_hold; if (m) { + struct mbuf *m0; + /* * assuming every packet in ln_hold has the * same IP header */ - ln->ln_hold = NULL; + m0 = m->m_nextpkt; + m->m_nextpkt = NULL; icmp6_error2(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR, 0, rt->rt_ifp); + + ln->ln_hold = m0; + clear_llinfo_pqueue(ln); } if (rt) (void)nd6_free(rt, 0); @@ -1403,8 +1410,7 @@ nd6_rtrequest(req, rt, info) nd6_llinfo_settimer(ln, -1); rt->rt_llinfo = 0; rt->rt_flags &= ~RTF_LLINFO; - if (ln->ln_hold) - m_freem(ln->ln_hold); + clear_llinfo_pqueue(ln); Free((caddr_t)ln); } } @@ -2078,7 +2084,7 @@ again: while (i >= nd6_maxqueuelen) { m_hold = ln->ln_hold; ln->ln_hold = ln->ln_hold->m_nextpkt; - m_free(m_hold); + m_freem(m_hold); i--; } } else { @@ -2236,6 +2242,22 @@ nd6_storelladdr(ifp, rt0, m, dst, desten) return (0); } +static void +clear_llinfo_pqueue(ln) + struct llinfo_nd6 *ln; +{ + struct mbuf *m_hold, *m_hold_next; + + for (m_hold = ln->ln_hold; m_hold; m_hold = m_hold_next) { + m_hold_next = m_hold->m_nextpkt; + m_hold->m_nextpkt = NULL; + m_freem(m_hold); + } + + ln->ln_hold = NULL; + return; +} + static int nd6_sysctl_drlist(SYSCTL_HANDLER_ARGS); static int nd6_sysctl_prlist(SYSCTL_HANDLER_ARGS); #ifdef SYSCTL_DECL |