Android wpa_supplcant 启动之--网络接口初始化

wpa_supplicant结构体与网络接口

在手机adb中运行 netcfg或者ifconfig可以看到相关的网络接口的ip,掩码,mac地址等信息

这里写图片描述
Wpa_supplicant为每个网络接口都分配了一个struct wpa_supplicant, 该结构体存储了一些必要信息例如 struct dl_list bss(扫描结果); struct wpa_config *conf(配置文件)等等。 
每一个网络接口的扫描,连接等操作都是通过struct wpa_supplicant中定义的相关函数和数据来实现的。下面是结构体中一些重要的元素介绍

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<code class = " hljs java" >struct wpa_supplicant{
     //接口的名字和mac地址
     unsigned char own_addr[ETH_ALEN];
     char ifname[ 100 ];
 
     /**************************************/   
 
     //外部控制wpa_s的socket
     struct ctrl_iface_priv *ctrl_iface;
 
     //网络接口当前的状态,断开/关联/连接的bssid ssid等
     enum wpa_states wpa_state;
     u8 bssid[ETH_ALEN];
     u8 pending_bssid[ETH_ALEN]; /* If wpa_state == WPA_ASSOCIATING, this
                      * field contains the target BSSID. */
     int reassociate; /* reassociation requested */
     int disconnected; /* all connections disabled; i.e., do no reassociate
                * before this has been cleared */
     struct wpa_ssid *current_ssid;
     struct wpa_bss *current_bss;
     int ap_ies_from_associnfo;
     unsigned int assoc_freq;
 
     //是否支持2.4G/5G
     enum { WPA_SETBAND_AUTO, WPA_SETBAND_5G, WPA_SETBAND_2G } setband;
 
     /**************************************/
 
     //配置文件
     struct wpa_config *conf;
     //配置文件中的ESS网络的信息
     /* Selected configuration (based on Beacon/ProbeResp WPA IE) */
     int pairwise_cipher;
     int group_cipher;
     int key_mgmt;
     int wpa_proto;
     int mgmt_group_cipher;
 
     /**************************************/
 
     //扫描结果的处理,每次扫描后的结果都会做相应的更新
     void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
                  struct wpa_scan_results *scan_res);
     struct dl_list bss; /* struct wpa_bss::list */
     struct dl_list bss_id; /* struct wpa_bss::list_id */
     size_t num_bss;
     unsigned int bss_update_idx;
     unsigned int bss_next_id;
     //黑名单
     struct wpa_blacklist *blacklist;
 
     /**************************************/
 
     //底层相关,驱动的操作函数
     struct wpa_driver_ops *driver;
     int interface_removed; /* whether the network interface has been removed */
     void *drv_priv; /* private data used by driver_ops */
     void *global_drv_priv;
 
     //用来处理密钥相关netlink socket和处理方法
     struct l2_packet_data *l2;
     struct l2_packet_data *l2_br;
 
     /**************************************/
 
     //扫描相关的一些信息
     struct wpa_radio_work *scan_work;
     int scanning;
     int sched_scanning;
     struct os_reltime scan_trigger_time, scan_start_time;
     int scan_runs; /* number of scan runs since WPS was started */
     int *next_scan_freqs;
     int scan_interval; /* time in sec between scans to find suitable AP */
     int normal_scans; /* normal scans run before sched_scan */
     int scan_for_connection; /* whether the scan request was triggered for
                   * finding a connection */
 
     //sched_scan
     struct wpa_ssid *prev_sched_ssid; /* last SSID used in sched scan */
     int sched_scan_timeout;
     int sched_scan_interval;
     int first_sched_scan;
     int sched_scan_timed_out;
 
     //pno扫描
     int pno;
     int pno_sched_pending;
}
</code>
初始化网络接口配置

