2008-02-12 16:05:55 +03:00
|
|
|
/* $NetBSD: in6_cksum.c,v 1.24 2008/02/12 13:05:55 joerg Exp $ */
|
1999-07-04 01:24:45 +04:00
|
|
|
|
2008-02-12 16:02:24 +03:00
|
|
|
/*-
|
|
|
|
* Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>.
|
1999-06-28 10:36:47 +04:00
|
|
|
* All rights reserved.
|
2000-09-09 15:42:22 +04:00
|
|
|
*
|
1999-06-28 10:36:47 +04:00
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
2000-09-09 15:42:22 +04:00
|
|
|
*
|
1999-06-28 10:36:47 +04:00
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
2008-02-12 16:02:24 +03:00
|
|
|
* notice, this list of conditions and the following disclaimer in
|
|
|
|
* the documentation and/or other materials provided with the
|
|
|
|
* distribution.
|
1999-06-28 10:36:47 +04:00
|
|
|
*
|
2008-02-12 16:02:24 +03:00
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
|
|
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
|
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
|
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
|
|
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
1999-06-28 10:36:47 +04:00
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2001-11-13 03:56:55 +03:00
|
|
|
#include <sys/cdefs.h>
|
2008-02-12 16:05:55 +03:00
|
|
|
__KERNEL_RCSID(0, "$NetBSD: in6_cksum.c,v 1.24 2008/02/12 13:05:55 joerg Exp $");
|
2001-11-13 03:56:55 +03:00
|
|
|
|
1999-06-28 10:36:47 +04:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/mbuf.h>
|
|
|
|
#include <netinet/in.h>
|
2000-02-06 15:49:37 +03:00
|
|
|
#include <netinet/ip6.h>
|
1999-12-13 18:17:17 +03:00
|
|
|
|
1999-06-28 10:36:47 +04:00
|
|
|
/*
|
2008-02-12 16:02:24 +03:00
|
|
|
* Checksum of the IPv6 pseudo header.
|
1999-06-28 10:36:47 +04:00
|
|
|
*
|
2008-02-12 16:02:24 +03:00
|
|
|
* off is supposed to be the skipped IPv6 header, len is the payload size.
|
1999-06-28 10:36:47 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
2008-02-12 16:02:24 +03:00
|
|
|
in6_cksum(struct mbuf *m, u_int8_t nxt, uint32_t off, uint32_t len)
|
1999-06-28 10:36:47 +04:00
|
|
|
{
|
2000-09-09 20:15:47 +04:00
|
|
|
union {
|
2008-02-12 16:02:24 +03:00
|
|
|
uint16_t words[16];
|
2000-09-09 20:15:47 +04:00
|
|
|
struct {
|
2008-02-12 16:02:24 +03:00
|
|
|
struct in6_addr ip6_src;
|
|
|
|
struct in6_addr ip6_dst;
|
|
|
|
} addrs;
|
|
|
|
} u;
|
|
|
|
struct in6_addr *in6_src, *in6_dst;
|
|
|
|
uint32_t sum;
|
|
|
|
uint16_t *w;
|
|
|
|
|
2008-02-12 16:05:55 +03:00
|
|
|
if (__predict_false(off < sizeof(struct ip6_hdr)))
|
2008-02-12 16:02:24 +03:00
|
|
|
panic("in6_cksum: offset too short for IPv6 header");
|
2008-02-12 16:05:55 +03:00
|
|
|
if (__predict_false(m->m_len < sizeof(struct ip6_hdr)))
|
2008-02-12 16:02:24 +03:00
|
|
|
panic("in6_cksum: mbuf too short for IPv6 header");
|
1999-06-28 10:36:47 +04:00
|
|
|
|
2001-05-30 07:06:56 +04:00
|
|
|
if (nxt == 0)
|
2008-02-12 16:02:24 +03:00
|
|
|
return cpu_in_cksum(m, len, off, 0);
|
1999-06-28 10:36:47 +04:00
|
|
|
|
Better support of IPv6 scoped addresses.
- most of the kernel code will not care about the actual encoding of
scope zone IDs and won't touch "s6_addr16[1]" directly.
- similarly, most of the kernel code will not care about link-local
scoped addresses as a special case.
- scope boundary check will be stricter. For example, the current
*BSD code allows a packet with src=::1 and dst=(some global IPv6
address) to be sent outside of the node, if the application do:
s = socket(AF_INET6);
bind(s, "::1");
sendto(s, some_global_IPv6_addr);
This is clearly wrong, since ::1 is only meaningful within a single
node, but the current implementation of the *BSD kernel cannot
reject this attempt.
- and, while there, don't try to remove the ff02::/32 interface route
entry in in6_ifdetach() as it's already gone.
This also includes some level of support for the standard source
address selection algorithm defined in RFC3484, which will be
completed on in the future.
From the KAME project via JINMEI Tatuya.
Approved by core@.
2006-01-21 03:15:35 +03:00
|
|
|
/*
|
2008-02-12 16:02:24 +03:00
|
|
|
* Compute the equivalent of:
|
|
|
|
* struct ip6_hdr_pseudo ip6;
|
|
|
|
*
|
|
|
|
* bzero(sizeof(*ip6));
|
|
|
|
* ip6.ip6ph_nxt = nxt;
|
|
|
|
* ip6.ip6ph_len = htonl(len);
|
|
|
|
* ipv6.ip6ph_src = mtod(m, struct ip6_hdr *)->ip6_src;
|
|
|
|
* in6_clearscope(&ip6->ip6ph_src);
|
|
|
|
* ipv6.ip6ph_dst = mtod(m, struct ip6_hdr *)->ip6_dst;
|
|
|
|
* in6_clearscope(&ip6->ip6ph_dst);
|
|
|
|
* sum = one_add(&ip6);
|
Better support of IPv6 scoped addresses.
- most of the kernel code will not care about the actual encoding of
scope zone IDs and won't touch "s6_addr16[1]" directly.
- similarly, most of the kernel code will not care about link-local
scoped addresses as a special case.
- scope boundary check will be stricter. For example, the current
*BSD code allows a packet with src=::1 and dst=(some global IPv6
address) to be sent outside of the node, if the application do:
s = socket(AF_INET6);
bind(s, "::1");
sendto(s, some_global_IPv6_addr);
This is clearly wrong, since ::1 is only meaningful within a single
node, but the current implementation of the *BSD kernel cannot
reject this attempt.
- and, while there, don't try to remove the ff02::/32 interface route
entry in in6_ifdetach() as it's already gone.
This also includes some level of support for the standard source
address selection algorithm defined in RFC3484, which will be
completed on in the future.
From the KAME project via JINMEI Tatuya.
Approved by core@.
2006-01-21 03:15:35 +03:00
|
|
|
*/
|
|
|
|
|
2008-02-12 16:02:24 +03:00
|
|
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
|
|
|
sum = ((len & 0xffff) + ((len >> 16) & 0xffff) + nxt) << 8;
|
|
|
|
#else
|
|
|
|
sum = (len & 0xffff) + ((len >> 16) & 0xffff) + nxt;
|
|
|
|
#endif
|
|
|
|
w = (uint16_t *)(mtod(m, char *) + offsetof(struct ip6_hdr, ip6_src));
|
|
|
|
if (__predict_true((uintptr_t)w % 2 == 0)) {
|
|
|
|
in6_src = &mtod(m, struct ip6_hdr *)->ip6_src;
|
|
|
|
in6_dst = &mtod(m, struct ip6_hdr *)->ip6_dst;
|
|
|
|
} else {
|
|
|
|
memcpy(&u, &mtod(m, struct ip6_hdr *)->ip6_src, 32);
|
|
|
|
w = u.words;
|
|
|
|
in6_src = &u.addrs.ip6_src;
|
|
|
|
in6_dst = &u.addrs.ip6_dst;
|
|
|
|
}
|
Better support of IPv6 scoped addresses.
- most of the kernel code will not care about the actual encoding of
scope zone IDs and won't touch "s6_addr16[1]" directly.
- similarly, most of the kernel code will not care about link-local
scoped addresses as a special case.
- scope boundary check will be stricter. For example, the current
*BSD code allows a packet with src=::1 and dst=(some global IPv6
address) to be sent outside of the node, if the application do:
s = socket(AF_INET6);
bind(s, "::1");
sendto(s, some_global_IPv6_addr);
This is clearly wrong, since ::1 is only meaningful within a single
node, but the current implementation of the *BSD kernel cannot
reject this attempt.
- and, while there, don't try to remove the ff02::/32 interface route
entry in in6_ifdetach() as it's already gone.
This also includes some level of support for the standard source
address selection algorithm defined in RFC3484, which will be
completed on in the future.
From the KAME project via JINMEI Tatuya.
Approved by core@.
2006-01-21 03:15:35 +03:00
|
|
|
|
2008-02-12 16:02:24 +03:00
|
|
|
sum += w[0];
|
|
|
|
if (!IN6_IS_SCOPE_LINKLOCAL(in6_src) &&
|
|
|
|
!IN6_IS_ADDR_MC_INTFACELOCAL(in6_src))
|
|
|
|
sum += w[1];
|
|
|
|
sum += w[2];
|
|
|
|
sum += w[3];
|
|
|
|
sum += w[4];
|
|
|
|
sum += w[5];
|
|
|
|
sum += w[6];
|
|
|
|
sum += w[7];
|
|
|
|
w += 8;
|
|
|
|
sum += w[0];
|
|
|
|
if (!IN6_IS_SCOPE_LINKLOCAL(in6_dst) &&
|
|
|
|
!IN6_IS_ADDR_MC_INTFACELOCAL(in6_dst))
|
|
|
|
sum += w[1];
|
|
|
|
sum += w[2];
|
|
|
|
sum += w[3];
|
|
|
|
sum += w[4];
|
|
|
|
sum += w[5];
|
|
|
|
sum += w[6];
|
|
|
|
sum += w[7];
|
1999-06-28 10:36:47 +04:00
|
|
|
|
2008-01-26 00:12:10 +03:00
|
|
|
return cpu_in_cksum(m, len, off, sum);
|
1999-06-28 10:36:47 +04:00
|
|
|
}
|