1

我在这里有一段相当具体的代码,到目前为止,互联网并没有什么帮助。我正在尝试编写一段代码(对于初学者)应该能够读取 802.11(无线)数据包并从 MAC 标头打印信息。我尝试用不同的教程、内核信息片段来编写我的代码……我正在尝试编写的程序是一个可加载的 android 内核模块(尽管 linux 内核非常相似)。虽然我目前可以接收 sk_buff 数据包,但在我看来这些是完全错误的。这是我到目前为止的代码:

/* 
 *  AUTHOR:     MATHIEU DEVOS
 *  
 */
/* Needed by all modules */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

/* KModule specific */
#include <linux/skbuff.h> /* ptype_function and others */
#include <linux/netdevice.h> /* used to print list of devices */
#include <linux/nl80211.h> /* used for iftypes types */
#include <net/cfg80211.h> /* used to handle ieee80211_ptr that point to wireless_dev*/
#include <linux/if_ether.h> /* used to specifiy which ethernet packages driver gets, not for header! */
#include <linux/netfilter.h> /* used to determine what to do with the packets */
#include <linux/string.h> /* used for memcmp */
#include <linux/ieee80211.h> /* used for 802.11 header and constants */
#include <net/mac80211.h> /* used for handling skb and getting hw */

/* used to show defines, currently unused, remove later on */
#define STR(x) #x
#define SHOW_DEFINE(x) printk(KERN_CRIT "%s = %s\n", #x, STR(x));


/* defines for modinfo */
#define DRIVER_AUTHOR "Mathieu Devos <mathieu.devos@ugent.be>"
#define DRIVER_DESC "Basic ethernet test"

/* Actual coding start */

/* initialisation of variables and functions */

    /* variables */
struct net_device *dev;
struct ieee80211_hw *hw;
static int foundWLAN = 0;
static struct packet_type ptype;

    /* functions */
static void print_mac_hdr(struct ieee80211_hdr *e_hdr);
static int dev_is_wireless(struct net_device *dev);
static void throw_hook(struct net_device *dev);
static int ptype_function(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *dev2);


/*start of functions*/

static void print_HWinfo(void){
    printk(KERN_CRIT "Network device: %s\n",dev->name);
    printk(KERN_CRIT "Network address: %pM\n",dev->dev_addr);
}

static int dev_is_wireless(struct net_device *dev){
    #ifdef CONFIG_WIRELESS_EXT
        if(dev->wireless_handlers && dev->operstate!=5){
            return 1;
        }
    #endif
    if(dev->ieee80211_ptr && dev->operstate!=5){
        return 1;
    }


    return 0; /* default false */
}

static int ptype_function(struct sk_buff *skb, struct net_device *dev1, struct packet_type *ptype, struct net_device *dev2){


    struct ieee80211_hdr *whdr = NULL;
    whdr = (struct ieee80211_hdr *)skb->mac_header;




    printk(KERN_CRIT "head: %pF",skb->head);
    printk(KERN_CRIT "mac_header: %pF",skb->mac_header);
    printk(KERN_CRIT "network_header: %pF",skb->network_header);
    printk(KERN_CRIT "transport_header: %pF",skb->transport_header);

    printk(KERN_CRIT "len: %u",skb->len);
    printk(KERN_CRIT "data_len: %u",skb->data_len);
    printk(KERN_CRIT "mac_len: %u",skb->mac_len);
    printk(KERN_CRIT "hdr_len: %u",skb->hdr_len);

    printk(KERN_CRIT "SKBUFF size: %u", sizeof(*skb));


    /*
    print_mac_hdr(whdr); */

    /* sizeof(*whdr)) = 30 bytes */
    /* sizeof(*ehdr)) = 14 bytes */

    if(memcmp(whdr->addr1,dev1->dev_addr,dev1->addr_len)==0){
        print_mac_hdr(whdr);
    }


    dev_kfree_skb(skb);
    return NF_DROP; /* NF_DROP Basically, print the info of the all the packets flying around, then drop it */
}

static void print_mac_hdr(struct ieee80211_hdr *whdr){

    printk(KERN_CRIT "DA ADDR: %pM\n",whdr->addr1);
    printk(KERN_CRIT "BSSID ADDR2: %pM\n",whdr->addr2);
    printk(KERN_CRIT "SA ADDR3: %pM\n",whdr->addr3);
    printk(KERN_CRIT "UNUSED ADDR4: %pM\n",whdr->addr4);
    /*printk(KERN_CRIT "PROTOCOL: 0x%04x\n",ntohs(ehdr->h_proto));*/
}

