Annotation of Net2/netiso/clnp_frag.c, revision 1.1.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.