トラフィックをスニッフィングし、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にするバッファの2つのサンプルを次に示します。
$ 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
最初のバッファでは、最初の4バイトは送信元IPアドレス(c0 a8 01 2c-> 192.168.1.44)を表し、次の4バイトは宛先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));