]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - wpa_supplicant/wpa_cli.c
Disallow WEP configuration in WPA network
[thirdparty/hostap.git] / wpa_supplicant / wpa_cli.c
index bd84a19c97d511ec2bd6533e2a7983e27a75193a..5e6643fcd7e7f82e06dbcc3bc20cb3be1348c06c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - command line interface for wpa_supplicant daemon
- * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -81,6 +81,7 @@ static const char *pid_file = NULL;
 static const char *action_file = NULL;
 static int ping_interval = 5;
 static int interactive = 0;
+static char *ifname_prefix = NULL;
 
 struct cli_txt_entry {
        struct dl_list list;
@@ -90,6 +91,7 @@ struct cli_txt_entry {
 static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
 static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
 static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
+static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */
 
 
 static void print_help(const char *cmd);
@@ -404,6 +406,12 @@ static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
                printf("Not connected to wpa_supplicant - command dropped.\n");
                return -1;
        }
+       if (ifname_prefix) {
+               os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
+                           ifname_prefix, cmd);
+               buf[sizeof(buf) - 1] = '\0';
+               cmd = buf;
+       }
        len = sizeof(buf) - 1;
        ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
                               wpa_cli_msg_cb);
@@ -560,52 +568,81 @@ static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
 }
 
 
-static void wpa_cli_show_variables(void)
-{
-       printf("set variables:\n"
-              "  EAPOL::heldPeriod (EAPOL state machine held period, "
-              "in seconds)\n"
-              "  EAPOL::authPeriod (EAPOL state machine authentication "
-              "period, in seconds)\n"
-              "  EAPOL::startPeriod (EAPOL state machine start period, in "
-              "seconds)\n"
-              "  EAPOL::maxStart (EAPOL state machine maximum start "
-              "attempts)\n");
-       printf("  dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
-              "seconds)\n"
-              "  dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
-              " threshold\n\tpercentage)\n"
-              "  dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
-              "security\n\tassociation in seconds)\n");
-}
-
-
 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
        char cmd[256];
        int res;
 
-       if (argc == 0) {
-               wpa_cli_show_variables();
-               return 0;
+       if (argc == 1) {
+               res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
+               if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+                       printf("Too long SET command.\n");
+                       return -1;
+               }
+               return wpa_ctrl_command(ctrl, cmd);
        }
 
-       if (argc != 1 && argc != 2) {
-               printf("Invalid SET command: needs two arguments (variable "
-                      "name and value)\n");
-               return -1;
-       }
+       return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
+}
 
