簡體   English   中英

計算netfilter模塊中的TCP校驗和

[英]Calculating TCP Checksum in a netfilter module

我試圖在netfilter postrouting鈎子中更改IP和TCP頭中的一些字段,但是我似乎無法使內核TCP校驗和功能正常工作以后再修改它。

在TCP握手期間校驗和很好,但是一旦數據包有任何有效負載,校驗和就會出錯。

我已經通過挖掘TCP源來將這個校驗和代碼拉到一起。 我相當確定tcplen是正確的,匹配預期的TCP標頭+有效負載大小。

static unsigned int posthook_fn(
    unsigned int hooknum, 
    struct sk_buff *skb,
    const struct net_device *in, 
    const struct net_device *out,
    int (*okfn)(struct sk_buff *))
{
  struct iphdr *iph;
  struct tcphdr *tcph;
  iph = ip_hdr(skb);
  tcph = (struct tcphdr *)(skb->data + iph->ihl * 4);

  tcph->source = port;
  iph->saddr = addr;

  tcplen = (skb->len - (ip_header->ihl << 2));
  tcph->check = 0; 
  tcph->check = tcp_v4_check(tcph, tcplen, 
        iph->saddr, 
        iph->daddr, 
        csum_partial((char *)tcph, tcplen, 0)); 
  skb->ip_summed = CHECKSUM_NONE; //stop offloading

  ip_header->check = ip_fast_csum((u8 *)iph, iph->ihl);         

  return NF_ACCEPT;
}

我是否認為tcp_v4_check計算psuedo標頭並且csum_partial計算有效負載和tcp_header的展開校驗和?

我真的想避免自己編寫函數,因為內核會更快,因為底層函數使用匯編進行計算。

有沒有可行的替代方法? 還是我錯過了什么?

因為include / linux / skbuff.h,所以不需要額外調用skb_is_nonlinear():

static inline int skb_linearize(struct sk_buff *skb)
{
         return skb_is_nonlinear(skb) ? __skb_linearize(skb) : 0;
}

此外,你必須:

ip_header->check = 0

之前:

ip_header->check = ip_fast_csum((u8 *)iph, iph->ihl);

到達此處需要一段時間,但問題似乎是套接字緩沖區並不總是線性的,以下代碼確保它在計算校驗和之前。

if (skb_is_nonlinear(skb)) {
    if (skb_linearize(skb) != 0) {
        return NF_DROP;
    }
    iph = ip_hdr(skb);
    tcph = (void *)iph + (iph->ihl << 2);
}

暫無
暫無

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

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