Cumulative patch from commit ee48f48ba
The following commits are merged as well as changes in
./wpa_supplicant/hidl/1.3 to fix compilation errors.
ee48f48ba hostapd: Support showing neighbor list through hostapd_cli
3204795d7 STA OBSS: Add check for overlapping BSSs
3af78a4e0 Extract BSS coex 40 MHz check into a separate function
70755e658 Allow removing neighbor DB entries by BSSID alone
bf3ab50f4 Change some RRM debug messages from wpa_printf() to wpa_dbg()
a737e40b5 drivers: Support of dynamic VLAN requires Linux ioctls
9b391715c mesh: Allow group management cipher to be configured
65d0b67c2 mesh: Increase plink action frame AMPY buffer length for max GTK/IGTK
b1b62a136 WPS: Add WPS-PIN-ACTIVE and WPS-CANCEL events
0b1839405 Add "reconnect" cmdline argument to hostapd_cli/wpa_cli
4318a635a DBus: Update dont_quote[] with new network profile parameters
26a00ba8b DBus: Remove not existing network profile params from dont_quote[]
23d87687c dbus: Move roam metrics to the correct interface
8e111157e nl80211: Relax bridge setup
3626e72c8 l2_packet: Fix bridge workaround for repeater configuration
84972999b FT: More debug prints for RSNE modification for EAPOL-Key msg 2/4
4cfa8b92b Fix wpa_insert_pmkid() when buffer includes extra IEs
32289112c wpa_passphrase: Output errors to stderr
07fe134d9 EAP-SIM peer: Do not accept SIM/Challenge without SIM/Start
b2e2a8588 OpenSSL: Extend key_block size determination to support GCM/CCM ciphers
efaa6256e More detailed documentation on ieee80211w configuration parameter
1730a6a5e nl80211: Fix couple of typos in a comment
307cfc328 Strip trailing zero data in EAPOL-Key msg 1/4 when no PMKID to send
2c5ccfa60 nl80211: Initialize full channel info struct even if channel is not known
e6d3aca9c WPS: Add prefixes to public event_* functions
2ba6aa604 Fix memory leak in case allocation of token fails during JSON parsing
84877f253 wpa_supplicant: Do not try to detect PSK mismatch during PTK rekeying
78d338d1b DPP: Fix a memory leak on an error path
9be30ffc1 DPP: Abort ongoing scan if connection status needs to be sent
3f3876344 SAE: Enable NEED_DH_GROUPS_ALL for CONFIG_TESTING_OPTIONS=y builds
1f1567d2a QCA vendor command for getting STA information
e5620bf02 6 GHz: Select channel width using configured op_class
0bfc04b8d Do not enable HT/VHT when operating in 6 GHz band
da8570f4c Allow non-PCS 6 GHz channels to be excluded from ACS
59bb72642 Allow ACS channel list to be configured as frequencies (in MHz)
5f9b4afdf Use frequency in HT/VHT validation steps done before starting AP
59e33b4a9 ACS: Select current hw_mode based on the selected frequency
bb781c763 AP: Populate iface->freq before starting AP
41cac481a ACS: Use frequency params in ACS (offload) completed event interface
840532aea Search through all hw_features sets in hw_get_channel_freq()
15d356873 ACS: Add channels from all modes matching with configured hw mode
996662250 P2P: Add support for EDMG channels
f86e34168 Update operating classes and channels for the 60 GHz band
a19277a28 Add EDMG bandwidth to channel frequency APIs
5a563a3d3 Avoid compiler warning on shadowing a local variable
e3c476bd8 SAE H2E: Fix RSNXE override in EAPOL-Key msg 2/4 for testing purposes
7fde39fb1 Add sae_rejected_groups to hostapd STA control interface command
5661ebd77 DPP: Configurator netRole for Enrollee
740457445 DPP: Replace ap boolean with netRole enum in Configurator params
f2c4b44b4 SAE H2E: RSNXE override in EAPOL-Key msg 3/4
132565539 SAE H2E: RSNXE override for testing purposes
a889e9a70 SAE: Reject invalid rejected group report in SAE commit explicitly (AP)
c88e01e1b SAE H2E: Fix validation of rejected groups list
b834e9700 SAE H2E: Testing option to report extra rejected groups
918df2227 SAE: Reject unexpected Status Code in SAE commit explicitly (AP)
405946d76 SAE: Testing option to ignore H2E requirement mismatch
23acdd9f3 Fix memory leak in ACS offload operation
e86ba912a ACS: Remove redundant ch_list parameters from do_acs interface
3cf360b8e DFS: Don't handle DFS ops for 6 GHz channels
ee0030e81 6 GHz: Do not check for HT capability on 6 GHz channels
e780b4bf2 DPP: Bootstrapping via NFC URI Record
3c0d6eb8a Sync with mac80211-next.git include/uapi/linux/nl80211.h
38203148e Extend hostapd to support setband to driver via QCA vendor command
3c13af557 hostapd: Register wpa_msg callback even if only global ctrl_iface is used
e92080568 hostapd: Extend global control interface notifications
9f50538e1 SAE H2E: Do not use sae_h2e param in AP mode if SAE is disabled
181bf9336 DPP2: Report received ssid_charset as DPP-CONFOBJ-SSID-CHARSET event
71e2848ea DPP2: ssid64/ssid_charset in Configurator
57a63b131 DPP2: Add parsing of ssid64/ssid_charset in Config Object
590bc64d6 DPP: Use JSON token builder helpers
e75ab5322 JSON: Add helper functions for building tokens
8e5e36a18 Clean up base64_{encode,decode} pointer types
b22608423 Clean up base64_url_{encode,decode} pointer types
a4255a207 Simplify base64_url_encode() prototype
c54227c26 DPP2: Replace connectionStatus object ssid with ssid64
31b6eb417 tests: Update SAE H2E test case to match SSWU parameter z change
0432237a4 SAE H2E: Update SSWU curve-specific parameter z values
5b50265e1 WMM: Do not modify input TSPEC buffer during processing
783a99b73 HS2.0: Skip check for roaming_consortium for NAI realm query
f3c077929 P2P: Fix listen state machine getting stuck in send_action() scheduled case
530b8ee3c hostapd: Update DFS status in VHT80+80 mode
93ba13bcf Fix status code in SAE/DPP association PMKID mismatch (driver-AP-SME)
b90d2f7ff Fix a typo in a comment
Bug: 146900007
Test: Device boots up and connects to wifi networks, run traffic.
Test: Able to turn on/off softap, associate wifi STA, run traffic.
Test: Regression test Passed (Bug: 146905211)
Change-Id: Idc3584b491429a2e4935068a293bff572fc9d62e
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 40066ad..21c9ab2 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -3162,6 +3162,15 @@
line);
return 1;
}
+ } else if (os_strcmp(buf, "freqlist") == 0) {
+ if (freq_range_list_parse(&conf->acs_freq_list, pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid frequency list",
+ line);
+ return 1;
+ }
+ conf->acs_freq_list_present = 1;
+ } else if (os_strcmp(buf, "acs_exclude_6ghz_non_psc") == 0) {
+ conf->acs_exclude_6ghz_non_psc = atoi(pos);
} else if (os_strcmp(buf, "beacon_int") == 0) {
int val = atoi(pos);
/* MIB defines range as 1..65535, but very small values
@@ -4156,6 +4165,9 @@
} else if (os_strcmp(buf, "sae_commit_override") == 0) {
wpabuf_free(bss->sae_commit_override);
bss->sae_commit_override = wpabuf_parse_bin(pos);
+ } else if (os_strcmp(buf, "rsnxe_override_eapol") == 0) {
+ wpabuf_free(bss->rsnxe_override_eapol);
+ bss->rsnxe_override_eapol = wpabuf_parse_bin(pos);
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_SAE
} else if (os_strcmp(buf, "sae_password") == 0) {
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 2c44d1e..9758881 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -1326,6 +1326,33 @@
}
}
+
+static int hostapd_ctrl_iface_set_band(struct hostapd_data *hapd,
+ const char *band)
+{
+ union wpa_event_data event;
+ enum set_band setband;
+
+ if (os_strcmp(band, "AUTO") == 0)
+ setband = WPA_SETBAND_AUTO;
+ else if (os_strcmp(band, "5G") == 0)
+ setband = WPA_SETBAND_5G;
+ else if (os_strcmp(band, "2G") == 0)
+ setband = WPA_SETBAND_2G;
+ else
+ return -1;
+
+ if (hostapd_drv_set_band(hapd, setband) == 0) {
+ os_memset(&event, 0, sizeof(event));
+ event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
+ event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
+ wpa_supplicant_event(hapd, EVENT_CHANNEL_LIST_CHANGED, &event);
+ }
+
+ return 0;
+}
+
+
static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
{
char *value;
@@ -1409,6 +1436,8 @@
os_free(hapd->dpp_configurator_params);
hapd->dpp_configurator_params = os_strdup(value);
#endif /* CONFIG_DPP */
+ } else if (os_strcasecmp(cmd, "setband") == 0) {
+ ret = hostapd_ctrl_iface_set_band(hapd, value);
} else {
ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
if (ret)
@@ -2678,6 +2707,20 @@
}
+static int hostapd_ctrl_iface_show_neighbor(struct hostapd_data *hapd,
+ char *buf, size_t buflen)
+{
+ if (!(hapd->conf->radio_measurements[0] &
+ WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
+ wpa_printf(MSG_ERROR,
+ "CTRL: SHOW_NEIGHBOR: Neighbor report is not enabled");
+ return -1;
+ }
+
+ return hostapd_neighbor_show(hapd, buf, buflen);
+}
+
+
static int hostapd_ctrl_iface_set_neighbor(struct hostapd_data *hapd, char *buf)
{
struct wpa_ssid_value ssid;
@@ -2784,6 +2827,7 @@
char *buf)
{
struct wpa_ssid_value ssid;
+ struct wpa_ssid_value *ssidp = NULL;
u8 bssid[ETH_ALEN];
char *tmp;
@@ -2793,13 +2837,16 @@
}
tmp = os_strstr(buf, "ssid=");
- if (!tmp || ssid_parse(tmp + 5, &ssid)) {
- wpa_printf(MSG_ERROR,
- "CTRL: REMOVE_NEIGHBORr: Bad or missing SSID");
- return -1;
+ if (tmp) {
+ ssidp = &ssid;
+ if (ssid_parse(tmp + 5, &ssid)) {
+ wpa_printf(MSG_ERROR,
+ "CTRL: REMOVE_NEIGHBOR: Bad SSID");
+ return -1;
+ }
}
- return hostapd_neighbor_remove(hapd, bssid, &ssid);
+ return hostapd_neighbor_remove(hapd, bssid, ssidp);
}
@@ -3222,6 +3269,9 @@
} else if (os_strncmp(buf, "SET_NEIGHBOR ", 13) == 0) {
if (hostapd_ctrl_iface_set_neighbor(hapd, buf + 13))
reply_len = -1;
+ } else if (os_strcmp(buf, "SHOW_NEIGHBOR") == 0) {
+ reply_len = hostapd_ctrl_iface_show_neighbor(hapd, reply,
+ reply_size);
} else if (os_strncmp(buf, "REMOVE_NEIGHBOR ", 16) == 0) {
if (hostapd_ctrl_iface_remove_neighbor(hapd, buf + 16))
reply_len = -1;
@@ -3289,6 +3339,15 @@
if (os_snprintf_error(reply_size, reply_len))
reply_len = -1;
}
+ } else if (os_strncmp(buf, "DPP_NFC_URI ", 12) == 0) {
+ res = hostapd_dpp_nfc_uri(hapd, buf + 12);
+ if (res < 0) {
+ reply_len = -1;
+ } else {
+ reply_len = os_snprintf(reply, reply_size, "%d", res);
+ if (os_snprintf_error(reply_size, reply_len))
+ reply_len = -1;
+ }
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
res = dpp_bootstrap_gen(hapd->iface->interfaces->dpp, buf + 18);
if (res < 0) {
@@ -4364,6 +4423,8 @@
return -1;
}
+ wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
+
return 0;
fail:
@@ -4466,6 +4527,8 @@
eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
interface, NULL);
+ wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
+
return 0;
fail:
@@ -4535,37 +4598,48 @@
}
-static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
- enum wpa_msg_type type,
- const char *buf, size_t len)
+static void hostapd_ctrl_iface_send_internal(int sock, struct dl_list *ctrl_dst,
+ const char *ifname, int level,
+ const char *buf, size_t len)
{
struct wpa_ctrl_dst *dst, *next;
- struct dl_list *ctrl_dst;
struct msghdr msg;
- int idx;
- struct iovec io[2];
+ int idx, res;
+ struct iovec io[5];
char levelstr[10];
- int s;
- if (type != WPA_MSG_ONLY_GLOBAL) {
- s = hapd->ctrl_sock;
- ctrl_dst = &hapd->ctrl_dst;
- } else {
- s = hapd->iface->interfaces->global_ctrl_sock;
- ctrl_dst = &hapd->iface->interfaces->global_ctrl_dst;
- }
-
- if (s < 0 || dl_list_empty(ctrl_dst))
+ if (sock < 0 || dl_list_empty(ctrl_dst))
return;
- os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
- io[0].iov_base = levelstr;
- io[0].iov_len = os_strlen(levelstr);
- io[1].iov_base = (char *) buf;
- io[1].iov_len = len;
+ res = os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
+ if (os_snprintf_error(sizeof(levelstr), res))
+ return;
+ idx = 0;
+ if (ifname) {
+#ifdef CONFIG_CTRL_IFACE_UDP
+ io[idx].iov_base = "IFACE=";
+ io[idx].iov_len = 6;
+#else /* CONFIG_CTRL_IFACE_UDP */
+ io[idx].iov_base = "IFNAME=";
+ io[idx].iov_len = 7;
+#endif /* CONFIG_CTRL_IFACE_UDP */
+ idx++;
+ io[idx].iov_base = (char *) ifname;
+ io[idx].iov_len = os_strlen(ifname);
+ idx++;
+ io[idx].iov_base = " ";
+ io[idx].iov_len = 1;
+ idx++;
+ }
+ io[idx].iov_base = levelstr;
+ io[idx].iov_len = os_strlen(levelstr);
+ idx++;
+ io[idx].iov_base = (char *) buf;
+ io[idx].iov_len = len;
+ idx++;
os_memset(&msg, 0, sizeof(msg));
msg.msg_iov = io;
- msg.msg_iovlen = 2;
+ msg.msg_iovlen = idx;
idx = 0;
dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) {
@@ -4575,22 +4649,16 @@
&dst->addr, dst->addrlen);
msg.msg_name = &dst->addr;
msg.msg_namelen = dst->addrlen;
- if (sendmsg(s, &msg, 0) < 0) {
+ if (sendmsg(sock, &msg, 0) < 0) {
int _errno = errno;
wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
"%d - %s",
idx, errno, strerror(errno));
dst->errors++;
if (dst->errors > 10 || _errno == ENOENT) {
- if (type != WPA_MSG_ONLY_GLOBAL)
- hostapd_ctrl_iface_detach(
- hapd, &dst->addr,
- dst->addrlen);
- else
- hostapd_global_ctrl_iface_detach(
- hapd->iface->interfaces,
- &dst->addr,
- dst->addrlen);
+ ctrl_iface_detach(ctrl_dst,
+ &dst->addr,
+ dst->addrlen);
}
} else
dst->errors = 0;
@@ -4599,4 +4667,25 @@
}
}
+
+static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
+ enum wpa_msg_type type,
+ const char *buf, size_t len)
+{
+ if (type != WPA_MSG_NO_GLOBAL) {
+ hostapd_ctrl_iface_send_internal(
+ hapd->iface->interfaces->global_ctrl_sock,
+ &hapd->iface->interfaces->global_ctrl_dst,
+ type != WPA_MSG_PER_INTERFACE ?
+ NULL : hapd->conf->iface,
+ level, buf, len);
+ }
+
+ if (type != WPA_MSG_ONLY_GLOBAL) {
+ hostapd_ctrl_iface_send_internal(
+ hapd->ctrl_sock, &hapd->ctrl_dst,
+ NULL, level, buf, len);
+ }
+}
+
#endif /* CONFIG_NATIVE_WINDOWS */
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 4cbe451..263a04e 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -205,11 +205,26 @@
#chanlist=100 104 108 112 116
#chanlist=1 6 11-13
+# Frequency list restriction. This option allows hostapd to select one of the
+# provided frequencies when a frequency should be automatically selected.
+# Frequency list can be provided as range using hyphen ('-') or individual
+# frequencies can be specified by comma (',') separated values
+# Default: all frequencies allowed in selected hw_mode
+#freqlist=2437,5945,5965
+#freqlist=2437,5985-6105
+
# Exclude DFS channels from ACS
# This option can be used to exclude all DFS channels from the ACS channel list
# in cases where the driver supports DFS channels.
#acs_exclude_dfs=1
+# Include only preferred scan channels from 6 GHz band for ACS
+# This option can be used to include only preferred scan channels in the 6 GHz
+# band. This can be useful in particular for devices that operate only a 6 GHz
+# BSS without a collocated 2.4/5 GHz BSS.
+# Default behavior is to include all PSC and non-PSC channels.
+#acs_exclude_6ghz_non_psc=1
+
# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)
beacon_int=100
@@ -1644,6 +1659,12 @@
# 1 = optional
# 2 = required
#ieee80211w=0
+# The most common configuration options for this based on the PMF (protected
+# management frames) certification program are:
+# PMF enabled: ieee80211w=1 and wpa_key_mgmt=WPA-EAP WPA-EAP-SHA256
+# PMF required: ieee80211w=2 and wpa_key_mgmt=WPA-EAP-SHA256
+# (and similarly for WPA-PSK and WPA-PSK-SHA256 if WPA2-Personal is used)
+# WPA3-Personal-only mode: ieee80211w=2 and wpa_key_mgmt=SAE
# Group management cipher suite
# Default: AES-128-CMAC (BIP)
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index 42edb7b..440664e 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -54,7 +54,7 @@
fprintf(stderr, "%s\n", hostapd_cli_version);
fprintf(stderr,
"\n"
- "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
+ "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvBr] "
"[-a<path>] \\\n"
" [-P<pid file>] [-G<ping interval>] [command..]\n"
"\n"
@@ -68,6 +68,9 @@
" -a<file> run in daemon mode executing the action file "
"based on events\n"
" from hostapd\n"
+ " -r try to reconnect when client socket is "
+ "disconnected.\n"
+ " This is useful only when used with -a.\n"
" -B run a daemon in the background\n"
" -i<ifname> Interface to listen on (default: first "
"interface found in the\n"
@@ -1309,24 +1312,17 @@
}
+static int hostapd_cli_cmd_show_neighbor(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "SHOW_NEIGHBOR");
+}
+
+
static int hostapd_cli_cmd_remove_neighbor(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
- char cmd[400];
- int res;
-
- if (argc != 2) {
- printf("Invalid remove_neighbor command: needs 2 arguments\n");
- return -1;
- }
-
- res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NEIGHBOR %s %s",
- argv[0], argv[1]);
- if (os_snprintf_error(sizeof(cmd), res)) {
- printf("Too long REMOVE_NEIGHBOR command.\n");
- return -1;
- }
- return wpa_ctrl_command(ctrl, cmd);
+ return hostapd_cli_cmd(ctrl, "REMOVE_NEIGHBOR", 1, argc, argv);
}
@@ -1633,8 +1629,10 @@
{ "set_neighbor", hostapd_cli_cmd_set_neighbor, NULL,
"<addr> <ssid=> <nr=> [lci=] [civic=] [stat]\n"
" = add AP to neighbor database" },
+ { "show_neighbor", hostapd_cli_cmd_show_neighbor, NULL,
+ " = show neighbor database entries" },
{ "remove_neighbor", hostapd_cli_cmd_remove_neighbor, NULL,
- "<addr> <ssid=> = remove AP from neighbor database" },
+ "<addr> [ssid=<hex>] = remove AP from neighbor database" },
{ "req_lci", hostapd_cli_cmd_req_lci, hostapd_complete_stations,
"<addr> = send LCI request to a station"},
{ "req_range", hostapd_cli_cmd_req_range, NULL,
@@ -2007,12 +2005,13 @@
int warning_displayed = 0;
int c;
int daemonize = 0;
+ int reconnect = 0;
if (os_program_init())
return -1;
for (;;) {
- c = getopt(argc, argv, "a:BhG:i:p:P:s:v");
+ c = getopt(argc, argv, "a:BhG:i:p:P:rs:v");
if (c < 0)
break;
switch (c) {
@@ -2041,6 +2040,9 @@
case 'P':
pid_file = optarg;
break;
+ case 'r':
+ reconnect = 1;
+ break;
case 's':
client_socket_dir = optarg;
break;
@@ -2083,8 +2085,7 @@
printf("Connection established.\n");
break;
}
-
- if (!interactive) {
+ if (!interactive && !reconnect) {
perror("Failed to connect to hostapd - "
"wpa_ctrl_open");
return -1;
@@ -2102,8 +2103,14 @@
return -1;
if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
return -1;
-
- if (interactive)
+ if (reconnect && action_file && ctrl_ifname) {
+ while (!hostapd_cli_quit) {
+ if (ctrl_conn)
+ hostapd_cli_action(ctrl_conn);
+ os_sleep(1, 0);
+ hostapd_cli_reconnect(ctrl_ifname);
+ }
+ } else if (interactive)
hostapd_cli_interactive();
else if (action_file)
hostapd_cli_action(ctrl_conn);
diff --git a/hs20/client/est.c b/hs20/client/est.c
index db65334..97f9132 100644
--- a/hs20/client/est.c
+++ b/hs20/client/est.c
@@ -158,7 +158,7 @@
return -1;
}
- pkcs7 = base64_decode((unsigned char *) resp, resp_len, &pkcs7_len);
+ pkcs7 = base64_decode(resp, resp_len, &pkcs7_len);
if (pkcs7 && pkcs7_len < resp_len / 2) {
wpa_printf(MSG_INFO, "Too short base64 decode (%u bytes; downloaded %u bytes) - assume this was binary",
(unsigned int) pkcs7_len, (unsigned int) resp_len);
@@ -639,8 +639,7 @@
return -1;
}
- attrs = base64_decode((unsigned char *) resp, resp_len,
- &attrs_len);
+ attrs = base64_decode(resp, resp_len, &attrs_len);
os_free(resp);
if (attrs == NULL) {
@@ -734,7 +733,7 @@
}
wpa_printf(MSG_DEBUG, "EST simpleenroll response: %s", resp);
- pkcs7 = base64_decode((unsigned char *) resp, resp_len, &pkcs7_len);
+ pkcs7 = base64_decode(resp, resp_len, &pkcs7_len);
if (pkcs7 == NULL) {
wpa_printf(MSG_INFO, "EST workaround - Could not decode base64, assume this is DER encoded PKCS7");
pkcs7 = os_malloc(resp_len);
diff --git a/hs20/client/osu_client.c b/hs20/client/osu_client.c
index fd99600..a94f40c 100644
--- a/hs20/client/osu_client.c
+++ b/hs20/client/osu_client.c
@@ -310,7 +310,7 @@
size_t len;
u8 digest1[SHA256_MAC_LEN], digest2[SHA256_MAC_LEN];
int res;
- unsigned char *b64;
+ char *b64;
FILE *f;
url_node = get_node(ctx->xml, params, "CertURL");
@@ -364,7 +364,7 @@
return -1;
}
- b64 = base64_encode((unsigned char *) cert, len, NULL);
+ b64 = base64_encode(cert, len, NULL);
os_free(cert);
if (b64 == NULL)
return -1;
diff --git a/hs20/server/spp_server.c b/hs20/server/spp_server.c
index 4bef0ff..a50e907 100644
--- a/hs20/server/spp_server.c
+++ b/hs20/server/spp_server.c
@@ -633,7 +633,7 @@
add_text_node(ctx, node, "Username", user);
- b64 = (char *) base64_encode((unsigned char *) pw, strlen(pw), NULL);
+ b64 = base64_encode(pw, strlen(pw), NULL);
if (b64 == NULL)
return NULL;
len = os_strlen(b64);
@@ -1602,8 +1602,7 @@
xml_node_create_text(ctx->xml, enroll, ns, "estUserID", user);
- b64 = (char *) base64_encode((unsigned char *) password,
- strlen(password), NULL);
+ b64 = base64_encode(password, strlen(password), NULL);
if (b64 == NULL) {
xml_node_free(ctx->xml, spp_node);
return NULL;
diff --git a/src/ap/acs.c b/src/ap/acs.c
index f12539f..232afa8 100644
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -862,6 +862,7 @@
}
iface->conf->channel = ideal_chan->chan;
+ iface->freq = ideal_chan->freq;
if (iface->conf->ieee80211ac || iface->conf->ieee80211ax)
acs_adjust_center_freq(iface);
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 58fc3e9..68af3c1 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -441,7 +441,7 @@
struct hostapd_ssid *ssid = &conf->ssid;
struct sae_password_entry *pw;
- if (conf->sae_pwe == 0)
+ if (conf->sae_pwe == 0 || !wpa_key_mgmt_sae(conf->wpa_key_mgmt))
return 0; /* PT not needed */
sae_deinit_pt(ssid->pt);
@@ -880,6 +880,7 @@
#ifdef CONFIG_TESTING_OPTIONS
wpabuf_free(conf->own_ie_override);
wpabuf_free(conf->sae_commit_override);
+ wpabuf_free(conf->rsnxe_override_eapol);
#endif /* CONFIG_TESTING_OPTIONS */
os_free(conf->no_probe_resp_if_seen_on);
@@ -935,6 +936,7 @@
os_free(conf->supported_rates);
os_free(conf->basic_rates);
os_free(conf->acs_ch_list.range);
+ os_free(conf->acs_freq_list.range);
os_free(conf->driver_params);
#ifdef CONFIG_ACS
os_free(conf->acs_chan_bias);
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 2a0c984..83b8aee 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -664,6 +664,7 @@
struct wpabuf *own_ie_override;
int sae_reflection_attack;
struct wpabuf *sae_commit_override;
+ struct wpabuf *rsnxe_override_eapol;
#endif /* CONFIG_TESTING_OPTIONS */
#define MESH_ENABLED BIT(0)
@@ -881,8 +882,11 @@
u8 edmg_channel;
u8 acs;
struct wpa_freq_range_list acs_ch_list;
+ struct wpa_freq_range_list acs_freq_list;
+ u8 acs_freq_list_present;
int acs_exclude_dfs;
enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
+ int acs_exclude_6ghz_non_psc;
enum {
LONG_PREAMBLE = 0,
SHORT_PREAMBLE = 1
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 204274f..7585866 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -10,6 +10,7 @@
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
#include "common/hw_features_common.h"
#include "wps/wps.h"
#include "p2p/p2p.h"
@@ -855,10 +856,24 @@
for (i = 0; i < mode->num_channels; i++) {
struct hostapd_channel_data *chan = &mode->channels[i];
- if ((acs_ch_list_all ||
- freq_range_list_includes(&hapd->iface->conf->acs_ch_list,
- chan->chan)) &&
- !(chan->flag & HOSTAPD_CHAN_DISABLED) &&
+ if (!acs_ch_list_all &&
+ (hapd->iface->conf->acs_freq_list.num &&
+ !freq_range_list_includes(
+ &hapd->iface->conf->acs_freq_list,
+ chan->freq)))
+ continue;
+ if (!acs_ch_list_all &&
+ (!hapd->iface->conf->acs_freq_list_present &&
+ hapd->iface->conf->acs_ch_list.num &&
+ !freq_range_list_includes(
+ &hapd->iface->conf->acs_ch_list,
+ chan->chan)))
+ continue;
+ if (is_6ghz_freq(chan->freq) &&
+ hapd->iface->conf->acs_exclude_6ghz_non_psc &&
+ !is_6ghz_psc_frequency(chan->freq))
+ continue;
+ if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
!(hapd->iface->conf->acs_exclude_dfs &&
(chan->flag & HOSTAPD_CHAN_RADAR)))
int_array_add_unique(freq_list, chan->freq);
@@ -884,10 +899,9 @@
{
struct drv_acs_params params;
int ret, i, acs_ch_list_all = 0;
- u8 *channels = NULL;
- unsigned int num_channels = 0;
struct hostapd_hw_modes *mode;
int *freq_list = NULL;
+ enum hostapd_hw_mode selected_mode;
if (hapd->driver == NULL || hapd->driver->do_acs == NULL)
return 0;
@@ -899,41 +913,25 @@
* If no chanlist config parameter is provided, include all enabled
* channels of the selected hw_mode.
*/
- if (!hapd->iface->conf->acs_ch_list.num)
- acs_ch_list_all = 1;
+ if (hapd->iface->conf->acs_freq_list_present)
+ acs_ch_list_all = !hapd->iface->conf->acs_freq_list.num;
+ else
+ acs_ch_list_all = !hapd->iface->conf->acs_ch_list.num;
- mode = hapd->iface->current_mode;
- if (mode) {
- channels = os_malloc(mode->num_channels);
- if (channels == NULL)
- return -1;
+ if (hapd->iface->current_mode)
+ selected_mode = hapd->iface->current_mode->mode;
+ else
+ selected_mode = HOSTAPD_MODE_IEEE80211ANY;
- for (i = 0; i < mode->num_channels; i++) {
- struct hostapd_channel_data *chan = &mode->channels[i];
- if (!acs_ch_list_all &&
- !freq_range_list_includes(
- &hapd->iface->conf->acs_ch_list,
- chan->chan))
- continue;
- if (hapd->iface->conf->acs_exclude_dfs &&
- (chan->flag & HOSTAPD_CHAN_RADAR))
- continue;
- if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) {
- channels[num_channels++] = chan->chan;
- int_array_add_unique(&freq_list, chan->freq);
- }
- }
- } else {
- for (i = 0; i < hapd->iface->num_hw_features; i++) {
- mode = &hapd->iface->hw_features[i];
- hostapd_get_hw_mode_any_channels(hapd, mode,
- acs_ch_list_all,
- &freq_list);
- }
+ for (i = 0; i < hapd->iface->num_hw_features; i++) {
+ mode = &hapd->iface->hw_features[i];
+ if (selected_mode != HOSTAPD_MODE_IEEE80211ANY &&
+ selected_mode != mode->mode)
+ continue;
+ hostapd_get_hw_mode_any_channels(hapd, mode, acs_ch_list_all,
+ &freq_list);
}
- params.ch_list = channels;
- params.ch_list_len = num_channels;
params.freq_list = freq_list;
params.ht_enabled = !!(hapd->iface->conf->ieee80211n);
@@ -958,8 +956,11 @@
params.ch_width = 160;
}
+ if (hapd->iface->conf->op_class)
+ params.ch_width = op_class_to_bandwidth(
+ hapd->iface->conf->op_class);
ret = hapd->driver->do_acs(hapd->drv_priv, ¶ms);
- os_free(channels);
+ os_free(freq_list);
return ret;
}
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 79b1302..fa413df 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -382,4 +382,12 @@
return hapd->driver->send_external_auth_status(hapd->drv_priv, params);
}
+static inline int
+hostapd_drv_set_band(struct hostapd_data *hapd, enum set_band band)
+{
+ if (!hapd->driver || !hapd->drv_priv || !hapd->driver->set_band)
+ return -1;
+ return hapd->driver->set_band(hapd->drv_priv, band);
+}
+
#endif /* AP_DRV_OPS */
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index bde61ee..9fd1b81 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -273,6 +273,36 @@
if (!os_snprintf_error(buflen - len, res))
len += res;
}
+
+ if (sta->sae && sta->sae->tmp) {
+ const u8 *pos;
+ unsigned int j, count;
+ struct wpabuf *groups = sta->sae->tmp->peer_rejected_groups;
+
+ res = os_snprintf(buf + len, buflen - len,
+ "sae_rejected_groups=");
+ if (!os_snprintf_error(buflen - len, res))
+ len += res;
+
+ if (groups) {
+ pos = wpabuf_head(groups);
+ count = wpabuf_len(groups) / 2;
+ } else {
+ pos = NULL;
+ count = 0;
+ }
+ for (j = 0; pos && j < count; j++) {
+ res = os_snprintf(buf + len, buflen - len, "%s%d",
+ j == 0 ? "" : " ", WPA_GET_LE16(pos));
+ if (!os_snprintf_error(buflen - len, res))
+ len += res;
+ pos += 2;
+ }
+
+ res = os_snprintf(buf + len, buflen - len, "\n");
+ if (!os_snprintf_error(buflen - len, res))
+ len += res;
+ }
#endif /* CONFIG_SAE */
if (sta->vlan_id > 0) {
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index c4c00fc..f70ecc9 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -515,6 +515,7 @@
int n_chans = 1, i;
struct hostapd_hw_modes *mode;
int frequency = freq;
+ int frequency2 = 0;
int ret = 0;
mode = iface->current_mode;
@@ -542,6 +543,11 @@
n_chans = 4;
frequency = cf1 - 30;
break;
+ case CHAN_WIDTH_80P80:
+ n_chans = 4;
+ frequency = cf1 - 30;
+ frequency2 = cf2 - 30;
+ break;
case CHAN_WIDTH_160:
n_chans = 8;
frequency = cf1 - 70;
@@ -557,6 +563,11 @@
for (i = 0; i < n_chans; i++) {
ret += set_dfs_state_freq(iface, frequency, state);
frequency = frequency + 20;
+
+ if (chan_width == CHAN_WIDTH_80P80) {
+ ret += set_dfs_state_freq(iface, frequency2, state);
+ frequency2 = frequency2 + 20;
+ }
}
return ret;
@@ -662,6 +673,9 @@
int res, n_chans, n_chans1, start_chan_idx, start_chan_idx1;
int skip_radar = 0;
+ if (is_6ghz_freq(iface->freq))
+ return 1;
+
if (!iface->current_mode) {
/*
* This can happen with drivers that do not provide mode
diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c
index 085d423..1a3a815 100644
--- a/src/ap/dpp_hostapd.c
+++ b/src/ap/dpp_hostapd.c
@@ -1,6 +1,7 @@
/*
* hostapd / DPP integration
* Copyright (c) 2017, Qualcomm Atheros, Inc.
+ * Copyright (c) 2018-2019, The Linux Foundation
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -62,6 +63,24 @@
}
+/**
+ * hostapd_dpp_nfc_uri - Parse and add DPP bootstrapping info from NFC Tag (URI)
+ * @hapd: Pointer to hostapd_data
+ * @cmd: DPP URI read from a NFC Tag (URI NDEF message)
+ * Returns: Identifier of the stored info or -1 on failure
+ */
+int hostapd_dpp_nfc_uri(struct hostapd_data *hapd, const char *cmd)
+{
+ struct dpp_bootstrap_info *bi;
+
+ bi = dpp_add_nfc_uri(hapd->iface->interfaces->dpp, cmd);
+ if (!bi)
+ return -1;
+
+ return bi->id;
+}
+
+
static void hostapd_dpp_auth_resp_retry_timeout(void *eloop_ctx,
void *timeout_ctx)
{
@@ -768,7 +787,8 @@
struct wpabuf *buf;
int res;
- buf = dpp_build_conf_req_helper(auth, hapd->conf->dpp_name, 1,
+ buf = dpp_build_conf_req_helper(auth, hapd->conf->dpp_name,
+ DPP_NETROLE_AP,
hapd->conf->dpp_mud_url, NULL);
if (!buf) {
wpa_printf(MSG_DEBUG,
diff --git a/src/ap/dpp_hostapd.h b/src/ap/dpp_hostapd.h
index c1ec5d7..e151c2f 100644
--- a/src/ap/dpp_hostapd.h
+++ b/src/ap/dpp_hostapd.h
@@ -1,6 +1,7 @@
/*
* hostapd / DPP integration
* Copyright (c) 2017, Qualcomm Atheros, Inc.
+ * Copyright (c) 2018-2019, The Linux Foundation
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -10,6 +11,7 @@
#define DPP_HOSTAPD_H
int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd);
+int hostapd_dpp_nfc_uri(struct hostapd_data *hapd, const char *cmd);
int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd);
int hostapd_dpp_listen(struct hostapd_data *hapd, const char *cmd);
void hostapd_dpp_listen_stop(struct hostapd_data *hapd);
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 3198bd5..8a4b0ef 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -17,6 +17,7 @@
#include "common/wpa_ctrl.h"
#include "common/dpp.h"
#include "common/sae.h"
+#include "common/hw_features_common.h"
#include "crypto/random.h"
#include "p2p/p2p.h"
#include "wps/wps.h"
@@ -344,6 +345,9 @@
} else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) {
reason = WLAN_REASON_CIPHER_SUITE_REJECTED;
status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
+ } else if (res == WPA_INVALID_PMKID) {
+ reason = WLAN_REASON_INVALID_PMKID;
+ status = WLAN_STATUS_INVALID_PMKID;
} else {
reason = WLAN_REASON_INVALID_IE;
status = WLAN_STATUS_INVALID_IE;
@@ -932,6 +936,7 @@
{
int ret, i;
int err = 0;
+ struct hostapd_channel_data *pri_chan;
if (hapd->iconf->channel) {
wpa_printf(MSG_INFO, "ACS: Channel was already set to %d",
@@ -939,12 +944,20 @@
return;
}
+ hapd->iface->freq = acs_res->pri_freq;
+
if (!hapd->iface->current_mode) {
for (i = 0; i < hapd->iface->num_hw_features; i++) {
struct hostapd_hw_modes *mode =
&hapd->iface->hw_features[i];
if (mode->mode == acs_res->hw_mode) {
+ if (hapd->iface->freq > 0 &&
+ !hw_get_chan(mode->mode,
+ hapd->iface->freq,
+ hapd->iface->hw_features,
+ hapd->iface->num_hw_features))
+ continue;
hapd->iface->current_mode = mode;
break;
}
@@ -958,24 +971,33 @@
}
}
- hapd->iface->freq = hostapd_hw_get_freq(hapd, acs_res->pri_channel);
-
- if (!acs_res->pri_channel) {
+ if (!acs_res->pri_freq) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
"driver switched to bad channel");
err = 1;
goto out;
}
+ pri_chan = hw_get_channel_freq(hapd->iface->current_mode->mode,
+ acs_res->pri_freq, NULL,
+ hapd->iface->hw_features,
+ hapd->iface->num_hw_features);
+ if (!pri_chan) {
+ wpa_printf(MSG_ERROR,
+ "ACS: Could not determine primary channel number from pri_freq %u",
+ acs_res->pri_freq);
+ err = 1;
+ goto out;
+ }
- hapd->iconf->channel = acs_res->pri_channel;
+ hapd->iconf->channel = pri_chan->chan;
hapd->iconf->acs = 1;
- if (acs_res->sec_channel == 0)
+ if (acs_res->sec_freq == 0)
hapd->iconf->secondary_channel = 0;
- else if (acs_res->sec_channel < acs_res->pri_channel)
+ else if (acs_res->sec_freq < acs_res->pri_freq)
hapd->iconf->secondary_channel = -1;
- else if (acs_res->sec_channel > acs_res->pri_channel)
+ else if (acs_res->sec_freq > acs_res->pri_freq)
hapd->iconf->secondary_channel = 1;
else {
wpa_printf(MSG_ERROR, "Invalid secondary channel!");
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 3686438..e4950e3 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1572,6 +1572,51 @@
}
+static int configured_fixed_chan_to_freq(struct hostapd_iface *iface)
+{
+ int freq, i, j;
+
+ if (!iface->conf->channel)
+ return 0;
+ if (iface->conf->op_class) {
+ freq = ieee80211_chan_to_freq(NULL, iface->conf->op_class,
+ iface->conf->channel);
+ if (freq < 0) {
+ wpa_printf(MSG_INFO,
+ "Could not convert op_class %u channel %u to operating frequency",
+ iface->conf->op_class, iface->conf->channel);
+ return -1;
+ }
+ iface->freq = freq;
+ return 0;
+ }
+
+ /* Old configurations using only 2.4/5/60 GHz bands may not specify the
+ * op_class parameter. Select a matching channel from the configured
+ * mode using the channel parameter for these cases.
+ */
+ for (j = 0; j < iface->num_hw_features; j++) {
+ struct hostapd_hw_modes *mode = &iface->hw_features[j];
+
+ if (iface->conf->hw_mode != HOSTAPD_MODE_IEEE80211ANY &&
+ iface->conf->hw_mode != mode->mode)
+ continue;
+ for (i = 0; i < mode->num_channels; i++) {
+ struct hostapd_channel_data *chan = &mode->channels[i];
+
+ if (chan->chan == iface->conf->channel &&
+ !is_6ghz_freq(chan->freq)) {
+ iface->freq = chan->freq;
+ return 0;
+ }
+ }
+ }
+
+ wpa_printf(MSG_INFO, "Could not determine operating frequency");
+ return -1;
+}
+
+
static int setup_interface2(struct hostapd_iface *iface)
{
iface->wait_channel_update = 0;
@@ -1580,7 +1625,20 @@
/* Not all drivers support this yet, so continue without hw
* feature data. */
} else {
- int ret = hostapd_select_hw_mode(iface);
+ int ret;
+
+ ret = configured_fixed_chan_to_freq(iface);
+ if (ret < 0)
+ goto fail;
+
+ if (iface->conf->op_class) {
+ int ch_width;
+
+ ch_width = op_class_to_ch_width(iface->conf->op_class);
+ hostapd_set_oper_chwidth(iface->conf, ch_width);
+ }
+
+ ret = hostapd_select_hw_mode(iface);
if (ret < 0) {
wpa_printf(MSG_ERROR, "Could not select hw_mode and "
"channel. (%d)", ret);
@@ -1864,12 +1922,11 @@
goto fail;
wpa_printf(MSG_DEBUG, "Completing interface initialization");
- if (iface->conf->channel) {
+ if (iface->freq) {
#ifdef NEED_AP_MLME
int res;
#endif /* NEED_AP_MLME */
- iface->freq = hostapd_hw_get_freq(hapd, iface->conf->channel);
wpa_printf(MSG_DEBUG, "Mode: %s Channel: %d "
"Frequency: %d MHz",
hostapd_hw_mode_txt(iface->conf->hw_mode),
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index 2fefaf8..ba10752 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -227,13 +227,25 @@
#ifdef CONFIG_IEEE80211N
static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface)
{
- int pri_chan, sec_chan;
+ int pri_freq, sec_freq;
+ struct hostapd_channel_data *p_chan, *s_chan;
- pri_chan = iface->conf->channel;
- sec_chan = pri_chan + iface->conf->secondary_channel * 4;
+ pri_freq = iface->freq;
+ sec_freq = pri_freq + iface->conf->secondary_channel * 20;
- return allowed_ht40_channel_pair(iface->current_mode, pri_chan,
- sec_chan);
+ if (!iface->current_mode)
+ return 0;
+
+ p_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq, NULL,
+ iface->hw_features,
+ iface->num_hw_features);
+
+ s_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq, NULL,
+ iface->hw_features,
+ iface->num_hw_features);
+
+ return allowed_ht40_channel_pair(iface->current_mode->mode,
+ p_chan, s_chan);
}
@@ -241,9 +253,11 @@
{
if (iface->conf->secondary_channel > 0) {
iface->conf->channel += 4;
+ iface->freq += 20;
iface->conf->secondary_channel = -1;
} else {
iface->conf->channel -= 4;
+ iface->freq -= 20;
iface->conf->secondary_channel = 1;
}
}
@@ -252,13 +266,23 @@
static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface,
struct wpa_scan_results *scan_res)
{
- int pri_chan, sec_chan;
+ unsigned int pri_freq, sec_freq;
int res;
+ struct hostapd_channel_data *pri_chan, *sec_chan;
- pri_chan = iface->conf->channel;
- sec_chan = pri_chan + iface->conf->secondary_channel * 4;
+ pri_freq = iface->freq;
+ sec_freq = pri_freq + iface->conf->secondary_channel * 20;
- res = check_40mhz_5g(iface->current_mode, scan_res, pri_chan, sec_chan);
+ if (!iface->current_mode)
+ return 0;
+ pri_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq,
+ NULL, iface->hw_features,
+ iface->num_hw_features);
+ sec_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq,
+ NULL, iface->hw_features,
+ iface->num_hw_features);
+
+ res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
if (res == 2) {
if (iface->conf->no_pri_sec_switch) {
@@ -352,7 +376,7 @@
if (iface->current_mode == NULL)
return;
- pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel);
+ pri_freq = iface->freq;
if (iface->conf->secondary_channel > 0)
sec_freq = pri_freq + 20;
else
@@ -397,7 +421,7 @@
if (iface->current_mode == NULL)
return;
- pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel);
+ pri_freq = iface->freq;
if (iface->conf->secondary_channel > 0) {
affected_start = pri_freq - 10;
affected_end = pri_freq + 30;
@@ -670,6 +694,9 @@
{
#ifdef CONFIG_IEEE80211N
int ret;
+
+ if (is_6ghz_freq(iface->freq))
+ return 0;
if (!iface->conf->ieee80211n)
return 0;
@@ -731,14 +758,15 @@
static int hostapd_is_usable_chan(struct hostapd_iface *iface,
- int channel, int primary)
+ int frequency, int primary)
{
struct hostapd_channel_data *chan;
if (!iface->current_mode)
return 0;
- chan = hw_get_channel_chan(iface->current_mode, channel, NULL);
+ chan = hw_get_channel_freq(iface->current_mode->mode, frequency, NULL,
+ iface->hw_features, iface->num_hw_features);
if (!chan)
return 0;
@@ -747,8 +775,8 @@
return 1;
wpa_printf(MSG_INFO,
- "Channel %d (%s) not allowed for AP mode, flags: 0x%x%s%s",
- channel, primary ? "primary" : "secondary",
+ "Frequency %d (%s) not allowed for AP mode, flags: 0x%x%s%s",
+ frequency, primary ? "primary" : "secondary",
chan->flag,
chan->flag & HOSTAPD_CHAN_NO_IR ? " NO-IR" : "",
chan->flag & HOSTAPD_CHAN_RADAR ? " RADAR" : "");
@@ -762,19 +790,28 @@
int num_of_enabled = 0;
int max_contiguous = 0;
struct ieee80211_edmg_config edmg;
+ struct hostapd_channel_data *pri_chan;
if (!iface->conf->enable_edmg)
return 1;
+ if (!iface->current_mode)
+ return 0;
+ pri_chan = hw_get_channel_freq(iface->current_mode->mode,
+ iface->freq, NULL,
+ iface->hw_features,
+ iface->num_hw_features);
hostapd_encode_edmg_chan(iface->conf->enable_edmg,
iface->conf->edmg_channel,
- iface->conf->channel,
+ pri_chan->chan,
&edmg);
- if (!(edmg.channels & BIT(iface->conf->channel - 1)))
+ if (!(edmg.channels & BIT(pri_chan->chan - 1)))
return 0;
/* 60 GHz channels 1..6 */
for (i = 0; i < 6; i++) {
+ int freq = 56160 + 2160 * i;
+
if (edmg.channels & BIT(i)) {
contiguous++;
num_of_enabled++;
@@ -789,7 +826,7 @@
if (num_of_enabled > 4)
return 0;
- if (!hostapd_is_usable_chan(iface, i + 1, 1))
+ if (!hostapd_is_usable_chan(iface, freq, 1))
return 0;
if (contiguous > max_contiguous)
@@ -819,17 +856,23 @@
static int hostapd_is_usable_chans(struct hostapd_iface *iface)
{
- int secondary_chan;
+ int secondary_freq;
struct hostapd_channel_data *pri_chan;
- pri_chan = hw_get_channel_chan(iface->current_mode,
- iface->conf->channel, NULL);
- if (!pri_chan)
+ if (!iface->current_mode)
return 0;
-
- if (!hostapd_is_usable_chan(iface, iface->conf->channel, 1))
+ pri_chan = hw_get_channel_freq(iface->current_mode->mode,
+ iface->freq, NULL,
+ iface->hw_features,
+ iface->num_hw_features);
+ if (!pri_chan) {
+ wpa_printf(MSG_ERROR, "Primary frequency not present");
return 0;
-
+ }
+ if (!hostapd_is_usable_chan(iface, pri_chan->freq, 1)) {
+ wpa_printf(MSG_ERROR, "Primary frequency not allowed");
+ return 0;
+ }
if (!hostapd_is_usable_edmg(iface))
return 0;
@@ -838,19 +881,19 @@
if (!iface->conf->ht40_plus_minus_allowed)
return hostapd_is_usable_chan(
- iface, iface->conf->channel +
- iface->conf->secondary_channel * 4, 0);
+ iface,
+ iface->freq + iface->conf->secondary_channel * 20, 0);
/* Both HT40+ and HT40- are set, pick a valid secondary channel */
- secondary_chan = iface->conf->channel + 4;
- if (hostapd_is_usable_chan(iface, secondary_chan, 0) &&
+ secondary_freq = iface->freq + 20;
+ if (hostapd_is_usable_chan(iface, secondary_freq, 0) &&
(pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)) {
iface->conf->secondary_channel = 1;
return 1;
}
- secondary_chan = iface->conf->channel - 4;
- if (hostapd_is_usable_chan(iface, secondary_chan, 0) &&
+ secondary_freq = iface->freq - 20;
+ if (hostapd_is_usable_chan(iface, secondary_freq, 0) &&
(pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M)) {
iface->conf->secondary_channel = -1;
return 1;
@@ -863,7 +906,7 @@
static enum hostapd_chan_status
hostapd_check_chans(struct hostapd_iface *iface)
{
- if (iface->conf->channel) {
+ if (iface->freq) {
if (hostapd_is_usable_chans(iface))
return HOSTAPD_CHAN_VALID;
else
@@ -897,9 +940,9 @@
hostapd_logger(iface->bss[0], NULL,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
- "Configured channel (%d) not found from the "
- "channel list of current mode (%d) %s",
+ "Configured channel (%d) or frequency (%d) not found from the channel list of the current mode (%d) %s",
iface->conf->channel,
+ iface->freq,
iface->current_mode->mode,
hostapd_hw_mode_txt(iface->current_mode->mode));
hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
@@ -919,9 +962,7 @@
case HOSTAPD_CHAN_VALID:
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO,
ACS_EVENT_COMPLETED "freq=%d channel=%d",
- hostapd_hw_get_freq(iface->bss[0],
- iface->conf->channel),
- iface->conf->channel);
+ iface->freq, iface->conf->channel);
break;
case HOSTAPD_CHAN_ACS:
wpa_printf(MSG_ERROR, "ACS error - reported complete, but no result available");
@@ -961,7 +1002,6 @@
int hostapd_select_hw_mode(struct hostapd_iface *iface)
{
int i;
- int freq = -1;
if (iface->num_hw_features < 1)
return -1;
@@ -978,13 +1018,13 @@
}
iface->current_mode = NULL;
- if (iface->conf->channel && iface->conf->op_class)
- freq = ieee80211_chan_to_freq(NULL, iface->conf->op_class,
- iface->conf->channel);
for (i = 0; i < iface->num_hw_features; i++) {
struct hostapd_hw_modes *mode = &iface->hw_features[i];
if (mode->mode == iface->conf->hw_mode) {
- if (freq > 0 && !hw_get_chan(mode, freq))
+ if (iface->freq > 0 &&
+ !hw_get_chan(mode->mode, iface->freq,
+ iface->hw_features,
+ iface->num_hw_features))
continue;
iface->current_mode = mode;
break;
@@ -1048,7 +1088,9 @@
struct hostapd_hw_modes *mode;
if (hapd->iface->current_mode) {
- channel = hw_get_chan(hapd->iface->current_mode, freq);
+ channel = hw_get_chan(hapd->iface->current_mode->mode, freq,
+ hapd->iface->hw_features,
+ hapd->iface->num_hw_features);
if (channel)
return channel;
}
@@ -1059,7 +1101,9 @@
return 0;
for (i = 0; i < hapd->iface->num_hw_features; i++) {
mode = &hapd->iface->hw_features[i];
- channel = hw_get_chan(mode, freq);
+ channel = hw_get_chan(mode->mode, freq,
+ hapd->iface->hw_features,
+ hapd->iface->num_hw_features);
if (channel)
return channel;
}
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 4d30bae..5b70425 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -98,7 +98,8 @@
num++;
if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
num++;
- if (hapd->conf->sae_pwe == 1)
+ if (hapd->conf->sae_pwe == 1 &&
+ wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt))
num++;
if (num > 8) {
/* rest of the rates are encoded in Extended supported
@@ -126,7 +127,9 @@
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
}
- if (hapd->conf->sae_pwe == 1 && count < 8) {
+ if (hapd->conf->sae_pwe == 1 &&
+ wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
+ count < 8) {
count++;
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
}
@@ -148,7 +151,8 @@
num++;
if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
num++;
- if (hapd->conf->sae_pwe == 1)
+ if (hapd->conf->sae_pwe == 1 &&
+ wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt))
num++;
if (num <= 8)
return eid;
@@ -179,7 +183,8 @@
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
}
- if (hapd->conf->sae_pwe == 1) {
+ if (hapd->conf->sae_pwe == 1 &&
+ wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt)) {
count++;
if (count > 8)
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
@@ -1117,8 +1122,10 @@
if (!sta->sae) {
if (auth_transaction != 1 ||
!sae_status_success(hapd, status_code)) {
- resp = -1;
- goto remove_sta;
+ wpa_printf(MSG_DEBUG, "SAE: Unexpected Status Code %u",
+ status_code);
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto reply;
}
sta->sae = os_zalloc(sizeof(*sta->sae));
if (!sta->sae) {
@@ -1273,9 +1280,9 @@
if (sta->sae->tmp &&
check_sae_rejected_groups(
- hapd, sta->sae->tmp->peer_rejected_groups) < 0) {
+ hapd, sta->sae->tmp->peer_rejected_groups)) {
resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
- goto remove_sta;
+ goto reply;
}
if (!token && use_sae_anti_clogging(hapd) && !allow_reuse) {
diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
index 0b828e9..1e1cc38 100644
--- a/src/ap/ieee802_11_shared.c
+++ b/src/ap/ieee802_11_shared.c
@@ -1011,6 +1011,7 @@
u8 *pos = eid;
if (!(hapd->conf->wpa & WPA_PROTO_RSN) ||
+ !wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) ||
(hapd->conf->sae_pwe != 1 && hapd->conf->sae_pwe != 2) ||
len < 3)
return pos;
diff --git a/src/ap/neighbor_db.c b/src/ap/neighbor_db.c
index 5415443..4012ae4 100644
--- a/src/ap/neighbor_db.c
+++ b/src/ap/neighbor_db.c
@@ -34,6 +34,60 @@
}
+int hostapd_neighbor_show(struct hostapd_data *hapd, char *buf, size_t buflen)
+{
+ struct hostapd_neighbor_entry *nr;
+ char *pos, *end;
+
+ pos = buf;
+ end = buf + buflen;
+
+ dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
+ list) {
+ int ret;
+ char nrie[2 * 255 + 1];
+ char lci[2 * 255 + 1];
+ char civic[2 * 255 + 1];
+ char ssid[SSID_MAX_LEN * 2 + 1];
+
+ ssid[0] = '\0';
+ wpa_snprintf_hex(ssid, sizeof(ssid), nr->ssid.ssid,
+ nr->ssid.ssid_len);
+
+ nrie[0] = '\0';
+ if (nr->nr)
+ wpa_snprintf_hex(nrie, sizeof(nrie),
+ wpabuf_head(nr->nr),
+ wpabuf_len(nr->nr));
+
+ lci[0] = '\0';
+ if (nr->lci)
+ wpa_snprintf_hex(lci, sizeof(lci),
+ wpabuf_head(nr->lci),
+ wpabuf_len(nr->lci));
+
+ civic[0] = '\0';
+ if (nr->civic)
+ wpa_snprintf_hex(civic, sizeof(civic),
+ wpabuf_head(nr->civic),
+ wpabuf_len(nr->civic));
+
+ ret = os_snprintf(pos, end - pos, MACSTR
+ " ssid=%s%s%s%s%s%s%s%s\n",
+ MAC2STR(nr->bssid), ssid,
+ nr->nr ? " nr=" : "", nrie,
+ nr->lci ? " lci=" : "", lci,
+ nr->civic ? " civic=" : "", civic,
+ nr->stationary ? " stat" : "");
+ if (os_snprintf_error(end - pos, ret))
+ break;
+ pos += ret;
+ }
+
+ return pos - buf;
+}
+
+
static void hostapd_neighbor_clear_entry(struct hostapd_neighbor_entry *nr)
{
wpabuf_free(nr->nr);
diff --git a/src/ap/neighbor_db.h b/src/ap/neighbor_db.h
index 9c8f4f2..bed0a2f 100644
--- a/src/ap/neighbor_db.h
+++ b/src/ap/neighbor_db.h
@@ -13,6 +13,7 @@
struct hostapd_neighbor_entry *
hostapd_neighbor_get(struct hostapd_data *hapd, const u8 *bssid,
const struct wpa_ssid_value *ssid);
+int hostapd_neighbor_show(struct hostapd_data *hapd, char *buf, size_t buflen);
int hostapd_neighbor_set(struct hostapd_data *hapd, const u8 *bssid,
const struct wpa_ssid_value *ssid,
const struct wpabuf *nr, const struct wpabuf *lci,
diff --git a/src/ap/wmm.c b/src/ap/wmm.c
index dc73493..9f52dee 100644
--- a/src/ap/wmm.c
+++ b/src/ap/wmm.c
@@ -291,10 +291,11 @@
static void wmm_addts_req(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt,
- struct wmm_tspec_element *tspec, size_t len)
+ const struct wmm_tspec_element *tspec, size_t len)
{
const u8 *end = ((const u8 *) mgmt) + len;
int res;
+ struct wmm_tspec_element tspec_resp;
if ((const u8 *) (tspec + 1) > end) {
wpa_printf(MSG_DEBUG, "WMM: TSPEC overflow in ADDTS Request");
@@ -306,10 +307,11 @@
mgmt->u.action.u.wmm_action.dialog_token,
MAC2STR(mgmt->sa));
- res = wmm_process_tspec(tspec);
+ os_memcpy(&tspec_resp, tspec, sizeof(struct wmm_tspec_element));
+ res = wmm_process_tspec(&tspec_resp);
wpa_printf(MSG_DEBUG, "WMM: ADDTS processing result: %d", res);
- wmm_send_action(hapd, mgmt->sa, tspec, WMM_ACTION_CODE_ADDTS_RESP,
+ wmm_send_action(hapd, mgmt->sa, &tspec_resp, WMM_ACTION_CODE_ADDTS_RESP,
mgmt->u.action.u.wmm_action.dialog_token, res);
}
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 7b690d7..6611b0e 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -2169,7 +2169,6 @@
wpa_printf(MSG_DEBUG,
"FT: No PMKID in message 1/4 when using FT protocol");
pmkid = NULL;
- pmkid_len = 0;
#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_SAE
} else if (wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
@@ -2199,6 +2198,8 @@
&pmkid[2 + RSN_SELECTOR_LEN], PMKID_LEN);
}
}
+ if (!pmkid)
+ pmkid_len = 0;
wpa_send_eapol(sm->wpa_auth, sm,
WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL,
sm->ANonce, pmkid, pmkid_len, 0, 0);
@@ -3139,11 +3140,12 @@
SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
{
- u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos, dummy_gtk[32];
+ u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, dummy_gtk[32];
size_t gtk_len, kde_len;
struct wpa_group *gsm = sm->group;
u8 *wpa_ie;
int wpa_ie_len, secure, gtkidx, encr = 0;
+ u8 *wpa_ie_buf = NULL;
SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk);
sm->TimeoutEvt = FALSE;
@@ -3177,6 +3179,35 @@
wpa_ie = wpa_ie + wpa_ie[1] + 2;
wpa_ie_len = wpa_ie[1] + 2;
}
+#ifdef CONFIG_TESTING_OPTIONS
+ if (sm->wpa_auth->conf.rsnxe_override_eapol_len) {
+ u8 *obuf = sm->wpa_auth->conf.rsnxe_override_eapol;
+ size_t olen = sm->wpa_auth->conf.rsnxe_override_eapol_len;
+ const u8 *rsnxe;
+
+ wpa_hexdump(MSG_DEBUG,
+ "TESTING: wpa_ie before RSNXE EAPOL override",
+ wpa_ie, wpa_ie_len);
+ wpa_ie_buf = os_malloc(wpa_ie_len + olen);
+ if (!wpa_ie_buf)
+ return;
+ os_memcpy(wpa_ie_buf, wpa_ie, wpa_ie_len);
+ wpa_ie = wpa_ie_buf;
+ rsnxe = get_ie(wpa_ie, wpa_ie_len, WLAN_EID_RSNX);
+ if (rsnxe) {
+ u8 rsnxe_len = 2 + rsnxe[1];
+
+ os_memmove((void *) rsnxe, rsnxe + rsnxe_len,
+ wpa_ie_len - (rsnxe - wpa_ie) - rsnxe_len);
+ wpa_ie_len -= rsnxe_len;
+ }
+ os_memcpy(wpa_ie + wpa_ie_len, obuf, olen);
+ wpa_ie_len += olen;
+ wpa_hexdump(MSG_DEBUG,
+ "TESTING: wpa_ie after RSNXE EAPOL override",
+ wpa_ie, wpa_ie_len);
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
"sending 3/4 msg of 4-Way Handshake");
if (sm->wpa == WPA_VERSION_WPA2) {
@@ -3191,7 +3222,7 @@
* of GTK in the BSS.
*/
if (random_get_bytes(dummy_gtk, gtk_len) < 0)
- return;
+ goto done;
gtk = dummy_gtk;
}
gtkidx = gsm->GN;
@@ -3234,7 +3265,7 @@
#endif /* CONFIG_P2P */
kde = os_malloc(kde_len);
if (kde == NULL)
- return;
+ goto done;
pos = kde;
os_memcpy(pos, wpa_ie, wpa_ie_len);
@@ -3249,8 +3280,7 @@
if (res < 0) {
wpa_printf(MSG_ERROR, "FT: Failed to insert "
"PMKR1Name into RSN IE in EAPOL-Key data");
- os_free(kde);
- return;
+ goto done;
}
pos -= wpa_ie_len;
pos += elen;
@@ -3264,10 +3294,8 @@
gtk, gtk_len);
}
pos = ieee80211w_kde_add(sm, pos);
- if (ocv_oci_add(sm, &pos) < 0) {
- os_free(kde);
- return;
- }
+ if (ocv_oci_add(sm, &pos) < 0)
+ goto done;
#ifdef CONFIG_IEEE80211R_AP
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
@@ -3293,8 +3321,7 @@
if (res < 0) {
wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE "
"into EAPOL-Key Key Data");
- os_free(kde);
- return;
+ goto done;
}
pos += res;
@@ -3331,7 +3358,9 @@
WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
WPA_KEY_INFO_KEY_TYPE,
_rsc, sm->ANonce, kde, pos - kde, 0, encr);
+done:
os_free(kde);
+ os_free(wpa_ie_buf);
}
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index f627838..933a4b8 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -219,6 +219,8 @@
double corrupt_gtk_rekey_mic_probability;
u8 own_ie_override[MAX_OWN_IE_OVERRIDE];
size_t own_ie_override_len;
+ u8 rsnxe_override_eapol[MAX_OWN_IE_OVERRIDE];
+ size_t rsnxe_override_eapol_len;
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_P2P
u8 ip_addr_go[4];
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index ddab950..7fb0923 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -118,6 +118,14 @@
wpabuf_head(conf->own_ie_override),
wconf->own_ie_override_len);
}
+ if (conf->rsnxe_override_eapol &&
+ wpabuf_len(conf->rsnxe_override_eapol) <= MAX_OWN_IE_OVERRIDE) {
+ wconf->rsnxe_override_eapol_len =
+ wpabuf_len(conf->rsnxe_override_eapol);
+ os_memcpy(wconf->rsnxe_override_eapol,
+ wpabuf_head(conf->rsnxe_override_eapol),
+ wconf->rsnxe_override_eapol_len);
+ }
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_P2P
os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4);
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index 33caeaf..175b9fc 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -1417,6 +1417,7 @@
data->count++;
wps_registrar_wps_cancel(hapd->wps->registrar);
ap_for_each_sta(hapd, ap_sta_wps_cancel, NULL);
+ wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_CANCEL);
}
return 0;
diff --git a/src/common/common_module_tests.c b/src/common/common_module_tests.c
index fb0cf43..7694c96 100644
--- a/src/common/common_module_tests.c
+++ b/src/common/common_module_tests.c
@@ -341,71 +341,71 @@
struct wpabuf *buf = NULL;
struct crypto_bignum *mask = NULL;
const u8 pwe_19_x[32] = {
- 0x19, 0xd3, 0x37, 0xc9, 0x30, 0x79, 0x2b, 0x47,
- 0x2b, 0x14, 0x5f, 0xc1, 0x5b, 0x98, 0x64, 0x0a,
- 0x0e, 0x7d, 0x3b, 0xb0, 0x7d, 0xc0, 0xad, 0xee,
- 0x6f, 0xc9, 0xdf, 0x75, 0xde, 0xc2, 0xd6, 0x94
+ 0xc9, 0x30, 0x49, 0xb9, 0xe6, 0x40, 0x00, 0xf8,
+ 0x48, 0x20, 0x16, 0x49, 0xe9, 0x99, 0xf2, 0xb5,
+ 0xc2, 0x2d, 0xea, 0x69, 0xb5, 0x63, 0x2c, 0x9d,
+ 0xf4, 0xd6, 0x33, 0xb8, 0xaa, 0x1f, 0x6c, 0x1e
};
const u8 pwe_19_y[32] = {
- 0xb7, 0x8a, 0x02, 0x39, 0x20, 0x29, 0xe7, 0xf4,
- 0x52, 0x41, 0x3d, 0x35, 0x8c, 0x88, 0xd9, 0x16,
- 0xc8, 0x90, 0xba, 0x40, 0xd9, 0x93, 0xe3, 0x2d,
- 0xd0, 0x0f, 0xfb, 0x58, 0xee, 0x62, 0x74, 0x98
+ 0x73, 0x63, 0x4e, 0x94, 0xb5, 0x3d, 0x82, 0xe7,
+ 0x38, 0x3a, 0x8d, 0x25, 0x81, 0x99, 0xd9, 0xdc,
+ 0x1a, 0x5e, 0xe8, 0x26, 0x9d, 0x06, 0x03, 0x82,
+ 0xcc, 0xbf, 0x33, 0xe6, 0x14, 0xff, 0x59, 0xa0
};
const u8 pwe_15[384] = {
- 0x59, 0x00, 0x9a, 0x32, 0xbb, 0x37, 0x84, 0x60,
- 0x27, 0xeb, 0x70, 0x20, 0x57, 0x34, 0xf1, 0xb4,
- 0xde, 0x1b, 0x48, 0xfc, 0x0e, 0xa5, 0xb8, 0x65,
- 0xb1, 0xa0, 0xd4, 0xb9, 0x42, 0x1d, 0x6d, 0xdf,
- 0x8b, 0x86, 0xeb, 0x4a, 0x2c, 0x2e, 0x38, 0x06,
- 0x52, 0xae, 0x67, 0x39, 0xed, 0x7d, 0x0c, 0xd0,
- 0xea, 0x30, 0x6e, 0x50, 0xe7, 0xb1, 0x8d, 0x91,
- 0xf0, 0x05, 0x1f, 0x16, 0xf5, 0x45, 0xa7, 0x37,
- 0x21, 0x0d, 0x8a, 0x69, 0x9a, 0xd1, 0xf1, 0x8c,
- 0x2b, 0xbb, 0xd8, 0x21, 0xa2, 0x8f, 0xcc, 0xd1,
- 0x35, 0x98, 0x66, 0xf3, 0x3c, 0x03, 0xba, 0x70,
- 0x72, 0x4e, 0xe4, 0x23, 0xb5, 0x2e, 0x96, 0x5f,
- 0xdd, 0xd1, 0xae, 0x71, 0xb1, 0xc1, 0x4b, 0x69,
- 0x4e, 0x60, 0x0a, 0x08, 0x02, 0xa1, 0x6e, 0x80,
- 0x68, 0x0a, 0xe7, 0x97, 0x9f, 0x5b, 0xbf, 0xa8,
- 0x77, 0xda, 0x5b, 0x26, 0x13, 0x0a, 0xab, 0x92,
- 0x79, 0x87, 0xa3, 0x85, 0x78, 0x74, 0xae, 0xae,
- 0x01, 0xf0, 0x31, 0x8a, 0xc3, 0x96, 0xce, 0xaa,
- 0x57, 0xbf, 0xb3, 0x57, 0xce, 0x2d, 0x2d, 0x36,
- 0xda, 0x02, 0x5b, 0x12, 0xeb, 0xff, 0x13, 0x00,
- 0x9e, 0xf7, 0xae, 0xe0, 0x47, 0xa4, 0x5d, 0x0a,
- 0x88, 0x65, 0xbc, 0x66, 0x23, 0x3e, 0xf2, 0xf1,
- 0xa0, 0x64, 0x5c, 0x6b, 0xdc, 0x81, 0xe9, 0x3c,
- 0x46, 0x4f, 0x83, 0xcf, 0x9f, 0x55, 0x33, 0x8f,
- 0xaa, 0x60, 0x4b, 0xd7, 0x21, 0x73, 0x6b, 0xdb,
- 0x26, 0xad, 0x2f, 0xb7, 0xe2, 0x42, 0x56, 0x33,
- 0xdb, 0xd6, 0xb2, 0x3a, 0x7d, 0x75, 0x87, 0xda,
- 0x86, 0xc4, 0xe9, 0x41, 0x8d, 0x63, 0x19, 0x8e,
- 0x8b, 0x17, 0x95, 0xfe, 0x2b, 0x96, 0xa0, 0x38,
- 0xf1, 0xe2, 0x1d, 0x42, 0xa9, 0xe3, 0x8a, 0xa1,
- 0x61, 0x62, 0x10, 0xf8, 0xb3, 0xb2, 0x2c, 0x7b,
- 0xdf, 0xba, 0x74, 0xb2, 0x5b, 0xf6, 0xa9, 0xae,
- 0x1d, 0x21, 0x0d, 0xc0, 0x48, 0x20, 0xfc, 0x28,
- 0xf6, 0x22, 0xd2, 0xf6, 0x9c, 0x71, 0x3f, 0x9f,
- 0x32, 0xd6, 0xbb, 0x9b, 0xd3, 0x87, 0x25, 0xcf,
- 0x62, 0xd1, 0x68, 0xba, 0x55, 0x3b, 0x74, 0x2b,
- 0x1d, 0x5a, 0xe4, 0x94, 0x59, 0x3b, 0x13, 0x21,
- 0x15, 0x87, 0x3b, 0x09, 0x0e, 0xcf, 0x35, 0x60,
- 0x04, 0xa8, 0xde, 0xa1, 0x09, 0xca, 0xb8, 0x35,
- 0x1e, 0x16, 0x61, 0xed, 0xa1, 0x1f, 0x8c, 0x92,
- 0x83, 0xa5, 0x27, 0x92, 0xf2, 0x80, 0xc3, 0xcb,
- 0xdd, 0x3c, 0x0c, 0xf5, 0x8d, 0x69, 0xb3, 0xe4,
- 0xd5, 0x49, 0x4d, 0x62, 0xcb, 0xb8, 0xe3, 0x9f,
- 0x89, 0xb5, 0x57, 0xff, 0xef, 0x12, 0x37, 0x05,
- 0xb6, 0x35, 0xe5, 0xc6, 0xd9, 0x23, 0xe2, 0xeb,
- 0xe4, 0x0d, 0x1a, 0x30, 0x8f, 0x73, 0x70, 0x3a,
- 0xef, 0x5a, 0xd1, 0x8c, 0x18, 0x34, 0x1e, 0xf0,
- 0xb9, 0x08, 0x57, 0xab, 0xcb, 0x5c, 0x87, 0x10
+ 0x69, 0x68, 0x73, 0x65, 0x8f, 0x65, 0x31, 0x42,
+ 0x9f, 0x97, 0x39, 0x6f, 0xb8, 0x5f, 0x89, 0xe1,
+ 0xfc, 0xd2, 0xf6, 0x92, 0x19, 0xa9, 0x0e, 0x82,
+ 0x2f, 0xf7, 0xf4, 0xbc, 0x0b, 0xd8, 0xa7, 0x9f,
+ 0xf0, 0x80, 0x35, 0x31, 0x6f, 0xca, 0xe1, 0xa5,
+ 0x39, 0x77, 0xdc, 0x11, 0x2b, 0x0b, 0xfe, 0x2e,
+ 0x6f, 0x65, 0x6d, 0xc7, 0xd4, 0xa4, 0x5b, 0x08,
+ 0x1f, 0xd9, 0xbb, 0xe2, 0x22, 0x85, 0x31, 0x81,
+ 0x79, 0x70, 0xbe, 0xa1, 0x66, 0x58, 0x4a, 0x09,
+ 0x3c, 0x57, 0x34, 0x3c, 0x9d, 0x57, 0x8f, 0x42,
+ 0x58, 0xd0, 0x39, 0x81, 0xdb, 0x8f, 0x79, 0xa2,
+ 0x1b, 0x01, 0xcd, 0x27, 0xc9, 0xae, 0xcf, 0xcb,
+ 0x9c, 0xdb, 0x1f, 0x84, 0xb8, 0x88, 0x4e, 0x8f,
+ 0x50, 0x66, 0xb4, 0x29, 0x83, 0x1e, 0xb9, 0x89,
+ 0x0c, 0xa5, 0x47, 0x21, 0xba, 0x10, 0xd5, 0xaa,
+ 0x1a, 0x80, 0xce, 0xf1, 0x4c, 0xad, 0x16, 0xda,
+ 0x57, 0xb2, 0x41, 0x8a, 0xbe, 0x4b, 0x8c, 0xb0,
+ 0xb2, 0xeb, 0xf7, 0xa8, 0x0e, 0x3e, 0xcf, 0x22,
+ 0x8f, 0xd8, 0xb6, 0xdb, 0x79, 0x9c, 0x9b, 0x80,
+ 0xaf, 0xd7, 0x14, 0xad, 0x51, 0x82, 0xf4, 0x64,
+ 0xb6, 0x3f, 0x4c, 0x6c, 0xe5, 0x3f, 0xaa, 0x6f,
+ 0xbf, 0x3d, 0xc2, 0x3f, 0x77, 0xfd, 0xcb, 0xe1,
+ 0x9c, 0xe3, 0x1e, 0x8a, 0x0e, 0x97, 0xe2, 0x2b,
+ 0xe2, 0xdd, 0x37, 0x39, 0x88, 0xc2, 0x8e, 0xbe,
+ 0xfa, 0xac, 0x3d, 0x5b, 0x62, 0x2e, 0x1e, 0x74,
+ 0xa0, 0x9a, 0xf8, 0xed, 0xfa, 0xe1, 0xce, 0x9c,
+ 0xab, 0xbb, 0xdc, 0x36, 0xb1, 0x28, 0x46, 0x3c,
+ 0x7e, 0xa8, 0xbd, 0xb9, 0x36, 0x4c, 0x26, 0x75,
+ 0xe0, 0x17, 0x73, 0x1f, 0xe0, 0xfe, 0xf6, 0x49,
+ 0xfa, 0xa0, 0x45, 0xf4, 0x44, 0x05, 0x20, 0x27,
+ 0x25, 0xc2, 0x99, 0xde, 0x27, 0x8b, 0x70, 0xdc,
+ 0x54, 0x60, 0x90, 0x02, 0x1e, 0x29, 0x97, 0x9a,
+ 0xc4, 0xe7, 0xb6, 0xf5, 0x8b, 0xae, 0x7c, 0x34,
+ 0xaa, 0xef, 0x9b, 0xc6, 0x30, 0xf2, 0x80, 0x8d,
+ 0x80, 0x78, 0xc2, 0x55, 0x63, 0xa0, 0xa1, 0x38,
+ 0x70, 0xfb, 0xf4, 0x74, 0x8d, 0xcd, 0x87, 0x90,
+ 0xb4, 0x54, 0xc3, 0x75, 0xdf, 0x10, 0xc5, 0xb6,
+ 0xb2, 0x08, 0x59, 0x61, 0xe6, 0x68, 0xa5, 0x82,
+ 0xf8, 0x8f, 0x47, 0x30, 0x43, 0xb4, 0xdc, 0x31,
+ 0xfc, 0xbc, 0x69, 0xe7, 0xb4, 0x94, 0xb0, 0x6a,
+ 0x60, 0x59, 0x80, 0x2e, 0xd3, 0xa4, 0xe8, 0x97,
+ 0xa2, 0xa3, 0xc9, 0x08, 0x4b, 0x27, 0x6c, 0xc1,
+ 0x37, 0xe8, 0xfc, 0x5c, 0xe2, 0x54, 0x30, 0x3e,
+ 0xf8, 0xfe, 0xa2, 0xfc, 0xbb, 0xbd, 0x88, 0x6c,
+ 0x92, 0xa3, 0x2a, 0x40, 0x7a, 0x2c, 0x22, 0x38,
+ 0x8c, 0x86, 0x86, 0xfe, 0xb9, 0xd4, 0x6b, 0xd6,
+ 0x47, 0x88, 0xa7, 0xf6, 0x8e, 0x0f, 0x14, 0xad,
+ 0x1e, 0xac, 0xcf, 0x33, 0x01, 0x99, 0xc1, 0x62
};
int pt_groups[] = { 19, 20, 21, 25, 26, 28, 29, 30, 15, 0 };
struct sae_pt *pt_info, *pt;
- u8 addr1b[ETH_ALEN] = { 0x3b, 0x36, 0xc2, 0x8b, 0x83, 0x03 };
- u8 addr2b[ETH_ALEN] = { 0x58, 0x36, 0xc0, 0x64, 0x2d, 0x31 };
+ const u8 addr1b[ETH_ALEN] = { 0x00, 0x09, 0x5b, 0x66, 0xec, 0x1e };
+ const u8 addr2b[ETH_ALEN] = { 0x00, 0x0b, 0x6b, 0xd9, 0x02, 0x46 };
os_memset(&sae, 0, sizeof(sae));
buf = wpabuf_alloc(1000);
diff --git a/src/common/defs.h b/src/common/defs.h
index 4faf1c8..e2fa4b2 100644
--- a/src/common/defs.h
+++ b/src/common/defs.h
@@ -416,6 +416,10 @@
CHAN_WIDTH_80,
CHAN_WIDTH_80P80,
CHAN_WIDTH_160,
+ CHAN_WIDTH_2160,
+ CHAN_WIDTH_4320,
+ CHAN_WIDTH_6480,
+ CHAN_WIDTH_8640,
CHAN_WIDTH_UNKNOWN
};
diff --git a/src/common/dpp.c b/src/common/dpp.c
index 44cb910..7542c66 100644
--- a/src/common/dpp.c
+++ b/src/common/dpp.c
@@ -33,6 +33,8 @@
#include "dpp.h"
+static const char * dpp_netrole_str(enum dpp_netrole netrole);
+
#ifdef CONFIG_TESTING_OPTIONS
enum dpp_test_behavior dpp_test = DPP_TEST_DISABLED;
u8 dpp_pkex_own_mac_override[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
@@ -830,6 +832,8 @@
return "QRCODE";
case DPP_BOOTSTRAP_PKEX:
return "PKEX";
+ case DPP_BOOTSTRAP_NFC_URI:
+ return "NFC-URI";
}
return "??";
}
@@ -1007,8 +1011,7 @@
if (!end)
return -1;
- data = base64_decode((const unsigned char *) info, end - info,
- &data_len);
+ data = base64_decode(info, end - info, &data_len);
if (!data) {
wpa_printf(MSG_DEBUG,
"DPP: Invalid base64 encoding on URI public-key");
@@ -1182,17 +1185,6 @@
}
-struct dpp_bootstrap_info * dpp_parse_qr_code(const char *uri)
-{
- struct dpp_bootstrap_info *bi;
-
- bi = dpp_parse_uri(uri);
- if (bi)
- bi->type = DPP_BOOTSTRAP_QR_CODE;
- return bi;
-}
-
-
static void dpp_debug_print_key(const char *title, EVP_PKEY *key)
{
EC_KEY *eckey;
@@ -1482,7 +1474,7 @@
char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
const u8 *privkey, size_t privkey_len)
{
- unsigned char *base64 = NULL;
+ char *base64 = NULL;
char *pos, *end;
size_t len;
struct wpabuf *der = NULL;
@@ -1528,7 +1520,7 @@
der = NULL;
if (!base64)
goto fail;
- pos = (char *) base64;
+ pos = base64;
end = pos + len;
for (;;) {
pos = os_strchr(pos, '\n');
@@ -1536,7 +1528,7 @@
break;
os_memmove(pos, pos + 1, end - pos);
}
- return (char *) base64;
+ return base64;
fail:
os_free(base64);
wpabuf_free(der);
@@ -2541,13 +2533,13 @@
struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth,
- const char *name, int netrole_ap,
+ const char *name,
+ enum dpp_netrole netrole,
const char *mud_url, int *opclasses)
{
- size_t len, nlen;
+ size_t len, name_len;
const char *tech = "infra";
const char *dpp_name;
- char *nbuf;
struct wpabuf *buf, *json;
#ifdef CONFIG_TESTING_OPTIONS
@@ -2560,39 +2552,38 @@
#endif /* CONFIG_TESTING_OPTIONS */
dpp_name = name ? name : "Test";
- len = os_strlen(dpp_name);
- nlen = len * 6 + 1;
- nbuf = os_malloc(nlen);
- if (!nbuf)
- return NULL;
- json_escape_string(nbuf, nlen, dpp_name, len);
+ name_len = os_strlen(dpp_name);
- len = 100 + os_strlen(nbuf) + int_array_len(opclasses) * 4;
+ len = 100 + name_len * 6 + 1 + int_array_len(opclasses) * 4;
if (mud_url && mud_url[0])
len += 10 + os_strlen(mud_url);
json = wpabuf_alloc(len);
- if (!json) {
- os_free(nbuf);
+ if (!json)
+ return NULL;
+
+ json_start_object(json, NULL);
+ if (json_add_string_escape(json, "name", dpp_name, name_len) < 0) {
+ wpabuf_free(json);
return NULL;
}
-
- wpabuf_printf(json,
- "{\"name\":\"%s\","
- "\"wi-fi_tech\":\"%s\","
- "\"netRole\":\"%s\"",
- nbuf, tech, netrole_ap ? "ap" : "sta");
- if (mud_url && mud_url[0])
- wpabuf_printf(json, ",\"mudurl\":\"%s\"", mud_url);
+ json_value_sep(json);
+ json_add_string(json, "wi-fi_tech", tech);
+ json_value_sep(json);
+ json_add_string(json, "netRole", dpp_netrole_str(netrole));
+ if (mud_url && mud_url[0]) {
+ json_value_sep(json);
+ json_add_string(json, "mudurl", mud_url);
+ }
if (opclasses) {
int i;
- wpabuf_put_str(json, ",\"bandSupport\":[");
+ json_value_sep(json);
+ json_start_array(json, "bandSupport");
for (i = 0; opclasses[i]; i++)
wpabuf_printf(json, "%s%u", i ? "," : "", opclasses[i]);
- wpabuf_put_str(json, "]");
+ json_end_array(json);
}
- wpabuf_put_str(json, "}");
- os_free(nbuf);
+ json_end_object(json);
buf = dpp_build_conf_req(auth, wpabuf_head(json));
wpabuf_free(json);
@@ -4435,6 +4426,16 @@
#endif /* CONFIG_TESTING_OPTIONS */
}
+ pos = os_strstr(cmd, " ssid_charset=");
+ if (pos) {
+ if (conf_ap) {
+ wpa_printf(MSG_INFO,
+ "DPP: ssid64 option (ssid_charset param) not allowed for AP enrollee");
+ goto fail;
+ }
+ conf->ssid_charset = atoi(pos + 14);
+ }
+
pos = os_strstr(cmd, " pass=");
if (pos) {
size_t pass_len;
@@ -4637,7 +4638,6 @@
struct dpp_configuration *conf, size_t tailroom)
{
struct wpabuf *buf;
- char ssid[6 * sizeof(conf->ssid) + 1];
#ifdef CONFIG_TESTING_OPTIONS
if (auth->discovery_override)
@@ -4647,21 +4647,35 @@
buf = wpabuf_alloc(200 + tailroom);
if (!buf)
return NULL;
- wpabuf_put_str(buf, "{\"wi-fi_tech\":\"infra\",\"discovery\":");
+ json_start_object(buf, NULL);
+ json_add_string(buf, "wi-fi_tech", "infra");
+ json_value_sep(buf);
#ifdef CONFIG_TESTING_OPTIONS
if (auth->discovery_override) {
wpa_printf(MSG_DEBUG, "DPP: TESTING - discovery override: '%s'",
auth->discovery_override);
+ wpabuf_put_str(buf, "\"discovery\":");
wpabuf_put_str(buf, auth->discovery_override);
- wpabuf_put_u8(buf, ',');
+ json_value_sep(buf);
return buf;
}
#endif /* CONFIG_TESTING_OPTIONS */
- wpabuf_put_str(buf, "{\"ssid\":\"");
- json_escape_string(ssid, sizeof(ssid),
- (const char *) conf->ssid, conf->ssid_len);
- wpabuf_put_str(buf, ssid);
- wpabuf_put_str(buf, "\"},");
+ json_start_object(buf, "discovery");
+ if (((!conf->ssid_charset || auth->peer_version < 2) &&
+ json_add_string_escape(buf, "ssid", conf->ssid,
+ conf->ssid_len) < 0) ||
+ ((conf->ssid_charset && auth->peer_version >= 2) &&
+ json_add_base64url(buf, "ssid64", conf->ssid,
+ conf->ssid_len) < 0)) {
+ wpabuf_free(buf);
+ return NULL;
+ }
+ if (conf->ssid_charset > 0) {
+ json_value_sep(buf);
+ json_add_int(buf, "ssid_charset", conf->ssid_charset);
+ }
+ json_end_object(buf);
+ json_value_sep(buf);
return buf;
}
@@ -4672,37 +4686,32 @@
{
struct wpabuf *pub;
const u8 *pos;
- char *x = NULL, *y = NULL;
int ret = -1;
pub = dpp_get_pubkey_point(key, 0);
if (!pub)
goto fail;
- pos = wpabuf_head(pub);
- x = (char *) base64_url_encode(pos, curve->prime_len, NULL, 0);
- pos += curve->prime_len;
- y = (char *) base64_url_encode(pos, curve->prime_len, NULL, 0);
- if (!x || !y)
- goto fail;
- wpabuf_put_str(buf, "\"");
- wpabuf_put_str(buf, name);
- wpabuf_put_str(buf, "\":{\"kty\":\"EC\",\"crv\":\"");
- wpabuf_put_str(buf, curve->jwk_crv);
- wpabuf_put_str(buf, "\",\"x\":\"");
- wpabuf_put_str(buf, x);
- wpabuf_put_str(buf, "\",\"y\":\"");
- wpabuf_put_str(buf, y);
+ json_start_object(buf, name);
+ json_add_string(buf, "kty", "EC");
+ json_value_sep(buf);
+ json_add_string(buf, "crv", curve->jwk_crv);
+ json_value_sep(buf);
+ pos = wpabuf_head(pub);
+ if (json_add_base64url(buf, "x", pos, curve->prime_len) < 0)
+ goto fail;
+ json_value_sep(buf);
+ pos += curve->prime_len;
+ if (json_add_base64url(buf, "y", pos, curve->prime_len) < 0)
+ goto fail;
if (kid) {
- wpabuf_put_str(buf, "\",\"kid\":\"");
- wpabuf_put_str(buf, kid);
+ json_value_sep(buf);
+ json_add_string(buf, "kid", kid);
}
- wpabuf_put_str(buf, "\"}");
+ json_end_object(buf);
ret = 0;
fail:
wpabuf_free(pub);
- os_free(x);
- os_free(y);
return ret;
}
@@ -4711,23 +4720,15 @@
struct dpp_configuration *conf)
{
if (conf->passphrase && os_strlen(conf->passphrase) < 64) {
- char pass[63 * 6 + 1];
-
- json_escape_string(pass, sizeof(pass), conf->passphrase,
- os_strlen(conf->passphrase));
- wpabuf_put_str(buf, "\"pass\":\"");
- wpabuf_put_str(buf, pass);
- wpabuf_put_str(buf, "\"");
- os_memset(pass, 0, sizeof(pass));
+ json_add_string_escape(buf, "pass", conf->passphrase,
+ os_strlen(conf->passphrase));
} else if (conf->psk_set) {
char psk[2 * sizeof(conf->psk) + 1];
wpa_snprintf_hex(psk, sizeof(psk),
conf->psk, sizeof(conf->psk));
- wpabuf_put_str(buf, "\"psk_hex\":\"");
- wpabuf_put_str(buf, psk);
- wpabuf_put_str(buf, "\"");
- os_memset(psk, 0, sizeof(psk));
+ json_add_string(buf, "psk_hex", psk);
+ forced_memzero(psk, sizeof(psk));
}
}
@@ -4739,6 +4740,8 @@
return "sta";
case DPP_NETROLE_AP:
return "ap";
+ case DPP_NETROLE_CONFIGURATOR:
+ return "configurator";
default:
return "??";
}
@@ -4753,7 +4756,7 @@
char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL;
size_t tailroom;
const struct dpp_curve_params *curve;
- char jws_prot_hdr[100];
+ struct wpabuf *jws_prot_hdr;
size_t signed1_len, signed2_len, signed3_len;
struct wpabuf *dppcon = NULL;
unsigned char *signature = NULL;
@@ -4814,15 +4817,21 @@
auth->groups_override);
wpabuf_put_str(dppcon, "\"groups\":");
wpabuf_put_str(dppcon, auth->groups_override);
- wpabuf_put_u8(dppcon, ',');
+ json_value_sep(dppcon);
}
goto skip_groups;
}
#endif /* CONFIG_TESTING_OPTIONS */
- wpabuf_printf(dppcon, "{\"groups\":[{\"groupId\":\"%s\",",
- conf->group_id ? conf->group_id : "*");
- wpabuf_printf(dppcon, "\"netRole\":\"%s\"}],",
- dpp_netrole_str(conf->netrole));
+ json_start_object(dppcon, NULL);
+ json_start_array(dppcon, "groups");
+ json_start_object(dppcon, NULL);
+ json_add_string(dppcon, "groupId",
+ conf->group_id ? conf->group_id : "*");
+ json_value_sep(dppcon);
+ json_add_string(dppcon, "netRole", dpp_netrole_str(conf->netrole));
+ json_end_object(dppcon);
+ json_end_array(dppcon);
+ json_value_sep(dppcon);
#ifdef CONFIG_TESTING_OPTIONS
skip_groups:
#endif /* CONFIG_TESTING_OPTIONS */
@@ -4833,30 +4842,40 @@
}
if (conf->netaccesskey_expiry) {
struct os_tm tm;
+ char expiry[30];
if (os_gmtime(conf->netaccesskey_expiry, &tm) < 0) {
wpa_printf(MSG_DEBUG,
"DPP: Failed to generate expiry string");
goto fail;
}
- wpabuf_printf(dppcon,
- ",\"expiry\":\"%04u-%02u-%02uT%02u:%02u:%02uZ\"",
- tm.year, tm.month, tm.day,
- tm.hour, tm.min, tm.sec);
+ os_snprintf(expiry, sizeof(expiry),
+ "%04u-%02u-%02uT%02u:%02u:%02uZ",
+ tm.year, tm.month, tm.day,
+ tm.hour, tm.min, tm.sec);
+ json_value_sep(dppcon);
+ json_add_string(dppcon, "expiry", expiry);
}
- wpabuf_put_u8(dppcon, '}');
+ json_end_object(dppcon);
wpa_printf(MSG_DEBUG, "DPP: dppCon: %s",
(const char *) wpabuf_head(dppcon));
- os_snprintf(jws_prot_hdr, sizeof(jws_prot_hdr),
- "{\"typ\":\"dppCon\",\"kid\":\"%s\",\"alg\":\"%s\"}",
- auth->conf->kid, curve->jws_alg);
- signed1 = (char *) base64_url_encode((unsigned char *) jws_prot_hdr,
- os_strlen(jws_prot_hdr),
- &signed1_len, 0);
- signed2 = (char *) base64_url_encode(wpabuf_head(dppcon),
- wpabuf_len(dppcon),
- &signed2_len, 0);
+ jws_prot_hdr = wpabuf_alloc(100);
+ if (!jws_prot_hdr)
+ goto fail;
+ json_start_object(jws_prot_hdr, NULL);
+ json_add_string(jws_prot_hdr, "typ", "dppCon");
+ json_value_sep(jws_prot_hdr);
+ json_add_string(jws_prot_hdr, "kid", auth->conf->kid);
+ json_value_sep(jws_prot_hdr);
+ json_add_string(jws_prot_hdr, "alg", curve->jws_alg);
+ json_end_object(jws_prot_hdr);
+ signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr),
+ wpabuf_len(jws_prot_hdr),
+ &signed1_len);
+ wpabuf_free(jws_prot_hdr);
+ signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon),
+ &signed2_len);
if (!signed1 || !signed2)
goto fail;
@@ -4906,8 +4925,7 @@
signature_len = 2 * curve->prime_len;
wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)",
signature, signature_len);
- signed3 = (char *) base64_url_encode(signature, signature_len,
- &signed3_len, 0);
+ signed3 = base64_url_encode(signature, signature_len, &signed3_len);
if (!signed3)
goto fail;
@@ -4925,10 +4943,12 @@
akm_str = dpp_akm_selector_str(akm);
else
akm_str = dpp_akm_str(akm);
- wpabuf_printf(buf, "\"cred\":{\"akm\":\"%s\",", akm_str);
+ json_start_object(buf, "cred");
+ json_add_string(buf, "akm", akm_str);
+ json_value_sep(buf);
if (incl_legacy) {
dpp_build_legacy_cred_params(buf, conf);
- wpabuf_put_str(buf, ",");
+ json_value_sep(buf);
}
wpabuf_put_str(buf, "\"signedConnector\":\"");
wpabuf_put_str(buf, signed1);
@@ -4936,14 +4956,16 @@
wpabuf_put_str(buf, signed2);
wpabuf_put_u8(buf, '.');
wpabuf_put_str(buf, signed3);
- wpabuf_put_str(buf, "\",");
+ wpabuf_put_str(buf, "\"");
+ json_value_sep(buf);
if (dpp_build_jwk(buf, "csign", auth->conf->csign, auth->conf->kid,
curve) < 0) {
wpa_printf(MSG_DEBUG, "DPP: Failed to build csign JWK");
goto fail;
}
- wpabuf_put_str(buf, "}}");
+ json_end_object(buf);
+ json_end_object(buf);
wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object",
wpabuf_head(buf), wpabuf_len(buf));
@@ -4980,9 +5002,12 @@
akm_str = dpp_akm_selector_str(conf->akm);
else
akm_str = dpp_akm_str(conf->akm);
- wpabuf_printf(buf, "\"cred\":{\"akm\":\"%s\",", akm_str);
+ json_start_object(buf, "cred");
+ json_add_string(buf, "akm", akm_str);
+ json_value_sep(buf);
dpp_build_legacy_cred_params(buf, conf);
- wpabuf_put_str(buf, "}}");
+ json_end_object(buf);
+ json_end_object(buf);
wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object (legacy)",
wpabuf_head(buf), wpabuf_len(buf));
@@ -4992,9 +5017,10 @@
static struct wpabuf *
-dpp_build_conf_obj(struct dpp_authentication *auth, int ap, int idx)
+dpp_build_conf_obj(struct dpp_authentication *auth, enum dpp_netrole netrole,
+ int idx)
{
- struct dpp_configuration *conf;
+ struct dpp_configuration *conf = NULL;
#ifdef CONFIG_TESTING_OPTIONS
if (auth->config_obj_override) {
@@ -5006,17 +5032,22 @@
}
#endif /* CONFIG_TESTING_OPTIONS */
- if (idx == 0)
- conf = ap ? auth->conf_ap : auth->conf_sta;
- else if (idx == 1)
- conf = ap ? auth->conf2_ap : auth->conf2_sta;
- else
- conf = NULL;
+ if (idx == 0) {
+ if (netrole == DPP_NETROLE_STA)
+ conf = auth->conf_sta;
+ else if (netrole == DPP_NETROLE_AP)
+ conf = auth->conf_ap;
+ } else if (idx == 1) {
+ if (netrole == DPP_NETROLE_STA)
+ conf = auth->conf2_sta;
+ else if (netrole == DPP_NETROLE_AP)
+ conf = auth->conf2_ap;
+ }
if (!conf) {
if (idx == 0)
wpa_printf(MSG_DEBUG,
"DPP: No configuration available for Enrollee(%s) - reject configuration request",
- ap ? "ap" : "sta");
+ dpp_netrole_str(netrole));
return NULL;
}
@@ -5028,7 +5059,7 @@
static struct wpabuf *
dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce,
- u16 e_nonce_len, int ap)
+ u16 e_nonce_len, enum dpp_netrole netrole)
{
struct wpabuf *conf, *conf2 = NULL;
size_t clear_len, attr_len;
@@ -5038,11 +5069,11 @@
size_t len[1];
enum dpp_status_error status;
- conf = dpp_build_conf_obj(auth, ap, 0);
+ conf = dpp_build_conf_obj(auth, netrole, 0);
if (conf) {
wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON",
wpabuf_head(conf), wpabuf_len(conf));
- conf2 = dpp_build_conf_obj(auth, ap, 1);
+ conf2 = dpp_build_conf_obj(auth, netrole, 1);
}
status = conf ? DPP_STATUS_OK : DPP_STATUS_CONFIGURE_FAILURE;
auth->conf_resp_status = status;
@@ -5053,7 +5084,8 @@
clear_len += 4 + wpabuf_len(conf);
if (conf2)
clear_len += 4 + wpabuf_len(conf2);
- if (auth->peer_version >= 2 && auth->send_conn_status && !ap)
+ if (auth->peer_version >= 2 && auth->send_conn_status &&
+ netrole == DPP_NETROLE_STA)
clear_len += 4;
clear = wpabuf_alloc(clear_len);
attr_len = 4 + 1 + 4 + clear_len + AES_BLOCK_SIZE;
@@ -5111,7 +5143,8 @@
"DPP: Second Config Object available, but peer does not support more than one");
}
- if (auth->peer_version >= 2 && auth->send_conn_status && !ap) {
+ if (auth->peer_version >= 2 && auth->send_conn_status &&
+ netrole == DPP_NETROLE_STA) {
wpa_printf(MSG_DEBUG, "DPP: sendConnStatus");
wpabuf_put_le16(clear, DPP_ATTR_SEND_CONN_STATUS);
wpabuf_put_le16(clear, 0);
@@ -5185,7 +5218,7 @@
size_t unwrapped_len = 0;
struct wpabuf *resp = NULL;
struct json_token *root = NULL, *token;
- int ap;
+ enum dpp_netrole netrole;
#ifdef CONFIG_TESTING_OPTIONS
if (dpp_test == DPP_TEST_STOP_AT_CONF_REQ) {
@@ -5283,9 +5316,11 @@
}
wpa_printf(MSG_DEBUG, "DPP: netRole = '%s'", token->string);
if (os_strcmp(token->string, "sta") == 0) {
- ap = 0;
+ netrole = DPP_NETROLE_STA;
} else if (os_strcmp(token->string, "ap") == 0) {
- ap = 1;
+ netrole = DPP_NETROLE_AP;
+ } else if (os_strcmp(token->string, "configurator") == 0) {
+ netrole = DPP_NETROLE_CONFIGURATOR;
} else {
wpa_printf(MSG_DEBUG, "DPP: Unsupported netRole '%s'",
token->string);
@@ -5319,7 +5354,7 @@
}
}
- resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, ap);
+ resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, netrole);
fail:
json_free(root);
@@ -5825,8 +5860,7 @@
ret = DPP_STATUS_INVALID_CONNECTOR;
goto fail;
}
- prot_hdr = base64_url_decode((const unsigned char *) pos,
- end - pos, &prot_hdr_len);
+ prot_hdr = base64_url_decode(pos, end - pos, &prot_hdr_len);
if (!prot_hdr) {
wpa_printf(MSG_DEBUG,
"DPP: Failed to base64url decode signedConnector JWS Protected Header");
@@ -5858,8 +5892,7 @@
goto fail;
}
signed_end = end - 1;
- info->payload = base64_url_decode((const unsigned char *) pos,
- end - pos, &info->payload_len);
+ info->payload = base64_url_decode(pos, end - pos, &info->payload_len);
if (!info->payload) {
wpa_printf(MSG_DEBUG,
"DPP: Failed to base64url decode signedConnector JWS Payload");
@@ -5870,8 +5903,7 @@
"DPP: signedConnector - JWS Payload",
info->payload, info->payload_len);
pos = end + 1;
- signature = base64_url_decode((const unsigned char *) pos,
- os_strlen(pos), &signature_len);
+ signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
if (!signature) {
wpa_printf(MSG_DEBUG,
"DPP: Failed to base64url decode signedConnector signature");
@@ -6126,6 +6158,7 @@
int ret = -1;
struct json_token *root, *token, *discovery, *cred;
struct dpp_config_obj *conf;
+ struct wpabuf *ssid64 = NULL;
root = json_parse((const char *) conf_obj, conf_obj_len);
if (!root)
@@ -6153,28 +6186,52 @@
goto fail;
}
- token = json_get_member(discovery, "ssid");
- if (!token || token->type != JSON_STRING) {
- dpp_auth_fail(auth, "No discovery::ssid string value found");
- goto fail;
- }
- wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid",
- token->string, os_strlen(token->string));
- if (os_strlen(token->string) > SSID_MAX_LEN) {
- dpp_auth_fail(auth, "Too long discovery::ssid string value");
- goto fail;
+ ssid64 = json_get_member_base64url(discovery, "ssid64");
+ if (ssid64) {
+ wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid64",
+ wpabuf_head(ssid64), wpabuf_len(ssid64));
+ if (wpabuf_len(ssid64) > SSID_MAX_LEN) {
+ dpp_auth_fail(auth, "Too long discovery::ssid64 value");
+ goto fail;
+ }
+ } else {
+ token = json_get_member(discovery, "ssid");
+ if (!token || token->type != JSON_STRING) {
+ dpp_auth_fail(auth,
+ "No discovery::ssid string value found");
+ goto fail;
+ }
+ wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid",
+ token->string, os_strlen(token->string));
+ if (os_strlen(token->string) > SSID_MAX_LEN) {
+ dpp_auth_fail(auth,
+ "Too long discovery::ssid string value");
+ goto fail;
+ }
}
if (auth->num_conf_obj == DPP_MAX_CONF_OBJ) {
wpa_printf(MSG_DEBUG,
"DPP: No room for this many Config Objects - ignore this one");
- json_free(root);
- return 0;
+ ret = 0;
+ goto fail;
}
conf = &auth->conf_obj[auth->num_conf_obj++];
- conf->ssid_len = os_strlen(token->string);
- os_memcpy(conf->ssid, token->string, conf->ssid_len);
+ if (ssid64) {
+ conf->ssid_len = wpabuf_len(ssid64);
+ os_memcpy(conf->ssid, wpabuf_head(ssid64), conf->ssid_len);
+ } else {
+ conf->ssid_len = os_strlen(token->string);
+ os_memcpy(conf->ssid, token->string, conf->ssid_len);
+ }
+
+ token = json_get_member(discovery, "ssid_charset");
+ if (token && token->type == JSON_NUMBER) {
+ conf->ssid_charset = token->number;
+ wpa_printf(MSG_DEBUG, "DPP: ssid_charset=%d",
+ conf->ssid_charset);
+ }
cred = json_get_member(root, "cred");
if (!cred || cred->type != JSON_OBJECT) {
@@ -6205,6 +6262,7 @@
wpa_printf(MSG_DEBUG, "DPP: JSON parsing completed successfully");
ret = 0;
fail:
+ wpabuf_free(ssid64);
json_free(root);
return ret;
}
@@ -6493,6 +6551,7 @@
size_t unwrapped_len = 0;
enum dpp_status_error ret = 256;
struct json_token *root = NULL, *token;
+ struct wpabuf *ssid64;
*ssid_len = 0;
*channel_list = NULL;
@@ -6567,12 +6626,12 @@
goto fail;
}
- token = json_get_member(root, "ssid");
- if (token && token->type == JSON_STRING &&
- os_strlen(token->string) <= SSID_MAX_LEN) {
- *ssid_len = os_strlen(token->string);
- os_memcpy(ssid, token->string, *ssid_len);
+ ssid64 = json_get_member_base64url(root, "ssid64");
+ if (ssid64 && wpabuf_len(ssid64) <= SSID_MAX_LEN) {
+ *ssid_len = wpabuf_len(ssid64);
+ os_memcpy(ssid, wpabuf_head(ssid64), *ssid_len);
}
+ wpabuf_free(ssid64);
token = json_get_member(root, "channelList");
if (token && token->type == JSON_STRING &&
@@ -6599,7 +6658,7 @@
const u8 *ssid, size_t ssid_len,
const char *channel_list)
{
- struct wpabuf *msg, *clear, *json;
+ struct wpabuf *msg = NULL, *clear = NULL, *json;
size_t nonce_len, clear_len, attr_len;
const u8 *addr[2];
size_t len[2];
@@ -6608,19 +6667,18 @@
json = wpabuf_alloc(1000);
if (!json)
return NULL;
- wpabuf_printf(json, "{\"result\":%d", result);
+ json_start_object(json, NULL);
+ json_add_int(json, "result", result);
if (ssid) {
- char ssid_str[6 * SSID_MAX_LEN + 1];
-
- wpabuf_put_str(json, ",\"ssid\":\"");
- json_escape_string(ssid_str, sizeof(ssid_str),
- (const char *) ssid, ssid_len);
- wpabuf_put_str(json, ssid_str);
- wpabuf_put_str(json, "\"");
+ json_value_sep(json);
+ if (json_add_base64url(json, "ssid64", ssid, ssid_len) < 0)
+ goto fail;
}
- if (channel_list)
- wpabuf_printf(json, ",\"channelList\":\"%s\"", channel_list);
- wpabuf_put_str(json, "}");
+ if (channel_list) {
+ json_value_sep(json);
+ json_add_string(json, "channelList", channel_list);
+ }
+ json_end_object(json);
wpa_hexdump_ascii(MSG_DEBUG, "DPP: connStatus JSON",
wpabuf_head(json), wpabuf_len(json));
@@ -6761,8 +6819,7 @@
goto fail;
}
- conf->kid = (char *) base64_url_encode(kid_hash, sizeof(kid_hash),
- NULL, 0);
+ conf->kid = base64_url_encode(kid_hash, sizeof(kid_hash), NULL);
if (!conf->kid)
goto fail;
out:
@@ -6808,8 +6865,11 @@
dpp_copy_csign(&auth->conf_obj[0], auth->conf->csign);
conf_obj = dpp_build_conf_obj(auth, ap, 0);
- if (!conf_obj)
+ if (!conf_obj) {
+ wpabuf_free(auth->conf_obj[0].c_sign_key);
+ auth->conf_obj[0].c_sign_key = NULL;
goto fail;
+ }
ret = dpp_parse_conf_obj(auth, wpabuf_head(conf_obj),
wpabuf_len(conf_obj));
fail:
@@ -7024,8 +7084,7 @@
wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the second dot (.)");
goto fail;
}
- own_conn = base64_url_decode((const unsigned char *) pos,
- end - pos, &own_conn_len);
+ own_conn = base64_url_decode(pos, end - pos, &own_conn_len);
if (!own_conn) {
wpa_printf(MSG_DEBUG,
"DPP: Failed to base64url decode own signedConnector JWS Payload");
@@ -8759,8 +8818,7 @@
wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s",
pos);
- signature = base64_url_decode((const unsigned char *) pos,
- os_strlen(pos), &signature_len);
+ signature = base64_url_decode(pos, os_strlen(pos), &signature_len);
if (!signature || signature_len == 0)
goto fail;
wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature",
@@ -8768,8 +8826,7 @@
signature[signature_len - 1] ^= 0x01;
wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature",
signature, signature_len);
- signed3 = (char *) base64_url_encode(signature, signature_len,
- &signed3_len, 0);
+ signed3 = base64_url_encode(signature, signature_len, &signed3_len);
if (!signed3)
goto fail;
os_memcpy(pos, signed3, signed3_len);
@@ -8917,10 +8974,30 @@
if (!dpp)
return NULL;
- bi = dpp_parse_qr_code(uri);
+ bi = dpp_parse_uri(uri);
if (!bi)
return NULL;
+ bi->type = DPP_BOOTSTRAP_QR_CODE;
+ bi->id = dpp_next_id(dpp);
+ dl_list_add(&dpp->bootstrap, &bi->list);
+ return bi;
+}
+
+
+struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp,
+ const char *uri)
+{
+ struct dpp_bootstrap_info *bi;
+
+ if (!dpp)
+ return NULL;
+
+ bi = dpp_parse_uri(uri);
+ if (!bi)
+ return NULL;
+
+ bi->type = DPP_BOOTSTRAP_NFC_URI;
bi->id = dpp_next_id(dpp);
dl_list_add(&dpp->bootstrap, &bi->list);
return bi;
@@ -8948,6 +9025,8 @@
bi->type = DPP_BOOTSTRAP_QR_CODE;
else if (os_strstr(cmd, "type=pkex"))
bi->type = DPP_BOOTSTRAP_PKEX;
+ else if (os_strstr(cmd, "type=nfc-uri"))
+ bi->type = DPP_BOOTSTRAP_NFC_URI;
else
goto fail;
diff --git a/src/common/dpp.h b/src/common/dpp.h
index abed3e4..cb788ae 100644
--- a/src/common/dpp.h
+++ b/src/common/dpp.h
@@ -106,6 +106,7 @@
enum dpp_bootstrap_type {
DPP_BOOTSTRAP_QR_CODE,
DPP_BOOTSTRAP_PKEX,
+ DPP_BOOTSTRAP_NFC_URI,
};
struct dpp_bootstrap_info {
@@ -164,11 +165,13 @@
enum dpp_netrole {
DPP_NETROLE_STA,
DPP_NETROLE_AP,
+ DPP_NETROLE_CONFIGURATOR,
};
struct dpp_configuration {
u8 ssid[32];
size_t ssid_len;
+ int ssid_charset;
enum dpp_akm akm;
enum dpp_netrole netrole;
@@ -248,6 +251,7 @@
char *connector; /* received signedConnector */
u8 ssid[SSID_MAX_LEN];
u8 ssid_len;
+ int ssid_charset;
char passphrase[64];
u8 psk[PMK_LEN];
int psk_set;
@@ -415,7 +419,6 @@
const char *chan_list);
int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac);
int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info);
-struct dpp_bootstrap_info * dpp_parse_qr_code(const char *uri);
char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
const u8 *privkey, size_t privkey_len);
struct hostapd_hw_modes;
@@ -438,7 +441,8 @@
struct wpabuf * dpp_build_conf_req(struct dpp_authentication *auth,
const char *json);
struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth,
- const char *name, int netrole_ap,
+ const char *name,
+ enum dpp_netrole netrole,
const char *mud_url, int *opclasses);
int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
const u8 *attr_start, size_t attr_len);
@@ -535,6 +539,8 @@
struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp,
const char *uri);
+struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp,
+ const char *uri);
int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd);
struct dpp_bootstrap_info *
dpp_bootstrap_get_id(struct dpp_global *dpp, unsigned int id);
diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c
index 1ad8d7c..19593a5 100644
--- a/src/common/hw_features_common.c
+++ b/src/common/hw_features_common.c
@@ -40,23 +40,32 @@
}
-struct hostapd_channel_data * hw_get_channel_freq(struct hostapd_hw_modes *mode,
- int freq, int *chan)
+struct hostapd_channel_data *
+hw_get_channel_freq(enum hostapd_hw_mode mode, int freq, int *chan,
+ struct hostapd_hw_modes *hw_features, int num_hw_features)
{
- int i;
+ int i, j;
if (chan)
*chan = 0;
- if (!mode)
+ if (!hw_features)
return NULL;
- for (i = 0; i < mode->num_channels; i++) {
- struct hostapd_channel_data *ch = &mode->channels[i];
- if (ch->freq == freq) {
- if (chan)
- *chan = ch->chan;
- return ch;
+ for (j = 0; j < num_hw_features; j++) {
+ struct hostapd_hw_modes *curr_mode = &hw_features[j];
+
+ if (curr_mode->mode != mode)
+ continue;
+ for (i = 0; i < curr_mode->num_channels; i++) {
+ struct hostapd_channel_data *ch =
+ &curr_mode->channels[i];
+
+ if (ch->freq == freq) {
+ if (chan)
+ *chan = ch->chan;
+ return ch;
+ }
}
}
@@ -74,29 +83,33 @@
}
-int hw_get_chan(struct hostapd_hw_modes *mode, int freq)
+int hw_get_chan(enum hostapd_hw_mode mode, int freq,
+ struct hostapd_hw_modes *hw_features, int num_hw_features)
{
int chan;
- hw_get_channel_freq(mode, freq, &chan);
+ hw_get_channel_freq(mode, freq, &chan, hw_features, num_hw_features);
return chan;
}
-int allowed_ht40_channel_pair(struct hostapd_hw_modes *mode, int pri_chan,
- int sec_chan)
+int allowed_ht40_channel_pair(enum hostapd_hw_mode mode,
+ struct hostapd_channel_data *p_chan,
+ struct hostapd_channel_data *s_chan)
{
int ok, first;
int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 140,
149, 157, 165, 184, 192 };
size_t k;
- struct hostapd_channel_data *p_chan, *s_chan;
- const int ht40_plus = pri_chan < sec_chan;
+ int ht40_plus, pri_chan, sec_chan;
- p_chan = hw_get_channel_chan(mode, pri_chan, NULL);
- if (!p_chan)
+ if (!p_chan || !s_chan)
return 0;
+ pri_chan = p_chan->chan;
+ sec_chan = s_chan->chan;
+
+ ht40_plus = pri_chan < sec_chan;
if (pri_chan == sec_chan || !sec_chan) {
if (chan_pri_allowed(p_chan))
@@ -107,13 +120,9 @@
return 0;
}
- s_chan = hw_get_channel_chan(mode, sec_chan, NULL);
- if (!s_chan)
- return 0;
-
wpa_printf(MSG_DEBUG,
- "HT40: control channel: %d secondary channel: %d",
- pri_chan, sec_chan);
+ "HT40: control channel: %d (%d MHz), secondary channel: %d (%d MHz)",
+ pri_chan, p_chan->freq, sec_chan, s_chan->freq);
/* Verify that HT40 secondary channel is an allowed 20 MHz
* channel */
@@ -131,7 +140,7 @@
* 2.4 GHz rules allow all cases where the secondary channel fits into
* the list of allowed channels (already checked above).
*/
- if (mode->mode != HOSTAPD_MODE_IEEE80211A)
+ if (mode != HOSTAPD_MODE_IEEE80211A)
return 1;
first = pri_chan < sec_chan ? pri_chan : sec_chan;
@@ -176,22 +185,19 @@
}
-int check_40mhz_5g(struct hostapd_hw_modes *mode,
- struct wpa_scan_results *scan_res, int pri_chan,
- int sec_chan)
+int check_40mhz_5g(struct wpa_scan_results *scan_res,
+ struct hostapd_channel_data *pri_chan,
+ struct hostapd_channel_data *sec_chan)
{
- int pri_freq, sec_freq, pri_bss, sec_bss;
+ int pri_bss, sec_bss;
int bss_pri_chan, bss_sec_chan;
size_t i;
int match;
- if (!mode || !scan_res || !pri_chan || !sec_chan ||
- pri_chan == sec_chan)
+ if (!scan_res || !pri_chan || !sec_chan ||
+ pri_chan->freq == sec_chan->freq)
return 0;
- pri_freq = hw_get_freq(mode, pri_chan);
- sec_freq = hw_get_freq(mode, sec_chan);
-
/*
* Switch PRI/SEC channels if Beacons were detected on selected SEC
* channel, but not on selected PRI channel.
@@ -199,9 +205,9 @@
pri_bss = sec_bss = 0;
for (i = 0; i < scan_res->num; i++) {
struct wpa_scan_res *bss = scan_res->res[i];
- if (bss->freq == pri_freq)
+ if (bss->freq == pri_chan->freq)
pri_bss++;
- else if (bss->freq == sec_freq)
+ else if (bss->freq == sec_chan->freq)
sec_bss++;
}
if (sec_bss && !pri_bss) {
@@ -219,8 +225,8 @@
for (i = 0; i < scan_res->num; i++) {
struct wpa_scan_res *bss = scan_res->res[i];
get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan);
- if (pri_chan == bss_pri_chan &&
- sec_chan == bss_sec_chan) {
+ if (pri_chan->chan == bss_pri_chan &&
+ sec_chan->chan == bss_sec_chan) {
match = 1;
break;
}
@@ -229,8 +235,8 @@
for (i = 0; i < scan_res->num; i++) {
struct wpa_scan_res *bss = scan_res->res[i];
get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan);
- if (pri_chan == bss_sec_chan &&
- sec_chan == bss_pri_chan) {
+ if (pri_chan->chan == bss_sec_chan &&
+ sec_chan->chan == bss_pri_chan) {
wpa_printf(MSG_INFO, "Switch own primary and "
"secondary channel due to BSS "
"overlap with " MACSTR,
@@ -273,12 +279,87 @@
}
+/*
+ * Returns:
+ * 0: no impact
+ * 1: overlapping BSS
+ * 2: overlapping BSS with 40 MHz intolerant advertisement
+ */
+int check_bss_coex_40mhz(struct wpa_scan_res *bss, int pri_freq, int sec_freq)
+{
+ int affected_start, affected_end;
+ struct ieee802_11_elems elems;
+ int pri_chan, sec_chan;
+ int pri = bss->freq;
+ int sec = pri;
+
+ if (pri_freq == sec_freq)
+ return 1;
+
+ affected_start = (pri_freq + sec_freq) / 2 - 25;
+ affected_end = (pri_freq + sec_freq) / 2 + 25;
+
+ /* Check for overlapping 20 MHz BSS */
+ if (check_20mhz_bss(bss, pri_freq, affected_start, affected_end)) {
+ wpa_printf(MSG_DEBUG, "Overlapping 20 MHz BSS is found");
+ return 1;
+ }
+
+ get_pri_sec_chan(bss, &pri_chan, &sec_chan);
+
+ if (sec_chan) {
+ if (sec_chan < pri_chan)
+ sec = pri - 20;
+ else
+ sec = pri + 20;
+ }
+
+ if ((pri < affected_start || pri > affected_end) &&
+ (sec < affected_start || sec > affected_end))
+ return 0; /* not within affected channel range */
+
+ wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR
+ " freq=%d pri=%d sec=%d",
+ MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan);
+
+ if (sec_chan) {
+ if (pri_freq != pri || sec_freq != sec) {
+ wpa_printf(MSG_DEBUG,
+ "40 MHz pri/sec mismatch with BSS "
+ MACSTR
+ " <%d,%d> (chan=%d%c) vs. <%d,%d>",
+ MAC2STR(bss->bssid),
+ pri, sec, pri_chan,
+ sec > pri ? '+' : '-',
+ pri_freq, sec_freq);
+ return 1;
+ }
+ }
+
+ ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0);
+ if (elems.ht_capabilities) {
+ struct ieee80211_ht_capabilities *ht_cap =
+ (struct ieee80211_ht_capabilities *)
+ elems.ht_capabilities;
+
+ if (le_to_host16(ht_cap->ht_capabilities_info) &
+ HT_CAP_INFO_40MHZ_INTOLERANT) {
+ wpa_printf(MSG_DEBUG,
+ "40 MHz Intolerant is set on channel %d in BSS "
+ MACSTR, pri, MAC2STR(bss->bssid));
+ return 2;
+ }
+ }
+
+ return 0;
+}
+
+
int check_40mhz_2g4(struct hostapd_hw_modes *mode,
struct wpa_scan_results *scan_res, int pri_chan,
int sec_chan)
{
int pri_freq, sec_freq;
- int affected_start, affected_end;
size_t i;
if (!mode || !scan_res || !pri_chan || !sec_chan ||
@@ -288,70 +369,12 @@
pri_freq = hw_get_freq(mode, pri_chan);
sec_freq = hw_get_freq(mode, sec_chan);
- affected_start = (pri_freq + sec_freq) / 2 - 25;
- affected_end = (pri_freq + sec_freq) / 2 + 25;
wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz",
- affected_start, affected_end);
+ (pri_freq + sec_freq) / 2 - 25,
+ (pri_freq + sec_freq) / 2 + 25);
for (i = 0; i < scan_res->num; i++) {
- struct wpa_scan_res *bss = scan_res->res[i];
- int pri = bss->freq;
- int sec = pri;
- struct ieee802_11_elems elems;
-
- /* Check for overlapping 20 MHz BSS */
- if (check_20mhz_bss(bss, pri_freq, affected_start,
- affected_end)) {
- wpa_printf(MSG_DEBUG,
- "Overlapping 20 MHz BSS is found");
+ if (check_bss_coex_40mhz(scan_res->res[i], pri_freq, sec_freq))
return 0;
- }
-
- get_pri_sec_chan(bss, &pri_chan, &sec_chan);
-
- if (sec_chan) {
- if (sec_chan < pri_chan)
- sec = pri - 20;
- else
- sec = pri + 20;
- }
-
- if ((pri < affected_start || pri > affected_end) &&
- (sec < affected_start || sec > affected_end))
- continue; /* not within affected channel range */
-
- wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR
- " freq=%d pri=%d sec=%d",
- MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan);
-
- if (sec_chan) {
- if (pri_freq != pri || sec_freq != sec) {
- wpa_printf(MSG_DEBUG,
- "40 MHz pri/sec mismatch with BSS "
- MACSTR
- " <%d,%d> (chan=%d%c) vs. <%d,%d>",
- MAC2STR(bss->bssid),
- pri, sec, pri_chan,
- sec > pri ? '+' : '-',
- pri_freq, sec_freq);
- return 0;
- }
- }
-
- ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems,
- 0);
- if (elems.ht_capabilities) {
- struct ieee80211_ht_capabilities *ht_cap =
- (struct ieee80211_ht_capabilities *)
- elems.ht_capabilities;
-
- if (le_to_host16(ht_cap->ht_capabilities_info) &
- HT_CAP_INFO_40MHZ_INTOLERANT) {
- wpa_printf(MSG_DEBUG,
- "40 MHz Intolerant is set on channel %d in BSS "
- MACSTR, pri, MAC2STR(bss->bssid));
- return 0;
- }
- }
}
return 1;
@@ -445,6 +468,8 @@
data->bandwidth = (1 << (u8) bw) * 20;
data->center_freq1 = freq1;
data->center_freq2 = freq2;
+ data->ht_enabled = 0;
+ data->vht_enabled = 0;
}
return 0;
diff --git a/src/common/hw_features_common.h b/src/common/hw_features_common.h
index c86e195..e57a8d6 100644
--- a/src/common/hw_features_common.h
+++ b/src/common/hw_features_common.h
@@ -14,18 +14,22 @@
struct hostapd_channel_data * hw_get_channel_chan(struct hostapd_hw_modes *mode,
int chan, int *freq);
-struct hostapd_channel_data * hw_get_channel_freq(struct hostapd_hw_modes *mode,
- int freq, int *chan);
+struct hostapd_channel_data *
+hw_get_channel_freq(enum hostapd_hw_mode mode, int freq, int *chan,
+ struct hostapd_hw_modes *hw_features, int num_hw_features);
int hw_get_freq(struct hostapd_hw_modes *mode, int chan);
-int hw_get_chan(struct hostapd_hw_modes *mode, int freq);
+int hw_get_chan(enum hostapd_hw_mode mode, int freq,
+ struct hostapd_hw_modes *hw_features, int num_hw_features);
-int allowed_ht40_channel_pair(struct hostapd_hw_modes *mode, int pri_chan,
- int sec_chan);
+int allowed_ht40_channel_pair(enum hostapd_hw_mode mode,
+ struct hostapd_channel_data *p_chan,
+ struct hostapd_channel_data *s_chan);
void get_pri_sec_chan(struct wpa_scan_res *bss, int *pri_chan, int *sec_chan);
-int check_40mhz_5g(struct hostapd_hw_modes *mode,
- struct wpa_scan_results *scan_res, int pri_chan,
- int sec_chan);
+int check_40mhz_5g(struct wpa_scan_results *scan_res,
+ struct hostapd_channel_data *pri_chan,
+ struct hostapd_channel_data *sec_chan);
+int check_bss_coex_40mhz(struct wpa_scan_res *bss, int pri_freq, int sec_freq);
int check_40mhz_2g4(struct hostapd_hw_modes *mode,
struct wpa_scan_results *scan_res, int pri_chan,
int sec_chan);
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index c6e6440..0d37674 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -722,13 +722,14 @@
* for HT40 and VHT. DFS channels are not covered.
* @freq: Frequency (MHz) to convert
* @sec_channel: 0 = non-HT40, 1 = sec. channel above, -1 = sec. channel below
- * @vht: VHT channel width (CHANWIDTH_*)
+ * @chanwidth: VHT/EDMG channel width (CHANWIDTH_*)
* @op_class: Buffer for returning operating class
* @channel: Buffer for returning channel number
* Returns: hw_mode on success, NUM_HOSTAPD_MODES on failure
*/
enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
- int sec_channel, int vht,
+ int sec_channel,
+ int chanwidth,
u8 *op_class, u8 *channel)
{
u8 vht_opclass;
@@ -742,7 +743,7 @@
if ((freq - 2407) % 5)
return NUM_HOSTAPD_MODES;
- if (vht)
+ if (chanwidth)
return NUM_HOSTAPD_MODES;
/* 2.407 GHz, channels 1..13 */
@@ -759,7 +760,7 @@
}
if (freq == 2484) {
- if (sec_channel || vht)
+ if (sec_channel || chanwidth)
return NUM_HOSTAPD_MODES;
*op_class = 82; /* channel 14 */
@@ -776,7 +777,7 @@
return HOSTAPD_MODE_IEEE80211A;
}
- switch (vht) {
+ switch (chanwidth) {
case CHANWIDTH_80MHZ:
vht_opclass = 128;
break;
@@ -877,17 +878,6 @@
return HOSTAPD_MODE_IEEE80211A;
}
- /* 56.16 GHz, channel 1..6 */
- if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 6) {
- if (sec_channel || vht)
- return NUM_HOSTAPD_MODES;
-
- *channel = (freq - 56160) / 2160;
- *op_class = 180;
-
- return HOSTAPD_MODE_IEEE80211AD;
- }
-
if (freq > 5940 && freq <= 7105) {
int bw;
u8 idx = (freq - 5940) / 5;
@@ -901,6 +891,48 @@
return HOSTAPD_MODE_IEEE80211A;
}
+ /* 56.16 GHz, channel 1..6 */
+ if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 6) {
+ if (sec_channel)
+ return NUM_HOSTAPD_MODES;
+
+ switch (chanwidth) {
+ case CHANWIDTH_USE_HT:
+ case CHANWIDTH_2160MHZ:
+ *channel = (freq - 56160) / 2160;
+ *op_class = 180;
+ break;
+ case CHANWIDTH_4320MHZ:
+ /* EDMG channels 9 - 13 */
+ if (freq > 56160 + 2160 * 5)
+ return NUM_HOSTAPD_MODES;
+
+ *channel = (freq - 56160) / 2160 + 8;
+ *op_class = 181;
+ break;
+ case CHANWIDTH_6480MHZ:
+ /* EDMG channels 17 - 20 */
+ if (freq > 56160 + 2160 * 4)
+ return NUM_HOSTAPD_MODES;
+
+ *channel = (freq - 56160) / 2160 + 16;
+ *op_class = 182;
+ break;
+ case CHANWIDTH_8640MHZ:
+ /* EDMG channels 25 - 27 */
+ if (freq > 56160 + 2160 * 3)
+ return NUM_HOSTAPD_MODES;
+
+ *channel = (freq - 56160) / 2160 + 24;
+ *op_class = 183;
+ break;
+ default:
+ return NUM_HOSTAPD_MODES;
+ }
+
+ return HOSTAPD_MODE_IEEE80211AD;
+ }
+
return NUM_HOSTAPD_MODES;
}
@@ -908,27 +940,39 @@
int ieee80211_chaninfo_to_channel(unsigned int freq, enum chan_width chanwidth,
int sec_channel, u8 *op_class, u8 *channel)
{
- int vht = CHAN_WIDTH_UNKNOWN;
+ int cw = CHAN_WIDTH_UNKNOWN;
switch (chanwidth) {
case CHAN_WIDTH_UNKNOWN:
case CHAN_WIDTH_20_NOHT:
case CHAN_WIDTH_20:
case CHAN_WIDTH_40:
- vht = CHANWIDTH_USE_HT;
+ cw = CHANWIDTH_USE_HT;
break;
case CHAN_WIDTH_80:
- vht = CHANWIDTH_80MHZ;
+ cw = CHANWIDTH_80MHZ;
break;
case CHAN_WIDTH_80P80:
- vht = CHANWIDTH_80P80MHZ;
+ cw = CHANWIDTH_80P80MHZ;
break;
case CHAN_WIDTH_160:
- vht = CHANWIDTH_160MHZ;
+ cw = CHANWIDTH_160MHZ;
+ break;
+ case CHAN_WIDTH_2160:
+ cw = CHANWIDTH_2160MHZ;
+ break;
+ case CHAN_WIDTH_4320:
+ cw = CHANWIDTH_4320MHZ;
+ break;
+ case CHAN_WIDTH_6480:
+ cw = CHANWIDTH_6480MHZ;
+ break;
+ case CHAN_WIDTH_8640:
+ cw = CHANWIDTH_8640MHZ;
break;
}
- if (ieee80211_freq_to_channel_ext(freq, sec_channel, vht, op_class,
+ if (ieee80211_freq_to_channel_ext(freq, sec_channel, cw, op_class,
channel) == NUM_HOSTAPD_MODES) {
wpa_printf(MSG_WARNING,
"Cannot determine operating class and channel (freq=%u chanwidth=%d sec_channel=%d)",
@@ -1010,10 +1054,22 @@
if (chan < 149 || chan > 165)
return -1;
return 5000 + 5 * chan;
- case 34: /* 60 GHz band, channels 1..6 */
- if (chan < 1 || chan > 6)
+ case 34: /* 60 GHz band, channels 1..8 */
+ if (chan < 1 || chan > 8)
return -1;
return 56160 + 2160 * chan;
+ case 37: /* 60 GHz band, EDMG CB2, channels 9..15 */
+ if (chan < 9 || chan > 15)
+ return -1;
+ return 56160 + 2160 * (chan - 8);
+ case 38: /* 60 GHz band, EDMG CB3, channels 17..22 */
+ if (chan < 17 || chan > 22)
+ return -1;
+ return 56160 + 2160 * (chan - 16);
+ case 39: /* 60 GHz band, EDMG CB4, channels 25..29 */
+ if (chan < 25 || chan > 29)
+ return -1;
+ return 56160 + 2160 * (chan - 24);
}
return -1;
}
@@ -1052,6 +1108,18 @@
if (chan < 1 || chan > 6)
return -1;
return 56160 + 2160 * chan;
+ case 21: /* 60 GHz band, EDMG CB2, channels 9..11 */
+ if (chan < 9 || chan > 11)
+ return -1;
+ return 56160 + 2160 * (chan - 8);
+ case 22: /* 60 GHz band, EDMG CB3, channels 17..18 */
+ if (chan < 17 || chan > 18)
+ return -1;
+ return 56160 + 2160 * (chan - 16);
+ case 23: /* 60 GHz band, EDMG CB4, channels 25 */
+ if (chan != 25)
+ return -1;
+ return 56160 + 2160 * (chan - 24);
}
return -1;
}
@@ -1096,6 +1164,18 @@
if (chan < 1 || chan > 6)
return -1;
return 56160 + 2160 * chan;
+ case 62: /* 60 GHz band, EDMG CB2, channels 9..11 */
+ if (chan < 9 || chan > 11)
+ return -1;
+ return 56160 + 2160 * (chan - 8);
+ case 63: /* 60 GHz band, EDMG CB3, channels 17..18 */
+ if (chan < 17 || chan > 18)
+ return -1;
+ return 56160 + 2160 * (chan - 16);
+ case 64: /* 60 GHz band, EDMG CB4, channel 25 */
+ if (chan != 25)
+ return -1;
+ return 56160 + 2160 * (chan - 24);
}
return -1;
}
@@ -1188,10 +1268,22 @@
if (chan < 1 || chan > 233)
return -1;
return 5940 + chan * 5;
- case 180: /* 60 GHz band, channels 1..6 */
- if (chan < 1 || chan > 6)
+ case 180: /* 60 GHz band, channels 1..8 */
+ if (chan < 1 || chan > 8)
return -1;
return 56160 + 2160 * chan;
+ case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */
+ if (chan < 9 || chan > 15)
+ return -1;
+ return 56160 + 2160 * (chan - 8);
+ case 182: /* 60 GHz band, EDMG CB3, channels 17..22 */
+ if (chan < 17 || chan > 22)
+ return -1;
+ return 56160 + 2160 * (chan - 16);
+ case 183: /* 60 GHz band, EDMG CB4, channel 25..29 */
+ if (chan < 25 || chan > 29)
+ return -1;
+ return 56160 + 2160 * (chan - 24);
}
return -1;
}
@@ -1619,7 +1711,16 @@
{ HOSTAPD_MODE_IEEE80211A, 129, 50, 114, 16, BW160, P2P_SUPP },
{ HOSTAPD_MODE_IEEE80211A, 130, 36, 161, 4, BW80P80, P2P_SUPP },
{ HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, P2P_SUPP },
- { HOSTAPD_MODE_IEEE80211AD, 180, 1, 4, 1, BW2160, P2P_SUPP },
+
+ /*
+ * IEEE Std 802.11ad-2012 and P802.ay/D5.0 60 GHz operating classes.
+ * Class 180 has the legacy channels 1-6. Classes 181-183 include
+ * channels which implement channel bonding features.
+ */
+ { HOSTAPD_MODE_IEEE80211AD, 180, 1, 6, 1, BW2160, P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211AD, 181, 9, 13, 1, BW4320, P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211AD, 182, 17, 20, 1, BW6480, P2P_SUPP },
+ { HOSTAPD_MODE_IEEE80211AD, 183, 25, 27, 1, BW8640, P2P_SUPP },
{ -1, 0, 0, 0, 0, BW20, NO_P2P_SUPP }
};
@@ -1970,6 +2071,26 @@
}
+int is_6ghz_psc_frequency(int freq)
+{
+ int i;
+
+ if (!is_6ghz_freq(freq))
+ return 0;
+ if ((((freq - 5940) / 5) & 0x3) != 0x1)
+ return 0;
+
+ i = (freq - 5940 + 55) % 80;
+ if (i == 0)
+ i = (freq - 5940 + 55) / 80;
+
+ if (i >= 1 && i <= 15)
+ return 1;
+
+ return 0;
+}
+
+
int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
size_t nei_rep_len)
{
@@ -2150,3 +2271,121 @@
return 1;
}
+
+
+int op_class_to_bandwidth(u8 op_class)
+{
+ switch (op_class) {
+ case 81:
+ case 82:
+ return 20;
+ case 83: /* channels 1..9; 40 MHz */
+ case 84: /* channels 5..13; 40 MHz */
+ return 40;
+ case 115: /* channels 36,40,44,48; indoor only */
+ return 20;
+ case 116: /* channels 36,44; 40 MHz; indoor only */
+ case 117: /* channels 40,48; 40 MHz; indoor only */
+ return 40;
+ case 118: /* channels 52,56,60,64; dfs */
+ return 20;
+ case 119: /* channels 52,60; 40 MHz; dfs */
+ case 120: /* channels 56,64; 40 MHz; dfs */
+ return 40;
+ case 121: /* channels 100-140 */
+ return 20;
+ case 122: /* channels 100-142; 40 MHz */
+ case 123: /* channels 104-136; 40 MHz */
+ return 40;
+ case 124: /* channels 149,153,157,161 */
+ case 125: /* channels 149,153,157,161,165,169 */
+ return 20;
+ case 126: /* channels 149,157; 40 MHz */
+ case 127: /* channels 153,161; 40 MHz */
+ return 40;
+ case 128: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
+ return 80;
+ case 129: /* center freqs 50, 114; 160 MHz */
+ return 160;
+ case 130: /* center freqs 42, 58, 106, 122, 138, 155; 80+80 MHz */
+ return 80;
+ case 131: /* UHB channels, 20 MHz: 1, 5, 9.. */
+ return 20;
+ case 132: /* UHB channels, 40 MHz: 3, 11, 19.. */
+ return 40;
+ case 133: /* UHB channels, 80 MHz: 7, 23, 39.. */
+ return 80;
+ case 134: /* UHB channels, 160 MHz: 15, 47, 79.. */
+ case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */
+ return 160;
+ case 180: /* 60 GHz band, channels 1..8 */
+ return 2160;
+ case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */
+ return 4320;
+ case 182: /* 60 GHz band, EDMG CB3, channels 17..22 */
+ return 6480;
+ case 183: /* 60 GHz band, EDMG CB4, channel 25..29 */
+ return 8640;
+ }
+
+ return 20;
+}
+
+
+int op_class_to_ch_width(u8 op_class)
+{
+ switch (op_class) {
+ case 81:
+ case 82:
+ return CHANWIDTH_USE_HT;
+ case 83: /* channels 1..9; 40 MHz */
+ case 84: /* channels 5..13; 40 MHz */
+ return CHANWIDTH_USE_HT;
+ case 115: /* channels 36,40,44,48; indoor only */
+ return CHANWIDTH_USE_HT;
+ case 116: /* channels 36,44; 40 MHz; indoor only */
+ case 117: /* channels 40,48; 40 MHz; indoor only */
+ return CHANWIDTH_USE_HT;
+ case 118: /* channels 52,56,60,64; dfs */
+ return CHANWIDTH_USE_HT;
+ case 119: /* channels 52,60; 40 MHz; dfs */
+ case 120: /* channels 56,64; 40 MHz; dfs */
+ return CHANWIDTH_USE_HT;
+ case 121: /* channels 100-140 */
+ return CHANWIDTH_USE_HT;
+ case 122: /* channels 100-142; 40 MHz */
+ case 123: /* channels 104-136; 40 MHz */
+ return CHANWIDTH_USE_HT;
+ case 124: /* channels 149,153,157,161 */
+ case 125: /* channels 149,153,157,161,165,169 */
+ return CHANWIDTH_USE_HT;
+ case 126: /* channels 149,157; 40 MHz */
+ case 127: /* channels 153,161; 40 MHz */
+ return CHANWIDTH_USE_HT;
+ case 128: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
+ return CHANWIDTH_80MHZ;
+ case 129: /* center freqs 50, 114; 160 MHz */
+ return CHANWIDTH_160MHZ;
+ case 130: /* center freqs 42, 58, 106, 122, 138, 155; 80+80 MHz */
+ return CHANWIDTH_80P80MHZ;
+ case 131: /* UHB channels, 20 MHz: 1, 5, 9.. */
+ return CHANWIDTH_USE_HT;
+ case 132: /* UHB channels, 40 MHz: 3, 11, 19.. */
+ return CHANWIDTH_USE_HT;
+ case 133: /* UHB channels, 80 MHz: 7, 23, 39.. */
+ return CHANWIDTH_80MHZ;
+ case 134: /* UHB channels, 160 MHz: 15, 47, 79.. */
+ return CHANWIDTH_160MHZ;
+ case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */
+ return CHANWIDTH_80P80MHZ;
+ case 180: /* 60 GHz band, channels 1..8 */
+ return CHANWIDTH_2160MHZ;
+ case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */
+ return CHANWIDTH_4320MHZ;
+ case 182: /* 60 GHz band, EDMG CB3, channels 17..22 */
+ return CHANWIDTH_6480MHZ;
+ case 183: /* 60 GHz band, EDMG CB4, channel 25..29 */
+ return CHANWIDTH_8640MHZ;
+ }
+ return CHANWIDTH_USE_HT;
+}
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index 052f333..fbda10c 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -198,7 +198,8 @@
u8 min_chan;
u8 max_chan;
u8 inc;
- enum { BW20, BW40PLUS, BW40MINUS, BW80, BW2160, BW160, BW80P80 } bw;
+ enum { BW20, BW40PLUS, BW40MINUS, BW80, BW2160, BW160, BW80P80, BW4320,
+ BW6480, BW8640} bw;
enum { P2P_SUPP, NO_P2P_SUPP } p2p;
};
@@ -225,11 +226,14 @@
int center_idx_to_bw_6ghz(u8 idx);
int is_6ghz_freq(int freq);
int is_6ghz_op_class(u8 op_class);
+int is_6ghz_psc_frequency(int freq);
int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
size_t nei_rep_len);
int ieee802_11_ext_capab(const u8 *ie, unsigned int capab);
+int op_class_to_bandwidth(u8 op_class);
+int op_class_to_ch_width(u8 op_class);
/* element iteration helpers */
#define for_each_element(_elem, _data, _datalen) \
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index fbed051..e3c2ed3 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -1285,11 +1285,15 @@
#define VHT_RX_NSS_MAX_STREAMS 8
-/* VHT channel widths */
+/* VHT/EDMG channel widths */
#define CHANWIDTH_USE_HT 0
#define CHANWIDTH_80MHZ 1
#define CHANWIDTH_160MHZ 2
#define CHANWIDTH_80P80MHZ 3
+#define CHANWIDTH_2160MHZ 4
+#define CHANWIDTH_4320MHZ 5
+#define CHANWIDTH_6480MHZ 6
+#define CHANWIDTH_8640MHZ 7
#define HE_NSS_MAX_STREAMS 8
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index a0a0fb5..778c217 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -609,6 +609,14 @@
* coex chain mode from application/service.
* The attributes defined in enum qca_vendor_attr_btc_chain_mode are used
* to deliver the parameters.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO: This vendor subcommand is used to
+ * get information of a station from driver to userspace. This command can
+ * be used in both STA and AP modes. For STA mode, it provides information
+ * of the current association when in connected state or the last
+ * association when in disconnected state. For AP mode, only information
+ * of the currently connected stations is available. This command uses
+ * attributes defined in enum qca_wlan_vendor_attr_get_sta_info.
*/
enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
@@ -784,6 +792,7 @@
QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_EXT = 183,
QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE = 184,
QCA_NL80211_VENDOR_SUBCMD_BTC_CHAIN_MODE = 185,
+ QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO = 186,
};
enum qca_wlan_vendor_attr {
@@ -8046,4 +8055,110 @@
QCA_VENDOR_ATTR_BTC_CHAIN_MODE_LAST - 1,
};
+/**
+ * enum qca_vendor_wlan_sta_flags - Station feature flags
+ * Bits will be set to 1 if the corresponding features are enabled.
+ * @QCA_VENDOR_WLAN_STA_FLAG_AMPDU: AMPDU is enabled for the station
+ * @QCA_VENDOR_WLAN_STA_FLAG_TX_STBC: TX Space-time block coding is enabled
+ for the station
+ * @QCA_VENDOR_WLAN_STA_FLAG_RX_STBC: RX Space-time block coding is enabled
+ for the station
+ */
+enum qca_vendor_wlan_sta_flags {
+ QCA_VENDOR_WLAN_STA_FLAG_AMPDU = BIT(0),
+ QCA_VENDOR_WLAN_STA_FLAG_TX_STBC = BIT(1),
+ QCA_VENDOR_WLAN_STA_FLAG_RX_STBC = BIT(2),
+};
+
+/**
+ * enum qca_vendor_wlan_sta_guard_interval - Station guard interval
+ * @QCA_VENDOR_WLAN_STA_GI_800_NS: Legacy normal guard interval
+ * @QCA_VENDOR_WLAN_STA_GI_400_NS: Legacy short guard interval
+ * @QCA_VENDOR_WLAN_STA_GI_1600_NS: Guard interval used by HE
+ * @QCA_VENDOR_WLAN_STA_GI_3200_NS: Guard interval used by HE
+ */
+enum qca_vendor_wlan_sta_guard_interval {
+ QCA_VENDOR_WLAN_STA_GI_800_NS = 0,
+ QCA_VENDOR_WLAN_STA_GI_400_NS = 1,
+ QCA_VENDOR_WLAN_STA_GI_1600_NS = 2,
+ QCA_VENDOR_WLAN_STA_GI_3200_NS = 3,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_get_sta_info - Defines attributes
+ * used by QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO vendor command.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAC:
+ * Required attribute in request, 6-byte MAC address,
+ * used in both STA and AP modes.
+ * MAC address of the station for which information is requested (BSSID of the
+ * AP in STA mode).
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_FLAGS:
+ * Optionally used in response, u32 attribute, contains a bitmap of different
+ * fields defined in enum qca_vendor_wlan_sta_flags, used in AP mode only.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_GUARD_INTERVAL:
+ * Optionally used in response, u32 attribute, possible values are defined in
+ * enum qca_vendor_wlan_sta_guard_interval, used in AP mode only.
+ * Guard interval used by the station.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_RETRY_COUNT:
+ * Optionally used in response, u32 attribute, used in AP mode only.
+ * Value indicates the number of data frames received from station with retry
+ * bit set to 1 in FC.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_BC_MC_COUNT:
+ * Optionally used in response, u32 attribute, used in AP mode only.
+ * Counter for number of data frames with broadcast or multicast address in
+ * the destination address received from the station.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RETRY_SUCCEED:
+ * Optionally used in response, u32 attribute, used in both STA and AP modes.
+ * Value indicates the number of data frames successfully transmitted only
+ * after retrying the packets and for which the TX status has been updated
+ * back to host from target.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RETRY_EXHAUSTED:
+ * Optionally used in response, u32 attribute, used in AP mode only.
+ * Value indicates the number of data frames not transmitted successfully even
+ * after retrying the packets for the number of times equal to the total number
+ * of retries allowed for that packet and for which the TX status has been
+ * updated back to host from target.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_TOTAL:
+ * Optionally used in response, u32 attribute, used in AP mode only.
+ * Counter in the target for the number of data frames successfully transmitted
+ * to the station.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_RETRY:
+ * Optionally used in response, u32 attribute, used in AP mode only.
+ * Value indicates the number of data frames successfully transmitted only
+ * after retrying the packets.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_RETRY_EXHAUSTED:
+ * Optionally used in response, u32 attribute, used in AP mode only.
+ * Value indicates the number of data frames not transmitted successfully even
+ * after retrying the packets for the number of times equal to the total number
+ * of retries allowed for that packet.
+ */
+enum qca_wlan_vendor_attr_get_sta_info {
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAC = 1,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_FLAGS = 2,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_GUARD_INTERVAL = 3,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_RETRY_COUNT = 4,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_BC_MC_COUNT = 5,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RETRY_SUCCEED = 6,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RETRY_EXHAUSTED = 7,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_TOTAL = 8,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_RETRY = 9,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_RETRY_EXHAUSTED = 10,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX =
+ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_AFTER_LAST - 1,
+};
+
#endif /* QCA_VENDOR_H */
diff --git a/src/common/sae.c b/src/common/sae.c
index 2ab168b..bf8cc9d 100644
--- a/src/common/sae.c
+++ b/src/common/sae.c
@@ -579,20 +579,26 @@
{
switch (group) {
case 19:
+ *z = -10;
+ return 0;
case 20:
+ *z = -12;
+ return 0;
case 21:
- case 28:
- *z = -2;
+ *z = -4;
return 0;
case 25:
case 29:
*z = -5;
return 0;
case 26:
- *z = -11;
+ *z = 31;
+ return 0;
+ case 28:
+ *z = -2;
return 0;
case 30:
- *z = 2;
+ *z = 7;
return 0;
}
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index ea9f7a2..de4b6ec 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -2200,7 +2200,7 @@
"RSN: Remove %u old PMKID(s) from RSNE",
num_pmkid);
after = rpos + 2 + num_pmkid * PMKID_LEN;
- os_memmove(rpos + 2, after, rend - after);
+ os_memmove(rpos + 2, after, end - after);
start[1] -= num_pmkid * PMKID_LEN;
added -= num_pmkid * PMKID_LEN;
}
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index 70ecf5d..f03c698 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -171,6 +171,7 @@
#define DPP_EVENT_CONN_STATUS_RESULT "DPP-CONN-STATUS-RESULT "
#define DPP_EVENT_CONFOBJ_AKM "DPP-CONFOBJ-AKM "
#define DPP_EVENT_CONFOBJ_SSID "DPP-CONFOBJ-SSID "
+#define DPP_EVENT_CONFOBJ_SSID_CHARSET "DPP-CONFOBJ-SSID-CHARSET "
#define DPP_EVENT_CONFOBJ_PASS "DPP-CONFOBJ-PASS "
#define DPP_EVENT_CONFOBJ_PSK "DPP-CONFOBJ-PSK "
#define DPP_EVENT_CONNECTOR "DPP-CONNECTOR "
@@ -300,6 +301,8 @@
#define WPS_EVENT_AP_SETUP_UNLOCKED "WPS-AP-SETUP-UNLOCKED "
#define WPS_EVENT_AP_PIN_ENABLED "WPS-AP-PIN-ENABLED "
#define WPS_EVENT_AP_PIN_DISABLED "WPS-AP-PIN-DISABLED "
+#define WPS_EVENT_PIN_ACTIVE "WPS-PIN-ACTIVE "
+#define WPS_EVENT_CANCEL "WPS-CANCEL "
#define AP_STA_CONNECTED "AP-STA-CONNECTED "
#define AP_STA_DISCONNECTED "AP-STA-DISCONNECTED "
#define AP_STA_POSSIBLE_PSK_MISMATCH "AP-STA-POSSIBLE-PSK-MISMATCH "
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index f3803bd..84ec985 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -4065,6 +4065,7 @@
int cipher, digest;
const EVP_CIPHER *c;
const EVP_MD *h;
+ int mac_key_len, enc_key_len, fixed_iv_len;
ssl_cipher = SSL_get_current_cipher(ssl);
if (!ssl_cipher)
@@ -4075,17 +4076,33 @@
cipher, digest);
if (cipher < 0 || digest < 0)
return -1;
- c = EVP_get_cipherbynid(cipher);
- h = EVP_get_digestbynid(digest);
- if (!c || !h)
+ if (cipher == NID_undef) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: no cipher in use?!");
return -1;
+ }
+ c = EVP_get_cipherbynid(cipher);
+ if (!c)
+ return -1;
+ enc_key_len = EVP_CIPHER_key_length(c);
+ if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE ||
+ EVP_CIPHER_mode(c) == EVP_CIPH_CCM_MODE)
+ fixed_iv_len = 4; /* only part of IV from PRF */
+ else
+ fixed_iv_len = EVP_CIPHER_iv_length(c);
+ if (digest == NID_undef) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: no digest in use (e.g., AEAD)");
+ mac_key_len = 0;
+ } else {
+ h = EVP_get_digestbynid(digest);
+ if (!h)
+ return -1;
+ mac_key_len = EVP_MD_size(h);
+ }
wpa_printf(MSG_DEBUG,
- "OpenSSL: keyblock size: key_len=%d MD_size=%d IV_len=%d",
- EVP_CIPHER_key_length(c), EVP_MD_size(h),
- EVP_CIPHER_iv_length(c));
- return 2 * (EVP_CIPHER_key_length(c) + EVP_MD_size(h) +
- EVP_CIPHER_iv_length(c));
+ "OpenSSL: keyblock size: mac_key_len=%d enc_key_len=%d fixed_iv_len=%d",
+ mac_key_len, enc_key_len, fixed_iv_len);
+ return 2 * (mac_key_len + enc_key_len + fixed_iv_len);
#endif
}
#endif /* OPENSSL_NEED_EAP_FAST_PRF */
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index ad68a07..f0e2a6f 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -2192,9 +2192,7 @@
/* Configured ACS channel width */
u16 ch_width;
- /* ACS channel list info */
- unsigned int ch_list_len;
- const u8 *ch_list;
+ /* ACS frequency list info */
const int *freq_list;
};
@@ -5609,8 +5607,8 @@
/**
* struct acs_selected_channels - Data for EVENT_ACS_CHANNEL_SELECTED
- * @pri_channel: Selected primary channel
- * @sec_channel: Selected secondary channel
+ * @pri_freq: Selected primary frequency
+ * @sec_freq: Selected secondary frequency
* @vht_seg0_center_ch: VHT mode Segment0 center channel
* @vht_seg1_center_ch: VHT mode Segment1 center channel
* @ch_width: Selected Channel width by driver. Driver may choose to
@@ -5619,8 +5617,8 @@
* hw_mode: Selected band (used with hw_mode=any)
*/
struct acs_selected_channels {
- u8 pri_channel;
- u8 sec_channel;
+ unsigned int pri_freq;
+ unsigned int sec_freq;
u8 vht_seg0_center_ch;
u8 vht_seg1_center_ch;
u16 ch_width;
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 4c8dcad..b7efb6a 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -6993,10 +6993,14 @@
wpa_printf(MSG_DEBUG, "nl80211: Adding interface %s into bridge %s",
ifname, brname);
if (linux_br_add_if(drv->global->ioctl_sock, brname, ifname) < 0) {
- wpa_printf(MSG_ERROR, "nl80211: Failed to add interface %s "
- "into bridge %s: %s",
+ wpa_printf(MSG_WARNING,
+ "nl80211: Failed to add interface %s into bridge %s: %s",
ifname, brname, strerror(errno));
- return -1;
+ /* Try to continue without the interface being in a bridge. This
+ * may be needed for some cases, e.g., with Open vSwitch, where
+ * an external component will need to handle bridge
+ * configuration. */
+ return 0;
}
bss->added_if_into_bridge = 1;
@@ -10157,6 +10161,48 @@
}
+static int add_acs_ch_list(struct nl_msg *msg, const int *freq_list)
+{
+ int num_channels = 0, num_freqs;
+ u8 *ch_list;
+ enum hostapd_hw_mode hw_mode;
+ int ret = 0;
+ int i;
+
+ if (!freq_list)
+ return 0;
+
+ num_freqs = int_array_len(freq_list);
+ ch_list = os_malloc(sizeof(u8) * num_freqs);
+ if (!ch_list)
+ return -1;
+
+ for (i = 0; i < num_freqs; i++) {
+ const int freq = freq_list[i];
+
+ if (freq == 0)
+ break;
+ /* Send 2.4 GHz and 5 GHz channels with
+ * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST to maintain backwards
+ * compatibility.
+ */
+ if (!(freq >= 2412 && freq <= 2484) &&
+ !(freq >= 5180 && freq <= 5900))
+ continue;
+ hw_mode = ieee80211_freq_to_chan(freq, &ch_list[num_channels]);
+ if (hw_mode != NUM_HOSTAPD_MODES)
+ num_channels++;
+ }
+
+ if (num_channels)
+ ret = nla_put(msg, QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST,
+ num_channels, ch_list);
+
+ os_free(ch_list);
+ return ret;
+}
+
+
static int add_acs_freq_list(struct nl_msg *msg, const int *freq_list)
{
int i, len, ret;
@@ -10204,9 +10250,7 @@
nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED)) ||
nla_put_u16(msg, QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
params->ch_width) ||
- (params->ch_list_len &&
- nla_put(msg, QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST, params->ch_list_len,
- params->ch_list)) ||
+ add_acs_ch_list(msg, params->freq_list) ||
add_acs_freq_list(msg, params->freq_list)) {
nlmsg_free(msg);
return -ENOBUFS;
@@ -10214,9 +10258,9 @@
nla_nest_end(msg, data);
wpa_printf(MSG_DEBUG,
- "nl80211: ACS Params: HW_MODE: %d HT: %d HT40: %d VHT: %d BW: %d CH_LIST_LEN: %u",
+ "nl80211: ACS Params: HW_MODE: %d HT: %d HT40: %d VHT: %d BW: %d",
params->hw_mode, params->ht_enabled, params->ht40_enabled,
- params->vht_enabled, params->ch_width, params->ch_list_len);
+ params->vht_enabled, params->ch_width);
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
if (ret) {
@@ -11051,8 +11095,8 @@
int ret = -1;
/* External auth command/status is intended for drivers that implement
- * intenral SME but want to offload authentication processing (e.g.,
- * SAE) to hostapd/wpa_supplicant. Do nott send the status to drivers
+ * internal SME but want to offload authentication processing (e.g.,
+ * SAE) to hostapd/wpa_supplicant. Do not send the status to drivers
* which do not support AP SME or use wpa_supplicant/hostapd SME.
*/
if ((is_ap_interface(drv->nlmode) && !bss->drv->device_ap_sme) ||
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index d8630bb..9a82cd1 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -1365,12 +1365,18 @@
struct nlattr *tb_freq[])
{
u8 channel;
+
+ os_memset(chan, 0, sizeof(*chan));
chan->freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
chan->flag = 0;
chan->allowed_bw = ~0;
chan->dfs_cac_ms = 0;
if (ieee80211_freq_to_chan(chan->freq, &channel) != NUM_HOSTAPD_MODES)
chan->chan = channel;
+ else
+ wpa_printf(MSG_DEBUG,
+ "nl80211: No channel number found for frequency %u MHz",
+ chan->freq);
if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
chan->flag |= HOSTAPD_CHAN_DISABLED;
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 7c16330..2aecc74 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -524,6 +524,10 @@
break;
case CHAN_WIDTH_UNKNOWN:
case CHAN_WIDTH_80P80:
+ case CHAN_WIDTH_2160:
+ case CHAN_WIDTH_4320:
+ case CHAN_WIDTH_6480:
+ case CHAN_WIDTH_8640:
/* FIXME: implement this */
return 0;
}
@@ -1736,26 +1740,57 @@
}
+static unsigned int chan_2ghz_or_5ghz_to_freq(u8 chan)
+{
+ if (chan >= 1 && chan <= 13)
+ return 2407 + 5 * chan;
+ if (chan == 14)
+ return 2484;
+ if (chan >= 36 && chan <= 169)
+ return 5000 + 5 * chan;
+
+ return 0;
+}
+
+
static void qca_nl80211_acs_select_ch(struct wpa_driver_nl80211_data *drv,
const u8 *data, size_t len)
{
struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
union wpa_event_data event;
+ u8 chan;
wpa_printf(MSG_DEBUG,
"nl80211: ACS channel selection vendor event received");
if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX,
(struct nlattr *) data, len, NULL) ||
- !tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL] ||
- !tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL])
+ (!tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY] &&
+ !tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL]) ||
+ (!tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY] &&
+ !tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL]))
return;
os_memset(&event, 0, sizeof(event));
- event.acs_selected_channels.pri_channel =
- nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL]);
- event.acs_selected_channels.sec_channel =
- nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL]);
+ if (tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY]) {
+ event.acs_selected_channels.pri_freq = nla_get_u32(
+ tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY]);
+ } else {
+ chan = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL]);
+ event.acs_selected_channels.pri_freq =
+ chan_2ghz_or_5ghz_to_freq(chan);
+ }
+
+ if (tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY]) {
+ event.acs_selected_channels.sec_freq = nla_get_u32(
+ tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY]);
+ } else {
+ chan = nla_get_u8(
+ tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL]);
+ event.acs_selected_channels.sec_freq =
+ chan_2ghz_or_5ghz_to_freq(chan);
+ }
+
if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL])
event.acs_selected_channels.vht_seg0_center_ch =
nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL]);
@@ -1780,9 +1815,9 @@
}
wpa_printf(MSG_INFO,
- "nl80211: ACS Results: PCH: %d SCH: %d BW: %d VHT0: %d VHT1: %d HW_MODE: %d",
- event.acs_selected_channels.pri_channel,
- event.acs_selected_channels.sec_channel,
+ "nl80211: ACS Results: PFreq: %d SFreq: %d BW: %d VHT0: %d VHT1: %d HW_MODE: %d",
+ event.acs_selected_channels.pri_freq,
+ event.acs_selected_channels.sec_freq,
event.acs_selected_channels.ch_width,
event.acs_selected_channels.vht_seg0_center_ch,
event.acs_selected_channels.vht_seg1_center_ch,
diff --git a/src/drivers/drivers.mak b/src/drivers/drivers.mak
index 442c59c..bc2e87e 100644
--- a/src/drivers/drivers.mak
+++ b/src/drivers/drivers.mak
@@ -140,10 +140,6 @@
DRV_OBJS += ../src/drivers/netlink.o
endif
-ifdef NEED_LINUX_IOCTL
-DRV_OBJS += ../src/drivers/linux_ioctl.o
-endif
-
ifdef NEED_RFKILL
DRV_OBJS += ../src/drivers/rfkill.o
endif
@@ -152,13 +148,18 @@
DRV_OBJS += ../src/utils/radiotap.o
endif
-ifdef CONFIG_VLAN_NETLINK
ifdef CONFIG_FULL_DYNAMIC_VLAN
+NEED_LINUX_IOCTL=y
+ifdef CONFIG_VLAN_NETLINK
NEED_LIBNL=y
CONFIG_LIBNL3_ROUTE=y
endif
endif
+ifdef NEED_LINUX_IOCTL
+DRV_OBJS += ../src/drivers/linux_ioctl.o
+endif
+
ifdef NEED_LIBNL
ifndef CONFIG_LIBNL32
ifndef CONFIG_LIBNL20
diff --git a/src/drivers/drivers.mk b/src/drivers/drivers.mk
index 599a0b5..c3c2c0f 100644
--- a/src/drivers/drivers.mk
+++ b/src/drivers/drivers.mk
@@ -132,10 +132,6 @@
DRV_OBJS += src/drivers/netlink.c
endif
-ifdef NEED_LINUX_IOCTL
-DRV_OBJS += src/drivers/linux_ioctl.c
-endif
-
ifdef NEED_RFKILL
DRV_OBJS += src/drivers/rfkill.c
endif
@@ -148,13 +144,18 @@
DRV_CFLAGS += -DCONFIG_DRIVER_CUSTOM
endif
-ifdef CONFIG_VLAN_NETLINK
ifdef CONFIG_FULL_DYNAMIC_VLAN
+NEED_LINUX_IOCTL=y
+ifdef CONFIG_VLAN_NETLINK
NEED_LIBNL=y
CONFIG_LIBNL3_ROUTE=y
endif
endif
+ifdef NEED_LINUX_IOCTL
+DRV_OBJS += src/drivers/linux_ioctl.c
+endif
+
ifdef NEED_LIBNL
ifdef CONFIG_LIBNL32
DRV_LIBS += -lnl-3
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
index beee59c..341e0e8 100644
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -249,6 +249,22 @@
*/
/**
+ * DOC: VLAN offload support for setting group keys and binding STAs to VLANs
+ *
+ * By setting @NL80211_EXT_FEATURE_VLAN_OFFLOAD flag drivers can indicate they
+ * support offloading VLAN functionality in a manner where the driver exposes a
+ * single netdev that uses VLAN tagged frames and separate VLAN-specific netdevs
+ * can then be added using RTM_NEWLINK/IFLA_VLAN_ID similarly to the Ethernet
+ * case. Frames received from stations that are not assigned to any VLAN are
+ * delivered on the main netdev and frames to such stations can be sent through
+ * that main netdev.
+ *
+ * %NL80211_CMD_NEW_KEY (for group keys), %NL80211_CMD_NEW_STATION, and
+ * %NL80211_CMD_SET_STATION will optionally specify vlan_id using
+ * %NL80211_ATTR_VLAN_ID.
+ */
+
+/**
* enum nl80211_commands - supported nl80211 commands
*
* @NL80211_CMD_UNSPEC: unspecified command to catch errors
@@ -571,6 +587,14 @@
* set of BSSID,frequency parameters is used (i.e., either the enforcing
* %NL80211_ATTR_MAC,%NL80211_ATTR_WIPHY_FREQ or the less strict
* %NL80211_ATTR_MAC_HINT and %NL80211_ATTR_WIPHY_FREQ_HINT).
+ * Driver shall not modify the IEs specified through %NL80211_ATTR_IE if
+ * %NL80211_ATTR_MAC is included. However, if %NL80211_ATTR_MAC_HINT is
+ * included, these IEs through %NL80211_ATTR_IE are specified by the user
+ * space based on the best possible BSS selected. Thus, if the driver ends
+ * up selecting a different BSS, it can modify these IEs accordingly (e.g.
+ * userspace asks the driver to perform PMKSA caching with BSS1 and the
+ * driver ends up selecting BSS2 with different PMKSA cache entry; RSNIE
+ * has to get updated with the apt PMKID).
* %NL80211_ATTR_PREV_BSSID can be used to request a reassociation within
* the ESS in case the device is already associated and an association with
* a different BSS is desired.
@@ -2373,6 +2397,9 @@
* the allowed channel bandwidth configurations. (u8 attribute)
* Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13.
*
+ * @NL80211_ATTR_VLAN_ID: VLAN ID (1..4094) for the station and VLAN group key
+ * (u16).
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2835,6 +2862,8 @@
NL80211_ATTR_WIPHY_EDMG_CHANNELS,
NL80211_ATTR_WIPHY_EDMG_BW_CONFIG,
+ NL80211_ATTR_VLAN_ID,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -5484,6 +5513,10 @@
* @NL80211_EXT_FEATURE_SAE_OFFLOAD: Device wants to do SAE authentication in
* station mode (SAE password is passed as part of the connect command).
*
+ * @NL80211_EXT_FEATURE_VLAN_OFFLOAD: The driver supports a single netdev
+ * with VLAN tagged frames and separate VLAN-specific netdevs added using
+ * vconfig similarly to the Ethernet case.
+ *
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
*/
@@ -5529,6 +5562,7 @@
NL80211_EXT_FEATURE_EXT_KEY_ID,
NL80211_EXT_FEATURE_STA_TX_PWR,
NL80211_EXT_FEATURE_SAE_OFFLOAD,
+ NL80211_EXT_FEATURE_VLAN_OFFLOAD,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/src/eap_peer/eap_sim.c b/src/eap_peer/eap_sim.c
index 2ea4efd..dd9848e 100644
--- a/src/eap_peer/eap_sim.c
+++ b/src/eap_peer/eap_sim.c
@@ -44,7 +44,7 @@
u8 *last_eap_identity;
size_t last_eap_identity_len;
enum {
- CONTINUE, RESULT_SUCCESS, SUCCESS, FAILURE
+ CONTINUE, START_DONE, RESULT_SUCCESS, SUCCESS, FAILURE
} state;
int result_ind, use_result_ind;
int use_pseudonym;
@@ -58,6 +58,8 @@
switch (state) {
case CONTINUE:
return "CONTINUE";
+ case START_DONE:
+ return "START_DONE";
case RESULT_SUCCESS:
return "RESULT_SUCCESS";
case SUCCESS:
@@ -486,6 +488,7 @@
const u8 *identity = NULL;
size_t identity_len = 0;
struct eap_sim_msg *msg;
+ struct wpabuf *resp;
data->reauth = 0;
if (id_req == ANY_ID && data->reauth_id) {
@@ -535,7 +538,10 @@
identity, identity_len);
}
- return eap_sim_msg_finish(msg, EAP_TYPE_SIM, NULL, NULL, 0);
+ resp = eap_sim_msg_finish(msg, EAP_TYPE_SIM, NULL, NULL, 0);
+ if (resp)
+ eap_sim_state(data, START_DONE);
+ return resp;
}
@@ -721,6 +727,13 @@
int res;
wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Challenge");
+ if (data->state != START_DONE) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-SIM: Unexpected Challenge in state %s",
+ eap_sim_state_txt(data->state));
+ return eap_sim_client_error(data, id,
+ EAP_SIM_UNABLE_TO_PROCESS_PACKET);
+ }
data->reauth = 0;
if (!attr->mac || !attr->rand) {
wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message "
diff --git a/src/eap_peer/tncc.c b/src/eap_peer/tncc.c
index a9bafe2..c460980 100644
--- a/src/eap_peer/tncc.c
+++ b/src/eap_peer/tncc.c
@@ -144,7 +144,7 @@
TNC_MessageType messageType)
{
struct tnc_if_imc *imc;
- unsigned char *b64;
+ char *b64;
size_t b64len;
wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_SendMessage(imcID=%lu "
@@ -629,8 +629,7 @@
return NULL;
*pos2 = '\0';
- decoded = base64_decode((unsigned char *) pos, os_strlen(pos),
- decoded_len);
+ decoded = base64_decode(pos, os_strlen(pos), decoded_len);
*pos2 = '<';
if (decoded == NULL) {
wpa_printf(MSG_DEBUG, "TNC: Failed to decode Base64 data");
diff --git a/src/eap_server/tncs.c b/src/eap_server/tncs.c
index 942a195..4a30486 100644
--- a/src/eap_server/tncs.c
+++ b/src/eap_server/tncs.c
@@ -179,7 +179,7 @@
TNC_MessageType messageType)
{
struct tncs_data *tncs;
- unsigned char *b64;
+ char *b64;
size_t b64len;
wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_SendMessage(imvID=%lu "
@@ -678,8 +678,7 @@
return NULL;
*pos2 = '\0';
- decoded = base64_decode((unsigned char *) pos, os_strlen(pos),
- decoded_len);
+ decoded = base64_decode(pos, os_strlen(pos), decoded_len);
*pos2 = '<';
if (decoded == NULL) {
wpa_printf(MSG_DEBUG, "TNC: Failed to decode Base64 data");
diff --git a/src/l2_packet/l2_packet_linux.c b/src/l2_packet/l2_packet_linux.c
index 291c9dd..138dcaf 100644
--- a/src/l2_packet/l2_packet_linux.c
+++ b/src/l2_packet/l2_packet_linux.c
@@ -171,13 +171,16 @@
u8 hash[SHA1_MAC_LEN];
const u8 *addr[1];
size_t len[1];
+ const struct l2_ethhdr *eth = (const struct l2_ethhdr *) buf;
/*
* Close the workaround socket if the kernel version seems to be
* able to deliver packets through the packet socket before
* authorization has been completed (in dormant state).
*/
- if (l2->num_rx_br <= 1) {
+ if (l2->num_rx_br <= 1 &&
+ (os_memcmp(eth->h_dest, l2->own_addr, ETH_ALEN) == 0 ||
+ is_multicast_ether_addr(eth->h_dest))) {
wpa_printf(MSG_DEBUG,
"l2_packet_receive: Main packet socket for %s seems to have working RX - close workaround bridge socket",
l2->ifname);
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 0396312..9c73885 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -1404,6 +1404,7 @@
const int op_classes_5ghz[] = { 124, 125, 115, 0 };
const int op_classes_ht40[] = { 126, 127, 116, 117, 0 };
const int op_classes_vht[] = { 128, 0 };
+ const int op_classes_edmg[] = { 181, 182, 183, 0 };
p2p_dbg(p2p, "Prepare channel best");
@@ -1435,6 +1436,11 @@
p2p_dbg(p2p, "Select first pref_chan entry as operating channel preference");
p2p->op_reg_class = p2p->cfg->pref_chan[0].op_class;
p2p->op_channel = p2p->cfg->pref_chan[0].chan;
+ } else if (p2p_channel_select(&p2p->cfg->channels, op_classes_edmg,
+ &p2p->op_reg_class, &p2p->op_channel) ==
+ 0) {
+ p2p_dbg(p2p, "Select possible EDMG channel (op_class %u channel %u) as operating channel preference",
+ p2p->op_reg_class, p2p->op_channel);
} else if (p2p_channel_select(&p2p->cfg->channels, op_classes_vht,
&p2p->op_reg_class, &p2p->op_channel) ==
0) {
@@ -4926,6 +4932,7 @@
res = p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, dst, src, bssid,
buf, len, wait_time, &scheduled);
if (res == 0 && scheduled && p2p->in_listen && freq > 0 &&
+ p2p->drv_in_listen > 0 &&
(unsigned int) p2p->drv_in_listen != freq) {
p2p_dbg(p2p,
"Stop listen on %d MHz to allow a frame to be sent immediately on %d MHz",
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 425b037..79de09c 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -99,6 +99,8 @@
int vht;
+ int edmg;
+
u8 max_oper_chwidth;
unsigned int vht_center_freq2;
diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c
index c94bf41..1133461 100644
--- a/src/p2p/p2p_go_neg.c
+++ b/src/p2p/p2p_go_neg.c
@@ -390,6 +390,7 @@
const int op_classes_5ghz[] = { 124, 125, 115, 0 };
const int op_classes_ht40[] = { 126, 127, 116, 117, 0 };
const int op_classes_vht[] = { 128, 129, 130, 0 };
+ const int op_classes_edmg[] = { 181, 182, 183, 0 };
if (p2p->own_freq_preference > 0 &&
p2p_freq_to_channel(p2p->own_freq_preference,
@@ -454,6 +455,14 @@
}
}
+ /* Try a channel where we might be able to use EDMG */
+ if (p2p_channel_select(intersection, op_classes_edmg,
+ &p2p->op_reg_class, &p2p->op_channel) == 0) {
+ p2p_dbg(p2p, "Pick possible EDMG channel (op_class %u channel %u) from intersection",
+ p2p->op_reg_class, p2p->op_channel);
+ return;
+ }
+
/* Try a channel where we might be able to use VHT */
if (p2p_channel_select(intersection, op_classes_vht,
&p2p->op_reg_class, &p2p->op_channel) == 0) {
diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c
index 35120a1..fa5215c 100644
--- a/src/rsn_supp/pmksa_cache.c
+++ b/src/rsn_supp/pmksa_cache.c
@@ -280,7 +280,7 @@
* pmksa_cache_flush - Flush PMKSA cache entries for a specific network
* @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
* @network_ctx: Network configuration context or %NULL to flush all entries
- * @pmk: PMK to match for or %NYLL to match all PMKs
+ * @pmk: PMK to match for or %NULL to match all PMKs
* @pmk_len: PMK length
*/
void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx,
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index ace0b6a..892eece 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -488,6 +488,8 @@
if (wpa_key_mgmt_ft(sm->key_mgmt)) {
int res;
+ wpa_hexdump(MSG_DEBUG, "WPA: WPA IE before FT processing",
+ wpa_ie, wpa_ie_len);
/*
* Add PMKR1Name into RSN IE (PMKID-List) and add MDIE and
* FTIE from (Re)Association Response.
@@ -503,8 +505,14 @@
os_free(rsn_ie_buf);
return -1;
}
+ wpa_hexdump(MSG_DEBUG,
+ "WPA: WPA IE after PMKID[PMKR1Name] addition into RSNE",
+ rsn_ie_buf, wpa_ie_len);
if (sm->assoc_resp_ies) {
+ wpa_hexdump(MSG_DEBUG, "WPA: Add assoc_resp_ies",
+ sm->assoc_resp_ies,
+ sm->assoc_resp_ies_len);
os_memcpy(rsn_ie_buf + wpa_ie_len, sm->assoc_resp_ies,
sm->assoc_resp_ies_len);
wpa_ie_len += sm->assoc_resp_ies_len;
diff --git a/src/tls/tlsv1_cred.c b/src/tls/tlsv1_cred.c
index 842e5dd..01b2f83 100644
--- a/src/tls/tlsv1_cred.c
+++ b/src/tls/tlsv1_cred.c
@@ -130,7 +130,7 @@
return -1;
}
- der = base64_decode(pos, end - pos, &der_len);
+ der = base64_decode((const char *) pos, end - pos, &der_len);
if (der == NULL) {
wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM "
"certificate");
@@ -293,7 +293,7 @@
}
}
- der = base64_decode(pos, end - pos, &der_len);
+ der = base64_decode((const char *) pos, end - pos, &der_len);
if (!der)
return NULL;
pkey = crypto_private_key_import(der, der_len, NULL);
@@ -321,7 +321,7 @@
if (!end)
return NULL;
- der = base64_decode(pos, end - pos, &der_len);
+ der = base64_decode((const char *) pos, end - pos, &der_len);
if (!der)
return NULL;
pkey = crypto_private_key_import(der, der_len, passwd);
@@ -1225,7 +1225,7 @@
return -1;
}
- der = base64_decode(pos, end - pos, &der_len);
+ der = base64_decode((const char *) pos, end - pos, &der_len);
if (der == NULL) {
wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM dhparams");
return -1;
diff --git a/src/utils/base64.c b/src/utils/base64.c
index 53a92f4..a17d2d3 100644
--- a/src/utils/base64.c
+++ b/src/utils/base64.c
@@ -12,18 +12,16 @@
#include "os.h"
#include "base64.h"
-static const unsigned char base64_table[65] =
+static const char base64_table[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-static const unsigned char base64_url_table[65] =
+static const char base64_url_table[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
-static unsigned char * base64_gen_encode(const unsigned char *src, size_t len,
- size_t *out_len,
- const unsigned char *table,
- int add_pad)
+static char * base64_gen_encode(const unsigned char *src, size_t len,
+ size_t *out_len, const char *table, int add_pad)
{
- unsigned char *out, *pos;
+ char *out, *pos;
const unsigned char *end, *in;
size_t olen;
int line_len;
@@ -83,9 +81,8 @@
}
-static unsigned char * base64_gen_decode(const unsigned char *src, size_t len,
- size_t *out_len,
- const unsigned char *table)
+static unsigned char * base64_gen_decode(const char *src, size_t len,
+ size_t *out_len, const char *table)
{
unsigned char dtable[256], *out, *pos, block[4], tmp;
size_t i, count, olen;
@@ -94,12 +91,12 @@
os_memset(dtable, 0x80, 256);
for (i = 0; i < sizeof(base64_table) - 1; i++)
- dtable[table[i]] = (unsigned char) i;
+ dtable[(unsigned char) table[i]] = (unsigned char) i;
dtable['='] = 0;
count = 0;
for (i = 0; i < len; i++) {
- if (dtable[src[i]] != 0x80)
+ if (dtable[(unsigned char) src[i]] != 0x80)
count++;
}
@@ -165,17 +162,15 @@
* nul terminated to make it easier to use as a C string. The nul terminator is
* not included in out_len.
*/
-unsigned char * base64_encode(const unsigned char *src, size_t len,
- size_t *out_len)
+char * base64_encode(const void *src, size_t len, size_t *out_len)
{
return base64_gen_encode(src, len, out_len, base64_table, 1);
}
-unsigned char * base64_url_encode(const unsigned char *src, size_t len,
- size_t *out_len, int add_pad)
+char * base64_url_encode(const void *src, size_t len, size_t *out_len)
{
- return base64_gen_encode(src, len, out_len, base64_url_table, add_pad);
+ return base64_gen_encode(src, len, out_len, base64_url_table, 0);
}
@@ -189,15 +184,13 @@
*
* Caller is responsible for freeing the returned buffer.
*/
-unsigned char * base64_decode(const unsigned char *src, size_t len,
- size_t *out_len)
+unsigned char * base64_decode(const char *src, size_t len, size_t *out_len)
{
return base64_gen_decode(src, len, out_len, base64_table);
}
-unsigned char * base64_url_decode(const unsigned char *src, size_t len,
- size_t *out_len)
+unsigned char * base64_url_decode(const char *src, size_t len, size_t *out_len)
{
return base64_gen_decode(src, len, out_len, base64_url_table);
}
diff --git a/src/utils/base64.h b/src/utils/base64.h
index 5a72c3e..6216f44 100644
--- a/src/utils/base64.h
+++ b/src/utils/base64.h
@@ -9,13 +9,9 @@
#ifndef BASE64_H
#define BASE64_H
-unsigned char * base64_encode(const unsigned char *src, size_t len,
- size_t *out_len);
-unsigned char * base64_decode(const unsigned char *src, size_t len,
- size_t *out_len);
-unsigned char * base64_url_encode(const unsigned char *src, size_t len,
- size_t *out_len, int add_pad);
-unsigned char * base64_url_decode(const unsigned char *src, size_t len,
- size_t *out_len);
+char * base64_encode(const void *src, size_t len, size_t *out_len);
+unsigned char * base64_decode(const char *src, size_t len, size_t *out_len);
+char * base64_url_encode(const void *src, size_t len, size_t *out_len);
+unsigned char * base64_url_decode(const char *src, size_t len, size_t *out_len);
#endif /* BASE64_H */
diff --git a/src/utils/json.c b/src/utils/json.c
index 3e5e214..5a0edf2 100644
--- a/src/utils/json.c
+++ b/src/utils/json.c
@@ -300,8 +300,10 @@
goto fail;
if (!curr_token) {
token = json_alloc_token(&tokens);
- if (!token)
+ if (!token) {
+ os_free(str);
goto fail;
+ }
token->type = JSON_STRING;
token->string = str;
token->state = JSON_COMPLETED;
@@ -514,8 +516,8 @@
token = json_get_member(json, name);
if (!token || token->type != JSON_STRING)
return NULL;
- buf = base64_url_decode((const unsigned char *) token->string,
- os_strlen(token->string), &buflen);
+ buf = base64_url_decode(token->string, os_strlen(token->string),
+ &buflen);
if (!buf)
return NULL;
ret = wpabuf_alloc_ext_data(buf, buflen);
@@ -574,3 +576,79 @@
buf[0] = '\0';
json_print_token(root, 1, buf, buflen);
}
+
+
+void json_add_int(struct wpabuf *json, const char *name, int val)
+{
+ wpabuf_printf(json, "\"%s\":%d", name, val);
+}
+
+
+void json_add_string(struct wpabuf *json, const char *name, const char *val)
+{
+ wpabuf_printf(json, "\"%s\":\"%s\"", name, val);
+}
+
+
+int json_add_string_escape(struct wpabuf *json, const char *name,
+ const void *val, size_t len)
+{
+ char *tmp;
+ size_t tmp_len = 6 * len + 1;
+
+ tmp = os_malloc(tmp_len);
+ if (!tmp)
+ return -1;
+ json_escape_string(tmp, tmp_len, val, len);
+ json_add_string(json, name, tmp);
+ bin_clear_free(tmp, tmp_len);
+ return 0;
+}
+
+
+int json_add_base64url(struct wpabuf *json, const char *name, const void *val,
+ size_t len)
+{
+ char *b64;
+
+ b64 = base64_url_encode(val, len, NULL);
+ if (!b64)
+ return -1;
+ json_add_string(json, name, b64);
+ os_free(b64);
+ return 0;
+}
+
+
+void json_start_object(struct wpabuf *json, const char *name)
+{
+ if (name)
+ wpabuf_printf(json, "\"%s\":", name);
+ wpabuf_put_u8(json, '{');
+}
+
+
+void json_end_object(struct wpabuf *json)
+{
+ wpabuf_put_u8(json, '}');
+}
+
+
+void json_start_array(struct wpabuf *json, const char *name)
+{
+ if (name)
+ wpabuf_printf(json, "\"%s\":", name);
+ wpabuf_put_u8(json, '[');
+}
+
+
+void json_end_array(struct wpabuf *json)
+{
+ wpabuf_put_u8(json, ']');
+}
+
+
+void json_value_sep(struct wpabuf *json)
+{
+ wpabuf_put_u8(json, ',');
+}
diff --git a/src/utils/json.h b/src/utils/json.h
index 8faa95d..ca4a2e4 100644
--- a/src/utils/json.h
+++ b/src/utils/json.h
@@ -38,5 +38,16 @@
struct wpabuf * json_get_member_base64url(struct json_token *json,
const char *name);
void json_print_tree(struct json_token *root, char *buf, size_t buflen);
+void json_add_int(struct wpabuf *json, const char *name, int val);
+void json_add_string(struct wpabuf *json, const char *name, const char *val);
+int json_add_string_escape(struct wpabuf *json, const char *name,
+ const void *val, size_t len);
+int json_add_base64url(struct wpabuf *json, const char *name, const void *val,
+ size_t len);
+void json_start_object(struct wpabuf *json, const char *name);
+void json_end_object(struct wpabuf *json);
+void json_start_array(struct wpabuf *json, const char *name);
+void json_end_array(struct wpabuf *json);
+void json_value_sep(struct wpabuf *json);
#endif /* JSON_H */
diff --git a/src/utils/utils_module_tests.c b/src/utils/utils_module_tests.c
index 3af4fcd..b09225d 100644
--- a/src/utils/utils_module_tests.c
+++ b/src/utils/utils_module_tests.c
@@ -296,52 +296,53 @@
{
int errors = 0;
unsigned char *res;
+ char *res2;
size_t res_len;
wpa_printf(MSG_INFO, "base64 tests");
- res = base64_encode((const unsigned char *) "", ~0, &res_len);
+ res2 = base64_encode("", ~0, &res_len);
+ if (res2) {
+ errors++;
+ os_free(res2);
+ }
+
+ res2 = base64_encode("=", 1, &res_len);
+ if (!res2 || res_len != 5 || res2[0] != 'P' || res2[1] != 'Q' ||
+ res2[2] != '=' || res2[3] != '=' || res2[4] != '\n')
+ errors++;
+ os_free(res2);
+
+ res2 = base64_encode("=", 1, NULL);
+ if (!res2 || res2[0] != 'P' || res2[1] != 'Q' ||
+ res2[2] != '=' || res2[3] != '=' || res2[4] != '\n')
+ errors++;
+ os_free(res2);
+
+ res = base64_decode("", 0, &res_len);
if (res) {
errors++;
os_free(res);
}
- res = base64_encode((const unsigned char *) "=", 1, &res_len);
- if (!res || res_len != 5 || res[0] != 'P' || res[1] != 'Q' ||
- res[2] != '=' || res[3] != '=' || res[4] != '\n')
- errors++;
- os_free(res);
-
- res = base64_encode((const unsigned char *) "=", 1, NULL);
- if (!res || res[0] != 'P' || res[1] != 'Q' ||
- res[2] != '=' || res[3] != '=' || res[4] != '\n')
- errors++;
- os_free(res);
-
- res = base64_decode((const unsigned char *) "", 0, &res_len);
+ res = base64_decode("a", 1, &res_len);
if (res) {
errors++;
os_free(res);
}
- res = base64_decode((const unsigned char *) "a", 1, &res_len);
+ res = base64_decode("====", 4, &res_len);
if (res) {
errors++;
os_free(res);
}
- res = base64_decode((const unsigned char *) "====", 4, &res_len);
- if (res) {
- errors++;
- os_free(res);
- }
-
- res = base64_decode((const unsigned char *) "PQ==", 4, &res_len);
+ res = base64_decode("PQ==", 4, &res_len);
if (!res || res_len != 1 || res[0] != '=')
errors++;
os_free(res);
- res = base64_decode((const unsigned char *) "P.Q-=!=*", 8, &res_len);
+ res = base64_decode("P.Q-=!=*", 8, &res_len);
if (!res || res_len != 1 || res[0] != '=')
errors++;
os_free(res);
diff --git a/src/utils/xml_libxml2.c b/src/utils/xml_libxml2.c
index 7b6d276..d73654e 100644
--- a/src/utils/xml_libxml2.c
+++ b/src/utils/xml_libxml2.c
@@ -409,7 +409,7 @@
if (txt == NULL)
return NULL;
- ret = base64_decode((unsigned char *) txt, strlen(txt), &len);
+ ret = base64_decode(txt, strlen(txt), &len);
if (ret_len)
*ret_len = len;
xml_node_get_text_free(ctx, txt);
diff --git a/src/wps/upnp_xml.c b/src/wps/upnp_xml.c
index a9958ee..ca0925c 100644
--- a/src/wps/upnp_xml.c
+++ b/src/wps/upnp_xml.c
@@ -235,7 +235,7 @@
return NULL;
}
- decoded = base64_decode((unsigned char *) msg, os_strlen(msg), &len);
+ decoded = base64_decode(msg, os_strlen(msg), &len);
os_free(msg);
if (decoded == NULL) {
*ret = UPNP_OUT_OF_MEMORY;
diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c
index 06a8fda..6bded14 100644
--- a/src/wps/wps_er.c
+++ b/src/wps/wps_er.c
@@ -897,7 +897,7 @@
const struct sockaddr_in *dst,
char **len_ptr, char **body_ptr)
{
- unsigned char *encoded;
+ char *encoded;
size_t encoded_len;
struct wpabuf *buf;
@@ -939,7 +939,7 @@
wpabuf_put_str(buf, "\">\n");
if (encoded) {
wpabuf_printf(buf, "<%s>%s</%s>\n",
- arg_name, (char *) encoded, arg_name);
+ arg_name, encoded, arg_name);
os_free(encoded);
}
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index 0ac5b28..671f5fe 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -1745,7 +1745,8 @@
return -1;
}
os_free(wps->new_psk);
- wps->new_psk = base64_encode(r, sizeof(r), &wps->new_psk_len);
+ wps->new_psk = (u8 *) base64_encode(r, sizeof(r),
+ &wps->new_psk_len);
if (wps->new_psk == NULL)
return -1;
wps->new_psk_len--; /* remove newline */
diff --git a/src/wps/wps_upnp.c b/src/wps/wps_upnp.c
index ca893a4..6e10e4b 100644
--- a/src/wps/wps_upnp.c
+++ b/src/wps/wps_upnp.c
@@ -519,8 +519,9 @@
dl_list_for_each_safe(s, tmp, &sm->subscriptions, struct subscription,
list) {
- event_add(s, buf,
- sm->wlanevent_type == UPNP_WPS_WLANEVENT_TYPE_PROBE);
+ wps_upnp_event_add(
+ s, buf,
+ sm->wlanevent_type == UPNP_WPS_WLANEVENT_TYPE_PROBE);
}
wpabuf_free(buf);
@@ -541,7 +542,7 @@
struct upnp_wps_device_interface *iface;
wpa_printf(MSG_DEBUG, "WPS UPnP: Destroy subscription %p", s);
subscr_addr_free_all(s);
- event_delete_all(s);
+ wps_upnp_event_delete_all(s);
dl_list_for_each(iface, &s->sm->interfaces,
struct upnp_wps_device_interface, list)
upnp_er_remove_notification(iface->wps->registrar, s);
@@ -647,7 +648,7 @@
"initial WLANEvent");
msg = build_fake_wsc_ack();
if (msg) {
- s->sm->wlanevent = (char *)
+ s->sm->wlanevent =
base64_encode(wpabuf_head(msg),
wpabuf_len(msg), NULL);
wpabuf_free(msg);
@@ -672,7 +673,7 @@
wpabuf_put_property(buf, "WLANEvent", wlan_event);
wpabuf_put_str(buf, tail);
- ret = event_add(s, buf, 0);
+ ret = wps_upnp_event_add(s, buf, 0);
if (ret) {
wpabuf_free(buf);
return ret;
@@ -749,7 +750,7 @@
"WPS UPnP: Subscription %p (SID %s) started with %s",
s, str, callback_urls);
/* Schedule sending this */
- event_send_all_later(sm);
+ wps_upnp_event_send_all_later(sm);
return s;
}
@@ -822,7 +823,7 @@
}
raw_len = pos;
- val = (char *) base64_encode(raw, raw_len, &val_len);
+ val = base64_encode(raw, raw_len, &val_len);
if (val == NULL)
goto fail;
@@ -987,7 +988,7 @@
advertisement_state_machine_stop(sm, 1);
- event_send_stop_all(sm);
+ wps_upnp_event_send_stop_all(sm);
os_free(sm->wlanevent);
sm->wlanevent = NULL;
os_free(sm->ip_addr_text);
diff --git a/src/wps/wps_upnp_event.c b/src/wps/wps_upnp_event.c
index 94aae75..d7e6edc 100644
--- a/src/wps/wps_upnp_event.c
+++ b/src/wps/wps_upnp_event.c
@@ -96,8 +96,8 @@
}
-/* event_delete_all -- delete entire event queue and current event */
-void event_delete_all(struct subscription *s)
+/* wps_upnp_event_delete_all -- delete entire event queue and current event */
+void wps_upnp_event_delete_all(struct subscription *s)
{
struct wps_event_ *e;
while ((e = event_dequeue(s)) != NULL)
@@ -134,11 +134,11 @@
event_delete(e);
s->last_event_failed = 1;
if (!dl_list_empty(&s->event_queue))
- event_send_all_later(s->sm);
+ wps_upnp_event_send_all_later(s->sm);
return;
}
dl_list_add(&s->event_queue, &e->list);
- event_send_all_later(sm);
+ wps_upnp_event_send_all_later(sm);
}
@@ -228,7 +228,7 @@
/* Schedule sending more if there is more to send */
if (!dl_list_empty(&s->event_queue))
- event_send_all_later(s->sm);
+ wps_upnp_event_send_all_later(s->sm);
break;
case HTTP_CLIENT_FAILED:
wpa_printf(MSG_DEBUG, "WPS UPnP: Event send failure");
@@ -328,19 +328,19 @@
if (nerrors) {
/* Try again later */
- event_send_all_later(sm);
+ wps_upnp_event_send_all_later(sm);
}
}
-/* event_send_all_later -- schedule sending events to all subscribers
+/* wps_upnp_event_send_all_later -- schedule sending events to all subscribers
* that need it.
* This avoids two problems:
* -- After getting a subscription, we should not send the first event
* until after our reply is fully queued to be sent back,
* -- Possible stack depth or infinite recursion issues.
*/
-void event_send_all_later(struct upnp_wps_device_sm *sm)
+void wps_upnp_event_send_all_later(struct upnp_wps_device_sm *sm)
{
/*
* The exact time in the future isn't too important. Waiting a bit
@@ -354,8 +354,8 @@
}
-/* event_send_stop_all -- cleanup */
-void event_send_stop_all(struct upnp_wps_device_sm *sm)
+/* wps_upnp_event_send_stop_all -- cleanup */
+void wps_upnp_event_send_stop_all(struct upnp_wps_device_sm *sm)
{
if (sm->event_send_all_queued)
eloop_cancel_timeout(event_send_all_later_handler, NULL, sm);
@@ -364,13 +364,14 @@
/**
- * event_add - Add a new event to a queue
+ * wps_upnp_event_add - Add a new event to a queue
* @s: Subscription
* @data: Event data (is copied; caller retains ownership)
* @probereq: Whether this is a Probe Request event
* Returns: 0 on success, -1 on error, 1 on max event queue limit reached
*/
-int event_add(struct subscription *s, const struct wpabuf *data, int probereq)
+int wps_upnp_event_add(struct subscription *s, const struct wpabuf *data,
+ int probereq)
{
struct wps_event_ *e;
unsigned int len;
@@ -416,6 +417,6 @@
wpa_printf(MSG_DEBUG, "WPS UPnP: Queue event %p for subscriber %p "
"(queue len %u)", e, s, len + 1);
dl_list_add_tail(&s->event_queue, &e->list);
- event_send_all_later(s->sm);
+ wps_upnp_event_send_all_later(s->sm);
return 0;
}
diff --git a/src/wps/wps_upnp_i.h b/src/wps/wps_upnp_i.h
index 6a7c627..e87a932 100644
--- a/src/wps/wps_upnp_i.h
+++ b/src/wps/wps_upnp_i.h
@@ -177,10 +177,11 @@
void web_listener_stop(struct upnp_wps_device_sm *sm);
/* wps_upnp_event.c */
-int event_add(struct subscription *s, const struct wpabuf *data, int probereq);
-void event_delete_all(struct subscription *s);
-void event_send_all_later(struct upnp_wps_device_sm *sm);
-void event_send_stop_all(struct upnp_wps_device_sm *sm);
+int wps_upnp_event_add(struct subscription *s, const struct wpabuf *data,
+ int probereq);
+void wps_upnp_event_delete_all(struct subscription *s);
+void wps_upnp_event_send_all_later(struct upnp_wps_device_sm *sm);
+void wps_upnp_event_send_stop_all(struct upnp_wps_device_sm *sm);
/* wps_upnp_ap.c */
int upnp_er_set_selected_registrar(struct wps_registrar *reg,
diff --git a/src/wps/wps_upnp_web.c b/src/wps/wps_upnp_web.c
index 7548e84..3c5a97c 100644
--- a/src/wps/wps_upnp_web.c
+++ b/src/wps/wps_upnp_web.c
@@ -765,8 +765,8 @@
if (reply) {
size_t len;
- replydata = (char *) base64_encode(wpabuf_head(reply),
- wpabuf_len(reply), &len);
+ replydata = base64_encode(wpabuf_head(reply), wpabuf_len(reply),
+ &len);
} else
replydata = NULL;
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index 5815b86..309127e 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -263,6 +263,9 @@
NEED_ECC=y
NEED_DH_GROUPS=y
NEED_DRAGONFLY=y
+ifdef CONFIG_TESTING_OPTIONS
+NEED_DH_GROUPS_ALL=y
+endif
endif
ifdef CONFIG_DPP
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index b478466..68ef5a2 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -265,6 +265,9 @@
NEED_ECC=y
NEED_DH_GROUPS=y
NEED_DRAGONFLY=y
+ifdef CONFIG_TESTING_OPTIONS
+NEED_DH_GROUPS_ALL=y
+endif
endif
ifdef CONFIG_DPP
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 59ca153..e552306 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -775,7 +775,8 @@
ssid->frequency = 2462; /* default channel 11 */
params.freq.freq = ssid->frequency;
- if (ssid->mode == WPAS_MODE_AP && ssid->enable_edmg) {
+ if ((ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO) &&
+ ssid->enable_edmg) {
u8 primary_channel;
if (ieee80211_freq_to_chan(ssid->frequency, &primary_channel) ==
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index d100c46..2d1c126 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -4950,6 +4950,7 @@
{ INT(p2p_go_ht40), 0 },
{ INT(p2p_go_vht), 0 },
{ INT(p2p_go_he), 0 },
+ { INT(p2p_go_edmg), 0 },
{ INT(p2p_disabled), 0 },
{ INT_RANGE(p2p_go_ctwindow, 0, 127), 0 },
{ INT(p2p_no_group_iface), 0 },
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 922a75e..d00c4ec 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -1090,6 +1090,16 @@
int p2p_go_vht;
/**
+ * p2p_go_edmg - Default mode for EDMG enable when operating as GO
+ *
+ * This will take effect for p2p_group_add, p2p_connect, and p2p_invite.
+ * Note that regulatory constraints and driver capabilities are
+ * consulted anyway, so setting it to 1 can't do real harm.
+ * By default: 0 (disabled)
+ */
+ int p2p_go_edmg;
+
+ /**
* p2p_go_he - Default mode for 11ax HE enable when operating as GO
*
* This will take effect for p2p_group_add, p2p_connect, and p2p_invite.
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 7651465..305291e 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -296,7 +296,7 @@
{
struct wpa_config_blob *blob;
char buf[256], *pos;
- unsigned char *encoded = NULL, *nencoded;
+ char *encoded = NULL, *nencoded;
int end = 0;
size_t encoded_len = 0, len;
@@ -1098,7 +1098,7 @@
#ifndef CONFIG_NO_CONFIG_BLOBS
static int wpa_config_write_blob(FILE *f, struct wpa_config_blob *blob)
{
- unsigned char *encoded;
+ char *encoded;
encoded = base64_encode(blob->data, blob->len, NULL);
if (encoded == NULL)
@@ -1287,6 +1287,8 @@
fprintf(f, "p2p_go_vht=%d\n", config->p2p_go_vht);
if (config->p2p_go_he)
fprintf(f, "p2p_go_he=%d\n", config->p2p_go_he);
+ if (config->p2p_go_edmg)
+ fprintf(f, "p2p_go_edmg=%d\n", config->p2p_go_edmg);
if (config->p2p_go_ctwindow != DEFAULT_P2P_GO_CTWINDOW)
fprintf(f, "p2p_go_ctwindow=%d\n", config->p2p_go_ctwindow);
if (config->p2p_disabled)
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 7f8ec4a..be5ea17 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -663,6 +663,42 @@
wpa_s->ignore_assoc_disallow = !!atoi(value);
wpa_drv_ignore_assoc_disallow(wpa_s,
wpa_s->ignore_assoc_disallow);
+ } else if (os_strcasecmp(cmd, "ignore_sae_h2e_only") == 0) {
+ wpa_s->ignore_sae_h2e_only = !!atoi(value);
+ } else if (os_strcasecmp(cmd, "extra_sae_rejected_groups") == 0) {
+ char *pos;
+
+ os_free(wpa_s->extra_sae_rejected_groups);
+ wpa_s->extra_sae_rejected_groups = NULL;
+ pos = value;
+ while (pos && pos[0]) {
+ int group;
+
+ group = atoi(pos);
+ wpa_printf(MSG_DEBUG,
+ "TESTING: Extra rejection of SAE group %d",
+ group);
+ if (group)
+ int_array_add_unique(
+ &wpa_s->extra_sae_rejected_groups,
+ group);
+ pos = os_strchr(pos, ' ');
+ if (!pos)
+ break;
+ pos++;
+ }
+ } else if (os_strcasecmp(cmd, "rsnxe_override_assoc") == 0) {
+ wpabuf_free(wpa_s->rsnxe_override_assoc);
+ if (os_strcmp(value, "NULL") == 0)
+ wpa_s->rsnxe_override_assoc = NULL;
+ else
+ wpa_s->rsnxe_override_assoc = wpabuf_parse_bin(value);
+ } else if (os_strcasecmp(cmd, "rsnxe_override_eapol") == 0) {
+ wpabuf_free(wpa_s->rsnxe_override_eapol);
+ if (os_strcmp(value, "NULL") == 0)
+ wpa_s->rsnxe_override_eapol = NULL;
+ else
+ wpa_s->rsnxe_override_eapol = wpabuf_parse_bin(value);
} else if (os_strcasecmp(cmd, "reject_btm_req_reason") == 0) {
wpa_s->reject_btm_req_reason = atoi(value);
} else if (os_strcasecmp(cmd, "get_pref_freq_list_override") == 0) {
@@ -5637,6 +5673,7 @@
int freq = 0;
int pd;
int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
+ int edmg;
u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL;
size_t group_ssid_len = 0;
int he;
@@ -5652,7 +5689,7 @@
/* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps]
* [persistent|persistent=<network id>]
* [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
- * [ht40] [vht] [he] [auto] [ssid=<hexdump>] */
+ * [ht40] [vht] [he] [edmg] [auto] [ssid=<hexdump>] */
if (hwaddr_aton(cmd, addr))
return -1;
@@ -5684,6 +5721,7 @@
ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
vht;
he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
+ edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg;
pos2 = os_strstr(pos, " go_intent=");
if (pos2) {
@@ -5754,7 +5792,7 @@
new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
persistent_group, automatic, join,
auth, go_intent, freq, freq2, persistent_id,
- pd, ht40, vht, max_oper_chwidth, he,
+ pd, ht40, vht, max_oper_chwidth, he, edmg,
group_ssid, group_ssid_len);
if (new_pin == -2) {
os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
@@ -6311,6 +6349,7 @@
u8 *_peer = NULL, peer[ETH_ALEN];
int freq = 0, pref_freq = 0;
int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0;
+ int edmg;
id = atoi(cmd);
pos = os_strstr(cmd, " peer=");
@@ -6348,6 +6387,7 @@
ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
vht;
he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he;
+ edmg = (os_strstr(cmd, " edmg") != NULL) || wpa_s->conf->p2p_go_edmg;
pos = os_strstr(cmd, "freq2=");
if (pos)
@@ -6362,7 +6402,7 @@
return -1;
return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
- max_oper_chwidth, pref_freq, he);
+ max_oper_chwidth, pref_freq, he, edmg);
}
@@ -6411,7 +6451,7 @@
static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
int id, int freq, int vht_center_freq2,
int ht40, int vht, int vht_chwidth,
- int he)
+ int he, int edmg)
{
struct wpa_ssid *ssid;
@@ -6425,7 +6465,8 @@
return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq,
vht_center_freq2, 0, ht40, vht,
- vht_chwidth, he, NULL, 0, 0);
+ vht_chwidth, he, edmg,
+ NULL, 0, 0);
}
@@ -6435,6 +6476,7 @@
int vht = wpa_s->conf->p2p_go_vht;
int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
int he = wpa_s->conf->p2p_go_he;
+ int edmg = wpa_s->conf->p2p_go_edmg;
int max_oper_chwidth, chwidth = 0, freq2 = 0;
char *token, *context = NULL;
#ifdef CONFIG_ACS
@@ -6459,6 +6501,8 @@
ht40 = 1;
} else if (os_strcmp(token, "he") == 0) {
he = 1;
+ } else if (os_strcmp(token, "edmg") == 0) {
+ edmg = 1;
} else if (os_strcmp(token, "persistent") == 0) {
persistent = 1;
} else {
@@ -6496,10 +6540,11 @@
if (group_id >= 0)
return p2p_ctrl_group_add_persistent(wpa_s, group_id,
freq, freq2, ht40, vht,
- max_oper_chwidth, he);
+ max_oper_chwidth, he,
+ edmg);
return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht,
- max_oper_chwidth, he);
+ max_oper_chwidth, he, edmg);
}
@@ -8045,12 +8090,19 @@
wpa_s->ignore_auth_resp = 0;
wpa_s->ignore_assoc_disallow = 0;
wpa_s->testing_resend_assoc = 0;
+ wpa_s->ignore_sae_h2e_only = 0;
wpa_s->reject_btm_req_reason = 0;
wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL);
os_free(wpa_s->get_pref_freq_list_override);
wpa_s->get_pref_freq_list_override = NULL;
wpabuf_free(wpa_s->sae_commit_override);
wpa_s->sae_commit_override = NULL;
+ os_free(wpa_s->extra_sae_rejected_groups);
+ wpa_s->extra_sae_rejected_groups = NULL;
+ wpabuf_free(wpa_s->rsnxe_override_assoc);
+ wpa_s->rsnxe_override_assoc = NULL;
+ wpabuf_free(wpa_s->rsnxe_override_eapol);
+ wpa_s->rsnxe_override_eapol = NULL;
#ifdef CONFIG_DPP
os_free(wpa_s->dpp_config_obj_override);
wpa_s->dpp_config_obj_override = NULL;
@@ -9465,16 +9517,16 @@
if (pos[0] != WLAN_EID_NEIGHBOR_REPORT ||
nr_len < NR_IE_MIN_LEN) {
- wpa_printf(MSG_DEBUG,
- "CTRL: Invalid Neighbor Report element: id=%u len=%u",
- data[0], nr_len);
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "CTRL: Invalid Neighbor Report element: id=%u len=%u",
+ data[0], nr_len);
goto out;
}
if (2U + nr_len > len) {
- wpa_printf(MSG_DEBUG,
- "CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u",
- data[0], len, nr_len);
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u",
+ data[0], len, nr_len);
goto out;
}
pos += 2;
@@ -9544,8 +9596,8 @@
ssid_s = os_strstr(cmd, "ssid=");
if (ssid_s) {
if (ssid_parse(ssid_s + 5, &ssid)) {
- wpa_printf(MSG_ERROR,
- "CTRL: Send Neighbor Report: bad SSID");
+ wpa_msg(wpa_s, MSG_INFO,
+ "CTRL: Send Neighbor Report: bad SSID");
return -1;
}
@@ -10678,6 +10730,17 @@
if (os_snprintf_error(reply_size, reply_len))
reply_len = -1;
}
+ } else if (os_strncmp(buf, "DPP_NFC_URI ", 12) == 0) {
+ int res;
+
+ res = wpas_dpp_nfc_uri(wpa_s, buf + 12);
+ if (res < 0) {
+ reply_len = -1;
+ } else {
+ reply_len = os_snprintf(reply, reply_size, "%d", res);
+ if (os_snprintf_error(reply_size, reply_len))
+ reply_len = -1;
+ }
} else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) {
int res;
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 5e6b522..e9e77bd 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -2855,30 +2855,6 @@
NULL,
NULL
},
- {
- "RoamTime", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
- wpas_dbus_getter_roam_time,
- NULL,
- NULL
- },
- {
- "RoamComplete", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
- wpas_dbus_getter_roam_complete,
- NULL,
- NULL
- },
- {
- "SessionLength", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
- wpas_dbus_getter_session_length,
- NULL,
- NULL
- },
- {
- "BSSTMStatus", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
- wpas_dbus_getter_bss_tm_status,
- NULL,
- NULL
- },
{ NULL, NULL, NULL, NULL, NULL, NULL }
};
@@ -3786,6 +3762,30 @@
NULL,
NULL
},
+ {
+ "RoamTime", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
+ wpas_dbus_getter_roam_time,
+ NULL,
+ NULL
+ },
+ {
+ "RoamComplete", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
+ wpas_dbus_getter_roam_complete,
+ NULL,
+ NULL
+ },
+ {
+ "SessionLength", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
+ wpas_dbus_getter_session_length,
+ NULL,
+ NULL
+ },
+ {
+ "BSSTMStatus", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
+ wpas_dbus_getter_bss_tm_status,
+ NULL,
+ NULL
+ },
#ifdef CONFIG_MESH
{ "MeshPeers", WPAS_DBUS_NEW_IFACE_MESH, "aay",
wpas_dbus_getter_mesh_peers,
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index 2582092..4b6dabc 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -137,8 +137,15 @@
static const char * const dont_quote[] = {
"key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
- "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
- "bssid", "scan_freq", "freq_list", NULL
+ "bssid", "scan_freq", "freq_list", "scan_ssid", "bssid_hint",
+ "bssid_blacklist", "bssid_whitelist", "group_mgmt",
+#ifdef CONFIG_MESH
+ "mesh_basic_rates",
+#endif /* CONFIG_MESH */
+#ifdef CONFIG_P2P
+ "go_p2p_dev_addr", "p2p_client_list", "psk_list",
+#endif /* CONFIG_P2P */
+ NULL
};
static dbus_bool_t should_quote_opt(const char *key)
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index 19715eb..7a65673 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -425,14 +425,14 @@
goto inv_args;
if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
- 0, 0, 0, NULL, 0, 0)) {
+ 0, 0, 0, 0, NULL, 0, 0)) {
reply = wpas_dbus_error_unknown_error(
message,
"Failed to reinvoke a persistent group");
goto out;
}
} else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0, 0,
- 0, 0))
+ 0, 0, 0))
goto inv_args;
out:
@@ -652,7 +652,7 @@
new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
persistent_group, 0, join, authorize_only,
- go_intent, freq, 0, -1, 0, 0, 0, 0, 0,
+ go_intent, freq, 0, -1, 0, 0, 0, 0, 0, 0,
NULL, 0);
if (new_pin >= 0) {
@@ -810,7 +810,7 @@
goto err;
if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0, 0,
- 0, 0) < 0) {
+ 0, 0, 0) < 0) {
reply = wpas_dbus_error_unknown_error(
message,
"Failed to reinvoke a persistent group");
diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c
index a436930..73649c2 100644
--- a/wpa_supplicant/dpp_supplicant.c
+++ b/wpa_supplicant/dpp_supplicant.c
@@ -89,6 +89,24 @@
}
+/**
+ * wpas_dpp_nfc_uri - Parse and add DPP bootstrapping info from NFC Tag (URI)
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @cmd: DPP URI read from a NFC Tag (URI NDEF message)
+ * Returns: Identifier of the stored info or -1 on failure
+ */
+int wpas_dpp_nfc_uri(struct wpa_supplicant *wpa_s, const char *cmd)
+{
+ struct dpp_bootstrap_info *bi;
+
+ bi = dpp_add_nfc_uri(wpa_s->dpp, cmd);
+ if (!bi)
+ return -1;
+
+ return bi->id;
+}
+
+
static void wpas_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_supplicant *wpa_s = eloop_ctx;
@@ -180,6 +198,8 @@
result = DPP_STATUS_NO_AP;
else
result = 255; /* What to report here for unexpected state? */
+ if (wpa_s->wpa_state == WPA_SCANNING)
+ wpas_abort_ongoing_scan(wpa_s);
wpas_dpp_send_conn_status_result(wpa_s, result);
}
@@ -663,7 +683,12 @@
pos = os_strstr(cmd, " netrole=");
if (pos) {
pos += 9;
- wpa_s->dpp_netrole_ap = os_strncmp(pos, "ap", 2) == 0;
+ if (os_strncmp(pos, "ap", 2) == 0)
+ wpa_s->dpp_netrole = DPP_NETROLE_AP;
+ else if (os_strncmp(pos, "configurator", 12) == 0)
+ wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
+ else
+ wpa_s->dpp_netrole = DPP_NETROLE_STA;
}
pos = os_strstr(cmd, " neg_freq=");
@@ -815,7 +840,12 @@
wpa_s->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
DPP_CAPAB_ENROLLEE;
wpa_s->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
- wpa_s->dpp_netrole_ap = os_strstr(cmd, " netrole=ap") != NULL;
+ if (os_strstr(cmd, " netrole=ap"))
+ wpa_s->dpp_netrole = DPP_NETROLE_AP;
+ else if (os_strstr(cmd, " netrole=configurator"))
+ wpa_s->dpp_netrole = DPP_NETROLE_CONFIGURATOR;
+ else
+ wpa_s->dpp_netrole = DPP_NETROLE_STA;
if (wpa_s->dpp_listen_freq == (unsigned int) freq) {
wpa_printf(MSG_DEBUG, "DPP: Already listening on %u MHz",
freq);
@@ -1120,6 +1150,9 @@
if (conf->ssid_len)
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
wpa_ssid_txt(conf->ssid, conf->ssid_len));
+ if (conf->ssid_charset)
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID_CHARSET "%d",
+ conf->ssid_charset);
if (conf->connector) {
/* TODO: Save the Connector and consider using a command
* to fetch the value instead of sending an event with
@@ -1283,7 +1316,7 @@
supp_op_classes = wpas_supp_op_classes(wpa_s);
buf = dpp_build_conf_req_helper(auth, wpa_s->conf->dpp_name,
- wpa_s->dpp_netrole_ap,
+ wpa_s->dpp_netrole,
wpa_s->conf->dpp_mud_url,
supp_op_classes);
os_free(supp_op_classes);
diff --git a/wpa_supplicant/dpp_supplicant.h b/wpa_supplicant/dpp_supplicant.h
index b337982..607036a 100644
--- a/wpa_supplicant/dpp_supplicant.h
+++ b/wpa_supplicant/dpp_supplicant.h
@@ -13,6 +13,7 @@
enum dpp_status_error;
int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd);
+int wpas_dpp_nfc_uri(struct wpa_supplicant *wpa_s, const char *cmd);
int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd);
int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd);
void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s);
diff --git a/wpa_supplicant/eapol_test.c b/wpa_supplicant/eapol_test.c
index 524724f..53d7585 100644
--- a/wpa_supplicant/eapol_test.c
+++ b/wpa_supplicant/eapol_test.c
@@ -439,7 +439,7 @@
static void eapol_test_write_cert(FILE *f, const char *subject,
const struct wpabuf *cert)
{
- unsigned char *encoded;
+ char *encoded;
encoded = base64_encode(wpabuf_head(cert), wpabuf_len(cert), NULL);
if (encoded == NULL)
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 139402e..15ef0f7 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -857,6 +857,13 @@
if (debug_print)
wpa_dbg(wpa_s, MSG_DEBUG,
" SAE H2E disabled");
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->ignore_sae_h2e_only) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "TESTING: Ignore SAE H2E requirement mismatch");
+ continue;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
return 0;
}
continue;
@@ -1914,7 +1921,7 @@
if (wnm_scan_process(wpa_s, 1) > 0)
goto scan_work_done;
- if (sme_proc_obss_scan(wpa_s) > 0)
+ if (sme_proc_obss_scan(wpa_s, scan_res) > 0)
goto scan_work_done;
if (own_request && data &&
@@ -2939,6 +2946,16 @@
wpa_s->last_eapol_matches_bssid = 0;
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->rsnxe_override_eapol) {
+ wpa_printf(MSG_DEBUG,
+ "TESTING: RSNXE EAPOL-Key msg 2/4 override");
+ wpa_sm_set_assoc_rsnxe(wpa_s->wpa,
+ wpabuf_head(wpa_s->rsnxe_override_eapol),
+ wpabuf_len(wpa_s->rsnxe_override_eapol));
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+
if (wpa_s->pending_eapol_rx) {
struct os_reltime now, age;
os_get_reltime(&now);
@@ -3054,9 +3071,10 @@
int locally_generated)
{
if (wpa_s->wpa_state != WPA_4WAY_HANDSHAKE ||
+ !wpa_s->new_connection ||
!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
wpa_key_mgmt_sae(wpa_s->key_mgmt))
- return 0; /* Not in 4-way handshake with PSK */
+ return 0; /* Not in initial 4-way handshake with PSK */
/*
* It looks like connection was lost while trying to go through PSK
diff --git a/wpa_supplicant/hidl/1.3/p2p_iface.cpp b/wpa_supplicant/hidl/1.3/p2p_iface.cpp
index ee53f71..833d624 100644
--- a/wpa_supplicant/hidl/1.3/p2p_iface.cpp
+++ b/wpa_supplicant/hidl/1.3/p2p_iface.cpp
@@ -331,6 +331,7 @@
const std::string& passphrase)
{
int ret = 0;
+ int he = wpa_s->conf->p2p_go_he;
int vht = wpa_s->conf->p2p_go_vht;
int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
@@ -349,7 +350,7 @@
if (wpas_p2p_group_add_persistent(
wpa_s, wpa_network, 0, 0, 0, 0, ht40, vht,
- CHANWIDTH_USE_HT, 0, NULL, 0, 0)) {
+ CHANWIDTH_USE_HT, he, 0, NULL, 0, 0)) {
ret = -1;
}
@@ -1061,6 +1062,7 @@
wps_method = WPS_PIN_KEYPAD;
break;
}
+ int he = wpa_s->conf->p2p_go_he;
int vht = wpa_s->conf->p2p_go_vht;
int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
const char* pin =
@@ -1068,7 +1070,7 @@
int new_pin = wpas_p2p_connect(
wpa_s, peer_address.data(), pin, wps_method, persistent, false,
join_existing_group, false, go_intent_signed, 0, 0, -1, false, ht40,
- vht, CHANWIDTH_USE_HT, 0, nullptr, 0);
+ vht, CHANWIDTH_USE_HT, he, 0, nullptr, 0);
if (new_pin < 0) {
return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
}
@@ -1124,6 +1126,7 @@
bool persistent, SupplicantNetworkId persistent_network_id)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ int he = wpa_s->conf->p2p_go_he;
int vht = wpa_s->conf->p2p_go_vht;
int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
struct wpa_ssid* ssid =
@@ -1131,7 +1134,7 @@
if (ssid == NULL) {
if (wpas_p2p_group_add(
wpa_s, persistent, 0, 0, ht40, vht,
- CHANWIDTH_USE_HT, 0)) {
+ CHANWIDTH_USE_HT, he, 0)) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
} else {
return {SupplicantStatusCode::SUCCESS, ""};
@@ -1139,7 +1142,7 @@
} else if (ssid->disabled == 2) {
if (wpas_p2p_group_add_persistent(
wpa_s, ssid, 0, 0, 0, 0, ht40, vht,
- CHANWIDTH_USE_HT, 0, NULL, 0, 0)) {
+ CHANWIDTH_USE_HT, he, 0, NULL, 0, 0)) {
return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN,
""};
} else {
@@ -1194,6 +1197,7 @@
const std::array<uint8_t, 6>& peer_address)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ int he = wpa_s->conf->p2p_go_he;
int vht = wpa_s->conf->p2p_go_vht;
int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
struct wpa_ssid* ssid =
@@ -1203,7 +1207,7 @@
}
if (wpas_p2p_invite(
wpa_s, peer_address.data(), ssid, NULL, 0, 0, ht40, vht,
- CHANWIDTH_USE_HT, 0, 0)) {
+ CHANWIDTH_USE_HT, 0, he, 0)) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
@@ -1632,6 +1636,7 @@
bool joinExistingGroup)
{
struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ int he = wpa_s->conf->p2p_go_he;
int vht = wpa_s->conf->p2p_go_vht;
int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
@@ -1659,7 +1664,7 @@
if (wpas_p2p_group_add(
wpa_s, persistent, freq, 0, ht40, vht,
- CHANWIDTH_USE_HT, 0)) {
+ CHANWIDTH_USE_HT, he, 0)) {
return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
}
return {SupplicantStatusCode::SUCCESS, ""};
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index e81fef1..741f925 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -341,7 +341,7 @@
{
struct icon_entry *icon;
size_t out_size;
- unsigned char *b64;
+ char *b64;
size_t b64_size;
int reply_size;
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index 585b7f0..dc51418 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -176,7 +176,7 @@
continue;
if (!cred->eap_method)
return 1;
- if (cred->realm && cred->roaming_consortium_len == 0)
+ if (cred->realm)
return 1;
}
return 0;
diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
index 5c1a47d..b504124 100644
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -114,8 +114,14 @@
}
conf->group_cipher = cipher;
- if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION)
- conf->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
+ if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
+ if (ssid->group_mgmt_cipher == WPA_CIPHER_BIP_GMAC_128 ||
+ ssid->group_mgmt_cipher == WPA_CIPHER_BIP_GMAC_256 ||
+ ssid->group_mgmt_cipher == WPA_CIPHER_BIP_CMAC_256)
+ conf->mgmt_group_cipher = ssid->group_mgmt_cipher;
+ else
+ conf->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
+ }
/* defaults */
conf->mesh_pp_id = MESH_PATH_PROTOCOL_HWMP;
diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c
index 4a163b6..308366f 100644
--- a/wpa_supplicant/mesh_mpm.c
+++ b/wpa_supplicant/mesh_mpm.c
@@ -231,7 +231,7 @@
2 + 32 + /* mesh ID */
2 + 7 + /* mesh config */
2 + 24 + /* peering management */
- 2 + 96 + /* AMPE */
+ 2 + 96 + 32 + 32 + /* AMPE (96 + max GTKlen + max IGTKlen) */
2 + 16; /* MIC */
#ifdef CONFIG_IEEE80211N
if (type != PLINK_CLOSE && wpa_s->mesh_ht_enabled) {
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index fb509a1..a3c4574 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -1885,6 +1885,83 @@
}
+/**
+ * wpas_p2p_freq_to_edmg_channel - Convert frequency into EDMG channel
+ * @freq: Frequency (MHz) to convert
+ * @op_class: Buffer for returning operating class
+ * @op_edmg_channel: Buffer for returning channel number
+ * Returns: 0 on success, -1 on failure
+ *
+ * This can be used to find the highest channel bonding which includes the
+ * specified frequency.
+ */
+static int wpas_p2p_freq_to_edmg_channel(struct wpa_supplicant *wpa_s,
+ unsigned int freq,
+ u8 *op_class, u8 *op_edmg_channel)
+{
+ struct hostapd_hw_modes *hwmode;
+ struct ieee80211_edmg_config edmg;
+ unsigned int i;
+ enum chan_width chanwidth[] = {
+ CHAN_WIDTH_8640,
+ CHAN_WIDTH_6480,
+ CHAN_WIDTH_4320,
+ };
+
+ if (!wpa_s->hw.modes)
+ return -1;
+
+ hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
+ HOSTAPD_MODE_IEEE80211AD);
+ if (!hwmode) {
+ wpa_printf(MSG_ERROR,
+ "Unsupported AP mode: HOSTAPD_MODE_IEEE80211AD");
+ return -1;
+ }
+
+ /* Find the highest EDMG channel bandwidth to start the P2P GO */
+ for (i = 0; i < ARRAY_SIZE(chanwidth); i++) {
+ if (ieee80211_chaninfo_to_channel(freq, chanwidth[i], 0,
+ op_class,
+ op_edmg_channel) < 0)
+ continue;
+
+ hostapd_encode_edmg_chan(1, *op_edmg_channel, 0, &edmg);
+ if (edmg.channels &&
+ ieee802_edmg_is_allowed(hwmode->edmg, edmg)) {
+ wpa_printf(MSG_DEBUG,
+ "Freq %u to EDMG channel %u at opclass %u",
+ freq, *op_edmg_channel, *op_class);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+
+int wpas_p2p_try_edmg_channel(struct wpa_supplicant *wpa_s,
+ struct p2p_go_neg_results *params)
+{
+ u8 op_channel, op_class;
+ int freq;
+
+ /* Try social channel as primary channel frequency */
+ freq = (!params->freq) ? 58320 + 1 * 2160 : params->freq;
+
+ if (wpas_p2p_freq_to_edmg_channel(wpa_s, freq, &op_class,
+ &op_channel) == 0) {
+ wpa_printf(MSG_DEBUG,
+ "Freq %d will be used to set an EDMG connection (channel=%u opclass=%u)",
+ freq, op_channel, op_class);
+ params->freq = freq;
+ return 0;
+ }
+
+ return -1;
+}
+
+
static void wpas_start_wps_go(struct wpa_supplicant *wpa_s,
struct p2p_go_neg_results *params,
int group_formation)
@@ -1921,6 +1998,20 @@
ssid->max_oper_chwidth = params->max_oper_chwidth;
ssid->vht_center_freq2 = params->vht_center_freq2;
ssid->he = params->he;
+ if (params->edmg) {
+ u8 op_channel, op_class;
+
+ if (!wpas_p2p_freq_to_edmg_channel(wpa_s, params->freq,
+ &op_class, &op_channel)) {
+ ssid->edmg_channel = op_channel;
+ ssid->enable_edmg = params->edmg;
+ } else {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "P2P: Could not match EDMG channel, freq %d, for GO",
+ params->freq);
+ }
+ }
+
ssid->ssid = os_zalloc(params->ssid_len + 1);
if (ssid->ssid) {
os_memcpy(ssid->ssid, params->ssid, params->ssid_len);
@@ -2270,6 +2361,8 @@
res->vht = 1;
if (wpa_s->p2p_go_he)
res->he = 1;
+ if (wpa_s->p2p_go_edmg)
+ res->edmg = 1;
res->max_oper_chwidth = wpa_s->p2p_go_max_oper_chwidth;
res->vht_center_freq2 = wpa_s->p2p_go_vht_center_freq2;
@@ -3099,7 +3192,8 @@
MAC2STR(sa), s->id);
}
wpas_p2p_group_add_persistent(
- wpa_s, s, go, 0, op_freq, 0, 0, 0, 0, 0, NULL,
+ wpa_s, s, go, 0, op_freq, 0, 0, 0, 0, 0,
+ 0, NULL,
go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0,
1);
} else if (bssid) {
@@ -3326,6 +3420,7 @@
wpa_s->p2p_go_ht40, wpa_s->p2p_go_vht,
wpa_s->p2p_go_max_oper_chwidth,
wpa_s->p2p_go_he,
+ wpa_s->p2p_go_edmg,
channels,
ssid->mode == WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
@@ -3570,6 +3665,20 @@
}
+static enum chan_allowed wpas_p2p_verify_edmg(struct wpa_supplicant *wpa_s,
+ struct hostapd_hw_modes *mode,
+ u8 channel)
+{
+ struct ieee80211_edmg_config edmg;
+
+ hostapd_encode_edmg_chan(1, channel, 0, &edmg);
+ if (edmg.channels && ieee802_edmg_is_allowed(mode->edmg, edmg))
+ return ALLOWED;
+
+ return NOT_ALLOWED;
+}
+
+
static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode,
u8 channel, u8 bw)
@@ -3590,6 +3699,8 @@
res2 = wpas_p2p_verify_80mhz(wpa_s, mode, channel, bw);
} else if (bw == BW160) {
res2 = wpas_p2p_verify_160mhz(wpa_s, mode, channel, bw);
+ } else if (bw == BW4320 || bw == BW6480 || bw == BW8640) {
+ return wpas_p2p_verify_edmg(wpa_s, mode, channel);
}
if (res == NOT_ALLOWED || res2 == NOT_ALLOWED)
@@ -4240,14 +4351,14 @@
if (response_done && persistent_go) {
wpas_p2p_group_add_persistent(
wpa_s, persistent_go,
- 0, 0, freq, 0, 0, 0, 0, 0, NULL,
+ 0, 0, freq, 0, 0, 0, 0, 0, 0, NULL,
persistent_go->mode ==
WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
0, 0);
} else if (response_done) {
wpas_p2p_group_add(wpa_s, 1, freq,
- 0, 0, 0, 0, 0);
+ 0, 0, 0, 0, 0, 0);
}
if (passwd_id == DEV_PW_P2PS_DEFAULT) {
@@ -4363,11 +4474,12 @@
if (persistent_go) {
wpas_p2p_group_add_persistent(
- wpa_s, persistent_go, 0, 0, 0, 0, 0, 0, 0, 0, NULL,
+ wpa_s, persistent_go, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ NULL,
persistent_go->mode == WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 0);
} else {
- wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0, 0);
+ wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0, 0, 0);
}
return 1;
@@ -4950,6 +5062,7 @@
wpa_s->p2p_go_vht,
wpa_s->p2p_go_max_oper_chwidth,
wpa_s->p2p_go_he,
+ wpa_s->p2p_go_edmg,
NULL, 0);
return;
}
@@ -5498,8 +5611,8 @@
int persistent_group, int auto_join, int join, int auth,
int go_intent, int freq, unsigned int vht_center_freq2,
int persistent_id, int pd, int ht40, int vht,
- unsigned int vht_chwidth, int he, const u8 *group_ssid,
- size_t group_ssid_len)
+ unsigned int vht_chwidth, int he, int edmg,
+ const u8 *group_ssid, size_t group_ssid_len)
{
int force_freq = 0, pref_freq = 0;
int ret = 0, res;
@@ -5544,6 +5657,7 @@
wpa_s->p2p_go_vht_center_freq2 = vht_center_freq2;
wpa_s->p2p_go_max_oper_chwidth = vht_chwidth;
wpa_s->p2p_go_he = !!he;
+ wpa_s->p2p_go_edmg = !!edmg;
if (pin)
os_strlcpy(wpa_s->p2p_pin, pin, sizeof(wpa_s->p2p_pin));
@@ -5968,6 +6082,7 @@
struct p2p_go_neg_results *params,
int freq, int vht_center_freq2, int ht40,
int vht, int max_oper_chwidth, int he,
+ int edmg,
const struct p2p_channels *channels)
{
struct wpa_used_freq_data *freqs;
@@ -5983,6 +6098,7 @@
params->he = he;
params->max_oper_chwidth = max_oper_chwidth;
params->vht_center_freq2 = vht_center_freq2;
+ params->edmg = edmg;
freqs = os_calloc(wpa_s->num_multichan_concurrent,
sizeof(struct wpa_used_freq_data));
@@ -6013,6 +6129,13 @@
}
}
+ /* Try to use EDMG channel */
+ if (params->edmg) {
+ if (wpas_p2p_try_edmg_channel(wpa_s, params) == 0)
+ goto success;
+ params->edmg = 0;
+ }
+
/* try using the forced freq */
if (freq) {
if (wpas_p2p_disallowed_freq(wpa_s->global, freq) ||
@@ -6330,6 +6453,7 @@
* @ht40: Start GO with 40 MHz channel width
* @vht: Start GO with VHT support
* @vht_chwidth: channel bandwidth for GO operating with VHT support
+ * @edmg: Start GO with EDMG support
* Returns: 0 on success, -1 on failure
*
* This function creates a new P2P group with the local end as the Group Owner,
@@ -6337,7 +6461,7 @@
*/
int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
int freq, int vht_center_freq2, int ht40, int vht,
- int max_oper_chwidth, int he)
+ int max_oper_chwidth, int he, int edmg)
{
struct p2p_go_neg_results params;
@@ -6358,7 +6482,8 @@
}
if (wpas_p2p_init_go_params(wpa_s, ¶ms, freq, vht_center_freq2,
- ht40, vht, max_oper_chwidth, he, NULL))
+ ht40, vht, max_oper_chwidth, he, edmg,
+ NULL))
return -1;
p2p_go_params(wpa_s->global->p2p, ¶ms);
@@ -6438,6 +6563,7 @@
int force_freq, int neg_freq,
int vht_center_freq2, int ht40,
int vht, int max_oper_chwidth, int he,
+ int edmg,
const struct p2p_channels *channels,
int connection_timeout, int force_scan)
{
@@ -6513,7 +6639,8 @@
}
if (wpas_p2p_init_go_params(wpa_s, ¶ms, freq, vht_center_freq2,
- ht40, vht, max_oper_chwidth, he, channels))
+ ht40, vht, max_oper_chwidth, he, edmg,
+ channels))
return -1;
params.role_go = 1;
@@ -7065,7 +7192,7 @@
int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
int vht_center_freq2, int ht40, int vht, int max_chwidth,
- int pref_freq, int he)
+ int pref_freq, int he, int edmg)
{
enum p2p_invite_role role;
u8 *bssid = NULL;
@@ -7086,6 +7213,7 @@
wpa_s->p2p_go_he = !!he;
wpa_s->p2p_go_max_oper_chwidth = max_chwidth;
wpa_s->p2p_go_vht_center_freq2 = vht_center_freq2;
+ wpa_s->p2p_go_edmg = !!edmg;
if (ssid->mode == WPAS_MODE_P2P_GO) {
role = P2P_INVITE_ROLE_GO;
if (peer_addr == NULL) {
@@ -7163,6 +7291,7 @@
wpa_s->p2p_go_vht = 0;
wpa_s->p2p_go_vht_center_freq2 = 0;
wpa_s->p2p_go_max_oper_chwidth = 0;
+ wpa_s->p2p_go_edmg = 0;
for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
if (os_strcmp(wpa_s->ifname, ifname) == 0)
@@ -8108,7 +8237,9 @@
wpa_s->p2p_go_ht40,
wpa_s->p2p_go_vht,
wpa_s->p2p_go_max_oper_chwidth,
- wpa_s->p2p_go_he, NULL, 0);
+ wpa_s->p2p_go_he,
+ wpa_s->p2p_go_edmg,
+ NULL, 0);
return ret;
}
@@ -8644,7 +8775,7 @@
WPS_NFC, 0, 0, 1, 0, wpa_s->conf->p2p_go_intent,
params->go_freq, wpa_s->p2p_go_vht_center_freq2,
-1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
- wpa_s->p2p_go_he,
+ wpa_s->p2p_go_he, wpa_s->p2p_go_edmg,
params->go_ssid_len ? params->go_ssid : NULL,
params->go_ssid_len);
}
@@ -8724,7 +8855,8 @@
WPS_NFC, 0, 0, 0, 0, wpa_s->conf->p2p_go_intent,
forced_freq, wpa_s->p2p_go_vht_center_freq2,
-1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
- wpa_s->p2p_go_he, NULL, 0);
+ wpa_s->p2p_go_he, wpa_s->p2p_go_edmg,
+ NULL, 0);
}
@@ -8740,7 +8872,8 @@
WPS_NFC, 0, 0, 0, 1, wpa_s->conf->p2p_go_intent,
forced_freq, wpa_s->p2p_go_vht_center_freq2,
-1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
- wpa_s->p2p_go_he, NULL, 0);
+ wpa_s->p2p_go_he, wpa_s->p2p_go_edmg,
+ NULL, 0);
if (res)
return res;
@@ -9125,7 +9258,8 @@
* TODO: This function may not always work correctly. For example,
* when we have a running GO and a BSS on a DFS channel.
*/
- if (wpas_p2p_init_go_params(wpa_s, ¶ms, 0, 0, 0, 0, 0, 0, NULL)) {
+ if (wpas_p2p_init_go_params(wpa_s, ¶ms, 0, 0, 0, 0, 0, 0, 0,
+ NULL)) {
wpa_dbg(wpa_s, MSG_DEBUG,
"P2P CSA: Failed to select new frequency for GO");
return -1;
@@ -9237,7 +9371,8 @@
wpa_supplicant_ap_deinit(wpa_s);
/* Reselect the GO frequency */
- if (wpas_p2p_init_go_params(wpa_s, ¶ms, 0, 0, 0, 0, 0, 0, NULL)) {
+ if (wpas_p2p_init_go_params(wpa_s, ¶ms, 0, 0, 0, 0, 0, 0, 0,
+ NULL)) {
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Failed to reselect freq");
wpas_p2p_group_delete(wpa_s,
P2P_GROUP_REMOVAL_GO_LEAVE_CHANNEL);
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index 24ec2ca..941198e 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -37,18 +37,18 @@
int persistent_group, int auto_join, int join, int auth,
int go_intent, int freq, unsigned int vht_center_freq2,
int persistent_id, int pd, int ht40, int vht,
- unsigned int vht_chwidth, int he, const u8 *group_ssid,
- size_t group_ssid_len);
+ unsigned int vht_chwidth, int he, int edmg,
+ const u8 *group_ssid, size_t group_ssid_len);
int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s,
int freq, struct wpa_ssid *ssid);
int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
int freq, int vht_center_freq2, int ht40, int vht,
- int max_oper_chwidth, int he);
+ int max_oper_chwidth, int he, int edmg);
int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, int addr_allocated,
int force_freq, int neg_freq,
- int vht_center_freq2, int ht40,
- int vht, int max_oper_chwidth, int he,
+ int vht_center_freq2, int ht40, int vht,
+ int max_oper_chwidth, int he, int edmg,
const struct p2p_channels *channels,
int connection_timeout, int force_scan);
struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
@@ -116,8 +116,8 @@
int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr);
int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
- int vht_center_freq2, int ht40, int vht,
- int max_oper_chwidth, int pref_freq, int he);
+ int vht_center_freq2, int ht40, int vht, int max_chwidth,
+ int pref_freq, int he, int edmg);
int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
const u8 *peer_addr, const u8 *go_dev_addr);
int wpas_p2p_presence_req(struct wpa_supplicant *wpa_s, u32 duration1,
@@ -165,6 +165,8 @@
const struct wpabuf *sel, int forced_freq);
int wpas_p2p_nfc_tag_enabled(struct wpa_supplicant *wpa_s, int enabled);
void wpas_p2p_pbc_overlap_cb(void *eloop_ctx, void *timeout_ctx);
+int wpas_p2p_try_edmg_channel(struct wpa_supplicant *wpa_s,
+ struct p2p_go_neg_results *params);
#ifdef CONFIG_P2P
diff --git a/wpa_supplicant/rrm.c b/wpa_supplicant/rrm.c
index b78ff10..7930e01 100644
--- a/wpa_supplicant/rrm.c
+++ b/wpa_supplicant/rrm.c
@@ -79,7 +79,7 @@
NULL);
if (!wpa_s->rrm.notify_neighbor_rep) {
- wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report");
+ wpa_msg(wpa_s, MSG_INFO, "RRM: Unexpected neighbor report");
return;
}
@@ -90,8 +90,8 @@
return;
}
wpabuf_put_data(neighbor_rep, report + 1, report_len - 1);
- wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
- report[0]);
+ wpa_dbg(wpa_s, MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)",
+ report[0]);
wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx,
neighbor_rep);
wpa_s->rrm.notify_neighbor_rep = NULL;
@@ -148,12 +148,12 @@
const u8 *rrm_ie;
if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) {
- wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM.");
+ wpa_dbg(wpa_s, MSG_DEBUG, "RRM: No connection, no RRM.");
return -ENOTCONN;
}
if (!wpa_s->rrm.rrm_used) {
- wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection.");
+ wpa_dbg(wpa_s, MSG_DEBUG, "RRM: No RRM in current connection.");
return -EOPNOTSUPP;
}
@@ -161,15 +161,15 @@
WLAN_EID_RRM_ENABLED_CAPABILITIES);
if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) ||
!(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
- wpa_printf(MSG_DEBUG,
- "RRM: No network support for Neighbor Report.");
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "RRM: No network support for Neighbor Report.");
return -EOPNOTSUPP;
}
/* Refuse if there's a live request */
if (wpa_s->rrm.notify_neighbor_rep) {
- wpa_printf(MSG_DEBUG,
- "RRM: Currently handling previous Neighbor Report.");
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "RRM: Currently handling previous Neighbor Report.");
return -EBUSY;
}
@@ -178,14 +178,15 @@
(lci ? 2 + MEASURE_REQUEST_LCI_LEN : 0) +
(civic ? 2 + MEASURE_REQUEST_CIVIC_LEN : 0));
if (buf == NULL) {
- wpa_printf(MSG_DEBUG,
- "RRM: Failed to allocate Neighbor Report Request");
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "RRM: Failed to allocate Neighbor Report Request");
return -ENOMEM;
}
- wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d",
- (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""),
- wpa_s->rrm.next_neighbor_rep_token);
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "RRM: Neighbor report request (for %s), token=%d",
+ (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""),
+ wpa_s->rrm.next_neighbor_rep_token);
wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST);
@@ -267,8 +268,8 @@
if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
wpa_s->own_addr, wpa_s->bssid,
wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
- wpa_printf(MSG_DEBUG,
- "RRM: Failed to send Neighbor Report Request");
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "RRM: Failed to send Neighbor Report Request");
wpabuf_free(buf);
return -ECANCELED;
}
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index cfb5bb3..08d7e3e 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -13,6 +13,7 @@
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "common/ocv.h"
+#include "common/hw_features_common.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "common/wpa_common.h"
#include "common/sae.h"
@@ -591,6 +592,18 @@
os_memcpy(pos, ext_capab, ext_capab_len);
}
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->rsnxe_override_assoc &&
+ wpabuf_len(wpa_s->rsnxe_override_assoc) <=
+ sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len) {
+ wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
+ os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
+ wpabuf_head(wpa_s->rsnxe_override_assoc),
+ wpabuf_len(wpa_s->rsnxe_override_assoc));
+ wpa_s->sme.assoc_req_ie_len +=
+ wpabuf_len(wpa_s->rsnxe_override_assoc);
+ } else
+#endif /* CONFIG_TESTING_OPTIONS */
if (wpa_s->rsnxe_len > 0 &&
wpa_s->rsnxe_len <=
sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len) {
@@ -1263,7 +1276,7 @@
if (wpa_s->sme.sae.tmp &&
sme_check_sae_rejected_groups(
wpa_s,
- wpa_s->sme.sae.tmp->peer_rejected_groups) < 0)
+ wpa_s->sme.sae.tmp->peer_rejected_groups))
return -1;
if (sae_process_commit(&wpa_s->sme.sae) < 0) {
@@ -2202,13 +2215,14 @@
}
-int sme_proc_obss_scan(struct wpa_supplicant *wpa_s)
+int sme_proc_obss_scan(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_results *scan_res)
{
- struct wpa_bss *bss;
const u8 *ie;
- u16 ht_cap;
u8 chan_list[P2P_MAX_CHANNELS], channel;
u8 num_channels = 0, num_intol = 0, i;
+ size_t j;
+ int pri_freq, sec_freq;
if (!wpa_s->sme.sched_obss_scan)
return 0;
@@ -2236,22 +2250,36 @@
os_memset(chan_list, 0, sizeof(chan_list));
- dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
- /* Skip other band bss */
+ pri_freq = wpa_s->assoc_freq;
+
+ switch (wpa_s->sme.ht_sec_chan) {
+ case HT_SEC_CHAN_ABOVE:
+ sec_freq = pri_freq + 20;
+ break;
+ case HT_SEC_CHAN_BELOW:
+ sec_freq = pri_freq - 20;
+ break;
+ case HT_SEC_CHAN_UNKNOWN:
+ default:
+ wpa_msg(wpa_s, MSG_WARNING,
+ "Undefined secondary channel: drop OBSS scan results");
+ return 1;
+ }
+
+ for (j = 0; j < scan_res->num; j++) {
+ struct wpa_scan_res *bss = scan_res->res[j];
enum hostapd_hw_mode mode;
+ int res;
+
+ /* Skip other band bss */
mode = ieee80211_freq_to_chan(bss->freq, &channel);
if (mode != HOSTAPD_MODE_IEEE80211G &&
mode != HOSTAPD_MODE_IEEE80211B)
continue;
- ie = wpa_bss_get_ie(bss, WLAN_EID_HT_CAP);
- ht_cap = (ie && (ie[1] == 26)) ? WPA_GET_LE16(ie + 2) : 0;
- wpa_printf(MSG_DEBUG, "SME OBSS scan BSS " MACSTR
- " freq=%u chan=%u ht_cap=0x%x",
- MAC2STR(bss->bssid), bss->freq, channel, ht_cap);
-
- if (!ht_cap || (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)) {
- if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)
+ res = check_bss_coex_40mhz(bss, pri_freq, sec_freq);
+ if (res) {
+ if (res == 2)
num_intol++;
/* Check whether the channel is already considered */
diff --git a/wpa_supplicant/sme.h b/wpa_supplicant/sme.h
index 1a7f9e8..42d5a83 100644
--- a/wpa_supplicant/sme.h
+++ b/wpa_supplicant/sme.h
@@ -37,7 +37,8 @@
void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s);
void sme_deinit(struct wpa_supplicant *wpa_s);
-int sme_proc_obss_scan(struct wpa_supplicant *wpa_s);
+int sme_proc_obss_scan(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_results *scan_res);
void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable);
void sme_external_auth_trigger(struct wpa_supplicant *wpa_s,
union wpa_event_data *data);
@@ -112,7 +113,8 @@
{
}
-static inline int sme_proc_obss_scan(struct wpa_supplicant *wpa_s)
+static inline int sme_proc_obss_scan(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_results *scan_res)
{
return 0;
}
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 47cec0b..a1b0615 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -52,6 +52,7 @@
static const char *global = NULL;
static const char *pid_file = NULL;
static const char *action_file = NULL;
+static int reconnect = 0;
static int ping_interval = 5;
static int interactive = 0;
static char *ifname_prefix = NULL;
@@ -80,7 +81,7 @@
static void usage(void)
{
- printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
+ printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvBr] "
"[-a<action file>] \\\n"
" [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
"\\\n"
@@ -91,6 +92,8 @@
" -a = run in daemon mode executing the action file based on "
"events from\n"
" wpa_supplicant\n"
+ " -r = try to reconnect when client socket is disconnected.\n"
+ " This is useful only when used with -a.\n"
" -B = run a daemon in the background\n"
" default path: " CONFIG_CTRL_IFACE_DIR "\n"
" default interface: first interface found in socket path\n");
@@ -474,7 +477,7 @@
"p2p_optimize_listen_chan", "p2p_go_ht40", "p2p_go_vht",
"p2p_disabled", "p2p_go_ctwindow", "p2p_no_group_iface",
"p2p_ignore_shared_freq", "ip_addr_go", "ip_addr_mask",
- "ip_addr_start", "ip_addr_end",
+ "ip_addr_start", "ip_addr_end", "p2p_go_edmg",
#endif /* CONFIG_P2P */
"country", "bss_max_count", "bss_expiration_age",
"bss_expiration_scan_count", "filter_ssids", "filter_rssi",
@@ -1406,7 +1409,7 @@
"bssid_whitelist", "psk", "proto", "key_mgmt",
"bg_scan_period", "pairwise", "group", "auth_alg", "scan_freq",
"freq_list", "max_oper_chwidth", "ht40", "vht", "vht_center_freq1",
- "vht_center_freq2", "ht",
+ "vht_center_freq2", "ht", "edmg",
#ifdef IEEE8021X_EAPOL
"eap", "identity", "anonymous_identity", "password", "ca_cert",
"ca_path", "client_cert", "private_key", "private_key_passwd",
@@ -4035,7 +4038,8 @@
wpa_cli_exec(action_file, ifname, pos);
} else if (str_starts(pos, WPA_EVENT_TERMINATING)) {
printf("wpa_supplicant is terminating - stop monitoring\n");
- wpa_cli_quit = 1;
+ if (!reconnect)
+ wpa_cli_quit = 1;
}
}
@@ -4227,6 +4231,10 @@
if (wpa_ctrl_pending(ctrl) < 0) {
printf("Connection to wpa_supplicant lost - trying to "
"reconnect\n");
+ if (reconnect) {
+ eloop_terminate();
+ return;
+ }
wpa_cli_reconnect();
}
}
@@ -4574,6 +4582,8 @@
static void wpa_cli_terminate(int sig, void *ctx)
{
eloop_terminate();
+ if (reconnect)
+ wpa_cli_quit = 1;
}
@@ -4654,7 +4664,7 @@
return -1;
for (;;) {
- c = getopt(argc, argv, "a:Bg:G:hi:p:P:s:v");
+ c = getopt(argc, argv, "a:Bg:G:hi:p:P:rs:v");
if (c < 0)
break;
switch (c) {
@@ -4686,6 +4696,9 @@
case 'P':
pid_file = optarg;
break;
+ case 'r':
+ reconnect = 1;
+ break;
case 's':
client_socket_dir = optarg;
break;
@@ -4711,7 +4724,22 @@
if (ctrl_ifname == NULL)
ctrl_ifname = wpa_cli_get_default_ifname();
- if (interactive) {
+ if (reconnect && action_file && ctrl_ifname) {
+ while (!wpa_cli_quit) {
+ if (ctrl_conn)
+ wpa_cli_action(ctrl_conn);
+ else
+ os_sleep(1, 0);
+ wpa_cli_close_connection();
+ wpa_cli_open_connection(ctrl_ifname, 0);
+ if (ctrl_conn) {
+ if (wpa_ctrl_attach(ctrl_conn) != 0)
+ wpa_cli_close_connection();
+ else
+ wpa_cli_attached = 1;
+ }
+ }
+ } else if (interactive) {
wpa_cli_interactive();
} else {
if (!global &&
diff --git a/wpa_supplicant/wpa_passphrase.c b/wpa_supplicant/wpa_passphrase.c
index adca1cc..538997e 100644
--- a/wpa_supplicant/wpa_passphrase.c
+++ b/wpa_supplicant/wpa_passphrase.c
@@ -31,9 +31,9 @@
if (argc > 2) {
passphrase = argv[2];
} else {
- printf("# reading passphrase from stdin\n");
+ fprintf(stderr, "# reading passphrase from stdin\n");
if (fgets(buf, sizeof(buf), stdin) == NULL) {
- printf("Failed to read passphrase\n");
+ fprintf(stderr, "Failed to read passphrase\n");
return 1;
}
buf[sizeof(buf) - 1] = '\0';
@@ -50,11 +50,11 @@
len = os_strlen(passphrase);
if (len < 8 || len > 63) {
- printf("Passphrase must be 8..63 characters\n");
+ fprintf(stderr, "Passphrase must be 8..63 characters\n");
return 1;
}
if (has_ctrl_char((u8 *) passphrase, len)) {
- printf("Invalid passphrase character\n");
+ fprintf(stderr, "Invalid passphrase character\n");
return 1;
}
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index e14bffd..73e63ab 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -500,6 +500,12 @@
wpa_s->get_pref_freq_list_override = NULL;
wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
wpa_s->last_assoc_req_wpa_ie = NULL;
+ os_free(wpa_s->extra_sae_rejected_groups);
+ wpa_s->extra_sae_rejected_groups = NULL;
+ wpabuf_free(wpa_s->rsnxe_override_assoc);
+ wpa_s->rsnxe_override_assoc = NULL;
+ wpabuf_free(wpa_s->rsnxe_override_eapol);
+ wpa_s->rsnxe_override_eapol = NULL;
#endif /* CONFIG_TESTING_OPTIONS */
if (wpa_s->conf != NULL) {
@@ -1973,6 +1979,28 @@
}
+static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
+{
+#if defined(CONFIG_SAE) && defined(CONFIG_SME)
+ os_free(wpa_s->sme.sae_rejected_groups);
+ wpa_s->sme.sae_rejected_groups = NULL;
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->extra_sae_rejected_groups) {
+ int i, *groups = wpa_s->extra_sae_rejected_groups;
+
+ for (i = 0; groups[i]; i++) {
+ wpa_printf(MSG_DEBUG,
+ "TESTING: Indicate rejection of an extra SAE group %d",
+ groups[i]);
+ int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
+ groups[i]);
+ }
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+#endif /* CONFIG_SAE && CONFIG_SME */
+}
+
+
static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
/**
@@ -2021,10 +2049,7 @@
}
} else {
#ifdef CONFIG_SAE
-#ifdef CONFIG_SME
- os_free(wpa_s->sme.sae_rejected_groups);
- wpa_s->sme.sae_rejected_groups = NULL;
-#endif /* CONFIG_SME */
+ wpa_s_clear_sae_rejected(wpa_s);
wpa_s_setup_sae_pt(wpa_s->conf, ssid);
#endif /* CONFIG_SAE */
}
@@ -2358,8 +2383,7 @@
return;
}
- res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
- sec_chan->chan);
+ res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
switch (res) {
case 0:
/* Back to HT20 */
@@ -3006,6 +3030,17 @@
}
#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->rsnxe_override_assoc &&
+ wpabuf_len(wpa_s->rsnxe_override_assoc) <=
+ max_wpa_ie_len - wpa_ie_len) {
+ wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
+ os_memcpy(wpa_ie + wpa_ie_len,
+ wpabuf_head(wpa_s->rsnxe_override_assoc),
+ wpabuf_len(wpa_s->rsnxe_override_assoc));
+ wpa_ie_len += wpabuf_len(wpa_s->rsnxe_override_assoc);
+ } else
+#endif /* CONFIG_TESTING_OPTIONS */
if (wpa_s->rsnxe_len > 0 &&
wpa_s->rsnxe_len <= max_wpa_ie_len - wpa_ie_len) {
os_memcpy(wpa_ie + wpa_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len);
@@ -4040,10 +4075,7 @@
wpa_s->disconnected = 0;
wpa_s->reassociate = 1;
-#if defined(CONFIG_SAE) && defined(CONFIG_SME)
- os_free(wpa_s->sme.sae_rejected_groups);
- wpa_s->sme.sae_rejected_groups = NULL;
-#endif /* CONFIG_SAE && CONFIG_SME */
+ wpa_s_clear_sae_rejected(wpa_s);
wpa_s->last_owe_group = 0;
if (ssid) {
ssid->owe_transition_bss_select_count = 0;
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index ba511b9..328f91a 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -955,7 +955,8 @@
# management frames) certification program are:
# PMF enabled: ieee80211w=1 and key_mgmt=WPA-EAP WPA-EAP-SHA256
# PMF required: ieee80211w=2 and key_mgmt=WPA-EAP-SHA256
-# (and similarly for WPA-PSK and WPA-WPSK-SHA256 if WPA2-Personal is used)
+# (and similarly for WPA-PSK and WPA-PSK-SHA256 if WPA2-Personal is used)
+# WPA3-Personal-only mode: ieee80211w=2 and key_mgmt=SAE
#
# ocv: whether operating channel validation is enabled
# This is a countermeasure against multi-channel man-in-the-middle attacks.
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index b6fb491..dcc2a6d 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -931,6 +931,7 @@
unsigned int p2p_pd_before_go_neg:1;
unsigned int p2p_go_ht40:1;
unsigned int p2p_go_vht:1;
+ unsigned int p2p_go_edmg:1;
unsigned int p2p_go_he:1;
unsigned int user_initiated_pd:1;
unsigned int p2p_go_group_formation_completed:1;
@@ -1123,6 +1124,7 @@
unsigned int ignore_auth_resp:1;
unsigned int ignore_assoc_disallow:1;
unsigned int testing_resend_assoc:1;
+ unsigned int ignore_sae_h2e_only:1;
struct wpabuf *sae_commit_override;
enum wpa_alg last_tk_alg;
u8 last_tk_addr[ETH_ALEN];
@@ -1130,6 +1132,9 @@
u8 last_tk[WPA_TK_MAX_LEN];
size_t last_tk_len;
struct wpabuf *last_assoc_req_wpa_ie;
+ int *extra_sae_rejected_groups;
+ struct wpabuf *rsnxe_override_assoc;
+ struct wpabuf *rsnxe_override_eapol;
#endif /* CONFIG_TESTING_OPTIONS */
struct wmm_ac_assoc_data *wmm_ac_assoc_info;
@@ -1232,7 +1237,7 @@
unsigned int dpp_listen_freq;
u8 dpp_allowed_roles;
int dpp_qr_mutual;
- int dpp_netrole_ap;
+ int dpp_netrole;
int dpp_auth_ok_on_ack;
int dpp_in_response_listen;
int dpp_gas_client;
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index f51340f..8387fc3 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -1178,6 +1178,11 @@
/* P2P in 60 GHz uses PBSS */
ssid->pbss = 1;
}
+ if (wpa_s->go_params->edmg &&
+ wpas_p2p_try_edmg_channel(wpa_s,
+ wpa_s->go_params) == 0)
+ ssid->enable_edmg = 1;
+
wpa_hexdump_ascii(MSG_DEBUG, "WPS: Use specific AP "
"SSID", ssid->ssid, ssid->ssid_len);
}
@@ -1261,6 +1266,11 @@
/* P2P in 60 GHz uses PBSS */
ssid->pbss = 1;
}
+ if (wpa_s->go_params->edmg &&
+ wpas_p2p_try_edmg_channel(wpa_s,
+ wpa_s->go_params) == 0)
+ ssid->enable_edmg = 1;
+
wpa_hexdump_ascii(MSG_DEBUG, "WPS: Use specific AP "
"SSID", ssid->ssid, ssid->ssid_len);
}
@@ -1284,6 +1294,10 @@
wpa_printf(MSG_DEBUG, "WPS: Failed to set phase1 '%s'", val);
return -1;
}
+
+ if (dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER)
+ wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_PIN_ACTIVE);
+
if (wpa_s->wps_fragment_size)
ssid->eap.fragment_size = wpa_s->wps_fragment_size;
eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
@@ -1349,6 +1363,7 @@
wpas_clear_wps(wpa_s);
}
+ wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_CANCEL);
wpa_s->after_wps = 0;
return 0;