|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /*- ! 23: * Copyright (c) 1991, 1993 ! 24: * The Regents of the University of California. All rights reserved. ! 25: * ! 26: * Redistribution and use in source and binary forms, with or without ! 27: * modification, are permitted provided that the following conditions ! 28: * are met: ! 29: * 1. Redistributions of source code must retain the above copyright ! 30: * notice, this list of conditions and the following disclaimer. ! 31: * 2. Redistributions in binary form must reproduce the above copyright ! 32: * notice, this list of conditions and the following disclaimer in the ! 33: * documentation and/or other materials provided with the distribution. ! 34: * 3. All advertising materials mentioning features or use of this software ! 35: * must display the following acknowledgement: ! 36: * This product includes software developed by the University of ! 37: * California, Berkeley and its contributors. ! 38: * 4. Neither the name of the University nor the names of its contributors ! 39: * may be used to endorse or promote products derived from this software ! 40: * without specific prior written permission. ! 41: * ! 42: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 43: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 44: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 45: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 46: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 47: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 48: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 49: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 50: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 51: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 52: * SUCH DAMAGE. ! 53: * ! 54: * @(#)clnp_frag.c 8.1 (Berkeley) 6/10/93 ! 55: */ ! 56: ! 57: /*********************************************************** ! 58: Copyright IBM Corporation 1987 ! 59: ! 60: All Rights Reserved ! 61: ! 62: Permission to use, copy, modify, and distribute this software and its ! 63: documentation for any purpose and without fee is hereby granted, ! 64: provided that the above copyright notice appear in all copies and that ! 65: both that copyright notice and this permission notice appear in ! 66: supporting documentation, and that the name of IBM not be ! 67: used in advertising or publicity pertaining to distribution of the ! 68: software without specific, written prior permission. ! 69: ! 70: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ! 71: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ! 72: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ! 73: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ! 74: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ! 75: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ! 76: SOFTWARE. ! 77: ! 78: ******************************************************************/ ! 79: ! 80: /* ! 81: * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison ! 82: */ ! 83: ! 84: #include <sys/param.h> ! 85: #include <sys/systm.h> ! 86: #include <sys/mbuf.h> ! 87: #include <sys/domain.h> ! 88: #include <sys/protosw.h> ! 89: #include <sys/socket.h> ! 90: #include <sys/socketvar.h> ! 91: #include <sys/errno.h> ! 92: ! 93: #include <net/if.h> ! 94: #include <net/route.h> ! 95: ! 96: #include <netiso/iso.h> ! 97: #include <netiso/iso_var.h> ! 98: #include <netiso/clnp.h> ! 99: #include <netiso/clnp_stat.h> ! 100: #include <netiso/argo_debug.h> ! 101: ! 102: /* all fragments are hung off this list */ ! 103: struct clnp_fragl *clnp_frags = NULL; ! 104: ! 105: struct mbuf *clnp_comp_pdu(); ! 106: ! 107: ! 108: /* ! 109: * FUNCTION: clnp_fragment ! 110: * ! 111: * PURPOSE: Fragment a datagram, and send the itty bitty pieces ! 112: * out over an interface. ! 113: * ! 114: * RETURNS: success - 0 ! 115: * failure - unix error code ! 116: * ! 117: * SIDE EFFECTS: ! 118: * ! 119: * NOTES: If there is an error sending the packet, clnp_discard ! 120: * is called to discard the packet and send an ER. If ! 121: * clnp_fragment was called from clnp_output, then ! 122: * we generated the packet, and should not send an ! 123: * ER -- clnp_emit_er will check for this. Otherwise, ! 124: * the packet was fragmented during forwarding. In this ! 125: * case, we ought to send an ER back. ! 126: */ ! 127: clnp_fragment(ifp, m, first_hop, total_len, segoff, flags, rt) ! 128: struct ifnet *ifp; /* ptr to outgoing interface */ ! 129: struct mbuf *m; /* ptr to packet */ ! 130: struct sockaddr *first_hop; /* ptr to first hop */ ! 131: int total_len; /* length of datagram */ ! 132: int segoff; /* offset of segpart in hdr */ ! 133: int flags; /* flags passed to clnp_output */ ! 134: struct rtentry *rt; /* route if direct ether */ ! 135: { ! 136: struct clnp_fixed *clnp = mtod(m, struct clnp_fixed *); ! 137: int hdr_len = (int)clnp->cnf_hdr_len; ! 138: int frag_size = (SN_MTU(ifp, rt) - hdr_len) & ~7; ! 139: ! 140: total_len -= hdr_len; ! 141: if ((clnp->cnf_type & CNF_SEG_OK) && ! 142: (total_len >= 8) && ! 143: (frag_size > 8 || (frag_size == 8 && !(total_len & 7)))) { ! 144: ! 145: struct mbuf *hdr = NULL; /* save copy of clnp hdr */ ! 146: struct mbuf *frag_hdr = NULL; ! 147: struct mbuf *frag_data = NULL; ! 148: struct clnp_segment seg_part; /* segmentation header */ ! 149: int frag_base; ! 150: int error = 0; ! 151: ! 152: ! 153: INCSTAT(cns_fragmented); ! 154: (void) bcopy(segoff + mtod(m, caddr_t), (caddr_t)&seg_part, ! 155: sizeof(seg_part)); ! 156: frag_base = ntohs(seg_part.cng_off); ! 157: /* ! 158: * Duplicate header, and remove from packet ! 159: */ ! 160: if ((hdr = m_copy(m, 0, hdr_len)) == NULL) { ! 161: clnp_discard(m, GEN_CONGEST); ! 162: return(ENOBUFS); ! 163: } ! 164: m_adj(m, hdr_len); ! 165: ! 166: while (total_len > 0) { ! 167: int remaining, last_frag; ! 168: ! 169: IFDEBUG(D_FRAG) ! 170: struct mbuf *mdump = frag_hdr; ! 171: int tot_mlen = 0; ! 172: printf("clnp_fragment: total_len %d:\n", total_len); ! 173: while (mdump != NULL) { ! 174: printf("\tmbuf x%x, m_len %d\n", ! 175: mdump, mdump->m_len); ! 176: tot_mlen += mdump->m_len; ! 177: mdump = mdump->m_next; ! 178: } ! 179: printf("clnp_fragment: sum of mbuf chain %d:\n", tot_mlen); ! 180: ENDDEBUG ! 181: ! 182: frag_size = min(total_len, frag_size); ! 183: if ((remaining = total_len - frag_size) == 0) ! 184: last_frag = 1; ! 185: else { ! 186: /* ! 187: * If this fragment will cause the last one to ! 188: * be less than 8 bytes, shorten this fragment a bit. ! 189: * The obscure test on frag_size above ensures that ! 190: * frag_size will be positive. ! 191: */ ! 192: last_frag = 0; ! 193: if (remaining < 8) ! 194: frag_size -= 8; ! 195: } ! 196: ! 197: ! 198: IFDEBUG(D_FRAG) ! 199: printf("clnp_fragment: seg off %d, size %d, remaining %d\n", ! 200: ntohs(seg_part.cng_off), frag_size, total_len-frag_size); ! 201: if (last_frag) ! 202: printf("clnp_fragment: last fragment\n"); ! 203: ENDDEBUG ! 204: ! 205: if (last_frag) { ! 206: /* ! 207: * this is the last fragment; we don't need to get any other ! 208: * mbufs. ! 209: */ ! 210: frag_hdr = hdr; ! 211: frag_data = m; ! 212: } else { ! 213: /* duplicate header and data mbufs */ ! 214: if ((frag_hdr = m_copy(hdr, 0, (int)M_COPYALL)) == NULL) { ! 215: clnp_discard(hdr, GEN_CONGEST); ! 216: m_freem(m); ! 217: return(ENOBUFS); ! 218: } ! 219: if ((frag_data = m_copy(m, 0, frag_size)) == NULL) { ! 220: clnp_discard(hdr, GEN_CONGEST); ! 221: m_freem(m); ! 222: m_freem(frag_hdr); ! 223: return(ENOBUFS); ! 224: } ! 225: INCSTAT(cns_fragments); ! 226: } ! 227: clnp = mtod(frag_hdr, struct clnp_fixed *); ! 228: ! 229: if (!last_frag) ! 230: clnp->cnf_type |= CNF_MORE_SEGS; ! 231: ! 232: /* link together */ ! 233: m_cat(frag_hdr, frag_data); ! 234: ! 235: /* insert segmentation part; updated below */ ! 236: bcopy((caddr_t)&seg_part, mtod(frag_hdr, caddr_t) + segoff, ! 237: sizeof(struct clnp_segment)); ! 238: ! 239: { ! 240: int derived_len = hdr_len + frag_size; ! 241: HTOC(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, derived_len); ! 242: if ((frag_hdr->m_flags & M_PKTHDR) == 0) ! 243: panic("clnp_frag:lost header"); ! 244: frag_hdr->m_pkthdr.len = derived_len; ! 245: } ! 246: /* compute clnp checksum (on header only) */ ! 247: if (flags & CLNP_NO_CKSUM) { ! 248: HTOC(clnp->cnf_cksum_msb, clnp->cnf_cksum_lsb, 0); ! 249: } else { ! 250: iso_gen_csum(frag_hdr, CLNP_CKSUM_OFF, hdr_len); ! 251: } ! 252: ! 253: IFDEBUG(D_DUMPOUT) ! 254: struct mbuf *mdump = frag_hdr; ! 255: printf("clnp_fragment: sending dg:\n"); ! 256: while (mdump != NULL) { ! 257: printf("\tmbuf x%x, m_len %d\n", mdump, mdump->m_len); ! 258: mdump = mdump->m_next; ! 259: } ! 260: ENDDEBUG ! 261: ! 262: #ifdef TROLL ! 263: error = troll_output(ifp, frag_hdr, first_hop, rt); ! 264: #else ! 265: error = (*ifp->if_output)(ifp, frag_hdr, first_hop, rt); ! 266: #endif /* TROLL */ ! 267: ! 268: /* ! 269: * Tough situation: if the error occured on the last ! 270: * fragment, we can not send an ER, as the if_output ! 271: * routine consumed the packet. If the error occured ! 272: * on any intermediate packets, we can send an ER ! 273: * because we still have the original header in (m). ! 274: */ ! 275: if (error) { ! 276: if (frag_hdr != hdr) { ! 277: /* ! 278: * The error was not on the last fragment. We must ! 279: * free hdr and m before returning ! 280: */ ! 281: clnp_discard(hdr, GEN_NOREAS); ! 282: m_freem(m); ! 283: } ! 284: return(error); ! 285: } ! 286: ! 287: /* bump segment offset, trim data mbuf, and decrement count left */ ! 288: #ifdef TROLL ! 289: /* ! 290: * Decrement frag_size by some fraction. This will cause the ! 291: * next fragment to start 'early', thus duplicating the end ! 292: * of the current fragment. troll.tr_dup_size controls ! 293: * the fraction. If positive, it specifies the fraction. If ! 294: * negative, a random fraction is used. ! 295: */ ! 296: if ((trollctl.tr_ops & TR_DUPEND) && (!last_frag)) { ! 297: int num_bytes = frag_size; ! 298: ! 299: if (trollctl.tr_dup_size > 0) ! 300: num_bytes *= trollctl.tr_dup_size; ! 301: else ! 302: num_bytes *= troll_random(); ! 303: frag_size -= num_bytes; ! 304: } ! 305: #endif /* TROLL */ ! 306: total_len -= frag_size; ! 307: if (!last_frag) { ! 308: frag_base += frag_size; ! 309: seg_part.cng_off = htons(frag_base); ! 310: m_adj(m, frag_size); ! 311: } ! 312: } ! 313: return(0); ! 314: } else { ! 315: cantfrag: ! 316: INCSTAT(cns_cantfrag); ! 317: clnp_discard(m, GEN_SEGNEEDED); ! 318: return(EMSGSIZE); ! 319: } ! 320: } ! 321: ! 322: /* ! 323: * FUNCTION: clnp_reass ! 324: * ! 325: * PURPOSE: Attempt to reassemble a clnp packet given the current ! 326: * fragment. If reassembly succeeds (all the fragments ! 327: * are present), then return a pointer to an mbuf chain ! 328: * containing the reassembled packet. This packet will ! 329: * appear in the mbufs as if it had just arrived in ! 330: * one piece. ! 331: * ! 332: * If reassembly fails, then save this fragment and ! 333: * return 0. ! 334: * ! 335: * RETURNS: Ptr to assembled packet, or 0 ! 336: * ! 337: * SIDE EFFECTS: ! 338: * ! 339: * NOTES: ! 340: * clnp_slowtimo can not affect this code because clnpintr, and thus ! 341: * this code, is called at a higher priority than clnp_slowtimo. ! 342: */ ! 343: struct mbuf * ! 344: clnp_reass(m, src, dst, seg) ! 345: struct mbuf *m; /* new fragment */ ! 346: struct iso_addr *src; /* src of new fragment */ ! 347: struct iso_addr *dst; /* dst of new fragment */ ! 348: struct clnp_segment *seg; /* segment part of fragment header */ ! 349: { ! 350: register struct clnp_fragl *cfh; ! 351: ! 352: /* look for other fragments of this datagram */ ! 353: for (cfh = clnp_frags; cfh != NULL; cfh = cfh->cfl_next) { ! 354: if (seg->cng_id == cfh->cfl_id && ! 355: iso_addrmatch1(src, &cfh->cfl_src) && ! 356: iso_addrmatch1(dst, &cfh->cfl_dst)) { ! 357: IFDEBUG(D_REASS) ! 358: printf("clnp_reass: found packet\n"); ! 359: ENDDEBUG ! 360: /* ! 361: * There are other fragments here already. Lets see if ! 362: * this fragment is of any help ! 363: */ ! 364: clnp_insert_frag(cfh, m, seg); ! 365: if (m = clnp_comp_pdu(cfh)) { ! 366: register struct clnp_fixed *clnp = mtod(m, struct clnp_fixed *); ! 367: HTOC(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, ! 368: seg->cng_tot_len); ! 369: } ! 370: return (m); ! 371: } ! 372: } ! 373: ! 374: IFDEBUG(D_REASS) ! 375: printf("clnp_reass: new packet!\n"); ! 376: ENDDEBUG ! 377: ! 378: /* ! 379: * This is the first fragment. If src is not consuming too many ! 380: * resources, then create a new fragment list and add ! 381: * this fragment to the list. ! 382: */ ! 383: /* TODO: don't let one src hog all the reassembly buffers */ ! 384: if (!clnp_newpkt(m, src, dst, seg) /* || this src is a hog */) { ! 385: INCSTAT(cns_fragdropped); ! 386: clnp_discard(m, GEN_CONGEST); ! 387: } ! 388: ! 389: return(NULL); ! 390: } ! 391: ! 392: /* ! 393: * FUNCTION: clnp_newpkt ! 394: * ! 395: * PURPOSE: Create the necessary structures to handle a new ! 396: * fragmented clnp packet. ! 397: * ! 398: * RETURNS: non-zero if it succeeds, zero if fails. ! 399: * ! 400: * SIDE EFFECTS: ! 401: * ! 402: * NOTES: Failure is only due to insufficient resources. ! 403: */ ! 404: clnp_newpkt(m, src, dst, seg) ! 405: struct mbuf *m; /* new fragment */ ! 406: struct iso_addr *src; /* src of new fragment */ ! 407: struct iso_addr *dst; /* dst of new fragment */ ! 408: struct clnp_segment *seg; /* segment part of fragment header */ ! 409: { ! 410: register struct clnp_fragl *cfh; ! 411: register struct clnp_fixed *clnp; ! 412: struct mbuf *m0; ! 413: ! 414: clnp = mtod(m, struct clnp_fixed *); ! 415: ! 416: /* ! 417: * Allocate new clnp fragl structure to act as header of all fragments ! 418: * for this datagram. ! 419: */ ! 420: MGET(m0, M_DONTWAIT, MT_FTABLE); ! 421: if (m0 == NULL) { ! 422: return (0); ! 423: } ! 424: cfh = mtod(m0, struct clnp_fragl *); ! 425: ! 426: /* ! 427: * Duplicate the header of this fragment, and save in cfh. ! 428: * Free m0 and return if m_copy does not succeed. ! 429: */ ! 430: if ((cfh->cfl_orighdr = m_copy(m, 0, (int)clnp->cnf_hdr_len)) == NULL) { ! 431: m_freem(m0); ! 432: return (0); ! 433: } ! 434: ! 435: /* Fill in rest of fragl structure */ ! 436: bcopy((caddr_t)src, (caddr_t)&cfh->cfl_src, sizeof(struct iso_addr)); ! 437: bcopy((caddr_t)dst, (caddr_t)&cfh->cfl_dst, sizeof(struct iso_addr)); ! 438: cfh->cfl_id = seg->cng_id; ! 439: cfh->cfl_ttl = clnp->cnf_ttl; ! 440: cfh->cfl_last = (seg->cng_tot_len - clnp->cnf_hdr_len) - 1; ! 441: cfh->cfl_frags = NULL; ! 442: cfh->cfl_next = NULL; ! 443: ! 444: /* Insert into list of packets */ ! 445: cfh->cfl_next = clnp_frags; ! 446: clnp_frags = cfh; ! 447: ! 448: /* Insert this fragment into list headed by cfh */ ! 449: clnp_insert_frag(cfh, m, seg); ! 450: return(1); ! 451: } ! 452: ! 453: /* ! 454: * FUNCTION: clnp_insert_frag ! 455: * ! 456: * PURPOSE: Insert fragment into list headed by 'cf'. ! 457: * ! 458: * RETURNS: nothing ! 459: * ! 460: * SIDE EFFECTS: ! 461: * ! 462: * NOTES: This is the 'guts' of the reassembly algorithm. ! 463: * Each fragment in this list contains a clnp_frag ! 464: * structure followed by the data of the fragment. ! 465: * The clnp_frag structure actually lies on top of ! 466: * part of the old clnp header. ! 467: */ ! 468: clnp_insert_frag(cfh, m, seg) ! 469: struct clnp_fragl *cfh; /* header of list of packet fragments */ ! 470: struct mbuf *m; /* new fragment */ ! 471: struct clnp_segment *seg; /* segment part of fragment header */ ! 472: { ! 473: register struct clnp_fixed *clnp; /* clnp hdr of fragment */ ! 474: register struct clnp_frag *cf; /* generic fragment ptr */ ! 475: register struct clnp_frag *cf_sub = NULL; /* frag subsequent to new one */ ! 476: register struct clnp_frag *cf_prev = NULL; /* frag previous to new one */ ! 477: u_short first; /* offset of first byte of initial pdu*/ ! 478: u_short last; /* offset of last byte of initial pdu */ ! 479: u_short fraglen;/* length of fragment */ ! 480: ! 481: clnp = mtod(m, struct clnp_fixed *); ! 482: first = seg->cng_off; ! 483: CTOH(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, fraglen); ! 484: fraglen -= clnp->cnf_hdr_len; ! 485: last = (first + fraglen) - 1; ! 486: ! 487: IFDEBUG(D_REASS) ! 488: printf("clnp_insert_frag: New fragment: [%d ... %d], len %d\n", ! 489: first, last, fraglen); ! 490: printf("clnp_insert_frag: current fragments:\n"); ! 491: for (cf = cfh->cfl_frags; cf != NULL; cf = cf->cfr_next) { ! 492: printf("\tcf x%x: [%d ... %d]\n", cf, cf->cfr_first, cf->cfr_last); ! 493: } ! 494: ENDDEBUG ! 495: ! 496: if (cfh->cfl_frags != NULL) { ! 497: /* ! 498: * Find fragment which begins after the new one ! 499: */ ! 500: for (cf = cfh->cfl_frags; cf != NULL; cf_prev = cf, cf = cf->cfr_next) { ! 501: if (cf->cfr_first > first) { ! 502: cf_sub = cf; ! 503: break; ! 504: } ! 505: } ! 506: ! 507: IFDEBUG(D_REASS) ! 508: printf("clnp_insert_frag: Previous frag is "); ! 509: if (cf_prev == NULL) ! 510: printf("NULL\n"); ! 511: else ! 512: printf("[%d ... %d]\n", cf_prev->cfr_first, cf_prev->cfr_last); ! 513: printf("clnp_insert_frag: Subsequent frag is "); ! 514: if (cf_sub == NULL) ! 515: printf("NULL\n"); ! 516: else ! 517: printf("[%d ... %d]\n", cf_sub->cfr_first, cf_sub->cfr_last); ! 518: ENDDEBUG ! 519: ! 520: /* ! 521: * If there is a fragment before the new one, check if it ! 522: * overlaps the new one. If so, then trim the end of the ! 523: * previous one. ! 524: */ ! 525: if (cf_prev != NULL) { ! 526: if (cf_prev->cfr_last > first) { ! 527: u_short overlap = cf_prev->cfr_last - first; ! 528: ! 529: IFDEBUG(D_REASS) ! 530: printf("clnp_insert_frag: previous overlaps by %d\n", ! 531: overlap); ! 532: ENDDEBUG ! 533: ! 534: if (overlap > fraglen) { ! 535: /* ! 536: * The new fragment is entirely contained in the ! 537: * preceeding one. We can punt on the new frag ! 538: * completely. ! 539: */ ! 540: m_freem(m); ! 541: return; ! 542: } else { ! 543: /* Trim data off of end of previous fragment */ ! 544: /* inc overlap to prevent duplication of last byte */ ! 545: overlap++; ! 546: m_adj(cf_prev->cfr_data, -(int)overlap); ! 547: cf_prev->cfr_last -= overlap; ! 548: } ! 549: } ! 550: } ! 551: ! 552: /* ! 553: * For all fragments past the new one, check if any data on ! 554: * the new one overlaps data on existing fragments. If so, ! 555: * then trim the extra data off the end of the new one. ! 556: */ ! 557: for (cf = cf_sub; cf != NULL; cf = cf->cfr_next) { ! 558: if (cf->cfr_first < last) { ! 559: u_short overlap = last - cf->cfr_first; ! 560: ! 561: IFDEBUG(D_REASS) ! 562: printf("clnp_insert_frag: subsequent overlaps by %d\n", ! 563: overlap); ! 564: ENDDEBUG ! 565: ! 566: if (overlap > fraglen) { ! 567: /* ! 568: * The new fragment is entirely contained in the ! 569: * succeeding one. This should not happen, because ! 570: * early on in this code we scanned for the fragment ! 571: * which started after the new one! ! 572: */ ! 573: m_freem(m); ! 574: printf("clnp_insert_frag: internal error!\n"); ! 575: return; ! 576: } else { ! 577: /* Trim data off of end of new fragment */ ! 578: /* inc overlap to prevent duplication of last byte */ ! 579: overlap++; ! 580: m_adj(m, -(int)overlap); ! 581: last -= overlap; ! 582: } ! 583: } ! 584: } ! 585: } ! 586: ! 587: /* ! 588: * Insert the new fragment beween cf_prev and cf_sub ! 589: * ! 590: * Note: the clnp hdr is still in the mbuf. ! 591: * If the data of the mbuf is not word aligned, shave off enough ! 592: * so that it is. Then, cast the clnp_frag structure on top ! 593: * of the clnp header. ! 594: * The clnp_hdr will not be used again (as we already have ! 595: * saved a copy of it). ! 596: * ! 597: * Save in cfr_bytes the number of bytes to shave off to get to ! 598: * the data of the packet. This is used when we coalesce fragments; ! 599: * the clnp_frag structure must be removed before joining mbufs. ! 600: */ ! 601: { ! 602: int pad; ! 603: u_int bytes; ! 604: ! 605: /* determine if header is not word aligned */ ! 606: pad = (int)clnp % 4; ! 607: if (pad < 0) ! 608: pad = -pad; ! 609: ! 610: /* bytes is number of bytes left in front of data */ ! 611: bytes = clnp->cnf_hdr_len - pad; ! 612: ! 613: IFDEBUG(D_REASS) ! 614: printf("clnp_insert_frag: clnp x%x requires %d alignment\n", ! 615: clnp, pad); ! 616: ENDDEBUG ! 617: ! 618: /* make it word aligned if necessary */ ! 619: if (pad) ! 620: m_adj(m, pad); ! 621: ! 622: cf = mtod(m, struct clnp_frag *); ! 623: cf->cfr_bytes = bytes; ! 624: ! 625: IFDEBUG(D_REASS) ! 626: printf("clnp_insert_frag: cf now x%x, cfr_bytes %d\n", cf, ! 627: cf->cfr_bytes); ! 628: ENDDEBUG ! 629: } ! 630: cf->cfr_first = first; ! 631: cf->cfr_last = last; ! 632: ! 633: ! 634: /* ! 635: * The data is the mbuf itself, although we must remember that the ! 636: * first few bytes are actually a clnp_frag structure ! 637: */ ! 638: cf->cfr_data = m; ! 639: ! 640: /* link into place */ ! 641: cf->cfr_next = cf_sub; ! 642: if (cf_prev == NULL) ! 643: cfh->cfl_frags = cf; ! 644: else ! 645: cf_prev->cfr_next = cf; ! 646: } ! 647: ! 648: /* ! 649: * FUNCTION: clnp_comp_pdu ! 650: * ! 651: * PURPOSE: Scan the list of fragments headed by cfh. Merge ! 652: * any contigious fragments into one. If, after ! 653: * traversing all the fragments, it is determined that ! 654: * the packet is complete, then return a pointer to ! 655: * the packet (with header prepended). Otherwise, ! 656: * return NULL. ! 657: * ! 658: * RETURNS: NULL, or a pointer to the assembled pdu in an mbuf chain. ! 659: * ! 660: * SIDE EFFECTS: Will colapse contigious fragments into one. ! 661: * ! 662: * NOTES: This code assumes that there are no overlaps of ! 663: * fragment pdus. ! 664: */ ! 665: struct mbuf * ! 666: clnp_comp_pdu(cfh) ! 667: struct clnp_fragl *cfh; /* fragment header */ ! 668: { ! 669: register struct clnp_frag *cf = cfh->cfl_frags; ! 670: ! 671: while (cf->cfr_next != NULL) { ! 672: register struct clnp_frag *cf_next = cf->cfr_next; ! 673: ! 674: IFDEBUG(D_REASS) ! 675: printf("clnp_comp_pdu: comparing: [%d ... %d] to [%d ... %d]\n", ! 676: cf->cfr_first, cf->cfr_last, cf_next->cfr_first, ! 677: cf_next->cfr_last); ! 678: ENDDEBUG ! 679: ! 680: if (cf->cfr_last == (cf_next->cfr_first - 1)) { ! 681: /* ! 682: * Merge fragment cf and cf_next ! 683: * ! 684: * - update cf header ! 685: * - trim clnp_frag structure off of cf_next ! 686: * - append cf_next to cf ! 687: */ ! 688: struct clnp_frag cf_next_hdr; ! 689: struct clnp_frag *next_frag; ! 690: ! 691: cf_next_hdr = *cf_next; ! 692: next_frag = cf_next->cfr_next; ! 693: ! 694: IFDEBUG(D_REASS) ! 695: struct mbuf *mdump; ! 696: int l; ! 697: printf("clnp_comp_pdu: merging fragments\n"); ! 698: printf("clnp_comp_pdu: 1st: [%d ... %d] (bytes %d)\n", ! 699: cf->cfr_first, cf->cfr_last, cf->cfr_bytes); ! 700: mdump = cf->cfr_data; ! 701: l = 0; ! 702: while (mdump != NULL) { ! 703: printf("\tmbuf x%x, m_len %d\n", mdump, mdump->m_len); ! 704: l += mdump->m_len; ! 705: mdump = mdump->m_next; ! 706: } ! 707: printf("\ttotal len: %d\n", l); ! 708: printf("clnp_comp_pdu: 2nd: [%d ... %d] (bytes %d)\n", ! 709: cf_next->cfr_first, cf_next->cfr_last, cf_next->cfr_bytes); ! 710: mdump = cf_next->cfr_data; ! 711: l = 0; ! 712: while (mdump != NULL) { ! 713: printf("\tmbuf x%x, m_len %d\n", mdump, mdump->m_len); ! 714: l += mdump->m_len; ! 715: mdump = mdump->m_next; ! 716: } ! 717: printf("\ttotal len: %d\n", l); ! 718: ENDDEBUG ! 719: ! 720: cf->cfr_last = cf_next->cfr_last; ! 721: /* ! 722: * After this m_adj, the cf_next ptr is useless because we ! 723: * have adjusted the clnp_frag structure away... ! 724: */ ! 725: IFDEBUG(D_REASS) ! 726: printf("clnp_comp_pdu: shaving off %d bytes\n", ! 727: cf_next_hdr.cfr_bytes); ! 728: ENDDEBUG ! 729: m_adj(cf_next_hdr.cfr_data, (int)cf_next_hdr.cfr_bytes); ! 730: m_cat(cf->cfr_data, cf_next_hdr.cfr_data); ! 731: cf->cfr_next = next_frag; ! 732: } else { ! 733: cf = cf->cfr_next; ! 734: } ! 735: } ! 736: ! 737: cf = cfh->cfl_frags; ! 738: ! 739: IFDEBUG(D_REASS) ! 740: struct mbuf *mdump = cf->cfr_data; ! 741: printf("clnp_comp_pdu: first frag now: [%d ... %d]\n", cf->cfr_first, ! 742: cf->cfr_last); ! 743: printf("clnp_comp_pdu: data for frag:\n"); ! 744: while (mdump != NULL) { ! 745: printf("mbuf x%x, m_len %d\n", mdump, mdump->m_len); ! 746: /* dump_buf(mtod(mdump, caddr_t), mdump->m_len);*/ ! 747: mdump = mdump->m_next; ! 748: } ! 749: ENDDEBUG ! 750: ! 751: /* Check if datagram is complete */ ! 752: if ((cf->cfr_first == 0) && (cf->cfr_last == cfh->cfl_last)) { ! 753: /* ! 754: * We have a complete pdu! ! 755: * - Remove the frag header from (only) remaining fragment ! 756: * (which is not really a fragment anymore, as the datagram is ! 757: * complete). ! 758: * - Prepend a clnp header ! 759: */ ! 760: struct mbuf *data = cf->cfr_data; ! 761: struct mbuf *hdr = cfh->cfl_orighdr; ! 762: struct clnp_fragl *scan; ! 763: ! 764: IFDEBUG(D_REASS) ! 765: printf("clnp_comp_pdu: complete pdu!\n"); ! 766: ENDDEBUG ! 767: ! 768: m_adj(data, (int)cf->cfr_bytes); ! 769: m_cat(hdr, data); ! 770: ! 771: IFDEBUG(D_DUMPIN) ! 772: struct mbuf *mdump = hdr; ! 773: printf("clnp_comp_pdu: pdu is:\n"); ! 774: while (mdump != NULL) { ! 775: printf("mbuf x%x, m_len %d\n", mdump, mdump->m_len); ! 776: /* dump_buf(mtod(mdump, caddr_t), mdump->m_len);*/ ! 777: mdump = mdump->m_next; ! 778: } ! 779: ENDDEBUG ! 780: ! 781: /* ! 782: * Remove cfh from the list of fragmented pdus ! 783: */ ! 784: if (clnp_frags == cfh) { ! 785: clnp_frags = cfh->cfl_next; ! 786: } else { ! 787: for (scan = clnp_frags; scan != NULL; scan = scan->cfl_next) { ! 788: if (scan->cfl_next == cfh) { ! 789: scan->cfl_next = cfh->cfl_next; ! 790: break; ! 791: } ! 792: } ! 793: } ! 794: ! 795: /* free cfh */ ! 796: m_freem(dtom(cfh)); ! 797: ! 798: return(hdr); ! 799: } ! 800: ! 801: return(NULL); ! 802: } ! 803: #ifdef TROLL ! 804: static int troll_cnt; ! 805: #include <sys/time.h> ! 806: /* ! 807: * FUNCTION: troll_random ! 808: * ! 809: * PURPOSE: generate a pseudo-random number between 0 and 1 ! 810: * ! 811: * RETURNS: the random number ! 812: * ! 813: * SIDE EFFECTS: ! 814: * ! 815: * NOTES: This is based on the clock. ! 816: */ ! 817: float troll_random() ! 818: { ! 819: extern struct timeval time; ! 820: long t = time.tv_usec % 100; ! 821: ! 822: return((float)t / (float) 100); ! 823: } ! 824: ! 825: /* ! 826: * FUNCTION: troll_output ! 827: * ! 828: * PURPOSE: Do something sneaky with the datagram passed. Possible ! 829: * operations are: ! 830: * Duplicate the packet ! 831: * Drop the packet ! 832: * Trim some number of bytes from the packet ! 833: * Munge some byte in the packet ! 834: * ! 835: * RETURNS: 0, or unix error code ! 836: * ! 837: * SIDE EFFECTS: ! 838: * ! 839: * NOTES: The operation of this procedure is regulated by the ! 840: * troll control structure (Troll). ! 841: */ ! 842: troll_output(ifp, m, dst, rt) ! 843: struct ifnet *ifp; ! 844: struct mbuf *m; ! 845: struct sockaddr *dst; ! 846: struct rtentry *rt; ! 847: { ! 848: int err = 0; ! 849: troll_cnt++; ! 850: ! 851: if (trollctl.tr_ops & TR_DUPPKT) { ! 852: /* ! 853: * Duplicate every Nth packet ! 854: * TODO: random? ! 855: */ ! 856: float f_freq = troll_cnt * trollctl.tr_dup_freq; ! 857: int i_freq = troll_cnt * trollctl.tr_dup_freq; ! 858: if (i_freq == f_freq) { ! 859: struct mbuf *dup = m_copy(m, 0, (int)M_COPYALL); ! 860: if (dup != NULL) ! 861: err = (*ifp->if_output)(ifp, dup, dst, rt); ! 862: } ! 863: if (!err) ! 864: err = (*ifp->if_output)(ifp, m, dst, rt); ! 865: return(err); ! 866: } else if (trollctl.tr_ops & TR_DROPPKT) { ! 867: } else if (trollctl.tr_ops & TR_CHANGE) { ! 868: struct clnp_fixed *clnp = mtod(m, struct clnp_fixed *); ! 869: clnp->cnf_cksum_msb = 0; ! 870: err = (*ifp->if_output)(ifp, m, dst, rt); ! 871: return(err); ! 872: } else { ! 873: err = (*ifp->if_output)(ifp, m, dst, rt); ! 874: return(err); ! 875: } ! 876: } ! 877: ! 878: #endif /* TROLL */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.