|
|
1.1 root 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: */
1.1.1.2 ! root 62: /* $Header: /cvsroot/src/sys/netiso/clnp_frag.c,v 1.1 1993/04/09 12:00:50 cgd Exp $ */
! 63: /* $Source: /cvsroot/src/sys/netiso/clnp_frag.c,v $ */
1.1 root 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.