BSD 4_4 release
[unix-history] / usr / src / sys / netiso / clnp_frag.c
index b59d9cf..546a592 100644 (file)
@@ -1,3 +1,38 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)clnp_frag.c 8.1 (Berkeley) 6/10/93
+ */
+
 /***********************************************************
                Copyright IBM Corporation 1987
 
 /***********************************************************
                Copyright IBM Corporation 1987
 
@@ -24,43 +59,32 @@ SOFTWARE.
 /*
  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
  */
 /*
  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
  */
-/* $Header: clnp_frag.c,v 4.2 88/06/29 14:58:40 hagens Exp $ */
-/* $Source: /usr/argo/sys/netiso/RCS/clnp_frag.c,v $ */
-
-#ifndef lint
-static char *rcsid = "$Header: clnp_frag.c,v 4.2 88/06/29 14:58:40 hagens Exp $";
-#endif lint
-
-#ifdef ISO
-
-#include "../h/types.h"
-#include "../h/param.h"
-#include "../h/mbuf.h"
-#include "../h/domain.h"
-#include "../h/protosw.h"
-#include "../h/socket.h"
-#include "../h/socketvar.h"
-#include "../h/errno.h"
-
-#include "../net/if.h"
-#include "../net/route.h"
-
-#include "../netiso/iso.h"
-#include "../netiso/iso_var.h"
-#include "../netiso/clnp.h"
-#include "../netiso/clnp_stat.h"
-#include "../netiso/argo_debug.h"
+/* $Header: /var/src/sys/netiso/RCS/clnp_frag.c,v 5.1 89/02/09 16:20:26 hagens Exp $ */
+/* $Source: /var/src/sys/netiso/RCS/clnp_frag.c,v $ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/domain.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/errno.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+#include <netiso/iso.h>
+#include <netiso/iso_var.h>
+#include <netiso/clnp.h>
+#include <netiso/clnp_stat.h>
+#include <netiso/argo_debug.h>
 
 /* all fragments are hung off this list */
 struct clnp_fragl      *clnp_frags = NULL;
 
 struct mbuf    *clnp_comp_pdu();
 
 
 /* all fragments are hung off this list */
 struct clnp_fragl      *clnp_frags = NULL;
 
 struct mbuf    *clnp_comp_pdu();
 
-#ifdef TROLL
-float troll_random();
-static int troll_cnt = 0;
-#endif TROLL
-
 
 /*
  * FUNCTION:           clnp_fragment
 
 /*
  * FUNCTION:           clnp_fragment
@@ -81,61 +105,80 @@ static int troll_cnt = 0;
  *                                     the packet was fragmented during forwarding. In this
  *                                     case, we ought to send an ER back.
  */
  *                                     the packet was fragmented during forwarding. In this
  *                                     case, we ought to send an ER back.
  */
-clnp_fragment(ifp, m, first_hop, total_len, segoff, flags)
+clnp_fragment(ifp, m, first_hop, total_len, segoff, flags, rt)
 struct ifnet   *ifp;           /* ptr to outgoing interface */
 struct mbuf            *m;                     /* ptr to packet */
 struct sockaddr        *first_hop;     /* ptr to first hop */
 int                            total_len;      /* length of datagram */
 int                            segoff;         /* offset of segpart in hdr */
 int                            flags;          /* flags passed to clnp_output */
 struct ifnet   *ifp;           /* ptr to outgoing interface */
 struct mbuf            *m;                     /* ptr to packet */
 struct sockaddr        *first_hop;     /* ptr to first hop */
 int                            total_len;      /* length of datagram */
 int                            segoff;         /* offset of segpart in hdr */
 int                            flags;          /* flags passed to clnp_output */
