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