4.5.2 SET_NETWORK命令处理

SET_NETWORK对应的命令处理函数为wpa_supplicant_ctrl_iface_set_network,其代码如下所示。

[—>ctrl_iface.c::wpa_supplicant_ctrl_iface_set_network]

  1. static int wpa_supplicant_ctrl_iface_set_network(
  2. struct wpa_supplicant *wpa_s, char *cmd)
  3. {
  4. int id;
  5. struct wpa_ssid *ssid;
  6. char *name, *value;
  7.  
  8. // SET_NETWORK的参数是: "<network id> <variable name> <value>"
  9. name = os_strchr(cmd, ' '); *name++ = '\0'; // 获取name
  10. value = os_strchr(name, ' '); *value++ = '\0'; // 获取value
  11. id = atoi(cmd); // 获取id
  12. ......
  13. // 从wpa_config中的无线网络配置列表中找到对应编号的无线网络配置项
  14. ssid = wpa_config_get_network(wpa_s->conf, id);
  15. ......
  16. /*
  17. 为该网络设置对应的配置值。wpa_config_set函数的具体实现与4.3.4节"wpa_supplicant_
  18. init_iface分析之一"介绍的wpa_config_process_global函数类似,其内部也是通过定义
  19. 一些宏和数组来完成配置项的设置,不讨论其细节。就本例而言,当三个SET_NETWORK命令处理
  20. 完毕时,wpa_ssid的
  21. ssid="Test"、key_mgmt=WPA_KEY_MGMT_PSK、passphrase="12345Test"。
  22. 注意:虽然在命令行中设置的是psk="12345Test",但实际上密码值将保存在passphrase变量中。
  23. */
  24. if (wpa_config_set(ssid, name, value, 0) < 0) {......}
  25. // 清空对应的PMKSA缓存信息。wpa_s->wpa指向一个wpa_sm对象
  26. wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
  27.  
  28. if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL)
  29. eapol_sm_invalidate_cached_session(wpa_s->eapol);
  30.  
  31. if ((os_strcmp(name, "psk") == 0 && value[0] == '"' && ssid->ssid_len) ||
  32. (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
  33. wpa_config_update_psk(ssid);// 将字符串形式的passphrase转成key,见下文介绍
  34. else if (os_strcmp(name, "priority") == 0)
  35. wpa_config_update_prio_list(wpa_s->conf);
  36.  
  37. return 0;
  38. }

我们在3.3.7节的开头部分曾介绍过Key和Passphrase的区别。一般而言,Passphrase(也叫Password)表现为human-readable的字符串,而Key则一般是二进制或十六进制的数据。STA和AP交互的是Key,而用户设置的是Passphrase。所以上述代码中需要将Passphrase转换成Key,这是通过wpa_config_update_psk函数来完成的。其代码如下所示。

[—>config.c::wpa_config_update_psk]

  1. void wpa_config_update_psk(struct wpa_ssid *ssid)
  2. {
  3. #ifndef CONFIG_NO_PBKDF2 // 本例支持该宏,如果没有它的话,用户只能输入十六进制的Key
  4. // 对用户设置的psk和ssid进行hash计算,最终的结果作为真正的Pre-Shared Key
  5. pbkdf2_sha1(ssid->passphrase,(char *) ssid->ssid, ssid->ssid_len,
  6. 4096,ssid->psk, PMK_LEN);
  7. ssid->psk_set = 1;
  8. #endif /* CONFIG_NO_PBKDF2 */
  9. }

SET_NETWORK命令处理的介绍到此为止。下面来看最后一个关键命令ENABLE_NETWORK的处理流程。