2017-06-29 10 views
2

をずらし合計+がシフトしている右の16ビットはthis line of codeで合計:なぜICMPチェックサムは、私が(補完される前に)なぜICMPチェックサムの合計を理解するのに苦労しています16ビット

checksum bs = let bs' = (if (BL.length bs) `mod` 2 == 0 then bs else BL.snoc bs 0) 
        ws = runGet listOfWord16 bs' 
        total = sum (map fromIntegral ws) :: Word32 
       in complement (fromIntegral total + fromIntegral (total `shiftR` 16)) 

RFC 792ましたこれは、チェックサムの計算について言いたいこと:1のの16ビットのもの補数は

チェックサム

チェックサムをありますは、ICMPタイプで始まるICMPメッセージの合計を補完します。 チェックサムの計算には、チェックサムフィールドはゼロにする必要があります。 全長が奇数の場合、受信データにチェックサムを計算するために0のオクテットが1つ埋め込まれます。このチェックサムは、今後 に変更される可能性があります。

算出する理由bs'によって要求されるように、私は、理解を「全長が奇数の場合、受信されたデータは、チェックサムを計算するためのゼロの1つのオクテットでパディングされます。」

私もtotal = sum (map fromIntegral ws) :: Word32

私は、なぜこのコード行では把握することはできませんのコード行で行われ、16ビット・ワードの合計を加算理解することができます:

complement (fromIntegral total + fromIntegral (total `shiftR` 16)) 

その+ fromIntegral (total `shiftR` 16)をすべて含める必要があります。

注:リンクされたコード行で行われたようにtotal + total `shiftR` 16を補完すると、チェックサムが正しいことがwiresharkによって確認されています。だから私はそれが正しいことを知っている、私はちょうど理由を理解していない。

+0

として「キャリーの周りに終わる」を計算することができます。また、この回答を見つけようとしている間、私はしばらく時間を費やしていました。後ろ向きの視界ではリンクが見えているようですが、他の人が同じように検索します。 –

+1

これは問題ありません。[クローズされた重複は削除されません](https:// meta。stackexchange.com/a/10844/229359)他の誰かがそれを同じように見つけることができます。 – Cactus

答えて

4

RFC 1071は、この重要な部分を含め、詳細にチェックサムの定義について説明します。2の補数マシンで

を、1の補数和は「キャリーの周りに終わる」によって計算さ 、すなわち、任意のものでなければなりませんオーバーフロー の最上位ビットは、最下位ビット に追加されます。コードで

total = sum (map fromIntegral ws) :: Word32 

は、すなわち、その下位16ビット、32ビットの合計である運ぶことなく和であり、上位16ビットは、搬送の和を含むことになります。 fromIntegral :: Word32 -> Word16は切り捨てを行うことを利用して、我々は

low = fromIntegral total :: Word16 
high = fromIntegral $ total `shiftR` 16 :: Word16 

を持っているので、私たちはあなたの説明は(少なくとも私には)非常に明確ですが、多分

eac = low + high 
+0

リンクされた質問の答えは、上位ビットがゼロになることを確認するためにこれを2回行う必要があることを示唆しています。 – dfeuer

関連する問題