BSD 4_3_Net_1 release
[unix-history] / timed / cksum.tahoe.c
/*
* Copyright (c) 1986 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef lint
static char sccsid[] = "@(#)cksum.tahoe.c 2.3 (Berkeley) 6/18/88";
#endif /* not lint */
#include <sys/types.h>
/*
* Checksum routine for Internet Protocol family headers.
*
* This routine is very heavily used in the network
* code and should be modified for each CPU to be as fast as possible.
*
* This implementation is TAHOE version.
*/
#undef ADDCARRY
#define ADDCARRY(sum) { \
if (sum & 0xffff0000) { \
sum &= 0xffff; \
sum++; \
} \
}
in_cksum(addr, len)
register u_short *addr;
register int len;
{
union word {
char c[2];
u_short s;
} u;
register int sum = 0;
while (len > 0) {
/*
* add by words.
*/
while ((len -= 2) >= 0) {
if ((int)addr & 0x1) {
/* word is not aligned */
u.c[0] = *(char *)addr;
u.c[1] = *((char *)addr+1);
sum += u.s;
addr++;
} else
sum += *addr++;
ADDCARRY(sum);
}
if (len == -1)
/*
* Odd number of bytes.
*/
u.c[0] = *(u_char *)addr;
}
if (len == -1) {
/* The last mbuf has odd # of bytes. Follow the
standard (the odd byte is shifted left by 8 bits) */
u.c[1] = 0;
sum += u.s;
ADDCARRY(sum);
}
return (~sum & 0xffff);
}