blob: fee8648f3fca9649dd67349b376bddba872df7a0 [file] [log] [blame]
Baruch Siache8f36332011-09-07 17:52:37 +02001/*
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
Denys Vlasenko4a0eb032020-10-01 03:07:22 +02009uint16_t FAST_FUNC inet_cksum(const void *ptr, int nleft)
Baruch Siache8f36332011-09-07 17:52:37 +020010{
Denys Vlasenko4a0eb032020-10-01 03:07:22 +020011 const uint16_t *addr = ptr;
12
Baruch Siache8f36332011-09-07 17:52:37 +020013 /*
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 */
Denys Vlasenko0d0260f2011-09-08 10:59:26 +020026 if (nleft == 1) {
27 if (BB_LITTLE_ENDIAN)
28 sum += *(uint8_t*)addr;
29 else
30 sum += *(uint8_t*)addr << 8;
31 }
Baruch Siache8f36332011-09-07 17:52:37 +020032
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}