/*
 * Hotspot 2.0 AP ANQP processing
 * Copyright (c) 2009, Atheros Communications, Inc.
 * Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
 *
 * This software may be distributed under the terms of the BSD license.
 * See README for more details.
 */

#include "includes.h"

#include "common.h"
#include "common/ieee802_11_defs.h"
#include "common/wpa_ctrl.h"
#include "hostapd.h"
#include "ap_config.h"
#include "ap_drv_ops.h"
#include "sta_info.h"
#include "hs20.h"


u8 * hostapd_eid_hs20_indication(struct hostapd_data *hapd, u8 *eid)
{
	u8 conf;
	if (!hapd->conf->hs20)
		return eid;
	*eid++ = WLAN_EID_VENDOR_SPECIFIC;
	*eid++ = hapd->conf->hs20_release < 2 ? 5 : 7;
	WPA_PUT_BE24(eid, OUI_WFA);
	eid += 3;
	*eid++ = HS20_INDICATION_OUI_TYPE;
	conf = (hapd->conf->hs20_release - 1) << 4; /* Release Number */
	if (hapd->conf->hs20_release >= 2)
		conf |= HS20_ANQP_DOMAIN_ID_PRESENT;
	if (hapd->conf->disable_dgaf)
		conf |= HS20_DGAF_DISABLED;
	*eid++ = conf;
	if (hapd->conf->hs20_release >= 2) {
		WPA_PUT_LE16(eid, hapd->conf->anqp_domain_id);
		eid += 2;
	}

	return eid;
}


u8 * hostapd_eid_osen(struct hostapd_data *hapd, u8 *eid)
{
	u8 *len;
	u16 capab;

	if (!hapd->conf->osen)
		return eid;

	*eid++ = WLAN_EID_VENDOR_SPECIFIC;
	len = eid++; /* to be filled */
	WPA_PUT_BE24(eid, OUI_WFA);
	eid += 3;
	*eid++ = HS20_OSEN_OUI_TYPE;

	/* Group Data Cipher Suite */
	RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
	eid += RSN_SELECTOR_LEN;

	/* Pairwise Cipher Suite Count and List */
	WPA_PUT_LE16(eid, 1);
	eid += 2;
	RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_CCMP);
	eid += RSN_SELECTOR_LEN;

	/* AKM Suite Count and List */
	WPA_PUT_LE16(eid, 1);
	eid += 2;
	RSN_SELECTOR_PUT(eid, RSN_AUTH_KEY_MGMT_OSEN);
	eid += RSN_SELECTOR_LEN;

	/* RSN Capabilities */
	capab = 0;
	if (hapd->conf->wmm_enabled) {
		/* 4 PTKSA replay counters when using WMM */
		capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
	}
	if (hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
		capab |= WPA_CAPABILITY_MFPC;
		if (hapd->conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
			capab |= WPA_CAPABILITY_MFPR;
	}
#ifdef CONFIG_OCV
	if (hapd->conf->ocv &&
	    (hapd->iface->drv_flags2 &
	     (WPA_DRIVER_FLAGS2_AP_SME | WPA_DRIVER_FLAGS2_OCV)))
		capab |= WPA_CAPABILITY_OCVC;
#endif /* CONFIG_OCV */
	WPA_PUT_LE16(eid, capab);
	eid += 2;

	*len = eid - len - 1;

	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;
}


int hs20_send_wnm_notification_deauth_req(struct hostapd_data *hapd,
					  const u8 *addr,
					  const struct wpabuf *payload)
{
	struct wpabuf *buf;
	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 */

	buf = wpabuf_alloc(4 + 6 + wpabuf_len(payload));
	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 */

	/* Deauthentication Imminent Notice subelement */
	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
	wpabuf_put_u8(buf, 4 + wpabuf_len(payload));
	wpabuf_put_be24(buf, OUI_WFA);
	wpabuf_put_u8(buf, HS20_WNM_DEAUTH_IMMINENT_NOTICE);
	wpabuf_put_buf(buf, payload);

	ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
				      wpabuf_head(buf), wpabuf_len(buf));

	wpabuf_free(buf);

	return ret;
}


int hs20_send_wnm_notification_t_c(struct hostapd_data *hapd,
				   const u8 *addr, const char *url)
{
	struct wpabuf *buf;
	int ret;
	size_t url_len;

	if (!url) {
		wpa_printf(MSG_INFO, "HS 2.0: No T&C Server URL available");
		return -1;
	}

	url_len = os_strlen(url);
	if (5 + url_len > 255) {
		wpa_printf(MSG_INFO,
			   "HS 2.0: Too long T&C Server URL for WNM-Notification: '%s'",
			   url);
		return -1;
	}

	buf = wpabuf_alloc(4 + 7 + url_len);
	if (!buf)
		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 */

	/* Terms and Conditions Acceptance subelement */
	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
	wpabuf_put_u8(buf, 4 + 1 + url_len);
	wpabuf_put_be24(buf, OUI_WFA);
	wpabuf_put_u8(buf, HS20_WNM_T_C_ACCEPTANCE);
	wpabuf_put_u8(buf, url_len);
	wpabuf_put_str(buf, url);

	ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
				      wpabuf_head(buf), wpabuf_len(buf));

	wpabuf_free(buf);

	return ret;
}


void hs20_t_c_filtering(struct hostapd_data *hapd, struct sta_info *sta,
			int enabled)
{
	if (enabled) {
		wpa_printf(MSG_DEBUG,
			   "HS 2.0: Terms and Conditions filtering required for "
			   MACSTR, MAC2STR(sta->addr));
		sta->hs20_t_c_filtering = 1;
		/* TODO: Enable firewall filtering for the STA */
		wpa_msg(hapd->msg_ctx, MSG_INFO, HS20_T_C_FILTERING_ADD MACSTR,
			MAC2STR(sta->addr));
	} else {
		wpa_printf(MSG_DEBUG,
			   "HS 2.0: Terms and Conditions filtering not required for "
			   MACSTR, MAC2STR(sta->addr));
		sta->hs20_t_c_filtering = 0;
		/* TODO: Disable firewall filtering for the STA */
		wpa_msg(hapd->msg_ctx, MSG_INFO,
			HS20_T_C_FILTERING_REMOVE MACSTR, MAC2STR(sta->addr));
	}
}
