2012-01-13 142 views
4

我一直在做几天的TCP校验和。我已经查看了互联网上的许多来源,但是我没有看到任何示例向您展示如何执行TCP校验和。我也看了看RFC文件,仍然我有麻烦:C编程TCP校验和

下面是我使用生成的校验码:

unsigned short checksum(unsigned short * buffer, int bytes) 
{ 
    unsigned long sum = 0; 
    unsigned short answer = 0; 
    int i = bytes; 
    while(i>0) 
    { 
      sum+=*buffer; 
      buffer+=1; 
      i-=2; 
    } 
    sum = (sum >> 16) + (sum & htonl(0x0000ffff)); 
    sum += (sum >> 16); 
    return ~sum; 
} 

此功能适用于IP校验和。

下面是我为我的TCP报头所做的结构:

struct tcp_header 
{ 
    unsigned short tcp_sprt; 
    unsigned short tcp_dprt; 
    unsigned int tcp_seq; 
    unsigned int tcp_ack; 
    unsigned char tcp_res:4; 
    unsigned char tcp_off:4; 
    unsigned char tcp_flags; 
    unsigned short tcp_win; 
    unsigned short tcp_csum; 
    unsigned short tcp_urp; 
}; 

我一直在使用Wireshark来测试这些数据包,唯一错的是校验码。

最后这里是伪报头结构,我从IP报头中的TCP报头和信息加载:

struct pseudoTcpHeader 
{ 
    unsigned int ip_src; 
    unsigned int ip_dst; 
    unsigned char zero;//always zero 
    unsigned char protocol;// = 6;//for tcp 
    unsigned short tcp_len; 
    struct tcp_header tcph; 
}; 

一旦我加载了这个结构用正确的信息然后我就用校验功能整个伪头结构并将TCP校验和分配给该值。你看到我提供的东西有什么不对吗?如果问题不在这里,可能是我看不到的一个粗心的错误。

+0

如何将信息加载到结构中以及它来自哪里? – 2012-01-13 02:36:15

回答

4

我发现了winpcap-users mailing list应该解决Greg的约奇数长度数据的注释,并给你的东西来比较你的代码对一个非常好的例子。

USHORT CheckSum(USHORT *buffer, int size) 
{ 
    unsigned long cksum=0; 
    while(size >1) 
    { 
     cksum+=*buffer++; 
     size -=sizeof(USHORT); 
    } 
    if(size) 
     cksum += *(UCHAR*)buffer; 

    cksum = (cksum >> 16) + (cksum & 0xffff); 
    cksum += (cksum >>16); 
    return (USHORT)(~cksum); 
} 
3

我看到一对夫妇的事情:

  • 你不是被填充零占奇数长度的数据。
  • 从数据包中读取每个单词时,您需要考虑网络字节顺序。
  • 您使用htonl(0x0000ffff)似乎是可疑的。为什么你要将一个常量转换为网络字节顺序与主机字节顺序中的数据结合起来?
2

RFC 793说“如果一个段包含要校验和奇数的标题和文本八位字节,最后一个八位字节是在用零权以形成用于校验目的的16位字填充”。上面的代码不处理这种情况。我认为循环条件应该是i> 1,然后检查循环外的i == 1,并为最后一个八位字节执行特殊处理。