代码改变世界

上层应用与wpa_supplicant,wpa_supplicant与kernel 相关socket创建交互分析

2013-09-16 21:43  ...平..淡...  阅读(3972)  评论(0编辑  收藏  举报

单独拿出来,分析以下上层应用与wpa_supplicant   wpa_supplicant与kernel 的socket交互。

关联上层应用与wpa_supplicant的socket的创建、连接流程分析

[-->./wpa_supplicant/ctrl_iface_unix.c]  

1.wpa_supplicant初始化时,在wpa_supplicant_ctrl_iface_init方法中,会通priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0); 创建了一个socket,然后bind到指定的地址中的路径(/data/misc/wifi/sockets/p2p0)。

这之后,便会把socket的fd保存到eloop_run中发rfds中了。由select监听变化。

 

2.然后在打开wifi之后,应用层会去连接wpa_supplicant,在wifi.c:: wifi_connect_to_supplicant--->wifi_connect_on_socket_path方法中,会创建ctrl_conn与monitor_conn来和wpa_supplicant交互,它们各自通过wpa_ctrl_open方法创建了一个socket(它们的目的端地址路径都是/data/misc/wifi/sockets/p2p0,可在wifi_connect_to_supplicant方法中打log查看)。然后,通过bind、connect方法与wpa_supplicant初始化时创建的priv->sock建立了连接。

 

ps:之前已经讨论过monitor_conn的作用是监听wpa_supplicant传递过来的消息。为什么呢,其实是因为通过wpa_ctrl_attach(monitor_conn[index])语句,将monitor_conn中的socket信息(包括源端地址)保存到wpa_supplicant的某个链表结构中,这样wpa_supplicant就能通过socket发送消息给上层应用了。

 

贴出部分log:

//wpa_supplicant初始化时,创建的socket关联的路径
D/wpa_supplicant(2575): cb--1-addr.sun_path is wpa_/data/misc/wifi/sockets
D/wpa_supplicant(2575): cb--2-addr.sun_path is /data/misc/wifi/sockets/p2p0
D/wpa_supplicant(2575): cb--1-addr.sun_path is wpa_wlan0
//创建ctrl_conn和monitor_conn时,socket关联的源端、目的端地址
I/wpa_ctrl(595): cb---fd is 254, ctrl->local.sun_path is /data/misc/wifi/sockets/wpa_ctrl_595-3, ctrl->dest.sun_path is /data/misc/wifi/sockets/p2p0
I/wpa_ctrl(595): cb---fd is 255, ctrl->local.sun_path is /data/misc/wifi/sockets/wpa_ctrl_595-4, ctrl->dest.sun_path is /data/misc/wifi/sockets/p2p0

 

 

关联kernel与wpa_supplicant的socket的创建流程分析        ---可参考” wpa_supplicant与kernel交互"

因为在”保存驱动接口”,select_driver方法中调用了global_init方法(会根据用户态的结构体wpa_driver_nl80211_ops中查找对应方法,即nl80211_global_init)。

在nl80211_global_init方法中,有两条关键语句:

//(1) 初始化netlink,并注册事件接收函数 
global->netlink = netlink_init(cfg); 

//(2) 此global->ioctl_sock用作为ioctl命令的fd
global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);

 

(1)netlink_init方法中创建了一个socket,并添加到eloop_run方法中的rfds中。用于从kernel态发送事件给用户态

netlink->sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
......
eloop_register_read_sock(netlink->sock, netlink_receive, netlink,NULL); 

(2)该socket用于从用户态发送请求给kernel态