Home | History | Annotate | Download | only in ap
      1 /*
      2  * Hotspot 2.0 AP ANQP processing
      3  * Copyright (c) 2009, Atheros Communications, Inc.
      4  * Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
      5  *
      6  * This software may be distributed under the terms of the BSD license.
      7  * See README for more details.
      8  */
      9 
     10 #include "includes.h"
     11 
     12 #include "common.h"
     13 #include "common/ieee802_11_defs.h"
     14 #include "common/wpa_ctrl.h"
     15 #include "hostapd.h"
     16 #include "ap_config.h"
     17 #include "ap_drv_ops.h"
     18 #include "sta_info.h"
     19 #include "hs20.h"
     20 
     21 
     22 u8 * hostapd_eid_hs20_indication(struct hostapd_data *hapd, u8 *eid)
     23 {
     24 	u8 conf;
     25 	if (!hapd->conf->hs20)
     26 		return eid;
     27 	*eid++ = WLAN_EID_VENDOR_SPECIFIC;
     28 	*eid++ = hapd->conf->hs20_release < 2 ? 5 : 7;
     29 	WPA_PUT_BE24(eid, OUI_WFA);
     30 	eid += 3;
     31 	*eid++ = HS20_INDICATION_OUI_TYPE;
     32 	conf = (hapd->conf->hs20_release - 1) << 4; /* Release Number */
     33 	if (hapd->conf->hs20_release >= 2)
     34 		conf |= HS20_ANQP_DOMAIN_ID_PRESENT;
     35 	if (hapd->conf->disable_dgaf)
     36 		conf |= HS20_DGAF_DISABLED;
     37 	*eid++ = conf;
     38 	if (hapd->conf->hs20_release >= 2) {
     39 		WPA_PUT_LE16(eid, hapd->conf->anqp_domain_id);
     40 		eid += 2;
     41 	}
     42 
     43 	return eid;
     44 }
     45 
     46 
     47 u8 * hostapd_eid_osen(struct hostapd_data *hapd, u8 *eid)
     48 {
     49 	u8 *len;
     50 	u16 capab;
     51 
     52 	if (!hapd->conf->osen)
     53 		return eid;
     54 
     55 	*eid++ = WLAN_EID_VENDOR_SPECIFIC;
     56 	len = eid++; /* to be filled */
     57 	WPA_PUT_BE24(eid, OUI_WFA);
     58 	eid += 3;
     59 	*eid++ = HS20_OSEN_OUI_TYPE;
     60 
     61 	/* Group Data Cipher Suite */
     62 	RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
     63 	eid += RSN_SELECTOR_LEN;
     64 
     65 	/* Pairwise Cipher Suite Count and List */
     66 	WPA_PUT_LE16(eid, 1);
     67 	eid += 2;
     68 	RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_CCMP);
     69 	eid += RSN_SELECTOR_LEN;
     70 
     71 	/* AKM Suite Count and List */
     72 	WPA_PUT_LE16(eid, 1);
     73 	eid += 2;
     74 	RSN_SELECTOR_PUT(eid, RSN_AUTH_KEY_MGMT_OSEN);
     75 	eid += RSN_SELECTOR_LEN;
     76 
     77 	/* RSN Capabilities */
     78 	capab = 0;
     79 	if (hapd->conf->wmm_enabled) {
     80 		/* 4 PTKSA replay counters when using WMM */
     81 		capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
     82 	}
     83 #ifdef CONFIG_IEEE80211W
     84 	if (hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
     85 		capab |= WPA_CAPABILITY_MFPC;
     86 		if (hapd->conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
     87 			capab |= WPA_CAPABILITY_MFPR;
     88 	}
     89 #endif /* CONFIG_IEEE80211W */
     90 #ifdef CONFIG_OCV
     91 	if (hapd->conf->ocv)
     92 		capab |= WPA_CAPABILITY_OCVC;
     93 #endif /* CONFIG_OCV */
     94 	WPA_PUT_LE16(eid, capab);
     95 	eid += 2;
     96 
     97 	*len = eid - len - 1;
     98 
     99 	return eid;
    100 }
    101 
    102 
    103 int hs20_send_wnm_notification(struct hostapd_data *hapd, const u8 *addr,
    104 			       u8 osu_method, const char *url)
    105 {
    106 	struct wpabuf *buf;
    107 	size_t len = 0;
    108 	int ret;
    109 
    110 	/* TODO: should refuse to send notification if the STA is not associated
    111 	 * or if the STA did not indicate support for WNM-Notification */
    112 
    113 	if (url) {
    114 		len = 1 + os_strlen(url);
    115 		if (5 + len > 255) {
    116 			wpa_printf(MSG_INFO, "HS 2.0: Too long URL for "
    117 				   "WNM-Notification: '%s'", url);
    118 			return -1;
    119 		}
    120 	}
    121 
    122 	buf = wpabuf_alloc(4 + 7 + len);
    123 	if (buf == NULL)
    124 		return -1;
    125 
    126 	wpabuf_put_u8(buf, WLAN_ACTION_WNM);
    127 	wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ);
    128 	wpabuf_put_u8(buf, 1); /* Dialog token */
    129 	wpabuf_put_u8(buf, 1); /* Type - 1 reserved for WFA */
    130 
    131 	/* Subscription Remediation subelement */
    132 	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
    133 	wpabuf_put_u8(buf, 5 + len);
    134 	wpabuf_put_be24(buf, OUI_WFA);
    135 	wpabuf_put_u8(buf, HS20_WNM_SUB_REM_NEEDED);
    136 	if (url) {
    137 		wpabuf_put_u8(buf, len - 1);
    138 		wpabuf_put_data(buf, url, len - 1);
    139 		wpabuf_put_u8(buf, osu_method);
    140 	} else {
    141 		/* Server URL and Server Method fields not included */
    142 		wpabuf_put_u8(buf, 0);
    143 	}
    144 
    145 	ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
    146 				      wpabuf_head(buf), wpabuf_len(buf));
    147 
    148 	wpabuf_free(buf);
    149 
    150 	return ret;
    151 }
    152 
    153 
    154 int hs20_send_wnm_notification_deauth_req(struct hostapd_data *hapd,
    155 					  const u8 *addr,
    156 					  const struct wpabuf *payload)
    157 {
    158 	struct wpabuf *buf;
    159 	int ret;
    160 
    161 	/* TODO: should refuse to send notification if the STA is not associated
    162 	 * or if the STA did not indicate support for WNM-Notification */
    163 
    164 	buf = wpabuf_alloc(4 + 6 + wpabuf_len(payload));
    165 	if (buf == NULL)
    166 		return -1;
    167 
    168 	wpabuf_put_u8(buf, WLAN_ACTION_WNM);
    169 	wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ);
    170 	wpabuf_put_u8(buf, 1); /* Dialog token */
    171 	wpabuf_put_u8(buf, 1); /* Type - 1 reserved for WFA */
    172 
    173 	/* Deauthentication Imminent Notice subelement */
    174 	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
    175 	wpabuf_put_u8(buf, 4 + wpabuf_len(payload));
    176 	wpabuf_put_be24(buf, OUI_WFA);
    177 	wpabuf_put_u8(buf, HS20_WNM_DEAUTH_IMMINENT_NOTICE);
    178 	wpabuf_put_buf(buf, payload);
    179 
    180 	ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
    181 				      wpabuf_head(buf), wpabuf_len(buf));
    182 
    183 	wpabuf_free(buf);
    184 
    185 	return ret;
    186 }
    187 
    188 
    189 int hs20_send_wnm_notification_t_c(struct hostapd_data *hapd,
    190 				   const u8 *addr, const char *url)
    191 {
    192 	struct wpabuf *buf;
    193 	int ret;
    194 	size_t url_len;
    195 
    196 	if (!url) {
    197 		wpa_printf(MSG_INFO, "HS 2.0: No T&C Server URL available");
    198 		return -1;
    199 	}
    200 
    201 	url_len = os_strlen(url);
    202 	if (5 + url_len > 255) {
    203 		wpa_printf(MSG_INFO,
    204 			   "HS 2.0: Too long T&C Server URL for WNM-Notification: '%s'",
    205 			   url);
    206 		return -1;
    207 	}
    208 
    209 	buf = wpabuf_alloc(4 + 7 + url_len);
    210 	if (!buf)
    211 		return -1;
    212 
    213 	wpabuf_put_u8(buf, WLAN_ACTION_WNM);
    214 	wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ);
    215 	wpabuf_put_u8(buf, 1); /* Dialog token */
    216 	wpabuf_put_u8(buf, 1); /* Type - 1 reserved for WFA */
    217 
    218 	/* Terms and Conditions Acceptance subelement */
    219 	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
    220 	wpabuf_put_u8(buf, 4 + 1 + url_len);
    221 	wpabuf_put_be24(buf, OUI_WFA);
    222 	wpabuf_put_u8(buf, HS20_WNM_T_C_ACCEPTANCE);
    223 	wpabuf_put_u8(buf, url_len);
    224 	wpabuf_put_str(buf, url);
    225 
    226 	ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
    227 				      wpabuf_head(buf), wpabuf_len(buf));
    228 
    229 	wpabuf_free(buf);
    230 
    231 	return ret;
    232 }
    233 
    234 
    235 void hs20_t_c_filtering(struct hostapd_data *hapd, struct sta_info *sta,
    236 			int enabled)
    237 {
    238 	if (enabled) {
    239 		wpa_printf(MSG_DEBUG,
    240 			   "HS 2.0: Terms and Conditions filtering required for "
    241 			   MACSTR, MAC2STR(sta->addr));
    242 		sta->hs20_t_c_filtering = 1;
    243 		/* TODO: Enable firewall filtering for the STA */
    244 		wpa_msg(hapd->msg_ctx, MSG_INFO, HS20_T_C_FILTERING_ADD MACSTR,
    245 			MAC2STR(sta->addr));
    246 	} else {
    247 		wpa_printf(MSG_DEBUG,
    248 			   "HS 2.0: Terms and Conditions filtering not required for "
    249 			   MACSTR, MAC2STR(sta->addr));
    250 		sta->hs20_t_c_filtering = 0;
    251 		/* TODO: Disable firewall filtering for the STA */
    252 		wpa_msg(hapd->msg_ctx, MSG_INFO,
    253 			HS20_T_C_FILTERING_REMOVE MACSTR, MAC2STR(sta->addr));
    254 	}
    255 }
    256