在wpa_s的main()函数中,进行完全局初始化后,会调用 wpa_supplicant_add_iface(),为wpa_s运行时传入的每个网络接口分配wpa_supplicant结构体,并进行相应的初始化

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<code class = " hljs autohotkey" >struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
                          struct wpa_interface *iface)
{
     struct wpa_supplicant *wpa_s = wpa_supplicant_alloc();
     wpa_s->global = global;
 
     //网络接口的初始化,与底层通信的socket,密钥数据包的socket,wpa_s的初始状态等
     if (wpa_supplicant_init_iface(wpa_s, &t_iface))
     {
 
 
         //读取两个conf配置文件
         //wpa_s允许提供两个配置文件,一个是原始的一个overlay,在overlay中的文件可以重新一些参数的值
         wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
         wpa_config_read(wpa_s->confanother, wpa_s->conf);
 
         //初始化驱动接口,并注册接收驱动event的函数 nl80211
         if (wpas_init_driver(wpa_s, iface) < 0 )
         {
             //根据传进来的-inl80211选定对应的wpa_driver_ops(driver_nl80211.c),里面定义了驱动的操作方法,同时调用对应的global_init()进行初始化
             if (wpa_supplicant_set_driver(wpa_s, driver) < 0 )
             ...</code>
列表内容

驱动初始化 
下一步是初始化相关驱动的操作参数和与驱动通信的socket 
wpa_supplicant支持多种架构的驱动,Android中多使用的是nl80211架构,相关操作函数在文件drivers_ml80211.c中

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<code class = " hljs fsharp" > //根据名称选择网络ops,创建于driver通信的socket
select_driver(wpa_s, i)
{
     //调用对应的global_init(),void * nl80211_global_init(void)
     global->drv_priv[i] = wpa_drivers[i]->global_init();
     {
         //初始化netlink socket,设置两个消息处理函数,netlink_receive中使用
         cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink;
         cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink;
         //创建一个接收kernel中 route 子系统的消息socket
         global->netlink = netlink_init(cfg);
         {
             //*****该socket用于接收 kernel中
             netlink->sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
             bind(netlink->sock, (struct sockaddr *) &local, sizeof(local));
             //注册内核消息接收函数, 根据接收到的消息type选择以下两个处理函数
             eloop_register_read_sock(netlink->sock, netlink_receive, netlink, NULL);
             static void netlink_receive( int sock, void *eloop_ctx, void *sock_ctx)
             {
                 char buf[ 8192 ]; //接收消息的字节数,
                 left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr *) &from, &fromlen);
                 //buf中是一个netlink消息,符合netlink规范,根据消息type选在相应的处理函数 newlink 和 dellink         
             }
         }
 
         //创建 global结构体中的 nl_cb(接收消息处理)和nl(发送消息)
         if (wpa_driver_nl80211_init_nl_global(global) < 0 )
         {
             //创建连接到 GENERIC_NETLINK 的socket
             global->nl = nl_create_handle(global->nl_cb, "nl" );
             //将nl连接到 内核中的nl80211模块
             global->nl80211_id = genl_ctrl_resolve(global->nl, "nl80211" );
 
             //创建接收消息的event socket, 并分别加入到组播组scan mlme regulatory vendor 中
             global->nl_event = nl_create_handle(global->nl_cb, "event" );
             ret = nl_get_multicast_id(global, "nl80211" , "scan" );
             ret = nl_socket_add_membership(global->nl_event, ret);
 
             //设置nl_cb的回调函数 process_global_event(), 该函数又会调用 wpa_supplicant_event() 做进一步处理
             nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_global_event, global);
             //为nl_event注册接收函数, 通过nl_recvmsgs()调用 process_global_event()
             nl80211_register_eloop_read(&global->nl_event, wpa_driver_nl80211_event_receive, global->nl_cb);
         }
 
         //创建一个 ioctl_sock, 还不知道干啥用,该sock用于通过ioctl方式向底层发送命令
         global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0 );
     }
}</code>
网络接口初始配置

