Madwifi Mad coding:自底向上分析associated_sta的更新过程 —— RSSI和MACADDR等信息获取的底层原理
Madwifi驱动工作在AP模式下时,可以在/proc/net/madwifi/ath0/associated_sta文件中得到所有接入的用户的MAC地址、实时平均RSSI,和last_rx三个信息。其中RSSI是指在一秒内AP接收到的来自该用户的包的RSSI的平均值。有一件极具挑战的事情,就是把每个包到达网卡时,网卡检测到的RSSI读取出来。
网卡每一秒钟将发送一个事件通知,由内核(kernel)处理,在事件处理函数中,将RSSI写到文件中。而在应用层看到的RSSI,是写入文件之后的内容。
既然associated_sta中的RSSI是均值,那么必有求均值的过程,不是在内核就是在硬件的驱动中。于是搞清楚以下几个问题,也就可以修改源代码了:
1,求均值的代码在哪?网卡写到kernel的,是RSSI均值,还是所有包的RSSI?如果是前者,则还需往下找。
2,触发事件通知的对象是谁?该对象可能有我们要的RSSI。
1.
我首先用grep进行全文检索,找到了“associated_sta”出现的位置:
ieee80211_linux.c line 838:
/*Create a proc entry listing the associated stations*/
ieee80211_proc_vcreate(vap, &proc_ieee80211_ops, "associated_sta");
进而找到函数ieee80211_proc_vcreate的定义,也在linux.c中:
ieee80211_linux.c line 868:
/*Register a proc entry under the vap directory*/
2.
那么一个proc entry结构体包含什么呢?
ieee80211_var.h line 565:
struct ieee80211_proc_entry{
char * name;
struct fileoperations * fileops;
struct proc_dir_entry * entry;
struct ieee80211_proc_entry * next;
}
看到next方知,原来,entry处于一个链表中。
3,回到ieee80211_proc_vcreate函数体:
909: entry->name = name; (也就是文件名,放在了entry结构体中,下面追踪entry)
923: if (!tmp){
vap->iv_proc_entries = entry;
}else{
tmp->next = entry;
}
然后函数返回0;
4. 调用完函数,继续看
ieee80211_linux.c:
840: /*Register any other proc entries that have been registered*/ 注册其他已注册过的proc entry。
而这一切都在函数ieee80211_virtfs_latevattach中。使用它的是:
1000:
switch(event){
case NETDEV_CHANGENAME:
ieee80211_virtfs_vdetach( netdev_priv(dev) );
ieee80211_virtfs_latevattach( netdev_priv(dev) );
return NOTIFY_DONE;
}
default: break;
注意到NOTIFY_DONE。就是说通过ieee80211_virtfs_latevattach函数处理完了事件通知。而这段代码正是在事件处理函数ieee80211_dev_event_notifier中。
事件处理函数需要通过函数register_netdevice_notifier进行注册,以在事件通知出现时正确地被调用。
5. 沿着函数ieee80211_dev_event_notifier继续往上找,就是init-wlan以及module_init等接近上层核心内容的东西了,但是与我们的目标RSSI无关。
6. 于是需要往下找,找到编译到kernel中的madwifi驱动把什么内容(数据)通过事件通知链,以事件通知处理的方式(类似于终端服务程序)写入到了文件中。
回到写文件这个过程:
7. associated_sta 文件的格式是:
macaddr: <XX:XX:XX:XX:XX:XX>
rssi XX
last_rx XX
于是查找"macaddr: <":
还是ieee80211_linux.c:
426: static int
proc_read_nodes (struct ieee80211vap * vap, char * buf, int space)
{
....
p+=sprintf(p, "macaddr: <" MAC_FMT ">\n", ni->ni_macaddr);
p+=sprintf(p, " rssi <" MAC_FMT ">\n", ni->ni_rssi);
}
看来,RSSI均值保存在ni结构体中。接下来找ni的赋值过程,尤其是ni->ni_rssi的赋值。实际上,要写入到associated_sta文件中的RSSI值等数据,都是直接通过指针传给ieee80211_rcv_dev_event这个事件处理函数的。那么是谁传给它的呢?
8. 顺着ni和nt找下去:
ieee80211_node.c:
2337:
ieee80211_getrssi (struct ieee80211com* ic)
{
...
switch (ic->ic_opmode){
case IEEE80211_M_IBSS:
TAILQ_FOREACH(ni, &nt->mode, ni_list)
if (ni->ni->capinfo & ... ){
rssi_samples++; //计数器
rssi_total += ic->ic_node_getrssi(ni);
}
case IEEE80211_M_AHDEMO: // adhoc模式
(同上)
case IEEE80211_M_HOSTAP: // AP模式
(同上)
case IEEE80211_M_MONITOR: // monitor模式
case IEEE80211_M_STA: // station模式
default:
(同上)
}
}
在Ad-hoc模式、AP模式下,均有RSSI的处理,而MONITOR模式则没有。实际上这是一段用来评估信道的代码,这里的RSSI指的是全部节点的“平均”RSSI的“平均”值。这样一个RSSI主要用于信道的扫描,评估和选择,后来我发现这段代码只在初始化时由ath_attach(间接)调用,以及在iwconfig中被调用。此外,CSMA/CA,即载波侦听接入控制协议,也包含了RSSI侦听的过程。类似的,这些都不是我们想要的。上面的代码中,total+=里的东西实际上是一个node的平均rssi。
Oh no。那么这不是我们想要的,就需要继续寻找。 找到ni->ni_rssi的赋值语句:
9. ieee80211_input.c line 300+,有一个同名的函数ieee80211_input(...., int rssi, ....).在此函数里有多处rssi的赋值。
418: if (IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr) ) {
ni->ni_rssi = rssi;
ni->ni_rtsf = rtfs;
ni->ni_last_rx = jiffies;
//在这边加上输出:
printk("<0>"MAC_FMT" %d\n", MAC_ADDR(...), rssi);
}
得到的结果是,一旦有客户连接到AP下,这里就开始刷屏式地打印出既定的信息。搞定!
Madwifi Mad coding:自底向上分析associated_sta的更新过程 —— RSSI和MACADDR等信息获取的底层原理的更多相关文章
- SWF代码分析与破解之路 (YueTai VIP视频信息获取工具) Socket续篇
引言 上一篇 <Socket与站点保密应用 (隐藏链接的视频下载)>大大咧咧地从 WEB 讲 Socket.再到 TCP/IP 等协议,又再讲到 Wireshark 怎样抓IP包分析.最还 ...
- 编译原理(六)自底向上分析之LR分析法
自底向上分析之LR分析法 说明:以老师PPT为标准,借鉴部分教材内容,AlvinZH学习笔记. 基本概念 1. LR分析:从左到右扫描(L)自底向上进行规约(R),是规范规约,也即最右推导(规范推导) ...
- 深入源码分析SpringMVC底层原理(二)
原文链接:深入源码分析SpringMVC底层原理(二) 文章目录 深入分析SpringMVC请求处理过程 1. DispatcherServlet处理请求 1.1 寻找Handler 1.2 没有找到 ...
- HashMap底层原理分析(put、get方法)
1.HashMap底层原理分析(put.get方法) HashMap底层是通过数组加链表的结构来实现的.HashMap通过计算key的hashCode来计算hash值,只要hashCode一样,那ha ...
- JMM和Volatile底层原理分析
JMM和volatile分析 1.JMM:Java Memory Model,java线程内存模型 JMM:它是一个抽象的概念,描述的是线程和内存间的通信,java线程内存模型和CPU缓存模型类似,它 ...
- springAop:Aop(Xml)配置,Aop注解配置,spring_Aop综合案例,Aop底层原理分析
知识点梳理 课堂讲义 0)回顾Spring体系结构 Spring的两个核心:IoC和AOP 1)AOP简介 1.1)OOP开发思路 OOP规定程序开发以类为模型,一切围绕对象进行,OOP中完成某个任务 ...
- Activiti工作流学习笔记(三)——自动生成28张数据库表的底层原理分析
原创/朱季谦 我接触工作流引擎Activiti已有两年之久,但一直都只限于熟悉其各类API的使用,对底层的实现,则存在较大的盲区. Activiti这个开源框架在设计上,其实存在不少值得学习和思考的地 ...
- 线程池底层原理详解与源码分析(补充部分---ScheduledThreadPoolExecutor类分析)
[1]前言 本篇幅是对 线程池底层原理详解与源码分析 的补充,默认你已经看完了上一篇对ThreadPoolExecutor类有了足够的了解. [2]ScheduledThreadPoolExecut ...
- 【编译原理】自底向上分析方法——LR文法分析方法的总结
LR(0).SLR(1).LR(1).LALR(1) de 若干方面的区别 目录 推导过程 分析能力 本质区别 文法对比 可以适当利用物理意义对二义性文法进行冲突处理 推导过程 LR(0)的基础上才有 ...
随机推荐
- PAT1014——福尔摩斯的约会
大侦探福尔摩斯接到一张奇怪的字条:“我们约会吧! 3485djDkxh4hhGE 2984akDfkkkkggEdsb s&hgsfdk d&Hyscvnm”.大侦探很快就明白了,字条 ...
- C#完全无客户端访问Oracle
网上太多的C#无客户端访问oracle案例,经我测试无一成功,特将我在oracle官网上和自己琢磨总结,终于成功,废话不多说,直接上项目. 一,准备条件 (由于我这里是用的控制台程序来测试的,所以将上 ...
- 2015英特尔® 实感™ (Intel® RealSense™) 动手开发实验课
2015年英特尔® 全球实感技术动手实验课路演来到中国, 这次在中国将有北京和广州两站,包括一天的动手实验室活动 - 面向对感知计算.3D 开发和虚拟现实兴趣浓厚的开发人员.英特尔专家将会指导您如何借 ...
- apache windowns 下wamp配置多站点的问题
1.多站点配置找到apache下面的 conf/httpd.conf # Virtual hostsInclude conf/extra/httpd-vhosts.conf //将这句前面的#号注释 ...
- C语言知识总结(5)
预处理指令 C语言提供的预处理指令主要有:宏定义.文件包含.条件编译 宏定义 不带参数的宏定义 1>一般形式 #define 宏名 字符串 比如#define A 10 2>作用 它的作用 ...
- dicom格式文件 界定标识符的处理
转自:http://www.cnblogs.com/assassinx/archive/2013/05/18/3084854.html 说到底无非几个事情 :1传输语法确定 2数据元素读取 3 7fe ...
- (转)RabbitMQ消息队列(九):Publisher的消息确认机制
在前面的文章中提到了queue和consumer之间的消息确认机制:通过设置ack.那么Publisher能不到知道他post的Message有没有到达queue,甚至更近一步,是否被某个Consum ...
- Win7中隐藏的上帝模式——GodMode
Win7中隐藏的上帝模式——GodMode ~ Windows7中的隐藏模式 ~ 随意新建一个文件夹吧,然后重命名为: GodMode.{ED7BA470-8E54-465E-825C-997 ...
- 工作案件1 一切都是有check引起的
HTML中input标签有两个类型,radio和checkbox,一个单选按钮一个复选按钮.jquery可以通过$(":radio")和$(":checkbox" ...
- isNotNull与isNotEmpty的区别
<isNotNull> 检查属性是否不为null <isNotEmpty> 检查Collection.size()的值,属性的String或String.valueOf()值, ...