Write hostapd pid to a file am: fa798f237b am: 62bade5796
am: cac82f62b7
Change-Id: Ic63bd018d7cc8d964b575a09bce1f82e74e24664
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index de37def..ea3a39a 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -947,7 +947,10 @@
L_CFLAGS += -DCONFIG_ANDROID_LOG
endif
-OBJS_c = hostapd_cli.c src/common/wpa_ctrl.c src/utils/os_$(CONFIG_OS).c
+OBJS_c = hostapd_cli.c
+OBJS_c += src/common/wpa_ctrl.c
+OBJS_c += src/utils/os_$(CONFIG_OS).c
+OBJS_c += src/common/cli.c
OBJS_c += src/utils/eloop.c
OBJS_c += src/utils/common.c
ifdef CONFIG_WPA_TRACE
diff --git a/hostapd/Makefile b/hostapd/Makefile
index baa7819..ba094ba 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -87,7 +87,10 @@
OBJS += ../src/ap/neighbor_db.o
OBJS += ../src/ap/rrm.o
-OBJS_c = hostapd_cli.o ../src/common/wpa_ctrl.o ../src/utils/os_$(CONFIG_OS).o
+OBJS_c = hostapd_cli.o
+OBJS_c += ../src/common/wpa_ctrl.o
+OBJS_c += ../src/utils/os_$(CONFIG_OS).o
+OBJS_c += ../src/common/cli.o
NEED_RC4=y
NEED_AES=y
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 6dc7e8c..1b506a7 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -636,8 +636,7 @@
}
-static int hostapd_parse_das_client(struct hostapd_bss_config *bss,
- const char *val)
+static int hostapd_parse_das_client(struct hostapd_bss_config *bss, char *val)
{
char *secret;
@@ -645,7 +644,7 @@
if (secret == NULL)
return -1;
- secret++;
+ *secret++ = '\0';
if (hostapd_parse_ip_addr(val, &bss->radius_das_client_addr))
return -1;
@@ -2411,6 +2410,9 @@
bss->radius_das_time_window = atoi(pos);
} else if (os_strcmp(buf, "radius_das_require_event_timestamp") == 0) {
bss->radius_das_require_event_timestamp = atoi(pos);
+ } else if (os_strcmp(buf, "radius_das_require_message_authenticator") ==
+ 0) {
+ bss->radius_das_require_message_authenticator = atoi(pos);
#endif /* CONFIG_NO_RADIUS */
} else if (os_strcmp(buf, "auth_algs") == 0) {
bss->auth_algs = atoi(pos);
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index c244624..a310c05 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -1088,6 +1088,9 @@
#
# DAS require Event-Timestamp
#radius_das_require_event_timestamp=1
+#
+# DAS require Message-Authenticator
+#radius_das_require_message_authenticator=1
##### RADIUS authentication server configuration ##############################
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index 5c1f297..04819d1 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -15,6 +15,7 @@
#include "utils/eloop.h"
#include "utils/edit.h"
#include "common/version.h"
+#include "common/cli.h"
#ifndef CONFIG_NO_CTRL_IFACE
@@ -22,74 +23,6 @@
"hostapd_cli v" VERSION_STR "\n"
"Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi> and contributors";
-
-static const char *const hostapd_cli_license =
-"This software may be distributed under the terms of the BSD license.\n"
-"See README for more details.\n";
-
-static const char *const hostapd_cli_full_license =
-"This software may be distributed under the terms of the BSD license.\n"
-"\n"
-"Redistribution and use in source and binary forms, with or without\n"
-"modification, are permitted provided that the following conditions are\n"
-"met:\n"
-"\n"
-"1. Redistributions of source code must retain the above copyright\n"
-" notice, this list of conditions and the following disclaimer.\n"
-"\n"
-"2. Redistributions in binary form must reproduce the above copyright\n"
-" notice, this list of conditions and the following disclaimer in the\n"
-" documentation and/or other materials provided with the distribution.\n"
-"\n"
-"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
-" names of its contributors may be used to endorse or promote products\n"
-" derived from this software without specific prior written permission.\n"
-"\n"
-"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
-"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
-"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
-"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
-"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
-"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
-"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
-"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
-"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
-"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
-"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
-"\n";
-
-static const char *const commands_help =
-"Commands:\n"
-" mib get MIB variables (dot1x, dot11, radius)\n"
-" sta <addr> get MIB variables for one station\n"
-" all_sta get MIB variables for all stations\n"
-" new_sta <addr> add a new station\n"
-" deauthenticate <addr> deauthenticate a station\n"
-" disassociate <addr> disassociate a station\n"
-#ifdef CONFIG_IEEE80211W
-" sa_query <addr> send SA Query to a station\n"
-#endif /* CONFIG_IEEE80211W */
-#ifdef CONFIG_WPS
-" wps_pin <uuid> <pin> [timeout] [addr] add WPS Enrollee PIN\n"
-" wps_check_pin <PIN> verify PIN checksum\n"
-" wps_pbc indicate button pushed to initiate PBC\n"
-" wps_cancel cancel the pending WPS operation\n"
-#ifdef CONFIG_WPS_NFC
-" wps_nfc_tag_read <hexdump> report read NFC tag with WPS data\n"
-" wps_nfc_config_token <WPS/NDEF> build NFC configuration token\n"
-" wps_nfc_token <WPS/NDEF/enable/disable> manager NFC password token\n"
-#endif /* CONFIG_WPS_NFC */
-" wps_ap_pin <cmd> [params..] enable/disable AP PIN\n"
-" wps_config <SSID> <auth> <encr> <key> configure AP\n"
-" wps_get_status show current WPS status\n"
-#endif /* CONFIG_WPS */
-" get_config show current configuration\n"
-" help show this usage help\n"
-" interface [ifname] show interfaces/select interface\n"
-" level <debug level> change debug level\n"
-" license show full hostapd_cli license\n"
-" quit exit hostapd_cli\n";
-
static struct wpa_ctrl *ctrl_conn;
static int hostapd_cli_quit = 0;
static int hostapd_cli_attached = 0;
@@ -105,6 +38,13 @@
static const char *action_file = NULL;
static int ping_interval = 5;
static int interactive = 0;
+static int event_handler_registered = 0;
+
+static DEFINE_DL_LIST(stations); /* struct cli_txt_entry */
+
+static void print_help(FILE *stream, const char *cmd);
+static char ** list_cmd_list(void);
+static void hostapd_cli_receive(int sock, void *eloop_ctx, void *sock_ctx);
static void usage(void)
@@ -129,9 +69,32 @@
" -B run a daemon in the background\n"
" -i<ifname> Interface to listen on (default: first "
"interface found in the\n"
- " socket path)\n\n"
- "%s",
- commands_help);
+ " socket path)\n\n");
+ print_help(stderr, NULL);
+}
+
+
+static void register_event_handler(struct wpa_ctrl *ctrl)
+{
+ if (!ctrl_conn)
+ return;
+ if (interactive) {
+ event_handler_registered =
+ !eloop_register_read_sock(wpa_ctrl_get_fd(ctrl),
+ hostapd_cli_receive,
+ NULL, NULL);
+ }
+}
+
+
+static void unregister_event_handler(struct wpa_ctrl *ctrl)
+{
+ if (!ctrl_conn)
+ return;
+ if (interactive && event_handler_registered) {
+ eloop_unregister_read_sock(wpa_ctrl_get_fd(ctrl));
+ event_handler_registered = 0;
+ }
}
@@ -174,6 +137,7 @@
if (ctrl_conn == NULL)
return;
+ unregister_event_handler(ctrl_conn);
if (hostapd_cli_attached) {
wpa_ctrl_detach(ctrl_conn);
hostapd_cli_attached = 0;
@@ -223,36 +187,6 @@
}
-static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
- char *argv[])
-{
- int i, res;
- char *pos, *end;
-
- pos = buf;
- end = buf + buflen;
-
- res = os_snprintf(pos, end - pos, "%s", cmd);
- if (os_snprintf_error(end - pos, res))
- goto fail;
- pos += res;
-
- for (i = 0; i < argc; i++) {
- res = os_snprintf(pos, end - pos, " %s", argv[i]);
- if (os_snprintf_error(end - pos, res))
- goto fail;
- pos += res;
- }
-
- buf[buflen - 1] = '\0';
- return 0;
-
-fail:
- printf("Too long command\n");
- return -1;
-}
-
-
static int hostapd_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd,
int min_args, int argc, char *argv[])
{
@@ -384,6 +318,21 @@
}
+static char ** hostapd_complete_deauthenticate(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ char **res = NULL;
+
+ switch (arg) {
+ case 1:
+ res = cli_txt_list_array(&stations);
+ break;
+ }
+
+ return res;
+}
+
+
static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@@ -402,6 +351,21 @@
}
+static char ** hostapd_complete_disassociate(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ char **res = NULL;
+
+ switch (arg) {
+ case 1:
+ res = cli_txt_list_array(&stations);
+ break;
+ }
+
+ return res;
+}
+
+
#ifdef CONFIG_IEEE80211W
static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
char *argv[])
@@ -774,15 +738,30 @@
static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
- printf("%s", commands_help);
+ print_help(stdout, argc > 0 ? argv[0] : NULL);
return 0;
}
+static char ** hostapd_cli_complete_help(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ char **res = NULL;
+
+ switch (arg) {
+ case 1:
+ res = list_cmd_list();
+ break;
+ }
+
+ return res;
+}
+
+
static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
- printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
+ printf("%s\n\n%s\n", hostapd_cli_version, cli_full_license);
return 0;
}
@@ -893,6 +872,28 @@
}
+static void hostapd_cli_get_interfaces(struct wpa_ctrl *ctrl,
+ struct dl_list *interfaces)
+{
+ struct dirent *dent;
+ DIR *dir;
+
+ if (!ctrl || !interfaces)
+ return;
+ dir = opendir(ctrl_iface_dir);
+ if (dir == NULL)
+ return;
+
+ while ((dent = readdir(dir))) {
+ if (strcmp(dent->d_name, ".") == 0 ||
+ strcmp(dent->d_name, "..") == 0)
+ continue;
+ cli_txt_list_add(interfaces, dent->d_name);
+ }
+ closedir(dir);
+}
+
+
static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
{
struct dirent *dent;
@@ -934,6 +935,7 @@
printf("Connected to interface '%s.\n", ctrl_ifname);
if (wpa_ctrl_attach(ctrl_conn) == 0) {
hostapd_cli_attached = 1;
+ register_event_handler(ctrl_conn);
} else {
printf("Warning: Failed to attach to "
"hostapd.\n");
@@ -946,6 +948,24 @@
}
+static char ** hostapd_complete_interface(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ char **res = NULL;
+ DEFINE_DL_LIST(interfaces);
+
+ switch (arg) {
+ case 1:
+ hostapd_cli_get_interfaces(ctrl_conn, &interfaces);
+ res = cli_txt_list_array(&interfaces);
+ cli_txt_list_flush(&interfaces);
+ break;
+ }
+
+ return res;
+}
+
+
static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
char cmd[256];
@@ -1228,73 +1248,135 @@
struct hostapd_cli_cmd {
const char *cmd;
int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
+ char ** (*completion)(const char *str, int pos);
+ const char *usage;
};
static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
- { "ping", hostapd_cli_cmd_ping },
- { "mib", hostapd_cli_cmd_mib },
- { "relog", hostapd_cli_cmd_relog },
- { "status", hostapd_cli_cmd_status },
- { "sta", hostapd_cli_cmd_sta },
- { "all_sta", hostapd_cli_cmd_all_sta },
- { "new_sta", hostapd_cli_cmd_new_sta },
- { "deauthenticate", hostapd_cli_cmd_deauthenticate },
- { "disassociate", hostapd_cli_cmd_disassociate },
+ { "ping", hostapd_cli_cmd_ping, NULL,
+ "= pings hostapd" },
+ { "mib", hostapd_cli_cmd_mib, NULL,
+ "= get MIB variables (dot1x, dot11, radius)" },
+ { "relog", hostapd_cli_cmd_relog, NULL, NULL },
+ { "status", hostapd_cli_cmd_status, NULL, NULL },
+ { "sta", hostapd_cli_cmd_sta, NULL,
+ "<addr> = get MIB variables for one station" },
+ { "all_sta", hostapd_cli_cmd_all_sta, NULL,
+ "= get MIB variables for all stations" },
+ { "new_sta", hostapd_cli_cmd_new_sta, NULL,
+ "<addr> = add a new station" },
+ { "deauthenticate", hostapd_cli_cmd_deauthenticate,
+ hostapd_complete_deauthenticate,
+ "<addr> = deauthenticate a station" },
+ { "disassociate", hostapd_cli_cmd_disassociate,
+ hostapd_complete_disassociate,
+ "<addr> = disassociate a station" },
#ifdef CONFIG_IEEE80211W
- { "sa_query", hostapd_cli_cmd_sa_query },
+ { "sa_query", hostapd_cli_cmd_sa_query, NULL,
+ "<addr> = send SA Query to a station" },
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_WPS
- { "wps_pin", hostapd_cli_cmd_wps_pin },
- { "wps_check_pin", hostapd_cli_cmd_wps_check_pin },
- { "wps_pbc", hostapd_cli_cmd_wps_pbc },
- { "wps_cancel", hostapd_cli_cmd_wps_cancel },
+ { "wps_pin", hostapd_cli_cmd_wps_pin, NULL,
+ "<uuid> <pin> [timeout] [addr] = add WPS Enrollee PIN" },
+ { "wps_check_pin", hostapd_cli_cmd_wps_check_pin, NULL,
+ "<PIN> = verify PIN checksum" },
+ { "wps_pbc", hostapd_cli_cmd_wps_pbc, NULL,
+ "= indicate button pushed to initiate PBC" },
+ { "wps_cancel", hostapd_cli_cmd_wps_cancel, NULL,
+ "= cancel the pending WPS operation" },
#ifdef CONFIG_WPS_NFC
- { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
- { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
- { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
- { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel },
+ { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read, NULL,
+ "<hexdump> = report read NFC tag with WPS data" },
+ { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token, NULL,
+ "<WPS/NDEF> = build NFC configuration token" },
+ { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token, NULL,
+ "<WPS/NDEF/enable/disable> = manager NFC password token" },
+ { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel, NULL,
+ NULL },
#endif /* CONFIG_WPS_NFC */
- { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
- { "wps_config", hostapd_cli_cmd_wps_config },
- { "wps_get_status", hostapd_cli_cmd_wps_get_status },
+ { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin, NULL,
+ "<cmd> [params..] = enable/disable AP PIN" },
+ { "wps_config", hostapd_cli_cmd_wps_config, NULL,
+ "<SSID> <auth> <encr> <key> = configure AP" },
+ { "wps_get_status", hostapd_cli_cmd_wps_get_status, NULL,
+ "= show current WPS status" },
#endif /* CONFIG_WPS */
- { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
- { "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
- { "bss_tm_req", hostapd_cli_cmd_bss_tm_req },
- { "get_config", hostapd_cli_cmd_get_config },
- { "help", hostapd_cli_cmd_help },
- { "interface", hostapd_cli_cmd_interface },
+ { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent, NULL, NULL },
+ { "ess_disassoc", hostapd_cli_cmd_ess_disassoc, NULL, NULL },
+ { "bss_tm_req", hostapd_cli_cmd_bss_tm_req, NULL, NULL },
+ { "get_config", hostapd_cli_cmd_get_config, NULL,
+ "= show current configuration" },
+ { "help", hostapd_cli_cmd_help, hostapd_cli_complete_help,
+ "= show this usage help" },
+ { "interface", hostapd_cli_cmd_interface, hostapd_complete_interface,
+ "[ifname] = show interfaces/select interface" },
#ifdef CONFIG_FST
- { "fst", hostapd_cli_cmd_fst },
+ { "fst", hostapd_cli_cmd_fst, NULL, NULL },
#endif /* CONFIG_FST */
- { "raw", hostapd_cli_cmd_raw },
- { "level", hostapd_cli_cmd_level },
- { "license", hostapd_cli_cmd_license },
- { "quit", hostapd_cli_cmd_quit },
- { "set", hostapd_cli_cmd_set },
- { "get", hostapd_cli_cmd_get },
- { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set },
- { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf },
- { "chan_switch", hostapd_cli_cmd_chan_switch },
- { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif },
- { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req },
- { "vendor", hostapd_cli_cmd_vendor },
- { "enable", hostapd_cli_cmd_enable },
- { "reload", hostapd_cli_cmd_reload },
- { "disable", hostapd_cli_cmd_disable },
- { "erp_flush", hostapd_cli_cmd_erp_flush },
- { "log_level", hostapd_cli_cmd_log_level },
- { "pmksa", hostapd_cli_cmd_pmksa },
- { "pmksa_flush", hostapd_cli_cmd_pmksa_flush },
- { "set_neighbor", hostapd_cli_cmd_set_neighbor },
- { "remove_neighbor", hostapd_cli_cmd_remove_neighbor },
- { "req_lci", hostapd_cli_cmd_req_lci },
- { "req_range", hostapd_cli_cmd_req_range },
- { "driver_flags", hostapd_cli_cmd_driver_flags },
- { NULL, NULL }
+ { "raw", hostapd_cli_cmd_raw, NULL, NULL },
+ { "level", hostapd_cli_cmd_level, NULL,
+ "<debug level> = change debug level" },
+ { "license", hostapd_cli_cmd_license, NULL,
+ "= show full hostapd_cli license" },
+ { "quit", hostapd_cli_cmd_quit, NULL,
+ "= exit hostapd_cli" },
+ { "set", hostapd_cli_cmd_set, NULL, NULL },
+ { "get", hostapd_cli_cmd_get, NULL, NULL },
+ { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set, NULL, NULL },
+ { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf, NULL, NULL },
+ { "chan_switch", hostapd_cli_cmd_chan_switch, NULL, NULL },
+ { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL, NULL },
+ { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req, NULL, NULL },
+ { "vendor", hostapd_cli_cmd_vendor, NULL, NULL },
+ { "enable", hostapd_cli_cmd_enable, NULL, NULL },
+ { "reload", hostapd_cli_cmd_reload, NULL, NULL },
+ { "disable", hostapd_cli_cmd_disable, NULL, NULL },
+ { "erp_flush", hostapd_cli_cmd_erp_flush, NULL, NULL },
+ { "log_level", hostapd_cli_cmd_log_level, NULL, NULL },
+ { "pmksa", hostapd_cli_cmd_pmksa, NULL, NULL },
+ { "pmksa_flush", hostapd_cli_cmd_pmksa_flush, NULL, NULL },
+ { "set_neighbor", hostapd_cli_cmd_set_neighbor, NULL, NULL },
+ { "remove_neighbor", hostapd_cli_cmd_remove_neighbor, NULL, NULL },
+ { "req_lci", hostapd_cli_cmd_req_lci, NULL, NULL },
+ { "req_range", hostapd_cli_cmd_req_range, NULL, NULL },
+ { "driver_flags", hostapd_cli_cmd_driver_flags, NULL, NULL },
+ { NULL, NULL, NULL, NULL }
};
+/*
+ * Prints command usage, lines are padded with the specified string.
+ */
+static void print_cmd_help(FILE *stream, const struct hostapd_cli_cmd *cmd,
+ const char *pad)
+{
+ char c;
+ size_t n;
+
+ if (cmd->usage == NULL)
+ return;
+ fprintf(stream, "%s%s ", pad, cmd->cmd);
+ for (n = 0; (c = cmd->usage[n]); n++) {
+ fprintf(stream, "%c", c);
+ if (c == '\n')
+ fprintf(stream, "%s", pad);
+ }
+ fprintf(stream, "\n");
+}
+
+
+static void print_help(FILE *stream, const char *cmd)
+{
+ int n;
+
+ fprintf(stream, "commands:\n");
+ for (n = 0; hostapd_cli_commands[n].cmd; n++) {
+ if (cmd == NULL || str_starts(hostapd_cli_commands[n].cmd, cmd))
+ print_cmd_help(stream, &hostapd_cli_commands[n], " ");
+ }
+}
+
+
static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
const struct hostapd_cli_cmd *cmd, *match = NULL;
@@ -1334,6 +1416,34 @@
}
+static void cli_event(const char *str)
+{
+ const char *start, *s;
+
+ start = os_strchr(str, '>');
+ if (start == NULL)
+ return;
+
+ start++;
+
+ if (str_starts(start, AP_STA_CONNECTED)) {
+ s = os_strchr(start, ' ');
+ if (s == NULL)
+ return;
+ cli_txt_list_add(&stations, s + 1);
+ return;
+ }
+
+ if (str_starts(start, AP_STA_DISCONNECTED)) {
+ s = os_strchr(start, ' ');
+ if (s == NULL)
+ return;
+ cli_txt_list_del_addr(&stations, s + 1);
+ return;
+ }
+}
+
+
static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
int action_monitor)
{
@@ -1348,6 +1458,7 @@
if (action_monitor)
hostapd_cli_action_process(buf, len);
else {
+ cli_event(buf);
if (in_read && first)
printf("\n");
first = 0;
@@ -1361,35 +1472,9 @@
}
-#define max_args 10
-
-static int tokenize_cmd(char *cmd, char *argv[])
+static void hostapd_cli_receive(int sock, void *eloop_ctx, void *sock_ctx)
{
- char *pos;
- int argc = 0;
-
- pos = cmd;
- for (;;) {
- while (*pos == ' ')
- pos++;
- if (*pos == '\0')
- break;
- argv[argc] = pos;
- argc++;
- if (argc == max_args)
- break;
- if (*pos == '"') {
- char *pos2 = os_strrchr(pos, '"');
- if (pos2)
- pos = pos2 + 1;
- }
- while (*pos != '\0' && *pos != ' ')
- pos++;
- if (*pos == ' ')
- *pos++ = '\0';
- }
-
- return argc;
+ hostapd_cli_recv_pending(ctrl_conn, 0, 0);
}
@@ -1405,6 +1490,7 @@
printf("Connection to hostapd re-established\n");
if (wpa_ctrl_attach(ctrl_conn) == 0) {
hostapd_cli_attached = 1;
+ register_event_handler(ctrl_conn);
} else {
printf("Warning: Failed to attach to "
"hostapd.\n");
@@ -1439,17 +1525,82 @@
}
+static char ** list_cmd_list(void)
+{
+ char **res;
+ int i, count;
+
+ count = ARRAY_SIZE(hostapd_cli_commands);
+ res = os_calloc(count + 1, sizeof(char *));
+ if (res == NULL)
+ return NULL;
+
+ for (i = 0; hostapd_cli_commands[i].cmd; i++) {
+ res[i] = os_strdup(hostapd_cli_commands[i].cmd);
+ if (res[i] == NULL)
+ break;
+ }
+
+ return res;
+}
+
+
+static char ** hostapd_cli_cmd_completion(const char *cmd, const char *str,
+ int pos)
+{
+ int i;
+
+ for (i = 0; hostapd_cli_commands[i].cmd; i++) {
+ if (os_strcasecmp(hostapd_cli_commands[i].cmd, cmd) != 0)
+ continue;
+ if (hostapd_cli_commands[i].completion)
+ return hostapd_cli_commands[i].completion(str, pos);
+ if (!hostapd_cli_commands[i].usage)
+ return NULL;
+ edit_clear_line();
+ printf("\r%s\n", hostapd_cli_commands[i].usage);
+ edit_redraw();
+ break;
+ }
+
+ return NULL;
+}
+
+
+static char ** hostapd_cli_edit_completion_cb(void *ctx, const char *str,
+ int pos)
+{
+ char **res;
+ const char *end;
+ char *cmd;
+
+ end = os_strchr(str, ' ');
+ if (end == NULL || str + pos < end)
+ return list_cmd_list();
+
+ cmd = os_malloc(pos + 1);
+ if (cmd == NULL)
+ return NULL;
+ os_memcpy(cmd, str, pos);
+ cmd[end - str] = '\0';
+ res = hostapd_cli_cmd_completion(cmd, str, pos);
+ os_free(cmd);
+ return res;
+}
+
+
static void hostapd_cli_interactive(void)
{
printf("\nInteractive mode\n\n");
eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
- NULL, NULL, NULL, NULL);
+ hostapd_cli_edit_completion_cb, NULL, NULL, NULL);
eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
eloop_run();
+ cli_txt_list_flush(&stations);
edit_deinit(NULL, NULL);
eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
}
@@ -1553,8 +1704,7 @@
interactive = (argc == optind) && (action_file == NULL);
if (interactive) {
- printf("%s\n\n%s\n\n", hostapd_cli_version,
- hostapd_cli_license);
+ printf("%s\n\n%s\n\n", hostapd_cli_version, cli_license);
}
if (eloop_init())
@@ -1602,6 +1752,7 @@
if (interactive || action_file) {
if (wpa_ctrl_attach(ctrl_conn) == 0) {
hostapd_cli_attached = 1;
+ register_event_handler(ctrl_conn);
} else {
printf("Warning: Failed to attach to hostapd.\n");
if (action_file)
@@ -1619,6 +1770,7 @@
else
wpa_request(ctrl_conn, argc - optind, &argv[optind]);
+ unregister_event_handler(ctrl_conn);
os_free(ctrl_ifname);
eloop_destroy();
hostapd_cli_cleanup();
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 2345dd9..228de2b 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -841,6 +841,15 @@
}
#endif /* CONFIG_IEEE80211N */
+#ifdef CONFIG_IEEE80211AC
+ if (full_config && conf->ieee80211ac &&
+ bss->ssid.security_policy == SECURITY_STATIC_WEP) {
+ bss->disable_11ac = 1;
+ wpa_printf(MSG_ERROR,
+ "VHT (IEEE 802.11ac) with WEP is not allowed, disabling VHT capabilities");
+ }
+#endif /* CONFIG_IEEE80211AC */
+
#ifdef CONFIG_WPS
if (full_config && bss->wps_state && bss->ignore_broadcast_ssid) {
wpa_printf(MSG_INFO, "WPS: ignore_broadcast_ssid "
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 0ae9a6e..64daf4c 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -263,6 +263,7 @@
int radius_das_port;
unsigned int radius_das_time_window;
int radius_das_require_event_timestamp;
+ int radius_das_require_message_authenticator;
struct hostapd_ip_addr radius_das_client_addr;
u8 *radius_das_shared_secret;
size_t radius_das_shared_secret_len;
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index 14c154f..17a3ea4 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -514,20 +514,28 @@
"channel=%u\n"
"secondary_channel=%d\n"
"ieee80211n=%d\n"
- "ieee80211ac=%d\n"
- "vht_oper_chwidth=%d\n"
- "vht_oper_centr_freq_seg0_idx=%d\n"
- "vht_oper_centr_freq_seg1_idx=%d\n",
+ "ieee80211ac=%d\n",
iface->conf->channel,
- iface->conf->secondary_channel,
- iface->conf->ieee80211n,
- iface->conf->ieee80211ac,
- iface->conf->vht_oper_chwidth,
- iface->conf->vht_oper_centr_freq_seg0_idx,
- iface->conf->vht_oper_centr_freq_seg1_idx);
+ iface->conf->ieee80211n && !hapd->conf->disable_11n ?
+ iface->conf->secondary_channel : 0,
+ iface->conf->ieee80211n && !hapd->conf->disable_11n,
+ iface->conf->ieee80211ac &&
+ !hapd->conf->disable_11ac);
if (os_snprintf_error(buflen - len, ret))
return len;
len += ret;
+ if (iface->conf->ieee80211ac && !hapd->conf->disable_11ac) {
+ ret = os_snprintf(buf + len, buflen - len,
+ "vht_oper_chwidth=%d\n"
+ "vht_oper_centr_freq_seg0_idx=%d\n"
+ "vht_oper_centr_freq_seg1_idx=%d\n",
+ iface->conf->vht_oper_chwidth,
+ iface->conf->vht_oper_centr_freq_seg0_idx,
+ iface->conf->vht_oper_centr_freq_seg1_idx);
+ if (os_snprintf_error(buflen - len, ret))
+ return len;
+ len += ret;
+ }
for (i = 0; i < iface->num_bss; i++) {
struct hostapd_data *bss = iface->bss[i];
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 30f57f4..65f513d 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1044,6 +1044,8 @@
das_conf.time_window = conf->radius_das_time_window;
das_conf.require_event_timestamp =
conf->radius_das_require_event_timestamp;
+ das_conf.require_message_authenticator =
+ conf->radius_das_require_message_authenticator;
das_conf.ctx = hapd;
das_conf.disconnect = hostapd_das_disconnect;
hapd->radius_das = radius_das_init(&das_conf);
diff --git a/src/ap/iapp.c b/src/ap/iapp.c
index 07672ce..2556da3 100644
--- a/src/ap/iapp.c
+++ b/src/ap/iapp.c
@@ -381,6 +381,7 @@
struct sockaddr_in *paddr, uaddr;
struct iapp_data *iapp;
struct ip_mreqn mreq;
+ int reuseaddr = 1;
iapp = os_zalloc(sizeof(*iapp));
if (iapp == NULL)
@@ -443,6 +444,18 @@
os_memset(&uaddr, 0, sizeof(uaddr));
uaddr.sin_family = AF_INET;
uaddr.sin_port = htons(IAPP_UDP_PORT);
+
+ if (setsockopt(iapp->udp_sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
+ sizeof(reuseaddr)) < 0) {
+ wpa_printf(MSG_INFO,
+ "iapp_init - setsockopt[UDP,SO_REUSEADDR]: %s",
+ strerror(errno));
+ /*
+ * Ignore this and try to continue. This is fine for single
+ * BSS cases, but may fail if multiple BSSes enable IAPP.
+ */
+ }
+
if (bind(iapp->udp_sock, (struct sockaddr *) &uaddr,
sizeof(uaddr)) < 0) {
wpa_printf(MSG_INFO, "iapp_init - bind[UDP]: %s",
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 11f12f9..eed5483 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -2557,8 +2557,9 @@
"handle_action - unknown action category %d or invalid "
"frame",
mgmt->u.action.category);
- if (!(mgmt->da[0] & 0x01) && !(mgmt->u.action.category & 0x80) &&
- !(mgmt->sa[0] & 0x01)) {
+ if (!is_multicast_ether_addr(mgmt->da) &&
+ !(mgmt->u.action.category & 0x80) &&
+ !is_multicast_ether_addr(mgmt->sa)) {
struct ieee80211_mgmt *resp;
/*
@@ -2605,7 +2606,6 @@
struct hostapd_frame_info *fi)
{
struct ieee80211_mgmt *mgmt;
- int broadcast;
u16 fc, stype;
int ret = 0;
@@ -2621,11 +2621,7 @@
return 1;
}
- broadcast = mgmt->bssid[0] == 0xff && mgmt->bssid[1] == 0xff &&
- mgmt->bssid[2] == 0xff && mgmt->bssid[3] == 0xff &&
- mgmt->bssid[4] == 0xff && mgmt->bssid[5] == 0xff;
-
- if (!broadcast &&
+ if (!is_broadcast_ether_addr(mgmt->bssid) &&
#ifdef CONFIG_P2P
/* Invitation responses can be sent with the peer MAC as BSSID */
!((hapd->conf->p2p & P2P_GROUP_OWNER) &&
@@ -2906,7 +2902,7 @@
size_t len, int ok)
{
struct sta_info *sta;
- if (mgmt->da[0] & 0x01)
+ if (is_multicast_ether_addr(mgmt->da))
return;
sta = ap_get_sta(hapd, mgmt->da);
if (!sta) {
@@ -2930,7 +2926,7 @@
size_t len, int ok)
{
struct sta_info *sta;
- if (mgmt->da[0] & 0x01)
+ if (is_multicast_ether_addr(mgmt->da))
return;
sta = ap_get_sta(hapd, mgmt->da);
if (!sta) {
@@ -3135,7 +3131,7 @@
wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated STA "
MACSTR, MAC2STR(src));
- if (src[0] & 0x01) {
+ if (is_multicast_ether_addr(src)) {
/* Broadcast bit set in SA?! Ignore the frame silently. */
return;
}
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index 42b0299..80ff996 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -414,6 +414,7 @@
if (!hostapd_config_get_radius_attr(req_attr,
RADIUS_ATTR_NAS_PORT) &&
+ sta->aid > 0 &&
!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) {
wpa_printf(MSG_ERROR, "Could not add NAS-Port");
return -1;
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index faf38c9..95b40da 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -269,12 +269,6 @@
}
-static int str_starts(const char *str, const char *start)
-{
- return os_strncmp(str, start, os_strlen(start)) == 0;
-}
-
-
static void wps_reload_config(void *eloop_data, void *user_ctx)
{
struct hostapd_iface *iface = eloop_data;
diff --git a/src/common/cli.c b/src/common/cli.c
new file mode 100644
index 0000000..b583d1c
--- /dev/null
+++ b/src/common/cli.c
@@ -0,0 +1,267 @@
+/*
+ * Common hostapd/wpa_supplicant command line interface functions
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "utils/common.h"
+#include "common/cli.h"
+
+
+const char *const cli_license =
+"This software may be distributed under the terms of the BSD license.\n"
+"See README for more details.\n";
+
+const char *const cli_full_license =
+"This software may be distributed under the terms of the BSD license.\n"
+"\n"
+"Redistribution and use in source and binary forms, with or without\n"
+"modification, are permitted provided that the following conditions are\n"
+"met:\n"
+"\n"
+"1. Redistributions of source code must retain the above copyright\n"
+" notice, this list of conditions and the following disclaimer.\n"
+"\n"
+"2. Redistributions in binary form must reproduce the above copyright\n"
+" notice, this list of conditions and the following disclaimer in the\n"
+" documentation and/or other materials provided with the distribution.\n"
+"\n"
+"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
+" names of its contributors may be used to endorse or promote products\n"
+" derived from this software without specific prior written permission.\n"
+"\n"
+"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
+"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
+"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
+"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
+"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
+"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
+"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
+"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
+"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
+"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
+"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
+"\n";
+
+
+void cli_txt_list_free(struct cli_txt_entry *e)
+{
+ dl_list_del(&e->list);
+ os_free(e->txt);
+ os_free(e);
+}
+
+
+void cli_txt_list_flush(struct dl_list *list)
+{
+ struct cli_txt_entry *e;
+
+ while ((e = dl_list_first(list, struct cli_txt_entry, list)))
+ cli_txt_list_free(e);
+}
+
+
+struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
+ const char *txt)
+{
+ struct cli_txt_entry *e;
+
+ dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
+ if (os_strcmp(e->txt, txt) == 0)
+ return e;
+ }
+ return NULL;
+}
+
+
+void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
+{
+ struct cli_txt_entry *e;
+
+ e = cli_txt_list_get(txt_list, txt);
+ if (e)
+ cli_txt_list_free(e);
+}
+
+
+void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
+{
+ u8 addr[ETH_ALEN];
+ char buf[18];
+
+ if (hwaddr_aton(txt, addr) < 0)
+ return;
+ os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
+ cli_txt_list_del(txt_list, buf);
+}
+
+
+void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt,
+ int separator)
+{
+ const char *end;
+ char *buf;
+
+ end = os_strchr(txt, separator);
+ if (end == NULL)
+ end = txt + os_strlen(txt);
+ buf = dup_binstr(txt, end - txt);
+ if (buf == NULL)
+ return;
+ cli_txt_list_del(txt_list, buf);
+ os_free(buf);
+}
+
+
+int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
+{
+ struct cli_txt_entry *e;
+
+ e = cli_txt_list_get(txt_list, txt);
+ if (e)
+ return 0;
+ e = os_zalloc(sizeof(*e));
+ if (e == NULL)
+ return -1;
+ e->txt = os_strdup(txt);
+ if (e->txt == NULL) {
+ os_free(e);
+ return -1;
+ }
+ dl_list_add(txt_list, &e->list);
+ return 0;
+}
+
+
+int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
+{
+ u8 addr[ETH_ALEN];
+ char buf[18];
+
+ if (hwaddr_aton(txt, addr) < 0)
+ return -1;
+ os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
+ return cli_txt_list_add(txt_list, buf);
+}
+
+
+int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt,
+ int separator)
+{
+ const char *end;
+ char *buf;
+ int ret;
+
+ end = os_strchr(txt, separator);
+ if (end == NULL)
+ end = txt + os_strlen(txt);
+ buf = dup_binstr(txt, end - txt);
+ if (buf == NULL)
+ return -1;
+ ret = cli_txt_list_add(txt_list, buf);
+ os_free(buf);
+ return ret;
+}
+
+
+char ** cli_txt_list_array(struct dl_list *txt_list)
+{
+ unsigned int i, count = dl_list_len(txt_list);
+ char **res;
+ struct cli_txt_entry *e;
+
+ res = os_calloc(count + 1, sizeof(char *));
+ if (res == NULL)
+ return NULL;
+
+ i = 0;
+ dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
+ res[i] = os_strdup(e->txt);
+ if (res[i] == NULL)
+ break;
+ i++;
+ }
+
+ return res;
+}
+
+
+int get_cmd_arg_num(const char *str, int pos)
+{
+ int arg = 0, i;
+
+ for (i = 0; i <= pos; i++) {
+ if (str[i] != ' ') {
+ arg++;
+ while (i <= pos && str[i] != ' ')
+ i++;
+ }
+ }
+
+ if (arg > 0)
+ arg--;
+ return arg;
+}
+
+
+int write_cmd(char *buf, size_t buflen, const char *cmd, int argc, char *argv[])
+{
+ int i, res;
+ char *pos, *end;
+
+ pos = buf;
+ end = buf + buflen;
+
+ res = os_snprintf(pos, end - pos, "%s", cmd);
+ if (os_snprintf_error(end - pos, res))
+ goto fail;
+ pos += res;
+
+ for (i = 0; i < argc; i++) {
+ res = os_snprintf(pos, end - pos, " %s", argv[i]);
+ if (os_snprintf_error(end - pos, res))
+ goto fail;
+ pos += res;
+ }
+
+ buf[buflen - 1] = '\0';
+ return 0;
+
+fail:
+ printf("Too long command\n");
+ return -1;
+}
+
+
+int tokenize_cmd(char *cmd, char *argv[])
+{
+ char *pos;
+ int argc = 0;
+
+ pos = cmd;
+ for (;;) {
+ while (*pos == ' ')
+ pos++;
+ if (*pos == '\0')
+ break;
+ argv[argc] = pos;
+ argc++;
+ if (argc == max_args)
+ break;
+ if (*pos == '"') {
+ char *pos2 = os_strrchr(pos, '"');
+ if (pos2)
+ pos = pos2 + 1;
+ }
+ while (*pos != '\0' && *pos != ' ')
+ pos++;
+ if (*pos == ' ')
+ *pos++ = '\0';
+ }
+
+ return argc;
+}
diff --git a/src/common/cli.h b/src/common/cli.h
new file mode 100644
index 0000000..41ef329
--- /dev/null
+++ b/src/common/cli.h
@@ -0,0 +1,47 @@
+/*
+ * Common hostapd/wpa_supplicant command line interface functionality
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef CLI_H
+#define CLI_H
+
+#include "utils/list.h"
+
+extern const char *const cli_license;
+extern const char *const cli_full_license;
+
+struct cli_txt_entry {
+ struct dl_list list;
+ char *txt;
+};
+
+void cli_txt_list_free(struct cli_txt_entry *e);
+void cli_txt_list_flush(struct dl_list *list);
+
+struct cli_txt_entry *
+cli_txt_list_get(struct dl_list *txt_list, const char *txt);
+
+void cli_txt_list_del(struct dl_list *txt_list, const char *txt);
+void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt);
+void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt,
+ int separator);
+
+int cli_txt_list_add(struct dl_list *txt_list, const char *txt);
+int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt);
+int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt,
+ int separator);
+
+char ** cli_txt_list_array(struct dl_list *txt_list);
+
+int get_cmd_arg_num(const char *str, int pos);
+int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
+ char *argv[]);
+
+#define max_args 10
+int tokenize_cmd(char *cmd, char *argv[]);
+
+#endif /* CLI_H */
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index 912d1e1..2312b22 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -115,6 +115,15 @@
* indicated through an event using the same sub command through
* @QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_STATUS. Attributes are
* listed in qca_wlan_vendor_attr_sap_conditional_chan_switch.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GPIO_CONFIG_COMMAND: Set GPIO pins. This uses the
+ * attributes defined in enum qca_wlan_gpio_attr.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_HW_CAPABILITY: Fetch hardware capabilities.
+ * This uses @QCA_WLAN_VENDOR_ATTR_GET_HW_CAPABILITY to indicate which
+ * capabilities are to be fetched and other
+ * enum qca_wlan_vendor_attr_get_hw_capability attributes to return the
+ * requested capabilities.
*/
enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
@@ -200,6 +209,8 @@
QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START = 122,
QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP = 123,
QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH = 124,
+ QCA_NL80211_VENDOR_SUBCMD_GPIO_CONFIG_COMMAND = 125,
+ QCA_NL80211_VENDOR_SUBCMD_GET_HW_CAPABILITY = 126,
};
@@ -417,6 +428,25 @@
};
/**
+ * enum qca_access_policy - Access control policy
+ *
+ * Access control policy is applied on the configured IE
+ * (QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE).
+ * To be set with QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY.
+ *
+ * @QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED: Deny Wi-Fi connections which match
+ * the specific configuration (IE) set, i.e., allow all the
+ * connections which do not match the configuration.
+ * @QCA_ACCESS_POLICY_DENY_UNLESS_LISTED: Accept Wi-Fi connections which match
+ * the specific configuration (IE) set, i.e., deny all the
+ * connections which do not match the configuration.
+ */
+enum qca_access_policy {
+ QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED,
+ QCA_ACCESS_POLICY_DENY_UNLESS_LISTED,
+};
+
+/**
* enum qca_vendor_attr_get_tsf: Vendor attributes for TSF capture
* @QCA_WLAN_VENDOR_ATTR_TSF_CMD: enum qca_tsf_operation (u32)
* @QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE: Unsigned 64 bit TSF timer value
@@ -603,8 +633,8 @@
};
/* Attributes for data used by
- * QCA_NL80211_VENDOR_SUBCMD_SET_CONFIGURATION and
- * QCA_NL80211_VENDOR_SUBCMD_GET_CONFIGURATION subcommands.
+ * QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION and
+ * QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION subcommands.
*/
enum qca_wlan_vendor_attr_config {
QCA_WLAN_VENDOR_ATTR_CONFIG_INVALID,
@@ -668,6 +698,45 @@
* packet count. The peer is disconnected once this threshold is
* reached. */
QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT,
+ /* Attribute used to set scan default IEs to the driver.
+ *
+ * These IEs can be used by scan operations that will be initiated by
+ * the driver/firmware.
+ *
+ * For further scan requests coming to the driver, these IEs should be
+ * merged with the IEs received along with scan request coming to the
+ * driver. If a particular IE is present in the scan default IEs but not
+ * present in the scan request, then that IE should be added to the IEs
+ * sent in the Probe Request frames for that scan request. */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES,
+ /* Unsigned 32-bit attribute for generic commands */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_COMMAND,
+ /* Unsigned 32-bit value attribute for generic commands */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_VALUE,
+ /* Unsigned 32-bit data attribute for generic command response */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA,
+ /* Unsigned 32-bit length attribute for
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_LENGTH,
+ /* Unsigned 32-bit flags attribute for
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_FLAGS,
+ /* Unsigned 32-bit, defining the access policy.
+ * See enum qca_access_policy. Used with
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST. */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY,
+ /* Sets the list of full set of IEs for which a specific access policy
+ * has to be applied. Used along with
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY to control the access.
+ * Zero length payload can be used to clear this access constraint. */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST,
+ /* Unsigned 32-bit, specifies the interface index (netdev) for which the
+ * corresponding configurations are applied. If the interface index is
+ * not specified, the configurations are attributed to the respective
+ * wiphy. */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_IFINDEX,
+ /* 8-bit unsigned value to trigger QPower: 1-Enable, 0-Disable */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER,
/* keep last */
QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST,
@@ -713,4 +782,54 @@
QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_AFTER_LAST - 1,
};
+/**
+ * enum qca_wlan_gpio_attr - Parameters for GPIO configuration
+ */
+enum qca_wlan_gpio_attr {
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INVALID = 0,
+ /* Unsigned 32-bit attribute for GPIO command */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND,
+ /* Unsigned 32-bit attribute for GPIO PIN number to configure */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM,
+ /* Unsigned 32-bit attribute for GPIO value to configure */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE,
+ /* Unsigned 32-bit attribute for GPIO pull type */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE,
+ /* Unsigned 32-bit attribute for GPIO interrupt mode */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_LAST,
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MAX =
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_LAST - 1
+};
+
+/**
+ * enum qca_wlan_vendor_attr_get_hw_capability - Wi-Fi hardware capability
+ */
+enum qca_wlan_vendor_attr_get_hw_capability {
+ QCA_WLAN_VENDOR_ATTR_HW_CAPABILITY_INVALID,
+ /* Antenna isolation
+ * An attribute used in the response.
+ * The content of this attribute is encoded in a byte array. Each byte
+ * value is an antenna isolation value. The array length is the number
+ * of antennas.
+ */
+ QCA_WLAN_VENDOR_ATTR_ANTENNA_ISOLATION,
+ /* Request HW capability
+ * An attribute used in the request.
+ * The content of this attribute is a u32 array for one or more of
+ * hardware capabilities (attribute IDs) that are being requested. Each
+ * u32 value has a value from this
+ * enum qca_wlan_vendor_attr_get_hw_capability
+ * identifying which capabilities are requested.
+ */
+ QCA_WLAN_VENDOR_ATTR_GET_HW_CAPABILITY,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_HW_CAPABILITY_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_HW_CAPABILITY_MAX =
+ QCA_WLAN_VENDOR_ATTR_HW_CAPABILITY_AFTER_LAST - 1,
+};
+
#endif /* QCA_VENDOR_H */
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index 7f33686..19e0e2b 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -49,6 +49,8 @@
static void HMAC_CTX_free(HMAC_CTX *ctx)
{
+ if (!ctx)
+ return;
HMAC_CTX_cleanup(ctx);
bin_clear_free(ctx, sizeof(*ctx));
}
@@ -67,6 +69,9 @@
static void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
{
+ if (!ctx)
+ return;
+ EVP_MD_CTX_cleanup(ctx);
bin_clear_free(ctx, sizeof(*ctx));
}
@@ -74,7 +79,11 @@
static BIGNUM * get_group5_prime(void)
{
-#ifdef OPENSSL_IS_BORINGSSL
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+ return BN_get_rfc3526_prime_1536(NULL);
+#elif !defined(OPENSSL_IS_BORINGSSL)
+ return get_rfc3526_prime_1536(NULL);
+#else
static const unsigned char RFC3526_PRIME_1536[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,
0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,
@@ -94,9 +103,7 @@
0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};
return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), NULL);
-#else /* OPENSSL_IS_BORINGSSL */
- return get_rfc3526_prime_1536(NULL);
-#endif /* OPENSSL_IS_BORINGSSL */
+#endif
}
#ifdef OPENSSL_NO_SHA256
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index a85ed32..a5c5c1b 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1118,13 +1118,19 @@
};
struct wpa_driver_mesh_bss_params {
-#define WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS 0x00000001
+#define WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS 0x00000001
+#define WPA_DRIVER_MESH_CONF_FLAG_PEER_LINK_TIMEOUT 0x00000002
+#define WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS 0x00000004
+#define WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE 0x00000008
/*
* TODO: Other mesh configuration parameters would go here.
* See NL80211_MESHCONF_* for all the mesh config parameters.
*/
unsigned int flags;
+ int auto_plinks;
int peer_link_timeout;
+ int max_peer_links;
+ u16 ht_opmode;
};
struct wpa_driver_mesh_join_params {
@@ -1136,7 +1142,6 @@
struct hostapd_freq_params freq;
int beacon_int;
int dtim_period;
- int max_peer_links;
struct wpa_driver_mesh_bss_params conf;
#define WPA_DRIVER_MESH_FLAG_USER_MPM 0x00000001
#define WPA_DRIVER_MESH_FLAG_DRIVER_MPM 0x00000002
@@ -3603,6 +3608,23 @@
* Returns: 0 on success or -1 on failure
*/
int (*p2p_lo_stop)(void *priv);
+
+ /**
+ * set_default_scan_ies - Set default scan IEs
+ * @priv: Private driver interface data
+ * @ies: Scan default IEs buffer
+ * @ies_len: Length of IEs in bytes
+ * Returns: 0 on success or -1 on failure
+ *
+ * The driver can use these by default when there are no scan IEs coming
+ * in the subsequent scan requests. Also in case of one or more of IEs
+ * given in set_default_scan_ies() are missing in the subsequent scan
+ * request, the driver should merge the missing scan IEs in the scan
+ * request from the IEs set by set_default_scan_ies() in the Probe
+ * Request frames sent.
+ */
+ int (*set_default_scan_ies)(void *priv, const u8 *ies, size_t ies_len);
+
};
diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c
index ba3cad0..a88345f 100644
--- a/src/drivers/driver_atheros.c
+++ b/src/drivers/driver_atheros.c
@@ -868,6 +868,16 @@
return;
}
+ if (stype == WLAN_FC_STYPE_ACTION &&
+ (os_memcmp(drv->own_addr, mgmt->bssid, ETH_ALEN) == 0 ||
+ is_broadcast_ether_addr(mgmt->bssid))) {
+ os_memset(&event, 0, sizeof(event));
+ event.rx_mgmt.frame = buf;
+ event.rx_mgmt.frame_len = len;
+ wpa_supplicant_event(drv->hapd, EVENT_RX_MGMT, &event);
+ return;
+ }
+
if (os_memcmp(drv->own_addr, mgmt->bssid, ETH_ALEN) != 0) {
wpa_printf(MSG_DEBUG, "%s: BSSID does not match - ignore",
__func__);
@@ -889,12 +899,6 @@
iebuf = mgmt->u.reassoc_req.variable;
drv_event_assoc(drv->hapd, mgmt->sa, iebuf, ielen, 1);
break;
- case WLAN_FC_STYPE_ACTION:
- os_memset(&event, 0, sizeof(event));
- event.rx_mgmt.frame = buf;
- event.rx_mgmt.frame_len = len;
- wpa_supplicant_event(drv->hapd, EVENT_RX_MGMT, &event);
- break;
case WLAN_FC_STYPE_AUTH:
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth))
break;
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index ae40f42..8d43c69 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -200,6 +200,10 @@
static int i802_set_iface_flags(struct i802_bss *bss, int up);
static int nl80211_set_param(void *priv, const char *param);
+#ifdef CONFIG_MESH
+static int nl80211_put_mesh_config(struct nl_msg *msg,
+ struct wpa_driver_mesh_bss_params *params);
+#endif /* CONFIG_MESH */
/* Converts nl80211_chan_width to a common format */
@@ -2332,7 +2336,8 @@
if (drv->hostapd || bss->static_ap)
nlmode = NL80211_IFTYPE_AP;
- else if (bss->if_dynamic)
+ else if (bss->if_dynamic ||
+ nl80211_get_ifmode(bss) == NL80211_IFTYPE_MESH_POINT)
nlmode = nl80211_get_ifmode(bss);
else
nlmode = NL80211_IFTYPE_STATION;
@@ -3479,6 +3484,37 @@
}
+#ifdef CONFIG_MESH
+static int nl80211_set_mesh_config(void *priv,
+ struct wpa_driver_mesh_bss_params *params)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ int ret;
+
+ msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_MESH_CONFIG);
+ if (!msg)
+ return -1;
+
+ ret = nl80211_put_mesh_config(msg, params);
+ if (ret < 0) {
+ nlmsg_free(msg);
+ return ret;
+ }
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ if (ret) {
+ wpa_printf(MSG_ERROR,
+ "nl80211: Mesh config set failed: %d (%s)",
+ ret, strerror(-ret));
+ return ret;
+ }
+ return 0;
+}
+#endif /* CONFIG_MESH */
+
+
static int wpa_driver_nl80211_set_ap(void *priv,
struct wpa_driver_ap_params *params)
{
@@ -3492,6 +3528,9 @@
int smps_mode;
u32 suites[10], suite;
u32 ver;
+#ifdef CONFIG_MESH
+ struct wpa_driver_mesh_bss_params mesh_params;
+#endif /* CONFIG_MESH */
beacon_set = params->reenable ? 0 : bss->beacon_set;
@@ -3586,8 +3625,10 @@
goto fail;
if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
- params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40) &&
- nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT))
+ (!params->pairwise_ciphers ||
+ params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40)) &&
+ (nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, ETH_P_PAE) ||
+ nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
goto fail;
wpa_printf(MSG_DEBUG, "nl80211: pairwise_ciphers=0x%x",
@@ -3715,6 +3756,18 @@
bss->bandwidth = params->freq->bandwidth;
}
}
+
+#ifdef CONFIG_MESH
+ if (is_mesh_interface(drv->nlmode) && params->ht_opmode != -1) {
+ os_memset(&mesh_params, 0, sizeof(mesh_params));
+ mesh_params.flags |= WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE;
+ mesh_params.ht_opmode = params->ht_opmode;
+ ret = nl80211_set_mesh_config(priv, &mesh_params);
+ if (ret < 0)
+ return ret;
+ }
+#endif /* CONFIG_MESH */
+
return ret;
fail:
nlmsg_free(msg);
@@ -4381,8 +4434,7 @@
"nl80211: Failed to subscribe for mgmt frames from SME driver - trying to run without it");
if (!drv->device_ap_sme && drv->use_monitor &&
- nl80211_create_monitor_interface(drv) &&
- !drv->device_ap_sme)
+ nl80211_create_monitor_interface(drv))
return -1;
if (drv->device_ap_sme &&
@@ -4903,6 +4955,14 @@
if (nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT))
return -1;
+ if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
+ (params->pairwise_suite == WPA_CIPHER_NONE ||
+ params->pairwise_suite == WPA_CIPHER_WEP104 ||
+ params->pairwise_suite == WPA_CIPHER_WEP40) &&
+ (nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, ETH_P_PAE) ||
+ nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
+ return -1;
+
if (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED &&
nla_put_u32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED))
return -1;
@@ -8403,6 +8463,46 @@
}
+static int nl80211_put_mesh_config(struct nl_msg *msg,
+ struct wpa_driver_mesh_bss_params *params)
+{
+ struct nlattr *container;
+
+ container = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG);
+ if (!container)
+ return -1;
+
+ if (((params->flags & WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS) &&
+ nla_put_u32(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
+ params->auto_plinks)) ||
+ ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS) &&
+ nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
+ params->max_peer_links)))
+ return -1;
+
+ /*
+ * Set NL80211_MESHCONF_PLINK_TIMEOUT even if user mpm is used because
+ * the timer could disconnect stations even in that case.
+ */
+ if ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_PEER_LINK_TIMEOUT) &&
+ nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT,
+ params->peer_link_timeout)) {
+ wpa_printf(MSG_ERROR, "nl80211: Failed to set PLINK_TIMEOUT");
+ return -1;
+ }
+
+ if ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE) &&
+ nla_put_u16(msg, NL80211_MESHCONF_HT_OPMODE, params->ht_opmode)) {
+ wpa_printf(MSG_ERROR, "nl80211: Failed to set HT_OP_MODE");
+ return -1;
+ }
+
+ nla_nest_end(msg, container);
+
+ return 0;
+}
+
+
static int nl80211_join_mesh(struct i802_bss *bss,
struct wpa_driver_mesh_join_params *params)
{
@@ -8447,29 +8547,12 @@
goto fail;
nla_nest_end(msg, container);
- container = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG);
- if (!container)
+ params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS;
+ params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_PEER_LINK_TIMEOUT;
+ params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS;
+ if (nl80211_put_mesh_config(msg, ¶ms->conf) < 0)
goto fail;
- if (!(params->conf.flags & WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS) &&
- nla_put_u32(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS, 0))
- goto fail;
- if (nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
- params->max_peer_links))
- goto fail;
-
- /*
- * Set NL80211_MESHCONF_PLINK_TIMEOUT even if user mpm is used because
- * the timer could disconnect stations even in that case.
- */
- if (nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT,
- params->conf.peer_link_timeout)) {
- wpa_printf(MSG_ERROR, "nl80211: Failed to set PLINK_TIMEOUT");
- goto fail;
- }
-
- nla_nest_end(msg, container);
-
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
msg = NULL;
if (ret) {
@@ -9469,6 +9552,7 @@
.set_prob_oper_freq = nl80211_set_prob_oper_freq,
.p2p_lo_start = nl80211_p2p_lo_start,
.p2p_lo_stop = nl80211_p2p_lo_stop,
+ .set_default_scan_ies = nl80211_set_default_scan_ies,
#endif /* CONFIG_DRIVER_NL80211_QCA */
.configure_data_frame_filters = nl80211_configure_data_frame_filters,
.get_ext_capab = nl80211_get_ext_capab,
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index 283dfd9..d0ec48c 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -159,6 +159,7 @@
unsigned int set_prob_oper_freq:1;
unsigned int scan_vendor_cmd_avail:1;
unsigned int connect_reassoc:1;
+ unsigned int set_wifi_conf_vendor_cmd_avail:1;
u64 vendor_scan_cookie;
u64 remain_on_chan_cookie;
@@ -301,5 +302,6 @@
int wpa_driver_nl80211_abort_scan(void *priv);
int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
struct wpa_driver_scan_params *params);
+int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len);
#endif /* DRIVER_NL80211_H */
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index 1134886..df10c21 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -709,6 +709,9 @@
case QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN:
drv->scan_vendor_cmd_avail = 1;
break;
+ case QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION:
+ drv->set_wifi_conf_vendor_cmd_avail = 1;
+ break;
#endif /* CONFIG_DRIVER_NL80211_QCA */
}
}
diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c
index c089891..c115b6b 100644
--- a/src/drivers/driver_nl80211_scan.c
+++ b/src/drivers/driver_nl80211_scan.c
@@ -1070,4 +1070,54 @@
return ret;
}
+
+/**
+ * nl80211_set_default_scan_ies - Set the scan default IEs to the driver
+ * @priv: Pointer to private driver data from wpa_driver_nl80211_init()
+ * @ies: Pointer to IEs buffer
+ * @ies_len: Length of IEs in bytes
+ * Returns: 0 on success, -1 on failure
+ */
+int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg = NULL;
+ struct nlattr *attr;
+ int ret = -1;
+
+ if (!drv->set_wifi_conf_vendor_cmd_avail)
+ return -1;
+
+ if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
+ QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION))
+ goto fail;
+
+ attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
+ if (attr == NULL)
+ goto fail;
+
+ wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan default IEs", ies, ies_len);
+ if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES,
+ ies_len, ies))
+ goto fail;
+
+ nla_nest_end(msg, attr);
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ msg = NULL;
+ if (ret) {
+ wpa_printf(MSG_ERROR,
+ "nl80211: Set scan default IEs failed: ret=%d (%s)",
+ ret, strerror(-ret));
+ goto fail;
+ }
+
+fail:
+ nlmsg_free(msg);
+ return ret;
+}
+
#endif /* CONFIG_DRIVER_NL80211_QCA */
diff --git a/src/drivers/driver_roboswitch.c b/src/drivers/driver_roboswitch.c
index d3e0595..e8a5135 100644
--- a/src/drivers/driver_roboswitch.c
+++ b/src/drivers/driver_roboswitch.c
@@ -1,6 +1,6 @@
/*
* WPA Supplicant - roboswitch driver interface
- * Copyright (c) 2008-2009 Jouke Witteveen
+ * Copyright (c) 2008-2012 Jouke Witteveen
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -401,7 +401,9 @@
os_free(drv);
return NULL;
}
- if (if_mii(&drv->ifr)->phy_id != ROBO_PHY_ADDR) {
+ /* BCM63xx devices provide 0 here */
+ if (if_mii(&drv->ifr)->phy_id != ROBO_PHY_ADDR &&
+ if_mii(&drv->ifr)->phy_id != 0) {
wpa_printf(MSG_INFO, "%s: Invalid phy address (not a "
"RoboSwitch?)", __func__);
os_free(drv);
diff --git a/src/pae/ieee802_1x_kay.c b/src/pae/ieee802_1x_kay.c
index 6980b09..dfc5870 100644
--- a/src/pae/ieee802_1x_kay.c
+++ b/src/pae/ieee802_1x_kay.c
@@ -98,7 +98,7 @@
}
-static int get_mka_param_body_type(const void *body)
+static u8 get_mka_param_body_type(const void *body)
{
const struct ieee802_1x_mka_hdr *hdr = body;
return hdr->type;
@@ -532,14 +532,16 @@
peer->sak_used = FALSE;
os_memcpy(&peer->sci, &participant->current_peer_sci,
sizeof(peer->sci));
- dl_list_add(&participant->live_peers, &peer->list);
secy_get_available_receive_sc(participant->kay, &sc_ch);
rxsc = ieee802_1x_kay_init_receive_sc(&peer->sci, sc_ch);
- if (!rxsc)
+ if (!rxsc) {
+ os_free(peer);
return NULL;
+ }
+ dl_list_add(&participant->live_peers, &peer->list);
dl_list_add(&participant->rxsc_list, &rxsc->list);
secy_create_receive_sc(participant->kay, rxsc);
@@ -602,6 +604,11 @@
break;
}
+ rxsc = ieee802_1x_kay_init_receive_sc(&participant->current_peer_sci,
+ sc_ch);
+ if (!rxsc)
+ return NULL;
+
os_memcpy(&peer->sci, &participant->current_peer_sci,
sizeof(peer->sci));
peer->mn = mn;
@@ -618,10 +625,6 @@
secy_get_available_receive_sc(participant->kay, &sc_ch);
- rxsc = ieee802_1x_kay_init_receive_sc(&peer->sci, sc_ch);
- if (!rxsc)
- return NULL;
-
dl_list_add(&participant->rxsc_list, &rxsc->list);
secy_create_receive_sc(participant->kay, rxsc);
@@ -916,7 +919,7 @@
struct ieee802_1x_mka_hdr *hdr;
size_t body_len;
size_t left_len;
- int body_type;
+ u8 body_type;
u32 peer_mn;
be32 _peer_mn;
const u8 *peer_mi;
@@ -997,6 +1000,12 @@
hdr = (const struct ieee802_1x_mka_hdr *) peer_msg;
body_len = get_mka_param_body_len(hdr);
+ if (body_len % 16 != 0) {
+ wpa_printf(MSG_ERROR,
+ "KaY: MKA Peer Packet Body Length (%zu bytes) should be a multiple of 16 octets",
+ body_len);
+ return -1;
+ }
for (i = 0; i < body_len; i += MI_LEN + sizeof(peer_mn)) {
peer_mi = MKA_HDR_LEN + peer_msg + i;
@@ -1051,6 +1060,12 @@
hdr = (struct ieee802_1x_mka_hdr *) peer_msg;
body_len = get_mka_param_body_len(hdr);
+ if (body_len % 16 != 0) {
+ wpa_printf(MSG_ERROR,
+ "KaY: MKA Peer Packet Body Length (%zu bytes) should be a multiple of 16 octets",
+ body_len);
+ return -1;
+ }
for (i = 0; i < body_len; i += MI_LEN + sizeof(peer_mn)) {
peer_mi = MKA_HDR_LEN + peer_msg + i;
@@ -1154,7 +1169,7 @@
u32 pn = 1;
length = ieee802_1x_mka_get_sak_use_length(participant);
- body = wpabuf_put(buf, sizeof(struct ieee802_1x_mka_sak_use_body));
+ body = wpabuf_put(buf, length);
body->type = MKA_SAK_USE;
set_mka_param_body_len(body, length - MKA_HDR_LEN);
@@ -1759,7 +1774,7 @@
struct ieee802_1x_mka_icv_body *body;
size_t body_len;
size_t left_len;
- int body_type;
+ u8 body_type;
const u8 *pos;
pos = mka_msg;
@@ -2097,7 +2112,6 @@
struct ieee802_1x_kay_peer *key_server = NULL;
struct ieee802_1x_kay *kay = participant->kay;
Boolean i_is_key_server;
- int i;
if (participant->is_obliged_key_server) {
participant->new_sak = TRUE;
@@ -2122,11 +2136,9 @@
key_server = peer;
} else if (peer->key_server_priority ==
key_server->key_server_priority) {
- for (i = 0; i < 6; i++) {
- if (peer->sci.addr[i] <
- key_server->sci.addr[i])
- key_server = peer;
- }
+ if (os_memcmp(peer->sci.addr, key_server->sci.addr,
+ ETH_ALEN) < 0)
+ key_server = peer;
}
}
@@ -2138,20 +2150,12 @@
i_is_key_server = TRUE;
} else if (kay->actor_priority
== key_server->key_server_priority) {
- for (i = 0; i < 6; i++) {
- if (kay->actor_sci.addr[i]
- < key_server->sci.addr[i]) {
- i_is_key_server = TRUE;
- }
- }
+ if (os_memcmp(kay->actor_sci.addr, key_server->sci.addr,
+ ETH_ALEN) < 0)
+ i_is_key_server = TRUE;
}
- }
-
- if (!key_server && !i_is_key_server) {
- participant->principal = FALSE;
- participant->is_key_server = FALSE;
- participant->is_elected = FALSE;
- return 0;
+ } else if (participant->can_be_key_server) {
+ i_is_key_server = TRUE;
}
if (i_is_key_server) {
@@ -2172,9 +2176,7 @@
os_memcpy(&kay->key_server_sci, &kay->actor_sci,
sizeof(kay->key_server_sci));
kay->key_server_priority = kay->actor_priority;
- }
-
- if (key_server) {
+ } else if (key_server) {
ieee802_1x_cp_set_electedself(kay->cp, FALSE);
if (os_memcmp(&kay->key_server_sci, &key_server->sci,
sizeof(kay->key_server_sci))) {
@@ -2189,6 +2191,10 @@
os_memcpy(&kay->key_server_sci, &key_server->sci,
sizeof(kay->key_server_sci));
kay->key_server_priority = key_server->key_server_priority;
+ } else {
+ participant->principal = FALSE;
+ participant->is_key_server = FALSE;
+ participant->is_elected = FALSE;
}
return 0;
@@ -2983,7 +2989,7 @@
struct ieee802_1x_mka_hdr *hdr;
size_t body_len;
size_t left_len;
- int body_type;
+ u8 body_type;
int i;
const u8 *pos;
Boolean my_included;
@@ -3024,9 +3030,12 @@
}
if (ieee802_1x_kay_is_in_potential_peer(
participant, participant->current_peer_id.mi)) {
- ieee802_1x_kay_move_live_peer(
- participant, participant->current_peer_id.mi,
- be_to_host32(participant->current_peer_id.mn));
+ if (!ieee802_1x_kay_move_live_peer(
+ participant,
+ participant->current_peer_id.mi,
+ be_to_host32(participant->
+ current_peer_id.mn)))
+ return -1;
ieee802_1x_kay_elect_key_server(participant);
ieee802_1x_kay_decide_macsec_use(participant);
}
@@ -3060,7 +3069,8 @@
goto next_para_set;
handled[body_type] = TRUE;
- if (mak_body_handler[body_type].body_rx) {
+ if (body_type < ARRAY_SIZE(mak_body_handler) &&
+ mak_body_handler[body_type].body_rx) {
mak_body_handler[body_type].body_rx
(participant, pos, left_len);
} else {
@@ -3320,7 +3330,7 @@
default:
participant->is_obliged_key_server = FALSE;
participant->can_be_key_server = TRUE;
- participant->is_key_server = FALSE;
+ participant->is_key_server = TRUE;
participant->is_elected = FALSE;
break;
}
@@ -3428,6 +3438,7 @@
return;
}
+ eloop_cancel_timeout(ieee802_1x_participant_timer, participant, NULL);
dl_list_del(&participant->list);
/* remove live peer */
diff --git a/src/radius/radius.c b/src/radius/radius.c
index defcd92..407e4f8 100644
--- a/src/radius/radius.c
+++ b/src/radius/radius.c
@@ -538,7 +538,8 @@
int radius_msg_verify_das_req(struct radius_msg *msg, const u8 *secret,
- size_t secret_len)
+ size_t secret_len,
+ int require_message_authenticator)
{
const u8 *addr[4];
size_t len[4];
@@ -577,7 +578,11 @@
}
if (attr == NULL) {
- /* Message-Authenticator is MAY; not required */
+ if (require_message_authenticator) {
+ wpa_printf(MSG_WARNING,
+ "Missing Message-Authenticator attribute in RADIUS message");
+ return 1;
+ }
return 0;
}
diff --git a/src/radius/radius.h b/src/radius/radius.h
index cba2b91..cd510d2 100644
--- a/src/radius/radius.h
+++ b/src/radius/radius.h
@@ -242,7 +242,8 @@
int radius_msg_verify_acct_req(struct radius_msg *msg, const u8 *secret,
size_t secret_len);
int radius_msg_verify_das_req(struct radius_msg *msg, const u8 *secret,
- size_t secret_len);
+ size_t secret_len,
+ int require_message_authenticator);
struct radius_attr_hdr * radius_msg_add_attr(struct radius_msg *msg, u8 type,
const u8 *data, size_t data_len);
struct radius_msg * radius_msg_parse(const u8 *data, size_t len);
diff --git a/src/radius/radius_das.c b/src/radius/radius_das.c
index b7d991b..8a3d7e0 100644
--- a/src/radius/radius_das.c
+++ b/src/radius/radius_das.c
@@ -23,6 +23,7 @@
struct hostapd_ip_addr client_addr;
unsigned int time_window;
int require_event_timestamp;
+ int require_message_authenticator;
void *ctx;
enum radius_das_res (*disconnect)(void *ctx,
struct radius_das_attrs *attr);
@@ -234,9 +235,11 @@
radius_msg_dump(msg);
if (radius_msg_verify_das_req(msg, das->shared_secret,
- das->shared_secret_len)) {
- wpa_printf(MSG_DEBUG, "DAS: Invalid authenticator in packet "
- "from %s:%d - drop", abuf, from_port);
+ das->shared_secret_len,
+ das->require_message_authenticator)) {
+ wpa_printf(MSG_DEBUG,
+ "DAS: Invalid authenticator or Message-Authenticator in packet from %s:%d - drop",
+ abuf, from_port);
goto fail;
}
@@ -362,6 +365,8 @@
das->time_window = conf->time_window;
das->require_event_timestamp = conf->require_event_timestamp;
+ das->require_message_authenticator =
+ conf->require_message_authenticator;
das->ctx = conf->ctx;
das->disconnect = conf->disconnect;
diff --git a/src/radius/radius_das.h b/src/radius/radius_das.h
index ce731d4..9863fdc 100644
--- a/src/radius/radius_das.h
+++ b/src/radius/radius_das.h
@@ -44,6 +44,7 @@
const struct hostapd_ip_addr *client_addr;
unsigned int time_window;
int require_event_timestamp;
+ int require_message_authenticator;
void *ctx;
enum radius_das_res (*disconnect)(void *ctx,
struct radius_das_attrs *attr);
diff --git a/src/utils/common.c b/src/utils/common.c
index 9856463..68413b2 100644
--- a/src/utils/common.c
+++ b/src/utils/common.c
@@ -1194,3 +1194,9 @@
return ssid->ssid_len ? 0 : -1;
}
+
+
+int str_starts(const char *str, const char *start)
+{
+ return os_strncmp(str, start, os_strlen(start)) == 0;
+}
diff --git a/src/utils/common.h b/src/utils/common.h
index 197e4d1..7785677 100644
--- a/src/utils/common.h
+++ b/src/utils/common.h
@@ -550,6 +550,8 @@
char *outp, size_t out_size);
int is_ctrl_char(char c);
+int str_starts(const char *str, const char *start);
+
/*
* gcc 4.4 ends up generating strict-aliasing warnings about some very common
diff --git a/src/utils/os_unix.c b/src/utils/os_unix.c
index 0118d98..65c6fa4 100644
--- a/src/utils/os_unix.c
+++ b/src/utils/os_unix.c
@@ -435,11 +435,7 @@
int os_file_exists(const char *fname)
{
- FILE *f = fopen(fname, "rb");
- if (f == NULL)
- return 0;
- fclose(f);
- return 1;
+ return access(fname, F_OK) == 0;
}
diff --git a/src/utils/pcsc_funcs.c b/src/utils/pcsc_funcs.c
index 2f1157b..383ed3d 100644
--- a/src/utils/pcsc_funcs.c
+++ b/src/utils/pcsc_funcs.c
@@ -11,7 +11,11 @@
*/
#include "includes.h"
+#ifdef __APPLE__
+#include <PCSC/winscard.h>
+#else
#include <winscard.h>
+#endif
#include "common.h"
#include "pcsc_funcs.h"
@@ -110,7 +114,11 @@
struct scard_data {
SCARDCONTEXT ctx;
SCARDHANDLE card;
+#ifdef __APPLE__
+ uint32_t protocol;
+#else
DWORD protocol;
+#endif
sim_types sim_type;
int pin1_required;
};
@@ -504,7 +512,12 @@
struct scard_data * scard_init(const char *reader)
{
long ret;
- unsigned long len, pos;
+#ifdef __APPLE__
+ uint32_t len;
+#else
+ unsigned long len;
+#endif
+ unsigned long pos;
struct scard_data *scard;
#ifdef CONFIG_NATIVE_WINDOWS
TCHAR *readers = NULL;
@@ -605,7 +618,7 @@
readers = NULL;
wpa_printf(MSG_DEBUG, "SCARD: card=0x%x active_protocol=%lu (%s)",
- (unsigned int) scard->card, scard->protocol,
+ (unsigned int) scard->card, (unsigned long) scard->protocol,
scard->protocol == SCARD_PROTOCOL_T0 ? "T0" : "T1");
ret = SCardBeginTransaction(scard->card);
@@ -764,7 +777,11 @@
unsigned char *_recv, size_t *recv_len)
{
long ret;
+#ifdef __APPLE__
+ uint32_t rlen;
+#else
unsigned long rlen;
+#endif
wpa_hexdump_key(MSG_DEBUG, "SCARD: scard_transmit: send",
_send, send_len);
diff --git a/src/wps/wps_upnp_ssdp.c b/src/wps/wps_upnp_ssdp.c
index 968fc03..a685ce4 100644
--- a/src/wps/wps_upnp_ssdp.c
+++ b/src/wps/wps_upnp_ssdp.c
@@ -100,12 +100,6 @@
}
-static int str_starts(const char *str, const char *start)
-{
- return os_strncmp(str, start, os_strlen(start)) == 0;
-}
-
-
/***************************************************************************
* Advertisements.
* These are multicast to the world to tell them we are here.
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index 0e08152..a8d6a7f 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -49,6 +49,12 @@
L_CFLAGS += -mabi=aapcs-linux
endif
+# C++ flags for binder interface
+L_CPPFLAGS := -std=c++11 -Wall -Werror
+# TODO: Remove these allowed warnings later.
+L_CPPFLAGS += -Wno-unused-variable -Wno-unused-parameter
+L_CPPFLAGS += -Wno-unused-private-field
+
INCLUDES = $(LOCAL_PATH)
INCLUDES += $(LOCAL_PATH)/src
INCLUDES += $(LOCAL_PATH)/src/common
@@ -94,6 +100,7 @@
OBJS_c = wpa_cli.c src/common/wpa_ctrl.c
OBJS_c += src/utils/wpa_debug.c
OBJS_c += src/utils/common.c
+OBJS_c += src/common/cli.c
OBJS_d =
OBJS_priv =
@@ -1349,13 +1356,8 @@
L_CFLAGS += $(DBUS_CFLAGS)
ifdef CONFIG_CTRL_IFACE_BINDER
-BINDER=y
+WPA_SUPPLICANT_USE_BINDER=y
L_CFLAGS += -DCONFIG_BINDER -DCONFIG_CTRL_IFACE_BINDER
-OBJS += binder/binder.cpp binder/binder_manager.cpp
-OBJS += binder/supplicant.cpp binder/iface.cpp
-OBJS += binder/fi/w1/wpa_supplicant/ISupplicant.aidl
-OBJS += binder/fi/w1/wpa_supplicant/ISupplicantCallbacks.aidl
-OBJS += binder/fi/w1/wpa_supplicant/IIface.aidl
endif
ifdef CONFIG_READLINE
@@ -1595,9 +1597,9 @@
ifeq ($(DBUS), y)
LOCAL_SHARED_LIBRARIES += libdbus
endif
-ifeq ($(BINDER), y)
-LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/binder frameworks/native/aidl/binder
-LOCAL_SHARED_LIBRARIES += libutils libbinder
+ifeq ($(WPA_SUPPLICANT_USE_BINDER), y)
+LOCAL_SHARED_LIBRARIES += libbinder libutils
+LOCAL_STATIC_LIBRARIES += libwpa_binder libwpa_binder_interface
endif
include $(BUILD_EXECUTABLE)
@@ -1637,3 +1639,42 @@
LOCAL_COPY_HEADERS := src/common/wpa_ctrl.h
LOCAL_COPY_HEADERS += src/common/qca-vendor.h
include $(BUILD_SHARED_LIBRARY)
+
+ifeq ($(WPA_SUPPLICANT_USE_BINDER), y)
+### Binder interface library ###
+########################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libwpa_binder_interface
+LOCAL_AIDL_INCLUDES := \
+ $(LOCAL_PATH)/binder \
+ frameworks/native/aidl/binder
+LOCAL_EXPORT_C_INCLUDE_DIRS := \
+ $(LOCAL_PATH)/binder
+LOCAL_CPPFLAGS := $(L_CPPFLAGS)
+LOCAL_SRC_FILES := \
+ binder/binder_constants.cpp \
+ binder/fi/w1/wpa_supplicant/ISupplicant.aidl \
+ binder/fi/w1/wpa_supplicant/ISupplicantCallbacks.aidl \
+ binder/fi/w1/wpa_supplicant/IIface.aidl
+LOCAL_SHARED_LIBRARIES := libbinder
+include $(BUILD_STATIC_LIBRARY)
+
+### Binder service library ###
+########################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libwpa_binder
+LOCAL_CPPFLAGS := $(L_CPPFLAGS)
+LOCAL_CFLAGS := $(L_CFLAGS)
+LOCAL_C_INCLUDES := $(INCLUDES)
+LOCAL_SRC_FILES := \
+ binder/binder.cpp binder/binder_manager.cpp \
+ binder/supplicant.cpp binder/iface.cpp
+LOCAL_SHARED_LIBRARIES := \
+ libbinder \
+ libutils
+LOCAL_STATIC_LIBRARIES := libwpa_binder_interface
+include $(BUILD_STATIC_LIBRARY)
+
+endif # BINDER == y
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index 2e61abe..f3e86c1 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -110,6 +110,7 @@
OBJS_c = wpa_cli.o ../src/common/wpa_ctrl.o
OBJS_c += ../src/utils/wpa_debug.o
OBJS_c += ../src/utils/common.o
+OBJS_c += ../src/common/cli.o
OBJS += wmm_ac.o
ifndef CONFIG_OS
@@ -930,9 +931,13 @@
#dynamic symbol loading that is now used in pcsc_funcs.c
#LIBS += -lwinscard
else
+ifdef CONFIG_OSX
+LIBS += -framework PCSC
+else
LIBS += -lpcsclite -lpthread
endif
endif
+endif
ifdef CONFIG_SIM_SIMULATOR
CFLAGS += -DCONFIG_SIM_SIMULATOR
diff --git a/wpa_supplicant/binder/.clang-format b/wpa_supplicant/binder/.clang-format
new file mode 100644
index 0000000..dbfdabf
--- /dev/null
+++ b/wpa_supplicant/binder/.clang-format
@@ -0,0 +1,9 @@
+BasedOnStyle: LLVM
+IndentWidth: 8
+UseTab: Always
+BreakBeforeBraces: Mozilla
+AllowShortIfStatementsOnASingleLine: false
+IndentCaseLabels: false
+AccessModifierOffset: -8
+AlignAfterOpenBracket: AlwaysBreak
+SortIncludes: false
diff --git a/wpa_supplicant/binder/binder.cpp b/wpa_supplicant/binder/binder.cpp
index 28f7a2b..750e878 100644
--- a/wpa_supplicant/binder/binder.cpp
+++ b/wpa_supplicant/binder/binder.cpp
@@ -8,36 +8,35 @@
*/
#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
#include "binder_manager.h"
extern "C" {
-#include "utils/includes.h"
-#include "utils/common.h"
-#include "utils/eloop.h"
#include "binder.h"
#include "binder_i.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "utils/includes.h"
}
void wpas_binder_sock_handler(int sock, void *eloop_ctx, void *sock_ctx)
{
- struct wpa_global *global = (wpa_global *) eloop_ctx;
- struct wpas_binder_priv *priv = (wpas_binder_priv *) sock_ctx;
+ struct wpa_global *global = (wpa_global *)eloop_ctx;
+ struct wpas_binder_priv *priv = (wpas_binder_priv *)sock_ctx;
- wpa_printf(MSG_DEBUG, "Processing binder events on FD %d",
- priv->binder_fd);
+ wpa_printf(
+ MSG_DEBUG, "Processing binder events on FD %d", priv->binder_fd);
android::IPCThreadState::self()->handlePolledCommands();
}
-
-struct wpas_binder_priv * wpas_binder_init(struct wpa_global *global)
+struct wpas_binder_priv *wpas_binder_init(struct wpa_global *global)
{
struct wpas_binder_priv *priv;
wpa_supplicant_binder::BinderManager *binder_manager;
- priv = (wpas_binder_priv *) os_zalloc(sizeof(*priv));
+ priv = (wpas_binder_priv *)os_zalloc(sizeof(*priv));
if (!priv)
return NULL;
priv->global = global;
@@ -49,8 +48,8 @@
if (priv->binder_fd < 0)
goto err;
/* Look for read events from the binder socket in the eloop. */
- if (eloop_register_read_sock(priv->binder_fd, wpas_binder_sock_handler,
- global, priv) < 0)
+ if (eloop_register_read_sock(
+ priv->binder_fd, wpas_binder_sock_handler, global, priv) < 0)
goto err;
binder_manager = wpa_supplicant_binder::BinderManager::getInstance();
@@ -59,7 +58,7 @@
binder_manager->registerBinderService(global);
/* We may not need to store this binder manager reference in the
* global data strucure because we've made it a singleton class. */
- priv->binder_manager = (void *) binder_manager;
+ priv->binder_manager = (void *)binder_manager;
return priv;
@@ -68,7 +67,6 @@
return NULL;
}
-
void wpas_binder_deinit(struct wpas_binder_priv *priv)
{
if (!priv)
@@ -79,28 +77,26 @@
android::IPCThreadState::shutdown();
}
-
int wpas_binder_register_interface(struct wpa_supplicant *wpa_s)
{
if (!wpa_s->global->binder)
return 1;
wpa_supplicant_binder::BinderManager *binder_manager =
- wpa_supplicant_binder::BinderManager::getInstance();
+ wpa_supplicant_binder::BinderManager::getInstance();
if (!binder_manager)
return 1;
return binder_manager->registerInterface(wpa_s);
}
-
int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s)
{
if (!wpa_s->global->binder)
return 1;
wpa_supplicant_binder::BinderManager *binder_manager =
- wpa_supplicant_binder::BinderManager::getInstance();
+ wpa_supplicant_binder::BinderManager::getInstance();
if (!binder_manager)
return 1;
diff --git a/wpa_supplicant/binder/binder.h b/wpa_supplicant/binder/binder.h
index a165074..019e327 100644
--- a/wpa_supplicant/binder/binder.h
+++ b/wpa_supplicant/binder/binder.h
@@ -7,8 +7,8 @@
* See README for more details.
*/
-#ifndef BINDER_H
-#define BINDER_H
+#ifndef WPA_SUPPLICANT_BINDER_BINDER_H
+#define WPA_SUPPLICANT_BINDER_BINDER_H
#ifdef _cplusplus
extern "C" {
@@ -22,13 +22,13 @@
struct wpas_binder_priv;
struct wpa_global;
-struct wpas_binder_priv * wpas_binder_init(struct wpa_global *global);
+struct wpas_binder_priv *wpas_binder_init(struct wpa_global *global);
void wpas_binder_deinit(struct wpas_binder_priv *priv);
#ifdef CONFIG_CTRL_IFACE_BINDER
int wpas_binder_register_interface(struct wpa_supplicant *wpa_s);
int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s);
-#else /* CONFIG_CTRL_IFACE_BINDER */
+#else /* CONFIG_CTRL_IFACE_BINDER */
static inline int wpas_binder_register_interface(struct wpa_supplicant *wpa_s)
{
return 0;
@@ -43,4 +43,4 @@
}
#endif /* _cplusplus */
-#endif /* BINDER_H */
+#endif /* WPA_SUPPLICANT_BINDER_BINDER_H */
diff --git a/wpa_supplicant/binder/binder_constants.cpp b/wpa_supplicant/binder/binder_constants.cpp
new file mode 100644
index 0000000..0d452b1
--- /dev/null
+++ b/wpa_supplicant/binder/binder_constants.cpp
@@ -0,0 +1,18 @@
+/*
+ * binder interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "binder_constants.h"
+
+namespace wpa_supplicant_binder {
+namespace binder_constants {
+
+const char kServiceName[] = "wpa_supplicant";
+
+} /* namespace binder_constants */
+} /* namespace wpa_supplicant_binder */
diff --git a/wpa_supplicant/binder/binder_constants.h b/wpa_supplicant/binder/binder_constants.h
new file mode 100644
index 0000000..a4d9b55
--- /dev/null
+++ b/wpa_supplicant/binder/binder_constants.h
@@ -0,0 +1,21 @@
+/*
+ * binder interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_BINDER_BINDER_CONSTANTS_H
+#define WPA_SUPPLICANT_BINDER_BINDER_CONSTANTS_H
+
+namespace wpa_supplicant_binder {
+namespace binder_constants {
+
+extern const char kServiceName[];
+
+} /* namespace binder_constants */
+} /* namespace wpa_supplicant_binder */
+
+#endif /* WPA_SUPPLICANT_BINDER_BINDER_CONSTANTS_H */
diff --git a/wpa_supplicant/binder/binder_i.h b/wpa_supplicant/binder/binder_i.h
index e8087b6..5140d6d 100644
--- a/wpa_supplicant/binder/binder_i.h
+++ b/wpa_supplicant/binder/binder_i.h
@@ -14,7 +14,8 @@
extern "C" {
#endif // _cplusplus
-struct wpas_binder_priv {
+struct wpas_binder_priv
+{
int binder_fd;
struct wpa_global *global;
void *binder_manager;
diff --git a/wpa_supplicant/binder/binder_manager.cpp b/wpa_supplicant/binder/binder_manager.cpp
index 728f4b7..27e8ded 100644
--- a/wpa_supplicant/binder/binder_manager.cpp
+++ b/wpa_supplicant/binder/binder_manager.cpp
@@ -9,27 +9,25 @@
#include <binder/IServiceManager.h>
+#include "binder_constants.h"
#include "binder_manager.h"
extern "C" {
-#include "utils/includes.h"
#include "utils/common.h"
+#include "utils/includes.h"
}
namespace wpa_supplicant_binder {
-const char BinderManager::kBinderServiceName[] = "fi.w1.wpa_supplicant";
BinderManager *BinderManager::instance_ = NULL;
-
-BinderManager * BinderManager::getInstance()
+BinderManager *BinderManager::getInstance()
{
if (!instance_)
instance_ = new BinderManager();
return instance_;
}
-
void BinderManager::destroyInstance()
{
if (instance_)
@@ -37,20 +35,17 @@
instance_ = NULL;
}
-
int BinderManager::registerBinderService(struct wpa_global *global)
{
/* Create the main binder service object and register with
* system service manager. */
supplicant_object_ = new Supplicant(global);
- android::String16 service_name(kBinderServiceName);
+ android::String16 service_name(binder_constants::kServiceName);
android::defaultServiceManager()->addService(
- service_name,
- android::IInterface::asBinder(supplicant_object_));
+ service_name, android::IInterface::asBinder(supplicant_object_));
return 0;
}
-
int BinderManager::registerInterface(struct wpa_supplicant *wpa_s)
{
if (!wpa_s)
@@ -73,7 +68,6 @@
return 0;
}
-
int BinderManager::unregisterInterface(struct wpa_supplicant *wpa_s)
{
if (!wpa_s || !wpa_s->binder_object_key)
@@ -89,10 +83,9 @@
return 0;
}
-
int BinderManager::getIfaceBinderObjectByKey(
- const void *iface_object_key,
- android::sp<fi::w1::wpa_supplicant::IIface> *iface_object)
+ const void *iface_object_key,
+ android::sp<fi::w1::wpa_supplicant::IIface> *iface_object)
{
if (!iface_object_key || !iface_object)
return 1;
diff --git a/wpa_supplicant/binder/binder_manager.h b/wpa_supplicant/binder/binder_manager.h
index 687e740..d8b7dd0 100644
--- a/wpa_supplicant/binder/binder_manager.h
+++ b/wpa_supplicant/binder/binder_manager.h
@@ -7,14 +7,14 @@
* See README for more details.
*/
-#ifndef BINDER_MANAGER_H
-#define BINDER_MANAGER_H
+#ifndef WPA_SUPPLICANT_BINDER_BINDER_MANAGER_H
+#define WPA_SUPPLICANT_BINDER_BINDER_MANAGER_H
#include <map>
#include <string>
-#include "supplicant.h"
#include "iface.h"
+#include "supplicant.h"
struct wpa_global;
struct wpa_supplicant;
@@ -27,18 +27,17 @@
* class which is created by the supplicant core and can be used
* to get references to the binder objects.
*/
-class BinderManager {
+class BinderManager
+{
public:
- static const char kBinderServiceName[];
-
- static BinderManager * getInstance();
+ static BinderManager *getInstance();
static void destroyInstance();
int registerBinderService(struct wpa_global *global);
int registerInterface(struct wpa_supplicant *wpa_s);
int unregisterInterface(struct wpa_supplicant *wpa_s);
int getIfaceBinderObjectByKey(
- const void *iface_object_key,
- android::sp<fi::w1::wpa_supplicant::IIface> *iface_object);
+ const void *iface_object_key,
+ android::sp<fi::w1::wpa_supplicant::IIface> *iface_object);
private:
BinderManager() = default;
@@ -56,4 +55,4 @@
} /* namespace wpa_supplicant_binder */
-#endif /* BINDER_MANAGER_H */
+#endif /* WPA_SUPPLICANT_BINDER_BINDER_MANAGER_H */
diff --git a/wpa_supplicant/binder/iface.cpp b/wpa_supplicant/binder/iface.cpp
index af2548d..c61b3b0 100644
--- a/wpa_supplicant/binder/iface.cpp
+++ b/wpa_supplicant/binder/iface.cpp
@@ -11,9 +11,6 @@
namespace wpa_supplicant_binder {
-Iface::Iface(struct wpa_supplicant *wpa_s)
- : wpa_s_(wpa_s)
-{
-}
+Iface::Iface(struct wpa_supplicant *wpa_s) : wpa_s_(wpa_s) {}
} /* namespace wpa_supplicant_binder */
diff --git a/wpa_supplicant/binder/iface.h b/wpa_supplicant/binder/iface.h
index acc8e55..c0ee12c 100644
--- a/wpa_supplicant/binder/iface.h
+++ b/wpa_supplicant/binder/iface.h
@@ -7,14 +7,14 @@
* See README for more details.
*/
-#ifndef IFACE_H
-#define IFACE_H
+#ifndef WPA_SUPPLICANT_BINDER_IFACE_H
+#define WPA_SUPPLICANT_BINDER_IFACE_H
#include "fi/w1/wpa_supplicant/BnIface.h"
extern "C" {
-#include "utils/includes.h"
#include "utils/common.h"
+#include "utils/includes.h"
#include "../wpa_supplicant_i.h"
}
@@ -39,4 +39,4 @@
} /* namespace wpa_supplicant_binder */
-#endif /* IFACE_H */
+#endif /* WPA_SUPPLICANT_BINDER_IFACE_H */
diff --git a/wpa_supplicant/binder/supplicant.cpp b/wpa_supplicant/binder/supplicant.cpp
index 6844e5a..76569b1 100644
--- a/wpa_supplicant/binder/supplicant.cpp
+++ b/wpa_supplicant/binder/supplicant.cpp
@@ -7,28 +7,24 @@
* See README for more details.
*/
-#include "binder_manager.h"
#include "supplicant.h"
+#include "binder_manager.h"
namespace wpa_supplicant_binder {
-Supplicant::Supplicant(struct wpa_global *global)
- : wpa_global_(global)
-{
-}
-
+Supplicant::Supplicant(struct wpa_global *global) : wpa_global_(global) {}
android::binder::Status Supplicant::CreateInterface(
- const android::os::PersistableBundle ¶ms,
- android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
+ const android::os::PersistableBundle ¶ms,
+ android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
{
android::String16 driver, ifname, confname, bridge_ifname;
/* Check if required Ifname argument is missing */
if (!params.getString(android::String16("Ifname"), &ifname))
return android::binder::Status::fromServiceSpecificError(
- ERROR_INVALID_ARGS,
- android::String8("Ifname missing in params."));
+ ERROR_INVALID_ARGS,
+ android::String8("Ifname missing in params."));
/* Retrieve the remaining params from the dictionary */
params.getString(android::String16("Driver"), &driver);
params.getString(android::String16("ConfigFile"), &confname);
@@ -38,11 +34,12 @@
* Try to get the wpa_supplicant record for this iface, return
* an error if we already control it.
*/
- if (wpa_supplicant_get_iface(wpa_global_,
- android::String8(ifname).string()) != NULL)
+ if (wpa_supplicant_get_iface(
+ wpa_global_, android::String8(ifname).string()) != NULL)
return android::binder::Status::fromServiceSpecificError(
- ERROR_IFACE_EXISTS,
- android::String8("wpa_supplicant already controls this interface."));
+ ERROR_IFACE_EXISTS,
+ android::String8("wpa_supplicant already controls this "
+ "interface."));
android::binder::Status status;
struct wpa_supplicant *wpa_s = NULL;
@@ -52,36 +49,38 @@
iface.driver = os_strdup(android::String8(driver).string());
iface.ifname = os_strdup(android::String8(ifname).string());
iface.confname = os_strdup(android::String8(confname).string());
- iface.bridge_ifname = os_strdup(
- android::String8(bridge_ifname).string());
+ iface.bridge_ifname =
+ os_strdup(android::String8(bridge_ifname).string());
/* Otherwise, have wpa_supplicant attach to it. */
wpa_s = wpa_supplicant_add_iface(wpa_global_, &iface, NULL);
/* The supplicant core creates a corresponding binder object via
* BinderManager when |wpa_supplicant_add_iface| is called. */
if (!wpa_s || !wpa_s->binder_object_key) {
status = android::binder::Status::fromServiceSpecificError(
- ERROR_UNKNOWN,
- android::String8("wpa_supplicant couldn't grab this interface."));
+ ERROR_UNKNOWN,
+ android::String8(
+ "wpa_supplicant couldn't grab this interface."));
} else {
BinderManager *binder_manager = BinderManager::getInstance();
if (!binder_manager ||
binder_manager->getIfaceBinderObjectByKey(
- wpa_s->binder_object_key, aidl_return))
- status = android::binder::Status::fromServiceSpecificError(
+ wpa_s->binder_object_key, aidl_return))
+ status =
+ android::binder::Status::fromServiceSpecificError(
ERROR_UNKNOWN,
- android::String8("wpa_supplicant encountered a binder error."));
+ android::String8("wpa_supplicant encountered a "
+ "binder error."));
else
status = android::binder::Status::ok();
}
- os_free((void *) iface.driver);
- os_free((void *) iface.ifname);
- os_free((void *) iface.confname);
- os_free((void *) iface.bridge_ifname);
+ os_free((void *)iface.driver);
+ os_free((void *)iface.ifname);
+ os_free((void *)iface.confname);
+ os_free((void *)iface.bridge_ifname);
return status;
}
-
android::binder::Status Supplicant::RemoveInterface(const std::string &ifname)
{
struct wpa_supplicant *wpa_s;
@@ -89,35 +88,38 @@
wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str());
if (!wpa_s || !wpa_s->binder_object_key)
return android::binder::Status::fromServiceSpecificError(
- ERROR_IFACE_UNKNOWN,
- android::String8("wpa_supplicant does not control this interface."));
+ ERROR_IFACE_UNKNOWN,
+ android::String8("wpa_supplicant does not control this "
+ "interface."));
if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0))
return android::binder::Status::fromServiceSpecificError(
- ERROR_UNKNOWN,
- android::String8("wpa_supplicant couldn't remove this interface."));
+ ERROR_UNKNOWN,
+ android::String8(
+ "wpa_supplicant couldn't remove this interface."));
return android::binder::Status::ok();
}
-
android::binder::Status Supplicant::GetInterface(
- const std::string &ifname,
- android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
+ const std::string &ifname,
+ android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
{
struct wpa_supplicant *wpa_s;
wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str());
if (!wpa_s || !wpa_s->binder_object_key)
return android::binder::Status::fromServiceSpecificError(
- ERROR_IFACE_UNKNOWN,
- android::String8("wpa_supplicant does not control this interface."));
+ ERROR_IFACE_UNKNOWN,
+ android::String8(
+ "wpa_supplicant does not control this interface."));
BinderManager *binder_manager = BinderManager::getInstance();
if (!binder_manager ||
- binder_manager->getIfaceBinderObjectByKey(wpa_s->binder_object_key,
- aidl_return))
+ binder_manager->getIfaceBinderObjectByKey(
+ wpa_s->binder_object_key, aidl_return))
return android::binder::Status::fromServiceSpecificError(
- ERROR_UNKNOWN,
- android::String8("wpa_supplicant encountered a binder error."));
+ ERROR_UNKNOWN,
+ android::String8(
+ "wpa_supplicant encountered a binder error."));
return android::binder::Status::ok();
}
diff --git a/wpa_supplicant/binder/supplicant.h b/wpa_supplicant/binder/supplicant.h
index b96f4e6..136b99b 100644
--- a/wpa_supplicant/binder/supplicant.h
+++ b/wpa_supplicant/binder/supplicant.h
@@ -7,16 +7,16 @@
* See README for more details.
*/
-#ifndef SUPPLICANT_H
-#define SUPPLICANT_H
+#ifndef WPA_SUPPLICANT_BINDER_SUPPLICANT_H
+#define WPA_SUPPLICANT_BINDER_SUPPLICANT_H
#include "fi/w1/wpa_supplicant/BnSupplicant.h"
#include "fi/w1/wpa_supplicant/IIface.h"
#include "fi/w1/wpa_supplicant/ISupplicantCallbacks.h"
extern "C" {
-#include "utils/includes.h"
#include "utils/common.h"
+#include "utils/includes.h"
#include "../wpa_supplicant_i.h"
}
@@ -34,24 +34,22 @@
virtual ~Supplicant() = default;
android::binder::Status CreateInterface(
- const android::os::PersistableBundle ¶ms,
- android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
- override;
- android::binder::Status RemoveInterface(
- const std::string &ifname) override;
+ const android::os::PersistableBundle ¶ms,
+ android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return) override;
+ android::binder::Status
+ RemoveInterface(const std::string &ifname) override;
android::binder::Status GetInterface(
- const std::string &ifname,
- android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
- override;
+ const std::string &ifname,
+ android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return) override;
private:
/* Raw pointer to the global structure maintained by the core. */
struct wpa_global *wpa_global_;
/* All the callback objects registered by the clients. */
std::vector<android::sp<fi::w1::wpa_supplicant::ISupplicantCallbacks>>
- callbacks_;
+ callbacks_;
};
} /* namespace wpa_supplicant_binder */
-#endif /* SUPPLICANT_H */
+#endif /* WPA_SUPPLICANT_BINDER_SUPPLICANT_H */
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index ce631dd..3f69936 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2005,6 +2005,7 @@
{ INT(dot11MeshHoldingTimeout) },
#endif /* CONFIG_MESH */
{ INT(wpa_ptk_rekey) },
+ { INT(group_rekey) },
{ STR(bgscan) },
{ INT_RANGE(ignore_broadcast_ssid, 0, 2) },
#ifdef CONFIG_P2P
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index e72f844..994d5ea 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -785,6 +785,7 @@
INT_DEF(dot11MeshHoldingTimeout, DEFAULT_MESH_HOLDING_TIMEOUT);
#endif /* CONFIG_MESH */
INT(wpa_ptk_rekey);
+ INT(group_rekey);
INT(ignore_broadcast_ssid);
#ifdef CONFIG_HT_OVERRIDES
INT_DEF(disable_ht, DEFAULT_DISABLE_HT);
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index 1ecdfc0..010b594 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -487,6 +487,14 @@
int wpa_ptk_rekey;
/**
+ * group_rekey - Group rekeying time in seconds
+ *
+ * This value, if non-zero, is used as the dot11RSNAConfigGroupRekeyTime
+ * parameter when operating in Authenticator role in IBSS.
+ */
+ int group_rekey;
+
+ /**
* scan_freq - Array of frequencies to scan or %NULL for all
*
* This is an optional zero-terminated array of frequencies in
diff --git a/wpa_supplicant/config_winreg.c b/wpa_supplicant/config_winreg.c
index 199f04f..82ba3b0 100644
--- a/wpa_supplicant/config_winreg.c
+++ b/wpa_supplicant/config_winreg.c
@@ -933,6 +933,7 @@
#ifdef CONFIG_HS20
INT(update_identifier);
#endif /* CONFIG_HS20 */
+ INT(group_rekey);
#undef STR
#undef INT
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 4aa0f24..9543fd1 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -2919,15 +2919,10 @@
wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
- ssid = wpa_config_add_network(wpa_s->conf);
+ ssid = wpa_supplicant_add_network(wpa_s);
if (ssid == NULL)
return -1;
- wpas_notify_network_added(wpa_s, ssid);
-
- ssid->disabled = 1;
- wpa_config_set_network_defaults(ssid);
-
ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
if (os_snprintf_error(buflen, ret))
return -1;
@@ -2940,7 +2935,7 @@
{
int id;
struct wpa_ssid *ssid;
- int was_disabled;
+ int result;
/* cmd: "<network id>" or "all" */
if (os_strcmp(cmd, "all") == 0) {
@@ -2976,54 +2971,17 @@
id = atoi(cmd);
wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
- ssid = wpa_config_get_network(wpa_s->conf, id);
- if (ssid)
- wpas_notify_network_removed(wpa_s, ssid);
- if (ssid == NULL) {
+ result = wpa_supplicant_remove_network(wpa_s, id);
+ if (result == -1) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
"id=%d", id);
return -1;
}
-
- if (wpa_s->last_ssid == ssid)
- wpa_s->last_ssid = NULL;
-
- if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
-#ifdef CONFIG_SME
- wpa_s->sme.prev_bssid_set = 0;
-#endif /* CONFIG_SME */
- /*
- * Invalidate the EAP session cache if the current or
- * previously used network is removed.
- */
- eapol_sm_invalidate_cached_session(wpa_s->eapol);
- }
-
- if (ssid == wpa_s->current_ssid) {
- wpa_sm_set_config(wpa_s->wpa, NULL);
- eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
-
- if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
- wpa_s->own_disconnect_req = 1;
- wpa_supplicant_deauthenticate(wpa_s,
- WLAN_REASON_DEAUTH_LEAVING);
- }
-
- was_disabled = ssid->disabled;
-
- if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
+ if (result == -2) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
"network id=%d", id);
return -1;
}
-
- if (!was_disabled && wpa_s->sched_scanning) {
- wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
- "network from filters");
- wpa_supplicant_cancel_sched_scan(wpa_s);
- wpa_supplicant_req_scan(wpa_s, 0, 0);
- }
-
return 0;
}
@@ -9127,16 +9085,7 @@
reply_len = wpa_supplicant_ctrl_iface_list_networks(
wpa_s, NULL, reply, reply_size);
} else if (os_strcmp(buf, "DISCONNECT") == 0) {
-#ifdef CONFIG_SME
- wpa_s->sme.prev_bssid_set = 0;
-#endif /* CONFIG_SME */
- wpa_s->reassociate = 0;
- wpa_s->disconnected = 1;
- wpa_supplicant_cancel_sched_scan(wpa_s);
- wpa_supplicant_cancel_scan(wpa_s);
- wpa_supplicant_deauthenticate(wpa_s,
- WLAN_REASON_DEAUTH_LEAVING);
- eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
+ wpas_request_disconnection(wpa_s);
} else if (os_strcmp(buf, "SCAN") == 0) {
wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
} else if (os_strncmp(buf, "SCAN ", 5) == 0) {
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index de6d216..f185f27 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -1475,10 +1475,7 @@
struct wpa_supplicant *wpa_s)
{
if (wpa_s->current_ssid != NULL) {
- wpa_s->disconnected = 1;
- wpa_supplicant_deauthenticate(wpa_s,
- WLAN_REASON_DEAUTH_LEAVING);
-
+ wpas_request_disconnection(wpa_s);
return NULL;
}
@@ -1507,7 +1504,7 @@
dbus_message_iter_init(message, &iter);
if (wpa_s->dbus_new_path)
- ssid = wpa_config_add_network(wpa_s->conf);
+ ssid = wpa_supplicant_add_network(wpa_s);
if (ssid == NULL) {
wpa_printf(MSG_ERROR, "%s[dbus]: can't add new interface.",
__func__);
@@ -1516,9 +1513,6 @@
"wpa_supplicant could not add a network on this interface.");
goto err;
}
- wpas_notify_network_added(wpa_s, ssid);
- ssid->disabled = 1;
- wpa_config_set_network_defaults(ssid);
dbus_error_init(&error);
if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
@@ -1665,8 +1659,7 @@
const char *op;
char *iface, *net_id;
int id;
- struct wpa_ssid *ssid;
- int was_disabled;
+ int result;
dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
DBUS_TYPE_INVALID);
@@ -1689,27 +1682,12 @@
goto out;
}
- ssid = wpa_config_get_network(wpa_s->conf, id);
- if (ssid == NULL) {
+ result = wpa_supplicant_remove_network(wpa_s, id);
+ if (result == -1) {
reply = wpas_dbus_error_network_unknown(message);
goto out;
}
-
- was_disabled = ssid->disabled;
-
- wpas_notify_network_removed(wpa_s, ssid);
-
- if (ssid == wpa_s->current_ssid)
- wpa_supplicant_deauthenticate(wpa_s,
- WLAN_REASON_DEAUTH_LEAVING);
- else if (!was_disabled && wpa_s->sched_scanning) {
- wpa_printf(MSG_DEBUG,
- "Stop ongoing sched_scan to remove network from filters");
- wpa_supplicant_cancel_sched_scan(wpa_s);
- wpa_supplicant_req_scan(wpa_s, 0, 0);
- }
-
- if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
+ if (result == -2) {
wpa_printf(MSG_ERROR,
"%s[dbus]: error occurred when removing network %d",
__func__, id);
diff --git a/wpa_supplicant/dbus/dbus_old_handlers.c b/wpa_supplicant/dbus/dbus_old_handlers.c
index e8f62ef..e540832 100644
--- a/wpa_supplicant/dbus/dbus_old_handlers.c
+++ b/wpa_supplicant/dbus/dbus_old_handlers.c
@@ -717,16 +717,13 @@
char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
if (wpa_s->dbus_path)
- ssid = wpa_config_add_network(wpa_s->conf);
+ ssid = wpa_supplicant_add_network(wpa_s);
if (ssid == NULL) {
reply = dbus_message_new_error(
message, WPAS_ERROR_ADD_NETWORK_ERROR,
"wpa_supplicant could not add a network on this interface.");
goto out;
}
- wpas_notify_network_added(wpa_s, ssid);
- ssid->disabled = 1;
- wpa_config_set_network_defaults(ssid);
/* Construct the object path for this network. */
os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
@@ -758,7 +755,7 @@
const char *op;
char *iface = NULL, *net_id = NULL;
int id;
- struct wpa_ssid *ssid;
+ int result;
if (!dbus_message_get_args(message, NULL,
DBUS_TYPE_OBJECT_PATH, &op,
@@ -781,19 +778,12 @@
}
id = strtoul(net_id, NULL, 10);
- ssid = wpa_config_get_network(wpa_s->conf, id);
- if (ssid == NULL) {
+ result = wpa_supplicant_remove_network(wpa_s, id);
+ if (result == -1) {
reply = wpas_dbus_new_invalid_network_error(message);
goto out;
}
-
- wpas_notify_network_removed(wpa_s, ssid);
-
- if (ssid == wpa_s->current_ssid)
- wpa_supplicant_deauthenticate(wpa_s,
- WLAN_REASON_DEAUTH_LEAVING);
-
- if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
+ if (result == -2) {
reply = dbus_message_new_error(
message, WPAS_ERROR_REMOVE_NETWORK_ERROR,
"error removing the specified on this interface.");
@@ -1069,8 +1059,7 @@
DBusMessage * wpas_dbus_iface_disconnect(DBusMessage *message,
struct wpa_supplicant *wpa_s)
{
- wpa_s->disconnected = 1;
- wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+ wpas_request_disconnection(wpa_s);
return wpas_dbus_new_success_reply(message);
}
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 396a0dc..7a16b7a 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -969,4 +969,12 @@
return wpa_s->driver->p2p_lo_stop(wpa_s->drv_priv);
}
+static inline int wpa_drv_set_default_scan_ies(struct wpa_supplicant *wpa_s,
+ const u8 *ies, size_t len)
+{
+ if (!wpa_s->driver->set_default_scan_ies)
+ return -1;
+ return wpa_s->driver->set_default_scan_ies(wpa_s->drv_priv, ies, len);
+}
+
#endif /* DRIVER_I_H */
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 50461b6..ef62d70 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -2234,7 +2234,7 @@
union wpa_event_data *data)
{
u8 bssid[ETH_ALEN];
- int ft_completed;
+ int ft_completed, already_authorized;
int new_bss = 0;
#ifdef CONFIG_AP
@@ -2310,6 +2310,8 @@
if (wpa_s->l2)
l2_packet_notify_auth_start(wpa_s->l2);
+ already_authorized = data && data->assoc_info.authorized;
+
/*
* Set portEnabled first to FALSE in order to get EAP state machine out
* of the SUCCESS state and eapSuccess cleared. Without this, EAPOL PAE
@@ -2318,11 +2320,12 @@
* AUTHENTICATED without ever giving chance to EAP state machine to
* reset the state.
*/
- if (!ft_completed) {
+ if (!ft_completed && !already_authorized) {
eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
}
- if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || ft_completed)
+ if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || ft_completed ||
+ already_authorized)
eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
/* 802.1X::portControl = Auto */
eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE);
@@ -2414,7 +2417,7 @@
wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE &&
wpa_s->ibss_rsn == NULL) {
- wpa_s->ibss_rsn = ibss_rsn_init(wpa_s);
+ wpa_s->ibss_rsn = ibss_rsn_init(wpa_s, wpa_s->current_ssid);
if (!wpa_s->ibss_rsn) {
wpa_msg(wpa_s, MSG_INFO, "Failed to init IBSS RSN");
wpa_supplicant_deauthenticate(
diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
index c00db31..53d7d57 100644
--- a/wpa_supplicant/ibss_rsn.c
+++ b/wpa_supplicant/ibss_rsn.c
@@ -221,6 +221,7 @@
peer->supp = wpa_sm_init(ctx);
if (peer->supp == NULL) {
wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed");
+ os_free(ctx);
return -1;
}
@@ -404,7 +405,7 @@
static int ibss_rsn_auth_init_group(struct ibss_rsn *ibss_rsn,
- const u8 *own_addr)
+ const u8 *own_addr, struct wpa_ssid *ssid)
{
struct wpa_auth_config conf;
struct wpa_auth_callbacks cb;
@@ -418,7 +419,7 @@
conf.rsn_pairwise = WPA_CIPHER_CCMP;
conf.wpa_group = WPA_CIPHER_CCMP;
conf.eapol_version = 2;
- conf.wpa_group_rekey = 600;
+ conf.wpa_group_rekey = ssid->group_rekey ? ssid->group_rekey : 600;
os_memset(&cb, 0, sizeof(cb));
cb.ctx = ibss_rsn;
@@ -665,7 +666,8 @@
}
-struct ibss_rsn * ibss_rsn_init(struct wpa_supplicant *wpa_s)
+struct ibss_rsn * ibss_rsn_init(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
{
struct ibss_rsn *ibss_rsn;
@@ -674,7 +676,7 @@
return NULL;
ibss_rsn->wpa_s = wpa_s;
- if (ibss_rsn_auth_init_group(ibss_rsn, wpa_s->own_addr) < 0) {
+ if (ibss_rsn_auth_init_group(ibss_rsn, wpa_s->own_addr, ssid) < 0) {
ibss_rsn_deinit(ibss_rsn);
return NULL;
}
diff --git a/wpa_supplicant/ibss_rsn.h b/wpa_supplicant/ibss_rsn.h
index 67fae2d..626c543 100644
--- a/wpa_supplicant/ibss_rsn.h
+++ b/wpa_supplicant/ibss_rsn.h
@@ -51,7 +51,8 @@
};
-struct ibss_rsn * ibss_rsn_init(struct wpa_supplicant *wpa_s);
+struct ibss_rsn * ibss_rsn_init(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid);
void ibss_rsn_deinit(struct ibss_rsn *ibss_rsn);
int ibss_rsn_start(struct ibss_rsn *ibss_rsn, const u8 *addr);
void ibss_rsn_stop(struct ibss_rsn *ibss_rsn, const u8 *peermac);
diff --git a/wpa_supplicant/mbo.c b/wpa_supplicant/mbo.c
index 5b5c3e6..91667b0 100644
--- a/wpa_supplicant/mbo.c
+++ b/wpa_supplicant/mbo.c
@@ -18,6 +18,7 @@
#include "wpa_supplicant_i.h"
#include "driver_i.h"
#include "bss.h"
+#include "scan.h"
/* type + length + oui + oui type */
#define MBO_IE_HEADER 6
@@ -810,4 +811,5 @@
cell_capa[6] = mbo_cell_capa;
wpas_mbo_send_wnm_notification(wpa_s, cell_capa, 7);
+ wpa_supplicant_set_default_scan_ies(wpa_s);
}
diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
index cdfe51c..741670b 100644
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -404,7 +404,7 @@
params.dtim_period = ssid->dtim_period;
else if (wpa_s->conf->dtim_period > 0)
params.dtim_period = wpa_s->conf->dtim_period;
- params.max_peer_links = wpa_s->conf->max_peer_links;
+ params.conf.max_peer_links = wpa_s->conf->max_peer_links;
if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
params.flags |= WPA_DRIVER_MESH_FLAG_SAE_AUTH;
@@ -414,10 +414,10 @@
if (wpa_s->conf->user_mpm) {
params.flags |= WPA_DRIVER_MESH_FLAG_USER_MPM;
- params.conf.flags &= ~WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS;
+ params.conf.auto_plinks = 0;
} else {
params.flags |= WPA_DRIVER_MESH_FLAG_DRIVER_MPM;
- params.conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS;
+ params.conf.auto_plinks = 1;
}
params.conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity;
@@ -438,6 +438,8 @@
params.ies = wpa_s->ifmsh->mconf->rsn_ie;
params.ie_len = wpa_s->ifmsh->mconf->rsn_ie_len;
params.basic_rates = wpa_s->ifmsh->basic_rates;
+ params.conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE;
+ params.conf.ht_opmode = wpa_s->ifmsh->bss[0]->iface->ht_op_mode;
}
wpa_msg(wpa_s, MSG_INFO, "joining mesh %s",
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index cb8df66..31eeb38 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -1076,7 +1076,7 @@
"go_dev_addr=" MACSTR,
MAC2STR(bssid), group_capab, MAC2STR(go_dev_addr));
- return group_capab & P2P_GROUP_CAPAB_PERSISTENT_GROUP;
+ return !!(group_capab & P2P_GROUP_CAPAB_PERSISTENT_GROUP);
}
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 119da28..371c16a 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -426,6 +426,39 @@
#endif /* CONFIG_INTERWORKING */
+void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s)
+{
+ struct wpabuf *default_ies = NULL;
+ u8 ext_capab[18];
+ int ext_capab_len;
+ enum wpa_driver_if_type type = WPA_IF_STATION;
+
+#ifdef CONFIG_P2P
+ if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT)
+ type = WPA_IF_P2P_CLIENT;
+#endif /* CONFIG_P2P */
+
+ wpa_drv_get_ext_capa(wpa_s, type);
+
+ ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
+ sizeof(ext_capab));
+ if (ext_capab_len > 0 &&
+ wpabuf_resize(&default_ies, ext_capab_len) == 0)
+ wpabuf_put_data(default_ies, ext_capab, ext_capab_len);
+
+#ifdef CONFIG_MBO
+ /* Send cellular capabilities for potential MBO STAs */
+ if (wpabuf_resize(&default_ies, 9) == 0)
+ wpas_mbo_scan_ie(wpa_s, default_ies);
+#endif /* CONFIG_MBO */
+
+ if (default_ies)
+ wpa_drv_set_default_scan_ies(wpa_s, wpabuf_head(default_ies),
+ wpabuf_len(default_ies));
+ wpabuf_free(default_ies);
+}
+
+
static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
{
struct wpabuf *extra_ie = NULL;
diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h
index 9f8d04e..b2bb386 100644
--- a/wpa_supplicant/scan.h
+++ b/wpa_supplicant/scan.h
@@ -56,5 +56,6 @@
void scan_snr(struct wpa_scan_res *res);
void scan_est_throughput(struct wpa_supplicant *wpa_s,
struct wpa_scan_res *res);
+void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s);
#endif /* SCAN_H */
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 7012dfb..ca3d8f8 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -14,6 +14,7 @@
#include <dirent.h>
#endif /* CONFIG_CTRL_IFACE_UNIX */
+#include "common/cli.h"
#include "common/wpa_ctrl.h"
#include "utils/common.h"
#include "utils/eloop.h"
@@ -30,42 +31,6 @@
"wpa_cli v" VERSION_STR "\n"
"Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi> and contributors";
-
-static const char *const wpa_cli_license =
-"This software may be distributed under the terms of the BSD license.\n"
-"See README for more details.\n";
-
-static const char *const wpa_cli_full_license =
-"This software may be distributed under the terms of the BSD license.\n"
-"\n"
-"Redistribution and use in source and binary forms, with or without\n"
-"modification, are permitted provided that the following conditions are\n"
-"met:\n"
-"\n"
-"1. Redistributions of source code must retain the above copyright\n"
-" notice, this list of conditions and the following disclaimer.\n"
-"\n"
-"2. Redistributions in binary form must reproduce the above copyright\n"
-" notice, this list of conditions and the following disclaimer in the\n"
-" documentation and/or other materials provided with the distribution.\n"
-"\n"
-"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
-" names of its contributors may be used to endorse or promote products\n"
-" derived from this software without specific prior written permission.\n"
-"\n"
-"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
-"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
-"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
-"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
-"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
-"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
-"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
-"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
-"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
-"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
-"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
-"\n";
-
#define VENDOR_ELEM_FRAME_ID \
" 0: Probe Req (P2P), 1: Probe Resp (P2P) , 2: Probe Resp (GO), " \
"3: Beacon (GO), 4: PD Req, 5: PD Resp, 6: GO Neg Req, " \
@@ -90,11 +55,6 @@
static int interactive = 0;
static char *ifname_prefix = NULL;
-struct cli_txt_entry {
- struct dl_list list;
- char *txt;
-};
-
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 */
@@ -130,168 +90,6 @@
}
-static void cli_txt_list_free(struct cli_txt_entry *e)
-{
- dl_list_del(&e->list);
- os_free(e->txt);
- os_free(e);
-}
-
-
-static void cli_txt_list_flush(struct dl_list *list)
-{
- struct cli_txt_entry *e;
- while ((e = dl_list_first(list, struct cli_txt_entry, list)))
- cli_txt_list_free(e);
-}
-
-
-static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
- const char *txt)
-{
- struct cli_txt_entry *e;
- dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
- if (os_strcmp(e->txt, txt) == 0)
- return e;
- }
- return NULL;
-}
-
-
-static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
-{
- struct cli_txt_entry *e;
- e = cli_txt_list_get(txt_list, txt);
- if (e)
- cli_txt_list_free(e);
-}
-
-
-static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
-{
- u8 addr[ETH_ALEN];
- char buf[18];
- if (hwaddr_aton(txt, addr) < 0)
- return;
- os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
- cli_txt_list_del(txt_list, buf);
-}
-
-
-#ifdef CONFIG_P2P
-static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt,
- int separator)
-{
- const char *end;
- char *buf;
- end = os_strchr(txt, separator);
- if (end == NULL)
- end = txt + os_strlen(txt);
- buf = dup_binstr(txt, end - txt);
- if (buf == NULL)
- return;
- cli_txt_list_del(txt_list, buf);
- os_free(buf);
-}
-#endif /* CONFIG_P2P */
-
-
-static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
-{
- struct cli_txt_entry *e;
- e = cli_txt_list_get(txt_list, txt);
- if (e)
- return 0;
- e = os_zalloc(sizeof(*e));
- if (e == NULL)
- return -1;
- e->txt = os_strdup(txt);
- if (e->txt == NULL) {
- os_free(e);
- return -1;
- }
- dl_list_add(txt_list, &e->list);
- return 0;
-}
-
-
-#ifdef CONFIG_P2P
-static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
-{
- u8 addr[ETH_ALEN];
- char buf[18];
- if (hwaddr_aton(txt, addr) < 0)
- return -1;
- os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
- return cli_txt_list_add(txt_list, buf);
-}
-#endif /* CONFIG_P2P */
-
-
-static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt,
- int separator)
-{
- const char *end;
- char *buf;
- int ret;
- end = os_strchr(txt, separator);
- if (end == NULL)
- end = txt + os_strlen(txt);
- buf = dup_binstr(txt, end - txt);
- if (buf == NULL)
- return -1;
- ret = cli_txt_list_add(txt_list, buf);
- os_free(buf);
- return ret;
-}
-
-
-static char ** cli_txt_list_array(struct dl_list *txt_list)
-{
- unsigned int i, count = dl_list_len(txt_list);
- char **res;
- struct cli_txt_entry *e;
-
- res = os_calloc(count + 1, sizeof(char *));
- if (res == NULL)
- return NULL;
-
- i = 0;
- dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
- res[i] = os_strdup(e->txt);
- if (res[i] == NULL)
- break;
- i++;
- }
-
- return res;
-}
-
-
-static int get_cmd_arg_num(const char *str, int pos)
-{
- int arg = 0, i;
-
- for (i = 0; i <= pos; i++) {
- if (str[i] != ' ') {
- arg++;
- while (i <= pos && str[i] != ' ')
- i++;
- }
- }
-
- if (arg > 0)
- arg--;
- return arg;
-}
-
-
-static int str_starts(const char *src, const char *match)
-{
- return os_strncmp(src, match, os_strlen(match)) == 0;
-}
-
-
static int wpa_cli_show_event(const char *event)
{
const char *start;
@@ -458,36 +256,6 @@
}
-static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
- char *argv[])
-{
- int i, res;
- char *pos, *end;
-
- pos = buf;
- end = buf + buflen;
-
- res = os_snprintf(pos, end - pos, "%s", cmd);
- if (os_snprintf_error(end - pos, res))
- goto fail;
- pos += res;
-
- for (i = 0; i < argc; i++) {
- res = os_snprintf(pos, end - pos, " %s", argv[i]);
- if (os_snprintf_error(end - pos, res))
- goto fail;
- pos += res;
- }
-
- buf[buflen - 1] = '\0';
- return 0;
-
-fail:
- printf("Too long command\n");
- return -1;
-}
-
-
static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
int argc, char *argv[])
{
@@ -587,7 +355,7 @@
static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
- printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
+ printf("%s\n\n%s\n", wpa_cli_version, cli_full_license);
return 0;
}
@@ -1824,6 +1592,48 @@
}
+static char ** wpa_cli_complete_get_capability(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ const char *fields[] = {
+ "eap", "pairwise", "group", "group_mgmt", "key_mgmt",
+ "proto", "auth_alg", "modes", "channels", "freq",
+#ifdef CONFIG_TDLS
+ "tdls",
+#endif /* CONFIG_TDLS */
+#ifdef CONFIG_ERP
+ "erp",
+#endif /* CONFIG_ERP */
+#ifdef CONFIG_FIPS
+ "fips",
+#endif /* CONFIG_FIPS */
+#ifdef CONFIG_ACS
+ "acs",
+#endif /* CONFIG_ACS */
+ };
+ int i, num_fields = ARRAY_SIZE(fields);
+ char **res = NULL;
+
+ if (arg == 1) {
+ 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;
+ }
+ }
+ if (arg == 2) {
+ res = os_calloc(1 + 1, sizeof(char *));
+ if (res == NULL)
+ return NULL;
+ res[0] = os_strdup("strict");
+ }
+ return res;
+}
+
+
static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
{
printf("Available interfaces:\n");
@@ -3100,8 +2910,8 @@
{ "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
cli_cmd_flag_none,
"<<idx> | <bssid>> = get detailed scan result info" },
- { "get_capability", wpa_cli_cmd_get_capability, NULL,
- cli_cmd_flag_none,
+ { "get_capability", wpa_cli_cmd_get_capability,
+ wpa_cli_complete_get_capability, cli_cmd_flag_none,
"<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
"= get capabilities" },
{ "reconfigure", wpa_cli_cmd_reconfigure, NULL,
@@ -3705,12 +3515,6 @@
}
-static int str_match(const char *a, const char *b)
-{
- return os_strncmp(a, b, os_strlen(b)) == 0;
-}
-
-
static int wpa_cli_exec(const char *program, const char *arg1,
const char *arg2)
{
@@ -3766,7 +3570,7 @@
pos = prev;
}
- if (str_match(pos, WPA_EVENT_CONNECTED)) {
+ if (str_starts(pos, WPA_EVENT_CONNECTED)) {
int new_id = -1;
os_unsetenv("WPA_ID");
os_unsetenv("WPA_ID_STR");
@@ -3802,48 +3606,48 @@
wpa_cli_last_id = new_id;
wpa_cli_exec(action_file, ifname, "CONNECTED");
}
- } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
+ } else if (str_starts(pos, WPA_EVENT_DISCONNECTED)) {
if (wpa_cli_connected) {
wpa_cli_connected = 0;
wpa_cli_exec(action_file, ifname, "DISCONNECTED");
}
- } else if (str_match(pos, AP_EVENT_ENABLED)) {
+ } else if (str_starts(pos, AP_EVENT_ENABLED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, AP_EVENT_DISABLED)) {
+ } else if (str_starts(pos, AP_EVENT_DISABLED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, MESH_GROUP_STARTED)) {
+ } else if (str_starts(pos, MESH_GROUP_STARTED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, MESH_GROUP_REMOVED)) {
+ } else if (str_starts(pos, MESH_GROUP_REMOVED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, MESH_PEER_CONNECTED)) {
+ } else if (str_starts(pos, MESH_PEER_CONNECTED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, MESH_PEER_DISCONNECTED)) {
+ } else if (str_starts(pos, MESH_PEER_DISCONNECTED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
+ } else if (str_starts(pos, P2P_EVENT_GROUP_STARTED)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
+ } else if (str_starts(pos, P2P_EVENT_GROUP_REMOVED)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
+ } else if (str_starts(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
+ } else if (str_starts(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
+ } else if (str_starts(pos, P2P_EVENT_GO_NEG_FAILURE)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
+ } else if (str_starts(pos, WPS_EVENT_SUCCESS)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, WPS_EVENT_FAIL)) {
+ } else if (str_starts(pos, WPS_EVENT_FAIL)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, AP_STA_CONNECTED)) {
+ } else if (str_starts(pos, AP_STA_CONNECTED)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, AP_STA_DISCONNECTED)) {
+ } else if (str_starts(pos, AP_STA_DISCONNECTED)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
+ } else if (str_starts(pos, ESS_DISASSOC_IMMINENT)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
+ } else if (str_starts(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
+ } else if (str_starts(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
+ } else if (str_starts(pos, WPA_EVENT_TERMINATING)) {
printf("wpa_supplicant is terminating - stop monitoring\n");
wpa_cli_quit = 1;
}
@@ -3953,7 +3757,7 @@
pos = msg;
}
- if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
+ if (str_starts(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
edit_clear_line();
printf("\rConnection to wpa_supplicant lost - trying to "
"reconnect\n");
@@ -4004,37 +3808,6 @@
}
}
-#define max_args 10
-
-static int tokenize_cmd(char *cmd, char *argv[])
-{
- char *pos;
- int argc = 0;
-
- pos = cmd;
- for (;;) {
- while (*pos == ' ')
- pos++;
- if (*pos == '\0')
- break;
- argv[argc] = pos;
- argc++;
- if (argc == max_args)
- break;
- if (*pos == '"') {
- char *pos2 = os_strrchr(pos, '"');
- if (pos2)
- pos = pos2 + 1;
- }
- while (*pos != '\0' && *pos != ' ')
- pos++;
- if (*pos == ' ')
- *pos++ = '\0';
- }
-
- return argc;
-}
-
static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
{
@@ -4444,7 +4217,7 @@
interactive = (argc == optind) && (action_file == NULL);
if (interactive)
- printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
+ printf("%s\n\n%s\n\n", wpa_cli_version, cli_license);
if (eloop_init())
return -1;
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 7ed7efa..5bb1f72 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1901,6 +1901,11 @@
if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
return;
+#ifdef CONFIG_HT_OVERRIDES
+ if (ssid->disable_ht40)
+ return;
+#endif /* CONFIG_HT_OVERRIDES */
+
/* Check/setup HT40+/HT40- */
for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
if (ht40plus[j] == channel) {
@@ -1925,22 +1930,16 @@
freq->channel = pri_chan->chan;
- switch (ht40) {
- case -1:
+ if (ht40 == -1) {
if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
return;
- freq->sec_channel_offset = -1;
- break;
- case 1:
+ } else {
if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
return;
- freq->sec_channel_offset = 1;
- break;
- default:
- break;
}
+ freq->sec_channel_offset = ht40;
- if (freq->sec_channel_offset && obss_scan) {
+ if (obss_scan) {
struct wpa_scan_results *scan_res;
scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
@@ -2754,6 +2753,95 @@
/**
+ * wpa_supplicant_add_network - Add a new network
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: The new network configuration or %NULL if operation failed
+ *
+ * This function performs the following operations:
+ * 1. Adds a new network.
+ * 2. Send network addition notification.
+ * 3. Marks the network disabled.
+ * 4. Set network default parameters.
+ */
+struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_ssid *ssid;
+
+ ssid = wpa_config_add_network(wpa_s->conf);
+ if (!ssid)
+ return NULL;
+ wpas_notify_network_added(wpa_s, ssid);
+ ssid->disabled = 1;
+ wpa_config_set_network_defaults(ssid);
+
+ return ssid;
+}
+
+
+/**
+ * wpa_supplicant_remove_network - Remove a configured network based on id
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * @id: Unique network id to search for
+ * Returns: 0 on success, or -1 if the network was not found, -2 if the network
+ * could not be removed
+ *
+ * This function performs the following operations:
+ * 1. Removes the network.
+ * 2. Send network removal notification.
+ * 3. Update internal state machines.
+ * 4. Stop any running sched scans.
+ */
+int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
+{
+ struct wpa_ssid *ssid;
+ int was_disabled;
+
+ ssid = wpa_config_get_network(wpa_s->conf, id);
+ if (!ssid)
+ return -1;
+ wpas_notify_network_removed(wpa_s, ssid);
+
+ if (wpa_s->last_ssid == ssid)
+ wpa_s->last_ssid = NULL;
+
+ if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
+#ifdef CONFIG_SME
+ wpa_s->sme.prev_bssid_set = 0;
+#endif /* CONFIG_SME */
+ /*
+ * Invalidate the EAP session cache if the current or
+ * previously used network is removed.
+ */
+ eapol_sm_invalidate_cached_session(wpa_s->eapol);
+ }
+
+ if (ssid == wpa_s->current_ssid) {
+ wpa_sm_set_config(wpa_s->wpa, NULL);
+ eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
+
+ if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
+ wpa_s->own_disconnect_req = 1;
+ wpa_supplicant_deauthenticate(wpa_s,
+ WLAN_REASON_DEAUTH_LEAVING);
+ }
+
+ was_disabled = ssid->disabled;
+
+ if (wpa_config_remove_network(wpa_s->conf, id) < 0)
+ return -2;
+
+ if (!was_disabled && wpa_s->sched_scanning) {
+ wpa_printf(MSG_DEBUG,
+ "Stop ongoing sched_scan to remove network from filters");
+ wpa_supplicant_cancel_sched_scan(wpa_s);
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+ }
+
+ return 0;
+}
+
+
+/**
* wpa_supplicant_enable_network - Mark a configured network as enabled
* @wpa_s: wpa_supplicant structure for a network interface
* @ssid: wpa_ssid structure for a configured network or %NULL
@@ -4875,6 +4963,8 @@
wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
#endif /* CONFIG_MBO */
+ wpa_supplicant_set_default_scan_ies(wpa_s);
+
return 0;
}
@@ -6022,6 +6112,27 @@
}
+/**
+ * wpas_request_disconnection - Request disconnection
+ * @wpa_s: Pointer to the network interface
+ *
+ * This function is used to request disconnection from the currently connected
+ * network. This will stop any ongoing scans and initiate deauthentication.
+ */
+void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
+{
+#ifdef CONFIG_SME
+ wpa_s->sme.prev_bssid_set = 0;
+#endif /* CONFIG_SME */
+ wpa_s->reassociate = 0;
+ wpa_s->disconnected = 1;
+ wpa_supplicant_cancel_sched_scan(wpa_s);
+ wpa_supplicant_cancel_scan(wpa_s);
+ wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+ eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
+}
+
+
void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
struct wpa_used_freq_data *freqs_data,
unsigned int len)
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 1d86a71..6ece942 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -896,6 +896,10 @@
# wpa_ptk_rekey: Maximum lifetime for PTK in seconds. This can be used to
# enforce rekeying of PTK to mitigate some attacks against TKIP deficiencies.
#
+# group_rekey: Group rekeying time in seconds. This value, if non-zero, is used
+# as the dot11RSNAConfigGroupRekeyTime parameter when operating in
+# Authenticator role in IBSS.
+#
# Following fields are only used with internal EAP implementation.
# eap: space-separated list of accepted EAP methods
# MD5 = EAP-MD5 (unsecure and does not generate keying material ->
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index dd6a60d..f3f96a3 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -1107,6 +1107,8 @@
void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
int reason_code);
+struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s);
+int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id);
void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
@@ -1162,6 +1164,7 @@
int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
size_t ssid_len);
void wpas_request_connection(struct wpa_supplicant *wpa_s);
+void wpas_request_disconnection(struct wpa_supplicant *wpa_s);
int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen);
int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style);
int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s);