+struct rtentry *rt;                    /* route if direct ether */
 {
 {
-       struct clnp_fixed       *clnp;          /* ptr to fixed part of header */
+       struct clnp_fixed               *clnp = mtod(m, struct clnp_fixed *);
+       int                                             hdr_len = (int)clnp->cnf_hdr_len;
+       int                                             frag_size = (SN_MTU(ifp, rt) - hdr_len) & ~7;
 
 
-       clnp = mtod(m, struct clnp_fixed *);
+       total_len -= hdr_len;
+       if ((clnp->cnf_type & CNF_SEG_OK) &&
+               (total_len >= 8) &&
+               (frag_size > 8 || (frag_size == 8 && !(total_len & 7)))) {
 
 
-       if (clnp->cnf_seg_ok) {
                struct mbuf                     *hdr = NULL;            /* save copy of clnp hdr */
                struct mbuf                     *frag_hdr = NULL;
                struct mbuf                     *frag_data = NULL;
                struct mbuf                     *hdr = NULL;            /* save copy of clnp hdr */
                struct mbuf                     *frag_hdr = NULL;
                struct mbuf                     *frag_data = NULL;
-               struct clnp_segment     seg_part, tmp_seg;      /* segmentation header */
-               extern int                      clnp_id;                        /* id of datagram */
+               struct clnp_segment     seg_part;                       /* segmentation header */
+               int                                     frag_base;
                int                                     error = 0;
 
                int                                     error = 0;
 
-               INCSTAT(cns_frag);
-
-               seg_part.cng_id = clnp_id++;
-               seg_part.cng_off = 0;
-               seg_part.cng_tot_len = total_len;
 
 
+               INCSTAT(cns_fragmented);
+        (void) bcopy(segoff + mtod(m, caddr_t), (caddr_t)&seg_part,
+            sizeof(seg_part));
+               frag_base = ntohs(seg_part.cng_off);
                /*
                 *      Duplicate header, and remove from packet
                 */
                /*
                 *      Duplicate header, and remove from packet
                 */
-               if ((hdr = m_copy(m, 0, clnp->cnf_hdr_len)) == NULL) {
+               if ((hdr = m_copy(m, 0, hdr_len)) == NULL) {
                        clnp_discard(m, GEN_CONGEST);
                        return(ENOBUFS);
                }
                        clnp_discard(m, GEN_CONGEST);
                        return(ENOBUFS);
                }
-               m_adj(m, clnp->cnf_hdr_len);
-               total_len -= clnp->cnf_hdr_len;
-               
+               m_adj(m, hdr_len);
+
                while (total_len > 0) {
                while (total_len > 0) {
-                       int             frag_size;
-                       int             last_frag = 0;          /* true if this is the last fragment */
-                       
-                       frag_size = min(total_len, ifp->if_mtu - clnp->cnf_hdr_len);
+                       int             remaining, last_frag;
 
 
-                       /*
-                        *      For some stupid reason, fragments must be at least 8 bytes
-                        *      in length. If this fragment will cause the last one to 
-                        *      be less than 8 bytes, shorten this fragment a bit.
-                        */
-                       if (((total_len - frag_size) > 0) && ((total_len - frag_size) < 8))
-                               frag_size -= (8 - (total_len - frag_size));
+                       IFDEBUG(D_FRAG)
+                               struct mbuf *mdump = frag_hdr;
+                               int tot_mlen = 0;
+                               printf("clnp_fragment: total_len %d:\n", total_len);
+                               while (mdump != NULL) {
+                                       printf("\tmbuf x%x, m_len %d\n", 
+                                               mdump, mdump->m_len);
+                                       tot_mlen += mdump->m_len;
+                                       mdump = mdump->m_next;
+                               }
+                               printf("clnp_fragment: sum of mbuf chain %d:\n", tot_mlen);
+                       ENDDEBUG
+                       
+                       frag_size = min(total_len, frag_size);
+                       if ((remaining = total_len - frag_size) == 0)
+                               last_frag = 1;
+                       else {
+                               /*
+                                *  If this fragment will cause the last one to 
+                                *      be less than 8 bytes, shorten this fragment a bit.
+                                *  The obscure test on frag_size above ensures that
+                                *  frag_size will be positive.
+                                */
+                               last_frag = 0;
+                               if (remaining < 8)
+                                               frag_size -= 8;
+                       }
                        
                        
-                       last_frag = ((total_len - frag_size) == 0);
 
                        IFDEBUG(D_FRAG)
                                printf("clnp_fragment: seg off %d, size %d, remaining %d\n", 
 
                        IFDEBUG(D_FRAG)
                                printf("clnp_fragment: seg off %d, size %d, remaining %d\n", 
-                                       seg_part.cng_off, frag_size, total_len-frag_size);
+                                       ntohs(seg_part.cng_off), frag_size, total_len-frag_size);
                                if (last_frag)
                                        printf("clnp_fragment: last fragment\n");
                        ENDDEBUG
                                if (last_frag)
                                        printf("clnp_fragment: last fragment\n");
                        ENDDEBUG
@@ -149,62 +192,59 @@ int                               flags;          /* flags passed to clnp_output */
                                frag_data = m;
                        } else {
                                /* duplicate header and data mbufs */
                                frag_data = m;
                        } else {
                                /* duplicate header and data mbufs */
-                               if ((frag_hdr = m_copy(hdr, 0, M_COPYALL)) == NULL) {
-                                       clnp_discard(m, GEN_CONGEST);
-                                       m_freem(hdr);
+                               if ((frag_hdr = m_copy(hdr, 0, (int)M_COPYALL)) == NULL) {
+                                       clnp_discard(hdr, GEN_CONGEST);
+                                       m_freem(m);
                                        return(ENOBUFS);
                                }
                                if ((frag_data = m_copy(m, 0, frag_size)) == NULL) {
                                        return(ENOBUFS);
                                }
                                if ((frag_data = m_copy(m, 0, frag_size)) == NULL) {
-                                       clnp_discard(m, GEN_CONGEST);
-                                       m_freem(hdr);
+                                       clnp_discard(hdr, GEN_CONGEST);
+                                       m_freem(m);
                                        m_freem(frag_hdr);
                                        return(ENOBUFS);
                                }
                                        m_freem(frag_hdr);
                                        return(ENOBUFS);
                                }
+                               INCSTAT(cns_fragments);
                        }
                        clnp = mtod(frag_hdr, struct clnp_fixed *);
 
                        if (!last_frag)
                        }
                        clnp = mtod(frag_hdr, struct clnp_fixed *);
 
                        if (!last_frag)
-                               clnp->cnf_more_segs = 1;
+                               clnp->cnf_type |= CNF_MORE_SEGS;
                        
                        /* link together */
                        m_cat(frag_hdr, frag_data);
 
                        
                        /* link together */
                        m_cat(frag_hdr, frag_data);
 
-                       /* make sure segmentation fields are in network order */
-                       tmp_seg.cng_id = htons(seg_part.cng_id);
-                       tmp_seg.cng_off = htons(seg_part.cng_off);
-                       tmp_seg.cng_tot_len = htons(seg_part.cng_tot_len);
-
-                       /* insert segmentation part */
-                       bcopy((caddr_t)&tmp_seg, mtod(frag_hdr, caddr_t) + segoff,
+                       /* insert segmentation part; updated below */
+                       bcopy((caddr_t)&seg_part, mtod(frag_hdr, caddr_t) + segoff,
                                sizeof(struct clnp_segment));
 
                        {
                                sizeof(struct clnp_segment));
 
                        {
-                               int     derived_len = clnp->cnf_hdr_len + frag_size;
+                               int     derived_len = hdr_len + frag_size;
                                HTOC(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, derived_len);
                                HTOC(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, derived_len);
+                               if ((frag_hdr->m_flags & M_PKTHDR) == 0)
+                                       panic("clnp_frag:lost header");
+                               frag_hdr->m_pkthdr.len = derived_len;
                        }
                        /* compute clnp checksum (on header only) */
                        if (flags & CLNP_NO_CKSUM) {
                                HTOC(clnp->cnf_cksum_msb, clnp->cnf_cksum_lsb, 0);
                        } else {
                        }
                        /* compute clnp checksum (on header only) */
                        if (flags & CLNP_NO_CKSUM) {
                                HTOC(clnp->cnf_cksum_msb, clnp->cnf_cksum_lsb, 0);
                        } else {
-                               iso_gen_csum(frag_hdr, CLNP_CKSUM_OFF, (int)clnp->cnf_hdr_len);
+                               iso_gen_csum(frag_hdr, CLNP_CKSUM_OFF, hdr_len);
                        }
 
                        IFDEBUG(D_DUMPOUT)
                                struct mbuf *mdump = frag_hdr;
                                printf("clnp_fragment: sending dg:\n");
                        }
 
                        IFDEBUG(D_DUMPOUT)
                                struct mbuf *mdump = frag_hdr;
                                printf("clnp_fragment: sending dg:\n");
-/*                             dump_buf(mtod(mdump, caddr_t), mdump->m_len);*/
                                while (mdump != NULL) {
                                while (mdump != NULL) {
-                                       printf("mbuf x%x, m_len %d\n", mdump, mdump->m_len);
-/*                                     dump_buf(mtod(mdump, caddr_t), mdump->m_len);*/
+                                       printf("\tmbuf x%x, m_len %d\n", mdump, mdump->m_len);
                                        mdump = mdump->m_next;
                                }
                        ENDDEBUG
 
 #ifdef TROLL
                                        mdump = mdump->m_next;
                                }
                        ENDDEBUG
 
 #ifdef TROLL
-                       error = troll_output(ifp, frag_hdr, first_hop);
+                       error = troll_output(ifp, frag_hdr, first_hop, rt);
 #else
 #else
-                       error = (*ifp->if_output)(ifp, frag_hdr, first_hop);
-#endif TROLL
+                       error = (*ifp->if_output)(ifp, frag_hdr, first_hop, rt);
+#endif /* TROLL */
 
                        /*
                         *      Tough situation: if the error occured on the last 
 
                        /*
                         *      Tough situation: if the error occured on the last 
@@ -219,8 +259,8 @@ int                         flags;          /* flags passed to clnp_output */
                                         *      The error was not on the last fragment. We must
                                         *      free hdr and m before returning
                                         */
                                         *      The error was not on the last fragment. We must
                                         *      free hdr and m before returning
                                         */
-                                       clnp_discard(m, GEN_NOREAS);
-                                       m_freem(hdr);
+                                       clnp_discard(hdr, GEN_NOREAS);
+                                       m_freem(m);
                                }
                                return(error);
                        }
                                }
                                return(error);
                        }
