7

TCPのチェックサムを数日間行うのに問題があります。私はインターネット上の多くの情報源を見てきましたが、私が見た例のどれもTCPチェックサムを行う方法を示していません。私もRFCドキュメントを見ましたが、それでも問題があります。

以下は、チェックサムを生成するために使用しているコードです。

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を使用してこれらのパケットをテストしてきましたが、間違っているのはチェックサムだけです。

最後に、TCPヘッダーとIPヘッダーからの情報をロードする疑似ヘッダー構造体を次に示します。

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チェックサムをその値に割り当てます。私が提供したものに何か問題がありますか?問題がここにない場合、それは私が見ることができない不注意なエラーである可能性があります。

4

4 に答える 4

6

winpcap-users メーリング リストで、奇妙な長さのデータに関する 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);
}
于 2012-01-13T02:49:22.433 に答える
3

いくつかのことがわかります:

  • ゼロでパディングすることにより、奇数長のデータを考慮していません。
  • パケットから各ワードを読み取るときは、ネットワークのバイト順を考慮する必要があります。
  • の使用がhtonl(0x0000ffff)疑わしいようです。定数をネットワークバイト オーダーに変換して、ホストバイト オーダーのデータと結合するのはなぜですか?
于 2012-01-13T02:38:45.627 に答える
2

RFC 793には、「チェックサムを計算するヘッダーとテキストのオクテットがセグメントに奇数含まれている場合、最後のオクテットの右側にゼロが埋め込まれ、チェックサム用の 16 ビット ワードが形成されます」とあります。上記のコードはそのケースを処理しません。ループ条件は i > 1 である必要があり、ループの外側で i == 1 をチェックし、最後のオクテットに対して特別な処理を行う必要があると思います。

于 2012-01-13T02:49:43.197 に答える