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

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

unix.superglobalmegacorp.com

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