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