@@ -243,15 +283,18 @@ int                               flags;          /* flags passed to clnp_output */
                                        num_bytes *= troll_random();
                                frag_size -= num_bytes;
                        }
                                        num_bytes *= troll_random();
                                frag_size -= num_bytes;
                        }
-#endif TROLL
+#endif /* TROLL */
                        total_len -= frag_size;
                        if (!last_frag) {
                        total_len -= frag_size;
                        if (!last_frag) {
-                               seg_part.cng_off += frag_size;
+                               frag_base += frag_size;
+                               seg_part.cng_off = htons(frag_base);
                                m_adj(m, frag_size);
                        }
                }
                return(0);
        } else {
                                m_adj(m, frag_size);
                        }
                }
                return(0);
        } else {
+       cantfrag:
+               INCSTAT(cns_cantfrag);
                clnp_discard(m, GEN_SEGNEEDED);
                return(EMSGSIZE);
        }
                clnp_discard(m, GEN_SEGNEEDED);
                return(EMSGSIZE);
        }
@@ -289,8 +332,9 @@ struct clnp_segment *seg;   /* segment part of fragment header */
 
        /* look for other fragments of this datagram */
        for (cfh = clnp_frags; cfh != NULL; cfh = cfh->cfl_next) {
 
        /* look for other fragments of this datagram */
        for (cfh = clnp_frags; cfh != NULL; cfh = cfh->cfl_next) {
-               if (iso_addrmatch1(src, &cfh->cfl_src) && 
-                       iso_addrmatch1(dst, &cfh->cfl_dst) && seg->cng_id == cfh->cfl_id) {
+               if (seg->cng_id == cfh->cfl_id &&
+                   iso_addrmatch1(src, &cfh->cfl_src) && 
+                       iso_addrmatch1(dst, &cfh->cfl_dst)) {
                        IFDEBUG(D_REASS)
                                printf("clnp_reass: found packet\n");
                        ENDDEBUG
                        IFDEBUG(D_REASS)
                                printf("clnp_reass: found packet\n");
                        ENDDEBUG
@@ -299,7 +343,12 @@ struct clnp_segment        *seg;   /* segment part of fragment header */
                         *      this fragment is of any help
                         */
                        clnp_insert_frag(cfh, m, seg);
                         *      this fragment is of any help
                         */
                        clnp_insert_frag(cfh, m, seg);
-                       return (clnp_comp_pdu(cfh));
+                       if (m = clnp_comp_pdu(cfh)) {
+                               register struct clnp_fixed *clnp = mtod(m, struct clnp_fixed *);
+                               HTOC(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb,
+                                        seg->cng_tot_len);
+                       }
+                       return (m);
                }
        }
 
                }
        }
 
