我在这里有一段相当具体的代码,到目前为止,互联网并没有什么帮助。我正在尝试编写一段代码(对于初学者)应该能够读取 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);
我知道的当前项目:
- 在检查 wifi 设备时,我同时收到 p2p0 和 wlan0,因为我想编写通用代码,我不希望仅根据名称选择“正确”设备。因此,为什么我要根据 DORMANT(运行状态)状态来选择它。
- 目前我不知道是否必须调用硬件信息(wiphy_to_ieee80211_hw),但是当尝试运行所述函数时,我的 __init 不再返回 0(因此它得到一个错误代码),我什至无法启动我的模块。
- 当尝试使用 skb->data 时,我的内核崩溃并且尝试读取数据指针 (*data) 会导致崩溃。
- 正如您在下面的示例输出中看到的那样,我当前同时接收到 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,因此它会导致我的模块崩溃(甚至不会加载):(。