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