我有一个用户空间程序,它构建自己的数据包(应用程序、UDP、IP)并将write()
其发送到 TUN 设备。该数据包被我自己的 Netfilter 模块拦截,它检查它收到的数据包是否是我们要处理的数据包。然后我的 Netfilter 模块将skb_clone()
原始skb
并创建一个响应数据包,我用一些数据填充该数据包以返回给用户空间程序。要发送响应,我使用dev_queue_xmit()
. NET_XMIT_CN
即使我刚刚创建了一个新的 TUN 设备并且没有其他流量通过,它也会随机返回。如果我继续执行用户空间程序(向 TUN 设备发送新数据包),最终 TUN 设备会响应,但不会始终如一。我似乎无法追查为什么它的行为如此不规律。
本质上,我使用 TUN 设备作为从用户空间到内核空间进行通信的机制,反之亦然。
这是我的用户空间应用程序:
tun_fd = tun_alloc(dev_name);
packet = ... /* Construct request...*/
nwrite = write(tun_fd, packet, packet_len);
...
unsigned recv_buf[1500];
int received = 0;
while (!received) {
nread = read(tun_fd, recv_buf, 1500);
...
}
...
close(tun_fd);
这是我的 Netfilter 模块:
static struct nf_hook_ops nfho;
static int __init my_hook(void)
{
nfho.hook = hook_func;
nfho.hooknum = 0;
nfho.hook = PF_INET;
nfho.hook = NF_IP_PRI_FIRST;
nf_register_hook(&nfho);
}
unsigned int hook_func(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
{
struct sk_buff *clone_skb = skb_clone(skb, GFP_KERNEL):
...
/*
* Check if packet is for us.
* Check IP & UDP header, etc
* If so, parse request, put together response clone_skb
*/
...
if ((err = dev_queue_xmit(clone_skb)) != 0) {
printk(....)
/* Either it return 0 (success) or 2, meaning NET_XMIT_CN */
}
return NF_STOLEN;
}
我似乎无法弄清楚这种行为。我是否误用了 TUN 设备?还有比这更简单的方法吗?
请让我知道我是否应该提供任何额外的细节或澄清一些事情。