c - Linux数据包处理绕过内核协议栈
问题描述
我想通过开发内核模块以自己的逻辑处理数据包。
更具体地说,对于发送到 的数据包enp0s3
,我想删除其以太网标头并将其发送到tap1
。tap1
是一个水龙头设备。
问题是:我无法tap1
使用 Wireshark 找到任何数据包。
dev_queue_xmit
返回码为 2。
我是 Linux 内核编程的菜鸟,我需要一些帮助!
这是我的代码:
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <linux/inet.h>
#include <net/net_namespace.h>
#include <linux/skbuff.h>
#define NIPQUAD(addr) \
((unsigned char *)&addr)[0], \
((unsigned char *)&addr)[1], \
((unsigned char *)&addr)[2], \
((unsigned char *)&addr)[3]
struct net_device *dev;
/**
* Hook function to be called.
* We modify the packet's src IP.
*/
rx_handler_result_t my_hookfn(struct sk_buff **skb)
{
printk(KERN_INFO "hook!\n");
struct sk_buff *sb=*skb;
/* remove ethernet header code here*/
// forward to tap1
struct net_device *go = dev_get_by_name(&init_net, "tap1");
if (go == NULL)
{
printk(KERN_INFO "tap1 not find \n");
return -1;
}
sb->dev = go;
int status = dev_queue_xmit(sb);
printk(KERN_INFO "forward status is %d\n", status);
return RX_HANDLER_CONSUMED;
}
int init_module()
{
int ret;
dev = dev_get_by_name(&init_net, "enp0s3");
if (dev == NULL)
{
printk(KERN_INFO "enp0s3 not find \n");
return -1;
}
ret = netdev_rx_handler_register(dev, my_hookfn, NULL);
if (ret != 0)
{
printk(KERN_INFO "module is NOT loaded into the kernel\n");
return -1;
}
else
{
printk(KERN_INFO "module IS loaded into the kernel\n");
return 0;
}
}
void cleanup_module()
{
netdev_rx_handler_unregister(dev);
printk(KERN_INFO "module has been unloaded\n");
}
MODULE_AUTHOR("lhy");
MODULE_LICENSE("GPL");