1/* 2 * Copyright (c) 2009-2011 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29/* 30 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 31 * All rights reserved. 32 * 33 * Redistribution and use in source and binary forms, with or without 34 * modification, are permitted provided that the following conditions 35 * are met: 36 * 1. Redistributions of source code must retain the above copyright 37 * notice, this list of conditions and the following disclaimer. 38 * 2. Redistributions in binary form must reproduce the above copyright 39 * notice, this list of conditions and the following disclaimer in the 40 * documentation and/or other materials provided with the distribution. 41 * 3. Neither the name of the project nor the names of its contributors 42 * may be used to endorse or promote products derived from this software 43 * without specific prior written permission. 44 * 45 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55 * SUCH DAMAGE. 56 */ 57 58/* 59 * Copyright (c) 1988, 1992, 1993 60 * The Regents of the University of California. All rights reserved. 61 * 62 * Redistribution and use in source and binary forms, with or without 63 * modification, are permitted provided that the following conditions 64 * are met: 65 * 1. Redistributions of source code must retain the above copyright 66 * notice, this list of conditions and the following disclaimer. 67 * 2. Redistributions in binary form must reproduce the above copyright 68 * notice, this list of conditions and the following disclaimer in the 69 * documentation and/or other materials provided with the distribution. 70 * 3. All advertising materials mentioning features or use of this software 71 * must display the following acknowledgement: 72 * This product includes software developed by the University of 73 * California, Berkeley and its contributors. 74 * 4. Neither the name of the University nor the names of its contributors 75 * may be used to endorse or promote products derived from this software 76 * without specific prior written permission. 77 * 78 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 79 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 80 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 81 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 82 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 83 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 84 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 85 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 86 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 87 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 88 * SUCH DAMAGE. 89 * 90 * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93 91 */ 92 93/*- 94 * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>. 95 * All rights reserved. 96 * 97 * Redistribution and use in source and binary forms, with or without 98 * modification, are permitted provided that the following conditions 99 * are met: 100 * 101 * 1. Redistributions of source code must retain the above copyright 102 * notice, this list of conditions and the following disclaimer. 103 * 2. Redistributions in binary form must reproduce the above copyright 104 * notice, this list of conditions and the following disclaimer in 105 * the documentation and/or other materials provided with the 106 * distribution. 107 * 108 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 109 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 110 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 111 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 112 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 113 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 114 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 115 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 116 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 117 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 118 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 119 * SUCH DAMAGE. 120 */ 121 122#include <sys/param.h> 123#include <sys/mbuf.h> 124#include <sys/systm.h> 125#include <kern/debug.h> 126#include <netinet/in.h> 127#include <netinet/ip6.h> 128 129#include <net/net_osdep.h> 130 131#include <machine/endian.h> 132 133 134 135/* 136 * Checksum routine for Internet Protocol family headers (Portable Version). 137 * 138 * This routine is very heavily used in the network 139 * code and should be modified for each CPU to be as fast as possible. 140 */ 141 142#define ADDCARRY(x) do { if (x > 65535) { x -= 65535; } } while (0) 143#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);} 144 145/* 146 * m MUST contain a continuous IP6 header. 147 * off is a offset where TCP/UDP/ICMP6 header starts. 148 * len is a total length of a transport segment. 149 * (e.g. TCP header + TCP payload) 150 */ 151 152u_int16_t 153inet6_cksum(struct mbuf *m, unsigned int nxt, unsigned int off, 154 unsigned int len) 155{ 156 u_int16_t *w; 157 int sum = 0; 158 int mlen = 0; 159 int byte_swapped = 0; 160 struct ip6_hdr *ip6; 161 union { 162 u_int16_t phs[4]; 163 struct { 164 u_int32_t ph_len; 165 u_int8_t ph_zero[3]; 166 u_int8_t ph_nxt; 167 } ph __attribute__((__packed__)); 168 } uph; 169 union { 170 u_int8_t c[2]; 171 u_int16_t s; 172 } s_util; 173 union { 174 u_int16_t s[2]; 175 u_int32_t l; 176 } l_util; 177 178 /* sanity check */ 179 if ((m->m_flags & M_PKTHDR) && m->m_pkthdr.len < off + len) { 180 panic("inet6_cksum: mbuf len (%d) < off+len (%d+%d)\n", 181 m->m_pkthdr.len, off, len); 182 } 183 184 if (nxt != 0) { 185 bzero(&uph, sizeof (uph)); 186 187 /* 188 * First create IP6 pseudo header and calculate a summary. 189 */ 190 ip6 = mtod(m, struct ip6_hdr *); 191 w = (u_int16_t *)&ip6->ip6_src; 192 uph.ph.ph_len = htonl(len); 193 uph.ph.ph_nxt = nxt; 194 195 /* IPv6 source address */ 196 sum += w[0]; 197 if (!IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) 198 sum += w[1]; 199 sum += w[2]; sum += w[3]; sum += w[4]; sum += w[5]; 200 sum += w[6]; sum += w[7]; 201 /* IPv6 destination address */ 202 sum += w[8]; 203 if (!IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) 204 sum += w[9]; 205 sum += w[10]; sum += w[11]; sum += w[12]; sum += w[13]; 206 sum += w[14]; sum += w[15]; 207 /* Payload length and upper layer identifier */ 208 sum += uph.phs[0]; sum += uph.phs[1]; 209 sum += uph.phs[2]; sum += uph.phs[3]; 210 } 211 212 /* 213 * Secondly calculate a summary of the first mbuf excluding offset. 214 */ 215 while (m != NULL && off > 0) { 216 if (m->m_len <= off) 217 off -= m->m_len; 218 else 219 break; 220 m = m->m_next; 221 } 222 w = (u_int16_t *)(void *)(mtod(m, u_char *) + off); 223 mlen = m->m_len - off; 224 if (len < mlen) 225 mlen = len; 226 len -= mlen; 227 /* 228 * Force to even boundary. 229 */ 230 if ((1 & (intptr_t) w) && (mlen > 0)) { 231 REDUCE; 232 sum <<= 8; 233 s_util.c[0] = *(u_char *)w; 234 w = (u_int16_t *)(void *)((char *)w + 1); 235 mlen--; 236 byte_swapped = 1; 237 } 238 /* 239 * Unroll the loop to make overhead from 240 * branches &c small. 241 */ 242 while ((mlen -= 32) >= 0) { 243 sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 244 sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; 245 sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11]; 246 sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; 247 w += 16; 248 } 249 mlen += 32; 250 while ((mlen -= 8) >= 0) { 251 sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 252 w += 4; 253 } 254 mlen += 8; 255 if (mlen == 0 && byte_swapped == 0) 256 goto next; 257 REDUCE; 258 while ((mlen -= 2) >= 0) { 259 sum += *w++; 260 } 261 if (byte_swapped) { 262 REDUCE; 263 sum <<= 8; 264 byte_swapped = 0; 265 if (mlen == -1) { 266 s_util.c[1] = *(char *)w; 267 sum += s_util.s; 268 mlen = 0; 269 } else 270 mlen = -1; 271 } else if (mlen == -1) 272 s_util.c[0] = *(char *)w; 273 next: 274 m = m->m_next; 275 276 /* 277 * Lastly calculate a summary of the rest of mbufs. 278 */ 279 280 for (;m && len; m = m->m_next) { 281 if (m->m_len == 0) 282 continue; 283 w = mtod(m, u_int16_t *); 284 if (mlen == -1) { 285 /* 286 * The first byte of this mbuf is the continuation 287 * of a word spanning between this mbuf and the 288 * last mbuf. 289 * 290 * s_util.c[0] is already saved when scanning previous 291 * mbuf. 292 */ 293 s_util.c[1] = *(char *)w; 294 sum += s_util.s; 295 w = (u_int16_t *)(void *)((char *)w + 1); 296 mlen = m->m_len - 1; 297 len--; 298 } else 299 mlen = m->m_len; 300 if (len < mlen) 301 mlen = len; 302 len -= mlen; 303 /* 304 * Force to even boundary. 305 */ 306 if ((1 & (intptr_t) w) && (mlen > 0)) { 307 REDUCE; 308 sum <<= 8; 309 s_util.c[0] = *(u_char *)w; 310 w = (u_int16_t *)(void *)((char *)w + 1); 311 mlen--; 312 byte_swapped = 1; 313 } 314 /* 315 * Unroll the loop to make overhead from 316 * branches &c small. 317 */ 318 while ((mlen -= 32) >= 0) { 319 sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 320 sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; 321 sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11]; 322 sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; 323 w += 16; 324 } 325 mlen += 32; 326 while ((mlen -= 8) >= 0) { 327 sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 328 w += 4; 329 } 330 mlen += 8; 331 if (mlen == 0 && byte_swapped == 0) 332 continue; 333 REDUCE; 334 while ((mlen -= 2) >= 0) { 335 sum += *w++; 336 } 337 if (byte_swapped) { 338 REDUCE; 339 sum <<= 8; 340 byte_swapped = 0; 341 if (mlen == -1) { 342 s_util.c[1] = *(char *)w; 343 sum += s_util.s; 344 mlen = 0; 345 } else 346 mlen = -1; 347 } else if (mlen == -1) 348 s_util.c[0] = *(char *)w; 349 } 350 if (len) 351 printf("inet6_cksum: out of data by %d\n", len); 352 if (mlen == -1) { 353 /* The last mbuf has odd # of bytes. Follow the 354 standard (the odd byte may be shifted left by 8 bits 355 or not as determined by endian-ness of the machine) */ 356 s_util.c[1] = 0; 357 sum += s_util.s; 358 } 359 REDUCE; 360 return (~sum & 0xffff); 361} 362 363