]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet/in_cksum.c
xnu-124.13.tar.gz
[apple/xnu.git] / bsd / netinet / in_cksum.c
CommitLineData
1c79356b
A
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) 1988, 1992, 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 * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
55 */
56
57#include <sys/param.h>
58#include <sys/mbuf.h>
59#include <sys/kdebug.h>
60
61#define DBG_FNC_IN_CKSUM NETDBG_CODE(DBG_NETIP, (3 << 8))
62
63/*
64 * Checksum routine for Internet Protocol family headers (Portable Version).
65 *
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.
68 */
69
70
71
72#if defined(ppc)
73
74int
75in_cksum(m, len)
76 register struct mbuf *m;
77 register int len;
78{
79 register u_short *w;
80 register int sum = 0;
81 register int mlen = 0;
82 int starting_on_odd = 0;
83
84
85 KERNEL_DEBUG(DBG_FNC_IN_CKSUM | DBG_FUNC_START, len,0,0,0,0);
86
87 for (;m && len; m = m->m_next) {
88 if (m->m_len == 0)
89 continue;
90 mlen = m->m_len;
91 w = mtod(m, u_short *);
92
93 if (len < mlen)
94 mlen = len;
95
96 sum = xsum_assym(w, mlen, sum, starting_on_odd);
97 len -= mlen;
98 if (mlen & 0x1)
99 {
100 if (starting_on_odd)
101 starting_on_odd = 0;
102 else
103 starting_on_odd = 1;
104 }
105 }
106
107 KERNEL_DEBUG(DBG_FNC_IN_CKSUM | DBG_FUNC_END, 0,0,0,0,0);
108 return (~sum & 0xffff);
109}
110
111#else
112
113
114#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
115#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
116
117
118
119int
120in_cksum(m, len)
121 register struct mbuf *m;
122 register int len;
123{
124 register u_short *w;
125 register int sum = 0;
126 register int mlen = 0;
127 int byte_swapped = 0;
128
129 union {
130 char c[2];
131 u_short s;
132 } s_util;
133 union {
134 u_short s[2];
135 long l;
136 } l_util;
137
138 KERNEL_DEBUG(DBG_FNC_IN_CKSUM | DBG_FUNC_START, len,0,0,0,0);
139
140 for (;m && len; m = m->m_next) {
141 if (m->m_len == 0)
142 continue;
143 w = mtod(m, u_short *);
144 if (mlen == -1) {
145 /*
146 * The first byte of this mbuf is the continuation
147 * of a word spanning between this mbuf and the
148 * last mbuf.
149 *
150 * s_util.c[0] is already saved when scanning previous
151 * mbuf.
152 */
153 s_util.c[1] = *(char *)w;
154 sum += s_util.s;
155 w = (u_short *)((char *)w + 1);
156 mlen = m->m_len - 1;
157 len--;
158 } else
159 mlen = m->m_len;
160 if (len < mlen)
161 mlen = len;
162 len -= mlen;
163 /*
164 * Force to even boundary.
165 */
166 if ((1 & (int) w) && (mlen > 0)) {
167 REDUCE;
168 sum <<= 8;
169 s_util.c[0] = *(u_char *)w;
170 w = (u_short *)((char *)w + 1);
171 mlen--;
172 byte_swapped = 1;
173 }
174 /*
175 * Unroll the loop to make overhead from
176 * branches &c small.
177 */
178 while ((mlen -= 32) >= 0) {
179 sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
180 sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
181 sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
182 sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
183 w += 16;
184 }
185 mlen += 32;
186 while ((mlen -= 8) >= 0) {
187 sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
188 w += 4;
189 }
190 mlen += 8;
191 if (mlen == 0 && byte_swapped == 0)
192 continue;
193 REDUCE;
194 while ((mlen -= 2) >= 0) {
195 sum += *w++;
196 }
197 if (byte_swapped) {
198 REDUCE;
199 sum <<= 8;
200 byte_swapped = 0;
201 if (mlen == -1) {
202 s_util.c[1] = *(char *)w;
203 sum += s_util.s;
204 mlen = 0;
205 } else
206 mlen = -1;
207 } else if (mlen == -1)
208 s_util.c[0] = *(char *)w;
209 }
210 if (len)
211 printf("cksum: out of data\n");
212 if (mlen == -1) {
213 /* The last mbuf has odd # of bytes. Follow the
214 standard (the odd byte may be shifted left by 8 bits
215 or not as determined by endian-ness of the machine) */
216 s_util.c[1] = 0;
217 sum += s_util.s;
218 }
219 REDUCE;
220 KERNEL_DEBUG(DBG_FNC_IN_CKSUM | DBG_FUNC_END, 0,0,0,0,0);
221 return (~sum & 0xffff);
222}
223
224#endif