|
|
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: /*
28: * $Header: iso_chksum.c,v 4.7 88/07/29 15:31:26 nhall Exp $
29: * $Source: /usr/argo/sys/netiso/RCS/iso_chksum.c,v $
30: * @(#)iso_chksum.c 7.4 (Berkeley) 9/26/89 *
31: *
32: * ISO CHECKSUM
33: *
34: * The checksum generation and check routines are here.
35: * The checksum is 2 bytes such that the sum of all the bytes b(i) == 0
36: * and the sum of i * b(i) == 0.
37: * The whole thing is complicated by the fact that the data are in mbuf
38: * chains.
39: * Furthermore, there is the possibility of wraparound in the running
40: * sums after adding up 4102 octets. In order to avoid doing a mod
41: * operation after EACH add, we have restricted this implementation to
42: * negotiating a maximum of 4096-octets per TPDU (for the transport layer).
43: * The routine iso_check_csum doesn't need to know where the checksum
44: * octets are.
45: * The routine iso_gen_csum takes a pointer to an mbuf chain (logically
46: * a chunk of data), an offset into the chunk at which the 2 octets are to
47: * be stuffed, and the length of the chunk. The 2 octets have to be
48: * logically adjacent, but may be physically located in separate mbufs.
49: */
50:
51: #ifdef ISO
52: #ifndef lint
53: static char *rcsid = "$Header: iso_chksum.c,v 4.7 88/07/29 15:31:26 nhall Exp $";
54: #endif
55:
56: #include "argo_debug.h"
57: #include "param.h"
58: #include "mbuf.h"
59: #endif ISO
60:
61: #ifndef MNULL
62: #define MNULL (struct mbuf *)0
63: #endif MNULL
64:
65: /*
66: * FUNCTION: iso_check_csum
67: *
68: * PURPOSE: To check the checksum of the packet in the mbuf chain (m).
69: * The total length of the packet is (len).
70: * Called from tp_input() and clnp_intr()
71: *
72: * RETURNS: TRUE (something non-zero) if there is a checksum error,
73: * FALSE if there was NO checksum error.
74: *
75: * SIDE EFFECTS: none
76: *
77: * NOTES: It might be possible to gain something by optimizing
78: * this routine (unrolling loops, etc). But it is such
79: * a horrible thing to fiddle with anyway, it probably
80: * isn't worth it.
81: */
82: int
83: iso_check_csum(m, len)
84: struct mbuf *m;
85: int len;
86: {
87: register u_char *p = mtod(m, u_char *);
88: register u_long c0=0, c1=0;
89: register int i=0;
90: int cum = 0; /* cumulative length */
91: int l;
92:
93: l = len;
94: len = MIN(m->m_len, len);
95: i = 0;
96:
97: IFDEBUG(D_CHKSUM)
98: printf("iso_check_csum: m x%x, l x%x, m->m_len x%x\n", m, l, m->m_len);
99: ENDDEBUG
100:
101: while( i<l ) {
102: cum += len;
103: while (i<cum) {
104: c0 = c0 + *(p++);
105: c1 += c0;
106: i++;
107: }
108: if(i < l) {
109: m = m->m_next;
110: IFDEBUG(D_CHKSUM)
111: printf("iso_check_csum: new mbuf\n");
112: if(l-i < m->m_len)
113: printf(
114: "bad mbuf chain in check csum l 0x%x i 0x%x m_data 0x%x",
115: l,i,m->m_data);
116: ENDDEBUG
117: ASSERT( m != MNULL);
118: len = MIN( m->m_len, l-i);
119: p = mtod(m, u_char *);
120: }
121: }
122: if ( ((int)c0 % 255) || ((int)c1 % 255) ) {
123: IFDEBUG(D_CHKSUM)
124: printf("BAD iso_check_csum l 0x%x cum 0x%x len 0x%x, i 0x%x",
125: l, cum, len, i);
126: ENDDEBUG
127: return ((int)c0 % 255)<<8 | ((int)c1 % 255);
128: }
129: return 0;
130: }
131:
132: /*
133: * FUNCTION: iso_gen_csum
134: *
135: * PURPOSE: To generate the checksum of the packet in the mbuf chain (m).
136: * The first of the 2 (logically) adjacent checksum bytes
137: * (x and y) go at offset (n).
138: * (n) is an offset relative to the beginning of the data,
139: * not the beginning of the mbuf.
140: * (l) is the length of the total mbuf chain's data.
141: * Called from tp_emit(), tp_error_emit()
142: * clnp_emit_er(), clnp_forward(), clnp_output().
143: *
144: * RETURNS: Rien
145: *
146: * SIDE EFFECTS: Puts the 2 checksum bytes into the packet.
147: *
148: * NOTES: Ditto the note for iso_check_csum().
149: */
150:
151: void
152: iso_gen_csum(m,n,l)
153: struct mbuf *m;
154: int n; /* offset of 2 checksum bytes */
155: int l;
156: {
157: register u_char *p = mtod(m, u_char *);
158: register int c0=0, c1=0;
159: register int i=0;
160: int loc = n++, len=0; /* n is position, loc is offset */
161: u_char *xloc;
162: u_char *yloc;
163: int cum=0; /* cum == cumulative length */
164:
165: IFDEBUG(D_CHKSUM)
166: printf("enter gen csum m 0x%x n 0x%x l 0x%x\n",m, n-1 ,l );
167: ENDDEBUG
168:
169: while(i < l) {
170: len = MIN(m->m_len, CLBYTES);
171: /* RAH: don't cksum more than l bytes */
172: len = MIN(len, l - i);
173:
174: cum +=len;
175: p = mtod(m, u_char *);
176:
177: if(loc>=0) {
178: if (loc < len) {
179: xloc = loc + mtod(m, u_char *);
180: IFDEBUG(D_CHKSUM)
181: printf("1: zeroing xloc 0x%x loc 0x%x\n",xloc, loc );
182: ENDDEBUG
183: *xloc = (u_char)0;
184: if (loc+1 < len) {
185: /* both xloc and yloc are in same mbuf */
186: yloc = 1 + xloc;
187: IFDEBUG(D_CHKSUM)
188: printf("2: zeroing yloc 0x%x loc 0x%x\n",yloc, loc );
189: ENDDEBUG
190: *yloc = (u_char)0;
191: } else {
192: /* crosses boundary of mbufs */
193: yloc = mtod(m->m_next, u_char *);
194: IFDEBUG(D_CHKSUM)
195: printf("3: zeroing yloc 0x%x \n",yloc );
196: ENDDEBUG
197: *yloc = (u_char)0;
198: }
199: }
200: loc -= len;
201: }
202:
203: while(i < cum) {
204: c0 = (c0 + *p);
205: c1 += c0 ;
206: i++;
207: p++;
208: }
209: m = m->m_next;
210: }
211: IFDEBUG(D_CHKSUM)
212: printf("gen csum final xloc 0x%x yloc 0x%x\n",xloc, yloc );
213: ENDDEBUG
214:
215: c1 = (((c0 * (l-n))-c1)%255) ;
216: *xloc = (u_char) ((c1 < 0)? c1+255 : c1);
217:
218: c1 = (-(int)(c1+c0))%255;
219: *yloc = (u_char) (c1 < 0? c1 + 255 : c1);
220:
221: IFDEBUG(D_CHKSUM)
222: printf("gen csum end \n");
223: ENDDEBUG
224: }
225:
226: struct mbuf *
227: m_append(head, m)
228: struct mbuf *head, *m;
229: {
230: register struct mbuf *n;
231:
232: if (m == 0)
233: return head;
234: if (head == 0)
235: return m;
236: n = head;
237: while (n->m_next)
238: n = n->m_next;
239: n->m_next = m;
240: return head;
241: }
242: /*
243: * FUNCTION: m_datalen
244: *
245: * PURPOSE: returns length of the mbuf chain.
246: * used all over the iso code.
247: *
248: * RETURNS: integer
249: *
250: * SIDE EFFECTS: none
251: *
252: * NOTES:
253: */
254:
255: int
256: m_datalen (morig)
257: struct mbuf *morig;
258: {
259: int s = splimp();
260: register struct mbuf *n=morig;
261: register int datalen = 0;
262:
263: if( morig == (struct mbuf *)0)
264: return 0;
265: for(;;) {
266: datalen += n->m_len;
267: if (n->m_next == (struct mbuf *)0 ) {
268: break;
269: }
270: n = n->m_next;
271: }
272: splx(s);
273: return datalen;
274: }
275:
276: int
277: m_compress(in, out)
278: register struct mbuf *in, **out;
279: {
280: register int datalen = 0;
281: int s = splimp();
282:
283: if( in->m_next == MNULL ) {
284: *out = in;
285: IFDEBUG(D_REQUEST)
286: printf("m_compress returning 0x%x: A\n", in->m_len);
287: ENDDEBUG
288: splx(s);
289: return in->m_len;
290: }
291: MGET((*out), M_DONTWAIT, MT_DATA);
292: if((*out) == MNULL) {
293: *out = in;
294: IFDEBUG(D_REQUEST)
295: printf("m_compress returning -1: B\n");
296: ENDDEBUG
297: splx(s);
298: return -1;
299: }
300: (*out)->m_len = 0;
301: (*out)->m_act = MNULL;
302:
303: while (in) {
304: IFDEBUG(D_REQUEST)
305: printf("m_compress in 0x%x *out 0x%x\n", in, *out);
306: printf("m_compress in: len 0x%x, off 0x%x\n", in->m_len, in->m_data);
307: printf("m_compress *out: len 0x%x, off 0x%x\n", (*out)->m_len,
308: (*out)->m_data);
309: ENDDEBUG
310: if (in->m_flags & M_EXT) {
311: ASSERT(in->m_len == 0);
312: }
313: if ( in->m_len == 0) {
314: in = in->m_next;
315: continue;
316: }
317: if (((*out)->m_flags & M_EXT) == 0) {
318: int len;
319:
320: len = M_TRAILINGSPACE(*out);
321: len = MIN(len, in->m_len);
322: datalen += len;
323:
324: IFDEBUG(D_REQUEST)
325: printf("m_compress copying len %d\n", len);
326: ENDDEBUG
327: bcopy(mtod(in, caddr_t), mtod((*out), caddr_t) + (*out)->m_len,
328: (unsigned)len);
329:
330: (*out)->m_len += len;
331: in->m_len -= len;
332: continue;
333: } else {
334: /* (*out) is full */
335: if(( (*out)->m_next = m_get(M_DONTWAIT, MT_DATA) ) == MNULL) {
336: m_freem(*out);
337: *out = in;
338: IFDEBUG(D_REQUEST)
339: printf("m_compress returning -1: B\n");
340: ENDDEBUG
341: splx(s);
342: return -1;
343: }
344: (*out)->m_len = 0;
345: (*out)->m_act = MNULL;
346: *out = (*out)->m_next;
347: }
348: }
349: m_freem(in);
350: IFDEBUG(D_REQUEST)
351: printf("m_compress returning 0x%x: A\n", datalen);
352: ENDDEBUG
353: splx(s);
354: return datalen;
355: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.