4.5 wpa_supplicant连接无线网络分析
本节将介绍第二条分析路线,即通过命令行发送命令的方式触发wpa_supplicant进行相关工作,使手机加入一个利用WPA-PSK进行认证的无线网络。以笔者的Note 2为例,整个过程用到的命令如下所示。
[命令示例]
- adb root #获取手机root用户权限。只有root被破解的手机才能成功
- adb shell #登录手机shell
- #笔者事先已编译wpa_cli并将其放到/system/bin目录中。这个命令用于启动wpa_cli,-i参数指明unix域控制
- #socket文件名,它应该和wpa_supplicant启动时设置的控制接口文件名一致
- wpa_cli -iwlan0 #该命令执行后,将进入wpa_cli进程,后续操作都在此进程中开展
- #发送ADD_NETWORK命令给wpa_supplicant,它将返回一个新网络配置项的编号
- #请参考4.3.3节wpas_ssid结构体介绍
- ADD_NETWORK #假设wpa_supplicant返回的新网络配置项编号为0
- SET_NETWORK 0 ssid "Test" #设置0号网络的ssid为"Test"
- SET_NETWORK 0 key_mgmt WPA-PSK #设置0号网络的key_mgmt为"WPA-PSK"
- SET_NETWORK 0 psk "12345Test" #设置0号网络的psk为"12345Test"
- ENABLE_NETWORK 0 #使能0号网络,它将触发wpa_supplicant扫描、关联等一系列操作直到加入无线网络"Test"
- CTRL+C #退出wpa_cli
- dhcpcd wlan0 #启动dhcpd,wlan0为无线接口设备名。dhcpcd可为手机从AP那获取一个IP地址
dhcpcd成功执行后,手机将从AP那分配到一个IP地址。至此,手机就可以使用"Test"无线网络了。
注意 上述命令执行前有几个注意事项。
1)先要在Settings中开启无线网络。这个操作完成了wlan驱动及相应固件加载的工作。该工作实际上由netd来完成,而wpa_cli无法完成它。
2)开启无线网络后,WifiService和wpa_supplicant都开始工作了。为了避免WifiService的干扰,可以把Settings中的那些已知的无线网络信息都清除。
3)由于wpa_supplicant支持多个客户端,所以wpa_cli可以和WifiService共同工作。只要不操作Settings中无线网络相关的选项,WifiService就不会干扰wpa_cli。
4)然后按上述步骤执行wpa_cli。
根据前文所述,所有来自客户端的命令都由wpa_supplicant_ctrl_iface_receive函数处理(参考4.3.4节)。该函数代码非常简单,就是根据客户端发送的命令进行对应处理。
[—>ctrl_iface_unix.c::wpa_supplicant_ctrl_iface_receive]
- static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
- void *sock_ctx)
- {
- struct wpa_supplicant *wpa_s = eloop_ctx;
- struct ctrl_iface_priv *priv = sock_ctx;
- char buf[4096]; int res; struct sockaddr_un from;
- socklen_t fromlen = sizeof(from);
- char *reply = NULL; size_t reply_len = 0; int new_attached = 0;
- res = recvfrom(sock, buf, sizeof(buf) - 1, 0,(struct sockaddr *) &from, &fromlen);
- ......
- buf[res] = '\0';
- // 客户端第一次和WPAS连接时,需要发送"ATTACH"命令
- if (os_strcmp(buf, "ATTACH") == 0) {
- ......// 略过相关处理
- }......// "DETACH"和"LEVEL"命令处理
- else {
- #if defined(CONFIG_P2P) && defined(ANDROID_P2P)
- ......// P2P处理。虽然WPAS编译时打开了CONFIG_P2P和ANDROID_P2P
- // 但本章不讨论P2P相关的内容
- #endif
- // 大部分的命令处理都在wpa_supplicant_ctrl_iface_process函数中
- reply = wpa_supplicant_ctrl_iface_process(wpa_s, buf,&reply_len);
- }
- if (reply) {// 回复客户端
- sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,fromlen);
- os_free(reply);
- } ......
- /*
- Client成功ATTACH后,将通知EAPOL模块。因为有些认证流程需要用户的参与(例如输入密码之类的),
- 所以当客户端连接上后,EAPOL模块将判断是否需要和客户端交互。读者可阅读
- eapol_sm_notify_ctrl_attached函数。
- */
- if (new_attached)
- eapol_sm_notify_ctrl_attached(wpa_s->eapol);
- }
如上述代码所示,绝大部分命令都由wpa_supplicant_ctrl_iface_process函数处理。下面将按顺序来分析其处理ADD_NETWORK、SET_NETWORK以及ENABLE_NETWORK的代码。