0%

how_to_use_wpa_supplicant

这个工具的下载和移植都很简单。移植后能得到 wpa_supplicantwpa_cliwpa_supplicant 运行在后台,使用socket与前台进行数据通信。wpa_cli 可以用来进行调试和查看 wpa_supplicant 的运行

配置

在文件 wpa_supplicant.conf 中添加

ctrl_interface=DIR=/var/run/wpa_supplicant

如果没有的话,无法使用wpa_cli

wpa_supplicant 执行时会在 /var/run/wpa_supplicant 下创建 socket 文件

执行

wpa_supplicant -d -Dnl80211 -i ra0 -c /etc/wpa_supplicant/wpa_supplicant.conf &
wpa_supplicant -i ra0 -t -f wpa_supplicant_tmp -Dwext -c /etc/wpa_supplicant/wpa_supplicant.conf &

在C代码中集成wpa_cli

wpa_cli 启动之前的必要条件

  • 加载好驱动并且开启了网卡
  • 建立/var/run/文件夹
  • 建立一个或者使用原有的配置文件,这个文件的第一行如下:
ctrl_interface=/var/run/wpa_supplicant  

ctrl_interface 指向的是一个目录,在这个目录中默认会生成一个文件 /var/run/wpa_supplicant/wlan0,这是 local socket address,用于我们的程序和后台程序 wpa_supplicant 进行通信(我们必须知道 wpa_supplicant 作为后台服务程序是通过本地socket和客户端进行通信的)

wpa_supplicant后台服务程序

wpa_supplicant -i ra0 -t -f wpa_supplicant_tmp -Dwext -c /etc/wpa_supplicant/wpa_supplicant.conf &

wpa_ctrl函数接口

static struct wpa_ctrl *ctrl_conn;
static struct wpa_ctrl *mon_conn;

static int wpa_cli_open_connection(const char *ifname, int attach)
{
#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
    ctrl_conn = wpa_ctrl_open(ifname);
    if (ctrl_conn == NULL)
        return -1;

    if (attach && interactive)
        mon_conn = wpa_ctrl_open(ifname);
    else
        mon_conn = NULL;
#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
    char *cfile = NULL;
    int flen, res;

    if (ifname == NULL)
        return -1;

#ifdef ANDROID
    if (access(ctrl_iface_dir, F_OK) < 0) {
        cfile = os_strdup(ifname);
        if (cfile == NULL)
            return -1;
    }
#endif /* ANDROID */

    if (cfile == NULL) {
        flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
        cfile = os_malloc(flen);
        if (cfile == NULL)
            return -1;
        res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
                  ifname);
        if (res < 0 || res >= flen) {
            os_free(cfile);
            return -1;
        }
    }

    ctrl_conn = wpa_ctrl_open(cfile);
    if (ctrl_conn == NULL) {
        os_free(cfile);
        return -1;
    }

    if (attach && interactive)
        mon_conn = wpa_ctrl_open(cfile);
    else
        mon_conn = NULL;
    os_free(cfile);
#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */

    if (mon_conn) {
        printf("\033[32m%s[%d]\n\033[0m", __func__, __LINE__);
        if (wpa_ctrl_attach(mon_conn) == 0) {
            wpa_cli_attached = 1;
            if (interactive)
                eloop_register_read_sock(
                    wpa_ctrl_get_fd(mon_conn),
                    wpa_cli_mon_receive, NULL, NULL);
        } else {
            printf("Warning: Failed to attach to "
                   "wpa_supplicant.\n");
            return -1;
        }
    }

    return 0;
}

struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
{
    struct wpa_ctrl *ctrl;
    static int counter = 0;
    int ret;
    size_t res;
    int tries = 0;

    ctrl = os_malloc(sizeof(*ctrl));
    if (ctrl == NULL)
        return NULL;
    os_memset(ctrl, 0, sizeof(*ctrl));

    ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
    if (ctrl->s < 0) {
        os_free(ctrl);
        return NULL;
    }

    ctrl->local.sun_family = AF_UNIX;
    counter++;
try_again:
    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);
    if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) {
        close(ctrl->s);
        os_free(ctrl);
        return NULL;
    }
    tries++;
    if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
            sizeof(ctrl->local)) < 0) {
        if (errno == EADDRINUSE && tries < 2) {
            /*
             * getpid() returns unique identifier for this instance
             * of wpa_ctrl, so the existing socket file must have
             * been left by unclean termination of an earlier run.
             * Remove the file and try again.
             */
            unlink(ctrl->local.sun_path);
            goto try_again;
        }
        close(ctrl->s);
        os_free(ctrl);
        return NULL;
    }

