checksum.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:2k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Network checksum routines
  3.  *
  4.  * Copyright (C) 1999 Hewlett-Packard Co
  5.  * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
  6.  *
  7.  * Most of the code coming from arch/alpha/lib/checksum.c
  8.  *
  9.  * This file contains network checksum routines that are better done
  10.  * in an architecture-specific manner due to speed..
  11.  */
  12. #include <linux/string.h>
  13. #include <asm/byteorder.h>
  14. static inline unsigned short
  15. from64to16(unsigned long x)
  16. {
  17. /* add up 32-bit words for 33 bits */
  18. x = (x & 0xffffffff) + (x >> 32);
  19. /* add up 16-bit and 17-bit words for 17+c bits */
  20. x = (x & 0xffff) + (x >> 16);
  21. /* add up 16-bit and 2-bit for 16+c bit */
  22. x = (x & 0xffff) + (x >> 16);
  23. /* add up carry.. */
  24. x = (x & 0xffff) + (x >> 16);
  25. return x;
  26. }
  27. /*
  28.  * computes the checksum of the TCP/UDP pseudo-header
  29.  * returns a 16-bit checksum, already complemented.
  30.  */
  31. unsigned short int csum_tcpudp_magic(unsigned long saddr,
  32.    unsigned long daddr,
  33.    unsigned short len,
  34.    unsigned short proto,
  35.    unsigned int sum)
  36. {
  37. return ~from64to16(saddr + daddr + sum +
  38. ((unsigned long) ntohs(len) << 16) +
  39. ((unsigned long) proto << 8));
  40. }
  41. unsigned int csum_tcpudp_nofold(unsigned long saddr,
  42.    unsigned long daddr,
  43.    unsigned short len,
  44.    unsigned short proto,
  45.    unsigned int sum)
  46. {
  47. unsigned long result;
  48. result = (saddr + daddr + sum +
  49.   ((unsigned long) ntohs(len) << 16) +
  50.   ((unsigned long) proto << 8));
  51. /* Fold down to 32-bits so we don't loose in the typedef-less network stack.  */
  52. /* 64 to 33 */
  53. result = (result & 0xffffffff) + (result >> 32);
  54. /* 33 to 32 */
  55. result = (result & 0xffffffff) + (result >> 32);
  56. return result;
  57. }
  58. extern unsigned long do_csum (const unsigned char *, long);
  59. /*
  60.  * computes the checksum of a memory block at buff, length len,
  61.  * and adds in "sum" (32-bit)
  62.  *
  63.  * returns a 32-bit number suitable for feeding into itself
  64.  * or csum_tcpudp_magic
  65.  *
  66.  * this function must be called with even lengths, except
  67.  * for the last fragment, which may be odd
  68.  *
  69.  * it's best to have buff aligned on a 32-bit boundary
  70.  */
  71. unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
  72. {
  73. unsigned long result = do_csum(buff, len);
  74. /* add in old sum, and carry.. */
  75. result += sum;
  76. /* 32+c bits -> 32 bits */
  77. result = (result & 0xffffffff) + (result >> 32);
  78. return result;
  79. }
  80. /*
  81.  * this routine is used for miscellaneous IP-like checksums, mainly
  82.  * in icmp.c
  83.  */
  84. unsigned short ip_compute_csum(unsigned char * buff, int len)
  85. {
  86. return ~do_csum(buff,len);
  87. }