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