簡體   English   中英

UDP校驗和計算

[英]UDP checksum calculation

/usr/include/netinet/udp.h定義的UDP頭結構如下

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

標頭的檢查字段中存儲了什么值? 如何驗證校驗和是否正確? 我的意思是計算校驗和的數據是什么? (它只是 udp 標頭還是 udp 標頭加上它后面的有效負載?)

謝謝。

執行在UDP校驗和的整個有效載荷,並且在報頭中的其它字段,從IP報頭的某些字段。 為了執行計算(通過這個偽頭、UDP 頭和有效載荷完成),從 IP 頭構造了一個偽頭。 包含偽標頭的原因是為了捕獲已路由到錯誤 IP 地址的數據包。

基本上,在接收端,將所有 16 位字頭和數據區相加(以 16 位換行),並根據0xffff檢查結果。

在發送端,它有點復雜。 對所有 16 位值執行補碼求和,然后取該值的補碼(即,反轉所有位)以填充校驗和字段(附加條件是計算出的校驗和為零將更改為所有一位)。

一的補總和是不是所有的人的補碼值的簡單相加。 它有點復雜。

基本上,您有一個從零開始運行的 16 位累加器,然后將每個 16 位值相加。 每當這些加法之一導致進位時,該值就會被環繞,然后您再次向該值添加 1。 這有效地采用了 16 位加法的進位位並將其添加到值中。


順便說一句,這純粹是我的猜測,但這可能可以通過使用ADC (帶進位相加)指令而不是ADD (令人驚訝的是,相加)指令或 CPU 上可用的任何等效指令來有效地完成時間。

如果沒有進位, ADC只會從進位中添加零位。 在這些東西完成的日子里(是的,不幸的是,我已經那么老了),內存比速度更受限制,現在情況並非如此,因此在代碼中節省幾個字節可以很好地提升你宇宙半神皇的水平:-)


請注意,您永遠不必擔心第二次進位(或者如果您使用上一段中提到的方法,則下一個ADC的進位是兩個),因為兩個最大的 16 位值相加后產生(從0x1fffe截斷 ) 0xfffe - 添加一個永遠不會導致另一個進位。

一旦計算出計算出的補碼和,將其位反轉並插入到數據包中,這將導致接收端計算產生0xffff ,當然假設傳輸沒有錯誤。

值得注意的是,負載總是被填充以確保有整數個 16 位字。 如果它填充,長度字段會告訴您實際長度。

RFC768是詳細說明這一點的規范。

Gerd Hoffmann 完成了一個很好且易於理解的 UDP 校驗和計算示例。

您可以在 google 上搜索“net-checksum.c Gerd Hoffmann”或查看此處的文件:

https://gist.github.com/fxlv/81209bbd150abfeaceb1f85ff076c9f3

您可以使用net_checksum_tcpudp函數,向它提供 UDP 有效負載長度、proto、src 和 dst IP,然后提供 UDP 有效負載本身,它會做正確的事情。

最后你必須在校驗和上調用htons()並且你很好。

我在網上搜索一些將計算 udp 標頭的代碼(使用上面提到的偽 ip 標頭)。

終於找到了open-bsd dhclient packet.c:

https://github.com/openbsd/src/blob/master/sbin/dhclient/packet.c

查看函數assemble_udp_ip_header()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM