1 /* 2 * INET An implementation of the TCP/IP protocol suite for the LINUX 3 * operating system. INET is implemented using the BSD Socket 4 * interface as the means of communication with the user level. 5 * 6 * Checksumming functions for IP, TCP, UDP and so on 7 * 8 * Authors: Jorge Cwik, <jorge@laser.satlink.net> 9 * Arnt Gulbrandsen, <agulbra@nvg.unit.no> 10 * Borrows very liberally from tcp.c and ip.c, see those 11 * files for more names. 12 * 13 * This program is free software; you can redistribute it and/or 14 * modify it under the terms of the GNU General Public License 15 * as published by the Free Software Foundation; either version 16 * 2 of the License, or (at your option) any later version. 17 */ 18 #ifndef_CHECKSUM_H 19 #define_CHECKSUM_H 20
21 #include <asm/byteorder.h>
22 #include "ip.h"
23
24 /* 25 * This is a version of ip_compute_csum() optimized for IP headers, 26 * which always checksum on 4 octet boundaries. 27 * 28 * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by 29 * Arnt Gulbrandsen. 30 */ 31 staticinlineunsignedshortip_fast_csum(unsignedchar * iph,
/* */ 32 unsignedintihl) { 33 unsignedshortintsum;
34
35 #ifdef__i386__ 36 __asm__("
37 movl (%%esi), %%eax
38 andl $15, %%ecx
39 subl $4, %%ecx
40 jbe 2f
41 addl 4(%%esi), %%eax
42 adcl 8(%%esi), %%eax
43 adcl 12(%%esi), %%eax
44 1: adcl 16(%%esi), %%eax
45 lea 4(%%esi), %%esi
46 decl %%ecx
47 jne 1b
48 adcl $0, %%eax
49 movl %%eax, %%ecx
50 shrl $16, %%eax
51 addw %%ecx, %%eax
52 adcl $0, %%eax
53 notl %%eax
54 andl $65535, %%eax
55 2:
56 "
57 : "=a" (sum)
58 : "S" (iph), "c"(ihl)
59 : "ax", "cx", "si");
60 #else 61 #error Not implemented for this CPU
62 #endif 63 return(sum);
64 } 65
66
67
68
69 /* 70 * computes the checksum of the TCP/UDP pseudo-header 71 * returns a 16-bit checksum, already complemented 72 */ 73
74 staticinlineunsignedshortintcsum_tcpudp_magic(unsignedlongsaddr,
/* */ 75 unsignedlongdaddr,
76 unsignedshortlen,
77 unsignedshortproto,
78 unsignedintsum) { 79 #ifdef__i386__ 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 #else 96 #error Not implemented for this CPU
97 #endif 98 return((unsignedshort)sum);
99 } 100
101
102
103 /* 104 * computes the checksum of a memory block at buff, length len, 105 * and adds in "sum" (32-bit) 106 * 107 * returns a 32-bit number suitable for feeding into itself 108 * or csum_tcpudp_magic 109 * 110 * this function must be called with even lengths, except 111 * for the last fragment, which may be odd 112 * 113 * it's best to have buff aligned on a 32-bit boundary 114 */ 115 unsignedintcsum_partial(unsignedchar * buff, intlen, unsignedintsum);
116
117
118
119 /* 120 * the same as csum_partial, but copies from fs:src while it 121 * checksums 122 * 123 * here even more important to align src and dst on a 32-bit (or even 124 * better 64-bit) boundary 125 */ 126
127 unsignedintcsum_partial_copyffs( char *src, char *dst, intlen, intsum);
128
129
130
131
132 /* 133 * this routine is used for miscellaneous IP-like checksums, mainly 134 * in icmp.c 135 */ 136
137 staticinlineunsignedshortip_compute_csum(unsignedchar * buff, intlen) {/* */ 138 unsignedshortintsum;
139
140 #ifdef__i386__ 141 __asm__("
142 movl %%eax, %%ecx
143 shrl $16, %%ecx
144 addw %%cx, %%ax
145 adcl $0, %%eax
146 notl %%eax
147 andl $65535, %%eax
148 "
149 : "=a"(sum)
150 : "a" (csum_partial(buff, len, 0))
151 : "cx");
152 #else 153 #error Not implemented for this CPU
154 #endif 155 return(sum);
156 } 157
158 #endif