【问题标题】:How to push skb in specific point of Linux network stack?如何在 Linux 网络堆栈的特定点推送 skb?
【发布时间】:2014-01-31 21:49:26
【问题描述】:

我想将 skb 推送到 Linux 网络堆栈的prerouting 点。有没有办法做到这一点? 我使用了dev_queue_xmit()netif_rx() 函数,但我认为它们不能将skb 推送到Linux 网络堆栈的prerouting 点。

【问题讨论】:

  • 您能否详细说明内核版本?没有内核版本很难具体
  • @Pegasus 我正在使用内核 3.2
  • 你真正想要达到什么目的?想将 skb 从哪里推送到预路由?能否请您详细说明
  • 我想在预路由点注册ioctl,然后从用户空间通过SEND_PACKET(buffer, size) ioctl发送数据包。
  • @Khajavi 根据发送数据包,一个简单的 send() 系统调用就足够了,我不知道你为什么要这样。您可以使用 netfilter 挂钩的概念在预路由点调用,您可以进行函数挂钩,并且可以在该点做任何您想做的事情。我认为你需要看看 netfilter 教程。

标签: c linux-kernel network-programming kernel linux-device-driver


【解决方案1】:

我不完全清楚这个 skb 的来源哪里。在用户空间中,有两种方法可以做到这一点。一种是使用tun 设备(只需将数据包写入其中)。另一种是使用libpcap(它有一个鲜为人知的功能,即发送隐藏在所有接收内容中的原始数据包)。

你说你想通过注册一个ioctl(大概意味着添加你自己的ioctl)然后从用户空间调用ioctl来做到这一点。当您已经可以在不修改内核的情况下实现这一点时,为什么要这样做并不是很明显。但是,如果您确实想这样做,我会按照tun 驱动程序使用的路径,并在您的新ioctl 中对tun 设备执行等效的write()-ing。这可能意味着有一个类似tun 的接口作为数据包的来源。我怀疑系统中的数据包需要某种源接口。

【讨论】:

  • 这个数据包的有效负载是从用户空间创建的,然后我想将此数据包ioctl到我的内核模块,然后我从用户空间获取数据包,知道我分配了新的skb并将数据包有效负载添加到它,知道我需要将 skb 推送到网络堆栈的预路由点。
  • 那你为什么认为netif_rx() 在这种情况下是错误的呢?这(或更准确地说是netif_rx_ni())正是drivers/net/tun.c 使用的,并且预路由绝对适用于tun。但是,我怀疑您的问题不是您调用了错误的函数,而是除非您的 skb 被跟踪为来自接口(您的接口不是),否则预路由的内容可能无法按您的意愿工作(考虑检查输入接口的预路由规则如何工作)。这就是为什么我建议使用tun 设备并且不更改内核的原因。
  • @abligh:我在 netfilter 的预路由钩子处理程序中 skb_copy() 我的 skb,修改了它的数据并想重新注入它 - 在原始 skb 旁边。这样每个接收到的数据包都被转换成2个数据包分别路由。在返回 NF_ACCEPT 之前,我试图通过链表将复制的 skb 粘贴到合法的 skb 上,但没有成功。知道如何解决这个问题吗?谢谢。
【解决方案2】:

我怀疑您希望 libpcap 或 libnetfilter_queue 在下文中统称为用户空间队列。用户态队列会将所有匹配某个规则(您定义)的数据包路由到您的用户态应用程序。 dev_queue_* 和 netif_* 函数适用于内核级路由,与用户态应用程序无关。

Userland 队列对性能有影响,根据您使用的库,您必须使用特定方法将数据包重新注入 netfilter 队列。

【讨论】:

    【解决方案3】:

    我认为您正在寻找的函数是ip_queue_xmit(),这是 IPV4 实施开始检查表、过滤器等的地方。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-01
      • 1970-01-01
      • 2012-04-23
      • 2011-03-20
      • 1970-01-01
      • 1970-01-01
      • 2011-04-01
      相关资源
      最近更新 更多