diff options
Diffstat (limited to 'sys/netinet6/frag6.c')
-rw-r--r-- | sys/netinet6/frag6.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/sys/netinet6/frag6.c b/sys/netinet6/frag6.c index ea4e6ca..dbf9279 100644 --- a/sys/netinet6/frag6.c +++ b/sys/netinet6/frag6.c @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $KAME: frag6.c,v 1.24 2000/03/25 07:23:41 sumikawa Exp $ */ +/* $KAME: frag6.c,v 1.31 2001/05/17 13:45:34 jinmei Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -66,6 +66,7 @@ static void frag6_insque __P((struct ip6q *, struct ip6q *)); static void frag6_remque __P((struct ip6q *)); static void frag6_freef __P((struct ip6q *)); +/* XXX we eventually need splreass6, or some real semaphore */ int frag6_doing_reass; u_int frag6_nfragpackets; struct ip6q ip6q; /* ip6 reassemble queue */ @@ -206,6 +207,8 @@ frag6_input(mp, offp, proto) /* offset now points to data portion */ offset += sizeof(struct ip6_frag); + frag6_doing_reass = 1; + for (q6 = ip6q.ip6q_next; q6 != &ip6q; q6 = q6->ip6q_next) if (ip6f->ip6f_ident == q6->ip6q_ident && IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &q6->ip6q_src) && @@ -217,7 +220,6 @@ frag6_input(mp, offp, proto) * the first fragment to arrive, create a reassembly queue. */ first_frag = 1; - frag6_nfragpackets++; /* * Enforce upper bound on number of fragmented packets @@ -225,11 +227,11 @@ frag6_input(mp, offp, proto) * If maxfrag is 0, never accept fragments. * If maxfrag is -1, accept all fragments without limitation. */ - if (frag6_nfragpackets >= (u_int)ip6_maxfragpackets) { - ip6stat.ip6s_fragoverflow++; - in6_ifstat_inc(dstifp, ifs6_reass_fail); - frag6_freef(ip6q.ip6q_prev); - } + if (ip6_maxfragpackets < 0) + ; + else if (frag6_nfragpackets >= (u_int)ip6_maxfragpackets) + goto dropfrag; + frag6_nfragpackets++; q6 = (struct ip6q *)malloc(sizeof(struct ip6q), M_FTABLE, M_DONTWAIT); if (q6 == NULL) @@ -274,6 +276,7 @@ frag6_input(mp, offp, proto) icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, offset - sizeof(struct ip6_frag) + offsetof(struct ip6_frag, ip6f_offlg)); + frag6_doing_reass = 0; return(IPPROTO_DONE); } } @@ -281,6 +284,7 @@ frag6_input(mp, offp, proto) icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, offset - sizeof(struct ip6_frag) + offsetof(struct ip6_frag, ip6f_offlg)); + frag6_doing_reass = 0; return(IPPROTO_DONE); } /* @@ -531,6 +535,7 @@ insert: in6_ifstat_inc(dstifp, ifs6_reass_fail); ip6stat.ip6s_fragdropped++; m_freem(m); + frag6_doing_reass = 0; return IPPROTO_DONE; } @@ -620,7 +625,7 @@ frag6_remque(p6) } /* - * IP timer processing; + * IPv6 reassembling timer processing; * if a timer expires on a reassembly * queue, discard it. */ @@ -629,9 +634,6 @@ frag6_slowtimo() { struct ip6q *q6; int s = splnet(); -#if 0 - extern struct route_in6 ip6_forward_rt; -#endif frag6_doing_reass = 1; q6 = ip6q.ip6q_next; @@ -650,7 +652,8 @@ frag6_slowtimo() * (due to the limit being lowered), drain off * enough to get down to the new limit. */ - while (frag6_nfragpackets > (u_int)ip6_maxfragpackets) { + while (frag6_nfragpackets > (u_int)ip6_maxfragpackets && + ip6q.ip6q_prev) { ip6stat.ip6s_fragoverflow++; /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */ frag6_freef(ip6q.ip6q_prev); |