Annotation of 43BSDReno/sys/netiso/clnp_frag.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.