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