diff options
| author | paul <paul> | 2002-12-13 20:15:29 +0000 | 
|---|---|---|
| committer | paul <paul> | 2002-12-13 20:15:29 +0000 | 
| commit | 718e3744195351130f4ce7dbe0613f4b3e23df93 (patch) | |
| tree | bac2ad39971cd43f31241ef123bd4e470f695ac9 /lib/checksum.c | |
Initial revision
Diffstat (limited to 'lib/checksum.c')
| -rw-r--r-- | lib/checksum.c | 47 | 
1 files changed, 47 insertions, 0 deletions
diff --git a/lib/checksum.c b/lib/checksum.c new file mode 100644 index 0000000000..6a29cbacc8 --- /dev/null +++ b/lib/checksum.c @@ -0,0 +1,47 @@ +/* + * Checksum routine for Internet Protocol family headers (C Version). + * + * Refer to "Computing the Internet Checksum" by R. Braden, D. Borman and + * C. Partridge, Computer Communication Review, Vol. 19, No. 2, April 1989, + * pp. 86-101, for additional details on computing this checksum. + */ + +#include <zebra.h> + +int				/* return checksum in low-order 16 bits */ +in_cksum(ptr, nbytes) +register u_short	*ptr; +register int		nbytes; +{ +	register long		sum;		/* assumes long == 32 bits */ +	u_short			oddbyte; +	register u_short	answer;		/* assumes u_short == 16 bits */ + +	/* +	 * Our algorithm is simple, using a 32-bit accumulator (sum), +	 * we add sequential 16-bit words to it, and at the end, fold back +	 * all the carry bits from the top 16 bits into the lower 16 bits. +	 */ + +	sum = 0; +	while (nbytes > 1)  { +		sum += *ptr++; +		nbytes -= 2; +	} + +				/* mop up an odd byte, if necessary */ +	if (nbytes == 1) { +		oddbyte = 0;		/* make sure top half is zero */ +		*((u_char *) &oddbyte) = *(u_char *)ptr;   /* one byte only */ +		sum += oddbyte; +	} + +	/* +	 * Add back carry outs from top 16 bits to low 16 bits. +	 */ + +	sum  = (sum >> 16) + (sum & 0xffff);	/* add high-16 to low-16 */ +	sum += (sum >> 16);			/* add carry */ +	answer = ~sum;		/* ones-complement, then truncate to 16 bits */ +	return(answer); +}  | 
