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