#ifdef ANDROID
    chmod(ctrl->local.sun_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
    chown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI);
    /*
     * If the ctrl_path isn't an absolute pathname, assume that
     * it's the name of a socket in the Android reserved namespace.
     * Otherwise, it's a normal UNIX domain socket appearing in the
     * filesystem.
     */
    if (ctrl_path != NULL && *ctrl_path != '/') {
        char buf[21];
        os_snprintf(buf, sizeof(buf), "wpa_%s", ctrl_path);
        if (socket_local_client_connect(
                ctrl->s, buf,
                ANDROID_SOCKET_NAMESPACE_RESERVED,
                SOCK_DGRAM) < 0) {
            close(ctrl->s);
            unlink(ctrl->local.sun_path);
            os_free(ctrl);
            return NULL;
        }
        return ctrl;
    }
#endif /* ANDROID */

    ctrl->dest.sun_family = AF_UNIX;
    res = os_strlcpy(ctrl->dest.sun_path, ctrl_path,
             sizeof(ctrl->dest.sun_path));
    if (res >= sizeof(ctrl->dest.sun_path)) {
        close(ctrl->s);
        os_free(ctrl);
        return NULL;
    }
    if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
            sizeof(ctrl->dest)) < 0) {
        close(ctrl->s);
        unlink(ctrl->local.sun_path);
        os_free(ctrl);
        return NULL;
    }

    return ctrl;
}

从函数中可以看出,使用wpa_ctrl_open打开两次,获得两个wpa_ctrl变量。这些变量代表着后台服务程序wpa_supplicant,通过这两个变量可以和wpa_supplicant进行通信。不过他们的分工有点不同,一个变量用于客户端主动给服务程序发起命令,另外一个变量用于监控wpa_supplicant的是否有数据发给客户端程序。

支持的命令

