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