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(unsigned char * buff, int len, unsigned int sum);
17
18 /*
19 * the same as csum_partial, but copies from fs: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_copyffs( char *src, char *dst, int len, int sum);
27
28
29 /*
30 * This is a version of ip_compute_csum() optimized for IP headers,
31 * which always checksum on 4 octet boundaries.
32 *
33 * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
34 * Arnt Gulbrandsen.
35 */
36 static inline unsigned short ip_fast_csum(unsigned char * iph,
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
37 unsigned int ihl) {
38 unsigned short int sum;
39
40 __asm__("
41 movl (%%esi), %%eax
42 andl $15, %%ecx
43 subl $4, %%ecx
44 jbe 2f
45 addl 4(%%esi), %%eax
46 adcl 8(%%esi), %%eax
47 adcl 12(%%esi), %%eax
48 1: adcl 16(%%esi), %%eax
49 lea 4(%%esi), %%esi
50 decl %%ecx
51 jne 1b
52 adcl $0, %%eax
53 movl %%eax, %%ecx
54 shrl $16, %%eax
55 addw %%ecx, %%eax
56 adcl $0, %%eax
57 notl %%eax
58 andl $65535, %%eax
59 2:
60 "
61 : "=a" (sum)
62 : "S" (iph), "c"(ihl)
63 : "ax", "cx", "si");
64 return(sum);
65 }
66
67
68
69
70 /*
71 * computes the checksum of the TCP/UDP pseudo-header
72 * returns a 16-bit checksum, already complemented
73 */
74
75 static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
76 unsigned long daddr,
77 unsigned short len,
78 unsigned short proto,
79 unsigned int sum) {
80 __asm__("
81 addl %2, %0
82 adcl %3, %0
83 adcl %4, %0
84 adcl $0, %0
85 movl %0, %2
86 shrl $16, %2
87 addw %2, %0
88 adcl $0, %0
89 notl %0
90 andl $65535, %0
91 "
92 : "=r" (sum)
93 : "0" (daddr), "S"(saddr), "r"((ntohs(len)<<16)+proto*256), "r"(sum)
94 : "si" );
95 return((unsigned short)sum);
96 }
97
98 /*
99 * this routine is used for miscellaneous IP-like checksums, mainly
100 * in icmp.c
101 */
102
103 static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
104 unsigned short int sum;
105
106 __asm__("
107 movl %%eax, %%ecx
108 shrl $16, %%ecx
109 addw %%cx, %%ax
110 adcl $0, %%eax
111 notl %%eax
112 andl $65535, %%eax
113 "
114 : "=a"(sum)
115 : "a" (csum_partial(buff, len, 0))
116 : "cx");
117 return(sum);
118 }
119
120 #endif