@@ -314,6 +363,7 @@ struct clnp_segment *seg;   /* segment part of fragment header */
         */
        /* TODO: don't let one src hog all the reassembly buffers */
        if (!clnp_newpkt(m, src, dst, seg) /* || this src is a hog */) {
         */
        /* TODO: don't let one src hog all the reassembly buffers */
        if (!clnp_newpkt(m, src, dst, seg) /* || this src is a hog */) {
+               INCSTAT(cns_fragdropped);
                clnp_discard(m, GEN_CONGEST);
        }
 
                clnp_discard(m, GEN_CONGEST);
        }
 
@@ -358,7 +408,7 @@ struct clnp_segment *seg;   /* segment part of fragment header */
         *      Duplicate the header of this fragment, and save in cfh.
         *      Free m0 and return if m_copy does not succeed.
         */
         *      Duplicate the header of this fragment, and save in cfh.
         *      Free m0 and return if m_copy does not succeed.
         */
-       if ((cfh->cfl_orighdr = m_copy(m, 0, clnp->cnf_hdr_len)) == NULL) {
+       if ((cfh->cfl_orighdr = m_copy(m, 0, (int)clnp->cnf_hdr_len)) == NULL) {
                m_freem(m0);
                return (0);
        }
                m_freem(m0);
                return (0);
        }