-       if (argc == 1)
-               res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
-       else
-               res = os_snprintf(cmd, sizeof(cmd), "SET %s %s",
-                                 argv[0], argv[1]);
-       if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
-               printf("Too long SET command.\n");
-               return -1;
+
+static char ** wpa_cli_complete_set(const char *str, int pos)
+{
+       int arg = get_cmd_arg_num(str, pos);
+       const char *fields[] = {
+               /* runtime values */
+               "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
+               "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
+               "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
+               "wps_fragment_size", "wps_version_number", "ampdu",
+               "tdls_testing", "tdls_disabled", "pno", "radio_disabled",
+               "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
+               "no_keep_alive",
+               /* global configuration parameters */
+               "eapol_version", "ap_scan", "disable_scan_offload",
+               "fast_reauth", "opensc_engine_path", "pkcs11_engine_path",
+               "pkcs11_module_path", "pcsc_reader", "pcsc_pin",
+               "driver_param", "dot11RSNAConfigPMKLifetime",
+               "dot11RSNAConfigPMKReauthThreshold",
+               "dot11RSNAConfigSATimeout",
+               "update_config", "load_dynamic_eap", "uuid", "device_name",
+               "manufacturer", "model_name", "model_number", "serial_number",
+               "device_type", "os_version", "config_methods",
+               "wps_cred_processing", "wps_vendor_ext_m1", "sec_device_type",
+               "p2p_listen_reg_class", "p2p_listen_channel",
+               "p2p_oper_reg_class", "p2p_oper_channel",
+               "p2p_go_intent", "p2p_ssid_postfix", "persistent_reconnect",
+               "p2p_intra_bss", "p2p_group_idle", "p2p_pref_chan",
+               "p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface",
+               "p2p_ignore_shared_freq", "country", "bss_max_count",
+               "bss_expiration_age", "bss_expiration_scan_count",
+               "filter_ssids", "filter_rssi", "max_num_sta",
+               "disassoc_low_ack", "hs20", "interworking", "hessid",
+               "access_network_type", "pbc_in_m1", "autoscan",
+               "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", "wps_nfc_dh_privkey",
+               "wps_nfc_dev_pw", "ext_password_backend",
+               "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
+               "sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
+               "ignore_old_scan_res", "freq_list"
+       };
+       int i, num_fields = sizeof(fields) / sizeof(fields[0]);
+
+       if (arg == 1) {
+               char **res = os_calloc(num_fields + 1, sizeof(char *));
+               if (res == NULL)
+                       return NULL;
+               for (i = 0; i < num_fields; i++) {
+                       res[i] = os_strdup(fields[i]);
+                       if (res[i] == NULL)
+                               return res;
+               }
+               return res;
        }
-       return wpa_ctrl_command(ctrl, cmd);
+
+       if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
+               return cli_txt_list_array(&bsses);
+
+       return NULL;
 }
 
 
@@ -2264,6 +2301,12 @@ static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
        return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
 }
 
+
+static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
+}
+
 #endif /* CONFIG_WNM */
 
 
@@ -2328,7 +2371,7 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
        { "quit", wpa_cli_cmd_quit, NULL,
          cli_cmd_flag_none,
          "= exit wpa_cli" },
-       { "set", wpa_cli_cmd_set, NULL,
+       { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
          cli_cmd_flag_none,
          "= set variables (shows list of variables when run without "
          "arguments)" },
@@ -2725,6 +2768,8 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
 #ifdef CONFIG_WNM
        { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
          "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
+       { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
+         "<query reason> = Send BSS Transition Management Query" },
 #endif /* CONFIG_WNM */
        { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
          "<params..> = Sent unprocessed command" },
@@ -2788,9 +2833,12 @@ static char ** wpa_list_cmd_list(void)
 {
        char **res;
        int i, count;
+       struct cli_txt_entry *e;
 
        count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
-       res = os_calloc(count, sizeof(char *));
+       count += dl_list_len(&p2p_groups);
+       count += dl_list_len(&ifnames);
+       res = os_calloc(count + 1, sizeof(char *));
        if (res == NULL)
                return NULL;
 
@@ -2800,6 +2848,22 @@ static char ** wpa_list_cmd_list(void)
                        break;
        }
 
+       dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
+               size_t len = 8 + os_strlen(e->txt);
+               res[i] = os_malloc(len);
+               if (res[i] == NULL)
+                       break;
+               os_snprintf(res[i], len, "ifname=%s", e->txt);
+               i++;
+       }
+
+       dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
+               res[i] = os_strdup(e->txt);
+               if (res[i] == NULL)
+                       break;
+               i++;
+       }
+
        return res;
 }
 
@@ -2831,6 +2895,14 @@ static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
        const char *end;
        char *cmd;
 
+       if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
+               end = os_strchr(str, ' ');
+               if (end && pos > end - str) {
+                       pos -= end - str + 1;
+                       str = end + 1;
+               }
+       }
+
        end = os_strchr(str, ' ');
        if (end == NULL || str + pos < end)
                return wpa_list_cmd_list();
@@ -2852,6 +2924,16 @@ static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
        int count;
        int ret = 0;
 
