4.5.2 SET_NETWORK命令处理
最后更新于:2022-04-02 06:03:22
SET_NETWORK对应的命令处理函数为wpa_supplicant_ctrl_iface_set_network,其代码如
下所示。
**ctrl_iface.c::wpa_supplicant_ctrl_iface_set_network**
~~~
static int wpa_supplicant_ctrl_iface_set_network(
struct wpa_supplicant *wpa_s, char *cmd)
{
int id;
struct wpa_ssid *ssid;
char *name, *value;
// SET_NETWORK的参数是: " "
name = os_strchr(cmd, ' '); *name++ = '\0'; // 获取name
value = os_strchr(name, ' '); *value++ = '\0'; // 获取value
id = atoi(cmd); // 获取id
......
// 从wpa_config中的无线网络配置列表中找到对应编号的无线网络配置项
ssid = wpa_config_get_network(wpa_s->conf, id);
......
/*
为该网络设置对应的配置值。wpa_config_set函数的具体实现与4.3.4节"wpa_supplicant_
init_iface分析之一"介绍的wpa_config_process_global函数类似,其内部也是通过定义
一些宏和数组来完成配置项的设置,不讨论其细节。就本例而言,当三个SET_NETWORK命令处理
完毕时,wpa_ssid的
ssid="Test"、key_mgmt=WPA_KEY_MGMT_PSK、passphrase="12345Test"。
注意:虽然在命令行中设置的是psk="12345Test",但实际上密码值将保存在passphrase变量中。
*/
if (wpa_config_set(ssid, name, value, 0) < 0) {......}
// 清空对应的PMKSA缓存信息。wpa_s->wpa指向一个wpa_sm对象
wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL)
eapol_sm_invalidate_cached_session(wpa_s->eapol);
if ((os_strcmp(name, "psk") == 0 && value[0] == '"' && ssid->ssid_len) ||
(os_strcmp(name, "ssid") == 0 && ssid->passphrase))
wpa_config_update_psk(ssid);// 将字符串形式的passphrase转成key,见下文介绍
else if (os_strcmp(name, "priority") == 0)
wpa_config_update_prio_list(wpa_s->conf);
return 0;
}
~~~
我们在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**
~~~
void wpa_config_update_psk(struct wpa_ssid *ssid)
{
#ifndef CONFIG_NO_PBKDF2 // 本例支持该宏,如果没有它的话,用户只能输入十六进制的Key
// 对用户设置的psk和ssid进行hash计算,最终的结果作为真正的Pre-Shared Key
pbkdf2_sha1(ssid->passphrase,(char *) ssid->ssid, ssid->ssid_len,4096,ssid->psk, PMK_LEN);
ssid->psk_set = 1;
#endif /* CONFIG_NO_PBKDF2 */
}
~~~
SET_NETWORK命令处理的介绍到此为止。下面来看最后一个关键命令ENABLE_NETWORK的处理流程。
';