home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / netiso / clnp_frag.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-06  |  24.0 KB  |  859 lines

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