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