static void throw_hook(struct net_device *dev){
    ptype.type = htons(ETH_P_ALL); /* listen to all ethernet packets! This should still work, even for 802.11, change later */
    ptype.func = &ptype_function;
    ptype.dev = dev;
    dev_add_pack(&ptype);
    printk(KERN_CRIT "Done setting up packet type");

}

static void delete_hook(struct net_device *dev){
    dev_remove_pack(&ptype);
    synchronize_net();
}

/* Handle init and exit of module */

static int __init init_mymodule(void){
    printk(KERN_CRIT "Started kernel module!\n");

    dev = first_net_device(&init_net);
    while(dev && !foundWLAN){
        foundWLAN = dev_is_wireless(dev);
        if(!foundWLAN){
            dev = next_net_device(dev);
        }
    }

    if(dev && dev->ieee80211_ptr->iftype==NL80211_IFTYPE_STATION){
        print_HWinfo();

        /*
        hw = wiphy_to_ieee80211_hw(dev->ieee80211_ptr->wiphy);
        if(!hw){
            printk(KERN_CRIT "Could not assign HW!");
        }else{
            printk(KERN_CRIT "Assigned hw!");
        }
        */

        throw_hook(dev);
    }

    return 0;

}

static void __exit exit_mymodule(void){

    delete_hook(dev);

    printk(KERN_CRIT "Finished kernel module, exiting \n");
}

module_init(init_mymodule);
module_exit(exit_mymodule);

/*
 *   Extra info for modinfo
 */

MODULE_LICENSE("GPL");

MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);

我知道的当前项目:

  1. 在检查 wifi 设备时,我同时收到 p2p0 和 wlan0,因为我想编写通用代码,我不希望仅根据名称选择“正确”设备。因此,为什么我要根据 DORMANT(运行状态)状态来选择它。
  2. 目前我不知道是否必须调用硬件信息(wiphy_to_ieee80211_hw),但是当尝试运行所述函数时,我的 __init 不再返回 0(因此它得到一个错误代码),我什至无法启动我的模块。
  3. 当尝试使用 skb->data 时,我的内核崩溃并且尝试读取数据指针 (*data) 会导致崩溃。
  4. 正如您在下面的示例输出中看到的那样,我当前同时接收到 mac_len 和 data_len 是完全错误的。Mac_len 应该是 30(802.11 标头的字节)并且 data_len 不应该一直为 0。

当前输出的示例:

<2>[19476.400718] c0 head: 0xe2e4f440
<2>[19476.400766] c0 mac_header: 0xe2e4f48e
<2>[19476.400818] c0 network_header: 0xe2e4f432
<2>[19476.400873] c0 transport_header: 0xe2e4f440
<2>[19476.400929] c0 len: 78
<2>[19476.400964] c0 data_len: 0
<2>[19476.401003] c0 mac_len: 14
<2>[19476.401041] c0 hdr_len: 0
<2>[19476.401079] c0 SKBUFF size: 184
<2>[19476.401307] c0 head: 0xe2e4f440
<2>[19476.401362] c0 mac_header: 0xe2e4f4dc
<2>[19476.401423] c0 network_header: 0xe2e4f432
<2>[19476.401485] c0 transport_header: 0xe2e4f440
<2>[19476.401541] c0 len: 156
<2>[19476.401577] c0 data_len: 0
<2>[19476.401615] c0 mac_len: 14
<2>[19476.401656] c0 hdr_len: 0
<2>[19476.401701] c0 SKBUFF size: 184

希望对这些问题有一些积极的见解,因为我是在这个网站上发帖的新手,但是已经使用它很长一段时间来帮助我解决我的编程问题。

在我保存所有进度并尝试明天寻找更多内容之前先进行快速编辑:

添加:

extern struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy);

到函数初始化(当尝试做同样的事情但使用 wiphy_to_ieee80211_hw 而不是 *wiphy_to_ieee80211_hw 我似乎得到了一大堆错误)。使用指针函数 (*wiphy_to_ieee80211_hw) 我只知道它是未定义的。所以它仍然是未定义的这个函数,这对我来说很烦人。我更改了我的makefile以添加:KBUILD_EXTRA_SYMBOLS=../kernel/net/mac80211(这是export_symbol所在的位置:../kernel/net/mac80211/util.c)总makefile:

obj-m += ethernet_test.o

all:
  make -C ../kernel M=$(PWD) KBUILD_EXTRA_SYMBOLS=../kernel/net/mac80211 modules
clean:
  make -C ../kernel M=$(PWD) clean

还尝试在 __init 部分再次加载 ieee80211_hw:

struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(dev->ieee802_ptr->wiphy);

但是由于这仍然是未定义的,它不会导致 ieee80211_hw,因此它会导致我的模块崩溃(甚至不会加载):(。

4

0 回答 0