+       if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
+               ifname_prefix = argv[0] + 7;
+               argv = &argv[1];
+               argc--;
+       } else
+               ifname_prefix = NULL;
+
+       if (argc == 0)
+               return -1;
+
        count = 0;
        cmd = wpa_cli_commands;
        while (cmd->cmd) {
@@ -2999,6 +3081,8 @@ static void wpa_cli_action_process(const char *msg)
                wpa_cli_exec(action_file, ctrl_ifname, pos);
        } else if (str_match(pos, AP_STA_DISCONNECTED)) {
                wpa_cli_exec(action_file, ctrl_ifname, pos);
+       } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
+               wpa_cli_exec(action_file, ctrl_ifname, pos);
        } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
                printf("wpa_supplicant is terminating - stop monitoring\n");
                wpa_cli_quit = 1;
@@ -3260,8 +3344,74 @@ static void start_edit(void)
 }
 
 
+static void update_bssid_list(struct wpa_ctrl *ctrl)
+{
+       char buf[4096];
+       size_t len = sizeof(buf);
+       int ret;
+       char *cmd = "BSS RANGE=ALL MASK=0x2";
+       char *pos, *end;
+
+       if (ctrl == NULL)
+               return;
+       ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
+       if (ret < 0)
+               return;
+       buf[len] = '\0';
+
+       pos = buf;
+       while (pos) {
+               pos = os_strstr(pos, "bssid=");
+               if (pos == NULL)
+                       break;
+               pos += 6;
+               end = os_strchr(pos, '\n');
+               if (end == NULL)
+                       break;
+               *end = '\0';
+               cli_txt_list_add(&bsses, pos);
+               pos = end + 1;
+       }
+}
+
+
+static void update_ifnames(struct wpa_ctrl *ctrl)
+{
+       char buf[4096];
+       size_t len = sizeof(buf);
+       int ret;
+       char *cmd = "INTERFACES";
+       char *pos, *end;
+       char txt[200];
+
+       cli_txt_list_flush(&ifnames);
+
+       if (ctrl == NULL)
+               return;
+       ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
+       if (ret < 0)
+               return;
+       buf[len] = '\0';
+
+       pos = buf;
+       while (pos) {
+               end = os_strchr(pos, '\n');
+               if (end == NULL)
+                       break;
+               *end = '\0';
+               ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
+               if (ret > 0 && ret < (int) sizeof(txt))
+                       cli_txt_list_add(&ifnames, txt);
+               pos = end + 1;
+       }
+}
+
+
 static void try_connection(void *eloop_ctx, void *timeout_ctx)
 {
+       if (ctrl_conn)
+               goto done;
+
        if (ctrl_ifname == NULL)
                ctrl_ifname = wpa_cli_get_default_ifname();
 
@@ -3275,9 +3425,12 @@ static void try_connection(void *eloop_ctx, void *timeout_ctx)
                return;
        }
 
+       update_bssid_list(ctrl_conn);
+
        if (warning_displayed)
                printf("Connection established.\n");
 
+done:
        start_edit();
 }
 
@@ -3293,6 +3446,7 @@ static void wpa_cli_interactive(void)
        cli_txt_list_flush(&p2p_peers);
        cli_txt_list_flush(&p2p_groups);
        cli_txt_list_flush(&bsses);
+       cli_txt_list_flush(&ifnames);
        if (edit_started)
                edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
        os_free(hfile);
@@ -3399,7 +3553,7 @@ static char * wpa_cli_get_default_ifname(void)
 #endif /* CONFIG_CTRL_IFACE_UNIX */
 
 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
-       char buf[2048], *pos;
+       char buf[4096], *pos;
        size_t len;
        struct wpa_ctrl *ctrl;
        int ret;
@@ -3493,6 +3647,24 @@ int main(int argc, char *argv[])
                                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\n");
+                               }
+                       }
+               }
        }
 
        eloop_register_signal_terminate(wpa_cli_terminate, NULL);