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