|
|
1.1 root 1: /*
2: * Copyright (c) 1988 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution is only permitted until one year after the first shipment
6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
7: * binary forms are permitted provided that: (1) source distributions retain
8: * this entire copyright notice and comment, and (2) distributions including
9: * binaries display the following acknowledgement: This product includes
10: * software developed by the University of California, Berkeley and its
11: * contributors'' in the documentation or other materials provided with the
12: * distribution and in all advertising materials mentioning features or use
13: * of this software. Neither the name of the University nor the names of
14: * its contributors may be used to endorse or promote products derived from
15: * this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: * @(#)in_cksum.c 7.3 (Berkeley) 6/28/90
21: */
22:
23: #include "../h/types.h"
24: #include "../h/mbuf.h"
25:
26: /*
27: * Checksum routine for Internet Protocol family headers (Portable Version).
28: *
29: * This routine is very heavily used in the network
30: * code and should be modified for each CPU to be as fast as possible.
31: */
32:
33: #define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
34: #define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
35:
36: in_cksum_c(m, len)
37: register struct mbuf *m;
38: register int len;
39: {
40: register u_short *w;
41: register int sum = 0;
42: register int mlen = 0;
43: int byte_swapped = 0;
44:
45: union {
46: char c[2];
47: u_short s;
48: } s_util;
49: union {
50: u_short s[2];
51: long l;
52: } l_util;
53:
54: for (;m && len; m = m->m_next) {
55: if (m->m_len == 0)
56: continue;
57: w = mtod(m, u_short *);
58: if (mlen == -1) {
59: /*
60: * The first byte of this mbuf is the continuation
61: * of a word spanning between this mbuf and the
62: * last mbuf.
63: *
64: * s_util.c[0] is already saved when scanning previous
65: * mbuf.
66: */
67: s_util.c[1] = *(char *)w;
68: sum += s_util.s;
69: w = (u_short *)((char *)w + 1);
70: mlen = m->m_len - 1;
71: len--;
72: } else
73: mlen = m->m_len;
74: if (len < mlen)
75: mlen = len;
76: len -= mlen;
77: /*
78: * Force to even boundary.
79: */
80: if ((1 & (int) w) && (mlen > 0)) {
81: REDUCE;
82: sum <<= 8;
83: s_util.c[0] = *(u_char *)w;
84: w = (u_short *)((char *)w + 1);
85: mlen--;
86: byte_swapped = 1;
87: }
88: /*
89: * Unroll the loop to make overhead from
90: * branches &c small.
91: */
92: while ((mlen -= 32) >= 0) {
93: sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
94: sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
95: sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
96: sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
97: w += 16;
98: }
99: mlen += 32;
100: while ((mlen -= 8) >= 0) {
101: sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
102: w += 4;
103: }
104: mlen += 8;
105: if (mlen == 0 && byte_swapped == 0)
106: continue;
107: REDUCE;
108: while ((mlen -= 2) >= 0) {
109: sum += *w++;
110: }
111: if (byte_swapped) {
112: REDUCE;
113: sum <<= 8;
114: byte_swapped = 0;
115: if (mlen == -1) {
116: s_util.c[1] = *(char *)w;
117: sum += s_util.s;
118: mlen = 0;
119: } else
120: mlen = -1;
121: } else if (mlen == -1)
122: s_util.c[0] = *(char *)w;
123: }
124: if (len)
125: printf("cksum: out of data\n");
126: if (mlen == -1) {
127: /* The last mbuf has odd # of bytes. Follow the
128: standard (the odd byte may be shifted left by 8 bits
129: or not as determined by endian-ness of the machine) */
130: s_util.c[1] = 0;
131: sum += s_util.s;
132: }
133: REDUCE;
134: return (~sum & 0xffff);
135: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.