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