c - 如何在Linux内核模块中获取下一个TCP段?

标签 c tcp linux-kernel network-programming

我知道我可以像这样获取 TCP 数据包数据的指针:

char *data = (char *)tcphdr + 4 * tcph->doff;

但是一旦数据被分段,我就无法以这种方式获得完整的数据。那么如何获取下一段的下一个 sk_buff 呢?

我的简单代码:

#include ...

static struct nf_hook_ops nfho;

unsigned int hook_funcion(void *priv, struct sk_buff *skb, const struct
                          nf_hook_state *state)
{

    // check if it is TCP packet

    char *data = (char *)tcphdr + 4 * tcph->doff;

    // do something here

    return NF_ACCEPT;
}

static int __init hook_init(void)
{
    int ret;

    nfho.hook = hook_funcion;
    nfho.pf = NFPROTO_IPV4;
    nfho.hooknum = NF_INET_POST_ROUTING;
    nfho.priority = NF_IP_PRI_LAST;
    ret = nf_register_hook(&nfho);
    printk("xmurp-test start\n");
    printk("nf_register_hook returnd %d\n", ret);

    return 0;
}

static void __exit hook_exit(void)
{
    nf_unregister_hook(&nfho);
    printk("xmurp-test stop\n");
}

module_init(hook_init);
module_exit(hook_exit);

最佳答案

你的问题有点复杂,因为TCP中不存在“完整数据”这样的东西,因为TCP是一个协议(protocol),而不是数据报协议(protocol)(在UDP 的对比)。这意味着数据没有特定的结束(除非连接关闭/重置)。

如果您正在处理将 TCP 流分段为一定大小的消息的应用程序层协议(protocol)(例如:HTTP),则应执行以下步骤:

  1. 解析 TCP 负载并计算出当前消息有多大。
  2. 只有这样,您才能在以下数据包/段作为同一消息的延续到达网络堆栈时对其进行处理。
  3. 最后,当您期望的所有数据都到达后,您可以将它们重新组合起来,然后才能在应用层使用它们的数据。

请记住,网络以数据报方式工作,而 TCP 是一种协议(protocol)。因此,很可能在处理第一个段时,其余数据尚未到达。因此,您必须管理此特定流上的此数据包和 future 数据包的反分段(碎片整理),然后才能解析上层协议(protocol)。

关于c - 如何在Linux内核模块中获取下一个TCP段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53692614/

相关文章:

c 字符数组和指针

c - PE装载机中的搬迁

linux-kernel - Eudyptula 挑战列表

linux-kernel - linux内核模块中的long到float转换

c - 在 C 语言中,如何将包含数字的字符串转换为 int 数组?

c - mmap 不存在的物理地址错误

C# - 通过网络序列化数据包

networking - 在进入网络时显示数据包丢失 - 可能导致什么?

c - 使用 CRIU 工具迁移特定的 TCP 连接

memory-management - Linux内核如何找到脏页来刷新?