|
|
1.1 root 1: #ifndef _I386_CHECKSUM_H
2: #define _I386_CHECKSUM_H
3:
4: /*
5: * computes the checksum of a memory block at buff, length len,
6: * and adds in "sum" (32-bit)
7: *
8: * returns a 32-bit number suitable for feeding into itself
9: * or csum_tcpudp_magic
10: *
11: * this function must be called with even lengths, except
12: * for the last fragment, which may be odd
13: *
14: * it's best to have buff aligned on a 32-bit boundary
15: */
16: unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
17:
18: /*
19: * the same as csum_partial, but copies from src while it
20: * checksums
21: *
22: * here even more important to align src and dst on a 32-bit (or even
23: * better 64-bit) boundary
24: */
25:
26: unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum);
27:
28:
29: /*
30: * the same as csum_partial_copy, but copies from user space.
31: *
32: * here even more important to align src and dst on a 32-bit (or even
33: * better 64-bit) boundary
34: */
35:
36: unsigned int csum_partial_copy_fromuser(const char *src, char *dst, int len, int sum);
37:
38: /*
39: * This is a version of ip_compute_csum() optimized for IP headers,
40: * which always checksum on 4 octet boundaries.
41: *
42: * By Jorge Cwik <[email protected]>, adapted for linux by
43: * Arnt Gulbrandsen.
44: */
45: static inline unsigned short ip_fast_csum(unsigned char * iph,
46: unsigned int ihl) {
47: unsigned int sum;
48:
49: __asm__ __volatile__("
50: movl (%1), %0
51: subl $4, %2
52: jbe 2f
53: addl 4(%1), %0
54: adcl 8(%1), %0
55: adcl 12(%1), %0
56: 1: adcl 16(%1), %0
57: lea 4(%1), %1
58: decl %2
59: jne 1b
60: adcl $0, %0
61: movl %0, %2
62: shrl $16, %0
63: addw %w2, %w0
64: adcl $0, %0
65: notl %0
66: 2:
67: "
68: /* Since the input registers which are loaded with iph and ipl
69: are modified, we must also specify them as outputs, or gcc
70: will assume they contain their original values. */
71: : "=r" (sum), "=r" (iph), "=r" (ihl)
72: : "1" (iph), "2" (ihl));
73: return(sum);
74: }
75:
76: /*
77: * Fold a partial checksum
78: */
79:
80: static inline unsigned int csum_fold(unsigned int sum)
81: {
82: __asm__("
83: addl %1, %0
84: adcl $0xffff, %0
85: "
86: : "=r" (sum)
87: : "r" (sum << 16), "0" (sum & 0xffff0000)
88: );
89: return (~sum) >> 16;
90: }
91:
92: /*
93: * computes the checksum of the TCP/UDP pseudo-header
94: * returns a 16-bit checksum, already complemented
95: */
96:
97: static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
98: unsigned long daddr,
99: unsigned short len,
100: unsigned short proto,
101: unsigned int sum) {
102: __asm__("
103: addl %1, %0
104: adcl %2, %0
105: adcl %3, %0
106: adcl $0, %0
107: "
108: : "=r" (sum)
109: : "g" (daddr), "g"(saddr), "g"((ntohs(len)<<16)+proto*256), "0"(sum));
110: return csum_fold(sum);
111: }
112: /*
113: * this routine is used for miscellaneous IP-like checksums, mainly
114: * in icmp.c
115: */
116:
117: static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
118: return csum_fold (csum_partial(buff, len, 0));
119: }
120:
121: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.