00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef _CHECKSUM_H
00028 #define _CHECKSUM_H
00029
00030 #ifndef __WIN32__
00031 #include <asm/types.h>
00032 #include <endian.h>
00033 #include <netinet/in.h>
00034 #else
00035 #include <win32/types.h>
00036 #include <ws2tcpip.h>
00037 #endif
00038
00039 #ifdef __WIN32__
00040
00041
00042
00043 struct my_in6_addr {
00044 __u32 s6_addr32[4];
00045 };
00046 #endif
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 #ifdef __WIN32__
00060
00061
00062 static __inline unsigned short ip_fast_csum(unsigned char * iph,
00063 unsigned int ihl)
00064 {
00065 __u16 checksum;
00066 unsigned long sum = 0;
00067 int count = ihl*4;
00068 unsigned short *p = (unsigned short *)iph;
00069
00070
00071
00072
00073
00074
00075
00076 while (count > 1) {
00077 sum += *p++;
00078 count -= 2;
00079 }
00080
00081 if (count > 0)
00082 sum += (unsigned char)*p;
00083
00084
00085 while (sum>>16)
00086 sum = (sum & 0xffff) + (sum >> 16);
00087
00088 checksum = (__u16)(~sum);
00089
00090 return(checksum);
00091 }
00092 #else
00093 static inline unsigned short ip_fast_csum(unsigned char * iph,
00094 unsigned int ihl)
00095 {
00096 unsigned int sum;
00097
00098 __asm__ __volatile__(
00099 "movl (%1), %0 ;\n"
00100 "subl $4, %2 ;\n"
00101 "jbe 2f ;\n"
00102 "addl 4(%1), %0 ;\n"
00103 "adcl 8(%1), %0 ;\n"
00104 "adcl 12(%1), %0 ;\n"
00105 "1: adcl 16(%1), %0 ;\n"
00106 "lea 4(%1), %1 ;\n"
00107 "decl %2 ;\n"
00108 "jne 1b ;\n"
00109 "adcl $0, %0 ;\n"
00110 "movl %0, %2 ;\n"
00111 "shrl $16, %0 ;\n"
00112 "addw %w2, %w0 ;\n"
00113 "adcl $0, %0 ;\n"
00114 "notl %0 ;\n"
00115 "2: ;\n"
00116
00117
00118
00119 : "=r" (sum), "=r" (iph), "=r" (ihl)
00120 : "1" (iph), "2" (ihl)
00121 : "memory");
00122 return(sum);
00123 }
00124 #endif
00125
00126
00127
00128
00129
00130 #ifdef __WIN32__
00131 static __inline unsigned int csum_fold(unsigned int sum)
00132 {
00133
00134
00135 while (sum>>16)
00136 sum = (sum & 0xffff) + (sum >> 16);
00137
00138 return((__u16)~sum);
00139 }
00140 #else
00141
00142 static inline unsigned int csum_fold(unsigned int sum)
00143 {
00144 __asm__(
00145 "addl %1, %0 ;\n"
00146 "adcl $0xffff, %0 ;\n"
00147 : "=r" (sum)
00148 : "r" (sum << 16), "0" (sum & 0xffff0000)
00149 );
00150 return (~sum) >> 16;
00151 }
00152 #endif
00153
00154 #ifdef __WIN32__
00155 static __inline unsigned int csum_add(unsigned int csum, unsigned int addend);
00156 static __inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
00157 unsigned long daddr,
00158 unsigned short len,
00159 unsigned short proto,
00160 unsigned int sum)
00161 {
00162 sum = csum_add(sum, saddr);
00163 sum = csum_add(sum, daddr);
00164 sum = csum_add(sum, (__u32)len);
00165 sum = csum_add(sum, (__u32)proto);
00166 return(sum);
00167 }
00168 #else
00169
00170 static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
00171 unsigned long daddr,
00172 unsigned short len,
00173 unsigned short proto,
00174 unsigned int sum)
00175 {
00176 __asm__(
00177 "addl %1, %0 ;\n"
00178 "adcl %2, %0 ;\n"
00179 "adcl %3, %0 ;\n"
00180 "adcl $0, %0 ;\n"
00181 : "=r" (sum)
00182 : "g" (daddr), "g"(saddr), "g"((ntohs(len)<<16)+proto*256), "0"(sum));
00183 return sum;
00184 }
00185 #endif
00186
00187
00188
00189
00190
00191 #ifdef __WIN32__
00192 static __inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
00193 unsigned long daddr,
00194 unsigned short len,
00195 unsigned short proto,
00196 unsigned int sum)
00197 #else
00198 static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
00199 unsigned long daddr,
00200 unsigned short len,
00201 unsigned short proto,
00202 unsigned int sum)
00203 #endif
00204 {
00205 return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
00206 }
00207
00208 #ifndef __WIN32__
00209 #define _HAVE_ARCH_IPV6_CSUM
00210 static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
00211 struct in6_addr *daddr,
00212 __u32 len,
00213 unsigned short proto,
00214 unsigned int sum)
00215 {
00216 __asm__(
00217 "addl 0(%1), %0 ;\n"
00218 "adcl 4(%1), %0 ;\n"
00219 "adcl 8(%1), %0 ;\n"
00220 "adcl 12(%1), %0 ;\n"
00221 "adcl 0(%2), %0 ;\n"
00222 "adcl 4(%2), %0 ;\n"
00223 "adcl 8(%2), %0 ;\n"
00224 "adcl 12(%2), %0 ;\n"
00225 "adcl %3, %0 ;\n"
00226 "adcl %4, %0 ;\n"
00227 "adcl $0, %0 ;\n"
00228 : "=&r" (sum)
00229 : "r" (saddr), "r" (daddr),
00230 "r"(htonl(len)), "r"(htonl(proto)), "0"(sum));
00231
00232 return csum_fold(sum);
00233 }
00234 #endif
00235
00236
00237
00238
00239
00240 #ifdef __WIN32__
00241 static __inline unsigned int csum_add(unsigned int csum, unsigned int addend)
00242 #else
00243 static inline unsigned int csum_add(unsigned int csum, unsigned int addend)
00244 #endif
00245 {
00246 csum += addend;
00247 return csum + (csum < addend);
00248 }
00249
00250 #ifdef __WIN32__
00251 static __inline unsigned int csum_sub(unsigned int csum, unsigned int addend)
00252 #else
00253 static inline unsigned int csum_sub(unsigned int csum, unsigned int addend)
00254 #endif
00255 {
00256 return csum_add(csum, ~addend);
00257 }
00258
00259
00260
00261
00262 #ifdef __WIN32__
00263 static __inline unsigned short csum_tcpudp_hip_nofold(unsigned long saddr,
00264 unsigned long daddr,
00265 unsigned short sum,
00266 unsigned short hitMagic)
00267 #else
00268 static inline unsigned short csum_tcpudp_hip_nofold(unsigned long saddr,
00269 unsigned long daddr,
00270 unsigned short sum,
00271 unsigned short hitMagic)
00272 #endif
00273 {
00274
00275 unsigned short ret = ~sum;
00276
00277 ret = ~csum_fold(csum_add(ret, hitMagic));
00278 ret = csum_fold(csum_sub(ret,~csum_fold(csum_add(saddr,daddr))));
00279
00280 return ret;
00281 }
00282
00283 #ifdef __WIN32__
00284 static __inline unsigned short csum_hip_revert(unsigned long saddr,
00285 unsigned long daddr,
00286 unsigned short sum,
00287 unsigned short hitMagic)
00288 #else
00289 static inline unsigned short csum_hip_revert(unsigned long saddr,
00290 unsigned long daddr,
00291 unsigned short sum,
00292 unsigned short hitMagic)
00293 #endif
00294 {
00295
00296 unsigned short ret = ~sum;
00297
00298 ret = ~csum_fold(csum_sub(ret, hitMagic));
00299 ret = csum_fold(csum_add(ret,~csum_fold(csum_add(saddr,daddr))));
00300 return ret;
00301 }
00302
00303
00304
00305
00306 #ifdef __WIN32__
00307 static __inline unsigned short csum_tcpudp_hip_nofold6(struct in6_addr *saddr1,
00308 struct in6_addr *daddr1,
00309 unsigned short sum,
00310 unsigned short hitMagic)
00311 {
00312 int carry;
00313 unsigned int csum;
00314
00315 unsigned short ret = ~sum;
00316
00317
00318 struct my_in6_addr *saddr = (struct my_in6_addr*)saddr1;
00319 struct my_in6_addr *daddr = (struct my_in6_addr*)daddr1;
00320
00321
00322 csum = saddr->s6_addr32[0];
00323 carry = (csum < saddr->s6_addr32[0]);
00324 csum += carry;
00325
00326 csum += saddr->s6_addr32[1];
00327 carry = (csum < saddr->s6_addr32[1]);
00328 csum += carry;
00329
00330 csum += saddr->s6_addr32[2];
00331 carry = (csum < saddr->s6_addr32[2]);
00332 csum += carry;
00333
00334 csum += saddr->s6_addr32[3];
00335 carry = (csum < saddr->s6_addr32[3]);
00336 csum += carry;
00337
00338 csum += daddr->s6_addr32[0];
00339 carry = (csum < daddr->s6_addr32[0]);
00340 csum += carry;
00341
00342 csum += daddr->s6_addr32[1];
00343 carry = (csum < daddr->s6_addr32[1]);
00344 csum += carry;
00345
00346 csum += daddr->s6_addr32[2];
00347 carry = (csum < daddr->s6_addr32[2]);
00348 csum += carry;
00349
00350 csum += daddr->s6_addr32[3];
00351 carry = (csum < daddr->s6_addr32[3]);
00352 csum += carry;
00353
00354
00355 ret = ~csum_fold(csum_add(ret, hitMagic));
00356 ret = csum_fold(csum_sub(ret,~csum_fold(csum)));
00357
00358 return ret;
00359
00360 }
00361 #else
00362
00363 static inline unsigned short csum_tcpudp_hip_nofold6(struct in6_addr *saddr,
00364 struct in6_addr *daddr,
00365 unsigned short sum,
00366 unsigned short hitMagic)
00367 {
00368 int carry;
00369 unsigned int csum;
00370
00371 unsigned short ret = ~sum;
00372
00373
00374 #ifdef __CYGWIN__
00375 csum = saddr->__u6_addr.__u6_addr32[0];
00376 carry = (csum < saddr->__u6_addr.__u6_addr32[0]);
00377 csum += carry;
00378
00379 csum += saddr->__u6_addr.__u6_addr32[1];
00380 carry = (csum < saddr->__u6_addr.__u6_addr32[1]);
00381 csum += carry;
00382
00383 csum += saddr->__u6_addr.__u6_addr32[2];
00384 carry = (csum < saddr->__u6_addr.__u6_addr32[2]);
00385 csum += carry;
00386
00387 csum += saddr->__u6_addr.__u6_addr32[3];
00388 carry = (csum < saddr->__u6_addr.__u6_addr32[3]);
00389 csum += carry;
00390
00391 csum += daddr->__u6_addr.__u6_addr32[0];
00392 carry = (csum < daddr->__u6_addr.__u6_addr32[0]);
00393 csum += carry;
00394
00395 csum += daddr->__u6_addr.__u6_addr32[1];
00396 carry = (csum < daddr->__u6_addr.__u6_addr32[1]);
00397 csum += carry;
00398
00399 csum += daddr->__u6_addr.__u6_addr32[2];
00400 carry = (csum < daddr->__u6_addr.__u6_addr32[2]);
00401 csum += carry;
00402
00403 csum += daddr->__u6_addr.__u6_addr32[3];
00404 carry = (csum < daddr->__u6_addr.__u6_addr32[3]);
00405 csum += carry;
00406 #else
00407 csum = saddr->s6_addr32[0];
00408 carry = (csum < saddr->s6_addr32[0]);
00409 csum += carry;
00410
00411 csum += saddr->s6_addr32[1];
00412 carry = (csum < saddr->s6_addr32[1]);
00413 csum += carry;
00414
00415 csum += saddr->s6_addr32[2];
00416 carry = (csum < saddr->s6_addr32[2]);
00417 csum += carry;
00418
00419 csum += saddr->s6_addr32[3];
00420 carry = (csum < saddr->s6_addr32[3]);
00421 csum += carry;
00422
00423 csum += daddr->s6_addr32[0];
00424 carry = (csum < daddr->s6_addr32[0]);
00425 csum += carry;
00426
00427 csum += daddr->s6_addr32[1];
00428 carry = (csum < daddr->s6_addr32[1]);
00429 csum += carry;
00430
00431 csum += daddr->s6_addr32[2];
00432 carry = (csum < daddr->s6_addr32[2]);
00433 csum += carry;
00434
00435 csum += daddr->s6_addr32[3];
00436 carry = (csum < daddr->s6_addr32[3]);
00437 csum += carry;
00438 #endif
00439
00440
00441 ret = ~csum_fold(csum_add(ret, hitMagic));
00442 ret = csum_fold(csum_sub(ret,~csum_fold(csum)));
00443
00444 return ret;
00445 }
00446 #endif
00447
00448 #ifdef __WIN32__
00449 static __inline unsigned short csum_hip_revert6(struct in6_addr *saddr1,
00450 struct in6_addr *daddr1,
00451 unsigned short sum,
00452 unsigned short hitMagic)
00453 {
00454 int carry;
00455 unsigned int csum;
00456
00457 unsigned short ret = ~sum;
00458
00459
00460 struct my_in6_addr *saddr = (struct my_in6_addr*)saddr1;
00461 struct my_in6_addr *daddr = (struct my_in6_addr*)daddr1;
00462
00463
00464 csum = saddr->s6_addr32[0];
00465 carry = (csum < saddr->s6_addr32[0]);
00466 csum += carry;
00467
00468 csum += saddr->s6_addr32[1];
00469 carry = (csum < saddr->s6_addr32[1]);
00470 csum += carry;
00471
00472 csum += saddr->s6_addr32[2];
00473 carry = (csum < saddr->s6_addr32[2]);
00474 csum += carry;
00475
00476 csum += saddr->s6_addr32[3];
00477 carry = (csum < saddr->s6_addr32[3]);
00478 csum += carry;
00479
00480 csum += daddr->s6_addr32[0];
00481 carry = (csum < daddr->s6_addr32[0]);
00482 csum += carry;
00483
00484 csum += daddr->s6_addr32[1];
00485 carry = (csum < daddr->s6_addr32[1]);
00486 csum += carry;
00487
00488 csum += daddr->s6_addr32[2];
00489 carry = (csum < daddr->s6_addr32[2]);
00490 csum += carry;
00491
00492 csum += daddr->s6_addr32[3];
00493 carry = (csum < daddr->s6_addr32[3]);
00494 csum += carry;
00495
00496
00497 ret = ~csum_fold(csum_sub(ret, hitMagic));
00498 ret = csum_fold(csum_add(ret,~csum_fold(csum)));
00499 return ret;
00500 }
00501
00502 #else
00503 static inline unsigned short csum_hip_revert6(struct in6_addr *saddr,
00504 struct in6_addr *daddr,
00505 unsigned short sum,
00506 unsigned short hitMagic)
00507 {
00508 int carry;
00509 unsigned int csum;
00510
00511 unsigned short ret = ~sum;
00512
00513
00514 #ifdef __CYGWIN__
00515 csum = saddr->__u6_addr.__u6_addr32[0];
00516 carry = (csum < saddr->__u6_addr.__u6_addr32[0]);
00517 csum += carry;
00518
00519 csum += saddr->__u6_addr.__u6_addr32[1];
00520 carry = (csum < saddr->__u6_addr.__u6_addr32[1]);
00521 csum += carry;
00522
00523 csum += saddr->__u6_addr.__u6_addr32[2];
00524 carry = (csum < saddr->__u6_addr.__u6_addr32[2]);
00525 csum += carry;
00526
00527 csum += saddr->__u6_addr.__u6_addr32[3];
00528 carry = (csum < saddr->__u6_addr.__u6_addr32[3]);
00529 csum += carry;
00530
00531 csum += daddr->__u6_addr.__u6_addr32[0];
00532 carry = (csum < daddr->__u6_addr.__u6_addr32[0]);
00533 csum += carry;
00534
00535 csum += daddr->__u6_addr.__u6_addr32[1];
00536 carry = (csum < daddr->__u6_addr.__u6_addr32[1]);
00537 csum += carry;
00538
00539 csum += daddr->__u6_addr.__u6_addr32[2];
00540 carry = (csum < daddr->__u6_addr.__u6_addr32[2]);
00541 csum += carry;
00542
00543 csum += daddr->__u6_addr.__u6_addr32[3];
00544 carry = (csum < daddr->__u6_addr.__u6_addr32[3]);
00545 csum += carry;
00546 #else
00547 csum = saddr->s6_addr32[0];
00548 carry = (csum < saddr->s6_addr32[0]);
00549 csum += carry;
00550
00551 csum += saddr->s6_addr32[1];
00552 carry = (csum < saddr->s6_addr32[1]);
00553 csum += carry;
00554
00555 csum += saddr->s6_addr32[2];
00556 carry = (csum < saddr->s6_addr32[2]);
00557 csum += carry;
00558
00559 csum += saddr->s6_addr32[3];
00560 carry = (csum < saddr->s6_addr32[3]);
00561 csum += carry;
00562
00563 csum += daddr->s6_addr32[0];
00564 carry = (csum < daddr->s6_addr32[0]);
00565 csum += carry;
00566
00567 csum += daddr->s6_addr32[1];
00568 carry = (csum < daddr->s6_addr32[1]);
00569 csum += carry;
00570
00571 csum += daddr->s6_addr32[2];
00572 carry = (csum < daddr->s6_addr32[2]);
00573 csum += carry;
00574
00575 csum += daddr->s6_addr32[3];
00576 carry = (csum < daddr->s6_addr32[3]);
00577 csum += carry;
00578 #endif
00579
00580
00581 ret = ~csum_fold(csum_sub(ret, hitMagic));
00582 ret = csum_fold(csum_add(ret,~csum_fold(csum)));
00583 return ret;
00584 }
00585 #endif
00586
00587 #endif