例如up对应的接口

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<code class = " hljs lasso" > //调用对应的初始化函数wpa_driver_nl80211_drv_init(),传入的ifname名称为 wlan0
wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
static void * wpa_driver_nl80211_drv_init( void *ctx, const char *ifname, void *global_priv, int hostapd, const u8 *set_addr)
{
     //挺重要的一个结构体
     struct wpa_driver_nl80211_data *drv;
 
     //添加了回调函数drv->nl_cb process_drv_event(),最终会调用 wpa_supplicant_event()
     if (wpa_driver_nl80211_init_nl(drv))
     //添加bss回调函数bss->nl_cb,看着没啥用,最终处理 wpa_supplicant_event(),这两个回调函数没有和socket绑定,目前不清楚调用地方
     if (nl80211_init_bss(bss))
 
     //RF射频省电相关,读取节点“/dev/rfkill”只是接受消息打印log,不做任何操作
     rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked;
     rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked;
     drv->rfkill = rfkill_init(rcfg);
 
     //检查当前接口是否为UP状态
     linux_iface_up(drv->global->ioctl_sock, ifname)
 
     //主要为操作网卡wlan0
     wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1 )
     {
         //得知网卡地址和设置网口为UP
         if (set_addr && (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0 ) || linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname, set_addr)))
         //获取网口能力,具体能力请查阅struct wpa_driver_capa
         if (wpa_driver_nl80211_capa(drv))
         //设置网口信息 IF_OPER_DORMANT
         netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 1 , IF_OPER_DORMANT);
         //获取网口地址
         if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname, bss->addr))
     }
 
     //创建一个socket,并注册接收函数wpa_driver_nl80211_handle_eapol_tx_status
     drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0 );
     eloop_register_read_sock(drv->eapol_tx_sock, wpa_driver_nl80211_handle_eapol_tx_status, drv, NULL);
}</code>

5 密钥处理数据包收发socekt 
由netlink创建

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<code class = " hljs lasso" > //初始化驱动,主要完成了l2_paket回掉函数的初始化,与4次握手相关
if (wpa_supplicant_driver_init(wpa_s) < 0 )
{
     //主要函数,该函数会初始化l2_packet,并注册回掉函数,与4次握手相关
     if (wpa_supplicant_update_mac_addr(wpa_s) < 0 )
     {
         //wpa_supplicant_rx_eapol()就是4次握手的处理函数了
         wpa_s->l2 = l2_packet_init(wpa_s->ifname, wpa_drv_get_mac_addr(wpa_s), ETH_P_EAPOL,  wpa_supplicant_rx_eapol, wpa_s, 0 );
         {
             //新建socket
             struct l2_packet_data *l2->fd = socket(PF_PACKET, l2_hdr ? SOCK_RAW : SOCK_DGRAM, htons(protocol));
             //bind
             if (bind(l2->fd, (struct sockaddr *) &ll, sizeof(ll)) < 0 )
             //将socket与回掉函数l2_packet_receive相关联,内部实际会调用 wpa_supplicant_rx_eapol()
             eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL);
             {  
                 //相关步骤请看eloop_data结构体,所有的回掉函数和回掉所用的数据都在保存在该结构体中
                 res = recvfrom(sock, buf, sizeof(buf), 0 , (struct sockaddr *) &ll, &fromlen);
                 l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res);
             }
         }
     }
}</code>
wap_cli控制socket

