1 /*
2  * Checksum routine for Internet Protocol family headers (C Version)
3  *
4  * Licensed under GPLv2, see file LICENSE in this source tree.
5  */
6 
7 #include "libbb.h"
8 
inet_cksum(const void * ptr,int nleft)9 uint16_t FAST_FUNC inet_cksum(const void *ptr, int nleft)
10 {
11 	const uint16_t *addr = ptr;
12 
13 	/*
14 	 * Our algorithm is simple, using a 32 bit accumulator,
15 	 * we add sequential 16 bit words to it, and at the end, fold
16 	 * back all the carry bits from the top 16 bits into the lower
17 	 * 16 bits.
18 	 */
19 	unsigned sum = 0;
20 	while (nleft > 1) {
21 		sum += *addr++;
22 		nleft -= 2;
23 	}
24 
25 	/* Mop up an odd byte, if necessary */
26 	if (nleft == 1) {
27 		if (BB_LITTLE_ENDIAN)
28 			sum += *(uint8_t*)addr;
29 		else
30 			sum += *(uint8_t*)addr << 8;
31 	}
32 
33 	/* Add back carry outs from top 16 bits to low 16 bits */
34 	sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
35 	sum += (sum >> 16);                     /* add carry */
36 
37 	return (uint16_t)~sum;
38 }
39