doc: new fedora/rhel maintainer
[netsniff-ng.git] / src / csum.h
blob5d54ef8a6e50453345994aea367ee467e4ee7832
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2010 Emmanuel Roullit.
5 * Subject to the GPL, version 2.
6 */
8 #ifndef CSUM_H
9 #define CSUM_H
11 #include <netinet/in.h> /* for htons() */
13 /* Shamelessly taken and adapted from tcpdump */
16 * Compute an IP header checksum.
17 * Don't modifiy the packet.
19 static inline uint16_t calc_csum(void *addr, size_t len, int csum)
21 int nleft = len;
22 int sum = csum;
23 uint16_t answer;
24 const uint16_t *w = (const uint16_t *) addr;
27 * Our algorithm is simple, using a 32 bit accumulator (sum),
28 * we add sequential 16 bit words to it, and at the end, fold
29 * back all the carry bits from the top 16 bits into the lower
30 * 16 bits.
32 while (nleft > 1) {
33 sum += *w++;
34 nleft -= 2;
37 if (nleft == 1)
38 sum += htons(*(const uint8_t *) w << 8);
41 * Add back carry outs from top 16 bits to low 16 bits
43 sum = (sum >> 16) + (sum & 0xFFFF); /* add hi 16 to low 16 */
44 sum += (sum >> 16); /* add carry */
45 answer = ~sum; /* truncate to 16 bits */
47 return answer;
51 * Given the host-byte-order value of the checksum field in a packet
52 * header, and the network-byte-order computed checksum of the data
53 * that the checksum covers (including the checksum itself), compute
54 * what the checksum field *should* have been.
56 static inline uint16_t csum_expected(uint16_t sum, uint16_t computed_sum)
58 uint32_t shouldbe;
61 * The value that should have gone into the checksum field
62 * is the negative of the value gotten by summing up everything
63 * *but* the checksum field.
65 * We can compute that by subtracting the value of the checksum
66 * field from the sum of all the data in the packet, and then
67 * computing the negative of that value.
69 * "sum" is the value of the checksum field, and "computed_sum"
70 * is the negative of the sum of all the data in the packets,
71 * so that's -(-computed_sum - sum), or (sum + computed_sum).
73 * All the arithmetic in question is one's complement, so the
74 * addition must include an end-around carry; we do this by
75 * doing the arithmetic in 32 bits (with no sign-extension),
76 * and then adding the upper 16 bits of the sum, which contain
77 * the carry, to the lower 16 bits of the sum, and then do it
78 * again in case *that* sum produced a carry.
80 * As RFC 1071 notes, the checksum can be computed without
81 * byte-swapping the 16-bit words; summing 16-bit words
82 * on a big-endian machine gives a big-endian checksum, which
83 * can be directly stuffed into the big-endian checksum fields
84 * in protocol headers, and summing words on a little-endian
85 * machine gives a little-endian checksum, which must be
86 * byte-swapped before being stuffed into a big-endian checksum
87 * field.
89 * "computed_sum" is a network-byte-order value, so we must put
90 * it in host byte order before subtracting it from the
91 * host-byte-order value from the header; the adjusted checksum
92 * will be in host byte order, which is what we'll return.
95 shouldbe = sum;
96 shouldbe += ntohs(computed_sum);
97 shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16);
98 shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16);
100 return shouldbe;
103 static inline uint16_t tcp_sum_calc(uint16_t len_tcp, uint16_t src_addr[],
104 uint16_t dest_addr[], uint8_t padding,
105 uint16_t buff[])
107 uint32_t i;
108 uint16_t padd = 0;
109 uint16_t word16;
110 uint32_t sum = 0;
111 uint16_t prot_tcp = IPPROTO_TCP;
114 * Find out if the length of data is even or odd number. If odd,
115 * add a padding byte = 0 at the end of packet.
117 if ((padding & 1) == 1) {
118 padd = 1;
119 buff[len_tcp] = 0;
123 * Make 16 bit words out of every two adjacent 8 bit words and
124 * calculate the sum of all 16 vit words.
126 for (i = 0; i < len_tcp + padd; i = i + 2) {
127 word16 = ((buff[i] << 8) & 0xFF00) + (buff[i + 1] & 0xFF);
128 sum += (unsigned long) word16;
132 * Add the TCP pseudo header which contains: the IP source and
133 * destinationn addresses.
135 for (i = 0; i < 4; i = i + 2) {
136 word16 = ((src_addr[i] << 8) & 0xFF00) +
137 (src_addr[i + 1] & 0xFF);
138 sum += word16;
141 for (i = 0; i < 4; i = i + 2) {
142 word16 = ((dest_addr[i] << 8) & 0xFF00) +
143 (dest_addr[i + 1] & 0xFF);
144 sum += word16;
147 /* The protocol number and the length of the TCP packet. */
148 sum += (prot_tcp + len_tcp);
151 * Keep only the last 16 bits of the 32 bit calculated sum and
152 * add the carries.
154 while (sum >> 16)
155 sum = (sum & 0xFFFF) + (sum >> 16);
157 /* Take the one's complement of sum. */
158 sum = ~sum;
160 return (uint16_t) sum;
163 #endif /* CSUM_H */