在linux中可以通过wpa_supplicant提供的wpa_cli工具控制wpa_supplicant,在android中也可以通过wpa_cli在没有framework的情况下实现扫描连接工作 
下述代码就是创建需要的socket和接收发送函数。 
在android手机中打开wifi后再 /data/misc/wifi/sockets下的wlan0 和p2p0 就是该段代码生成的

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<code class = " hljs rust" >wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
{
     //分配空间,然后执行真正的初始化工作
     struct ctrl_iface_priv *priv;
     if (wpas_ctrl_iface_open_sock(wpa_s, priv) < 0 )
     {
         //android上运行不会执行以下两行代码
         //os_snprintf(addr.sun_path, sizeof(addr.sun_path), "wpa_%s", wpa_s->conf->ctrl_interface);
         //priv->sock = android_get_control_socket(addr.sun_path);
 
         //新建sock
         priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0 );
         //bind,地址为,/data/misc/wifi/sockets/wlan0,这个地址是新生成的               
         bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr))
         //注册接收socket的函数wpa_supplicant_ctrl_iface_receive, 其核心调用函数是 wpa_supplicant_ctrl_iface_process
         eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive, wpa_s, priv);
         //向socket上传event的函数
         wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
     }
}</code>

通过wpa_cli工具使用连接网络的步骤:

添加接口过程中的全部代码
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
<code class = " hljs fsharp" >struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
                          struct wpa_interface *iface)
{
     struct wpa_supplicant *wpa_s;
     struct wpa_interface t_iface;
     struct wpa_ssid *ssid;
 
 
     struct wpa_supplicant *wpa_s = wpa_supplicant_alloc();
     wpa_s->global = global;
 
