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