hostapd wpa_supplicant madwifi详细分析——hostapd整体梳理

Posted 奔跑的路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hostapd wpa_supplicant madwifi详细分析——hostapd整体梳理相关的知识,希望对你有一定的参考价值。

     这篇主要对hostapd这个程序做一个整体的梳理,自己也觉得前面说的都好乱,尽是一些代码的分析,过于细节了。

     关于EAP状态机的转化,这里就不多说了,点击打开链接 这里可以下载原文档,知道的是自己不会比原文档写的还好的,所以就放弃了介绍状态机了。

    

       先理解一下 struct hapd_interfaces interfaces 这个结构体对象, 这个结构体里面封装的是一个count成员和一个 struct hostapd_iface  **iface成员:

       struct hapd_interfaces interfaces

                  size_t  count;

                  struct hostapd_iface  **iface;  

       所以interfaces其实是对接口的封装,也许有多张无线网卡,那么就会有多个无线接口(注意区分空中接口),那么hostapd程序的interfaces就会封装多个 iface对象,并用count计数。比如我现在hostapd需要用两张网卡来创建两个接口,一个是2.4G、一个是5G的网络,那么调用hostapd 传入参数时,就需要传入两个配置文件,count将会获得值2,并且会创建两个结构体指针 iface[0]和iface[1] (  struct hostapd_iface  *iface[ ] ),用来分别存放两张网卡的各自操作和信息等。  

       下面只分析一张网卡(注意下面说的网卡都是指无线网卡)的整体过程,因为不同无线网卡的区别主要体现在驱动方面,所以hostapd程序来说,不同网卡之间的处理过程都差不多的(比较数据包格式和通信协议没差啊)。

       

       main函数开始的for循环就不在重复了,主要注意的是-B选项和-e选项指定了 程序以后台进程运行和指定了entropy文件罢了。

       下面将以3条线开始整理,分别是 hostapd_global_init()    hostapd_interfaces_init()   hostapd_global_run() , 关于出错处理时,需要注意一下这个进程的重新加载,判断reloading以后调用execvp()函数实现重载。


一、 hostapd_global_init()   实现安全方法的注册、eloop初始化、entropy文件的读取和处理、退出中断的注册

    1. 注册方法 eap_server_register_methods()

      首先调用各种方法对应的注册函数,定义struct eap_method *eap 对像,给这个对象申请空间后,给eap对象中的操作函数指针赋值,最后使用eap_server_method_register()将本方法添加进 method的链表中。

     2. eloop初始化 eloop_init()

      将struct eloop_data  eloop对象清空后,将eloop.timeout添加到双链表中,最后注册一个SIGSAVE中断,以在特定情况下终止进程。

     3. entropy文件的读取和处理 random_init()

     4.退出中断的注册  eloop_register_signal_terminate()

         这里主要完成eloop.teminate = 1 ,当信号产生时, 这个变量置1,能够让后面的while循环退出,终止程序,第二个参数interfaces主要用来指定这个信号发送给哪张无线网卡(当前无线网卡)。


二、 hostapd_interfaces_init()    这个函数很关键,接下来慢慢细说!

     struct hostapd_iface *iface  这个对象封装了对接口操作的各种函数以及对接口描述的各种参数。

     iface = hostapd_init (config_fname);  注意着句话,函数的返回值赋值给了iface,而传入的参数是config_fname(配置文件路径及名称),我们可以猜想这句话就是要完成将配置文件中的内容读取出来,并存放到iface对象中。

     1. 根据配置文件配置接口  hostapd_init() 

       为了具体一点,现在将代码列出来:


      首先定义三个结构体对象,分别用来存放接口信息、接口配置信息和报文协议等信息——hostapd_iface、 hostapd_conf、 hostapd_data

       hapd_iface->reload_config = hostapd_reload_config  需要刷新或者修改了配置文件需要重新加载的时候,调用这个函数

       hapd_iface->config_read_cb = hostapd_config_read 先加载默认的配置,然后加载配置文件中的配置,存放到conf对象中

       hapd_iface-> config_fname  存放配置文件的路径信息

       hapd_iface->ctrl_iface_init = hostapd_ctrl_iface_init   这个函数很重要,主要对初始化套接字通信,包括调用socket和bind函数eloop_register_read_sock,实现套接字通信,这里调用了hostapd_ctrl_iface_receive(),里面有receivefrom和sendto函数实现通信。

       hapd_iface->conf = conf 存放读取的配置信息

       hapd->msg_ctx = hapd   这里存放各种要发送的信息,比如报文信息、协议信息等, 因为hapd是struct hostapd_data 结构体对象

       接下来对bss进行初始化


2. 驱动程序初始化  hostapd_driver_init()

     首先对启动可能用到的各种params进行初始化赋值,然后用hapd->driver_priv = hapd->driver-> hostapd_init( hapd, &params) 语句,用params中的参数对驱动进行初始化。

     那么hostapd_init调用的是哪里的函数呢?这个路径的指定在初始化iface时,在iface->BSS[0] 中,hostapd_init将会调用 src/ driver / dirver_madwifi.c 中的 madwifi_init函数,具体驱动应用程序做了什么,就不拓展了。

     hapd->driver->get_capa 需要留意一下。


3. 设置接口配置 hostapd_setup_interface()      "setup_interface"

    使用的hostapd_data对象还是来自于 iface->bss[0]  ,首先使用hostapd_validate_bssid_configuration验证iface中的BSSID是否可用,调用hosta_get_hw_features获取硬件信息,最后调用hostapd_setup_interface_complete返回结果。

    其实在上面那个函数中,是做了好多设置才返回的,比如通道、频率、硬件模式(hw_mode)、传输速率、RTS、帧、热拔插、WPS等等。


三、 hostapd_global_run()

1. tncs_global_init 初始化

2.os_daemonize()让本进行以守护进程运行

3.eloop_run()

    将申请的标准输入、输出、出错文件描述符集,用select函数进行监听,调用eloop_process_pending_signals处理即将到来的中断信号,接下来进行超时处理。




       还有关于驱动那一块还没有整理,先留着吧,说不定哪一天兴趣来了在看看,花这么多时间才弄清楚这个小小的hostapd,感觉有点不值,有时候问自己为什么要花时间去弄明白人家已经做好的东西呢,直接拿过来用不就好了吗,没办法,也许嵌入式开发就是这样吧,也许是性格使然。



    


以上是关于hostapd wpa_supplicant madwifi详细分析——hostapd整体梳理的主要内容,如果未能解决你的问题,请参考以下文章

hostapd wpa_supplicant madwifi详细分析——wpa_supplicant的配置文件

hostapd wpa_supplicant madwifi详细分析——wps原理及实现 一

hostapd wpa_supplicant madwifi详细分析——wps原理及实现 三

hostapd wpa_supplicant madwifi详细分析——wps原理及实现 二

hostapdwpa_supplicant 交叉编译

hostapdwpa_supplicant 交叉编译