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