我正在尝试更改 netfilter 后路由挂钩中 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 计算伪标头而 csum_partial 计算有效负载和 tcp_header 的展开校验和是否正确?
我真的想避免自己编写函数,因为内核会更快,因为底层函数使用汇编进行计算。
有没有其他可行的方法?还是我错过了什么?