在Linux内核中使用skb_make_writable和skb_ensure_writable

我写了一个netfilter钩子来修改应用程序层中的某些数据。我尝试通过以下方式获取应用程序数据的开始和结束:

sturct iphdr* iph = ip_hdr(skb);
struct tcphdr* tcph;
char *data_start,*data_end;
if(iph -> protocol != IPPROTO_TCP)
    return NF_accEPT;
tcph = tcp_hdr(skb);
data_start = (char *)tcph + tcph -> doff * 4;
data_end = (char *)tcph + ntohs(iph -> tot_len) - iph -> ihl * 4;

然后,例如,打印第一个字符:

if(data_end - data_start >= 1)
    printk("%x\n",*data_start);

但是我发现代码并不总是能正常工作,因为有时应用程序数据似乎并没有完全放在TCP标头后面。

我找到了解决方案:在读取应用程序数据并重新获取标头和char指针之前,先使用skb_ensure_writable(或旧内核中的skb_make_writable):

sturct iphdr* iph = ip_hdr(skb);
struct tcphdr* tcph;
char *data_start,*data_end;
if(iph -> protocol != IPPROTO_TCP)
    return NF_accEPT;
tcph = tcp_hdr(skb);
data_end = (char *)tcph + ntohs(iph -> tot_len) - iph -> ihl * 4;

skb_ensure_writable(skb,(char*)data_end - (char*)skb -> data);

iph = ip_hdr(skb);
tcph = tcp_hdr(skb);
data_start = (char *)tcph + tcph -> doff * 4;
data_end = (char *)tcph + ntohs(iph -> tot_len) - iph -> ihl * 4;

但是我仍然有一些问题:

  1. 为什么不将应用程序数据设计为位于TCP标头的后面?
  2. TCP头是否也不能放在IP头后面?如果是,如何获取skb_ensure_writable的第二个参数?
  3. skb_ensure_writableskb_make_writeable到底是做什么的?我几乎找不到任何文件。
za80967190 回答:在Linux内核中使用skb_make_writable和skb_ensure_writable

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/2761501.html

大家都在问