1 /* 2 * Copyright (c) 1986 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that this notice is preserved and that due credit is given 7 * to the University of California at Berkeley. The name of the University 8 * may not be used to endorse or promote products derived from this 9 * software without specific prior written permission. This software 10 * is provided ``as is'' without express or implied warranty. 11 */ 12 13 #ifndef lint 14 static char sccsid[] = "@(#)cksum.tahoe.c 2.2 (Berkeley) 12/23/87"; 15 #endif /* not lint */ 16 17 #include <sys/types.h> 18 19 /* 20 * Checksum routine for Internet Protocol family headers. 21 * 22 * This routine is very heavily used in the network 23 * code and should be modified for each CPU to be as fast as possible. 24 * 25 * This implementation is TAHOE version. 26 */ 27 28 #undef ADDCARRY 29 #define ADDCARRY(sum) { \ 30 if (sum & 0xffff0000) { \ 31 sum &= 0xffff; \ 32 sum++; \ 33 } \ 34 } 35 36 in_cksum(addr, len) 37 register u_short *addr; 38 register int len; 39 { 40 union word { 41 char c[2]; 42 u_short s; 43 } u; 44 register int sum = 0; 45 46 while (len > 0) { 47 /* 48 * add by words. 49 */ 50 while ((len -= 2) >= 0) { 51 if ((int)addr & 0x1) { 52 /* word is not aligned */ 53 u.c[0] = *(char *)addr; 54 u.c[1] = *((char *)addr+1); 55 sum += u.s; 56 addr++; 57 } else 58 sum += *addr++; 59 ADDCARRY(sum); 60 } 61 if (len == -1) 62 /* 63 * Odd number of bytes. 64 */ 65 u.c[0] = *(u_char *)addr; 66 } 67 if (len == -1) { 68 /* The last mbuf has odd # of bytes. Follow the 69 standard (the odd byte is shifted left by 8 bits) */ 70 u.c[1] = 0; 71 sum += u.s; 72 ADDCARRY(sum); 73 } 74 return (~sum & 0xffff); 75 } 76