1 /* $NetBSD: frag6.c,v 1.56 2014/09/05 05:33:06 matt Exp $ */ 2 /* $KAME: frag6.c,v 1.40 2002/05/27 21:40:31 itojun 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: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: frag6.c,v 1.56 2014/09/05 05:33:06 matt Exp $"); 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/mbuf.h> 39 #include <sys/domain.h> 40 #include <sys/protosw.h> 41 #include <sys/socket.h> 42 #include <sys/socketvar.h> 43 #include <sys/errno.h> 44 #include <sys/time.h> 45 #include <sys/kmem.h> 46 #include <sys/kernel.h> 47 #include <sys/syslog.h> 48 49 #include <net/if.h> 50 #include <net/route.h> 51 52 #include <netinet/in.h> 53 #include <netinet/in_var.h> 54 #include <netinet/ip6.h> 55 #include <netinet6/ip6_var.h> 56 #include <netinet6/ip6_private.h> 57 #include <netinet/icmp6.h> 58 59 #include <net/net_osdep.h> 60 61 static void frag6_enq(struct ip6asfrag *, struct ip6asfrag *); 62 static void frag6_deq(struct ip6asfrag *); 63 static void frag6_insque(struct ip6q *, struct ip6q *); 64 static void frag6_remque(struct ip6q *); 65 static void frag6_freef(struct ip6q *); 66 67 static int frag6_drainwanted; 68 69 u_int frag6_nfragpackets; 70 u_int frag6_nfrags; 71 struct ip6q ip6q; /* ip6 reassemble queue */ 72 73 static kmutex_t frag6_lock; 74 75 /* 76 * Initialise reassembly queue and fragment identifier. 77 */ 78 void 79 frag6_init(void) 80 { 81 82 ip6q.ip6q_next = ip6q.ip6q_prev = &ip6q; 83 mutex_init(&frag6_lock, MUTEX_DEFAULT, IPL_NET); 84 } 85 86 /* 87 * IPv6 fragment input. 88 * 89 * In RFC2460, fragment and reassembly rule do not agree with each other, 90 * in terms of next header field handling in fragment header. 91 * While the sender will use the same value for all of the fragmented packets, 92 * receiver is suggested not to check the consistency. 93 * 94 * fragment rule (p20): 95 * (2) A Fragment header containing: 96 * The Next Header value that identifies the first header of 97 * the Fragmentable Part of the original packet. 98 * -> next header field is same for all fragments 99 * 100 * reassembly rule (p21): 101 * The Next Header field of the last header of the Unfragmentable 102 * Part is obtained from the Next Header field of the first 103 * fragment's Fragment header. 104 * -> should grab it from the first fragment only 105 * 106 * The following note also contradicts with fragment rule - noone is going to 107 * send different fragment with different next header field. 108 * 109 * additional note (p22): 110 * The Next Header values in the Fragment headers of different 111 * fragments of the same original packet may differ. Only the value 112 * from the Offset zero fragment packet is used for reassembly. 113 * -> should grab it from the first fragment only 114 * 115 * There is no explicit reason given in the RFC. Historical reason maybe? 116 */ 117 int 118 frag6_input(struct mbuf **mp, int *offp, int proto) 119 { 120 struct rtentry *rt; 121 struct mbuf *m = *mp, *t; 122 struct ip6_hdr *ip6; 123 struct ip6_frag *ip6f; 124 struct ip6q *q6; 125 struct ip6asfrag *af6, *ip6af, *af6dwn; 126 int offset = *offp, nxt, i, next; 127 int first_frag = 0; 128 int fragoff, frgpartlen; /* must be larger than u_int16_t */ 129 struct ifnet *dstifp; 130 static struct route ro; 131 union { 132 struct sockaddr dst; 133 struct sockaddr_in6 dst6; 134 } u; 135 136 ip6 = mtod(m, struct ip6_hdr *); 137 IP6_EXTHDR_GET(ip6f, struct ip6_frag *, m, offset, sizeof(*ip6f)); 138 if (ip6f == NULL) 139 return IPPROTO_DONE; 140 141 dstifp = NULL; 142 /* find the destination interface of the packet. */ 143 sockaddr_in6_init(&u.dst6, &ip6->ip6_dst, 0, 0, 0); 144 if ((rt = rtcache_lookup(&ro, &u.dst)) != NULL && rt->rt_ifa != NULL) 145 dstifp = ((struct in6_ifaddr *)rt->rt_ifa)->ia_ifp; 146 147 /* jumbo payload can't contain a fragment header */ 148 if (ip6->ip6_plen == 0) { 149 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, offset); 150 in6_ifstat_inc(dstifp, ifs6_reass_fail); 151 return IPPROTO_DONE; 152 } 153 154 /* 155 * check whether fragment packet's fragment length is 156 * multiple of 8 octets. 157 * sizeof(struct ip6_frag) == 8 158 * sizeof(struct ip6_hdr) = 40 159 */ 160 if ((ip6f->ip6f_offlg & IP6F_MORE_FRAG) && 161 (((ntohs(ip6->ip6_plen) - offset) & 0x7) != 0)) { 162 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, 163 offsetof(struct ip6_hdr, ip6_plen)); 164 in6_ifstat_inc(dstifp, ifs6_reass_fail); 165 return IPPROTO_DONE; 166 } 167 168 IP6_STATINC(IP6_STAT_FRAGMENTS); 169 in6_ifstat_inc(dstifp, ifs6_reass_reqd); 170 171 /* offset now points to data portion */ 172 offset += sizeof(struct ip6_frag); 173 174 /* 175 * RFC6946: A host that receives an IPv6 packet which includes 176 * a Fragment Header with the "Fragmen Offset" equal to 0 and 177 * the "M" bit equal to 0 MUST process such packet in isolation 178 * from any other packets/fragments. 179 */ 180 fragoff = ntohs(ip6f->ip6f_offlg & IP6F_OFF_MASK); 181 if (fragoff == 0 && !(ip6f->ip6f_offlg & IP6F_MORE_FRAG)) { 182 IP6_STATINC(IP6_STAT_REASSEMBLED); 183 in6_ifstat_inc(dstifp, ifs6_reass_ok); 184 *offp = offset; 185 return ip6f->ip6f_nxt; 186 } 187 188 mutex_enter(&frag6_lock); 189 190 /* 191 * Enforce upper bound on number of fragments. 192 * If maxfrag is 0, never accept fragments. 193 * If maxfrag is -1, accept all fragments without limitation. 194 */ 195 if (ip6_maxfrags < 0) 196 ; 197 else if (frag6_nfrags >= (u_int)ip6_maxfrags) 198 goto dropfrag; 199 200 for (q6 = ip6q.ip6q_next; q6 != &ip6q; q6 = q6->ip6q_next) 201 if (ip6f->ip6f_ident == q6->ip6q_ident && 202 IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &q6->ip6q_src) && 203 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &q6->ip6q_dst)) 204 break; 205 206 if (q6 == &ip6q) { 207 /* 208 * the first fragment to arrive, create a reassembly queue. 209 */ 210 first_frag = 1; 211 212 /* 213 * Enforce upper bound on number of fragmented packets 214 * for which we attempt reassembly; 215 * If maxfragpackets is 0, never accept fragments. 216 * If maxfragpackets is -1, accept all fragments without 217 * limitation. 218 */ 219 if (ip6_maxfragpackets < 0) 220 ; 221 else if (frag6_nfragpackets >= (u_int)ip6_maxfragpackets) 222 goto dropfrag; 223 frag6_nfragpackets++; 224 225 q6 = kmem_intr_zalloc(sizeof(struct ip6q), KM_NOSLEEP); 226 if (q6 == NULL) { 227 goto dropfrag; 228 } 229 frag6_insque(q6, &ip6q); 230 231 /* ip6q_nxt will be filled afterwards, from 1st fragment */ 232 q6->ip6q_down = q6->ip6q_up = (struct ip6asfrag *)q6; 233 #ifdef notyet 234 q6->ip6q_nxtp = (u_char *)nxtp; 235 #endif 236 q6->ip6q_ident = ip6f->ip6f_ident; 237 q6->ip6q_arrive = 0; /* Is it used anywhere? */ 238 q6->ip6q_ttl = IPV6_FRAGTTL; 239 q6->ip6q_src = ip6->ip6_src; 240 q6->ip6q_dst = ip6->ip6_dst; 241 q6->ip6q_unfrglen = -1; /* The 1st fragment has not arrived. */ 242 243 q6->ip6q_nfrag = 0; 244 } 245 246 /* 247 * If it's the 1st fragment, record the length of the 248 * unfragmentable part and the next header of the fragment header. 249 */ 250 251 if (fragoff == 0) { 252 q6->ip6q_unfrglen = offset - sizeof(struct ip6_hdr) - 253 sizeof(struct ip6_frag); 254 q6->ip6q_nxt = ip6f->ip6f_nxt; 255 } 256 257 /* 258 * Check that the reassembled packet would not exceed 65535 bytes 259 * in size. 260 * If it would exceed, discard the fragment and return an ICMP error. 261 */ 262 frgpartlen = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen) - offset; 263 if (q6->ip6q_unfrglen >= 0) { 264 /* The 1st fragment has already arrived. */ 265 if (q6->ip6q_unfrglen + fragoff + frgpartlen > IPV6_MAXPACKET) { 266 mutex_exit(&frag6_lock); 267 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, 268 offset - sizeof(struct ip6_frag) + 269 offsetof(struct ip6_frag, ip6f_offlg)); 270 return IPPROTO_DONE; 271 } 272 } else if (fragoff + frgpartlen > IPV6_MAXPACKET) { 273 mutex_exit(&frag6_lock); 274 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, 275 offset - sizeof(struct ip6_frag) + 276 offsetof(struct ip6_frag, ip6f_offlg)); 277 return IPPROTO_DONE; 278 } 279 /* 280 * If it's the first fragment, do the above check for each 281 * fragment already stored in the reassembly queue. 282 */ 283 if (fragoff == 0) { 284 for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6; 285 af6 = af6dwn) { 286 af6dwn = af6->ip6af_down; 287 288 if (q6->ip6q_unfrglen + af6->ip6af_off + af6->ip6af_frglen > 289 IPV6_MAXPACKET) { 290 struct mbuf *merr = IP6_REASS_MBUF(af6); 291 struct ip6_hdr *ip6err; 292 int erroff = af6->ip6af_offset; 293 294 /* dequeue the fragment. */ 295 frag6_deq(af6); 296 kmem_intr_free(af6, sizeof(struct ip6asfrag)); 297 298 /* adjust pointer. */ 299 ip6err = mtod(merr, struct ip6_hdr *); 300 301 /* 302 * Restore source and destination addresses 303 * in the erroneous IPv6 header. 304 */ 305 ip6err->ip6_src = q6->ip6q_src; 306 ip6err->ip6_dst = q6->ip6q_dst; 307 308 icmp6_error(merr, ICMP6_PARAM_PROB, 309 ICMP6_PARAMPROB_HEADER, 310 erroff - sizeof(struct ip6_frag) + 311 offsetof(struct ip6_frag, ip6f_offlg)); 312 } 313 } 314 } 315 316 ip6af = kmem_intr_zalloc(sizeof(struct ip6asfrag), KM_NOSLEEP); 317 if (ip6af == NULL) { 318 goto dropfrag; 319 } 320 ip6af->ip6af_head = ip6->ip6_flow; 321 ip6af->ip6af_len = ip6->ip6_plen; 322 ip6af->ip6af_nxt = ip6->ip6_nxt; 323 ip6af->ip6af_hlim = ip6->ip6_hlim; 324 ip6af->ip6af_mff = ip6f->ip6f_offlg & IP6F_MORE_FRAG; 325 ip6af->ip6af_off = fragoff; 326 ip6af->ip6af_frglen = frgpartlen; 327 ip6af->ip6af_offset = offset; 328 IP6_REASS_MBUF(ip6af) = m; 329 330 if (first_frag) { 331 af6 = (struct ip6asfrag *)q6; 332 goto insert; 333 } 334 335 /* 336 * Find a segment which begins after this one does. 337 */ 338 for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6; 339 af6 = af6->ip6af_down) 340 if (af6->ip6af_off > ip6af->ip6af_off) 341 break; 342 343 /* 344 * If the incoming fragment overlaps some existing fragments in 345 * the reassembly queue - drop it as per RFC 5722. 346 */ 347 if (af6->ip6af_up != (struct ip6asfrag *)q6) { 348 i = af6->ip6af_up->ip6af_off + af6->ip6af_up->ip6af_frglen 349 - ip6af->ip6af_off; 350 if (i > 0) { 351 kmem_intr_free(ip6af, sizeof(struct ip6asfrag)); 352 goto dropfrag; 353 } 354 } 355 if (af6 != (struct ip6asfrag *)q6) { 356 i = (ip6af->ip6af_off + ip6af->ip6af_frglen) - af6->ip6af_off; 357 if (i > 0) { 358 kmem_intr_free(ip6af, sizeof(struct ip6asfrag)); 359 goto dropfrag; 360 } 361 } 362 363 insert: 364 365 /* 366 * Stick new segment in its place; 367 * check for complete reassembly. 368 * Move to front of packet queue, as we are 369 * the most recently active fragmented packet. 370 */ 371 frag6_enq(ip6af, af6->ip6af_up); 372 frag6_nfrags++; 373 q6->ip6q_nfrag++; 374 #if 0 /* xxx */ 375 if (q6 != ip6q.ip6q_next) { 376 frag6_remque(q6); 377 frag6_insque(q6, &ip6q); 378 } 379 #endif 380 next = 0; 381 for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6; 382 af6 = af6->ip6af_down) { 383 if (af6->ip6af_off != next) { 384 mutex_exit(&frag6_lock); 385 return IPPROTO_DONE; 386 } 387 next += af6->ip6af_frglen; 388 } 389 if (af6->ip6af_up->ip6af_mff) { 390 mutex_exit(&frag6_lock); 391 return IPPROTO_DONE; 392 } 393 394 /* 395 * Reassembly is complete; concatenate fragments. 396 */ 397 ip6af = q6->ip6q_down; 398 t = m = IP6_REASS_MBUF(ip6af); 399 af6 = ip6af->ip6af_down; 400 frag6_deq(ip6af); 401 while (af6 != (struct ip6asfrag *)q6) { 402 af6dwn = af6->ip6af_down; 403 frag6_deq(af6); 404 while (t->m_next) 405 t = t->m_next; 406 t->m_next = IP6_REASS_MBUF(af6); 407 m_adj(t->m_next, af6->ip6af_offset); 408 kmem_intr_free(af6, sizeof(struct ip6asfrag)); 409 af6 = af6dwn; 410 } 411 412 /* adjust offset to point where the original next header starts */ 413 offset = ip6af->ip6af_offset - sizeof(struct ip6_frag); 414 kmem_intr_free(ip6af, sizeof(struct ip6asfrag)); 415 ip6 = mtod(m, struct ip6_hdr *); 416 ip6->ip6_plen = htons(next + offset - sizeof(struct ip6_hdr)); 417 ip6->ip6_src = q6->ip6q_src; 418 ip6->ip6_dst = q6->ip6q_dst; 419 nxt = q6->ip6q_nxt; 420 #ifdef notyet 421 *q6->ip6q_nxtp = (u_char)(nxt & 0xff); 422 #endif 423 424 /* 425 * Delete frag6 header with as a few cost as possible. 426 */ 427 if (m->m_len >= offset + sizeof(struct ip6_frag)) { 428 memmove((char *)ip6 + sizeof(struct ip6_frag), ip6, offset); 429 m->m_data += sizeof(struct ip6_frag); 430 m->m_len -= sizeof(struct ip6_frag); 431 } else { 432 /* this comes with no copy if the boundary is on cluster */ 433 if ((t = m_split(m, offset, M_DONTWAIT)) == NULL) { 434 frag6_remque(q6); 435 frag6_nfrags -= q6->ip6q_nfrag; 436 kmem_intr_free(q6, sizeof(struct ip6q)); 437 frag6_nfragpackets--; 438 goto dropfrag; 439 } 440 m_adj(t, sizeof(struct ip6_frag)); 441 m_cat(m, t); 442 } 443 444 /* 445 * Store NXT to the original. 446 */ 447 { 448 u_int8_t *prvnxtp = ip6_get_prevhdr(m, offset); /* XXX */ 449 *prvnxtp = nxt; 450 } 451 452 frag6_remque(q6); 453 frag6_nfrags -= q6->ip6q_nfrag; 454 kmem_intr_free(q6, sizeof(struct ip6q)); 455 frag6_nfragpackets--; 456 457 if (m->m_flags & M_PKTHDR) { /* Isn't it always true? */ 458 int plen = 0; 459 for (t = m; t; t = t->m_next) 460 plen += t->m_len; 461 m->m_pkthdr.len = plen; 462 } 463 464 IP6_STATINC(IP6_STAT_REASSEMBLED); 465 in6_ifstat_inc(dstifp, ifs6_reass_ok); 466 467 /* 468 * Tell launch routine the next header 469 */ 470 471 *mp = m; 472 *offp = offset; 473 474 mutex_exit(&frag6_lock); 475 return nxt; 476 477 dropfrag: 478 mutex_exit(&frag6_lock); 479 in6_ifstat_inc(dstifp, ifs6_reass_fail); 480 IP6_STATINC(IP6_STAT_FRAGDROPPED); 481 m_freem(m); 482 return IPPROTO_DONE; 483 } 484 485 int 486 ip6_reass_packet(struct mbuf **mp, int offset) 487 { 488 489 if (frag6_input(mp, &offset, IPPROTO_IPV6) == IPPROTO_DONE) { 490 *mp = NULL; 491 return EINVAL; 492 } 493 return 0; 494 } 495 496 /* 497 * Free a fragment reassembly header and all 498 * associated datagrams. 499 */ 500 void 501 frag6_freef(struct ip6q *q6) 502 { 503 struct ip6asfrag *af6, *down6; 504 505 KASSERT(mutex_owned(&frag6_lock)); 506 507 for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6; 508 af6 = down6) { 509 struct mbuf *m = IP6_REASS_MBUF(af6); 510 511 down6 = af6->ip6af_down; 512 frag6_deq(af6); 513 514 /* 515 * Return ICMP time exceeded error for the 1st fragment. 516 * Just free other fragments. 517 */ 518 if (af6->ip6af_off == 0) { 519 struct ip6_hdr *ip6; 520 521 /* adjust pointer */ 522 ip6 = mtod(m, struct ip6_hdr *); 523 524 /* restoure source and destination addresses */ 525 ip6->ip6_src = q6->ip6q_src; 526 ip6->ip6_dst = q6->ip6q_dst; 527 528 icmp6_error(m, ICMP6_TIME_EXCEEDED, 529 ICMP6_TIME_EXCEED_REASSEMBLY, 0); 530 } else { 531 m_freem(m); 532 } 533 kmem_intr_free(af6, sizeof(struct ip6asfrag)); 534 } 535 frag6_remque(q6); 536 frag6_nfrags -= q6->ip6q_nfrag; 537 kmem_intr_free(q6, sizeof(struct ip6q)); 538 frag6_nfragpackets--; 539 } 540 541 /* 542 * Put an ip fragment on a reassembly chain. 543 * Like insque, but pointers in middle of structure. 544 */ 545 void 546 frag6_enq(struct ip6asfrag *af6, struct ip6asfrag *up6) 547 { 548 549 KASSERT(mutex_owned(&frag6_lock)); 550 551 af6->ip6af_up = up6; 552 af6->ip6af_down = up6->ip6af_down; 553 up6->ip6af_down->ip6af_up = af6; 554 up6->ip6af_down = af6; 555 } 556 557 /* 558 * To frag6_enq as remque is to insque. 559 */ 560 void 561 frag6_deq(struct ip6asfrag *af6) 562 { 563 564 KASSERT(mutex_owned(&frag6_lock)); 565 566 af6->ip6af_up->ip6af_down = af6->ip6af_down; 567 af6->ip6af_down->ip6af_up = af6->ip6af_up; 568 } 569 570 void 571 frag6_insque(struct ip6q *newq, struct ip6q *oldq) 572 { 573 574 KASSERT(mutex_owned(&frag6_lock)); 575 576 newq->ip6q_prev = oldq; 577 newq->ip6q_next = oldq->ip6q_next; 578 oldq->ip6q_next->ip6q_prev= newq; 579 oldq->ip6q_next = newq; 580 } 581 582 void 583 frag6_remque(struct ip6q *p6) 584 { 585 586 KASSERT(mutex_owned(&frag6_lock)); 587 588 p6->ip6q_prev->ip6q_next = p6->ip6q_next; 589 p6->ip6q_next->ip6q_prev = p6->ip6q_prev; 590 } 591 592 void 593 frag6_fasttimo(void) 594 { 595 mutex_enter(softnet_lock); 596 KERNEL_LOCK(1, NULL); 597 598 if (frag6_drainwanted) { 599 frag6_drain(); 600 frag6_drainwanted = 0; 601 } 602 603 KERNEL_UNLOCK_ONE(NULL); 604 mutex_exit(softnet_lock); 605 } 606 607 /* 608 * IPv6 reassembling timer processing; 609 * if a timer expires on a reassembly 610 * queue, discard it. 611 */ 612 void 613 frag6_slowtimo(void) 614 { 615 struct ip6q *q6; 616 617 mutex_enter(softnet_lock); 618 KERNEL_LOCK(1, NULL); 619 620 mutex_enter(&frag6_lock); 621 q6 = ip6q.ip6q_next; 622 if (q6) 623 while (q6 != &ip6q) { 624 --q6->ip6q_ttl; 625 q6 = q6->ip6q_next; 626 if (q6->ip6q_prev->ip6q_ttl == 0) { 627 IP6_STATINC(IP6_STAT_FRAGTIMEOUT); 628 /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */ 629 frag6_freef(q6->ip6q_prev); 630 } 631 } 632 /* 633 * If we are over the maximum number of fragments 634 * (due to the limit being lowered), drain off 635 * enough to get down to the new limit. 636 */ 637 while (frag6_nfragpackets > (u_int)ip6_maxfragpackets && 638 ip6q.ip6q_prev) { 639 IP6_STATINC(IP6_STAT_FRAGOVERFLOW); 640 /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */ 641 frag6_freef(ip6q.ip6q_prev); 642 } 643 mutex_exit(&frag6_lock); 644 645 KERNEL_UNLOCK_ONE(NULL); 646 mutex_exit(softnet_lock); 647 648 #if 0 649 /* 650 * Routing changes might produce a better route than we last used; 651 * make sure we notice eventually, even if forwarding only for one 652 * destination and the cache is never replaced. 653 */ 654 rtcache_free(&ip6_forward_rt); 655 rtcache_free(&ipsrcchk_rt); 656 #endif 657 658 } 659 660 void 661 frag6_drainstub(void) 662 { 663 frag6_drainwanted = 1; 664 } 665 666 /* 667 * Drain off all datagram fragments. 668 */ 669 void 670 frag6_drain(void) 671 { 672 673 if (mutex_tryenter(&frag6_lock)) { 674 while (ip6q.ip6q_next != &ip6q) { 675 IP6_STATINC(IP6_STAT_FRAGDROPPED); 676 /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */ 677 frag6_freef(ip6q.ip6q_next); 678 } 679 mutex_exit(&frag6_lock); 680 } 681 } 682