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