1 /*- 2 * Copyright (c) 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * from tahoe: in_cksum.c 1.2 86/01/05 8 * @(#)in_cksum.c 8.1 (Berkeley) 06/11/93 9 */ 10 11 #include <sys/param.h> 12 #include <sys/mbuf.h> 13 14 #include <netinet/in.h> 15 #include <netinet/in_systm.h> 16 17 /* 18 * Checksum routine for Internet Protocol family headers. 19 * 20 * This routine is very heavily used in the network 21 * code and should be modified for each CPU to be as fast as possible. 22 * 23 * This implementation is 386 version. 24 */ 25 26 #undef ADDCARRY 27 #define ADDCARRY(sum) { \ 28 if (sum & 0xffff0000) { \ 29 sum &= 0xffff; \ 30 sum++; \ 31 } \ 32 } 33 in_cksum(m, len) 34 register struct mbuf *m; 35 register int len; 36 { 37 union word { 38 char c[2]; 39 u_short s; 40 } u; 41 register u_short *w; 42 register int sum = 0; 43 register int mlen = 0; 44 45 for (;m && len; m = m->m_next) { 46 if (m->m_len == 0) 47 continue; 48 w = mtod(m, u_short *); 49 if (mlen == -1) { 50 /* 51 * The first byte of this mbuf is the continuation 52 * of a word spanning between this mbuf and the 53 * last mbuf. 54 */ 55 56 /* u.c[0] is already saved when scanning previous 57 * mbuf. 58 */ 59 u.c[1] = *(u_char *)w; 60 sum += u.s; 61 ADDCARRY(sum); 62 w = (u_short *)((char *)w + 1); 63 mlen = m->m_len - 1; 64 len--; 65 } else 66 mlen = m->m_len; 67 68 if (len < mlen) 69 mlen = len; 70 len -= mlen; 71 72 /* 73 * add by words. 74 */ 75 while ((mlen -= 2) >= 0) { 76 if ((int)w & 0x1) { 77 /* word is not aligned */ 78 u.c[0] = *(char *)w; 79 u.c[1] = *((char *)w+1); 80 sum += u.s; 81 w++; 82 } else 83 sum += *w++; 84 ADDCARRY(sum); 85 } 86 if (mlen == -1) 87 /* 88 * This mbuf has odd number of bytes. 89 * There could be a word split betwen 90 * this mbuf and the next mbuf. 91 * Save the last byte (to prepend to next mbuf). 92 */ 93 u.c[0] = *(u_char *)w; 94 } 95 if (len) 96 printf("cksum: out of data\n"); 97 if (mlen == -1) { 98 /* The last mbuf has odd # of bytes. Follow the 99 standard (the odd byte is shifted left by 8 bits) */ 100 u.c[1] = 0; 101 sum += u.s; 102 ADDCARRY(sum); 103 } 104 return (~sum & 0xffff); 105 } 106