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