NetBSD/external/bsd/tcpdump/dist/in_cksum.c

206 lines
6.6 KiB
C
Raw Normal View History

2013-04-06 21:57:45 +04:00
/* in_cksum.c
* 4.4-Lite-2 Internet checksum routine, modified to take a vector of
* pointers/lengths giving the pieces to be checksummed. Also using
* Tahoe/CGI version of ADDCARRY(x) macro instead of from portable version.
*/
/*
* Copyright (c) 1988, 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 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
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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
* SUCH DAMAGE.
*
* @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
*/
2017-01-25 02:29:13 +03:00
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: in_cksum.c,v 1.2 2017/01/24 23:29:13 christos Exp $");
#endif
2013-04-06 21:57:45 +04:00
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
Tuesday October 25, 2016 mcr@sandelman.ca Summary for 4.8.1 tcpdump release Fix "-x" for Apple PKTAP and PPI packets Use PRIx64 to print a 64-bit number in hex. Printer for HNCP (RFCs 7787 and 7788). dagid is always an IPv6 address, not an opaque 128-bit string, and other fixes to RPL printer. RSVP: Add bounds and length checks OSPF: Do more bounds checking Handle OpenSSL 1.1.x. Initial support for the REdis Serialization Protocol known as RESP. Add printing function for Generic Protocol Extension for VXLAN draft-ietf-nvo3-vxlan-gpe-01 Network Service Header: draft-ietf-sfc-nsh-01 Don't recompile the filter if the new file has the same DLT. Pass an adjusted struct pcap_pkthdr to the sub-printer. Add three test cases for already fixed CVEs CVE-2014-8767: OLSR CVE-2014-8768: Geonet CVE-2014-8769: AODV Don't do the DDP-over-UDP heuristic first: GitHub issue #499. Use the new debugging routines in libpcap. Harmonize TCP source or destination ports tests with UDP ones Introduce data types to use for integral values in packet structures. RSVP: Fix an infinite loop Support of Type 3 and Type 4 LISP packets. Don't require IPv6 library support in order to support IPv6 addresses. Many many changes to support libnetdissect usage. Add a test that makes unaligned accesses: GitHub issue #478. add a DNSSEC test case: GH #445 and GH #467. BGP: add decoding of ADD-PATH capability fixes to LLC header printing, and RFC948-style IP packets Friday April 10, 2015 guy@alum.mit.edu Summary for 4.7.4 tcpdump release RPKI to Router Protocol: Fix Segmentation Faults and other problems RPKI to Router Protocol: print strings with fn_printn() wb: fix some bounds checks
2017-01-25 00:33:37 +03:00
#include <netdissect-stdinc.h>
2013-04-06 21:57:45 +04:00
Tuesday October 25, 2016 mcr@sandelman.ca Summary for 4.8.1 tcpdump release Fix "-x" for Apple PKTAP and PPI packets Use PRIx64 to print a 64-bit number in hex. Printer for HNCP (RFCs 7787 and 7788). dagid is always an IPv6 address, not an opaque 128-bit string, and other fixes to RPL printer. RSVP: Add bounds and length checks OSPF: Do more bounds checking Handle OpenSSL 1.1.x. Initial support for the REdis Serialization Protocol known as RESP. Add printing function for Generic Protocol Extension for VXLAN draft-ietf-nvo3-vxlan-gpe-01 Network Service Header: draft-ietf-sfc-nsh-01 Don't recompile the filter if the new file has the same DLT. Pass an adjusted struct pcap_pkthdr to the sub-printer. Add three test cases for already fixed CVEs CVE-2014-8767: OLSR CVE-2014-8768: Geonet CVE-2014-8769: AODV Don't do the DDP-over-UDP heuristic first: GitHub issue #499. Use the new debugging routines in libpcap. Harmonize TCP source or destination ports tests with UDP ones Introduce data types to use for integral values in packet structures. RSVP: Fix an infinite loop Support of Type 3 and Type 4 LISP packets. Don't require IPv6 library support in order to support IPv6 addresses. Many many changes to support libnetdissect usage. Add a test that makes unaligned accesses: GitHub issue #478. add a DNSSEC test case: GH #445 and GH #467. BGP: add decoding of ADD-PATH capability fixes to LLC header printing, and RFC948-style IP packets Friday April 10, 2015 guy@alum.mit.edu Summary for 4.7.4 tcpdump release RPKI to Router Protocol: Fix Segmentation Faults and other problems RPKI to Router Protocol: print strings with fn_printn() wb: fix some bounds checks
2017-01-25 00:33:37 +03:00
#include "netdissect.h"
2013-04-06 21:57:45 +04:00
/*
* Checksum routine for Internet Protocol family headers (Portable Version).
*
* This routine is very heavily used in the network
* code and should be modified for each CPU to be as fast as possible.
*/
#define ADDCARRY(x) {if ((x) > 65535) (x) -= 65535;}
#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
2014-11-20 04:30:52 +03:00
uint16_t
2013-04-06 21:57:45 +04:00
in_cksum(const struct cksum_vec *vec, int veclen)
{
2014-11-20 04:30:52 +03:00
register const uint16_t *w;
2013-04-06 21:57:45 +04:00
register int sum = 0;
register int mlen = 0;
int byte_swapped = 0;
union {
2014-11-20 04:30:52 +03:00
uint8_t c[2];
uint16_t s;
2013-04-06 21:57:45 +04:00
} s_util;
union {
2014-11-20 04:30:52 +03:00
uint16_t s[2];
uint32_t l;
2013-04-06 21:57:45 +04:00
} l_util;
for (; veclen != 0; vec++, veclen--) {
if (vec->len == 0)
continue;
Tuesday October 25, 2016 mcr@sandelman.ca Summary for 4.8.1 tcpdump release Fix "-x" for Apple PKTAP and PPI packets Use PRIx64 to print a 64-bit number in hex. Printer for HNCP (RFCs 7787 and 7788). dagid is always an IPv6 address, not an opaque 128-bit string, and other fixes to RPL printer. RSVP: Add bounds and length checks OSPF: Do more bounds checking Handle OpenSSL 1.1.x. Initial support for the REdis Serialization Protocol known as RESP. Add printing function for Generic Protocol Extension for VXLAN draft-ietf-nvo3-vxlan-gpe-01 Network Service Header: draft-ietf-sfc-nsh-01 Don't recompile the filter if the new file has the same DLT. Pass an adjusted struct pcap_pkthdr to the sub-printer. Add three test cases for already fixed CVEs CVE-2014-8767: OLSR CVE-2014-8768: Geonet CVE-2014-8769: AODV Don't do the DDP-over-UDP heuristic first: GitHub issue #499. Use the new debugging routines in libpcap. Harmonize TCP source or destination ports tests with UDP ones Introduce data types to use for integral values in packet structures. RSVP: Fix an infinite loop Support of Type 3 and Type 4 LISP packets. Don't require IPv6 library support in order to support IPv6 addresses. Many many changes to support libnetdissect usage. Add a test that makes unaligned accesses: GitHub issue #478. add a DNSSEC test case: GH #445 and GH #467. BGP: add decoding of ADD-PATH capability fixes to LLC header printing, and RFC948-style IP packets Friday April 10, 2015 guy@alum.mit.edu Summary for 4.7.4 tcpdump release RPKI to Router Protocol: Fix Segmentation Faults and other problems RPKI to Router Protocol: print strings with fn_printn() wb: fix some bounds checks
2017-01-25 00:33:37 +03:00
w = (const uint16_t *)(const void *)vec->ptr;
2013-04-06 21:57:45 +04:00
if (mlen == -1) {
/*
* The first byte of this chunk is the continuation
* of a word spanning between this chunk and the
* last chunk.
*
* s_util.c[0] is already saved when scanning previous
* chunk.
*/
2014-11-20 04:30:52 +03:00
s_util.c[1] = *(const uint8_t *)w;
2013-04-06 21:57:45 +04:00
sum += s_util.s;
Tuesday October 25, 2016 mcr@sandelman.ca Summary for 4.8.1 tcpdump release Fix "-x" for Apple PKTAP and PPI packets Use PRIx64 to print a 64-bit number in hex. Printer for HNCP (RFCs 7787 and 7788). dagid is always an IPv6 address, not an opaque 128-bit string, and other fixes to RPL printer. RSVP: Add bounds and length checks OSPF: Do more bounds checking Handle OpenSSL 1.1.x. Initial support for the REdis Serialization Protocol known as RESP. Add printing function for Generic Protocol Extension for VXLAN draft-ietf-nvo3-vxlan-gpe-01 Network Service Header: draft-ietf-sfc-nsh-01 Don't recompile the filter if the new file has the same DLT. Pass an adjusted struct pcap_pkthdr to the sub-printer. Add three test cases for already fixed CVEs CVE-2014-8767: OLSR CVE-2014-8768: Geonet CVE-2014-8769: AODV Don't do the DDP-over-UDP heuristic first: GitHub issue #499. Use the new debugging routines in libpcap. Harmonize TCP source or destination ports tests with UDP ones Introduce data types to use for integral values in packet structures. RSVP: Fix an infinite loop Support of Type 3 and Type 4 LISP packets. Don't require IPv6 library support in order to support IPv6 addresses. Many many changes to support libnetdissect usage. Add a test that makes unaligned accesses: GitHub issue #478. add a DNSSEC test case: GH #445 and GH #467. BGP: add decoding of ADD-PATH capability fixes to LLC header printing, and RFC948-style IP packets Friday April 10, 2015 guy@alum.mit.edu Summary for 4.7.4 tcpdump release RPKI to Router Protocol: Fix Segmentation Faults and other problems RPKI to Router Protocol: print strings with fn_printn() wb: fix some bounds checks
2017-01-25 00:33:37 +03:00
w = (const uint16_t *)(const void *)((const uint8_t *)w + 1);
2013-04-06 21:57:45 +04:00
mlen = vec->len - 1;
} else
mlen = vec->len;
/*
* Force to even boundary.
*/
Tuesday October 25, 2016 mcr@sandelman.ca Summary for 4.8.1 tcpdump release Fix "-x" for Apple PKTAP and PPI packets Use PRIx64 to print a 64-bit number in hex. Printer for HNCP (RFCs 7787 and 7788). dagid is always an IPv6 address, not an opaque 128-bit string, and other fixes to RPL printer. RSVP: Add bounds and length checks OSPF: Do more bounds checking Handle OpenSSL 1.1.x. Initial support for the REdis Serialization Protocol known as RESP. Add printing function for Generic Protocol Extension for VXLAN draft-ietf-nvo3-vxlan-gpe-01 Network Service Header: draft-ietf-sfc-nsh-01 Don't recompile the filter if the new file has the same DLT. Pass an adjusted struct pcap_pkthdr to the sub-printer. Add three test cases for already fixed CVEs CVE-2014-8767: OLSR CVE-2014-8768: Geonet CVE-2014-8769: AODV Don't do the DDP-over-UDP heuristic first: GitHub issue #499. Use the new debugging routines in libpcap. Harmonize TCP source or destination ports tests with UDP ones Introduce data types to use for integral values in packet structures. RSVP: Fix an infinite loop Support of Type 3 and Type 4 LISP packets. Don't require IPv6 library support in order to support IPv6 addresses. Many many changes to support libnetdissect usage. Add a test that makes unaligned accesses: GitHub issue #478. add a DNSSEC test case: GH #445 and GH #467. BGP: add decoding of ADD-PATH capability fixes to LLC header printing, and RFC948-style IP packets Friday April 10, 2015 guy@alum.mit.edu Summary for 4.7.4 tcpdump release RPKI to Router Protocol: Fix Segmentation Faults and other problems RPKI to Router Protocol: print strings with fn_printn() wb: fix some bounds checks
2017-01-25 00:33:37 +03:00
if ((1 & (uintptr_t) w) && (mlen > 0)) {
2013-04-06 21:57:45 +04:00
REDUCE;
sum <<= 8;
2014-11-20 04:30:52 +03:00
s_util.c[0] = *(const uint8_t *)w;
Tuesday October 25, 2016 mcr@sandelman.ca Summary for 4.8.1 tcpdump release Fix "-x" for Apple PKTAP and PPI packets Use PRIx64 to print a 64-bit number in hex. Printer for HNCP (RFCs 7787 and 7788). dagid is always an IPv6 address, not an opaque 128-bit string, and other fixes to RPL printer. RSVP: Add bounds and length checks OSPF: Do more bounds checking Handle OpenSSL 1.1.x. Initial support for the REdis Serialization Protocol known as RESP. Add printing function for Generic Protocol Extension for VXLAN draft-ietf-nvo3-vxlan-gpe-01 Network Service Header: draft-ietf-sfc-nsh-01 Don't recompile the filter if the new file has the same DLT. Pass an adjusted struct pcap_pkthdr to the sub-printer. Add three test cases for already fixed CVEs CVE-2014-8767: OLSR CVE-2014-8768: Geonet CVE-2014-8769: AODV Don't do the DDP-over-UDP heuristic first: GitHub issue #499. Use the new debugging routines in libpcap. Harmonize TCP source or destination ports tests with UDP ones Introduce data types to use for integral values in packet structures. RSVP: Fix an infinite loop Support of Type 3 and Type 4 LISP packets. Don't require IPv6 library support in order to support IPv6 addresses. Many many changes to support libnetdissect usage. Add a test that makes unaligned accesses: GitHub issue #478. add a DNSSEC test case: GH #445 and GH #467. BGP: add decoding of ADD-PATH capability fixes to LLC header printing, and RFC948-style IP packets Friday April 10, 2015 guy@alum.mit.edu Summary for 4.7.4 tcpdump release RPKI to Router Protocol: Fix Segmentation Faults and other problems RPKI to Router Protocol: print strings with fn_printn() wb: fix some bounds checks
2017-01-25 00:33:37 +03:00
w = (const uint16_t *)(const void *)((const uint8_t *)w + 1);
2013-04-06 21:57:45 +04:00
mlen--;
byte_swapped = 1;
}
/*
* Unroll the loop to make overhead from
* branches &c small.
*/
while ((mlen -= 32) >= 0) {
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
w += 16;
}
mlen += 32;
while ((mlen -= 8) >= 0) {
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
w += 4;
}
mlen += 8;
if (mlen == 0 && byte_swapped == 0)
continue;
REDUCE;
while ((mlen -= 2) >= 0) {
sum += *w++;
}
if (byte_swapped) {
REDUCE;
sum <<= 8;
byte_swapped = 0;
if (mlen == -1) {
2014-11-20 04:30:52 +03:00
s_util.c[1] = *(const uint8_t *)w;
2013-04-06 21:57:45 +04:00
sum += s_util.s;
mlen = 0;
} else
mlen = -1;
} else if (mlen == -1)
2014-11-20 04:30:52 +03:00
s_util.c[0] = *(const uint8_t *)w;
2013-04-06 21:57:45 +04:00
}
if (mlen == -1) {
/* The last mbuf has odd # of bytes. Follow the
standard (the odd byte may be shifted left by 8 bits
or not as determined by endian-ness of the machine) */
s_util.c[1] = 0;
sum += s_util.s;
}
REDUCE;
return (~sum & 0xffff);
}
/*
* Given the host-byte-order value of the checksum field in a packet
* header, and the network-byte-order computed checksum of the data
* that the checksum covers (including the checksum itself), compute
* what the checksum field *should* have been.
*/
2014-11-20 04:30:52 +03:00
uint16_t
in_cksum_shouldbe(uint16_t sum, uint16_t computed_sum)
2013-04-06 21:57:45 +04:00
{
2014-11-20 04:30:52 +03:00
uint32_t shouldbe;
2013-04-06 21:57:45 +04:00
/*
* The value that should have gone into the checksum field
* is the negative of the value gotten by summing up everything
* *but* the checksum field.
*
* We can compute that by subtracting the value of the checksum
* field from the sum of all the data in the packet, and then
* computing the negative of that value.
*
* "sum" is the value of the checksum field, and "computed_sum"
* is the negative of the sum of all the data in the packets,
* so that's -(-computed_sum - sum), or (sum + computed_sum).
*
* All the arithmetic in question is one's complement, so the
* addition must include an end-around carry; we do this by
* doing the arithmetic in 32 bits (with no sign-extension),
* and then adding the upper 16 bits of the sum, which contain
* the carry, to the lower 16 bits of the sum, and then do it
* again in case *that* sum produced a carry.
*
* As RFC 1071 notes, the checksum can be computed without
* byte-swapping the 16-bit words; summing 16-bit words
* on a big-endian machine gives a big-endian checksum, which
* can be directly stuffed into the big-endian checksum fields
* in protocol headers, and summing words on a little-endian
* machine gives a little-endian checksum, which must be
* byte-swapped before being stuffed into a big-endian checksum
* field.
*
* "computed_sum" is a network-byte-order value, so we must put
* it in host byte order before subtracting it from the
* host-byte-order value from the header; the adjusted checksum
* will be in host byte order, which is what we'll return.
*/
shouldbe = sum;
shouldbe += ntohs(computed_sum);
shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16);
shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16);
return shouldbe;
}