2012-07-10 156 views
7

我寫一個使用Netfilter的鉤子來修改某些TCP報頭信息,並且顯然是一個內核模塊,發送前,我要重新計算校驗和。
我也在接收端編輯標題,所以我需要在那裏重新計算它。如何計算TCP校驗

網上搜索,我發現有些人說我可以簡單地將其設置爲0,它會計算對我來說,顯然沒有奏效。
我還發現這個功能

tcp_v4_send_check(struct sock *sk, struct sk_buff *skb); 

雖然沒有人解釋這是怎麼使用的,以及是否我可以在接收/實際使用它發送相同的方式。
我自己嘗試是校驗設置爲0,則調用該函數傳遞SKB我已經和是skb-> SK我有,仍然一無所獲。

那麼請問,什麼是直接計算TCP數據報校驗和的方法?

+0

你究竟什麼設置爲0,你在哪裏期望找到校驗?查看代碼,你應該設置tcp_hdr(skb) - > check爲0,然後調用該函數,之後新的校驗和應該在那裏。 – BjoernD 2012-07-10 09:16:59

+0

,這正是我所做的,但是當我加載模塊時,所有的TCP連接都不起作用。 – Fingolfin 2012-07-10 10:25:04

+0

您應該在問題中添加「C」標籤。順便說一句,看看http://www.winpcap.org/pipermail/winpcap-users/2007-July/001984.html – Jite 2012-07-10 10:27:47

回答

3

要重新計算校驗和,你更好地計算增量校驗 - 只需要修改根據你已經改變了各個領域,現有的校驗和,而不是讀取整個數據包。

這必須在你改變數據包來實現,當你知道這兩個老的價值觀和您存儲的新值。

的基本思想是tcp->check += (new_val - old_val)
這比這更復雜一點,因爲:
1. old_valnew_val需要是16位值,它們在2個字節上對齊(例如更改端口號)。
2.校驗和使用補碼算術,所以你需要做「帶反饋」。這基本上意味着,如果tcp->check + new_val - old_val爲負值,則需要從結果中減去1。

+1

這是做這件事的正確方法。它速度更快,數據損壞風險更小。從頭開始重新計算校驗和可能會掩蓋已經發生的任何數據損壞。 – kasperd 2015-10-17 22:08:02

1

這裏是一個結合網絡過濾器API +校驗的TCP(而不是IP)的例子:

http://www.linuxvirtualserver.org/software/tcpsp/index.html

查找到一個名爲tcpsp_core.c文件。 (注意先分配零,計算校驗和,然後IP校驗和表示爲不需要)。

取決於ü加載哪個網絡過濾模塊(有很多!!!),他們將在不同的層,例如,在iptable的IP層工作的工作如下所示(圖像):

http://ars.sciencedirect.com/content/image/1-s2.0-S1389128608004040-gr3.jpg

1

@烏戈倫的答案並不準確。根據RFC1624 https://tools.ietf.org/html/rfc1624,這有時會產生-0(0xFFFF),這是不允許的。

計算校驗和應該是正確的方法: new_tcp_check = ~(~old_tcp_check + ~old_val + new_val)