@@ -474,7 +524,7 @@ struct clnp_segment *seg;   /* segment part of fragment header */
                                        /* Trim data off of end of previous fragment */
                                        /* inc overlap to prevent duplication of last byte */
                                        overlap++;
                                        /* Trim data off of end of previous fragment */
                                        /* inc overlap to prevent duplication of last byte */
                                        overlap++;
-                                       m_adj(cf_prev->cfr_data, -overlap);
+                                       m_adj(cf_prev->cfr_data, -(int)overlap);
                                        cf_prev->cfr_last -= overlap;
                                }
                        }
                                        cf_prev->cfr_last -= overlap;
                                }
                        }
@@ -508,7 +558,7 @@ struct clnp_segment *seg;   /* segment part of fragment header */
                                        /* Trim data off of end of new fragment */
                                        /* inc overlap to prevent duplication of last byte */
                                        overlap++;
                                        /* Trim data off of end of new fragment */
                                        /* inc overlap to prevent duplication of last byte */
                                        overlap++;
-                                       m_adj(m, -overlap);
+                                       m_adj(m, -(int)overlap);
                                        last -= overlap;
                                }
                        }
                                        last -= overlap;
                                }
                        }
@@ -541,12 +591,22 @@ struct clnp_segment       *seg;   /* segment part of fragment header */
                /* bytes is number of bytes left in front of data */
                bytes = clnp->cnf_hdr_len - pad;
 
                /* bytes is number of bytes left in front of data */
                bytes = clnp->cnf_hdr_len - pad;
 
