docs: added project to PROJECTS file
[netsniff-ng.git] / src / csum.h
bloba90d3221875045ae429f3f499ffd3f7ee11d1fd7
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2009, 2010 Daniel Borkmann.
5 * Copyright 2010 Emmanuel Roullit.
6 * Subject to the GPL, version 2.
7 */
9 #ifndef CSUM_H
10 #define CSUM_H
12 #include <netinet/in.h> /* for htons() */
14 /* Shamelessly taken and adapted from tcpdump */
17 * Compute an IP header checksum.
18 * Don't modifiy the packet.
20 static inline uint16_t calc_csum(void *addr, size_t len, int csum)
22 int nleft = len;
23 int sum = csum;
24 uint16_t answer;
25 const uint16_t *w = (const uint16_t *) addr;
28 * Our algorithm is simple, using a 32 bit accumulator (sum),
29 * we add sequential 16 bit words to it, and at the end, fold
30 * back all the carry bits from the top 16 bits into the lower
31 * 16 bits.
33 while (nleft > 1) {
34 sum += *w++;
35 nleft -= 2;
38 if (nleft == 1)
39 sum += htons(*(const uint8_t *) w << 8);
42 * Add back carry outs from top 16 bits to low 16 bits
44 sum = (sum >> 16) + (sum & 0xFFFF); /* add hi 16 to low 16 */
45 sum += (sum >> 16); /* add carry */
46 answer = ~sum; /* truncate to 16 bits */
48 return answer;
52 * Given the host-byte-order value of the checksum field in a packet
53 * header, and the network-byte-order computed checksum of the data
54 * that the checksum covers (including the checksum itself), compute
55 * what the checksum field *should* have been.
57 static inline uint16_t csum_expected(uint16_t sum, uint16_t computed_sum)
59 uint32_t shouldbe;
62 * The value that should have gone into the checksum field
63 * is the negative of the value gotten by summing up everything
64 * *but* the checksum field.
66 * We can compute that by subtracting the value of the checksum
67 * field from the sum of all the data in the packet, and then
68 * computing the negative of that value.
70 * "sum" is the value of the checksum field, and "computed_sum"
71 * is the negative of the sum of all the data in the packets,
72 * so that's -(-computed_sum - sum), or (sum + computed_sum).
74 * All the arithmetic in question is one's complement, so the
75 * addition must include an end-around carry; we do this by
76 * doing the arithmetic in 32 bits (with no sign-extension),
77 * and then adding the upper 16 bits of the sum, which contain
78 * the carry, to the lower 16 bits of the sum, and then do it
79 * again in case *that* sum produced a carry.
81 * As RFC 1071 notes, the checksum can be computed without
82 * byte-swapping the 16-bit words; summing 16-bit words
83 * on a big-endian machine gives a big-endian checksum, which
84 * can be directly stuffed into the big-endian checksum fields
85 * in protocol headers, and summing words on a little-endian
86 * machine gives a little-endian checksum, which must be
87 * byte-swapped before being stuffed into a big-endian checksum
88 * field.
90 * "computed_sum" is a network-byte-order value, so we must put
91 * it in host byte order before subtracting it from the
92 * host-byte-order value from the header; the adjusted checksum
93 * will be in host byte order, which is what we'll return.
96 shouldbe = sum;
97 shouldbe += ntohs(computed_sum);
98 shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16);
99 shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16);
101 return shouldbe;
104 static inline uint16_t tcp_sum_calc(uint16_t len_tcp, uint16_t src_addr[],
105 uint16_t dest_addr[], uint8_t padding,
106 uint16_t buff[])
108 uint32_t i;
109 uint16_t padd = 0;
110 uint16_t word16;
111 uint32_t sum = 0;
112 uint16_t prot_tcp = IPPROTO_TCP;
115 * Find out if the length of data is even or odd number. If odd,
116 * add a padding byte = 0 at the end of packet.
118 if ((padding & 1) == 1) {
119 padd = 1;
120 buff[len_tcp] = 0;
124 * Make 16 bit words out of every two adjacent 8 bit words and
125 * calculate the sum of all 16 vit words.
127 for (i = 0; i < len_tcp + padd; i = i + 2) {
128 word16 = ((buff[i] << 8) & 0xFF00) + (buff[i + 1] & 0xFF);
129 sum += (unsigned long) word16;
133 * Add the TCP pseudo header which contains: the IP source and
134 * destinationn addresses.
136 for (i = 0; i < 4; i = i + 2) {
137 word16 = ((src_addr[i] << 8) & 0xFF00) +
138 (src_addr[i + 1] & 0xFF);
139 sum += word16;
142 for (i = 0; i < 4; i = i + 2) {
143 word16 = ((dest_addr[i] << 8) & 0xFF00) +
144 (dest_addr[i + 1] & 0xFF);
145 sum += word16;
148 /* The protocol number and the length of the TCP packet. */
149 sum += (prot_tcp + len_tcp);
152 * Keep only the last 16 bits of the 32 bit calculated sum and
153 * add the carries.
155 while (sum >> 16)
156 sum = (sum & 0xFFFF) + (sum >> 16);
158 /* Take the one's complement of sum. */
159 sum = ~sum;
161 return (uint16_t) sum;
164 #endif /* CSUM_H */