static struct wpa_cli_cmd wpa_cli_commands[] = {
    { "status", wpa_cli_cmd_status,
      cli_cmd_flag_none,
      "[verbose] = get current WPA/EAPOL/EAP status" },
    { "ping", wpa_cli_cmd_ping,
      cli_cmd_flag_none,
      "= pings wpa_supplicant" },
    { "relog", wpa_cli_cmd_relog,
      cli_cmd_flag_none,
      "= re-open log-file (allow rolling logs)" },
    { "note", wpa_cli_cmd_note,
      cli_cmd_flag_none,
      "<text> = add a note to wpa_supplicant debug log" },
    { "mib", wpa_cli_cmd_mib,
      cli_cmd_flag_none,
      "= get MIB variables (dot1x, dot11)" },
    { "help", wpa_cli_cmd_help,
      cli_cmd_flag_none,
      "= show this usage help" },
    { "interface", wpa_cli_cmd_interface,
      cli_cmd_flag_none,
      "[ifname] = show interfaces/select interface" },
    { "level", wpa_cli_cmd_level,
      cli_cmd_flag_none,
      "<debug level> = change debug level" },
    { "license", wpa_cli_cmd_license,
      cli_cmd_flag_none,
      "= show full wpa_cli license" },
    { "quit", wpa_cli_cmd_quit,
      cli_cmd_flag_none,
      "= exit wpa_cli" },
    { "set", wpa_cli_cmd_set,
      cli_cmd_flag_none,
      "= set variables (shows list of variables when run without "
      "arguments)" },
    { "get", wpa_cli_cmd_get,
      cli_cmd_flag_none,
      "<name> = get information" },
    { "logon", wpa_cli_cmd_logon,
      cli_cmd_flag_none,
      "= IEEE 802.1X EAPOL state machine logon" },
    { "logoff", wpa_cli_cmd_logoff,
      cli_cmd_flag_none,
      "= IEEE 802.1X EAPOL state machine logoff" },
    { "pmksa", wpa_cli_cmd_pmksa,
      cli_cmd_flag_none,
      "= show PMKSA cache" },
    { "reassociate", wpa_cli_cmd_reassociate,
      cli_cmd_flag_none,
      "= force reassociation" },
    { "preauthenticate", wpa_cli_cmd_preauthenticate,
      cli_cmd_flag_none,
      "<BSSID> = force preauthentication" },
    { "identity", wpa_cli_cmd_identity,
      cli_cmd_flag_none,
      "<network id> <identity> = configure identity for an SSID" },
    { "password", wpa_cli_cmd_password,
      cli_cmd_flag_sensitive,
      "<network id> <password> = configure password for an SSID" },
    { "new_password", wpa_cli_cmd_new_password,
      cli_cmd_flag_sensitive,
      "<network id> <password> = change password for an SSID" },
    { "pin", wpa_cli_cmd_pin,
      cli_cmd_flag_sensitive,
      "<network id> <pin> = configure pin for an SSID" },
    { "otp", wpa_cli_cmd_otp,
      cli_cmd_flag_sensitive,
      "<network id> <password> = configure one-time-password for an SSID"
    },
    { "passphrase", wpa_cli_cmd_passphrase,
      cli_cmd_flag_sensitive,
      "<network id> <passphrase> = configure private key passphrase\n"
      "  for an SSID" },
    { "bssid", wpa_cli_cmd_bssid,
      cli_cmd_flag_none,
      "<network id> <BSSID> = set preferred BSSID for an SSID" },
    { "blacklist", wpa_cli_cmd_blacklist,
      cli_cmd_flag_none,
      "<BSSID> = add a BSSID to the blacklist\n"
      "blacklist clear = clear the blacklist\n"
      "blacklist = display the blacklist" },
    { "log_level", wpa_cli_cmd_log_level,
      cli_cmd_flag_none,
      "<level> [<timestamp>] = update the log level/timestamp\n"
      "log_level = display the current log level and log options" },
    { "list_networks", wpa_cli_cmd_list_networks,
      cli_cmd_flag_none,
      "= list configured networks" },
    { "select_network", wpa_cli_cmd_select_network,
      cli_cmd_flag_none,
      "<network id> = select a network (disable others)" },
    { "enable_network", wpa_cli_cmd_enable_network,
      cli_cmd_flag_none,
      "<network id> = enable a network" },
    { "disable_network", wpa_cli_cmd_disable_network,
      cli_cmd_flag_none,
      "<network id> = disable a network" },
    { "add_network", wpa_cli_cmd_add_network,
      cli_cmd_flag_none,
      "= add a network" },
    { "remove_network", wpa_cli_cmd_remove_network,
      cli_cmd_flag_none,
      "<network id> = remove a network" },
    { "set_network", wpa_cli_cmd_set_network,
      cli_cmd_flag_sensitive,
      "<network id> <variable> <value> = set network variables (shows\n"
      "  list of variables when run without arguments)" },
    { "get_network", wpa_cli_cmd_get_network,
      cli_cmd_flag_none,
      "<network id> <variable> = get network variables" },
    { "save_config", wpa_cli_cmd_save_config,
      cli_cmd_flag_none,
      "= save the current configuration" },
    { "disconnect", wpa_cli_cmd_disconnect,
      cli_cmd_flag_none,
      "= disconnect and wait for reassociate/reconnect command before\n"
      "  connecting" },
    { "reconnect", wpa_cli_cmd_reconnect,
      cli_cmd_flag_none,
      "= like reassociate, but only takes effect if already disconnected"
    },
    { "scan", wpa_cli_cmd_scan,
      cli_cmd_flag_none,
      "= request new BSS scan" },
    { "scan_results", wpa_cli_cmd_scan_results,
      cli_cmd_flag_none,
      "= get latest scan results" },
    { "bss", wpa_cli_cmd_bss,
      cli_cmd_flag_none,
      "<<idx> | <bssid>> = get detailed scan result info" },
    { "get_capability", wpa_cli_cmd_get_capability,
      cli_cmd_flag_none,
      "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
    { "reconfigure", wpa_cli_cmd_reconfigure,
      cli_cmd_flag_none,
      "= force wpa_supplicant to re-read its configuration file" },
    { "terminate", wpa_cli_cmd_terminate,
      cli_cmd_flag_none,
      "= terminate wpa_supplicant" },
    { "interface_add", wpa_cli_cmd_interface_add,
      cli_cmd_flag_none,
      "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
      "  <bridge_name> = adds new interface, all parameters but <ifname>\n"
      "  are optional" },
    { "interface_remove", wpa_cli_cmd_interface_remove,
      cli_cmd_flag_none,
      "<ifname> = removes the interface" },
    { "interface_list", wpa_cli_cmd_interface_list,
      cli_cmd_flag_none,
      "= list available interfaces" },
    { "ap_scan", wpa_cli_cmd_ap_scan,
      cli_cmd_flag_none,
      "<value> = set ap_scan parameter" },
    { "scan_interval", wpa_cli_cmd_scan_interval,
      cli_cmd_flag_none,
      "<value> = set scan_interval parameter (in seconds)" },
    { "bss_expire_age", wpa_cli_cmd_bss_expire_age,
      cli_cmd_flag_none,
      "<value> = set BSS expiration age parameter" },
    { "bss_expire_count", wpa_cli_cmd_bss_expire_count,
      cli_cmd_flag_none,
      "<value> = set BSS expiration scan count parameter" },
    { "stkstart", wpa_cli_cmd_stkstart,
      cli_cmd_flag_none,
      "<addr> = request STK negotiation with <addr>" },
    { "ft_ds", wpa_cli_cmd_ft_ds,
      cli_cmd_flag_none,
      "<addr> = request over-the-DS FT with <addr>" },
    { "wps_pbc", wpa_cli_cmd_wps_pbc,
      cli_cmd_flag_none,
      "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
    { "wps_pin", wpa_cli_cmd_wps_pin,
      cli_cmd_flag_sensitive,
      "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
      "hardcoded)" },
    { "wps_check_pin", wpa_cli_cmd_wps_check_pin,
      cli_cmd_flag_sensitive,
      "<PIN> = verify PIN checksum" },
    { "wps_cancel", wpa_cli_cmd_wps_cancel, cli_cmd_flag_none,
      "Cancels the pending WPS operation" },
#ifdef CONFIG_WPS_OOB
    { "wps_oob", wpa_cli_cmd_wps_oob,
      cli_cmd_flag_sensitive,
      "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
#endif /* CONFIG_WPS_OOB */
    { "wps_reg", wpa_cli_cmd_wps_reg,
      cli_cmd_flag_sensitive,
      "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
    { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin,
      cli_cmd_flag_sensitive,
      "[params..] = enable/disable AP PIN" },
    { "wps_er_start", wpa_cli_cmd_wps_er_start,
      cli_cmd_flag_none,
      "[IP address] = start Wi-Fi Protected Setup External Registrar" },
    { "wps_er_stop", wpa_cli_cmd_wps_er_stop,
      cli_cmd_flag_none,
      "= stop Wi-Fi Protected Setup External Registrar" },
    { "wps_er_pin", wpa_cli_cmd_wps_er_pin,
      cli_cmd_flag_sensitive,
      "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
    { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
      cli_cmd_flag_none,
      "<UUID> = accept an Enrollee PBC using External Registrar" },
    { "wps_er_learn", wpa_cli_cmd_wps_er_learn,
      cli_cmd_flag_sensitive,
      "<UUID> <PIN> = learn AP configuration" },
    { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config,
      cli_cmd_flag_none,
      "<UUID> <network id> = set AP configuration for enrolling" },
    { "wps_er_config", wpa_cli_cmd_wps_er_config,
      cli_cmd_flag_sensitive,
      "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
    { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
      cli_cmd_flag_none,
      "<addr> = request RSN authentication with <addr> in IBSS" },
#ifdef CONFIG_AP
    { "sta", wpa_cli_cmd_sta,
      cli_cmd_flag_none,
      "<addr> = get information about an associated station (AP)" },
    { "all_sta", wpa_cli_cmd_all_sta,
      cli_cmd_flag_none,
      "= get information about all associated stations (AP)" },
#endif /* CONFIG_AP */
    { "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none,
      "= notification of suspend/hibernate" },
    { "resume", wpa_cli_cmd_resume, cli_cmd_flag_none,
      "= notification of resume/thaw" },
    { "drop_sa", wpa_cli_cmd_drop_sa, cli_cmd_flag_none,
      "= drop SA without deauth/disassoc (test command)" },
    { "roam", wpa_cli_cmd_roam,
      cli_cmd_flag_none,
      "<addr> = roam to the specified BSS" },
#ifdef CONFIG_P2P
    { "p2p_find", wpa_cli_cmd_p2p_find, cli_cmd_flag_none,
      "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
    { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, cli_cmd_flag_none,
      "= stop P2P Devices search" },
    { "p2p_connect", wpa_cli_cmd_p2p_connect, cli_cmd_flag_none,
      "<addr> <\"pbc\"|PIN> = connect to a P2P Devices" },
    { "p2p_listen", wpa_cli_cmd_p2p_listen, cli_cmd_flag_none,
      "[timeout] = listen for P2P Devices for up-to timeout seconds" },
    { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove, cli_cmd_flag_none,
      "<ifname> = remove P2P group interface (terminate group if GO)" },
    { "p2p_group_add", wpa_cli_cmd_p2p_group_add, cli_cmd_flag_none,
      "= add a new P2P group (local end as GO)" },
    { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc, cli_cmd_flag_none,
      "<addr> <method> = request provisioning discovery" },
    { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase,
      cli_cmd_flag_none,
      "= get the passphrase for a group (GO only)" },
    { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
      cli_cmd_flag_none,
      "<addr> <TLVs> = schedule service discovery request" },
    { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
      cli_cmd_flag_none,
      "<id> = cancel pending service discovery request" },
    { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp,
      cli_cmd_flag_none,
      "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
    { "p2p_service_update", wpa_cli_cmd_p2p_service_update,
      cli_cmd_flag_none,
      "= indicate change in local services" },
    { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external,
      cli_cmd_flag_none,
      "<external> = set external processing of service discovery" },
    { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush,
      cli_cmd_flag_none,
      "= remove all stored service entries" },
    { "p2p_service_add", wpa_cli_cmd_p2p_service_add,
      cli_cmd_flag_none,
      "<bonjour|upnp> <query|version> <response|service> = add a local "
      "service" },
    { "p2p_service_del", wpa_cli_cmd_p2p_service_del,
      cli_cmd_flag_none,
      "<bonjour|upnp> <query|version> [|service] = remove a local "
      "service" },
    { "p2p_reject", wpa_cli_cmd_p2p_reject,
      cli_cmd_flag_none,
      "<addr> = reject connection attempts from a specific peer" },
    { "p2p_invite", wpa_cli_cmd_p2p_invite,
      cli_cmd_flag_none,
      "<cmd> [peer=addr] = invite peer" },
    { "p2p_peers", wpa_cli_cmd_p2p_peers, cli_cmd_flag_none,
      "[discovered] = list known (optionally, only fully discovered) P2P "
      "peers" },
    { "p2p_peer", wpa_cli_cmd_p2p_peer, cli_cmd_flag_none,
      "<address> = show information about known P2P peer" },
    { "p2p_set", wpa_cli_cmd_p2p_set, cli_cmd_flag_none,
      "<field> <value> = set a P2P parameter" },
    { "p2p_flush", wpa_cli_cmd_p2p_flush, cli_cmd_flag_none,
      "= flush P2P state" },
    { "p2p_cancel", wpa_cli_cmd_p2p_cancel, cli_cmd_flag_none,
      "= cancel P2P group formation" },
    { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize, cli_cmd_flag_none,
      "<address> = unauthorize a peer" },
    { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, cli_cmd_flag_none,
      "[<duration> <interval>] [<duration> <interval>] = request GO "
      "presence" },
    { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, cli_cmd_flag_none,
      "[<period> <interval>] = set extended listen timing" },
#endif /* CONFIG_P2P */

#ifdef CONFIG_INTERWORKING
    { "fetch_anqp", wpa_cli_cmd_fetch_anqp, cli_cmd_flag_none,
      "= fetch ANQP information for all APs" },
    { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, cli_cmd_flag_none,
      "= stop fetch_anqp operation" },
    { "interworking_select", wpa_cli_cmd_interworking_select,
      cli_cmd_flag_none,
      "[auto] = perform Interworking network selection" },
    { "interworking_connect", wpa_cli_cmd_interworking_connect,
      cli_cmd_flag_none,
      "<BSSID> = connect using Interworking credentials" },
    { "anqp_get", wpa_cli_cmd_anqp_get, cli_cmd_flag_none,
      "<addr> <info id>[,<info id>]... = request ANQP information" },
#endif /* CONFIG_INTERWORKING */
    { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, cli_cmd_flag_none,
      "<0/1> = disable/enable automatic reconnection" },
    { "tdls_discover", wpa_cli_cmd_tdls_discover,
      cli_cmd_flag_none,
      "<addr> = request TDLS discovery with <addr>" },
    { "tdls_setup", wpa_cli_cmd_tdls_setup,
      cli_cmd_flag_none,
      "<addr> = request TDLS setup with <addr>" },
    { "tdls_teardown", wpa_cli_cmd_tdls_teardown,
      cli_cmd_flag_none,
      "<addr> = tear down TDLS with <addr>" },
    { "signal_poll", wpa_cli_cmd_signal_poll,
      cli_cmd_flag_none,
      "= get signal parameters" },
    { NULL, NULL, cli_cmd_flag_none, NULL }
};

在C语言中集成wpa_cli

简化不使用监控socket代码如下:

#ifndef CONFIG_CTRL_IFACE_CLIENT_DIR
#define CONFIG_CTRL_IFACE_CLIENT_DIR "/tmp"
#endif
#ifndef CONFIG_CTRL_IFACE_CLIENT_PREFIX
#define CONFIG_CTRL_IFACE_CLIENT_PREFIX "wpa_ctrl_"
#endif
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
{
    struct wpa_ctrl *ctrl = NULL;
    static int counter = 0;
    int ret;
    size_t res;
    int tries = 0;

    ctrl = GxCore_Mallocz(sizeof(*ctrl));
    if (ctrl == NULL)
        return NULL;
    memset(ctrl, 0, sizeof(*ctrl));

    ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
    if (ctrl->s < 0) {
        GXCORE_FREE(ctrl);
        return NULL;
    }
    ctrl->local.sun_family = AF_UNIX;
    counter++;
try_again:
    ret = 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);
    if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) {
        close(ctrl->s);
        GXCORE_FREE(ctrl);
        return NULL;
    }
    tries++;
    if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
                sizeof(ctrl->local)) < 0) {
        if (errno == EADDRINUSE && tries < 2) {
            /*
             * getpid() returns unique identifier for this instance
             * of wpa_ctrl, so the existing socket file must have
             * been left by unclean termination of an earlier run.
             * Remove the file and try again.
             */
            unlink(ctrl->local.sun_path);
            goto try_again;
        }
        close(ctrl->s);
        GXCORE_FREE(ctrl);
        return NULL;
    }
    ctrl->dest.sun_family = AF_UNIX;
    res = strlcpy(ctrl->dest.sun_path, ctrl_path,
            sizeof(ctrl->dest.sun_path));
    if (res >= sizeof(ctrl->dest.sun_path)) {
        close(ctrl->s);
        GXCORE_FREE(ctrl);
        return NULL;
    }
    if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
                sizeof(ctrl->dest)) < 0) {
        close(ctrl->s);
        unlink(ctrl->local.sun_path);
        GXCORE_FREE(ctrl);
        return NULL;
    }

    return ctrl;
}

static int wpa_cli_open_connection(const char *ifname, int attach)
{
    char *cfile = NULL;
    int flen, res;

    if (ifname == NULL)
        return -1;
    if (cfile == NULL) {
        flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
        cfile = GxCore_Mallocz(flen);
        if (cfile == NULL)
            return -1;
        res = snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
                ifname);
        if (res < 0 || res >= flen) {
            GXCORE_FREE(cfile);
            return -1;
        }
    }
    ctrl_conn = wpa_ctrl_open(cfile);
    if (ctrl_conn == NULL) {
        GXCORE_FREE(cfile);
        return -1;
    }

    GXCORE_FREE(cfile);

    return 0;

}

static void wpa_ctrl_close(struct wpa_ctrl *ctrl)
{
    if (ctrl == NULL)
        return;
    unlink(ctrl->local.sun_path);
    if (ctrl->s >= 0)
        close(ctrl->s);
    GXCORE_FREE(ctrl);
    ctrl = NULL;
}

static void wpa_cli_close_connection(void)
{
    if (ctrl_conn == NULL)
        return;

    wpa_ctrl_close(ctrl_conn);
    ctrl_conn = NULL;
}

static void wpa_cli_cleanup(void)
{
    wpa_cli_close_connection();
}

static int wpa_cli(const char *ifname, char *cmd)
{
    int ret = 0;
    char *argv[1] = {};
    argv[0] = cmd;

    GXCORE_FREE(ctrl_ifname);
    ctrl_ifname = GxCore_Strdup(ifname);

    if (wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
        //printf("Failed to connect to wpa_supplicant - wpa_ctrl_open\n");
        GXCORE_FREE(ctrl_ifname);
        return -1;
    }

    ret = wpa_request(ctrl_conn, 1, &argv[0]);
    GXCORE_FREE(ctrl_ifname);
    wpa_cli_cleanup();

    return ret;
}

Ref

  1. 无线网络配置 wpa_supplicant
  2. wpa_supplicant使用笔记
  3. Getting started with wpa_supplicant using C
  4. WPA_Supplicant使用及配置