1

パケットの正しい IP チェックサムを計算するのに問題があります。これがコードです。私が何をしていて、何が間違っているのかを説明します..

u_short checkSum(u_short *data, int byteCount){
int i, sum = 0;

for(i = 0; i < byteCount/2; i++){
    if(i == 5) continue;
    sum += *data++;
}

while(sum >> 16)
sum = (sum & 0xffff) + (sum >> 16);
return (u_short)~sum;
}

まず、私の関数は、送信されたデータの 16 ビット チェックサムを計算するための一般的なものです。バイト数は、テスト目的のためだけに均等であると想定されています。sum は、32 ビットの合計を保持する変数です (16 ビットの合計がオーバーフローした場合、上位 16 ビットの半分にオーバーフローを保持できます)。データの 16 ビット ブロックを介して for i ループを使用してそれらを合計し、データ ポインターをインクリメントします (16 ビットずつ u_short です)。ヘッダーのチェックサム部分をスキップする if テストが 1 つあります。 rfc 791 では、チェックサム部分はヘッダーの 6 番目の 16 ビット ブロックです (0 からカウントを開始するため、私の場合は 5 です)。データが合計された後、上位 16 ビットを下位 16 ビットに加算し、32 ビット int を 16 ビット short に折りたたみます。最後に、ビット (1 の補数) を反転し、32 ビットを 16 ビットに短縮して呼び出し元関数に返します。

これは、pcap から送信された正しいチェックサムを提供していません (パケットのスニッフィングに使用します)。これは、結果を比較するために関数を呼び出す方法です..

if(etherHdr->ether_type == 8){
    ipHdr = (struct ip*) (packet + sizeof(struct ether_header));
    printf("chck: %04x mychck: %04x\n\n", ipHdr->ip_sum, checkSum((u_short*)ipHdr, sizeof(struct ip)));
}

if は、IP パケット (イーサネット ヘッダー タイプ フィールドのコード 8) のみをフィルタリングしています。

これは、プログラムを実行したときの出力です..

chck: ef66 mychck: 06ee

チェック: 3db8 mychck: 0264

chck: 9615 mychck: 0000

chck: edef mychck: ff64

chck: 59f1 mychck: 0164

chck: 49f1 mychck: 0264

chck: a3d4 mychck: 0c77

チェック: e36b mychck: 0264

チェック: aad4 mychck: 0c77

chck: 46d1 mychck: 0c77

chck: f40b mychck: 0264

chck: a8d4 mychck: 0c77

ネット上で実行されている他のコード例をダウンロードしましたが、pcapがパケットをコードに転送するときに、すべてのIPヘッダーに含まれる結果はどちらも得られません..

できれば助けてください、ありがとう。

4

2 に答える 2

1

正しい方法はRFC 1071に記載されています。あなたは近くにいますが、葉巻はまだありません。

于 2012-09-11T00:26:35.173 に答える
0

チェックサムを計算するためにこのソースコードを試してみてください。私はそれを使用しており、ソフトウェアに最適です。

            int
checksum
            (unsigned short *   data,
            int         length)
{
    register int                nleft   = length;
    register unsigned short     *   w   = data;
    register int                sum = 0;
    unsigned short              answer  = 0;

    while (nleft > 1)
    {
        sum     += *w++;
        nleft   -= 2;
    }

    if (nleft == 1)
    {
        *(unsigned char *)(&answer) = *(unsigned char *)w;
        sum+=answer;
    }

    sum = (sum>>16) + (sum & 0xffff);
    sum += (sum>>16);
    answer = ~sum;

    return answer;
}
于 2012-09-11T14:04:51.270 に答える