Annotation of kernel/bsd/netiso/clnp_frag.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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