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

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

unix.superglobalmegacorp.com

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