Annotation of Net2/netiso/clnp_frag.c, revision 1.1

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

unix.superglobalmegacorp.com

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