HS 2.0R2 AP: Add WNM-Notification Request for Subscription Remediation

Subscription remediation notification can now be sent from hostapd with:
hostapd_cli hs20_wnm_notif 02:00:00:00:00:00 http://example.com/foo/

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2013-03-17 16:03:42 +02:00 committed by Jouni Malinen
parent d5d24784e6
commit 3fb17a9530
5 changed files with 115 additions and 0 deletions

View file

@ -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,32 @@ static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd,
#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);
}
#endif /* CONFIG_HS20 */
#ifdef CONFIG_INTERWORKING
@ -1348,6 +1375,11 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
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;
#endif /* CONFIG_HS20 */
#ifdef CONFIG_WNM
} else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))

View file

@ -743,6 +743,26 @@ static int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl,
}
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_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
hostapd_cli_quit = 1;
@ -941,6 +961,7 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
{ "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 },
{ NULL, NULL }
};

View file

@ -13,6 +13,7 @@
#include "common/ieee802_11_defs.h"
#include "hostapd.h"
#include "ap_config.h"
#include "ap_drv_ops.h"
#include "hs20.h"
@ -36,3 +37,54 @@ u8 * hostapd_eid_hs20_indication(struct hostapd_data *hapd, u8 *eid)
return eid;
}
int hs20_send_wnm_notification(struct hostapd_data *hapd, const u8 *addr,
u8 osu_method, const char *url)
{
struct wpabuf *buf;
size_t len = 0;
int ret;
/* TODO: should refuse to send notification if the STA is not associated
* or if the STA did not indicate support for WNM-Notification */
if (url) {
len = 1 + os_strlen(url);
if (5 + len > 255) {
wpa_printf(MSG_INFO, "HS 2.0: Too long URL for "
"WNM-Notification: '%s'", url);
return -1;
}
}
buf = wpabuf_alloc(4 + 7 + len);
if (buf == NULL)
return -1;
wpabuf_put_u8(buf, WLAN_ACTION_WNM);
wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ);
wpabuf_put_u8(buf, 1); /* Dialog token */
wpabuf_put_u8(buf, 1); /* Type - 1 reserved for WFA */
/* Subscription Remediation subelement */
wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
wpabuf_put_u8(buf, 5 + len);
wpabuf_put_be24(buf, OUI_WFA);
wpabuf_put_u8(buf, HS20_WNM_SUB_REM_NEEDED);
if (url) {
wpabuf_put_u8(buf, len - 1);
wpabuf_put_data(buf, url, len - 1);
wpabuf_put_u8(buf, osu_method);
} else {
/* Server URL and Server Method fields not included */
wpabuf_put_u8(buf, 0);
}
ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
wpabuf_head(buf), wpabuf_len(buf));
wpabuf_free(buf);
return ret;
}

View file

@ -12,5 +12,7 @@
struct hostapd_data;
u8 * hostapd_eid_hs20_indication(struct hostapd_data *hapd, u8 *eid);
int hs20_send_wnm_notification(struct hostapd_data *hapd, const u8 *addr,
u8 osu_method, const char *url);
#endif /* HS20_H */

View file

@ -199,6 +199,10 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
}
break;
case 5: /* Bits 40-47 */
#ifdef CONFIG_HS20
if (hapd->conf->hs20)
*pos |= 0x40; /* Bit 46 - WNM-Notification */
#endif /* CONFIG_HS20 */
break;
case 6: /* Bits 48-55 */
if (hapd->conf->ssid.utf8_ssid)
@ -225,6 +229,10 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
if (len < 4)
len = 4;
#endif /* CONFIG_WNM */
#ifdef CONFIG_HS20
if (hapd->conf->hs20 && len < 6)
len = 6;
#endif /* CONFIG_HS20 */
if (len < hapd->iface->extended_capa_len)
len = hapd->iface->extended_capa_len;
if (len == 0)