1 /* $NetBSD: clnp_frag.c,v 1.24 2009/03/18 17:06:52 cegger Exp $ */
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * @(#)clnp_frag.c 8.1 (Berkeley) 6/10/93
34 /***********************************************************
35 Copyright IBM Corporation 1987
39 Permission to use, copy, modify, and distribute this software and its
40 documentation for any purpose and without fee is hereby granted,
41 provided that the above copyright notice appear in all copies and that
42 both that copyright notice and this permission notice appear in
43 supporting documentation, and that the name of IBM not be
44 used in advertising or publicity pertaining to distribution of the
45 software without specific, written prior permission.
47 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
48 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
49 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
50 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
51 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
52 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
55 ******************************************************************/
58 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
61 #include <sys/cdefs.h>
62 __KERNEL_RCSID(0, "$NetBSD: clnp_frag.c,v 1.24 2009/03/18 17:06:52 cegger Exp $");
64 #include <sys/param.h>
65 #include <sys/systm.h>
67 #include <sys/domain.h>
68 #include <sys/protosw.h>
69 #include <sys/socket.h>
70 #include <sys/socketvar.h>
71 #include <sys/errno.h>
74 #include <net/route.h>
76 #include <netiso/iso.h>
77 #include <netiso/iso_var.h>
78 #include <netiso/clnp.h>
79 #include <netiso/clnp_stat.h>
80 #include <netiso/argo_debug.h>
82 /* all fragments are hung off this list */
83 struct clnp_fragl
*clnp_frags
= NULL
;
86 * FUNCTION: clnp_fragment
88 * PURPOSE: Fragment a datagram, and send the itty bitty pieces
89 * out over an interface.
91 * RETURNS: success - 0
92 * failure - unix error code
96 * NOTES: If there is an error sending the packet, clnp_discard
97 * is called to discard the packet and send an ER. If
98 * clnp_fragment was called from clnp_output, then
99 * we generated the packet, and should not send an
100 * ER -- clnp_emit_er will check for this. Otherwise,
101 * the packet was fragmented during forwarding. In this
102 * case, we ought to send an ER back.
106 struct ifnet
*ifp
, /* ptr to outgoing interface */
107 struct mbuf
*m
, /* ptr to packet */
108 const struct sockaddr
*first_hop
, /* ptr to first hop */
109 int total_len
, /* length of datagram */
110 int segoff
, /* offset of segpart in hdr */
111 int flags
, /* flags passed to clnp_output */
112 struct rtentry
*rt
) /* route if direct ether */
114 struct clnp_fixed
*clnp
= mtod(m
, struct clnp_fixed
*);
115 int hdr_len
= (int) clnp
->cnf_hdr_len
;
116 int frag_size
= (SN_MTU(ifp
, rt
) - hdr_len
) & ~7;
118 total_len
-= hdr_len
;
119 if ((clnp
->cnf_type
& CNF_SEG_OK
) &&
121 (frag_size
> 8 || (frag_size
== 8 && !(total_len
& 7)))) {
122 struct mbuf
*hdr
= NULL
; /* save copy of clnp hdr */
123 struct mbuf
*frag_hdr
= NULL
;
124 struct mbuf
*frag_data
= NULL
;
125 struct clnp_segment seg_part
; /* segmentation header */
130 INCSTAT(cns_fragmented
);
131 (void)memmove(&seg_part
, segoff
+ mtod(m
, char *),
133 frag_base
= ntohs(seg_part
.cng_off
);
135 * Duplicate header, and remove from packet
137 if ((hdr
= m_copy(m
, 0, hdr_len
)) == NULL
) {
138 clnp_discard(m
, GEN_CONGEST
);
143 while (total_len
> 0) {
144 int remaining
, last_frag
;
147 if (argo_debug
[D_FRAG
]) {
148 struct mbuf
*mdump
= frag_hdr
;
150 printf("clnp_fragment: total_len %d:\n",
152 while (mdump
!= NULL
) {
153 printf("\tmbuf %p, m_len %d\n",
154 mdump
, mdump
->m_len
);
155 tot_mlen
+= mdump
->m_len
;
156 mdump
= mdump
->m_next
;
158 printf("clnp_fragment: sum of mbuf chain %d:\n",
163 frag_size
= min(total_len
, frag_size
);
164 if ((remaining
= total_len
- frag_size
) == 0)
168 * If this fragment will cause the last one to
169 * be less than 8 bytes, shorten this fragment
170 * a bit. The obscure test on frag_size above
171 * ensures that frag_size will be positive.
180 if (argo_debug
[D_FRAG
]) {
182 "clnp_fragment: seg off %d, size %d, rem %d\n",
183 ntohs(seg_part
.cng_off
), frag_size
,
184 total_len
- frag_size
);
187 "clnp_fragment: last fragment\n");
193 * this is the last fragment; we don't need
194 * to get any other mbufs.
199 /* duplicate header and data mbufs */
200 frag_hdr
= m_copy(hdr
, 0, (int) M_COPYALL
);
201 if (frag_hdr
== NULL
) {
202 clnp_discard(hdr
, GEN_CONGEST
);
206 frag_data
= m_copy(m
, 0, frag_size
);
207 if (frag_data
== NULL
) {
208 clnp_discard(hdr
, GEN_CONGEST
);
213 INCSTAT(cns_fragments
);
215 clnp
= mtod(frag_hdr
, struct clnp_fixed
*);
218 clnp
->cnf_type
|= CNF_MORE_SEGS
;
221 m_cat(frag_hdr
, frag_data
);
223 /* insert segmentation part; updated below */
224 (void)memmove(mtod(frag_hdr
, char *) + segoff
,
226 sizeof(struct clnp_segment
));
229 int derived_len
= hdr_len
+ frag_size
;
230 HTOC(clnp
->cnf_seglen_msb
,
231 clnp
->cnf_seglen_lsb
, derived_len
);
232 if ((frag_hdr
->m_flags
& M_PKTHDR
) == 0)
233 panic("clnp_frag:lost header");
234 frag_hdr
->m_pkthdr
.len
= derived_len
;
237 /* compute clnp checksum (on header only) */
238 if (flags
& CLNP_NO_CKSUM
) {
239 HTOC(clnp
->cnf_cksum_msb
,
240 clnp
->cnf_cksum_lsb
, 0);
242 iso_gen_csum(frag_hdr
, CLNP_CKSUM_OFF
, hdr_len
);
246 if (argo_debug
[D_DUMPOUT
]) {
247 struct mbuf
*mdump
= frag_hdr
;
248 printf("clnp_fragment: sending dg:\n");
249 while (mdump
!= NULL
) {
250 printf("\tmbuf %p, m_len %d\n",
251 mdump
, mdump
->m_len
);
252 mdump
= mdump
->m_next
;
258 error
= troll_output(ifp
, frag_hdr
, first_hop
, rt
);
260 error
= (*ifp
->if_output
) (ifp
, frag_hdr
, first_hop
, rt
);
264 * Tough situation: if the error occurred on the last
265 * fragment, we can not send an ER, as the if_output
266 * routine consumed the packet. If the error occurred
267 * on any intermediate packets, we can send an ER
268 * because we still have the original header in (m).
271 if (frag_hdr
!= hdr
) {
273 * The error was not on the last
274 * fragment. We must free hdr and m
277 clnp_discard(hdr
, GEN_NOREAS
);
283 * bump segment offset, trim data mbuf, and decrement
288 * Decrement frag_size by some fraction. This will
289 * cause the next fragment to start 'early', thus
290 * duplicating the end of the current fragment.
291 * troll.tr_dup_size controls the fraction. If
292 * positive, it specifies the fraction. If
293 * negative, a random fraction is used.
295 if ((trollctl
.tr_ops
& TR_DUPEND
) && (!last_frag
)) {
296 int num_bytes
= frag_size
;
298 if (trollctl
.tr_dup_size
> 0)
299 num_bytes
*= trollctl
.tr_dup_size
;
301 num_bytes
*= troll_random();
302 frag_size
-= num_bytes
;
305 total_len
-= frag_size
;
307 frag_base
+= frag_size
;
308 seg_part
.cng_off
= htons(frag_base
);
314 INCSTAT(cns_cantfrag
);
315 clnp_discard(m
, GEN_SEGNEEDED
);
321 * FUNCTION: clnp_reass
323 * PURPOSE: Attempt to reassemble a clnp packet given the current
324 * fragment. If reassembly succeeds (all the fragments
325 * are present), then return a pointer to an mbuf chain
326 * containing the reassembled packet. This packet will
327 * appear in the mbufs as if it had just arrived in
330 * If reassembly fails, then save this fragment and
333 * RETURNS: Ptr to assembled packet, or 0
337 * NOTES: clnp_slowtimo can not affect this code because
338 * clnpintr, and thus this code, is called at a higher
339 * priority than clnp_slowtimo.
343 struct mbuf
*m
, /* new fragment */
344 struct iso_addr
*src
, /* src of new fragment */
345 struct iso_addr
*dst
, /* dst of new fragment */
346 struct clnp_segment
*seg
) /* segment part of fragment header */
348 struct clnp_fragl
*cfh
;
350 /* look for other fragments of this datagram */
351 for (cfh
= clnp_frags
; cfh
!= NULL
; cfh
= cfh
->cfl_next
) {
352 if (seg
->cng_id
== cfh
->cfl_id
&&
353 iso_addrmatch1(src
, &cfh
->cfl_src
) &&
354 iso_addrmatch1(dst
, &cfh
->cfl_dst
)) {
356 if (argo_debug
[D_REASS
]) {
357 printf("clnp_reass: found packet\n");
361 * There are other fragments here already. Lets see if
362 * this fragment is of any help
364 clnp_insert_frag(cfh
, m
, seg
);
365 if ((m
= clnp_comp_pdu(cfh
)) != NULL
) {
366 struct clnp_fixed
*clnp
=
367 mtod(m
, struct clnp_fixed
*);
368 HTOC(clnp
->cnf_seglen_msb
,
369 clnp
->cnf_seglen_lsb
,
377 if (argo_debug
[D_REASS
]) {
378 printf("clnp_reass: new packet!\n");
383 * This is the first fragment. If src is not consuming too many
384 * resources, then create a new fragment list and add
385 * this fragment to the list.
387 /* TODO: don't let one src hog all the reassembly buffers */
388 if (!clnp_newpkt(m
, src
, dst
, seg
) /* || this src is a hog */ ) {
389 INCSTAT(cns_fragdropped
);
390 clnp_discard(m
, GEN_CONGEST
);
396 * FUNCTION: clnp_newpkt
398 * PURPOSE: Create the necessary structures to handle a new
399 * fragmented clnp packet.
401 * RETURNS: non-zero if it succeeds, zero if fails.
405 * NOTES: Failure is only due to insufficient resources.
409 struct mbuf
*m
, /* new fragment */
410 struct iso_addr
*src
, /* src of new fragment */
411 struct iso_addr
*dst
, /* dst of new fragment */
412 struct clnp_segment
*seg
) /* segment part of fragment header */
414 struct clnp_fragl
*cfh
;
415 struct clnp_fixed
*clnp
;
417 clnp
= mtod(m
, struct clnp_fixed
*);
420 * Allocate new clnp fragl structure to act as header of all
421 * fragments for this datagram.
423 cfh
= malloc(sizeof (struct clnp_fragl
), M_FTABLE
, M_NOWAIT
);
429 * Duplicate the header of this fragment, and save in cfh. Free m0
430 * and return if m_copy does not succeed.
432 cfh
->cfl_orighdr
= m_copy(m
, 0, (int) clnp
->cnf_hdr_len
);
433 if (cfh
->cfl_orighdr
== NULL
) {
437 /* Fill in rest of fragl structure */
438 memcpy((void *) & cfh
->cfl_src
, (void *) src
, sizeof(struct iso_addr
));
439 memcpy((void *) & cfh
->cfl_dst
, (void *) dst
, sizeof(struct iso_addr
));
440 cfh
->cfl_id
= seg
->cng_id
;
441 cfh
->cfl_ttl
= clnp
->cnf_ttl
;
442 cfh
->cfl_last
= (seg
->cng_tot_len
- clnp
->cnf_hdr_len
) - 1;
443 cfh
->cfl_frags
= NULL
;
444 cfh
->cfl_next
= NULL
;
446 /* Insert into list of packets */
447 cfh
->cfl_next
= clnp_frags
;
450 /* Insert this fragment into list headed by cfh */
451 clnp_insert_frag(cfh
, m
, seg
);
456 * FUNCTION: clnp_insert_frag
458 * PURPOSE: Insert fragment into list headed by 'cf'.
464 * NOTES: This is the 'guts' of the reassembly algorithm.
465 * Each fragment in this list contains a clnp_frag
466 * structure followed by the data of the fragment.
467 * The clnp_frag structure actually lies on top of
468 * part of the old clnp header.
472 struct clnp_fragl
*cfh
, /* header of list of packet fragments */
473 struct mbuf
*m
, /* new fragment */
474 struct clnp_segment
*seg
) /* segment part of fragment header */
476 struct clnp_fixed
*clnp
; /* clnp hdr of fragment */
477 struct clnp_frag
*cf
; /* generic fragment ptr */
478 struct clnp_frag
*cf_sub
= NULL
; /* frag subseq to new
480 struct clnp_frag
*cf_prev
= NULL
; /* frag prev to new one */
481 u_short first
; /* offset of first byte of initial pdu */
482 u_short last
; /* offset of last byte of initial pdu */
483 u_short fraglen
;/* length of fragment */
485 clnp
= mtod(m
, struct clnp_fixed
*);
486 first
= seg
->cng_off
;
487 CTOH(clnp
->cnf_seglen_msb
, clnp
->cnf_seglen_lsb
, fraglen
);
488 fraglen
-= clnp
->cnf_hdr_len
;
489 last
= (first
+ fraglen
) - 1;
492 if (argo_debug
[D_REASS
]) {
493 printf("clnp_insert_frag: New fragment: [%d-%d], len %d\n",
494 first
, last
, fraglen
);
495 printf("clnp_insert_frag: current fragments:\n");
496 for (cf
= cfh
->cfl_frags
; cf
!= NULL
; cf
= cf
->cfr_next
) {
497 printf("\tcf %p: [%d-%d]\n",
498 cf
, cf
->cfr_first
, cf
->cfr_last
);
503 if (cfh
->cfl_frags
!= NULL
) {
505 * Find fragment which begins after the new one
507 for (cf
= cfh
->cfl_frags
; cf
!= NULL
;
508 cf_prev
= cf
, cf
= cf
->cfr_next
) {
509 if (cf
->cfr_first
> first
) {
516 if (argo_debug
[D_REASS
]) {
517 printf("clnp_insert_frag: Previous frag is ");
521 printf("[%d-%d]\n", cf_prev
->cfr_first
,
523 printf("clnp_insert_frag: Subsequent frag is ");
527 printf("[%d-%d]\n", cf_sub
->cfr_first
,
533 * If there is a fragment before the new one, check if it
534 * overlaps the new one. If so, then trim the end of the
537 if (cf_prev
!= NULL
) {
538 if (cf_prev
->cfr_last
> first
) {
539 u_short overlap
= cf_prev
->cfr_last
- first
;
542 if (argo_debug
[D_REASS
]) {
544 "clnp_insert_frag: previous overlaps by %d\n",
549 if (overlap
> fraglen
) {
551 * The new fragment is entirely
552 * contained in the preceding one.
553 * We can punt on the new frag
560 * Trim data off of end of previous
564 * inc overlap to prevent duplication
568 m_adj(cf_prev
->cfr_data
, -(int) overlap
);
569 cf_prev
->cfr_last
-= overlap
;
574 * For all fragments past the new one, check if any data on
575 * the new one overlaps data on existing fragments. If so,
576 * then trim the extra data off the end of the new one.
578 for (cf
= cf_sub
; cf
!= NULL
; cf
= cf
->cfr_next
) {
579 if (cf
->cfr_first
< last
) {
580 u_short overlap
= last
- cf
->cfr_first
;
583 if (argo_debug
[D_REASS
]) {
585 "clnp_insert_frag: subsequent overlaps by %d\n",
590 if (overlap
> fraglen
) {
592 * The new fragment is entirely
593 * contained in the succeeding one.
594 * This should not happen, because
595 * early on in this code we scanned
596 * for the fragment which started
601 "clnp_insert_frag: internal error!\n");
605 * Trim data off of end of new fragment
606 * inc overlap to prevent duplication
610 m_adj(m
, -(int) overlap
);
617 * Insert the new fragment beween cf_prev and cf_sub
619 * Note: the clnp hdr is still in the mbuf.
620 * If the data of the mbuf is not word aligned, shave off enough
621 * so that it is. Then, cast the clnp_frag structure on top
622 * of the clnp header.
623 * The clnp_hdr will not be used again (as we already have
624 * saved a copy of it).
626 * Save in cfr_bytes the number of bytes to shave off to get to
627 * the data of the packet. This is used when we coalesce fragments;
628 * the clnp_frag structure must be removed before joining mbufs.
634 /* determine if header is not word aligned */
635 pad
= (long) clnp
% 4;
639 /* bytes is number of bytes left in front of data */
640 bytes
= clnp
->cnf_hdr_len
- pad
;
643 if (argo_debug
[D_REASS
]) {
645 "clnp_insert_frag: clnp %p requires %d alignment\n",
650 /* make it word aligned if necessary */
654 cf
= mtod(m
, struct clnp_frag
*);
655 cf
->cfr_bytes
= bytes
;
658 if (argo_debug
[D_REASS
]) {
659 printf("clnp_insert_frag: cf now %p, cfr_bytes %d\n",
664 cf
->cfr_first
= first
;
669 * The data is the mbuf itself, although we must remember that the
670 * first few bytes are actually a clnp_frag structure
674 /* link into place */
675 cf
->cfr_next
= cf_sub
;
679 cf_prev
->cfr_next
= cf
;
683 * FUNCTION: clnp_comp_pdu
685 * PURPOSE: Scan the list of fragments headed by cfh. Merge
686 * any contigious fragments into one. If, after
687 * traversing all the fragments, it is determined that
688 * the packet is complete, then return a pointer to
689 * the packet (with header prepended). Otherwise,
692 * RETURNS: NULL, or a pointer to the assembled pdu in an mbuf
695 * SIDE EFFECTS: Will colapse contigious fragments into one.
697 * NOTES: This code assumes that there are no overlaps of
702 struct clnp_fragl
*cfh
) /* fragment header */
704 struct clnp_frag
*cf
= cfh
->cfl_frags
;
706 while (cf
->cfr_next
!= NULL
) {
707 struct clnp_frag
*cf_next
= cf
->cfr_next
;
710 if (argo_debug
[D_REASS
]) {
711 printf("clnp_comp_pdu: comparing: [%d-%d] to [%d-%d]\n",
712 cf
->cfr_first
, cf
->cfr_last
, cf_next
->cfr_first
,
717 if (cf
->cfr_last
== (cf_next
->cfr_first
- 1)) {
719 * Merge fragment cf and cf_next
722 * - trim clnp_frag structure off of cf_next
723 * - append cf_next to cf
725 struct clnp_frag cf_next_hdr
;
726 struct clnp_frag
*next_frag
;
728 cf_next_hdr
= *cf_next
;
729 next_frag
= cf_next
->cfr_next
;
732 if (argo_debug
[D_REASS
]) {
735 printf("clnp_comp_pdu: merging fragments\n");
737 "clnp_comp_pdu: 1st: [%d-%d] (bytes %d)\n",
738 cf
->cfr_first
, cf
->cfr_last
,
740 mdump
= cf
->cfr_data
;
742 while (mdump
!= NULL
) {
743 printf("\tmbuf %p, m_len %d\n",
744 mdump
, mdump
->m_len
);
746 mdump
= mdump
->m_next
;
748 printf("\ttotal len: %d\n", l
);
750 "clnp_comp_pdu: 2nd: [%d-%d] (bytes %d)\n",
751 cf_next
->cfr_first
, cf_next
->cfr_last
,
753 mdump
= cf_next
->cfr_data
;
755 while (mdump
!= NULL
) {
756 printf("\tmbuf %p, m_len %d\n",
757 mdump
, mdump
->m_len
);
759 mdump
= mdump
->m_next
;
761 printf("\ttotal len: %d\n", l
);
765 cf
->cfr_last
= cf_next
->cfr_last
;
767 * After this m_adj, the cf_next ptr is useless
768 * because we have adjusted the clnp_frag structure
772 if (argo_debug
[D_REASS
]) {
773 printf("clnp_comp_pdu: shaving off %d bytes\n",
774 cf_next_hdr
.cfr_bytes
);
777 m_adj(cf_next_hdr
.cfr_data
,
778 (int) cf_next_hdr
.cfr_bytes
);
779 m_cat(cf
->cfr_data
, cf_next_hdr
.cfr_data
);
780 cf
->cfr_next
= next_frag
;
789 if (argo_debug
[D_REASS
]) {
790 struct mbuf
*mdump
= cf
->cfr_data
;
791 printf("clnp_comp_pdu: first frag now: [%d-%d]\n",
792 cf
->cfr_first
, cf
->cfr_last
);
793 printf("clnp_comp_pdu: data for frag:\n");
794 while (mdump
!= NULL
) {
795 printf("mbuf %p, m_len %d\n", mdump
, mdump
->m_len
);
796 /* dump_buf(mtod(mdump, void *), mdump->m_len); */
797 mdump
= mdump
->m_next
;
802 /* Check if datagram is complete */
803 if ((cf
->cfr_first
== 0) && (cf
->cfr_last
== cfh
->cfl_last
)) {
805 * We have a complete pdu!
806 * - Remove the frag header from (only) remaining fragment
807 * (which is not really a fragment anymore, as the datagram
809 * - Prepend a clnp header
811 struct mbuf
*data
= cf
->cfr_data
;
812 struct mbuf
*hdr
= cfh
->cfl_orighdr
;
813 struct clnp_fragl
*scan
;
816 if (argo_debug
[D_REASS
]) {
817 printf("clnp_comp_pdu: complete pdu!\n");
821 m_adj(data
, (int) cf
->cfr_bytes
);
825 if (argo_debug
[D_DUMPIN
]) {
826 struct mbuf
*mdump
= hdr
;
827 printf("clnp_comp_pdu: pdu is:\n");
828 while (mdump
!= NULL
) {
829 printf("mbuf %p, m_len %d\n",
830 mdump
, mdump
->m_len
);
832 dump_buf(mtod(mdump
, void *), mdump
->m_len
);
834 mdump
= mdump
->m_next
;
840 * Remove cfh from the list of fragmented pdus
842 if (clnp_frags
== cfh
) {
843 clnp_frags
= cfh
->cfl_next
;
845 for (scan
= clnp_frags
; scan
!= NULL
;
846 scan
= scan
->cfl_next
) {
847 if (scan
->cfl_next
== cfh
) {
848 scan
->cfl_next
= cfh
->cfl_next
;
862 static int troll_cnt
;
863 #include <sys/time.h>
865 * FUNCTION: troll_random
867 * PURPOSE: generate a pseudo-random number between 0 and 1
869 * RETURNS: the random number
873 * NOTES: This is based on the clock.
878 extern struct timeval time
;
879 long t
= time
.tv_usec
% 100;
881 return ((float) t
/ (float) 100);
885 * FUNCTION: troll_output
887 * PURPOSE: Do something sneaky with the datagram passed. Possible
889 * Duplicate the packet
891 * Trim some number of bytes from the packet
892 * Munge some byte in the packet
894 * RETURNS: 0, or unix error code
898 * NOTES: The operation of this procedure is regulated by the
899 * troll control structure (Troll).
902 troll_output(struct ifnet
*ifp
, struct mbuf
*m
, const struct sockaddr
*dst
, struct rtentry
*rt
)
907 if (trollctl
.tr_ops
& TR_DUPPKT
) {
909 * Duplicate every Nth packet
912 float f_freq
= troll_cnt
* trollctl
.tr_dup_freq
;
913 int i_freq
= troll_cnt
* trollctl
.tr_dup_freq
;
914 if (i_freq
== f_freq
) {
915 struct mbuf
*dup
= m_copy(m
, 0, (int) M_COPYALL
);
917 err
= (*ifp
->if_output
) (ifp
, dup
, dst
, rt
);
920 err
= (*ifp
->if_output
) (ifp
, m
, dst
, rt
);
922 } else if (trollctl
.tr_ops
& TR_DROPPKT
) {
923 } else if (trollctl
.tr_ops
& TR_CHANGE
) {
924 struct clnp_fixed
*clnp
= mtod(m
, struct clnp_fixed
*);
925 clnp
->cnf_cksum_msb
= 0;
926 err
= (*ifp
->if_output
) (ifp
, m
, dst
, rt
);
929 err
= (*ifp
->if_output
) (ifp
, m
, dst
, rt
);