+               IFDEBUG(D_REASS)
+                       printf("clnp_insert_frag: clnp x%x requires %d alignment\n",
+                               clnp, pad);
+               ENDDEBUG
+
                /* make it word aligned if necessary */
                if (pad)
                        m_adj(m, pad);
 
                cf = mtod(m, struct clnp_frag *);
                cf->cfr_bytes = bytes;
                /* make it word aligned if necessary */
                if (pad)
                        m_adj(m, pad);
 
                cf = mtod(m, struct clnp_frag *);
                cf->cfr_bytes = bytes;
+
+               IFDEBUG(D_REASS)
+                       printf("clnp_insert_frag: cf now x%x, cfr_bytes %d\n", cf,
+                               cf->cfr_bytes);
+               ENDDEBUG
        }
        cf->cfr_first = first;
        cf->cfr_last = last;
        }
        cf->cfr_first = first;
        cf->cfr_last = last;
@@ -614,21 +674,28 @@ struct clnp_fragl *cfh;           /* fragment header */
 
                        IFDEBUG(D_REASS)
                                struct mbuf *mdump;
 
                        IFDEBUG(D_REASS)
                                struct mbuf *mdump;
+                               int l;
                                printf("clnp_comp_pdu: merging fragments\n");
                                printf("clnp_comp_pdu: merging fragments\n");
-                               printf("clnp_comp_pdu: 1st: [%d ... %d]\n", cf->cfr_first
-                                       cf->cfr_last);
+                               printf("clnp_comp_pdu: 1st: [%d ... %d] (bytes %d)\n"
+                                       cf->cfr_first, cf->cfr_last, cf->cfr_bytes);
                                mdump = cf->cfr_data;
                                mdump = cf->cfr_data;
+                               l = 0;
                                while (mdump != NULL) {
                                        printf("\tmbuf x%x, m_len %d\n", mdump, mdump->m_len);
                                while (mdump != NULL) {
                                        printf("\tmbuf x%x, m_len %d\n", mdump, mdump->m_len);
+                                       l += mdump->m_len;
                                        mdump = mdump->m_next;
                                }
                                        mdump = mdump->m_next;
                                }
-                               printf("clnp_comp_pdu: 2nd: [%d ... %d]\n", cf_next->cfr_first, 
-                                       cf_next->cfr_last);
+                               printf("\ttotal len: %d\n", l);
+                               printf("clnp_comp_pdu: 2nd: [%d ... %d] (bytes %d)\n", 
+                                       cf_next->cfr_first, cf_next->cfr_last, cf_next->cfr_bytes);
                                mdump = cf_next->cfr_data;
                                mdump = cf_next->cfr_data;
+                               l = 0;
                                while (mdump != NULL) {
                                        printf("\tmbuf x%x, m_len %d\n", mdump, mdump->m_len);
                                while (mdump != NULL) {
                                        printf("\tmbuf x%x, m_len %d\n", mdump, mdump->m_len);
+                                       l += mdump->m_len;
                                        mdump = mdump->m_next;
                                }
                                        mdump = mdump->m_next;
                                }
+                               printf("\ttotal len: %d\n", l);
                        ENDDEBUG
 
                        cf->cfr_last = cf_next->cfr_last;
                        ENDDEBUG
 
                        cf->cfr_last = cf_next->cfr_last;
@@ -636,7 +703,11 @@ struct clnp_fragl  *cfh;           /* fragment header */
                         *      After this m_adj, the cf_next ptr is useless because we
                         *      have adjusted the clnp_frag structure away...
                         */
                         *      After this m_adj, the cf_next ptr is useless because we
                         *      have adjusted the clnp_frag structure away...
                         */
