frag6.c (77969) | frag6.c (78064) |
---|---|
1/* $FreeBSD: head/sys/netinet6/frag6.c 77969 2001-06-10 11:04:10Z jesper $ */ 2/* $KAME: frag6.c,v 1.24 2000/03/25 07:23:41 sumikawa Exp $ */ | 1/* $FreeBSD: head/sys/netinet6/frag6.c 78064 2001-06-11 12:39:29Z ume $ */ 2/* $KAME: frag6.c,v 1.31 2001/05/17 13:45:34 jinmei Exp $ */ |
3 4/* 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: --- 50 unchanged lines hidden (view full) --- 61#define IN6_IFSTAT_STRICT 62 63static void frag6_enq __P((struct ip6asfrag *, struct ip6asfrag *)); 64static void frag6_deq __P((struct ip6asfrag *)); 65static void frag6_insque __P((struct ip6q *, struct ip6q *)); 66static void frag6_remque __P((struct ip6q *)); 67static void frag6_freef __P((struct ip6q *)); 68 | 3 4/* 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: --- 50 unchanged lines hidden (view full) --- 61#define IN6_IFSTAT_STRICT 62 63static void frag6_enq __P((struct ip6asfrag *, struct ip6asfrag *)); 64static void frag6_deq __P((struct ip6asfrag *)); 65static void frag6_insque __P((struct ip6q *, struct ip6q *)); 66static void frag6_remque __P((struct ip6q *)); 67static void frag6_freef __P((struct ip6q *)); 68 |
69/* XXX we eventually need splreass6, or some real semaphore */ |
|
69int frag6_doing_reass; 70u_int frag6_nfragpackets; 71struct ip6q ip6q; /* ip6 reassemble queue */ 72 73/* FreeBSD tweak */ 74static MALLOC_DEFINE(M_FTABLE, "fragment", "fragment reassembly header"); 75 76/* --- 124 unchanged lines hidden (view full) --- 201 } 202 203 ip6stat.ip6s_fragments++; 204 in6_ifstat_inc(dstifp, ifs6_reass_reqd); 205 206 /* offset now points to data portion */ 207 offset += sizeof(struct ip6_frag); 208 | 70int frag6_doing_reass; 71u_int frag6_nfragpackets; 72struct ip6q ip6q; /* ip6 reassemble queue */ 73 74/* FreeBSD tweak */ 75static MALLOC_DEFINE(M_FTABLE, "fragment", "fragment reassembly header"); 76 77/* --- 124 unchanged lines hidden (view full) --- 202 } 203 204 ip6stat.ip6s_fragments++; 205 in6_ifstat_inc(dstifp, ifs6_reass_reqd); 206 207 /* offset now points to data portion */ 208 offset += sizeof(struct ip6_frag); 209 |
210 frag6_doing_reass = 1; 211 |
|
209 for (q6 = ip6q.ip6q_next; q6 != &ip6q; q6 = q6->ip6q_next) 210 if (ip6f->ip6f_ident == q6->ip6q_ident && 211 IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &q6->ip6q_src) && 212 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &q6->ip6q_dst)) 213 break; 214 215 if (q6 == &ip6q) { 216 /* 217 * the first fragment to arrive, create a reassembly queue. 218 */ 219 first_frag = 1; | 212 for (q6 = ip6q.ip6q_next; q6 != &ip6q; q6 = q6->ip6q_next) 213 if (ip6f->ip6f_ident == q6->ip6q_ident && 214 IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &q6->ip6q_src) && 215 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &q6->ip6q_dst)) 216 break; 217 218 if (q6 == &ip6q) { 219 /* 220 * the first fragment to arrive, create a reassembly queue. 221 */ 222 first_frag = 1; |
220 frag6_nfragpackets++; | |
221 222 /* 223 * Enforce upper bound on number of fragmented packets 224 * for which we attempt reassembly; 225 * If maxfrag is 0, never accept fragments. 226 * If maxfrag is -1, accept all fragments without limitation. 227 */ | 223 224 /* 225 * Enforce upper bound on number of fragmented packets 226 * for which we attempt reassembly; 227 * If maxfrag is 0, never accept fragments. 228 * If maxfrag is -1, accept all fragments without limitation. 229 */ |
228 if (frag6_nfragpackets >= (u_int)ip6_maxfragpackets) { 229 ip6stat.ip6s_fragoverflow++; 230 in6_ifstat_inc(dstifp, ifs6_reass_fail); 231 frag6_freef(ip6q.ip6q_prev); 232 } | 230 if (ip6_maxfragpackets < 0) 231 ; 232 else if (frag6_nfragpackets >= (u_int)ip6_maxfragpackets) 233 goto dropfrag; 234 frag6_nfragpackets++; |
233 q6 = (struct ip6q *)malloc(sizeof(struct ip6q), M_FTABLE, 234 M_DONTWAIT); 235 if (q6 == NULL) 236 goto dropfrag; 237 bzero(q6, sizeof(*q6)); 238 239 frag6_insque(q6, &ip6q); 240 --- 28 unchanged lines hidden (view full) --- 269 */ 270 frgpartlen = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen) - offset; 271 if (q6->ip6q_unfrglen >= 0) { 272 /* The 1st fragment has already arrived. */ 273 if (q6->ip6q_unfrglen + fragoff + frgpartlen > IPV6_MAXPACKET) { 274 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, 275 offset - sizeof(struct ip6_frag) + 276 offsetof(struct ip6_frag, ip6f_offlg)); | 235 q6 = (struct ip6q *)malloc(sizeof(struct ip6q), M_FTABLE, 236 M_DONTWAIT); 237 if (q6 == NULL) 238 goto dropfrag; 239 bzero(q6, sizeof(*q6)); 240 241 frag6_insque(q6, &ip6q); 242 --- 28 unchanged lines hidden (view full) --- 271 */ 272 frgpartlen = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen) - offset; 273 if (q6->ip6q_unfrglen >= 0) { 274 /* The 1st fragment has already arrived. */ 275 if (q6->ip6q_unfrglen + fragoff + frgpartlen > IPV6_MAXPACKET) { 276 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, 277 offset - sizeof(struct ip6_frag) + 278 offsetof(struct ip6_frag, ip6f_offlg)); |
279 frag6_doing_reass = 0; |
|
277 return(IPPROTO_DONE); 278 } 279 } 280 else if (fragoff + frgpartlen > IPV6_MAXPACKET) { 281 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, 282 offset - sizeof(struct ip6_frag) + 283 offsetof(struct ip6_frag, ip6f_offlg)); | 280 return(IPPROTO_DONE); 281 } 282 } 283 else if (fragoff + frgpartlen > IPV6_MAXPACKET) { 284 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, 285 offset - sizeof(struct ip6_frag) + 286 offsetof(struct ip6_frag, ip6f_offlg)); |
287 frag6_doing_reass = 0; |
|
284 return(IPPROTO_DONE); 285 } 286 /* 287 * If it's the first fragment, do the above check for each 288 * fragment already stored in the reassembly queue. 289 */ 290 if (fragoff == 0) { 291 for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6; --- 234 unchanged lines hidden (view full) --- 526 527 frag6_doing_reass = 0; 528 return nxt; 529 530 dropfrag: 531 in6_ifstat_inc(dstifp, ifs6_reass_fail); 532 ip6stat.ip6s_fragdropped++; 533 m_freem(m); | 288 return(IPPROTO_DONE); 289 } 290 /* 291 * If it's the first fragment, do the above check for each 292 * fragment already stored in the reassembly queue. 293 */ 294 if (fragoff == 0) { 295 for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6; --- 234 unchanged lines hidden (view full) --- 530 531 frag6_doing_reass = 0; 532 return nxt; 533 534 dropfrag: 535 in6_ifstat_inc(dstifp, ifs6_reass_fail); 536 ip6stat.ip6s_fragdropped++; 537 m_freem(m); |
538 frag6_doing_reass = 0; |
|
534 return IPPROTO_DONE; 535} 536 537/* 538 * Free a fragment reassembly header and all 539 * associated datagrams. 540 */ 541void --- 73 unchanged lines hidden (view full) --- 615frag6_remque(p6) 616 struct ip6q *p6; 617{ 618 p6->ip6q_prev->ip6q_next = p6->ip6q_next; 619 p6->ip6q_next->ip6q_prev = p6->ip6q_prev; 620} 621 622/* | 539 return IPPROTO_DONE; 540} 541 542/* 543 * Free a fragment reassembly header and all 544 * associated datagrams. 545 */ 546void --- 73 unchanged lines hidden (view full) --- 620frag6_remque(p6) 621 struct ip6q *p6; 622{ 623 p6->ip6q_prev->ip6q_next = p6->ip6q_next; 624 p6->ip6q_next->ip6q_prev = p6->ip6q_prev; 625} 626 627/* |
623 * IP timer processing; | 628 * IPv6 reassembling timer processing; |
624 * if a timer expires on a reassembly 625 * queue, discard it. 626 */ 627void 628frag6_slowtimo() 629{ 630 struct ip6q *q6; 631 int s = splnet(); | 629 * if a timer expires on a reassembly 630 * queue, discard it. 631 */ 632void 633frag6_slowtimo() 634{ 635 struct ip6q *q6; 636 int s = splnet(); |
632#if 0 633 extern struct route_in6 ip6_forward_rt; 634#endif | |
635 636 frag6_doing_reass = 1; 637 q6 = ip6q.ip6q_next; 638 if (q6) 639 while (q6 != &ip6q) { 640 --q6->ip6q_ttl; 641 q6 = q6->ip6q_next; 642 if (q6->ip6q_prev->ip6q_ttl == 0) { 643 ip6stat.ip6s_fragtimeout++; 644 /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */ 645 frag6_freef(q6->ip6q_prev); 646 } 647 } 648 /* 649 * If we are over the maximum number of fragments 650 * (due to the limit being lowered), drain off 651 * enough to get down to the new limit. 652 */ | 637 638 frag6_doing_reass = 1; 639 q6 = ip6q.ip6q_next; 640 if (q6) 641 while (q6 != &ip6q) { 642 --q6->ip6q_ttl; 643 q6 = q6->ip6q_next; 644 if (q6->ip6q_prev->ip6q_ttl == 0) { 645 ip6stat.ip6s_fragtimeout++; 646 /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */ 647 frag6_freef(q6->ip6q_prev); 648 } 649 } 650 /* 651 * If we are over the maximum number of fragments 652 * (due to the limit being lowered), drain off 653 * enough to get down to the new limit. 654 */ |
653 while (frag6_nfragpackets > (u_int)ip6_maxfragpackets) { | 655 while (frag6_nfragpackets > (u_int)ip6_maxfragpackets && 656 ip6q.ip6q_prev) { |
654 ip6stat.ip6s_fragoverflow++; 655 /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */ 656 frag6_freef(ip6q.ip6q_prev); 657 } 658 frag6_doing_reass = 0; 659 660#if 0 661 /* --- 31 unchanged lines hidden --- | 657 ip6stat.ip6s_fragoverflow++; 658 /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */ 659 frag6_freef(ip6q.ip6q_prev); 660 } 661 frag6_doing_reass = 0; 662 663#if 0 664 /* --- 31 unchanged lines hidden --- |