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