-                       m_adj(cf_next_hdr.cfr_data, cf_next_hdr.cfr_bytes);
+                       IFDEBUG(D_REASS)
+                               printf("clnp_comp_pdu: shaving off %d bytes\n", 
+                                       cf_next_hdr.cfr_bytes);
+                       ENDDEBUG
+                       m_adj(cf_next_hdr.cfr_data, (int)cf_next_hdr.cfr_bytes);
                        m_cat(cf->cfr_data, cf_next_hdr.cfr_data);
                        cf->cfr_next = next_frag;
                } else {
                        m_cat(cf->cfr_data, cf_next_hdr.cfr_data);
                        cf->cfr_next = next_frag;
                } else {
@@ -675,7 +746,7 @@ struct clnp_fragl   *cfh;           /* fragment header */
                        printf("clnp_comp_pdu: complete pdu!\n");
                ENDDEBUG
 
                        printf("clnp_comp_pdu: complete pdu!\n");
                ENDDEBUG
 
-               m_adj(data, cf->cfr_bytes);
+               m_adj(data, (int)cf->cfr_bytes);
                m_cat(hdr, data);
 
                IFDEBUG(D_DUMPIN)
                m_cat(hdr, data);
 
                IFDEBUG(D_DUMPIN)
@@ -711,7 +782,8 @@ struct clnp_fragl   *cfh;           /* fragment header */
        return(NULL);
 }
 #ifdef TROLL
        return(NULL);
 }
 #ifdef TROLL
-#include "../h/time.h"
+static int troll_cnt;
+#include <sys/time.h>
 /*
  * FUNCTION:           troll_random
  *
 /*
  * FUNCTION:           troll_random
  *
@@ -748,10 +820,11 @@ float troll_random()
  * NOTES:                      The operation of this procedure is regulated by the
  *                                     troll control structure (Troll).
  */
  * NOTES:                      The operation of this procedure is regulated by the
  *                                     troll control structure (Troll).
  */
-troll_output(ifp, m, dst)
+troll_output(ifp, m, dst, rt)
 struct ifnet   *ifp;
 struct mbuf            *m;
 struct sockaddr        *dst;
 struct ifnet   *ifp;
 struct mbuf            *m;
 struct sockaddr        *dst;
+struct rtentry *rt;
 {
        int     err = 0;
        troll_cnt++;
 {
        int     err = 0;
        troll_cnt++;
@@ -764,24 +837,23 @@ struct sockaddr   *dst;
                float   f_freq = troll_cnt * trollctl.tr_dup_freq;
                int             i_freq = troll_cnt * trollctl.tr_dup_freq;
                if (i_freq == f_freq) {
                float   f_freq = troll_cnt * trollctl.tr_dup_freq;
                int             i_freq = troll_cnt * trollctl.tr_dup_freq;
                if (i_freq == f_freq) {
-                       struct mbuf *dup = m_copy(m, 0, M_COPYALL);
+                       struct mbuf *dup = m_copy(m, 0, (int)M_COPYALL);
                        if (dup != NULL)
                        if (dup != NULL)
-                               err = (*ifp->if_output)(ifp, dup, dst);
+                               err = (*ifp->if_output)(ifp, dup, dst, rt);
                }
                if (!err)
                }
                if (!err)
-                       err = (*ifp->if_output)(ifp, m, dst);
+                       err = (*ifp->if_output)(ifp, m, dst, rt);
                return(err);
        } else if (trollctl.tr_ops & TR_DROPPKT) {
        } else if (trollctl.tr_ops & TR_CHANGE) {
                struct clnp_fixed *clnp = mtod(m, struct clnp_fixed *);
                clnp->cnf_cksum_msb = 0;
                return(err);
        } else if (trollctl.tr_ops & TR_DROPPKT) {
        } else if (trollctl.tr_ops & TR_CHANGE) {
                struct clnp_fixed *clnp = mtod(m, struct clnp_fixed *);
                clnp->cnf_cksum_msb = 0;
-               err = (*ifp->if_output)(ifp, m, dst);
+               err = (*ifp->if_output)(ifp, m, dst, rt);
                return(err);
        } else {
                return(err);
        } else {
-               err = (*ifp->if_output)(ifp, m, dst);
+               err = (*ifp->if_output)(ifp, m, dst, rt);
                return(err);
        }
 }
 
                return(err);
        }
 }
 
-#endif TROLL
-#endif ISO
+#endif /* TROLL */