Annotation of 43BSDReno/sys/netiso/clnp_frag.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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