4.5 wpa_supplicant连接无线网络分析

本节将介绍第二条分析路线,即通过命令行发送命令的方式触发wpa_supplicant进行相关工作,使手机加入一个利用WPA-PSK进行认证的无线网络。以笔者的Note 2为例,整个过程用到的命令如下所示。

[命令示例]

  1. adb root #获取手机root用户权限。只有root被破解的手机才能成功
  2. adb shell #登录手机shell
  3. #笔者事先已编译wpa_cli并将其放到/system/bin目录中。这个命令用于启动wpa_cli,-i参数指明unix域控制
  4. #socket文件名,它应该和wpa_supplicant启动时设置的控制接口文件名一致
  5. wpa_cli -iwlan0 #该命令执行后,将进入wpa_cli进程,后续操作都在此进程中开展
  6. #发送ADD_NETWORK命令给wpa_supplicant,它将返回一个新网络配置项的编号
  7. #请参考4.3.3节wpas_ssid结构体介绍
  8. ADD_NETWORK #假设wpa_supplicant返回的新网络配置项编号为0
  9. SET_NETWORK 0 ssid "Test" #设置0号网络的ssid为"Test"
  10. SET_NETWORK 0 key_mgmt WPA-PSK #设置0号网络的key_mgmt为"WPA-PSK"
  11. SET_NETWORK 0 psk "12345Test" #设置0号网络的psk为"12345Test"
  12. ENABLE_NETWORK 0 #使能0号网络,它将触发wpa_supplicant扫描、关联等一系列操作直到加入无线网络"Test"
  13. CTRL+C #退出wpa_cli
  14. 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]

  1. static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
  2. void *sock_ctx)
  3. {
  4. struct wpa_supplicant *wpa_s = eloop_ctx;
  5. struct ctrl_iface_priv *priv = sock_ctx;
  6. char buf[4096]; int res; struct sockaddr_un from;
  7. socklen_t fromlen = sizeof(from);
  8. char *reply = NULL; size_t reply_len = 0; int new_attached = 0;
  9.  
  10. res = recvfrom(sock, buf, sizeof(buf) - 1, 0,(struct sockaddr *) &from, &fromlen);
  11. ......
  12. buf[res] = '\0';
  13. // 客户端第一次和WPAS连接时,需要发送"ATTACH"命令
  14. if (os_strcmp(buf, "ATTACH") == 0) {
  15. ......// 略过相关处理
  16. }......// "DETACH"和"LEVEL"命令处理
  17. else {
  18. #if defined(CONFIG_P2P) && defined(ANDROID_P2P)
  19. ......// P2P处理。虽然WPAS编译时打开了CONFIG_P2P和ANDROID_P2P
  20. // 但本章不讨论P2P相关的内容
  21. #endif
  22. // 大部分的命令处理都在wpa_supplicant_ctrl_iface_process函数中
  23. reply = wpa_supplicant_ctrl_iface_process(wpa_s, buf,&reply_len);
  24. }
  25.  
  26. if (reply) {// 回复客户端
  27. sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,fromlen);
  28. os_free(reply);
  29. } ......
  30. /*
  31. Client成功ATTACH后,将通知EAPOL模块。因为有些认证流程需要用户的参与(例如输入密码之类的),
  32. 所以当客户端连接上后,EAPOL模块将判断是否需要和客户端交互。读者可阅读
  33. eapol_sm_notify_ctrl_attached函数。
  34. */
  35. if (new_attached)
  36. eapol_sm_notify_ctrl_attached(wpa_s->eapol);
  37. }

如上述代码所示,绝大部分命令都由wpa_supplicant_ctrl_iface_process函数处理。下面将按顺序来分析其处理ADD_NETWORK、SET_NETWORK以及ENABLE_NETWORK的代码。