首页 > 解决方案 > Linux数据包处理绕过内核协议栈

问题描述

我想通过开发内核模块以自己的逻辑处理数据包。

更具体地说,对于发送到 的数据包enp0s3,我想删除其以太网标头并将其发送到tap1tap1是一个水龙头设备。

问题是:我无法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");

标签: clinuxlinux-kernelnetwork-programmingkernel-module

解决方案


推荐阅读