summaryrefslogtreecommitdiffstats
path: root/src/checksum.c
blob: 41866ff3b443759e2b1946e92dc55cc2c59e0494 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/* 
 * Extracted from RFC 1071 with some minor changes to fix compilation on GCC,
 * this can probably be improved
 * 					--pablo 11/feb/07
 */

#include <conntrackd.h>

unsigned short do_csum(const void *addr, unsigned int count)
{
	unsigned int sum = 0;

	/* checksumming disabled, just skip */
	if (CONFIG(flags) & DONT_CHECKSUM)
		return 0;

	while(count > 1)  {
		/*  This is the inner loop */
		sum += *((unsigned short *) addr++);
		count -= 2;
	}

	/*  Add left-over byte, if any */
	if(count > 0)
		sum += *((unsigned char *) addr);

	/*  Fold 32-bit sum to 16 bits */
	while (sum>>16)
		sum = (sum & 0xffff) + (sum >> 16);

	return ~sum;
}