1. ホーム
  2. c

[解決済み] UDPチェックサム計算

2022-03-11 02:36:24

質問

usr/include/netinet/udp.h で定義されている UDP ヘッダ構造体は次のとおりです。

struct udphdr
{
  u_int16_t source;
  u_int16_t dest;
  u_int16_t len;
  u_int16_t check;
};

ヘッダーのcheckフィールドにはどのような値が格納されているのでしょうか?チェックサムが正しいかどうかを確認するにはどうすればよいのでしょうか?つまり、チェックサムはどのようなデータに対して計算されるのですか?(udpヘッダだけなのか、udpヘッダ+それに続くペイロードなのか?)

ありがとうございます。

解決方法は?

UDPチェックサムはペイロード全体に対して実行されます。 ヘッダーの他のフィールド IPヘッダーのいくつかのフィールド。計算を行うために、IPヘッダーから疑似ヘッダーが構築されます(この疑似ヘッダー、UDPヘッダー、ペイロードの上で計算されます)。擬似ヘッダが含まれる理由は、間違ったIPアドレスにルーティングされたパケットをキャッチするためです。

基本的には、受信側でヘッダとデータ領域の16ビットワードをすべて足し合わせ(16ビットで折り返す)、その結果を 0xffff .

送信側では、もう少し複雑です。16ビットの値すべてについて1の補数和をとり、その値から1の補数(つまりすべてのビットを反転)をとってチェックサムフィールドに入力します(計算されたチェックサムがゼロの場合はすべて1のビットに変更されるという特別な条件付きです)。

1の補数和は ない は、単に1つの補数値の総和に過ぎません。もう少し複雑です。

基本的には、0から始まる16ビットのアキュムレータが動いていて、そこに16ビットの値をすべて足していくわけです。加算の結果がキャリーになるたびに、その値はラップされ、再び値が1加算されます。これは、16ビット加算のキャリービットを効果的に取り込み、値に加算するものです。


<ブロッククオート

余談ですが、これは私の憶測ですが、これはおそらく ADC (キャリー付き加算) 命令ではなく ADD (驚くべきことに、add)など、当時のCPUで利用可能な同等の命令です。

キャリーがなかったら ADC は、キャリーからゼロビットを足すだけです。こんなことをやっていた時代には(そう、残念ながら、私は アム そのため、数バイトのコードを節約することで、宇宙の半神半人の皇帝になることができるかもしれません。)


なお、2回目以降はキャリーを気にする必要はありませんでした(次のキャリーで2回分の ADC というのも、16ビットの最大値2つを合計すると、(前項で述べた方法で計算した場合、切り捨てられた 0x1fffe ) 0xfffe - を追加しても、もうキャリーが発生することはありません。

計算された1の補数和が計算され、そのビットが反転され、パケットに挿入されると、受信側の計算では、次のようになります。 0xffff もちろん、送信時のエラーはないものとします。

注目すべきは、ペイロードは常に16ビットワードの整数倍となるようにパディングされることです。もし でした 長さフィールドは、実際の長さを示します。

RFC768 は、その詳細を記した仕様書です。