~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/include/asm-i386/checksum.h

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #ifndef _I386_CHECKSUM_H
  2 #define _I386_CHECKSUM_H
  3 
  4 
  5 /*
  6  * computes the checksum of a memory block at buff, length len,
  7  * and adds in "sum" (32-bit)
  8  *
  9  * returns a 32-bit number suitable for feeding into itself
 10  * or csum_tcpudp_magic
 11  *
 12  * this function must be called with even lengths, except
 13  * for the last fragment, which may be odd
 14  *
 15  * it's best to have buff aligned on a 32-bit boundary
 16  */
 17 asmlinkage unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
 18 
 19 /*
 20  * the same as csum_partial, but copies from src while it
 21  * checksums, and handles user-space pointer exceptions correctly, when needed.
 22  *
 23  * here even more important to align src and dst on a 32-bit (or even
 24  * better 64-bit) boundary
 25  */
 26 
 27 asmlinkage unsigned int csum_partial_copy_generic( const char *src, char *dst, int len, int sum,
 28                                                    int *src_err_ptr, int *dst_err_ptr);
 29 
 30 /*
 31  *      Note: when you get a NULL pointer exception here this means someone
 32  *      passed in an incorrect kernel address to one of these functions. 
 33  *      
 34  *      If you use these functions directly please don't forget the 
 35  *      verify_area().
 36  */
 37 extern __inline__
 38 unsigned int csum_partial_copy_nocheck ( const char *src, char *dst,
 39                                         int len, int sum)
 40 {
 41         return csum_partial_copy_generic ( src, dst, len, sum, NULL, NULL);
 42 }
 43 
 44 extern __inline__
 45 unsigned int csum_partial_copy_from_user ( const char *src, char *dst,
 46                                                 int len, int sum, int *err_ptr)
 47 {
 48         return csum_partial_copy_generic ( src, dst, len, sum, err_ptr, NULL);
 49 }
 50 
 51 /*
 52  * These are the old (and unsafe) way of doing checksums, a warning message will be
 53  * printed if they are used and an exeption occurs.
 54  *
 55  * these functions should go away after some time.
 56  */
 57 
 58 #define csum_partial_copy_fromuser csum_partial_copy
 59 unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum);
 60 
 61 /*
 62  *      This is a version of ip_compute_csum() optimized for IP headers,
 63  *      which always checksum on 4 octet boundaries.
 64  *
 65  *      By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
 66  *      Arnt Gulbrandsen.
 67  */
 68 static inline unsigned short ip_fast_csum(unsigned char * iph,
 69                                           unsigned int ihl) {
 70         unsigned int sum;
 71 
 72         __asm__ __volatile__("
 73             movl (%1), %0
 74             subl $4, %2
 75             jbe 2f
 76             addl 4(%1), %0
 77             adcl 8(%1), %0
 78             adcl 12(%1), %0
 79 1:          adcl 16(%1), %0
 80             lea 4(%1), %1
 81             decl %2
 82             jne 1b
 83             adcl $0, %0
 84             movl %0, %2
 85             shrl $16, %0
 86             addw %w2, %w0
 87             adcl $0, %0
 88             notl %0
 89 2:
 90             "
 91         /* Since the input registers which are loaded with iph and ipl
 92            are modified, we must also specify them as outputs, or gcc
 93            will assume they contain their original values. */
 94         : "=r" (sum), "=r" (iph), "=r" (ihl)
 95         : "1" (iph), "2" (ihl));
 96         return(sum);
 97 }
 98 
 99 /*
100  *      Fold a partial checksum
101  */
102 
103 static inline unsigned int csum_fold(unsigned int sum)
104 {
105         __asm__("
106                 addl %1, %0
107                 adcl $0xffff, %0
108                 "
109                 : "=r" (sum)
110                 : "r" (sum << 16), "" (sum & 0xffff0000)
111         );
112         return (~sum) >> 16;
113 }
114  
115 static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
116                                                    unsigned long daddr,
117                                                    unsigned short len,
118                                                    unsigned short proto,
119                                                    unsigned int sum) 
120 {
121     __asm__("
122         addl %1, %0
123         adcl %2, %0
124         adcl %3, %0
125         adcl $0, %0
126         "
127         : "=r" (sum)
128         : "g" (daddr), "g"(saddr), "g"((ntohs(len)<<16)+proto*256), ""(sum));
129     return sum;
130 }
131 
132 /*
133  * computes the checksum of the TCP/UDP pseudo-header
134  * returns a 16-bit checksum, already complemented
135  */
136 static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
137                                                    unsigned long daddr,
138                                                    unsigned short len,
139                                                    unsigned short proto,
140                                                    unsigned int sum) 
141 {
142         return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
143 }
144 
145 /*
146  * this routine is used for miscellaneous IP-like checksums, mainly
147  * in icmp.c
148  */
149 
150 static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
151     return csum_fold (csum_partial(buff, len, 0));
152 }
153 
154 #define _HAVE_ARCH_IPV6_CSUM
155 static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
156                                                      struct in6_addr *daddr,
157                                                      __u32 len,
158                                                      unsigned short proto,
159                                                      unsigned int sum) 
160 {
161         __asm__("
162                 addl 0(%1), %0
163                 adcl 4(%1), %0
164                 adcl 8(%1), %0
165                 adcl 12(%1), %0
166                 adcl 0(%2), %0
167                 adcl 4(%2), %0
168                 adcl 8(%2), %0
169                 adcl 12(%2), %0
170                 adcl %3, %0
171                 adcl %4, %0
172                 adcl $0, %0
173                 "
174                 : "=&r" (sum)
175                 : "r" (saddr), "r" (daddr), 
176                   "r"(htonl(len)), "r"(htonl(proto)), ""(sum));
177 
178         return csum_fold(sum);
179 }
180 
181 /* 
182  *      Copy and checksum to user
183  */
184 #define HAVE_CSUM_COPY_USER
185 static __inline__ unsigned int csum_and_copy_to_user (const char *src, char *dst,
186                                     int len, int sum, int *err_ptr)
187 {
188         if (access_ok(VERIFY_WRITE, dst, len))
189                 return csum_partial_copy_generic(src, dst, len, sum, NULL, err_ptr);
190 
191         if (len)
192                 *err_ptr = -EFAULT;
193 
194         return -1; /* invalid checksum */
195 }
196 
197 #endif
198 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.