wifi構成ツールwpa_についてcliおよびwpa_supplicant単純分析
44192 ワード
最近、同社で新製品のスマートAndroidロボットを開発し、rk 3229開発ボードを使い始めた.wifiをデバッグする際によく使われるツールwap_cli、demoボードのデバッグを開始するときwpa_cliは正常に使用できます.しかし、製品はBluetooth機能をサポートする必要があるため、博通のAP 6212のwifiモジュールを交換しました.demoが使用するrtl 8616 wifiモジュール.新しいハードウェアのwap_が見つかりましたcliは使用できません.デバッグの進捗に影響します.次のように誤報する
このエラーの原因は、関連するwaln 0というsocket通信ノードが見つからないためです.通常、このsocketはこのディレクトリの下で通信ノード
これは博通です.
-iネットワークソケット通信ノードを指定ここではwlan 0を指定します
ここはちょっとよくわかりませんctrl_interface = @android:wpa_wlan 0ですが、本当にコードでctrl_interfaceはctrlになりますinterface =/data/misc/wifi/sockets. 具体的な転換原因は自分ではあまり注目していない.知っていることがあれば言ってもいいです.一般的にプロファイルの内容は次のとおりです.
ctrl_interface=/data/misc/wifi/socketsおよび-g@android:wpa_wlan 0のソースコードでの体現
これが疑問の場所です2つの明らかな違いは確かに同じctrlを指しています.interface ap_scan=1-wpasはネットワーク0、2-駆動はupdateのスキャンと接続を担当します.config=1プロファイルの更新を許可
wpa_supplicant_Init関数機能はstruct wpaを初期化することです.global*globalという構造体wpa_globalはグローバルな性質のコンテキスト情報である.ifaces変数によってwpaを指しますsupplicantオブジェクト.(1)wpa_interfaceは、無線デバイスを記述するために使用される.このパラメータは初期化時に使用されます.(2)wpa_globalはグローバルな性質のコンテキスト情報である.ifaces変数によってwpaを指しますsupplicantオブジェクト.(3)wpa_supplicantはwpa_supplicantのコアデータ構造.1つのinterfaceは1つのwpaに対応しますsupplicantオブジェクトで、内部に非常に多くのメンバー変数が含まれています.(4)ctrl_iface_global_privはグローバル制御インタフェースの情報であり、内部には通信用のsocketハンドルが含まれている.
wpa_supplicant_global_ctrl_iface_receive()は、2つのコマンド、インタフェースコマンド、グローバルコマンドを受け入れることができます.クラスコマンドの前に「IFNAME=」があり、コマンドを処理するインタフェースを示し、各インタフェースに対応するwpaを呼び出す.supplicant_ctrl_iface_プロセス()は、対応する処理を行う.もう1つのクラスは、wpa_によってインタフェースが指定されていません.supplicant_global_ctrl_iface_プロセス直接処理.
wpa_supplicant_global_ctrl_iface_processは主にコマンド解析でwpa_によるcliまたはframeworkから渡されたパラメータ.次に、関連する関数を実行します.ここで注目したいのは
設定したパラメータを保存します.settings.apkでもwpaでもcliツールはネットワークに接続され、最後に関連するssidとpasswordはwpa_に保存されます.supplicant.confにあります.これも、市場で簡単にwifiを共有するためにroot権限が必要な理由です.root権限がなければ、プロファイルを読み取ることはできません.本当にファイルを保存するコードは
wpa_configwrite_globalはnetworkホットスポット以外のプロパティ(**ctrl_など)を保存します.interface=/data/misc/wifi/sockets update_config=1 device_name=rk322x_box manufacturer=rockchip model_name=rk322x-box model_number=rk322x-box serial_number=FNM88CD8WC**
wpa_cliはshellの場合に使用されるwifiネットワーク構成ツールです.framework下のwifi.cとはsocketサービスを共用しています.一般的な使用例
次にインタラクティブモードに入ります.この時点で関連wpaが確立されていない場合supplicantサービスは、Failed to connect to wpa_に報告されます.supplicantこの行のコードはwpa_にありますcli.c下
wpa_cli_open_Connectionがsocketサービスを開くのに失敗するとエラーが発生します.ctrl_connはwpaに使用されます.cli下へコマンドmonitor_connはwpaを受信するために使用されるsupplicantから送られてきたメッセージ
Failed to connect to non-global ctrl_ifname: wlan0 error: No such file or directory
Could not connect to wpa_supplicant: wlan0 - re-trying
このエラーの原因は、関連するwaln 0というsocket通信ノードが見つからないためです.通常、このsocketはこのディレクトリの下で通信ノード
/data/misc/wifi/sockets/wlan0
を確立しますが、新しいハードウェアの下では関連ノードが確立されていないことに気づきました.デバッグを続けてlog情報を追加するとctrl_interfaceはロックの原因を定義していません.params.override_ctrl_interfaceが定義されたらokです.wifiのsupplicantモジュールがinit.rcで起動すると、wifiチップによってトリガされるサービスが異なります.例えばrtl wifiservice rtw_suppl_con /system/bin/wpa_supplicant_rtl \
-ip2p0 -Dnl80211 -c/data/misc/wifi/p2p_supplicant.conf \
-e/data/misc/wifi/entropy.bin -N \
-iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \
-O/data/misc/wifi/sockets \
-g@android:wpa_wlan0
class main
socket wpa_wlan0 dgram 660 wifi wifi
disabled
oneshot
これは博通です.
service wpa_supplicant /system/bin/wpa_supplicant \
-iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \
-I/system/etc/wifi/wpa_supplicant_overlay.conf \
-e/data/misc/wifi/entropy.bin -g@android:wpa_wlan0
class main
socket wpa_wlan0 dgram 660 wifi wifi
disabled
oneshot
-iネットワークソケット通信ノードを指定ここではwlan 0を指定します
-D wifi nl80211
-C wpa_supplicant
/data/misc/wifi/wpa_supplicant.conf
-I
-g ctrl_interface = @android:wpa_ -i waln0
ここはちょっとよくわかりませんctrl_interface = @android:wpa_wlan 0ですが、本当にコードでctrl_interfaceはctrlになりますinterface =/data/misc/wifi/sockets. 具体的な転換原因は自分ではあまり注目していない.知っていることがあれば言ってもいいです.一般的にプロファイルの内容は次のとおりです.
ctrl_interface=/data/misc/wifi/sockets
update_config=1
ap_scan=1
ctrl_interface=/data/misc/wifi/socketsおよび-g@android:wpa_wlan 0のソースコードでの体現
case 'g':
params.ctrl_interface = optarg;
break;
これが疑問の場所です2つの明らかな違いは確かに同じctrlを指しています.interface ap_scan=1-wpasはネットワーク0、2-駆動はupdateのスキャンと接続を担当します.config=1プロファイルの更新を許可
int main(int argc, char *argv[])
{
case 'c':
iface->confname = optarg;
break;
case 'C':
iface->ctrl_interface = optarg;
break;
case 'D':
iface->driver = optarg;
break;
case 'd':
#ifdef CONFIG_NO_STDOUT_DEBUG
printf("Debugging disabled with "
"CONFIG_NO_STDOUT_DEBUG=y build time "
"option.
");
goto out;
#else /* CONFIG_NO_STDOUT_DEBUG */
params.wpa_debug_level--;
break;
#endif /* CONFIG_NO_STDOUT_DEBUG */
case 'e':
params.entropy_file = optarg;
break;
#ifdef CONFIG_DEBUG_FILE
case 'f':
params.wpa_debug_file_path = optarg;
break;
#endif /* CONFIG_DEBUG_FILE */
case 'g':
params.ctrl_interface = optarg;
break;
case 'G':
params.ctrl_interface_group = optarg;
break;
case 'h':
usage();
exitcode = 0;
goto out;
case 'i':
iface->ifname = optarg;
、、、、、、、、
global = wpa_supplicant_init(¶ms);
for (i = 0; exitcode == 0 && i < iface_count; i++) {
struct wpa_supplicant *wpa_s;
if ((ifaces[i].confname == NULL &&
ifaces[i].ctrl_interface == NULL) ||
ifaces[i].ifname == NULL) {
if (iface_count == 1 && (params.ctrl_interface ||
params.dbus_ctrl_interface))
break;
usage();
exitcode = -1;
break;
}
// wpa_supplicant_add_iface
wpa_s = wpa_supplicant_add_iface(global, &ifaces[i]);
}
if (exitcode == 0)
exitcode = wpa_supplicant_run(global);
wpa_supplicant_Init関数機能はstruct wpaを初期化することです.global*globalという構造体wpa_globalはグローバルな性質のコンテキスト情報である.ifaces変数によってwpaを指しますsupplicantオブジェクト.(1)wpa_interfaceは、無線デバイスを記述するために使用される.このパラメータは初期化時に使用されます.(2)wpa_globalはグローバルな性質のコンテキスト情報である.ifaces変数によってwpaを指しますsupplicantオブジェクト.(3)wpa_supplicantはwpa_supplicantのコアデータ構造.1つのinterfaceは1つのwpaに対応しますsupplicantオブジェクトで、内部に非常に多くのメンバー変数が含まれています.(4)ctrl_iface_global_privはグローバル制御インタフェースの情報であり、内部には通信用のsocketハンドルが含まれている.
wpa_supplicant_init()
{
return
struct wpa_global *global;
global = os_zalloc(sizeof(*global));
if (global == NULL)
return NULL;
dl_list_init(&global->p2p_srv_bonjour);
dl_list_init(&global->p2p_srv_upnp);
global->params.daemonize = params->daemonize;
global->params.wait_for_monitor = params->wait_for_monitor;
global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
if (params->pid_file)
global->params.pid_file = os_strdup(params->pid_file);
if (params->ctrl_interface)
global->params.ctrl_interface =
os_strdup(params->ctrl_interface);
。 。 socket
if (params->ctrl_interface_group)
global->params.ctrl_interface_group =
os_strdup(params->ctrl_interface_group);
if (params->override_driver)
global->params.override_driver =
os_strdup(params->override_driver);
if (params->override_ctrl_interface)
global->params.override_ctrl_interface =
os_strdup(params->override_ctrl_interface);
params global wpa_params
ctrl_iface_global_priv, socket , socket ctrl_interface。
global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
}
wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
{
struct ctrl_iface_global_priv *priv;
priv = os_zalloc(sizeof(*priv));
if (priv == NULL)
return NULL;
dl_list_init(&priv->ctrl_dst);
priv->global = global;
priv->sock = -1;
if (global->params.ctrl_interface == NULL)
ctrl_interface 。 。 socket
return priv;
socket wpa_cli framework
if (wpas_global_ctrl_iface_open_sock(global, priv) < 0) {
os_free(priv);
return NULL;
}
wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
return priv;
}
static int wpas_global_ctrl_iface_open_sock(struct wpa_global *global,
struct ctrl_iface_global_priv *priv)
{
struct sockaddr_un addr;
ctrl_interface=/data/misc/wifi/sockets
const char *ctrl = global->params.ctrl_interface;
int flags;
#ifdef ANDROID
ctrl=@android:wpa_wlan0, ctrl + 9 = wlan0
if (os_strncmp(ctrl, "@android:", 9) == 0) {
socket
priv->sock = android_get_control_socket(ctrl + 9);
if (priv->sock < 0) {
wpa_printf(MSG_ERROR, "Failed to open Android control "
"socket '%s'", ctrl + 9);
goto fail;
}
wpa_printf(MSG_DEBUG, "Using Android control socket '%s'",
ctrl + 9);
goto havesock;
}
if (os_strncmp(ctrl, "@abstract:", 10) != 0) {
/*
* Backwards compatibility - try to open an Android control
* socket and if that fails, assume this was a UNIX domain
* socket instead.
*/
priv->sock = android_get_control_socket(ctrl);
if (priv->sock >= 0) {
wpa_printf(MSG_DEBUG,
"Using Android control socket '%s'",
ctrl);
goto havesock;
}
}
#endif /* ANDROID */
havesock:
flags = fcntl(priv->sock, F_GETFL);
if (flags >= 0) {
flags |= O_NONBLOCK;
if (fcntl(priv->sock, F_SETFL, flags) < 0) {
wpa_printf(MSG_INFO, "fcntl(ctrl, O_NONBLOCK): %s",
strerror(errno));
/* Not fatal, continue on.*/
}
}
// conf 。 init.rc service wpa_supplicant data/misc/wifi/wpa_supplicant.conf
eloop_register_read_sock(priv->sock,
wpa_supplicant_global_ctrl_iface_receive,
global, priv);
return 0;
fail:
if (priv->sock >= 0) {
close(priv->sock);
priv->sock = -1;
}
return -1;
}
wpa_supplicant_global_ctrl_iface_receive()は、2つのコマンド、インタフェースコマンド、グローバルコマンドを受け入れることができます.クラスコマンドの前に「IFNAME=」があり、コマンドを処理するインタフェースを示し、各インタフェースに対応するwpaを呼び出す.supplicant_ctrl_iface_プロセス()は、対応する処理を行う.もう1つのクラスは、wpa_によってインタフェースが指定されていません.supplicant_global_ctrl_iface_プロセス直接処理.
static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
void *sock_ctx)
{
struct wpa_global *global = eloop_ctx;
struct ctrl_iface_global_priv *priv = sock_ctx;
char buf[4096];
int res;
struct sockaddr_un from;
socklen_t fromlen = sizeof(from);
char *reply = NULL, *reply_buf = NULL;
size_t reply_len;
res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
(struct sockaddr *) &from, &fromlen);
if (res < 0) {
wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
strerror(errno));
return;
}
buf[res] = '\0';
if (os_strcmp(buf, "ATTACH") == 0) {
if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst, &from,
fromlen))
reply_len = 1;
else
reply_len = 2;
} else if (os_strcmp(buf, "DETACH") == 0) {
if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst, &from,
fromlen))
reply_len = 1;
else
reply_len = 2;
} else {
//wpa_supplicant_global_ctrl_iface_process
reply_buf = wpa_supplicant_global_ctrl_iface_process(
global, buf, &reply_len);
reply = reply_buf;
}
if (!reply && reply_len == 1) {
reply = "FAIL
";
reply_len = 5;
} else if (!reply && reply_len == 2) {
reply = "OK
";
reply_len = 3;
}
if (reply) {
if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
fromlen) < 0) {
wpa_printf(MSG_DEBUG, "ctrl_iface sendto failed: %s",
strerror(errno));
}
}
os_free(reply_buf);
}
char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
char *buf, size_t *resp_len)
{
if (os_strcmp(buf, "PING") == 0) {
os_memcpy(reply, "PONG
", 5);
reply_len = 5;
} else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
if (wpa_supplicant_global_iface_add(global, buf + 14))
reply_len = -1;
} else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
if (wpa_supplicant_global_iface_remove(global, buf + 17))
reply_len = -1;
} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
reply_len = wpa_supplicant_global_iface_list(
global, reply, reply_size);
} else if (os_strcmp(buf, "INTERFACES") == 0) {
reply_len = wpa_supplicant_global_iface_interfaces(
global, reply, reply_size);
} else if (os_strcmp(buf, "TERMINATE") == 0) {
wpa_supplicant_terminate_proc(global);
} else if (os_strcmp(buf, "SUSPEND") == 0) {
wpas_notify_suspend(global);
} else if (os_strcmp(buf, "RESUME") == 0) {
wpas_notify_resume(global);
} else if (os_strncmp(buf, "SET ", 4) == 0) {
if (wpas_global_ctrl_iface_set(global, buf + 4)) {
#ifdef CONFIG_P2P
if (global->p2p_init_wpa_s) {
os_free(reply);
/* Check if P2P redirection would work for this
* command. */
return wpa_supplicant_ctrl_iface_process(
global->p2p_init_wpa_s,
buf, resp_len);
}
#endif /* CONFIG_P2P */
reply_len = -1;
}
#ifndef CONFIG_NO_CONFIG_WRITE
} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
if (wpas_global_ctrl_iface_save_config(global))
reply_len = -1;
#endif /* CONFIG_NO_CONFIG_WRITE */
} else if (os_strcmp(buf, "STATUS") == 0) {
reply_len = wpas_global_ctrl_iface_status(global, reply,
reply_size);
#ifdef CONFIG_MODULE_TESTS
} else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
int wpas_module_tests(void);
if (wpas_module_tests() < 0)
reply_len = -1;
#endif /* CONFIG_MODULE_TESTS */
} else {
os_memcpy(reply, "UNKNOWN COMMAND
", 16);
reply_len = 16;
}
if (reply_len < 0) {
os_memcpy(reply, "FAIL
", 5);
reply_len = 5;
}
*resp_len = reply_len;
return reply;
}
wpa_supplicant_global_ctrl_iface_processは主にコマンド解析でwpa_によるcliまたはframeworkから渡されたパラメータ.次に、関連する関数を実行します.ここで注目したいのは
if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
if (wpas_global_ctrl_iface_save_config(global))
reply_len = -1;
設定したパラメータを保存します.settings.apkでもwpaでもcliツールはネットワークに接続され、最後に関連するssidとpasswordはwpa_に保存されます.supplicant.confにあります.これも、市場で簡単にwifiを共有するためにroot権限が必要な理由です.root権限がなければ、プロファイルを読み取ることはできません.本当にファイルを保存するコードは
int wpa_config_write(const char *name, struct wpa_config *config)
{
f = fopen(tmp_name, "w");
wpa_config_write_global(f, config);
// network={
// ssid="yzs_test"
// psk="12345ABCDE"
// key_mgmt=WPA-PSK
// priority=10
//}
for (ssid = config->ssid; ssid; ssid = ssid->next) {
if (ssid->key_mgmt == WPA_KEY_MGMT_WPS || ssid->temporary)
continue; /* do not save temporary networks */
if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
!ssid->passphrase)
continue; /* do not save invalid network */
fprintf(f, "
network={
");
wpa_config_write_network(f, ssid);
fprintf(f, "}
");
}
fflush(f);
}
wpa_configwrite_globalはnetworkホットスポット以外のプロパティ(**ctrl_など)を保存します.interface=/data/misc/wifi/sockets update_config=1 device_name=rk322x_box manufacturer=rockchip model_name=rk322x-box model_number=rk322x-box serial_number=FNM88CD8WC**
wpa_cliはshellの場合に使用されるwifiネットワーク構成ツールです.framework下のwifi.cとはsocketサービスを共用しています.一般的な使用例
wpa_cli -i wlan0 -p /data/misc/wifi/sockets
次にインタラクティブモードに入ります.この時点で関連wpaが確立されていない場合supplicantサービスは、Failed to connect to wpa_に報告されます.supplicantこの行のコードはwpa_にありますcli.c下
int main(int argc, char *argv[])
{
int c;
int daemonize = 0;
int ret = 0;
const char *global = NULL;
if (os_program_init())
return -1;
for (;;) {
c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
if (c < 0)
break;
switch (c) {
case 'a':
action_file = optarg;
break;
case 'B':
daemonize = 1;
break;
case 'g':
global = optarg;
break;
case 'G':
ping_interval = atoi(optarg);
break;
case 'h':
usage();
return 0;
case 'v':
printf("%s
", wpa_cli_version);
return 0;
case 'i':
os_free(ctrl_ifname);
ctrl_ifname = os_strdup(optarg);
printf("ctrl_ifname is ===== %s
", ctrl_ifname);
break;
case 'p':
ctrl_iface_dir = optarg;
break;
case 'P':
pid_file = optarg;
break;
default:
usage();
return -1;
}
}
interactive = (argc == optind) && (action_file == NULL);
if (interactive)
printf("%s
%s
", wpa_cli_version, wpa_cli_license);
if (eloop_init())
return -1;
if (global) {
#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
ctrl_conn = wpa_ctrl_open(NULL);
#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
ctrl_conn = wpa_ctrl_open(global);
#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
if (ctrl_conn == NULL) {
fprintf(stderr, "Failed to connect to wpa_supplicant "
"global interface: %s error: %s
",
global, strerror(errno));
return -1;
}
if (interactive) {
update_ifnames(ctrl_conn);
mon_conn = wpa_ctrl_open(global);
if (mon_conn) {
if (wpa_ctrl_attach(mon_conn) == 0) {
wpa_cli_attached = 1;
eloop_register_read_sock(
wpa_ctrl_get_fd(mon_conn),
wpa_cli_mon_receive,
NULL, NULL);
} else {
printf("Failed to open monitor "
"connection through global "
"control interface
");
}
}
}
}
eloop_register_signal_terminate(wpa_cli_terminate, NULL);
if (ctrl_ifname == NULL)
ctrl_ifname = wpa_cli_get_default_ifname();
if (interactive) {
// socket , socket ctrl_conn mon_conn ,
wpa_cli_interactive();
} else {
// Failed to connect to non-global ctrl_ifname: wlan0 error: No such file or directory
if (!global &&
wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
fprintf(stderr, "Failed to connect to non-global "
"ctrl_ifname: %s error: %s
",
ctrl_ifname, strerror(errno));
return -1;
}
if (action_file) {
if (wpa_ctrl_attach(ctrl_conn) == 0) {
wpa_cli_attached = 1;
} else {
printf("Warning: Failed to attach to "
"wpa_supplicant.
");
return -1;
}
}
if (daemonize && os_daemonize(pid_file))
return -1;
if (action_file)
wpa_cli_action(ctrl_conn);
else
ret = wpa_request(ctrl_conn, argc - optind,
&argv[optind]);
}
os_free(ctrl_ifname);
eloop_destroy();
wpa_cli_cleanup();
return ret;
}
wpa_cli_open_Connectionがsocketサービスを開くのに失敗するとエラーが発生します.ctrl_connはwpaに使用されます.cli下へコマンドmonitor_connはwpaを受信するために使用されるsupplicantから送られてきたメッセージ
static int wpa_cli_open_connection(const char *ifname, int attach)
{
ctrl_conn = wpa_ctrl_open(ifname);
mon_conn = wpa_ctrl_open(ifname)
}
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
{
// socket
ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
ctrl->local.sun_family = AF_UNIX;
// addr.sun_path is data/misc/wifi/sockets/wlan0
ret = os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
CONFIG_CTRL_IFACE_CLIENT_DIR "/"
CONFIG_CTRL_IFACE_CLIENT_PREFIX "%d-%d",
(int) getpid(), counter);
// socket
bind(ctrl->s, (struct sockaddr *) &ctrl->local,
sizeof(ctrl->local)) < 0)
//
connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
sizeof(ctrl->dest)) < 0)
}