From 31d4137bf3a39c32b3db9efbe617597337956418 Mon Sep 17 00:00:00 2001 From: SUZUKI Shinsuke Date: Fri, 24 Mar 2006 16:20:12 +0000 Subject: [PATCH] fixed a memory leak when net.inet6.icmp6.nd6_maxqueuelen is greater than 1 Obtained from: KAME MFC after: 3 days --- sys/netinet6/nd6.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index 303d947d7585..3ff8b22419a7 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