繁体   English   中英

我的TCP校验和函数对于大多数数据包返回0

[英]My TCP checksum function returns 0 for most of the packets

我正在编写一个小程序来监听流量并重新计算TCP校验和以进行验证。 对于大多数HTTP数据包,我的程序将校验和返回为零。

我所做的是通过PSEUDO_TCP_HEADER |创建缓冲区。 TCP_HEADER | TCP_PAYLOAD。 伪TCP标头是由以下内容定义的结构:

struct pseudo_tcp
{
    unsigned long saddr, daddr;
    unsigned char mbz;
    unsigned char ptcl;
    unsigned short tcpl;
};

然后,我调用此函数来计算校验和(我相信该函数可以完成很多项目所使用的正确工作):

unsigned short in_cksum(unsigned short *addr,int len)
{
    register int sum = 0;
    u_short answer = 0;
    register u_short *w = addr;
    register int nleft = len;

        /*!
    * Our algorithm is simple, using a 32 bit accumulator (sum), we add
    * sequential 16 bit words to it, and at the end, fold back all the
    * carry bits from the top 16 bits into the lower 16 bits.
    */
    while (nleft > 1)  {
        sum += *w++;
        nleft -= 2;
    }

    /*! mop up an odd byte, if necessary */
    if (nleft == 1) {
        *(u_char *)(&answer) = *(u_char *)w ;
        sum += answer;
    }

    /*! add back carry outs from top 16 bits to low 16 bits */
    sum = (sum >> 16) + (sum & 0xffff);     /*! add hi 16 to low 16 */
    sum += (sum >> 16);                     /*! add carry */
    answer = ~sum;                          /*! truncate to 16 bits */
    return(answer);
}

为了使测试更容易,我设法将缓冲区转储到文件中,这是两个导致校验和为0的缓冲区示例:

$ hexdump -C buffer.out
00000000  c0 a8 01 2c ad c2 26 92  00 06 00 a5 d5 90 00 50  |...,..&........P|
00000010  fa 2a 96 7b 56 9c 7c 27  50 18 40 00 ab 9f 00 00  |.*.{V.|'P.@.....|
00000020  47 45 54 20 2f 20 48 54  54 50 2f 31 2e 31 0d 0a  |GET / HTTP/1.1..|
00000030  55 73 65 72 2d 41 67 65  6e 74 3a 20 63 75 72 6c  |User-Agent: curl|
00000040  2f 37 2e 32 34 2e 30 20  28 78 38 36 5f 36 34 2d  |/7.24.0 (x86_64-|
00000050  61 70 70 6c 65 2d 64 61  72 77 69 6e 31 32 2e 30  |apple-darwin12.0|
00000060  29 20 6c 69 62 63 75 72  6c 2f 37 2e 32 34 2e 30  |) libcurl/7.24.0|
00000070  20 4f 70 65 6e 53 53 4c  2f 30 2e 39 2e 38 72 20  | OpenSSL/0.9.8r |
00000080  7a 6c 69 62 2f 31 2e 32  2e 35 0d 0a 48 6f 73 74  |zlib/1.2.5..Host|
00000090  3a 20 77 77 77 2e 67 6f  6f 67 6c 65 2e 63 6f 6d  |: www.google.com|
000000a0  0d 0a 41 63 63 65 70 74  3a 20 2a 2f 2a 0d 0a 0d  |..Accept: */*...|
000000b0  0a                                                |.|
000000b1

$ hexdump -C buffer1.out 
00000000  c0 a8 01 2c c7 3b 96 07  00 06 00 a2 de 35 00 50  |...,.;.......5.P|
00000010  a1 95 ce 03 c4 f9 f0 1a  50 18 ff ff e7 7a 00 00  |........P....z..|
00000020  47 45 54 20 2f 20 48 54  54 50 2f 31 2e 31 0d 0a  |GET / HTTP/1.1..|
00000030  55 73 65 72 2d 41 67 65  6e 74 3a 20 63 75 72 6c  |User-Agent: curl|
00000040  2f 37 2e 32 34 2e 30 20  28 78 38 36 5f 36 34 2d  |/7.24.0 (x86_64-|
00000050  61 70 70 6c 65 2d 64 61  72 77 69 6e 31 32 2e 30  |apple-darwin12.0|
00000060  29 20 6c 69 62 63 75 72  6c 2f 37 2e 32 34 2e 30  |) libcurl/7.24.0|
00000070  20 4f 70 65 6e 53 53 4c  2f 30 2e 39 2e 38 72 20  | OpenSSL/0.9.8r |
00000080  7a 6c 69 62 2f 31 2e 32  2e 35 0d 0a 48 6f 73 74  |zlib/1.2.5..Host|
00000090  3a 20 74 77 69 74 74 65  72 2e 63 6f 6d 0d 0a 41  |: twitter.com..A|
000000a0  63 63 65 70 74 3a 20 2a  2f 2a 0d 0a 0d 0a        |ccept: */*....|
000000ae

在第一个缓冲区中,前四个字节代表源IP地址(c0 a8 01 2c-> 192.168.1.44),后四个字节代表目标IP地址(ad c2 26 92-> 173.194.38.146),依此类推...

计算或构造缓冲区的方式有什么问题吗?

更新 :这是我用来从文件中读取并计算TCP校验和的测试代码

  int c,i=0;
  char buffer[1000];
  FILE *file; 
  file = fopen("buffer.out", "r");
  if (file) 
  {
    while ((c = getc(file)) != EOF)
        buffer[i++] = c;
    fclose(file);
  }
  printf("CSUM = %hu\n", in_chksum((unsigned short *  ) buffer, i));

该代码看起来正确,除了我看不到您正在将标头中的校验和清零。 这是一些代码,从winpcap邮件列表中执行相同的操作,您可以在TCPCheckSum()函数中看到它们首先将tcp标头的校验和字段清零: tcph->Chksum=0

[Winpcap用户] TCP校验和计算

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM