Cumulative patch from commit 5e32f8256f5fcce8b70a95e070375ac549ac935a
5e32f82 tests: Verify HS 2.0R2 deauthentication request
b61e70c HS 2.0R2: Add WFA server-only EAP-TLS server method
8d2a992 HS 2.0R2: RADIUS server support to request Subscr Remediation
ae6d15c HS 2.0R2 AP: Add OSU Providers list ANQP element
f7bd7a0 HS 2.0R2 AP: Add Icon Request and Icon binary File ANQP elements
97596f8 HS 2.0R2 AP: Add support for Session Info URL RADIUS AVP
8e1146d HS 2.0R2 AP: Add support for deauthentication request
a14896e HS 2.0R2 AP: Add OSEN implementation
6ca0853 HS 2.0R2 AP: Use Subscr Remediation request from RADIUS server
7bc9c25 HS 2.0R2 AP: Add STA's Hotspot 2.0 Release Number into Access-Request
76579ec HS 2.0R2 AP: Add AP Hotspot 2.0 Release Number as WFA RADIUS VSA
0dd100f HS 2.0R2 AP: Add definition and helper function for WFA RADIUS VSA
3fb17a9 HS 2.0R2 AP: Add WNM-Notification Request for Subscription Remediation
d5d2478 HS 2.0R2 AP: Update HS 2.0 Indication element to Release 2
a6739e1 HS 2.0R2: Try to scan multiple times for OSU providers
cf6d08a Interworking: Add OCSP parameter to the cred block
6402f2f Interworking: Add more debug info on roaming partner preferences
7479489 Interworking: Add sp_priority cred parameter
751ac99 Interworking: Use a helper function to compare cred priority
aff419f Interworking: Remove separate credential priority tracking
533536d HS 2.0R2: Disable full ESS for as a workaround for per-BSS issues
8a77f1b HS 2.0R2: Slow down connection attempts on EAP failures
76a55a8 HS 2.0R2: Add more debug to network selection
8b4b9fb HS 2.0R2: Fix bandwidth policy BSS selection
28f2a7c HS 2.0R2: Allow excluded network to be selected based on user override
33fb8c5 HS 2.0R2: Add support for Policy/RequiredProtoPortTuple
a45b2dc HS 2.0R2: Add support for Policy/MaximumBSSLoadValue
4cad9df HS 2.0R2: Add support for Policy/MinBackhaulThreshold
aa26ba6 HS 2.0R2: Add tracking of provisioning SP
8e5fdfa HS 2.0R2: Add WFA server-only EAP-TLS peer method
df0f01d HS 2.0R2: Add OSEN client implementation
a5d7563 HS 2.0R2: Add common OSEN definitions
230e373 HS 2.0R2: Add GAS operation duration statistics into debug
b572df8 HS 2.0R2: Add routine for fetching OSU provider information
1d2215f HS 2.0R2: Add OSU Providers list ANQP element
184e110 HS 2.0R2: Add Icon Request and Icon binary File ANQP elements
7ef6947 HS 2.0R2: Add STA support for Deauthentication Request notification
95a3ea9 HS 2.0R2: Add WNM-Notification Request for Subscription Remediation
f9cd147 HS 2.0R2: Update Indication element to Release 2
bc00053 Interworking: Allow roaming partner configuration
ae6f927 nl80211: Add driver capability for GTK_NOT_USED
2c49d04 Do not clear global pmf setting on FLUSH
eef7235 Only try fast reconnect if network is not disabled
3d910ef Interworking: Prefer last added network during network selection
2a33687 P2P: Remove unnecessary ifdef CONFIG_NO_CONFIG_WRITE
050d8b5 Fix documentation for wpa_supplicant_global_ctrl_iface_process()
8c9cb81 DFS: Fix coding style (missing whitespace)
4f1e01b DFS: Add VHT160 available channels
b8058a6 hostapd: DFS allow mixed channels
4db216f wpa_supplicant: Add support for IPv6 with UDP ctrl_iface
e2364d1 hostapd: Deauthenticate clients forbidden by maclist changes
1748f1d hostapd: Make it possible to remove addresses from maclists
064eb05 Add os_remove_in_array()
c1151e4 Force OFDM/HT/VHT to be disabled on channel 14
bfb79dd nl80211: Show regulatory rule flags in debug output
3d7ad2f hostapd: Configure spectrum management capability
e0392f8 hostapd: Add Power Constraint element
891330f Fix spelling s/algorith/algorithm/
f0e30c8 Do not start another connect work while one is pending
3290398 WPS: Fix UNSUBSCRIBE error returns if NT or CALLBACK header is used
f34df28 WPS: Fix UNSUBSCRIBE to return 412 if no SID match found
80f256a WPS: Remove unnecessary filename NULL check
Change-Id: I7dc25a8bb0074f4970ade8d42dfa60da166baf96
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index 5d6fe56..888ee2b 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -201,6 +201,10 @@
OBJS += src/ap/peerkey_auth.c
endif
+ifdef CONFIG_HS20
+NEED_AES_OMAC1=y
+endif
+
ifdef CONFIG_IEEE80211W
L_CFLAGS += -DCONFIG_IEEE80211W
NEED_SHA256=y
diff --git a/hostapd/Makefile b/hostapd/Makefile
index 25c560f..c541d43 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -185,6 +185,10 @@
OBJS += ../src/ap/peerkey_auth.o
endif
+ifdef CONFIG_HS20
+NEED_AES_OMAC1=y
+endif
+
ifdef CONFIG_IEEE80211W
CFLAGS += -DCONFIG_IEEE80211W
NEED_SHA256=y
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 19d6ad3..fa7d14a 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -129,6 +129,8 @@
}
while (fgets(buf, sizeof(buf), f)) {
+ int i, rem = 0;
+
line++;
if (buf[0] == '#')
@@ -143,14 +145,32 @@
}
if (buf[0] == '\0')
continue;
+ pos = buf;
+ if (buf[0] == '-') {
+ rem = 1;
+ pos++;
+ }
- if (hwaddr_aton(buf, addr)) {
+ if (hwaddr_aton(pos, addr)) {
wpa_printf(MSG_ERROR, "Invalid MAC address '%s' at "
- "line %d in '%s'", buf, line, fname);
+ "line %d in '%s'", pos, line, fname);
fclose(f);
return -1;
}
+ if (rem) {
+ i = 0;
+ while (i < *num) {
+ if (os_memcmp((*acl)[i].addr, addr, ETH_ALEN) ==
+ 0) {
+ os_remove_in_array(*acl, *num,
+ sizeof(**acl), i);
+ (*num)--;
+ } else
+ i++;
+ }
+ continue;
+ }
vlan_id = 0;
pos = buf;
while (*pos != '\0' && *pos != ' ' && *pos != '\t')
@@ -1556,6 +1576,196 @@
}
return 0;
}
+
+
+static int hs20_parse_icon(struct hostapd_bss_config *bss, char *pos)
+{
+ struct hs20_icon *icon;
+ char *end;
+
+ icon = os_realloc_array(bss->hs20_icons, bss->hs20_icons_count + 1,
+ sizeof(struct hs20_icon));
+ if (icon == NULL)
+ return -1;
+ bss->hs20_icons = icon;
+ icon = &bss->hs20_icons[bss->hs20_icons_count];
+ os_memset(icon, 0, sizeof(*icon));
+
+ icon->width = atoi(pos);
+ pos = os_strchr(pos, ':');
+ if (pos == NULL)
+ return -1;
+ pos++;
+
+ icon->height = atoi(pos);
+ pos = os_strchr(pos, ':');
+ if (pos == NULL)
+ return -1;
+ pos++;
+
+ end = os_strchr(pos, ':');
+ if (end == NULL || end - pos > 3)
+ return -1;
+ os_memcpy(icon->language, pos, end - pos);
+ pos = end + 1;
+
+ end = os_strchr(pos, ':');
+ if (end == NULL || end - pos > 255)
+ return -1;
+ os_memcpy(icon->type, pos, end - pos);
+ pos = end + 1;
+
+ end = os_strchr(pos, ':');
+ if (end == NULL || end - pos > 255)
+ return -1;
+ os_memcpy(icon->name, pos, end - pos);
+ pos = end + 1;
+
+ if (os_strlen(pos) > 255)
+ return -1;
+ os_memcpy(icon->file, pos, os_strlen(pos));
+
+ bss->hs20_icons_count++;
+
+ return 0;
+}
+
+
+static int hs20_parse_osu_ssid(struct hostapd_bss_config *bss,
+ char *pos, int line)
+{
+ size_t slen;
+ char *str;
+
+ str = wpa_config_parse_string(pos, &slen);
+ if (str == NULL || slen < 1 || slen > HOSTAPD_MAX_SSID_LEN) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid SSID '%s'", line, pos);
+ return -1;
+ }
+
+ os_memcpy(bss->osu_ssid, str, slen);
+ bss->osu_ssid_len = slen;
+ os_free(str);
+
+ return 0;
+}
+
+
+static int hs20_parse_osu_server_uri(struct hostapd_bss_config *bss,
+ char *pos, int line)
+{
+ struct hs20_osu_provider *p;
+
+ p = os_realloc_array(bss->hs20_osu_providers,
+ bss->hs20_osu_providers_count + 1, sizeof(*p));
+ if (p == NULL)
+ return -1;
+
+ bss->hs20_osu_providers = p;
+ bss->last_osu = &bss->hs20_osu_providers[bss->hs20_osu_providers_count];
+ bss->hs20_osu_providers_count++;
+ os_memset(bss->last_osu, 0, sizeof(*p));
+ bss->last_osu->server_uri = os_strdup(pos);
+
+ return 0;
+}
+
+
+static int hs20_parse_osu_friendly_name(struct hostapd_bss_config *bss,
+ char *pos, int line)
+{
+ if (bss->last_osu == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
+ return -1;
+ }
+
+ if (parse_lang_string(&bss->last_osu->friendly_name,
+ &bss->last_osu->friendly_name_count, pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid osu_friendly_name '%s'",
+ line, pos);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int hs20_parse_osu_nai(struct hostapd_bss_config *bss,
+ char *pos, int line)
+{
+ if (bss->last_osu == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
+ return -1;
+ }
+
+ os_free(bss->last_osu->osu_nai);
+ bss->last_osu->osu_nai = os_strdup(pos);
+ if (bss->last_osu->osu_nai == NULL)
+ return -1;
+
+ return 0;
+}
+
+
+static int hs20_parse_osu_method_list(struct hostapd_bss_config *bss, char *pos,
+ int line)
+{
+ if (bss->last_osu == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
+ return -1;
+ }
+
+ if (hostapd_parse_intlist(&bss->last_osu->method_list, pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid osu_method_list", line);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int hs20_parse_osu_icon(struct hostapd_bss_config *bss, char *pos,
+ int line)
+{
+ char **n;
+ struct hs20_osu_provider *p = bss->last_osu;
+
+ if (p == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
+ return -1;
+ }
+
+ n = os_realloc_array(p->icons, p->icons_count + 1, sizeof(char *));
+ if (n == NULL)
+ return -1;
+ p->icons = n;
+ p->icons[p->icons_count] = os_strdup(pos);
+ if (p->icons[p->icons_count] == NULL)
+ return -1;
+ p->icons_count++;
+
+ return 0;
+}
+
+
+static int hs20_parse_osu_service_desc(struct hostapd_bss_config *bss,
+ char *pos, int line)
+{
+ if (bss->last_osu == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
+ return -1;
+ }
+
+ if (parse_lang_string(&bss->last_osu->service_desc,
+ &bss->last_osu->service_desc_count, pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid osu_service_desc '%s'",
+ line, pos);
+ return -1;
+ }
+
+ return 0;
+}
+
#endif /* CONFIG_HS20 */
@@ -2790,6 +3000,12 @@
bss->hs20 = atoi(pos);
} else if (os_strcmp(buf, "disable_dgaf") == 0) {
bss->disable_dgaf = atoi(pos);
+ } else if (os_strcmp(buf, "osen") == 0) {
+ bss->osen = atoi(pos);
+ } else if (os_strcmp(buf, "anqp_domain_id") == 0) {
+ bss->anqp_domain_id = atoi(pos);
+ } else if (os_strcmp(buf, "hs20_deauth_req_timeout") == 0) {
+ bss->hs20_deauth_req_timeout = atoi(pos);
} else if (os_strcmp(buf, "hs20_oper_friendly_name") == 0) {
if (hs20_parse_oper_friendly_name(bss, pos, line) < 0)
errors++;
@@ -2831,6 +3047,39 @@
os_free(bss->hs20_operating_class);
bss->hs20_operating_class = oper_class;
bss->hs20_operating_class_len = oper_class_len;
+ } else if (os_strcmp(buf, "hs20_icon") == 0) {
+ if (hs20_parse_icon(bss, pos) < 0) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid "
+ "hs20_icon '%s'", line, pos);
+ errors++;
+ return errors;
+ }
+ } else if (os_strcmp(buf, "osu_ssid") == 0) {
+ if (hs20_parse_osu_ssid(bss, pos, line) < 0)
+ errors++;
+ } else if (os_strcmp(buf, "osu_server_uri") == 0) {
+ if (hs20_parse_osu_server_uri(bss, pos, line) < 0)
+ errors++;
+ } else if (os_strcmp(buf, "osu_friendly_name") == 0) {
+ if (hs20_parse_osu_friendly_name(bss, pos, line) < 0)
+ errors++;
+ } else if (os_strcmp(buf, "osu_nai") == 0) {
+ if (hs20_parse_osu_nai(bss, pos, line) < 0)
+ errors++;
+ } else if (os_strcmp(buf, "osu_method_list") == 0) {
+ if (hs20_parse_osu_method_list(bss, pos, line) < 0)
+ errors++;
+ } else if (os_strcmp(buf, "osu_icon") == 0) {
+ if (hs20_parse_osu_icon(bss, pos, line) < 0)
+ errors++;
+ } else if (os_strcmp(buf, "osu_service_desc") == 0) {
+ if (hs20_parse_osu_service_desc(bss, pos, line) < 0)
+ errors++;
+ } else if (os_strcmp(buf, "subscr_remediation_url") == 0) {
+ os_free(bss->subscr_remediation_url);
+ bss->subscr_remediation_url = os_strdup(pos);
+ } else if (os_strcmp(buf, "subscr_remediation_method") == 0) {
+ bss->subscr_remediation_method = atoi(pos);
#endif /* CONFIG_HS20 */
#ifdef CONFIG_TESTING_OPTIONS
#define PARSE_TEST_PROBABILITY(_val) \
@@ -2907,6 +3156,16 @@
"sae_groups value '%s'", line, pos);
return 1;
}
+ } else if (os_strcmp(buf, "local_pwr_constraint") == 0) {
+ int val = atoi(pos);
+ if (val < 0 || val > 255) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid local_pwr_constraint %d (expected 0..255)",
+ line, val);
+ return 1;
+ }
+ conf->local_pwr_constraint = val;
+ } else if (os_strcmp(buf, "spectrum_mgmt_required") == 0) {
+ conf->spectrum_mgmt_required = atoi(pos);
} else {
wpa_printf(MSG_ERROR, "Line %d: unknown configuration "
"item '%s'", line, buf);
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 7f5de62..dbdc8c6 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -30,6 +30,7 @@
#include "ap/wps_hostapd.h"
#include "ap/ctrl_iface_ap.h"
#include "ap/ap_drv_ops.h"
+#include "ap/hs20.h"
#include "ap/wnm_ap.h"
#include "ap/wpa_auth.h"
#include "wps/wps_defs.h"
@@ -617,6 +618,82 @@
#endif /* CONFIG_WPS */
+#ifdef CONFIG_HS20
+
+static int hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data *hapd,
+ const char *cmd)
+{
+ u8 addr[ETH_ALEN];
+ const char *url;
+
+ if (hwaddr_aton(cmd, addr))
+ return -1;
+ url = cmd + 17;
+ if (*url == '\0') {
+ url = NULL;
+ } else {
+ if (*url != ' ')
+ return -1;
+ url++;
+ if (*url == '\0')
+ url = NULL;
+ }
+
+ return hs20_send_wnm_notification(hapd, addr, 1, url);
+}
+
+
+static int hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data *hapd,
+ const char *cmd)
+{
+ u8 addr[ETH_ALEN];
+ int code, reauth_delay, ret;
+ const char *pos;
+ size_t url_len;
+ struct wpabuf *req;
+
+ /* <STA MAC Addr> <Code(0/1)> <Re-auth-Delay(sec)> [URL] */
+ if (hwaddr_aton(cmd, addr))
+ return -1;
+
+ pos = os_strchr(cmd, ' ');
+ if (pos == NULL)
+ return -1;
+ pos++;
+ code = atoi(pos);
+
+ pos = os_strchr(pos, ' ');
+ if (pos == NULL)
+ return -1;
+ pos++;
+ reauth_delay = atoi(pos);
+
+ url_len = 0;
+ pos = os_strchr(pos, ' ');
+ if (pos) {
+ pos++;
+ url_len = os_strlen(pos);
+ }
+
+ req = wpabuf_alloc(4 + url_len);
+ if (req == NULL)
+ return -1;
+ wpabuf_put_u8(req, code);
+ wpabuf_put_le16(req, reauth_delay);
+ wpabuf_put_u8(req, url_len);
+ if (pos)
+ wpabuf_put_data(req, pos, url_len);
+
+ wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " MACSTR
+ " to indicate imminent deauthentication (code=%d "
+ "reauth_delay=%d)", MAC2STR(addr), code, reauth_delay);
+ ret = hs20_send_wnm_notification_deauth_req(hapd, addr, req);
+ wpabuf_free(req);
+ return ret;
+}
+
+#endif /* CONFIG_HS20 */
+
#ifdef CONFIG_INTERWORKING
@@ -983,7 +1060,37 @@
hapd->ext_mgmt_frame_handling = atoi(value);
#endif /* CONFIG_TESTING_OPTIONS */
} else {
+ struct sta_info *sta;
+ int vlan_id;
+
ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
+ if (ret)
+ return ret;
+
+ if (os_strcasecmp(cmd, "deny_mac_file") == 0) {
+ for (sta = hapd->sta_list; sta; sta = sta->next) {
+ if (hostapd_maclist_found(
+ hapd->conf->deny_mac,
+ hapd->conf->num_deny_mac, sta->addr,
+ &vlan_id) &&
+ (!vlan_id || vlan_id == sta->vlan_id))
+ ap_sta_deauthenticate(
+ hapd, sta,
+ WLAN_REASON_UNSPECIFIED);
+ }
+ } else if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED &&
+ os_strcasecmp(cmd, "accept_mac_file") == 0) {
+ for (sta = hapd->sta_list; sta; sta = sta->next) {
+ if (!hostapd_maclist_found(
+ hapd->conf->accept_mac,
+ hapd->conf->num_accept_mac,
+ sta->addr, &vlan_id) ||
+ (vlan_id && vlan_id != sta->vlan_id))
+ ap_sta_deauthenticate(
+ hapd, sta,
+ WLAN_REASON_UNSPECIFIED);
+ }
+ }
}
return ret;
@@ -1318,6 +1425,14 @@
if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18))
reply_len = -1;
#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_HS20
+ } else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) {
+ if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15))
+ reply_len = -1;
+ } else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) {
+ if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16))
+ reply_len = -1;
+#endif /* CONFIG_HS20 */
#ifdef CONFIG_WNM
} else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
diff --git a/hostapd/eap_register.c b/hostapd/eap_register.c
index 981e539..8477c21 100644
--- a/hostapd/eap_register.c
+++ b/hostapd/eap_register.c
@@ -44,6 +44,13 @@
ret = eap_server_unauth_tls_register();
#endif /* EAP_SERVER_TLS */
+#ifdef EAP_SERVER_TLS
+#ifdef CONFIG_HS20
+ if (ret == 0)
+ ret = eap_server_wfa_unauth_tls_register();
+#endif /* CONFIG_HS20 */
+#endif /* EAP_SERVER_TLS */
+
#ifdef EAP_SERVER_MSCHAPV2
if (ret == 0)
ret = eap_server_mschapv2_register();
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index c503ce2..c745fe8 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -108,6 +108,20 @@
# (default: 0 = disabled)
#ieee80211h=1
+# Add Power Constraint element to Beacon and Probe Response frames
+# This config option adds Power Constraint element when applicable and Country
+# element is added. Power Constraint element is required by Transmit Power
+# Control. This can be used only with ieee80211d=1.
+# Valid values are 0..255.
+#local_pwr_constraint=3
+
+# Set Spectrum Management subfield in the Capability Information field.
+# This config option forces the Spectrum Management bit to be set. When this
+# option is not set, the value of the Spectrum Management bit depends on whether
+# DFS or TPC is required by regulatory authorities. This can be used only with
+# ieee80211d=1 and local_pwr_constraint configured.
+#spectrum_mgmt_required=1
+
# Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g,
# ad = IEEE 802.11ad (60 GHz); a/g options are used with IEEE 802.11n, too, to
# specify band)
@@ -1568,6 +1582,21 @@
# forging such frames to other stations in the BSS.
#disable_dgaf=1
+# OSU Server-Only Authenticated L2 Encryption Network
+#osen=1
+
+# ANQP Domain ID (0..65535)
+# An identifier for a set of APs in an ESS that share the same common ANQP
+# information. 0 = Some of the ANQP information is unique to this AP (default).
+#anqp_domain_id=1234
+
+# Deauthentication request timeout
+# If the RADIUS server indicates that the station is not allowed to connect to
+# the BSS/ESS, the AP can allow the station some time to download a
+# notification page (URL included in the message). This parameter sets that
+# timeout in seconds.
+#hs20_deauth_req_timeout=60
+
# Operator Friendly Name
# This parameter can be used to configure one or more Operator Friendly Name
# Duples. Each entry has a two or three character language code (ISO-639)
@@ -1611,6 +1640,32 @@
# channels 36-48):
#hs20_operating_class=5173
+# OSU icons
+# <Icon Width>:<Icon Height>:<Language code>:<Icon Type>:<Name>:<file path>
+#hs20_icon=32:32:eng:image/png:icon32:/tmp/icon32.png
+#hs20_icon=64:64:eng:image/png:icon64:/tmp/icon64.png
+
+# OSU SSID (see ssid2 for format description)
+# This is the SSID used for all OSU connections to all the listed OSU Providers.
+#osu_ssid="example"
+
+# OSU Providers
+# One or more sets of following parameter. Each OSU provider is started by the
+# mandatory osu_server_uri item. The other parameters add information for the
+# last added OSU provider.
+#
+#osu_server_uri=https://example.com/osu/
+#osu_friendly_name=eng:Example operator
+#osu_friendly_name=fin:Esimerkkipalveluntarjoaja
+#osu_nai=anonymous@example.com
+#osu_method_list=1 0
+#osu_icon=icon32
+#osu_icon=icon64
+#osu_service_desc=eng:Example services
+#osu_service_desc=fin:Esimerkkipalveluja
+#
+#osu_server_uri=...
+
##### TESTING OPTIONS #########################################################
#
# The options in this section are only available when the build configuration
diff --git a/hostapd/hostapd.eap_user_sqlite b/hostapd/hostapd.eap_user_sqlite
index f688327..2c1f130 100644
--- a/hostapd/hostapd.eap_user_sqlite
+++ b/hostapd/hostapd.eap_user_sqlite
@@ -2,6 +2,7 @@
identity TEXT PRIMARY KEY,
methods TEXT,
password TEXT,
+ remediation TEXT,
phase2 INTEGER
);
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index eee8504..8caca4f 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -743,6 +743,51 @@
}
+static int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ char buf[300];
+ int res;
+
+ if (argc < 2) {
+ printf("Invalid 'hs20_wnm_notif' command - two arguments (STA "
+ "addr and URL) are needed\n");
+ return -1;
+ }
+
+ res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %s %s",
+ argv[0], argv[1]);
+ if (res < 0 || res >= (int) sizeof(buf))
+ return -1;
+ return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ char buf[300];
+ int res;
+
+ if (argc < 3) {
+ printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n");
+ return -1;
+ }
+
+ if (argc > 3)
+ res = os_snprintf(buf, sizeof(buf),
+ "HS20_DEAUTH_REQ %s %s %s %s",
+ argv[0], argv[1], argv[2], argv[3]);
+ else
+ res = os_snprintf(buf, sizeof(buf),
+ "HS20_DEAUTH_REQ %s %s %s",
+ argv[0], argv[1], argv[2]);
+ if (res < 0 || res >= (int) sizeof(buf))
+ return -1;
+ return wpa_ctrl_command(ctrl, buf);
+}
+
+
static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
hostapd_cli_quit = 1;
@@ -941,6 +986,8 @@
{ "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set },
{ "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf },
{ "chan_switch", hostapd_cli_cmd_chan_switch },
+ { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif },
+ { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req },
{ NULL, NULL }
};