]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netinet/in_cksum.c
c8a2d462fa042ae70420c12f9a1aa649b9698d4d
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1988, 1992, 1993
24 * The Regents of the University of California. All rights reserved.
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
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.
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
54 * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
57 #include <sys/param.h>
59 #include <sys/kdebug.h>
61 #define DBG_FNC_IN_CKSUM NETDBG_CODE(DBG_NETIP, (3 << 8))
64 * Checksum routine for Internet Protocol family headers (Portable Version).
66 * This routine is very heavily used in the network
67 * code and should be modified for each CPU to be as fast as possible.
86 #define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
91 sum = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \
96 l_util.l = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \
97 sum = l_util.s[0] + l_util.s[1]; \
101 #define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
106 __inline
unsigned short
107 in_addword(u_short a
, u_short b
)
110 u_int32_t sum
= a
+ b
;
115 __inline
unsigned short
116 in_pseudo(u_int a
, u_int b
, u_int c
)
122 sum
= (u_int64_t
) a
+ b
+ c
;
130 register struct mbuf
*m
;
134 register int sum
= 0;
135 register int mlen
= 0;
136 int starting_on_odd
= 0;
139 KERNEL_DEBUG(DBG_FNC_IN_CKSUM
| DBG_FUNC_START
, len
,0,0,0,0);
141 for (;m
&& len
; m
= m
->m_next
) {
145 w
= mtod(m
, u_short
*);
150 sum
= xsum_assym(w
, mlen
, sum
, starting_on_odd
);
161 KERNEL_DEBUG(DBG_FNC_IN_CKSUM
| DBG_FUNC_END
, 0,0,0,0,0);
162 return (~sum
& 0xffff);
166 in_cksum_skip(m
, len
, skip
)
167 register struct mbuf
*m
;
172 register int sum
= 0;
173 register int mlen
= 0;
174 int starting_on_odd
= 0;
177 for (; skip
&& m
; m
= m
->m_next
) {
178 if (m
->m_len
> skip
) {
179 mlen
= m
->m_len
- skip
;
180 w
= (u_short
*)(m
->m_data
+skip
);
186 for (;m
&& len
; m
= m
->m_next
) {
190 w
= mtod(m
, u_short
*);
195 sum
= xsum_assym(w
, mlen
, sum
, starting_on_odd
);
206 return (~sum
& 0xffff);
211 in_addword(u_short a
, u_short b
)
214 u_int32_t sum
= a
+ b
;
220 in_pseudo(u_int a
, u_int b
, u_int c
)
226 sum
= (u_int64_t
) a
+ b
+ c
;
234 register struct mbuf
*m
;
238 register int sum
= 0;
239 register int mlen
= 0;
240 int byte_swapped
= 0;
244 KERNEL_DEBUG(DBG_FNC_IN_CKSUM
| DBG_FUNC_START
, len
,0,0,0,0);
246 for (;m
&& len
; m
= m
->m_next
) {
249 w
= mtod(m
, u_short
*);
252 * The first byte of this mbuf is the continuation
253 * of a word spanning between this mbuf and the
256 * s_util.c[0] is already saved when scanning previous
259 s_util
.c
[1] = *(char *)w
;
261 w
= (u_short
*)((char *)w
+ 1);
270 * Force to even boundary.
272 if ((1 & (int) w
) && (mlen
> 0)) {
275 s_util
.c
[0] = *(u_char
*)w
;
276 w
= (u_short
*)((char *)w
+ 1);
281 * Unroll the loop to make overhead from
284 while ((mlen
-= 32) >= 0) {
285 sum
+= w
[0]; sum
+= w
[1]; sum
+= w
[2]; sum
+= w
[3];
286 sum
+= w
[4]; sum
+= w
[5]; sum
+= w
[6]; sum
+= w
[7];
287 sum
+= w
[8]; sum
+= w
[9]; sum
+= w
[10]; sum
+= w
[11];
288 sum
+= w
[12]; sum
+= w
[13]; sum
+= w
[14]; sum
+= w
[15];
292 while ((mlen
-= 8) >= 0) {
293 sum
+= w
[0]; sum
+= w
[1]; sum
+= w
[2]; sum
+= w
[3];
297 if (mlen
== 0 && byte_swapped
== 0)
300 while ((mlen
-= 2) >= 0) {
308 s_util
.c
[1] = *(char *)w
;
313 } else if (mlen
== -1)
314 s_util
.c
[0] = *(char *)w
;
317 printf("cksum: out of data\n");
319 /* The last mbuf has odd # of bytes. Follow the
320 standard (the odd byte may be shifted left by 8 bits
321 or not as determined by endian-ness of the machine) */
326 KERNEL_DEBUG(DBG_FNC_IN_CKSUM
| DBG_FUNC_END
, 0,0,0,0,0);
327 return (~sum
& 0xffff);
331 in_cksum_skip(m
, len
, skip
)
332 register struct mbuf
*m
;
333 register u_short len
;
334 register u_short skip
;
337 register int sum
= 0;
338 register int mlen
= 0;
339 int byte_swapped
= 0;
343 KERNEL_DEBUG(DBG_FNC_IN_CKSUM
| DBG_FUNC_START
, len
,0,0,0,0);
346 for (; skip
&& m
; m
= m
->m_next
) {
347 if (m
->m_len
> skip
) {
348 mlen
= m
->m_len
- skip
;
349 w
= (u_short
*)(m
->m_data
+skip
);
355 for (;m
&& len
; m
= m
->m_next
) {
358 w
= mtod(m
, u_short
*);
362 * The first byte of this mbuf is the continuation
363 * of a word spanning between this mbuf and the
366 * s_util.c[0] is already saved when scanning previous
369 s_util
.c
[1] = *(char *)w
;
371 w
= (u_short
*)((char *)w
+ 1);
383 * Force to even boundary.
385 if ((1 & (int) w
) && (mlen
> 0)) {
388 s_util
.c
[0] = *(u_char
*)w
;
389 w
= (u_short
*)((char *)w
+ 1);
394 * Unroll the loop to make overhead from
397 while ((mlen
-= 32) >= 0) {
398 sum
+= w
[0]; sum
+= w
[1]; sum
+= w
[2]; sum
+= w
[3];
399 sum
+= w
[4]; sum
+= w
[5]; sum
+= w
[6]; sum
+= w
[7];
400 sum
+= w
[8]; sum
+= w
[9]; sum
+= w
[10]; sum
+= w
[11];
401 sum
+= w
[12]; sum
+= w
[13]; sum
+= w
[14]; sum
+= w
[15];
405 while ((mlen
-= 8) >= 0) {
406 sum
+= w
[0]; sum
+= w
[1]; sum
+= w
[2]; sum
+= w
[3];
410 if (mlen
== 0 && byte_swapped
== 0)
413 while ((mlen
-= 2) >= 0) {
421 s_util
.c
[1] = *(char *)w
;
426 } else if (mlen
== -1)
427 s_util
.c
[0] = *(char *)w
;
430 printf("cksum: out of data\n");
432 /* The last mbuf has odd # of bytes. Follow the
433 standard (the odd byte may be shifted left by 8 bits
434 or not as determined by endian-ness of the machine) */
439 KERNEL_DEBUG(DBG_FNC_IN_CKSUM
| DBG_FUNC_END
, 0,0,0,0,0);
440 return (~sum
& 0xffff);