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 "hostapd.h"
     15 #include "ap_config.h"
     16 #include "ap_drv_ops.h"
     17 #include "hs20.h"
     18 
     19 
     20 u8 * hostapd_eid_hs20_indication(struct hostapd_data *hapd, u8 *eid)
     21 {
     22 	u8 conf;
     23 	if (!hapd->conf->hs20)
     24 		return eid;
     25 	*eid++ = WLAN_EID_VENDOR_SPECIFIC;
     26 	*eid++ = 7;
     27 	WPA_PUT_BE24(eid, OUI_WFA);
     28 	eid += 3;
     29 	*eid++ = HS20_INDICATION_OUI_TYPE;
     30 	conf = HS20_VERSION; /* Release Number */
     31 	conf |= HS20_ANQP_DOMAIN_ID_PRESENT;
     32 	if (hapd->conf->disable_dgaf)
     33 		conf |= HS20_DGAF_DISABLED;
     34 	*eid++ = conf;
     35 	WPA_PUT_LE16(eid, hapd->conf->anqp_domain_id);
     36 	eid += 2;
     37 
     38 	return eid;
     39 }
     40 
     41 
     42 u8 * hostapd_eid_osen(struct hostapd_data *hapd, u8 *eid)
     43 {
     44 	u8 *len;
     45 	u16 capab;
     46 
     47 	if (!hapd->conf->osen)
     48 		return eid;
     49 
     50 	*eid++ = WLAN_EID_VENDOR_SPECIFIC;
     51 	len = eid++; /* to be filled */
     52 	WPA_PUT_BE24(eid, OUI_WFA);
     53 	eid += 3;
     54 	*eid++ = HS20_OSEN_OUI_TYPE;
     55 
     56 	/* Group Data Cipher Suite */
     57 	RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
     58 	eid += RSN_SELECTOR_LEN;
     59 
     60 	/* Pairwise Cipher Suite Count and List */
     61 	WPA_PUT_LE16(eid, 1);
     62 	eid += 2;
     63 	RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_CCMP);
     64 	eid += RSN_SELECTOR_LEN;
     65 
     66 	/* AKM Suite Count and List */
     67 	WPA_PUT_LE16(eid, 1);
     68 	eid += 2;
     69 	RSN_SELECTOR_PUT(eid, RSN_AUTH_KEY_MGMT_OSEN);
     70 	eid += RSN_SELECTOR_LEN;
     71 
     72 	/* RSN Capabilities */
     73 	capab = 0;
     74 	if (hapd->conf->wmm_enabled) {
     75 		/* 4 PTKSA replay counters when using WMM */
     76 		capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
     77 	}
     78 #ifdef CONFIG_IEEE80211W
     79 	if (hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
     80 		capab |= WPA_CAPABILITY_MFPC;
     81 		if (hapd->conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
     82 			capab |= WPA_CAPABILITY_MFPR;
     83 	}
     84 #endif /* CONFIG_IEEE80211W */
     85 	WPA_PUT_LE16(eid, capab);
     86 	eid += 2;
     87 
     88 	*len = eid - len - 1;
     89 
     90 	return eid;
     91 }
     92 
     93 
     94 int hs20_send_wnm_notification(struct hostapd_data *hapd, const u8 *addr,
     95 			       u8 osu_method, const char *url)
     96 {
     97 	struct wpabuf *buf;
     98 	size_t len = 0;
     99 	int ret;
    100 
    101 	/* TODO: should refuse to send notification if the STA is not associated
    102 	 * or if the STA did not indicate support for WNM-Notification */
    103 
    104 	if (url) {
    105 		len = 1 + os_strlen(url);
    106 		if (5 + len > 255) {
    107 			wpa_printf(MSG_INFO, "HS 2.0: Too long URL for "
    108 				   "WNM-Notification: '%s'", url);
    109 			return -1;
    110 		}
    111 	}
    112 
    113 	buf = wpabuf_alloc(4 + 7 + len);
    114 	if (buf == NULL)
    115 		return -1;
    116 
    117 	wpabuf_put_u8(buf, WLAN_ACTION_WNM);
    118 	wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ);
    119 	wpabuf_put_u8(buf, 1); /* Dialog token */
    120 	wpabuf_put_u8(buf, 1); /* Type - 1 reserved for WFA */
    121 
    122 	/* Subscription Remediation subelement */
    123 	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
    124 	wpabuf_put_u8(buf, 5 + len);
    125 	wpabuf_put_be24(buf, OUI_WFA);
    126 	wpabuf_put_u8(buf, HS20_WNM_SUB_REM_NEEDED);
    127 	if (url) {
    128 		wpabuf_put_u8(buf, len - 1);
    129 		wpabuf_put_data(buf, url, len - 1);
    130 		wpabuf_put_u8(buf, osu_method);
    131 	} else {
    132 		/* Server URL and Server Method fields not included */
    133 		wpabuf_put_u8(buf, 0);
    134 	}
    135 
    136 	ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
    137 				      wpabuf_head(buf), wpabuf_len(buf));
    138 
    139 	wpabuf_free(buf);
    140 
    141 	return ret;
    142 }
    143 
    144 
    145 int hs20_send_wnm_notification_deauth_req(struct hostapd_data *hapd,
    146 					  const u8 *addr,
    147 					  const struct wpabuf *payload)
    148 {
    149 	struct wpabuf *buf;
    150 	int ret;
    151 
    152 	/* TODO: should refuse to send notification if the STA is not associated
    153 	 * or if the STA did not indicate support for WNM-Notification */
    154 
    155 	buf = wpabuf_alloc(4 + 6 + wpabuf_len(payload));
    156 	if (buf == NULL)
    157 		return -1;
    158 
    159 	wpabuf_put_u8(buf, WLAN_ACTION_WNM);
    160 	wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ);
    161 	wpabuf_put_u8(buf, 1); /* Dialog token */
    162 	wpabuf_put_u8(buf, 1); /* Type - 1 reserved for WFA */
    163 
    164 	/* Deauthentication Imminent Notice subelement */
    165 	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
    166 	wpabuf_put_u8(buf, 4 + wpabuf_len(payload));
    167 	wpabuf_put_be24(buf, OUI_WFA);
    168 	wpabuf_put_u8(buf, HS20_WNM_DEAUTH_IMMINENT_NOTICE);
    169 	wpabuf_put_buf(buf, payload);
    170 
    171 	ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
    172 				      wpabuf_head(buf), wpabuf_len(buf));
    173 
    174 	wpabuf_free(buf);
    175 
    176 	return ret;
    177 }
    178