

Please wait until the page is fully downloaded and then press the "Expand" button or the blue line numbers.
0105000 /* oneC_sum() - One complement's checksum Author: Kees J. Bot
0105001 * 8 May 1995
0105002 * See RFC 1071, "Computing the Internet checksum"
0105003 */
0105004
0105005 #include <sys/types.h>
0105006 #include <net/gen/oneCsum.h>
0105007
0105008 u16_t oneC_sum(U16_t prev, void *data, size_t size)
0105009 {
0105010 u8_t *dptr;
0105011 size_t n;
0105012 u16_t word;
0105013 u32_t sum;
0105014 int swap= 0;
0105015
0105016 sum= prev;
0105017 dptr= data;
0105018 n= size;
0105019
0105020 swap= ((size_t) dptr & 1);
0105021 if (swap) {
0105022 sum= ((sum & 0xFF) << 8) | ((sum & 0xFF00) >> 8);
0105023 if (n > 0) {
0105024 ((u8_t *) &word)[0]= 0;
0105025 ((u8_t *) &word)[1]= dptr[0];
0105026 sum+= (u32_t) word;
0105027 dptr+= 1;
0105028 n-= 1;
0105029 }
0105030 }
0105031
0105032 while (n >= 8) {
0105033 sum+= (u32_t) ((u16_t *) dptr)[0]
0105034 + (u32_t) ((u16_t *) dptr)[1]
0105035 + (u32_t) ((u16_t *) dptr)[2]
0105036 + (u32_t) ((u16_t *) dptr)[3];
0105037 dptr+= 8;
0105038 n-= 8;
0105039 }
0105040
0105041 while (n >= 2) {
0105042 sum+= (u32_t) ((u16_t *) dptr)[0];
0105043 dptr+= 2;
0105044 n-= 2;
0105045 }
0105046
0105047 if (n > 0) {
0105048 ((u8_t *) &word)[0]= dptr[0];
0105049 ((u8_t *) &word)[1]= 0;
0105050 sum+= (u32_t) word;
0105051 }
0105052
0105053 sum= (sum & 0xFFFF) + (sum >> 16);
0105054 if (sum > 0xFFFF) sum++;
0105055
0105056 if (swap) {
0105057 sum= ((sum & 0xFF) << 8) | ((sum & 0xFF00) >> 8);
0105058 }
0105059 return sum;
0105060 }
A checksum is used to determine if errors occurred during the transmission of data. The checksum algorithm used by oneC_sum() (which is also the Internet standard) is described by RFC 1071.
Essentially, the algorithm goes through data and adds all the bytes together (using one's complement addition). The high 16 bits of the resulting 32 bit value is then added to the low 16 bits (again, using one's complement addition). The checksum field is then set to the one's complement of this 16 bit sum. (Recall that the one's complement of 0xF0F0 is 0x0F0F.) Since AND'ing any 16 bit number and its 16 bit one's complement will equal 0xFFFF, the checksum of the packet (without the checksum field) AND'ed with the checksum field will equal 0xFFFF (provided the packet was not corrupted after the checksum field was calculated). For example, the checksum of a udp header (including the checksum field) will equal 0xFFFF if the packet was not corrupted in delivery.
From RFC 1071:
In outline, the Internet checksum algorithm is fairly simple:
(1) Adjacent octets to be checksummed are paired to form 16-bit
integers, and the 1's complement sum of these 16-bit integers is
formed.
(2) To generate a checksum, the checksum field itself is cleared,
the 16-bit 1's complement sum is computed over the octets
concerned, and the 1's complement of this sum is placed in the
checksum field.
(3) To check a checksum, the 1's complement sum is computed over the
same set of octets, including the checksum field. If the result
is all 1 bits (-0 in 1's complement arithmetic), the check
succeeds.
Below is a "C" code algorithm that describes the process above. This algorithm is also from RFC 1071. Note that count is the running count of all the bytes in the data and checksum is the return value.