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