From 657b10fdbf86b6ea6cc358287931dceebebdaab7 Mon Sep 17 00:00:00 2001 From: suz Date: Fri, 21 Jan 2005 03:14:48 +0000 Subject: [PATCH] fixed a loss of fragmented packets when the corresponding NDP state is not resolved. --- CHANGELOG | 6 ++++- kame/sys/netinet6/nd6.c | 54 ++++++++++++++++++++++++++++--------- kame/sys/netinet6/nd6_nbr.c | 31 ++++++++++++++++----- 3 files changed, 71 insertions(+), 20 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index f7e1cfcc9d..138bae21e1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,11 @@ CHANGELOG for KAME kit -$KAME: CHANGELOG,v 1.2717 2005/01/17 09:53:51 suz Exp $ +$KAME: CHANGELOG,v 1.2718 2005/01/21 03:14:48 suz Exp $ <200501> +2005-01-21 suz@crl.hitachi.co.jp + * kame/sys/netinet6/{nd6.c, nd6_nbr.c}: fixed a loss of fragmented + packets when the corresponding NDP state is not resolved. + 2005-01-17 suz@crl.hitachi.co.jp * kame/sys/netinet6/icmp6.c: ignores ICMPv6 code field in case of ICMPv6 Packet-Too-Big. diff --git a/kame/sys/netinet6/nd6.c b/kame/sys/netinet6/nd6.c index 6da88ad156..2dc6722ec3 100644 --- a/kame/sys/netinet6/nd6.c +++ b/kame/sys/netinet6/nd6.c @@ -1,4 +1,4 @@ -/* $KAME: nd6.c,v 1.369 2005/01/20 09:14:05 t-momose Exp $ */ +/* $KAME: nd6.c,v 1.370 2005/01/21 03:14:49 suz Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -608,6 +608,10 @@ nd6_llinfo_timer(arg) } else { struct mbuf *m = ln->ln_hold; if (m) { + /* + * assuming every packet in ln_hold has the + * same IP header + */ ln->ln_hold = NULL; icmp6_error2(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR, 0, rt->rt_ifp); @@ -2116,12 +2120,28 @@ nd6_cache_lladdr(ifp, from, lladdr, lladdrlen, type, code) nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz); if (ln->ln_hold) { - /* - * we assume ifp is not a p2p here, so just - * set the 2nd argument as the 1st one. - */ - nd6_output(ifp, ifp, ln->ln_hold, - (struct sockaddr_in6 *)rt_key(rt), rt); + struct mbuf *m_hold, *m_hold_next; + for (m_hold = ln->ln_hold; m_hold; + m_hold = m_hold_next) { + struct mbuf *mpkt = NULL; + + m_hold_next = m_hold->m_nextpkt; + mpkt = m_copym(m_hold, 0, M_COPYALL, M_DONTWAIT); + if (mpkt == NULL) { + m_freem(m_hold); + break; + } + mpkt->m_nextpkt = NULL; + + /* + * we assume ifp is not a p2p here, so + * just set the 2nd argument as the + * 1st one. + */ + nd6_output(ifp, ifp, mpkt, + (struct sockaddr_in6 *)rt_key(rt), + rt); + } ln->ln_hold = NULL; } } else if (ln->ln_state == ND6_LLINFO_INCOMPLETE) { @@ -2494,14 +2514,24 @@ nd6_output(ifp, origifp, m0, dst, rt0) /* * There is a neighbor cache entry, but no ethernet address - * response yet. Replace the held mbuf (if any) with this - * latest one. + * response yet. Append this latest packet to the end of the + * packet queue in the mbuf */ if (ln->ln_state == ND6_LLINFO_NOSTATE) ln->ln_state = ND6_LLINFO_INCOMPLETE; - if (ln->ln_hold) - m_freem(ln->ln_hold); - ln->ln_hold = m; + if (ln->ln_hold) { + struct mbuf *m_hold, *m_hold_last; + + m_hold = m_hold_last = ln->ln_hold; + while (m_hold) { + m_hold_last = m_hold; + m_hold = m_hold->m_nextpkt; + } + m_hold_last->m_nextpkt = m; + } else { + ln->ln_hold = m; + } + /* * If there has been no NS for the neighbor after entering the * INCOMPLETE state, send the first solicitation. diff --git a/kame/sys/netinet6/nd6_nbr.c b/kame/sys/netinet6/nd6_nbr.c index 3e262eb51d..a1a9694e5b 100644 --- a/kame/sys/netinet6/nd6_nbr.c +++ b/kame/sys/netinet6/nd6_nbr.c @@ -1,4 +1,4 @@ -/* $KAME: nd6_nbr.c,v 1.153 2004/12/27 05:41:19 itojun Exp $ */ +/* $KAME: nd6_nbr.c,v 1.154 2005/01/21 03:14:49 suz Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -499,6 +499,10 @@ nd6_ns_output(ifp, daddr6, taddr6, ln, dad) struct in6_addr *hsrc = NULL; if (ln && ln->ln_hold) { + /* + * assuming every packet in ln_hold has the same IP + * header + */ hip6 = mtod(ln->ln_hold, struct ip6_hdr *); hsrc = &hip6->ip6_src; } @@ -921,12 +925,25 @@ nd6_na_input(m, off, icmp6len) rt->rt_flags &= ~RTF_REJECT; ln->ln_asked = 0; if (ln->ln_hold) { - /* - * we assume ifp is not a loopback here, so just set the 2nd - * argument as the 1st one. - */ - nd6_output(ifp, ifp, ln->ln_hold, - (struct sockaddr_in6 *)rt_key(rt), rt); + struct mbuf *m_hold, *m_hold_next; + + for (m_hold = ln->ln_hold; m_hold; m_hold = m_hold_next) { + struct mbuf *mpkt = NULL; + + m_hold_next = m_hold->m_nextpkt; + mpkt = m_copym(m_hold, 0, M_COPYALL, M_DONTWAIT); + if (mpkt == NULL) { + m_freem(m_hold); + break; + } + mpkt->m_nextpkt = NULL; + /* + * we assume ifp is not a loopback here, so just set + * the 2nd argument as the 1st one. + */ + nd6_output(ifp, ifp, mpkt, + (struct sockaddr_in6 *)rt_key(rt), rt); + } ln->ln_hold = NULL; }