in4_cksum.c revision 1.4.6.2 1 1.4.6.2 bouyer /* $NetBSD: in4_cksum.c,v 1.4.6.2 2000/11/20 18:10:22 bouyer Exp $ */
2 1.4.6.2 bouyer
3 1.4.6.2 bouyer /*
4 1.4.6.2 bouyer * Copyright (C) 1999 WIDE Project.
5 1.4.6.2 bouyer * All rights reserved.
6 1.4.6.2 bouyer *
7 1.4.6.2 bouyer * Redistribution and use in source and binary forms, with or without
8 1.4.6.2 bouyer * modification, are permitted provided that the following conditions
9 1.4.6.2 bouyer * are met:
10 1.4.6.2 bouyer * 1. Redistributions of source code must retain the above copyright
11 1.4.6.2 bouyer * notice, this list of conditions and the following disclaimer.
12 1.4.6.2 bouyer * 2. Redistributions in binary form must reproduce the above copyright
13 1.4.6.2 bouyer * notice, this list of conditions and the following disclaimer in the
14 1.4.6.2 bouyer * documentation and/or other materials provided with the distribution.
15 1.4.6.2 bouyer * 3. Neither the name of the project nor the names of its contributors
16 1.4.6.2 bouyer * may be used to endorse or promote products derived from this software
17 1.4.6.2 bouyer * without specific prior written permission.
18 1.4.6.2 bouyer *
19 1.4.6.2 bouyer * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 1.4.6.2 bouyer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 1.4.6.2 bouyer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 1.4.6.2 bouyer * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 1.4.6.2 bouyer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 1.4.6.2 bouyer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 1.4.6.2 bouyer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 1.4.6.2 bouyer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 1.4.6.2 bouyer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 1.4.6.2 bouyer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 1.4.6.2 bouyer * SUCH DAMAGE.
30 1.4.6.2 bouyer */
31 1.4.6.2 bouyer
32 1.4.6.2 bouyer /*
33 1.4.6.2 bouyer * Copyright (c) 1988, 1992, 1993
34 1.4.6.2 bouyer * The Regents of the University of California. All rights reserved.
35 1.4.6.2 bouyer *
36 1.4.6.2 bouyer * Redistribution and use in source and binary forms, with or without
37 1.4.6.2 bouyer * modification, are permitted provided that the following conditions
38 1.4.6.2 bouyer * are met:
39 1.4.6.2 bouyer * 1. Redistributions of source code must retain the above copyright
40 1.4.6.2 bouyer * notice, this list of conditions and the following disclaimer.
41 1.4.6.2 bouyer * 2. Redistributions in binary form must reproduce the above copyright
42 1.4.6.2 bouyer * notice, this list of conditions and the following disclaimer in the
43 1.4.6.2 bouyer * documentation and/or other materials provided with the distribution.
44 1.4.6.2 bouyer * 3. All advertising materials mentioning features or use of this software
45 1.4.6.2 bouyer * must display the following acknowledgement:
46 1.4.6.2 bouyer * This product includes software developed by the University of
47 1.4.6.2 bouyer * California, Berkeley and its contributors.
48 1.4.6.2 bouyer * 4. Neither the name of the University nor the names of its contributors
49 1.4.6.2 bouyer * may be used to endorse or promote products derived from this software
50 1.4.6.2 bouyer * without specific prior written permission.
51 1.4.6.2 bouyer *
52 1.4.6.2 bouyer * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 1.4.6.2 bouyer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 1.4.6.2 bouyer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 1.4.6.2 bouyer * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 1.4.6.2 bouyer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 1.4.6.2 bouyer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 1.4.6.2 bouyer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 1.4.6.2 bouyer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 1.4.6.2 bouyer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 1.4.6.2 bouyer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 1.4.6.2 bouyer * SUCH DAMAGE.
63 1.4.6.2 bouyer *
64 1.4.6.2 bouyer * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
65 1.4.6.2 bouyer */
66 1.4.6.2 bouyer
67 1.4.6.2 bouyer #include <sys/param.h>
68 1.4.6.2 bouyer #include <sys/mbuf.h>
69 1.4.6.2 bouyer #include <sys/systm.h>
70 1.4.6.2 bouyer #include <sys/socket.h>
71 1.4.6.2 bouyer #include <net/route.h>
72 1.4.6.2 bouyer #include <netinet/in.h>
73 1.4.6.2 bouyer #include <netinet/in_systm.h>
74 1.4.6.2 bouyer #include <netinet/ip.h>
75 1.4.6.2 bouyer #include <netinet/ip_var.h>
76 1.4.6.2 bouyer
77 1.4.6.2 bouyer /*
78 1.4.6.2 bouyer * Checksum routine for Internet Protocol family headers (Portable Version).
79 1.4.6.2 bouyer * This is only for IPv4 pseudo header checksum.
80 1.4.6.2 bouyer * No need to clear non-pseudo-header fields in IPv4 header.
81 1.4.6.2 bouyer * len is for actual payload size, and does not include IPv4 header and
82 1.4.6.2 bouyer * skipped header chain (off + len should be equal to the whole packet).
83 1.4.6.2 bouyer *
84 1.4.6.2 bouyer * This routine is very heavily used in the network
85 1.4.6.2 bouyer * code and should be modified for each CPU to be as fast as possible.
86 1.4.6.2 bouyer */
87 1.4.6.2 bouyer
88 1.4.6.2 bouyer #define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
89 1.4.6.2 bouyer #define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
90 1.4.6.2 bouyer
91 1.4.6.2 bouyer int
92 1.4.6.2 bouyer in4_cksum(m, nxt, off, len)
93 1.4.6.2 bouyer struct mbuf *m;
94 1.4.6.2 bouyer u_int8_t nxt;
95 1.4.6.2 bouyer int off, len;
96 1.4.6.2 bouyer {
97 1.4.6.2 bouyer u_int16_t *w;
98 1.4.6.2 bouyer int sum = 0;
99 1.4.6.2 bouyer int mlen = 0;
100 1.4.6.2 bouyer int byte_swapped = 0;
101 1.4.6.2 bouyer struct ipovly ipov;
102 1.4.6.2 bouyer
103 1.4.6.2 bouyer union {
104 1.4.6.2 bouyer u_int8_t c[2];
105 1.4.6.2 bouyer u_int16_t s;
106 1.4.6.2 bouyer } s_util;
107 1.4.6.2 bouyer union {
108 1.4.6.2 bouyer u_int16_t s[2];
109 1.4.6.2 bouyer u_int32_t l;
110 1.4.6.2 bouyer } l_util;
111 1.4.6.2 bouyer
112 1.4.6.2 bouyer /* pseudo header */
113 1.4.6.2 bouyer if (off < sizeof(struct ipovly))
114 1.4.6.2 bouyer panic("in4_cksum: offset too short");
115 1.4.6.2 bouyer if (m->m_len < sizeof(struct ip))
116 1.4.6.2 bouyer panic("in4_cksum: bad mbuf chain");
117 1.4.6.2 bouyer bzero(&ipov, sizeof(ipov));
118 1.4.6.2 bouyer ipov.ih_len = htons(len);
119 1.4.6.2 bouyer ipov.ih_pr = nxt;
120 1.4.6.2 bouyer ipov.ih_src = mtod(m, struct ip *)->ip_src;
121 1.4.6.2 bouyer ipov.ih_dst = mtod(m, struct ip *)->ip_dst;
122 1.4.6.2 bouyer w = (u_int16_t *)&ipov;
123 1.4.6.2 bouyer /* assumes sizeof(ipov) == 20 */
124 1.4.6.2 bouyer sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; sum += w[4];
125 1.4.6.2 bouyer sum += w[5]; sum += w[6]; sum += w[7]; sum += w[8]; sum += w[9];
126 1.4.6.2 bouyer
127 1.4.6.2 bouyer /* skip unnecessary part */
128 1.4.6.2 bouyer while (m && off > 0) {
129 1.4.6.2 bouyer if (m->m_len > off)
130 1.4.6.2 bouyer break;
131 1.4.6.2 bouyer off -= m->m_len;
132 1.4.6.2 bouyer m = m->m_next;
133 1.4.6.2 bouyer }
134 1.4.6.2 bouyer
135 1.4.6.2 bouyer for (;m && len; m = m->m_next) {
136 1.4.6.2 bouyer if (m->m_len == 0)
137 1.4.6.2 bouyer continue;
138 1.4.6.2 bouyer w = (u_int16_t *)(mtod(m, caddr_t) + off);
139 1.4.6.2 bouyer if (mlen == -1) {
140 1.4.6.2 bouyer /*
141 1.4.6.2 bouyer * The first byte of this mbuf is the continuation
142 1.4.6.2 bouyer * of a word spanning between this mbuf and the
143 1.4.6.2 bouyer * last mbuf.
144 1.4.6.2 bouyer *
145 1.4.6.2 bouyer * s_util.c[0] is already saved when scanning previous
146 1.4.6.2 bouyer * mbuf.
147 1.4.6.2 bouyer */
148 1.4.6.2 bouyer s_util.c[1] = *(u_int8_t *)w;
149 1.4.6.2 bouyer sum += s_util.s;
150 1.4.6.2 bouyer w = (u_int16_t *)((u_int8_t *)w + 1);
151 1.4.6.2 bouyer mlen = m->m_len - off - 1;
152 1.4.6.2 bouyer len--;
153 1.4.6.2 bouyer } else
154 1.4.6.2 bouyer mlen = m->m_len - off;
155 1.4.6.2 bouyer off = 0;
156 1.4.6.2 bouyer if (len < mlen)
157 1.4.6.2 bouyer mlen = len;
158 1.4.6.2 bouyer len -= mlen;
159 1.4.6.2 bouyer /*
160 1.4.6.2 bouyer * Force to even boundary.
161 1.4.6.2 bouyer */
162 1.4.6.2 bouyer if ((1 & (long) w) && (mlen > 0)) {
163 1.4.6.2 bouyer REDUCE;
164 1.4.6.2 bouyer sum <<= 8;
165 1.4.6.2 bouyer s_util.c[0] = *(u_int8_t *)w;
166 1.4.6.2 bouyer w = (u_int16_t *)((int8_t *)w + 1);
167 1.4.6.2 bouyer mlen--;
168 1.4.6.2 bouyer byte_swapped = 1;
169 1.4.6.2 bouyer }
170 1.4.6.2 bouyer /*
171 1.4.6.2 bouyer * Unroll the loop to make overhead from
172 1.4.6.2 bouyer * branches &c small.
173 1.4.6.2 bouyer */
174 1.4.6.2 bouyer while ((mlen -= 32) >= 0) {
175 1.4.6.2 bouyer sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
176 1.4.6.2 bouyer sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
177 1.4.6.2 bouyer sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
178 1.4.6.2 bouyer sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
179 1.4.6.2 bouyer w += 16;
180 1.4.6.2 bouyer }
181 1.4.6.2 bouyer mlen += 32;
182 1.4.6.2 bouyer while ((mlen -= 8) >= 0) {
183 1.4.6.2 bouyer sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
184 1.4.6.2 bouyer w += 4;
185 1.4.6.2 bouyer }
186 1.4.6.2 bouyer mlen += 8;
187 1.4.6.2 bouyer if (mlen == 0 && byte_swapped == 0)
188 1.4.6.2 bouyer continue;
189 1.4.6.2 bouyer REDUCE;
190 1.4.6.2 bouyer while ((mlen -= 2) >= 0) {
191 1.4.6.2 bouyer sum += *w++;
192 1.4.6.2 bouyer }
193 1.4.6.2 bouyer if (byte_swapped) {
194 1.4.6.2 bouyer REDUCE;
195 1.4.6.2 bouyer sum <<= 8;
196 1.4.6.2 bouyer byte_swapped = 0;
197 1.4.6.2 bouyer if (mlen == -1) {
198 1.4.6.2 bouyer s_util.c[1] = *(u_int8_t *)w;
199 1.4.6.2 bouyer sum += s_util.s;
200 1.4.6.2 bouyer mlen = 0;
201 1.4.6.2 bouyer } else
202 1.4.6.2 bouyer mlen = -1;
203 1.4.6.2 bouyer } else if (mlen == -1)
204 1.4.6.2 bouyer s_util.c[0] = *(u_int8_t *)w;
205 1.4.6.2 bouyer }
206 1.4.6.2 bouyer if (len)
207 1.4.6.2 bouyer printf("cksum4: out of data\n");
208 1.4.6.2 bouyer if (mlen == -1) {
209 1.4.6.2 bouyer /* The last mbuf has odd # of bytes. Follow the
210 1.4.6.2 bouyer standard (the odd byte may be shifted left by 8 bits
211 1.4.6.2 bouyer or not as determined by endian-ness of the machine) */
212 1.4.6.2 bouyer s_util.c[1] = 0;
213 1.4.6.2 bouyer sum += s_util.s;
214 1.4.6.2 bouyer }
215 1.4.6.2 bouyer REDUCE;
216 1.4.6.2 bouyer return (~sum & 0xffff);
217 1.4.6.2 bouyer }
218