     //网络接口的初始化,与底层通信的socket,密钥数据包的socket,wpa_s的初始状态等
     if (wpa_supplicant_init_iface(wpa_s, &t_iface))
     {
         //读取两个conf配置文件
         wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
         wpa_config_read(wpa_s->confanother, wpa_s->conf);
 
         //初始化驱动接口,并注册接收驱动event的函数 nl80211
         if (wpas_init_driver(wpa_s, iface) < 0 )
         {
             //根据传进来的-inl80211选定对应的wpa_driver_ops(driver_nl80211.c),里面定义了驱动的操作方法(),同时调用对应的global_init()进行初始化
             if (wpa_supplicant_set_driver(wpa_s, driver) < 0 )
             {
                 //根据名称选择网络ops
                 select_driver(wpa_s, i)
                 {
                     //调用对应的global_init(),void * nl80211_global_init(void)
                     global->drv_priv[i] = wpa_drivers[i]->global_init();
                     {
                         //初始化netlink socket,设置两个消息处理函数,netlink_receive中使用
                         cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink;
                         cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink;
                         //创建一个接收kernel中 route 子系统的消息socket
                         global->netlink = netlink_init(cfg);
                         {
                             //*****该socket用于接收 kernel中
                             netlink->sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
                             bind(netlink->sock, (struct sockaddr *) &local, sizeof(local));
                             //注册内核消息接收函数, 根据接收到的消息type选择以下两个处理函数
                             eloop_register_read_sock(netlink->sock, netlink_receive, netlink, NULL);
                             static void netlink_receive( int sock, void *eloop_ctx, void *sock_ctx)
                             {
                                 char buf[ 8192 ]; //接收消息的字节数,
                                 left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr *) &from, &fromlen);
                                 //buf中是一个netlink消息,符合netlink规范,根据消息type选在相应的处理函数 newlink 和 dellink         
                             }
                         }
 
                         //创建 global结构体中的 nl_cb(接收消息处理)和nl(发送消息)
                         if (wpa_driver_nl80211_init_nl_global(global) < 0 )
                         {
                             //创建连接到 GENERIC_NETLINK 的socket
                             global->nl = nl_create_handle(global->nl_cb, "nl" );
                             //将nl连接到 内核中的nl80211模块
                             global->nl80211_id = genl_ctrl_resolve(global->nl, "nl80211" );
 
                             //创建接收消息的event socket, 并分别加入到组播组scan mlme regulatory vendor 中
                             global->nl_event = nl_create_handle(global->nl_cb, "event" );
                             ret = nl_get_multicast_id(global, "nl80211" , "scan" );
                             ret = nl_socket_add_membership(global->nl_event, ret);
 
                             //设置nl_cb的回调函数 process_global_event(), 该函数又会调用 wpa_supplicant_event() 做进一步处理
                             nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_global_event, global);
                             //为nl_event注册接收函数, 通过nl_recvmsgs()调用 process_global_event()
                             nl80211_register_eloop_read(&global->nl_event, wpa_driver_nl80211_event_receive, global->nl_cb);
                         }
 
                         //创建一个 ioctl_sock, 还不知道干啥用,该sock用于通过ioctl方式向底层发送命令
                         global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0 );
                     }
                 }              
             }
 
             //调用对应的初始化函数wpa_driver_nl80211_drv_init(),传入的ifname名称为 wlan0
             wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
                 static void * wpa_driver_nl80211_drv_init( void *ctx, const char *ifname, void *global_priv, int hostapd, const u8 *set_addr)
                 {
                     //挺重要的一个结构体
                     struct wpa_driver_nl80211_data *drv;
 
                     //添加了回调函数drv->nl_cb process_drv_event(),最终会调用 wpa_supplicant_event()
                     if (wpa_driver_nl80211_init_nl(drv))
                     //添加bss回调函数bss->nl_cb,看着没啥用,最终处理 wpa_supplicant_event(),这两个回调函数没有和socket绑定,目前不清楚调用地方
                     if (nl80211_init_bss(bss))
 
                     //RF射频省电相关,读取节点“/dev/rfkill”只是接受消息打印log,不做任何操作
                     rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked;
                     rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked;
                     drv->rfkill = rfkill_init(rcfg);
 
                     //检查当前接口是否为UP状态
                     linux_iface_up(drv->global->ioctl_sock, ifname)
 
                     //主要为操作网卡wlan0
                     wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1 )
                     {
                         //得知网卡地址和设置网口为UP
                         if (set_addr && (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0 ) || linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname, set_addr)))
                         //获取网口能力,具体能力请查阅struct wpa_driver_capa
                         if (wpa_driver_nl80211_capa(drv))
                         //设置网口信息 IF_OPER_DORMANT
                         netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 1 , IF_OPER_DORMANT);
                         //获取网口地址
                         if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname, bss->addr))
                     }
 
                     。。创建一个socket,并注册接收函数wpa_driver_nl80211_handle_eapol_tx_status
                     drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0 );
                     eloop_register_read_sock(drv->eapol_tx_sock, wpa_driver_nl80211_handle_eapol_tx_status, drv, NULL);
                 }
 
 
         }
 
         //初始化wpa_s,主要设置 wpa 状态机
         if (wpa_supplicant_init_wpa(wpa_s) < 0 )
         {
             //设置一些操作函数,请查看结构体 struct wpa_sm_ctx
             。。。
             //
             struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx)
             {
                 //主要是3个变量值
                 sm->dot11RSNAConfigPMKLifetime = 43200 ; //PMK的生存时间(秒)(12小时),超时后要重新计算
                 sm->dot11RSNAConfigPMKReauthThreshold = 70 //PMK超时多少(70%)后,需要重新身份认证
                 sm->dot11RSNAConfigSATimeout = 60 ;      //进行身份验证的最长时间(秒)
             }
         }
 
         //初始化驱动,主要完成了l2_paket回掉函数的初始化,与4次握手相关
         if (wpa_supplicant_driver_init(wpa_s) < 0 )
         {
             //主要函数,该函数会初始化l2_packet,并注册回掉函数,与4次握手相关
             if (wpa_supplicant_update_mac_addr(wpa_s) < 0 )
             {
                 //wpa_supplicant_rx_eapol()就是4次握手的处理函数了
                 wpa_s->l2 = l2_packet_init(wpa_s->ifname, wpa_drv_get_mac_addr(wpa_s), ETH_P_EAPOL,  wpa_supplicant_rx_eapol, wpa_s, 0 );
                 {
                     //新建socket
                     struct l2_packet_data *l2->fd = socket(PF_PACKET, l2_hdr ? SOCK_RAW : SOCK_DGRAM, htons(protocol));
                     //bind
                     if (bind(l2->fd, (struct sockaddr *) &ll, sizeof(ll)) < 0 )
                     //将socket与回掉函数l2_packet_receive相关联,内部实际会调用 wpa_supplicant_rx_eapol()
                     eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL);
                     {  
                         //相关步骤请看eloop_data结构体,所有的回掉函数和回掉所用的数据都在保存在该结构体中
                         res = recvfrom(sock, buf, sizeof(buf), 0 , (struct sockaddr *) &ll, &fromlen);
                         l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res);
                     }
                 }
             }
         }
 
         //设置国家码到驱动中
         wpa_drv_set_country(wpa_s, wpa_s->conf->country))
 
         //wpa_s中的 struct wps_context *wps 节点
         if (wpas_wps_init(wpa_s))
         {
             //wps_context *wps中定义了一些方法,具体请查看注释,没什么逻辑处理的问题
         }
 
         //初始化 EAPOOL,参考eapol模块信息
         wpa_supplicant_init_eapol(wpa_s)
         {
             //设置一些方法
             。。。
             ctx->eapol_send = wpa_supplicant_eapol_send;
             。。。
             //初始化eapol状态机
             wpa_s->eapol = eapol_sm_init(ctx);
         }
 
 
         //初始化与FWKS的通信的socket???
         wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
         {
             //分配空间,然后执行真正的初始化工作
             struct ctrl_iface_priv *priv;
             if (wpas_ctrl_iface_open_sock(wpa_s, priv) < 0 )
             {
                 //参数通过启动参数传入wlan0的名称,然后获取init.rc中wpa_wlan0的socket
                 //android上运行不会执行以下两行代码
                 //os_snprintf(addr.sun_path, sizeof(addr.sun_path), "wpa_%s", wpa_s->conf->ctrl_interface);
                 //priv->sock = android_get_control_socket(addr.sun_path);
 
                 //新建sock
                 priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0 );
                 //bind,地址为,/data/misc/wifi/sockets/wlan0,这个地址是新生成的               
                 bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr))
                 //注册接收socket 命令的函数wpa_supplicant_ctrl_iface_receive, 其核心调用函数是 wpa_supplicant_ctrl_iface_process
                 eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive, wpa_s, priv);
                 //向socket上传event的函数
                 wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
             }
         }
 
         //初始化bss相关,主要是wpa_s中的两个链表
         if (wpa_bss_init(wpa_s) < 0 )
         {
             //初始化wpa_s中bss和bssid链表
             dl_list_init(&wpa_s->bss);
             dl_list_init(&wpa_s->bss_id);
             //注册超时函数 ,每隔10秒刷新下bss,去掉无用的bss
             eloop_register_timeout(WPA_BSS_EXPIRATION_PERIOD= 10 , wpa_bss_timeout, wpa_s, NULL);
         }
 
         //sim卡 sd卡相关
         if (pcsc_reader_init(wpa_s) < 0 )
 
         //不知道做什么用的
         if (wpas_init_ext_pw(wpa_s) < 0 )           
     }
 
     /* Notify the control interfaces about new iface */
     if (wpas_notify_iface_added(wpa_s)) {
         wpa_supplicant_deinit_iface(wpa_s, 1 , 0 );
         return NULL;
     }
 
     for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
         wpas_notify_network_added(wpa_s, ssid);
 
     //设置wpas状态
     wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
     return wpa_s;
}</code>
流程图

其中虚线表示数据的传递,深棕色部分表示创建的socket以及收发函数 
添加接口流程图

下一篇为wpa_supplicant中的两个重要的结构体bss和conf 
bss中保存着扫描结果, conf中为wpa_s的参数和保存的网络

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值