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