aboutsummaryrefslogtreecommitdiffstats
path: root/wpa_supplicant
diff options
context:
space:
mode:
authorJouni Malinen <jouni@qca.qualcomm.com>2012-11-02 11:05:57 (GMT)
committerJouni Malinen <j@w1.fi>2014-02-25 23:24:23 (GMT)
commit95a3ea9426180feeaa47498b5a0f89e2de59bc95 (patch)
treee07c4ff389006ebc954b398a6a670bae424a883f /wpa_supplicant
parentf9cd147d6b4718b03d8f3110e5dcaa56fe57902b (diff)
downloadhostap-95a3ea9426180feeaa47498b5a0f89e2de59bc95.zip
hostap-95a3ea9426180feeaa47498b5a0f89e2de59bc95.tar.gz
hostap-95a3ea9426180feeaa47498b5a0f89e2de59bc95.tar.bz2
HS 2.0R2: Add WNM-Notification Request for Subscription Remediation
Subscription remediation notification WNM-Notification Request is now shown in the following way in wpa_supplicant control interface: <3>HS20-SUBSCRIPTION-REMEDIATION http://example.com/foo/ Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
Diffstat (limited to 'wpa_supplicant')
-rw-r--r--wpa_supplicant/hs20_supplicant.c11
-rw-r--r--wpa_supplicant/hs20_supplicant.h3
-rw-r--r--wpa_supplicant/scan.c8
-rw-r--r--wpa_supplicant/wnm_sta.c110
-rw-r--r--wpa_supplicant/wpa_cli.c2
-rw-r--r--wpa_supplicant/wpa_supplicant.c6
6 files changed, 138 insertions, 2 deletions
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index 0040244..d419ffb 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -235,3 +235,14 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
break;
}
}
+
+
+void hs20_rx_subscription_remediation(struct wpa_supplicant *wpa_s,
+ const char *url, u8 osu_method)
+{
+ if (url)
+ wpa_msg(wpa_s, MSG_INFO, HS20_SUBSCRIPTION_REMEDIATION "%u %s",
+ osu_method, url);
+ else
+ wpa_msg(wpa_s, MSG_INFO, HS20_SUBSCRIPTION_REMEDIATION);
+}
diff --git a/wpa_supplicant/hs20_supplicant.h b/wpa_supplicant/hs20_supplicant.h
index 7f62a15..b19355b 100644
--- a/wpa_supplicant/hs20_supplicant.h
+++ b/wpa_supplicant/hs20_supplicant.h
@@ -20,4 +20,7 @@ int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
struct wpa_bss *bss);
int hs20_get_pps_mo_id(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+void hs20_rx_subscription_remediation(struct wpa_supplicant *wpa_s,
+ const char *url, u8 osu_method);
+
#endif /* HS20_SUPPLICANT_H */
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 6f58667..f7eb537 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -365,11 +365,17 @@ static void wpas_add_interworking_elements(struct wpa_supplicant *wpa_s,
return;
wpabuf_put_u8(buf, WLAN_EID_EXT_CAPAB);
- wpabuf_put_u8(buf, 4);
+ wpabuf_put_u8(buf, 6);
wpabuf_put_u8(buf, 0x00);
wpabuf_put_u8(buf, 0x00);
wpabuf_put_u8(buf, 0x00);
wpabuf_put_u8(buf, 0x80); /* Bit 31 - Interworking */
+ wpabuf_put_u8(buf, 0x00);
+#ifdef CONFIG_HS20
+ wpabuf_put_u8(buf, 0x40); /* Bit 46 - WNM-Notification */
+#else /* CONFIG_HS20 */
+ wpabuf_put_u8(buf, 0x00);
+#endif /* CONFIG_HS20 */
wpabuf_put_u8(buf, WLAN_EID_INTERWORKING);
wpabuf_put_u8(buf, is_zero_ether_addr(wpa_s->conf->hessid) ? 1 :
diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c
index 65b2783..9b7bfa7 100644
--- a/wpa_supplicant/wnm_sta.c
+++ b/wpa_supplicant/wnm_sta.c
@@ -18,6 +18,7 @@
#include "ctrl_iface.h"
#include "bss.h"
#include "wnm_sta.h"
+#include "hs20_supplicant.h"
#define MAX_TFS_IE_LEN 1024
#define WNM_MAX_NEIGHBOR_REPORT 10
@@ -751,6 +752,112 @@ int wnm_send_bss_transition_mgmt_query(struct wpa_supplicant *wpa_s,
}
+static void ieee802_11_rx_wnm_notif_req_wfa(struct wpa_supplicant *wpa_s,
+ const u8 *sa, const u8 *data,
+ int len)
+{
+ const u8 *pos, *end;
+ u8 ie, ie_len;
+
+ pos = data;
+ end = data + len;
+
+ while (pos + 1 < end) {
+ ie = *pos++;
+ ie_len = *pos++;
+ wpa_printf(MSG_DEBUG, "WNM: WFA subelement %u len %u",
+ ie, ie_len);
+ if (ie_len > end - pos) {
+ wpa_printf(MSG_DEBUG, "WNM: Not enough room for "
+ "subelement");
+ break;
+ }
+
+#ifdef CONFIG_HS20
+ if (ie == WLAN_EID_VENDOR_SPECIFIC && ie_len >= 5 &&
+ WPA_GET_BE24(pos) == OUI_WFA &&
+ pos[3] == HS20_WNM_SUB_REM_NEEDED) {
+ /* Subscription Remediation subelement */
+ const u8 *ie_end;
+ u8 url_len;
+ char *url;
+ u8 osu_method;
+
+ wpa_printf(MSG_DEBUG, "WNM: Subscription Remediation "
+ "subelement");
+ ie_end = pos + ie_len;
+ pos += 4;
+ url_len = *pos++;
+ if (url_len == 0) {
+ wpa_printf(MSG_DEBUG, "WNM: No Server URL included");
+ url = NULL;
+ osu_method = 1;
+ } else {
+ if (pos + url_len + 1 > ie_end) {
+ wpa_printf(MSG_DEBUG, "WNM: Not enough room for Server URL (len=%u) and Server Method (left %d)",
+ url_len,
+ (int) (ie_end - pos));
+ break;
+ }
+ url = os_malloc(url_len + 1);
+ if (url == NULL)
+ break;
+ os_memcpy(url, pos, url_len);
+ url[url_len] = '\0';
+ osu_method = pos[url_len];
+ }
+ hs20_rx_subscription_remediation(wpa_s, url,
+ osu_method);
+ os_free(url);
+ break;
+ }
+#endif /* CONFIG_HS20 */
+
+ pos += ie_len;
+ }
+}
+
+
+static void ieee802_11_rx_wnm_notif_req(struct wpa_supplicant *wpa_s,
+ const u8 *sa, const u8 *frm, int len)
+{
+ const u8 *pos, *end;
+ u8 dialog_token, type;
+
+ /* Dialog Token [1] | Type [1] | Subelements */
+
+ if (len < 2 || sa == NULL)
+ return;
+ end = frm + len;
+ pos = frm;
+ dialog_token = *pos++;
+ type = *pos++;
+
+ wpa_dbg(wpa_s, MSG_DEBUG, "WNM: Received WNM-Notification Request "
+ "(dialog_token %u type %u sa " MACSTR ")",
+ dialog_token, type, MAC2STR(sa));
+ wpa_hexdump(MSG_DEBUG, "WNM-Notification Request subelements",
+ pos, end - pos);
+
+ if (wpa_s->wpa_state != WPA_COMPLETED ||
+ os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "WNM: WNM-Notification frame not "
+ "from our AP - ignore it");
+ return;
+ }
+
+ switch (type) {
+ case 1:
+ ieee802_11_rx_wnm_notif_req_wfa(wpa_s, sa, pos, end - pos);
+ break;
+ default:
+ wpa_dbg(wpa_s, MSG_DEBUG, "WNM: Ignore unknown "
+ "WNM-Notification type %u", type);
+ break;
+ }
+}
+
+
void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
const struct ieee80211_mgmt *mgmt, size_t len)
{
@@ -782,6 +889,9 @@ void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
case WNM_SLEEP_MODE_RESP:
ieee802_11_rx_wnmsleep_resp(wpa_s, pos, end - pos);
break;
+ case WNM_NOTIFICATION_REQ:
+ ieee802_11_rx_wnm_notif_req(wpa_s, mgmt->sa, pos, end - pos);
+ break;
default:
wpa_printf(MSG_ERROR, "WNM: Unknown request");
break;
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 6278806..07a334a 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -3181,6 +3181,8 @@ static void wpa_cli_action_process(const char *msg)
wpa_cli_exec(action_file, ctrl_ifname, pos);
} else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
+ } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
+ wpa_cli_exec(action_file, ctrl_ifname, pos);
} else if (str_match(pos, WPA_EVENT_TERMINATING)) {
printf("wpa_supplicant is terminating - stop monitoring\n");
wpa_cli_quit = 1;
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index f67daea..71b6b63 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1208,6 +1208,10 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
#endif /* CONFIG_INTERWORKING */
break;
case 5: /* Bits 40-47 */
+#ifdef CONFIG_HS20
+ if (wpa_s->conf->hs20)
+ *pos |= 0x40; /* Bit 46 - WNM-Notification */
+#endif /* CONFIG_HS20 */
break;
case 6: /* Bits 48-55 */
break;
@@ -1218,7 +1222,7 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf)
{
u8 *pos = buf;
- u8 len = 4, i;
+ u8 len = 6, i;
if (len < wpa_s->extended_capa_len)
len = wpa_s->extended_capa_len;