Home | History | Annotate | Download | only in ap
      1 /*
      2  * Generic advertisement service (GAS) server
      3  * Copyright (c) 2011-2014, Qualcomm Atheros, Inc.
      4  *
      5  * This software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  */
      8 
      9 #include "includes.h"
     10 
     11 #include "common.h"
     12 #include "common/ieee802_11_defs.h"
     13 #include "common/gas.h"
     14 #include "utils/eloop.h"
     15 #include "hostapd.h"
     16 #include "ap_config.h"
     17 #include "ap_drv_ops.h"
     18 #include "sta_info.h"
     19 #include "gas_serv.h"
     20 
     21 
     22 static void convert_to_protected_dual(struct wpabuf *msg)
     23 {
     24 	u8 *categ = wpabuf_mhead_u8(msg);
     25 	*categ = WLAN_ACTION_PROTECTED_DUAL;
     26 }
     27 
     28 
     29 static struct gas_dialog_info *
     30 gas_dialog_create(struct hostapd_data *hapd, const u8 *addr, u8 dialog_token)
     31 {
     32 	struct sta_info *sta;
     33 	struct gas_dialog_info *dia = NULL;
     34 	int i, j;
     35 
     36 	sta = ap_get_sta(hapd, addr);
     37 	if (!sta) {
     38 		/*
     39 		 * We need a STA entry to be able to maintain state for
     40 		 * the GAS query.
     41 		 */
     42 		wpa_printf(MSG_DEBUG, "ANQP: Add a temporary STA entry for "
     43 			   "GAS query");
     44 		sta = ap_sta_add(hapd, addr);
     45 		if (!sta) {
     46 			wpa_printf(MSG_DEBUG, "Failed to add STA " MACSTR
     47 				   " for GAS query", MAC2STR(addr));
     48 			return NULL;
     49 		}
     50 		sta->flags |= WLAN_STA_GAS;
     51 		/*
     52 		 * The default inactivity is 300 seconds. We don't need
     53 		 * it to be that long.
     54 		 */
     55 		ap_sta_session_timeout(hapd, sta, 5);
     56 	} else {
     57 		ap_sta_replenish_timeout(hapd, sta, 5);
     58 	}
     59 
     60 	if (sta->gas_dialog == NULL) {
     61 		sta->gas_dialog = os_calloc(GAS_DIALOG_MAX,
     62 					    sizeof(struct gas_dialog_info));
     63 		if (sta->gas_dialog == NULL)
     64 			return NULL;
     65 	}
     66 
     67 	for (i = sta->gas_dialog_next, j = 0; j < GAS_DIALOG_MAX; i++, j++) {
     68 		if (i == GAS_DIALOG_MAX)
     69 			i = 0;
     70 		if (sta->gas_dialog[i].valid)
     71 			continue;
     72 		dia = &sta->gas_dialog[i];
     73 		dia->valid = 1;
     74 		dia->dialog_token = dialog_token;
     75 		sta->gas_dialog_next = (++i == GAS_DIALOG_MAX) ? 0 : i;
     76 		return dia;
     77 	}
     78 
     79 	wpa_msg(hapd->msg_ctx, MSG_ERROR, "ANQP: Could not create dialog for "
     80 		MACSTR " dialog_token %u. Consider increasing "
     81 		"GAS_DIALOG_MAX.", MAC2STR(addr), dialog_token);
     82 
     83 	return NULL;
     84 }
     85 
     86 
     87 struct gas_dialog_info *
     88 gas_serv_dialog_find(struct hostapd_data *hapd, const u8 *addr,
     89 		     u8 dialog_token)
     90 {
     91 	struct sta_info *sta;
     92 	int i;
     93 
     94 	sta = ap_get_sta(hapd, addr);
     95 	if (!sta) {
     96 		wpa_printf(MSG_DEBUG, "ANQP: could not find STA " MACSTR,
     97 			   MAC2STR(addr));
     98 		return NULL;
     99 	}
    100 	for (i = 0; sta->gas_dialog && i < GAS_DIALOG_MAX; i++) {
    101 		if (sta->gas_dialog[i].dialog_token != dialog_token ||
    102 		    !sta->gas_dialog[i].valid)
    103 			continue;
    104 		ap_sta_replenish_timeout(hapd, sta, 5);
    105 		return &sta->gas_dialog[i];
    106 	}
    107 	wpa_printf(MSG_DEBUG, "ANQP: Could not find dialog for "
    108 		   MACSTR " dialog_token %u", MAC2STR(addr), dialog_token);
    109 	return NULL;
    110 }
    111 
    112 
    113 void gas_serv_dialog_clear(struct gas_dialog_info *dia)
    114 {
    115 	wpabuf_free(dia->sd_resp);
    116 	os_memset(dia, 0, sizeof(*dia));
    117 }
    118 
    119 
    120 static void gas_serv_free_dialogs(struct hostapd_data *hapd,
    121 				  const u8 *sta_addr)
    122 {
    123 	struct sta_info *sta;
    124 	int i;
    125 
    126 	sta = ap_get_sta(hapd, sta_addr);
    127 	if (sta == NULL || sta->gas_dialog == NULL)
    128 		return;
    129 
    130 	for (i = 0; i < GAS_DIALOG_MAX; i++) {
    131 		if (sta->gas_dialog[i].valid)
    132 			return;
    133 	}
    134 
    135 	os_free(sta->gas_dialog);
    136 	sta->gas_dialog = NULL;
    137 }
    138 
    139 
    140 #ifdef CONFIG_HS20
    141 static void anqp_add_hs_capab_list(struct hostapd_data *hapd,
    142 				   struct wpabuf *buf)
    143 {
    144 	u8 *len;
    145 
    146 	len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
    147 	wpabuf_put_be24(buf, OUI_WFA);
    148 	wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
    149 	wpabuf_put_u8(buf, HS20_STYPE_CAPABILITY_LIST);
    150 	wpabuf_put_u8(buf, 0); /* Reserved */
    151 	wpabuf_put_u8(buf, HS20_STYPE_CAPABILITY_LIST);
    152 	if (hapd->conf->hs20_oper_friendly_name)
    153 		wpabuf_put_u8(buf, HS20_STYPE_OPERATOR_FRIENDLY_NAME);
    154 	if (hapd->conf->hs20_wan_metrics)
    155 		wpabuf_put_u8(buf, HS20_STYPE_WAN_METRICS);
    156 	if (hapd->conf->hs20_connection_capability)
    157 		wpabuf_put_u8(buf, HS20_STYPE_CONNECTION_CAPABILITY);
    158 	if (hapd->conf->nai_realm_data)
    159 		wpabuf_put_u8(buf, HS20_STYPE_NAI_HOME_REALM_QUERY);
    160 	if (hapd->conf->hs20_operating_class)
    161 		wpabuf_put_u8(buf, HS20_STYPE_OPERATING_CLASS);
    162 	if (hapd->conf->hs20_osu_providers_count)
    163 		wpabuf_put_u8(buf, HS20_STYPE_OSU_PROVIDERS_LIST);
    164 	if (hapd->conf->hs20_icons_count)
    165 		wpabuf_put_u8(buf, HS20_STYPE_ICON_REQUEST);
    166 	gas_anqp_set_element_len(buf, len);
    167 }
    168 #endif /* CONFIG_HS20 */
    169 
    170 
    171 static struct anqp_element * get_anqp_elem(struct hostapd_data *hapd,
    172 					   u16 infoid)
    173 {
    174 	struct anqp_element *elem;
    175 
    176 	dl_list_for_each(elem, &hapd->conf->anqp_elem, struct anqp_element,
    177 			 list) {
    178 		if (elem->infoid == infoid)
    179 			return elem;
    180 	}
    181 
    182 	return NULL;
    183 }
    184 
    185 
    186 static void anqp_add_elem(struct hostapd_data *hapd, struct wpabuf *buf,
    187 			  u16 infoid)
    188 {
    189 	struct anqp_element *elem;
    190 
    191 	elem = get_anqp_elem(hapd, infoid);
    192 	if (!elem)
    193 		return;
    194 	if (wpabuf_tailroom(buf) < 2 + 2 + wpabuf_len(elem->payload)) {
    195 		wpa_printf(MSG_DEBUG, "ANQP: No room for InfoID %u payload",
    196 			   infoid);
    197 		return;
    198 	}
    199 
    200 	wpabuf_put_le16(buf, infoid);
    201 	wpabuf_put_le16(buf, wpabuf_len(elem->payload));
    202 	wpabuf_put_buf(buf, elem->payload);
    203 }
    204 
    205 
    206 static int anqp_add_override(struct hostapd_data *hapd, struct wpabuf *buf,
    207 			     u16 infoid)
    208 {
    209 	if (get_anqp_elem(hapd, infoid)) {
    210 		anqp_add_elem(hapd, buf, infoid);
    211 		return 1;
    212 	}
    213 
    214 	return 0;
    215 }
    216 
    217 
    218 static void anqp_add_capab_list(struct hostapd_data *hapd,
    219 				struct wpabuf *buf)
    220 {
    221 	u8 *len;
    222 	u16 id;
    223 
    224 	if (anqp_add_override(hapd, buf, ANQP_CAPABILITY_LIST))
    225 		return;
    226 
    227 	len = gas_anqp_add_element(buf, ANQP_CAPABILITY_LIST);
    228 	wpabuf_put_le16(buf, ANQP_CAPABILITY_LIST);
    229 	if (hapd->conf->venue_name || get_anqp_elem(hapd, ANQP_VENUE_NAME))
    230 		wpabuf_put_le16(buf, ANQP_VENUE_NAME);
    231 	if (get_anqp_elem(hapd, ANQP_EMERGENCY_CALL_NUMBER))
    232 		wpabuf_put_le16(buf, ANQP_EMERGENCY_CALL_NUMBER);
    233 	if (hapd->conf->network_auth_type ||
    234 	    get_anqp_elem(hapd, ANQP_NETWORK_AUTH_TYPE))
    235 		wpabuf_put_le16(buf, ANQP_NETWORK_AUTH_TYPE);
    236 	if (hapd->conf->roaming_consortium ||
    237 	    get_anqp_elem(hapd, ANQP_ROAMING_CONSORTIUM))
    238 		wpabuf_put_le16(buf, ANQP_ROAMING_CONSORTIUM);
    239 	if (hapd->conf->ipaddr_type_configured ||
    240 	    get_anqp_elem(hapd, ANQP_IP_ADDR_TYPE_AVAILABILITY))
    241 		wpabuf_put_le16(buf, ANQP_IP_ADDR_TYPE_AVAILABILITY);
    242 	if (hapd->conf->nai_realm_data ||
    243 	    get_anqp_elem(hapd, ANQP_NAI_REALM))
    244 		wpabuf_put_le16(buf, ANQP_NAI_REALM);
    245 	if (hapd->conf->anqp_3gpp_cell_net ||
    246 	    get_anqp_elem(hapd, ANQP_3GPP_CELLULAR_NETWORK))
    247 		wpabuf_put_le16(buf, ANQP_3GPP_CELLULAR_NETWORK);
    248 	if (get_anqp_elem(hapd, ANQP_AP_GEOSPATIAL_LOCATION))
    249 		wpabuf_put_le16(buf, ANQP_AP_GEOSPATIAL_LOCATION);
    250 	if (get_anqp_elem(hapd, ANQP_AP_CIVIC_LOCATION))
    251 		wpabuf_put_le16(buf, ANQP_AP_CIVIC_LOCATION);
    252 	if (get_anqp_elem(hapd, ANQP_AP_LOCATION_PUBLIC_URI))
    253 		wpabuf_put_le16(buf, ANQP_AP_LOCATION_PUBLIC_URI);
    254 	if (hapd->conf->domain_name || get_anqp_elem(hapd, ANQP_DOMAIN_NAME))
    255 		wpabuf_put_le16(buf, ANQP_DOMAIN_NAME);
    256 	if (get_anqp_elem(hapd, ANQP_EMERGENCY_ALERT_URI))
    257 		wpabuf_put_le16(buf, ANQP_EMERGENCY_ALERT_URI);
    258 	if (get_anqp_elem(hapd, ANQP_EMERGENCY_NAI))
    259 		wpabuf_put_le16(buf, ANQP_EMERGENCY_NAI);
    260 	if (get_anqp_elem(hapd, ANQP_NEIGHBOR_REPORT))
    261 		wpabuf_put_le16(buf, ANQP_NEIGHBOR_REPORT);
    262 	for (id = 273; id < 277; id++) {
    263 		if (get_anqp_elem(hapd, id))
    264 			wpabuf_put_le16(buf, id);
    265 	}
    266 	if (get_anqp_elem(hapd, ANQP_VENUE_URL))
    267 		wpabuf_put_le16(buf, ANQP_VENUE_URL);
    268 	if (get_anqp_elem(hapd, ANQP_ADVICE_OF_CHARGE))
    269 		wpabuf_put_le16(buf, ANQP_ADVICE_OF_CHARGE);
    270 	if (get_anqp_elem(hapd, ANQP_LOCAL_CONTENT))
    271 		wpabuf_put_le16(buf, ANQP_LOCAL_CONTENT);
    272 #ifdef CONFIG_HS20
    273 	anqp_add_hs_capab_list(hapd, buf);
    274 #endif /* CONFIG_HS20 */
    275 	gas_anqp_set_element_len(buf, len);
    276 }
    277 
    278 
    279 static void anqp_add_venue_name(struct hostapd_data *hapd, struct wpabuf *buf)
    280 {
    281 	if (anqp_add_override(hapd, buf, ANQP_VENUE_NAME))
    282 		return;
    283 
    284 	if (hapd->conf->venue_name) {
    285 		u8 *len;
    286 		unsigned int i;
    287 		len = gas_anqp_add_element(buf, ANQP_VENUE_NAME);
    288 		wpabuf_put_u8(buf, hapd->conf->venue_group);
    289 		wpabuf_put_u8(buf, hapd->conf->venue_type);
    290 		for (i = 0; i < hapd->conf->venue_name_count; i++) {
    291 			struct hostapd_lang_string *vn;
    292 			vn = &hapd->conf->venue_name[i];
    293 			wpabuf_put_u8(buf, 3 + vn->name_len);
    294 			wpabuf_put_data(buf, vn->lang, 3);
    295 			wpabuf_put_data(buf, vn->name, vn->name_len);
    296 		}
    297 		gas_anqp_set_element_len(buf, len);
    298 	}
    299 }
    300 
    301 
    302 static void anqp_add_network_auth_type(struct hostapd_data *hapd,
    303 				       struct wpabuf *buf)
    304 {
    305 	if (anqp_add_override(hapd, buf, ANQP_NETWORK_AUTH_TYPE))
    306 		return;
    307 
    308 	if (hapd->conf->network_auth_type) {
    309 		wpabuf_put_le16(buf, ANQP_NETWORK_AUTH_TYPE);
    310 		wpabuf_put_le16(buf, hapd->conf->network_auth_type_len);
    311 		wpabuf_put_data(buf, hapd->conf->network_auth_type,
    312 				hapd->conf->network_auth_type_len);
    313 	}
    314 }
    315 
    316 
    317 static void anqp_add_roaming_consortium(struct hostapd_data *hapd,
    318 					struct wpabuf *buf)
    319 {
    320 	unsigned int i;
    321 	u8 *len;
    322 
    323 	if (anqp_add_override(hapd, buf, ANQP_ROAMING_CONSORTIUM))
    324 		return;
    325 
    326 	len = gas_anqp_add_element(buf, ANQP_ROAMING_CONSORTIUM);
    327 	for (i = 0; i < hapd->conf->roaming_consortium_count; i++) {
    328 		struct hostapd_roaming_consortium *rc;
    329 		rc = &hapd->conf->roaming_consortium[i];
    330 		wpabuf_put_u8(buf, rc->len);
    331 		wpabuf_put_data(buf, rc->oi, rc->len);
    332 	}
    333 	gas_anqp_set_element_len(buf, len);
    334 }
    335 
    336 
    337 static void anqp_add_ip_addr_type_availability(struct hostapd_data *hapd,
    338 					       struct wpabuf *buf)
    339 {
    340 	if (anqp_add_override(hapd, buf, ANQP_IP_ADDR_TYPE_AVAILABILITY))
    341 		return;
    342 
    343 	if (hapd->conf->ipaddr_type_configured) {
    344 		wpabuf_put_le16(buf, ANQP_IP_ADDR_TYPE_AVAILABILITY);
    345 		wpabuf_put_le16(buf, 1);
    346 		wpabuf_put_u8(buf, hapd->conf->ipaddr_type_availability);
    347 	}
    348 }
    349 
    350 
    351 static void anqp_add_nai_realm_eap(struct wpabuf *buf,
    352 				   struct hostapd_nai_realm_data *realm)
    353 {
    354 	unsigned int i, j;
    355 
    356 	wpabuf_put_u8(buf, realm->eap_method_count);
    357 
    358 	for (i = 0; i < realm->eap_method_count; i++) {
    359 		struct hostapd_nai_realm_eap *eap = &realm->eap_method[i];
    360 		wpabuf_put_u8(buf, 2 + (3 * eap->num_auths));
    361 		wpabuf_put_u8(buf, eap->eap_method);
    362 		wpabuf_put_u8(buf, eap->num_auths);
    363 		for (j = 0; j < eap->num_auths; j++) {
    364 			wpabuf_put_u8(buf, eap->auth_id[j]);
    365 			wpabuf_put_u8(buf, 1);
    366 			wpabuf_put_u8(buf, eap->auth_val[j]);
    367 		}
    368 	}
    369 }
    370 
    371 
    372 static void anqp_add_nai_realm_data(struct wpabuf *buf,
    373 				    struct hostapd_nai_realm_data *realm,
    374 				    unsigned int realm_idx)
    375 {
    376 	u8 *realm_data_len;
    377 
    378 	wpa_printf(MSG_DEBUG, "realm=%s, len=%d", realm->realm[realm_idx],
    379 		   (int) os_strlen(realm->realm[realm_idx]));
    380 	realm_data_len = wpabuf_put(buf, 2);
    381 	wpabuf_put_u8(buf, realm->encoding);
    382 	wpabuf_put_u8(buf, os_strlen(realm->realm[realm_idx]));
    383 	wpabuf_put_str(buf, realm->realm[realm_idx]);
    384 	anqp_add_nai_realm_eap(buf, realm);
    385 	gas_anqp_set_element_len(buf, realm_data_len);
    386 }
    387 
    388 
    389 static int hs20_add_nai_home_realm_matches(struct hostapd_data *hapd,
    390 					   struct wpabuf *buf,
    391 					   const u8 *home_realm,
    392 					   size_t home_realm_len)
    393 {
    394 	unsigned int i, j, k;
    395 	u8 num_realms, num_matching = 0, encoding, realm_len, *realm_list_len;
    396 	struct hostapd_nai_realm_data *realm;
    397 	const u8 *pos, *realm_name, *end;
    398 	struct {
    399 		unsigned int realm_data_idx;
    400 		unsigned int realm_idx;
    401 	} matches[10];
    402 
    403 	pos = home_realm;
    404 	end = pos + home_realm_len;
    405 	if (end - pos < 1) {
    406 		wpa_hexdump(MSG_DEBUG, "Too short NAI Home Realm Query",
    407 			    home_realm, home_realm_len);
    408 		return -1;
    409 	}
    410 	num_realms = *pos++;
    411 
    412 	for (i = 0; i < num_realms && num_matching < 10; i++) {
    413 		if (end - pos < 2) {
    414 			wpa_hexdump(MSG_DEBUG,
    415 				    "Truncated NAI Home Realm Query",
    416 				    home_realm, home_realm_len);
    417 			return -1;
    418 		}
    419 		encoding = *pos++;
    420 		realm_len = *pos++;
    421 		if (realm_len > end - pos) {
    422 			wpa_hexdump(MSG_DEBUG,
    423 				    "Truncated NAI Home Realm Query",
    424 				    home_realm, home_realm_len);
    425 			return -1;
    426 		}
    427 		realm_name = pos;
    428 		for (j = 0; j < hapd->conf->nai_realm_count &&
    429 			     num_matching < 10; j++) {
    430 			const u8 *rpos, *rend;
    431 			realm = &hapd->conf->nai_realm_data[j];
    432 			if (encoding != realm->encoding)
    433 				continue;
    434 
    435 			rpos = realm_name;
    436 			while (rpos < realm_name + realm_len &&
    437 			       num_matching < 10) {
    438 				for (rend = rpos;
    439 				     rend < realm_name + realm_len; rend++) {
    440 					if (*rend == ';')
    441 						break;
    442 				}
    443 				for (k = 0; k < MAX_NAI_REALMS &&
    444 					     realm->realm[k] &&
    445 					     num_matching < 10; k++) {
    446 					if ((int) os_strlen(realm->realm[k]) !=
    447 					    rend - rpos ||
    448 					    os_strncmp((char *) rpos,
    449 						       realm->realm[k],
    450 						       rend - rpos) != 0)
    451 						continue;
    452 					matches[num_matching].realm_data_idx =
    453 						j;
    454 					matches[num_matching].realm_idx = k;
    455 					num_matching++;
    456 				}
    457 				rpos = rend + 1;
    458 			}
    459 		}
    460 		pos += realm_len;
    461 	}
    462 
    463 	realm_list_len = gas_anqp_add_element(buf, ANQP_NAI_REALM);
    464 	wpabuf_put_le16(buf, num_matching);
    465 
    466 	/*
    467 	 * There are two ways to format. 1. each realm in a NAI Realm Data unit
    468 	 * 2. all realms that share the same EAP methods in a NAI Realm Data
    469 	 * unit. The first format is likely to be bigger in size than the
    470 	 * second, but may be easier to parse and process by the receiver.
    471 	 */
    472 	for (i = 0; i < num_matching; i++) {
    473 		wpa_printf(MSG_DEBUG, "realm_idx %d, realm_data_idx %d",
    474 			   matches[i].realm_data_idx, matches[i].realm_idx);
    475 		realm = &hapd->conf->nai_realm_data[matches[i].realm_data_idx];
    476 		anqp_add_nai_realm_data(buf, realm, matches[i].realm_idx);
    477 	}
    478 	gas_anqp_set_element_len(buf, realm_list_len);
    479 	return 0;
    480 }
    481 
    482 
    483 static void anqp_add_nai_realm(struct hostapd_data *hapd, struct wpabuf *buf,
    484 			       const u8 *home_realm, size_t home_realm_len,
    485 			       int nai_realm, int nai_home_realm)
    486 {
    487 	if (nai_realm && !nai_home_realm &&
    488 	    anqp_add_override(hapd, buf, ANQP_NAI_REALM))
    489 		return;
    490 
    491 	if (nai_realm && hapd->conf->nai_realm_data) {
    492 		u8 *len;
    493 		unsigned int i, j;
    494 		len = gas_anqp_add_element(buf, ANQP_NAI_REALM);
    495 		wpabuf_put_le16(buf, hapd->conf->nai_realm_count);
    496 		for (i = 0; i < hapd->conf->nai_realm_count; i++) {
    497 			u8 *realm_data_len, *realm_len;
    498 			struct hostapd_nai_realm_data *realm;
    499 
    500 			realm = &hapd->conf->nai_realm_data[i];
    501 			realm_data_len = wpabuf_put(buf, 2);
    502 			wpabuf_put_u8(buf, realm->encoding);
    503 			realm_len = wpabuf_put(buf, 1);
    504 			for (j = 0; realm->realm[j]; j++) {
    505 				if (j > 0)
    506 					wpabuf_put_u8(buf, ';');
    507 				wpabuf_put_str(buf, realm->realm[j]);
    508 			}
    509 			*realm_len = (u8 *) wpabuf_put(buf, 0) - realm_len - 1;
    510 			anqp_add_nai_realm_eap(buf, realm);
    511 			gas_anqp_set_element_len(buf, realm_data_len);
    512 		}
    513 		gas_anqp_set_element_len(buf, len);
    514 	} else if (nai_home_realm && hapd->conf->nai_realm_data && home_realm) {
    515 		hs20_add_nai_home_realm_matches(hapd, buf, home_realm,
    516 						home_realm_len);
    517 	}
    518 }
    519 
    520 
    521 static void anqp_add_3gpp_cellular_network(struct hostapd_data *hapd,
    522 					   struct wpabuf *buf)
    523 {
    524 	if (anqp_add_override(hapd, buf, ANQP_3GPP_CELLULAR_NETWORK))
    525 		return;
    526 
    527 	if (hapd->conf->anqp_3gpp_cell_net) {
    528 		wpabuf_put_le16(buf, ANQP_3GPP_CELLULAR_NETWORK);
    529 		wpabuf_put_le16(buf,
    530 				hapd->conf->anqp_3gpp_cell_net_len);
    531 		wpabuf_put_data(buf, hapd->conf->anqp_3gpp_cell_net,
    532 				hapd->conf->anqp_3gpp_cell_net_len);
    533 	}
    534 }
    535 
    536 
    537 static void anqp_add_domain_name(struct hostapd_data *hapd, struct wpabuf *buf)
    538 {
    539 	if (anqp_add_override(hapd, buf, ANQP_DOMAIN_NAME))
    540 		return;
    541 
    542 	if (hapd->conf->domain_name) {
    543 		wpabuf_put_le16(buf, ANQP_DOMAIN_NAME);
    544 		wpabuf_put_le16(buf, hapd->conf->domain_name_len);
    545 		wpabuf_put_data(buf, hapd->conf->domain_name,
    546 				hapd->conf->domain_name_len);
    547 	}
    548 }
    549 
    550 
    551 #ifdef CONFIG_HS20
    552 
    553 static void anqp_add_operator_friendly_name(struct hostapd_data *hapd,
    554 					    struct wpabuf *buf)
    555 {
    556 	if (hapd->conf->hs20_oper_friendly_name) {
    557 		u8 *len;
    558 		unsigned int i;
    559 		len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
    560 		wpabuf_put_be24(buf, OUI_WFA);
    561 		wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
    562 		wpabuf_put_u8(buf, HS20_STYPE_OPERATOR_FRIENDLY_NAME);
    563 		wpabuf_put_u8(buf, 0); /* Reserved */
    564 		for (i = 0; i < hapd->conf->hs20_oper_friendly_name_count; i++)
    565 		{
    566 			struct hostapd_lang_string *vn;
    567 			vn = &hapd->conf->hs20_oper_friendly_name[i];
    568 			wpabuf_put_u8(buf, 3 + vn->name_len);
    569 			wpabuf_put_data(buf, vn->lang, 3);
    570 			wpabuf_put_data(buf, vn->name, vn->name_len);
    571 		}
    572 		gas_anqp_set_element_len(buf, len);
    573 	}
    574 }
    575 
    576 
    577 static void anqp_add_wan_metrics(struct hostapd_data *hapd,
    578 				 struct wpabuf *buf)
    579 {
    580 	if (hapd->conf->hs20_wan_metrics) {
    581 		u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
    582 		wpabuf_put_be24(buf, OUI_WFA);
    583 		wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
    584 		wpabuf_put_u8(buf, HS20_STYPE_WAN_METRICS);
    585 		wpabuf_put_u8(buf, 0); /* Reserved */
    586 		wpabuf_put_data(buf, hapd->conf->hs20_wan_metrics, 13);
    587 		gas_anqp_set_element_len(buf, len);
    588 	}
    589 }
    590 
    591 
    592 static void anqp_add_connection_capability(struct hostapd_data *hapd,
    593 					   struct wpabuf *buf)
    594 {
    595 	if (hapd->conf->hs20_connection_capability) {
    596 		u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
    597 		wpabuf_put_be24(buf, OUI_WFA);
    598 		wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
    599 		wpabuf_put_u8(buf, HS20_STYPE_CONNECTION_CAPABILITY);
    600 		wpabuf_put_u8(buf, 0); /* Reserved */
    601 		wpabuf_put_data(buf, hapd->conf->hs20_connection_capability,
    602 				hapd->conf->hs20_connection_capability_len);
    603 		gas_anqp_set_element_len(buf, len);
    604 	}
    605 }
    606 
    607 
    608 static void anqp_add_operating_class(struct hostapd_data *hapd,
    609 				     struct wpabuf *buf)
    610 {
    611 	if (hapd->conf->hs20_operating_class) {
    612 		u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
    613 		wpabuf_put_be24(buf, OUI_WFA);
    614 		wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
    615 		wpabuf_put_u8(buf, HS20_STYPE_OPERATING_CLASS);
    616 		wpabuf_put_u8(buf, 0); /* Reserved */
    617 		wpabuf_put_data(buf, hapd->conf->hs20_operating_class,
    618 				hapd->conf->hs20_operating_class_len);
    619 		gas_anqp_set_element_len(buf, len);
    620 	}
    621 }
    622 
    623 
    624 static void anqp_add_osu_provider(struct wpabuf *buf,
    625 				  struct hostapd_bss_config *bss,
    626 				  struct hs20_osu_provider *p)
    627 {
    628 	u8 *len, *len2, *count;
    629 	unsigned int i;
    630 
    631 	len = wpabuf_put(buf, 2); /* OSU Provider Length to be filled */
    632 
    633 	/* OSU Friendly Name Duples */
    634 	len2 = wpabuf_put(buf, 2);
    635 	for (i = 0; i < p->friendly_name_count; i++) {
    636 		struct hostapd_lang_string *s = &p->friendly_name[i];
    637 		wpabuf_put_u8(buf, 3 + s->name_len);
    638 		wpabuf_put_data(buf, s->lang, 3);
    639 		wpabuf_put_data(buf, s->name, s->name_len);
    640 	}
    641 	WPA_PUT_LE16(len2, (u8 *) wpabuf_put(buf, 0) - len2 - 2);
    642 
    643 	/* OSU Server URI */
    644 	if (p->server_uri) {
    645 		wpabuf_put_u8(buf, os_strlen(p->server_uri));
    646 		wpabuf_put_str(buf, p->server_uri);
    647 	} else
    648 		wpabuf_put_u8(buf, 0);
    649 
    650 	/* OSU Method List */
    651 	count = wpabuf_put(buf, 1);
    652 	for (i = 0; p->method_list[i] >= 0; i++)
    653 		wpabuf_put_u8(buf, p->method_list[i]);
    654 	*count = i;
    655 
    656 	/* Icons Available */
    657 	len2 = wpabuf_put(buf, 2);
    658 	for (i = 0; i < p->icons_count; i++) {
    659 		size_t j;
    660 		struct hs20_icon *icon = NULL;
    661 
    662 		for (j = 0; j < bss->hs20_icons_count && !icon; j++) {
    663 			if (os_strcmp(p->icons[i], bss->hs20_icons[j].name) ==
    664 			    0)
    665 				icon = &bss->hs20_icons[j];
    666 		}
    667 		if (!icon)
    668 			continue; /* icon info not found */
    669 
    670 		wpabuf_put_le16(buf, icon->width);
    671 		wpabuf_put_le16(buf, icon->height);
    672 		wpabuf_put_data(buf, icon->language, 3);
    673 		wpabuf_put_u8(buf, os_strlen(icon->type));
    674 		wpabuf_put_str(buf, icon->type);
    675 		wpabuf_put_u8(buf, os_strlen(icon->name));
    676 		wpabuf_put_str(buf, icon->name);
    677 	}
    678 	WPA_PUT_LE16(len2, (u8 *) wpabuf_put(buf, 0) - len2 - 2);
    679 
    680 	/* OSU_NAI */
    681 	if (p->osu_nai) {
    682 		wpabuf_put_u8(buf, os_strlen(p->osu_nai));
    683 		wpabuf_put_str(buf, p->osu_nai);
    684 	} else
    685 		wpabuf_put_u8(buf, 0);
    686 
    687 	/* OSU Service Description Duples */
    688 	len2 = wpabuf_put(buf, 2);
    689 	for (i = 0; i < p->service_desc_count; i++) {
    690 		struct hostapd_lang_string *s = &p->service_desc[i];
    691 		wpabuf_put_u8(buf, 3 + s->name_len);
    692 		wpabuf_put_data(buf, s->lang, 3);
    693 		wpabuf_put_data(buf, s->name, s->name_len);
    694 	}
    695 	WPA_PUT_LE16(len2, (u8 *) wpabuf_put(buf, 0) - len2 - 2);
    696 
    697 	WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
    698 }
    699 
    700 
    701 static void anqp_add_osu_providers_list(struct hostapd_data *hapd,
    702 					struct wpabuf *buf)
    703 {
    704 	if (hapd->conf->hs20_osu_providers_count) {
    705 		size_t i;
    706 		u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
    707 		wpabuf_put_be24(buf, OUI_WFA);
    708 		wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
    709 		wpabuf_put_u8(buf, HS20_STYPE_OSU_PROVIDERS_LIST);
    710 		wpabuf_put_u8(buf, 0); /* Reserved */
    711 
    712 		/* OSU SSID */
    713 		wpabuf_put_u8(buf, hapd->conf->osu_ssid_len);
    714 		wpabuf_put_data(buf, hapd->conf->osu_ssid,
    715 				hapd->conf->osu_ssid_len);
    716 
    717 		/* Number of OSU Providers */
    718 		wpabuf_put_u8(buf, hapd->conf->hs20_osu_providers_count);
    719 
    720 		for (i = 0; i < hapd->conf->hs20_osu_providers_count; i++) {
    721 			anqp_add_osu_provider(
    722 				buf, hapd->conf,
    723 				&hapd->conf->hs20_osu_providers[i]);
    724 		}
    725 
    726 		gas_anqp_set_element_len(buf, len);
    727 	}
    728 }
    729 
    730 
    731 static void anqp_add_icon_binary_file(struct hostapd_data *hapd,
    732 				      struct wpabuf *buf,
    733 				      const u8 *name, size_t name_len)
    734 {
    735 	struct hs20_icon *icon;
    736 	size_t i;
    737 	u8 *len;
    738 
    739 	wpa_hexdump_ascii(MSG_DEBUG, "HS 2.0: Requested Icon Filename",
    740 			  name, name_len);
    741 	for (i = 0; i < hapd->conf->hs20_icons_count; i++) {
    742 		icon = &hapd->conf->hs20_icons[i];
    743 		if (name_len == os_strlen(icon->name) &&
    744 		    os_memcmp(name, icon->name, name_len) == 0)
    745 			break;
    746 	}
    747 
    748 	if (i < hapd->conf->hs20_icons_count)
    749 		icon = &hapd->conf->hs20_icons[i];
    750 	else
    751 		icon = NULL;
    752 
    753 	len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
    754 	wpabuf_put_be24(buf, OUI_WFA);
    755 	wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
    756 	wpabuf_put_u8(buf, HS20_STYPE_ICON_BINARY_FILE);
    757 	wpabuf_put_u8(buf, 0); /* Reserved */
    758 
    759 	if (icon) {
    760 		char *data;
    761 		size_t data_len;
    762 
    763 		data = os_readfile(icon->file, &data_len);
    764 		if (data == NULL || data_len > 65535) {
    765 			wpabuf_put_u8(buf, 2); /* Download Status:
    766 						* Unspecified file error */
    767 			wpabuf_put_u8(buf, 0);
    768 			wpabuf_put_le16(buf, 0);
    769 		} else {
    770 			wpabuf_put_u8(buf, 0); /* Download Status: Success */
    771 			wpabuf_put_u8(buf, os_strlen(icon->type));
    772 			wpabuf_put_str(buf, icon->type);
    773 			wpabuf_put_le16(buf, data_len);
    774 			wpabuf_put_data(buf, data, data_len);
    775 		}
    776 		os_free(data);
    777 	} else {
    778 		wpabuf_put_u8(buf, 1); /* Download Status: File not found */
    779 		wpabuf_put_u8(buf, 0);
    780 		wpabuf_put_le16(buf, 0);
    781 	}
    782 
    783 	gas_anqp_set_element_len(buf, len);
    784 }
    785 
    786 #endif /* CONFIG_HS20 */
    787 
    788 
    789 static size_t anqp_get_required_len(struct hostapd_data *hapd,
    790 				    const u16 *infoid,
    791 				    unsigned int num_infoid)
    792 {
    793 	size_t len = 0;
    794 	unsigned int i;
    795 
    796 	for (i = 0; i < num_infoid; i++) {
    797 		struct anqp_element *elem = get_anqp_elem(hapd, infoid[i]);
    798 
    799 		if (elem)
    800 			len += 2 + 2 + wpabuf_len(elem->payload);
    801 	}
    802 
    803 	return len;
    804 }
    805 
    806 
    807 static struct wpabuf *
    808 gas_serv_build_gas_resp_payload(struct hostapd_data *hapd,
    809 				unsigned int request,
    810 				const u8 *home_realm, size_t home_realm_len,
    811 				const u8 *icon_name, size_t icon_name_len,
    812 				const u16 *extra_req,
    813 				unsigned int num_extra_req)
    814 {
    815 	struct wpabuf *buf;
    816 	size_t len;
    817 	unsigned int i;
    818 
    819 	len = 1400;
    820 	if (request & (ANQP_REQ_NAI_REALM | ANQP_REQ_NAI_HOME_REALM))
    821 		len += 1000;
    822 	if (request & ANQP_REQ_ICON_REQUEST)
    823 		len += 65536;
    824 	len += anqp_get_required_len(hapd, extra_req, num_extra_req);
    825 
    826 	buf = wpabuf_alloc(len);
    827 	if (buf == NULL)
    828 		return NULL;
    829 
    830 	if (request & ANQP_REQ_CAPABILITY_LIST)
    831 		anqp_add_capab_list(hapd, buf);
    832 	if (request & ANQP_REQ_VENUE_NAME)
    833 		anqp_add_venue_name(hapd, buf);
    834 	if (request & ANQP_REQ_EMERGENCY_CALL_NUMBER)
    835 		anqp_add_elem(hapd, buf, ANQP_EMERGENCY_CALL_NUMBER);
    836 	if (request & ANQP_REQ_NETWORK_AUTH_TYPE)
    837 		anqp_add_network_auth_type(hapd, buf);
    838 	if (request & ANQP_REQ_ROAMING_CONSORTIUM)
    839 		anqp_add_roaming_consortium(hapd, buf);
    840 	if (request & ANQP_REQ_IP_ADDR_TYPE_AVAILABILITY)
    841 		anqp_add_ip_addr_type_availability(hapd, buf);
    842 	if (request & (ANQP_REQ_NAI_REALM | ANQP_REQ_NAI_HOME_REALM))
    843 		anqp_add_nai_realm(hapd, buf, home_realm, home_realm_len,
    844 				   request & ANQP_REQ_NAI_REALM,
    845 				   request & ANQP_REQ_NAI_HOME_REALM);
    846 	if (request & ANQP_REQ_3GPP_CELLULAR_NETWORK)
    847 		anqp_add_3gpp_cellular_network(hapd, buf);
    848 	if (request & ANQP_REQ_AP_GEOSPATIAL_LOCATION)
    849 		anqp_add_elem(hapd, buf, ANQP_AP_GEOSPATIAL_LOCATION);
    850 	if (request & ANQP_REQ_AP_CIVIC_LOCATION)
    851 		anqp_add_elem(hapd, buf, ANQP_AP_CIVIC_LOCATION);
    852 	if (request & ANQP_REQ_AP_LOCATION_PUBLIC_URI)
    853 		anqp_add_elem(hapd, buf, ANQP_AP_LOCATION_PUBLIC_URI);
    854 	if (request & ANQP_REQ_DOMAIN_NAME)
    855 		anqp_add_domain_name(hapd, buf);
    856 	if (request & ANQP_REQ_EMERGENCY_ALERT_URI)
    857 		anqp_add_elem(hapd, buf, ANQP_EMERGENCY_ALERT_URI);
    858 	if (request & ANQP_REQ_TDLS_CAPABILITY)
    859 		anqp_add_elem(hapd, buf, ANQP_TDLS_CAPABILITY);
    860 	if (request & ANQP_REQ_EMERGENCY_NAI)
    861 		anqp_add_elem(hapd, buf, ANQP_EMERGENCY_NAI);
    862 
    863 	for (i = 0; i < num_extra_req; i++)
    864 		anqp_add_elem(hapd, buf, extra_req[i]);
    865 
    866 #ifdef CONFIG_HS20
    867 	if (request & ANQP_REQ_HS_CAPABILITY_LIST)
    868 		anqp_add_hs_capab_list(hapd, buf);
    869 	if (request & ANQP_REQ_OPERATOR_FRIENDLY_NAME)
    870 		anqp_add_operator_friendly_name(hapd, buf);
    871 	if (request & ANQP_REQ_WAN_METRICS)
    872 		anqp_add_wan_metrics(hapd, buf);
    873 	if (request & ANQP_REQ_CONNECTION_CAPABILITY)
    874 		anqp_add_connection_capability(hapd, buf);
    875 	if (request & ANQP_REQ_OPERATING_CLASS)
    876 		anqp_add_operating_class(hapd, buf);
    877 	if (request & ANQP_REQ_OSU_PROVIDERS_LIST)
    878 		anqp_add_osu_providers_list(hapd, buf);
    879 	if (request & ANQP_REQ_ICON_REQUEST)
    880 		anqp_add_icon_binary_file(hapd, buf, icon_name, icon_name_len);
    881 #endif /* CONFIG_HS20 */
    882 
    883 	return buf;
    884 }
    885 
    886 
    887 #define ANQP_MAX_EXTRA_REQ 20
    888 
    889 struct anqp_query_info {
    890 	unsigned int request;
    891 	const u8 *home_realm_query;
    892 	size_t home_realm_query_len;
    893 	const u8 *icon_name;
    894 	size_t icon_name_len;
    895 	int p2p_sd;
    896 	u16 extra_req[ANQP_MAX_EXTRA_REQ];
    897 	unsigned int num_extra_req;
    898 };
    899 
    900 
    901 static void set_anqp_req(unsigned int bit, const char *name, int local,
    902 			 struct anqp_query_info *qi)
    903 {
    904 	qi->request |= bit;
    905 	if (local) {
    906 		wpa_printf(MSG_DEBUG, "ANQP: %s (local)", name);
    907 	} else {
    908 		wpa_printf(MSG_DEBUG, "ANQP: %s not available", name);
    909 	}
    910 }
    911 
    912 
    913 static void rx_anqp_query_list_id(struct hostapd_data *hapd, u16 info_id,
    914 				  struct anqp_query_info *qi)
    915 {
    916 	switch (info_id) {
    917 	case ANQP_CAPABILITY_LIST:
    918 		set_anqp_req(ANQP_REQ_CAPABILITY_LIST, "Capability List", 1,
    919 			     qi);
    920 		break;
    921 	case ANQP_VENUE_NAME:
    922 		set_anqp_req(ANQP_REQ_VENUE_NAME, "Venue Name",
    923 			     hapd->conf->venue_name != NULL, qi);
    924 		break;
    925 	case ANQP_EMERGENCY_CALL_NUMBER:
    926 		set_anqp_req(ANQP_REQ_EMERGENCY_CALL_NUMBER,
    927 			     "Emergency Call Number",
    928 			     get_anqp_elem(hapd, info_id) != NULL, qi);
    929 		break;
    930 	case ANQP_NETWORK_AUTH_TYPE:
    931 		set_anqp_req(ANQP_REQ_NETWORK_AUTH_TYPE, "Network Auth Type",
    932 			     hapd->conf->network_auth_type != NULL, qi);
    933 		break;
    934 	case ANQP_ROAMING_CONSORTIUM:
    935 		set_anqp_req(ANQP_REQ_ROAMING_CONSORTIUM, "Roaming Consortium",
    936 			     hapd->conf->roaming_consortium != NULL, qi);
    937 		break;
    938 	case ANQP_IP_ADDR_TYPE_AVAILABILITY:
    939 		set_anqp_req(ANQP_REQ_IP_ADDR_TYPE_AVAILABILITY,
    940 			     "IP Addr Type Availability",
    941 			     hapd->conf->ipaddr_type_configured, qi);
    942 		break;
    943 	case ANQP_NAI_REALM:
    944 		set_anqp_req(ANQP_REQ_NAI_REALM, "NAI Realm",
    945 			     hapd->conf->nai_realm_data != NULL, qi);
    946 		break;
    947 	case ANQP_3GPP_CELLULAR_NETWORK:
    948 		set_anqp_req(ANQP_REQ_3GPP_CELLULAR_NETWORK,
    949 			     "3GPP Cellular Network",
    950 			     hapd->conf->anqp_3gpp_cell_net != NULL, qi);
    951 		break;
    952 	case ANQP_AP_GEOSPATIAL_LOCATION:
    953 		set_anqp_req(ANQP_REQ_AP_GEOSPATIAL_LOCATION,
    954 			     "AP Geospatial Location",
    955 			     get_anqp_elem(hapd, info_id) != NULL, qi);
    956 		break;
    957 	case ANQP_AP_CIVIC_LOCATION:
    958 		set_anqp_req(ANQP_REQ_AP_CIVIC_LOCATION,
    959 			     "AP Civic Location",
    960 			     get_anqp_elem(hapd, info_id) != NULL, qi);
    961 		break;
    962 	case ANQP_AP_LOCATION_PUBLIC_URI:
    963 		set_anqp_req(ANQP_REQ_AP_LOCATION_PUBLIC_URI,
    964 			     "AP Location Public URI",
    965 			     get_anqp_elem(hapd, info_id) != NULL, qi);
    966 		break;
    967 	case ANQP_DOMAIN_NAME:
    968 		set_anqp_req(ANQP_REQ_DOMAIN_NAME, "Domain Name",
    969 			     hapd->conf->domain_name != NULL, qi);
    970 		break;
    971 	case ANQP_EMERGENCY_ALERT_URI:
    972 		set_anqp_req(ANQP_REQ_EMERGENCY_ALERT_URI,
    973 			     "Emergency Alert URI",
    974 			     get_anqp_elem(hapd, info_id) != NULL, qi);
    975 		break;
    976 	case ANQP_TDLS_CAPABILITY:
    977 		set_anqp_req(ANQP_REQ_TDLS_CAPABILITY,
    978 			     "TDLS Capability",
    979 			     get_anqp_elem(hapd, info_id) != NULL, qi);
    980 		break;
    981 	case ANQP_EMERGENCY_NAI:
    982 		set_anqp_req(ANQP_REQ_EMERGENCY_NAI,
    983 			     "Emergency NAI",
    984 			     get_anqp_elem(hapd, info_id) != NULL, qi);
    985 		break;
    986 	default:
    987 		if (!get_anqp_elem(hapd, info_id)) {
    988 			wpa_printf(MSG_DEBUG, "ANQP: Unsupported Info Id %u",
    989 				   info_id);
    990 			break;
    991 		}
    992 		if (qi->num_extra_req == ANQP_MAX_EXTRA_REQ) {
    993 			wpa_printf(MSG_DEBUG,
    994 				   "ANQP: No more room for extra requests - ignore Info Id %u",
    995 				   info_id);
    996 			break;
    997 		}
    998 		wpa_printf(MSG_DEBUG, "ANQP: Info Id %u (local)", info_id);
    999 		qi->extra_req[qi->num_extra_req] = info_id;
   1000 		qi->num_extra_req++;
   1001 		break;
   1002 	}
   1003 }
   1004 
   1005 
   1006 static void rx_anqp_query_list(struct hostapd_data *hapd,
   1007 			       const u8 *pos, const u8 *end,
   1008 			       struct anqp_query_info *qi)
   1009 {
   1010 	wpa_printf(MSG_DEBUG, "ANQP: %u Info IDs requested in Query list",
   1011 		   (unsigned int) (end - pos) / 2);
   1012 
   1013 	while (end - pos >= 2) {
   1014 		rx_anqp_query_list_id(hapd, WPA_GET_LE16(pos), qi);
   1015 		pos += 2;
   1016 	}
   1017 }
   1018 
   1019 
   1020 #ifdef CONFIG_HS20
   1021 
   1022 static void rx_anqp_hs_query_list(struct hostapd_data *hapd, u8 subtype,
   1023 				  struct anqp_query_info *qi)
   1024 {
   1025 	switch (subtype) {
   1026 	case HS20_STYPE_CAPABILITY_LIST:
   1027 		set_anqp_req(ANQP_REQ_HS_CAPABILITY_LIST, "HS Capability List",
   1028 			     1, qi);
   1029 		break;
   1030 	case HS20_STYPE_OPERATOR_FRIENDLY_NAME:
   1031 		set_anqp_req(ANQP_REQ_OPERATOR_FRIENDLY_NAME,
   1032 			     "Operator Friendly Name",
   1033 			     hapd->conf->hs20_oper_friendly_name != NULL, qi);
   1034 		break;
   1035 	case HS20_STYPE_WAN_METRICS:
   1036 		set_anqp_req(ANQP_REQ_WAN_METRICS, "WAN Metrics",
   1037 			     hapd->conf->hs20_wan_metrics != NULL, qi);
   1038 		break;
   1039 	case HS20_STYPE_CONNECTION_CAPABILITY:
   1040 		set_anqp_req(ANQP_REQ_CONNECTION_CAPABILITY,
   1041 			     "Connection Capability",
   1042 			     hapd->conf->hs20_connection_capability != NULL,
   1043 			     qi);
   1044 		break;
   1045 	case HS20_STYPE_OPERATING_CLASS:
   1046 		set_anqp_req(ANQP_REQ_OPERATING_CLASS, "Operating Class",
   1047 			     hapd->conf->hs20_operating_class != NULL, qi);
   1048 		break;
   1049 	case HS20_STYPE_OSU_PROVIDERS_LIST:
   1050 		set_anqp_req(ANQP_REQ_OSU_PROVIDERS_LIST, "OSU Providers list",
   1051 			     hapd->conf->hs20_osu_providers_count, qi);
   1052 		break;
   1053 	default:
   1054 		wpa_printf(MSG_DEBUG, "ANQP: Unsupported HS 2.0 subtype %u",
   1055 			   subtype);
   1056 		break;
   1057 	}
   1058 }
   1059 
   1060 
   1061 static void rx_anqp_hs_nai_home_realm(struct hostapd_data *hapd,
   1062 				      const u8 *pos, const u8 *end,
   1063 				      struct anqp_query_info *qi)
   1064 {
   1065 	qi->request |= ANQP_REQ_NAI_HOME_REALM;
   1066 	qi->home_realm_query = pos;
   1067 	qi->home_realm_query_len = end - pos;
   1068 	if (hapd->conf->nai_realm_data != NULL) {
   1069 		wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 NAI Home Realm Query "
   1070 			   "(local)");
   1071 	} else {
   1072 		wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 NAI Home Realm Query not "
   1073 			   "available");
   1074 	}
   1075 }
   1076 
   1077 
   1078 static void rx_anqp_hs_icon_request(struct hostapd_data *hapd,
   1079 				    const u8 *pos, const u8 *end,
   1080 				    struct anqp_query_info *qi)
   1081 {
   1082 	qi->request |= ANQP_REQ_ICON_REQUEST;
   1083 	qi->icon_name = pos;
   1084 	qi->icon_name_len = end - pos;
   1085 	if (hapd->conf->hs20_icons_count) {
   1086 		wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 Icon Request Query "
   1087 			   "(local)");
   1088 	} else {
   1089 		wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 Icon Request Query not "
   1090 			   "available");
   1091 	}
   1092 }
   1093 
   1094 
   1095 static void rx_anqp_vendor_specific(struct hostapd_data *hapd,
   1096 				    const u8 *pos, const u8 *end,
   1097 				    struct anqp_query_info *qi)
   1098 {
   1099 	u32 oui;
   1100 	u8 subtype;
   1101 
   1102 	if (end - pos < 4) {
   1103 		wpa_printf(MSG_DEBUG, "ANQP: Too short vendor specific ANQP "
   1104 			   "Query element");
   1105 		return;
   1106 	}
   1107 
   1108 	oui = WPA_GET_BE24(pos);
   1109 	pos += 3;
   1110 	if (oui != OUI_WFA) {
   1111 		wpa_printf(MSG_DEBUG, "ANQP: Unsupported vendor OUI %06x",
   1112 			   oui);
   1113 		return;
   1114 	}
   1115 
   1116 #ifdef CONFIG_P2P
   1117 	if (*pos == P2P_OUI_TYPE) {
   1118 		/*
   1119 		 * This is for P2P SD and will be taken care of by the P2P
   1120 		 * implementation. This query needs to be ignored in the generic
   1121 		 * GAS server to avoid duplicated response.
   1122 		 */
   1123 		wpa_printf(MSG_DEBUG,
   1124 			   "ANQP: Ignore WFA vendor type %u (P2P SD) in generic GAS server",
   1125 			   *pos);
   1126 		qi->p2p_sd = 1;
   1127 		return;
   1128 	}
   1129 #endif /* CONFIG_P2P */
   1130 
   1131 	if (*pos != HS20_ANQP_OUI_TYPE) {
   1132 		wpa_printf(MSG_DEBUG, "ANQP: Unsupported WFA vendor type %u",
   1133 			   *pos);
   1134 		return;
   1135 	}
   1136 	pos++;
   1137 
   1138 	if (end - pos <= 1)
   1139 		return;
   1140 
   1141 	subtype = *pos++;
   1142 	pos++; /* Reserved */
   1143 	switch (subtype) {
   1144 	case HS20_STYPE_QUERY_LIST:
   1145 		wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 Query List");
   1146 		while (pos < end) {
   1147 			rx_anqp_hs_query_list(hapd, *pos, qi);
   1148 			pos++;
   1149 		}
   1150 		break;
   1151 	case HS20_STYPE_NAI_HOME_REALM_QUERY:
   1152 		rx_anqp_hs_nai_home_realm(hapd, pos, end, qi);
   1153 		break;
   1154 	case HS20_STYPE_ICON_REQUEST:
   1155 		rx_anqp_hs_icon_request(hapd, pos, end, qi);
   1156 		break;
   1157 	default:
   1158 		wpa_printf(MSG_DEBUG, "ANQP: Unsupported HS 2.0 query subtype "
   1159 			   "%u", subtype);
   1160 		break;
   1161 	}
   1162 }
   1163 
   1164 #endif /* CONFIG_HS20 */
   1165 
   1166 
   1167 static void gas_serv_req_local_processing(struct hostapd_data *hapd,
   1168 					  const u8 *sa, u8 dialog_token,
   1169 					  struct anqp_query_info *qi, int prot)
   1170 {
   1171 	struct wpabuf *buf, *tx_buf;
   1172 
   1173 	buf = gas_serv_build_gas_resp_payload(hapd, qi->request,
   1174 					      qi->home_realm_query,
   1175 					      qi->home_realm_query_len,
   1176 					      qi->icon_name, qi->icon_name_len,
   1177 					      qi->extra_req, qi->num_extra_req);
   1178 	wpa_hexdump_buf(MSG_MSGDUMP, "ANQP: Locally generated ANQP responses",
   1179 			buf);
   1180 	if (!buf)
   1181 		return;
   1182 #ifdef CONFIG_P2P
   1183 	if (wpabuf_len(buf) == 0 && qi->p2p_sd) {
   1184 		wpa_printf(MSG_DEBUG,
   1185 			   "ANQP: Do not send response to P2P SD from generic GAS service (P2P SD implementation will process this)");
   1186 		wpabuf_free(buf);
   1187 		return;
   1188 	}
   1189 #endif /* CONFIG_P2P */
   1190 
   1191 	if (wpabuf_len(buf) > hapd->gas_frag_limit ||
   1192 	    hapd->conf->gas_comeback_delay) {
   1193 		struct gas_dialog_info *di;
   1194 		u16 comeback_delay = 1;
   1195 
   1196 		if (hapd->conf->gas_comeback_delay) {
   1197 			/* Testing - allow overriding of the delay value */
   1198 			comeback_delay = hapd->conf->gas_comeback_delay;
   1199 		}
   1200 
   1201 		wpa_printf(MSG_DEBUG, "ANQP: Too long response to fit in "
   1202 			   "initial response - use GAS comeback");
   1203 		di = gas_dialog_create(hapd, sa, dialog_token);
   1204 		if (!di) {
   1205 			wpa_printf(MSG_INFO, "ANQP: Could not create dialog "
   1206 				   "for " MACSTR " (dialog token %u)",
   1207 				   MAC2STR(sa), dialog_token);
   1208 			wpabuf_free(buf);
   1209 			tx_buf = gas_anqp_build_initial_resp_buf(
   1210 				dialog_token, WLAN_STATUS_UNSPECIFIED_FAILURE,
   1211 				0, NULL);
   1212 		} else {
   1213 			di->prot = prot;
   1214 			di->sd_resp = buf;
   1215 			di->sd_resp_pos = 0;
   1216 			tx_buf = gas_anqp_build_initial_resp_buf(
   1217 				dialog_token, WLAN_STATUS_SUCCESS,
   1218 				comeback_delay, NULL);
   1219 		}
   1220 	} else {
   1221 		wpa_printf(MSG_DEBUG, "ANQP: Initial response (no comeback)");
   1222 		tx_buf = gas_anqp_build_initial_resp_buf(
   1223 			dialog_token, WLAN_STATUS_SUCCESS, 0, buf);
   1224 		wpabuf_free(buf);
   1225 	}
   1226 	if (!tx_buf)
   1227 		return;
   1228 	if (prot)
   1229 		convert_to_protected_dual(tx_buf);
   1230 	hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
   1231 				wpabuf_head(tx_buf), wpabuf_len(tx_buf));
   1232 	wpabuf_free(tx_buf);
   1233 }
   1234 
   1235 
   1236 static void gas_serv_rx_gas_initial_req(struct hostapd_data *hapd,
   1237 					const u8 *sa,
   1238 					const u8 *data, size_t len, int prot)
   1239 {
   1240 	const u8 *pos = data;
   1241 	const u8 *end = data + len;
   1242 	const u8 *next;
   1243 	u8 dialog_token;
   1244 	u16 slen;
   1245 	struct anqp_query_info qi;
   1246 	const u8 *adv_proto;
   1247 
   1248 	if (len < 1 + 2)
   1249 		return;
   1250 
   1251 	os_memset(&qi, 0, sizeof(qi));
   1252 
   1253 	dialog_token = *pos++;
   1254 	wpa_msg(hapd->msg_ctx, MSG_DEBUG,
   1255 		"GAS: GAS Initial Request from " MACSTR " (dialog token %u) ",
   1256 		MAC2STR(sa), dialog_token);
   1257 
   1258 	if (*pos != WLAN_EID_ADV_PROTO) {
   1259 		wpa_msg(hapd->msg_ctx, MSG_DEBUG,
   1260 			"GAS: Unexpected IE in GAS Initial Request: %u", *pos);
   1261 		return;
   1262 	}
   1263 	adv_proto = pos++;
   1264 
   1265 	slen = *pos++;
   1266 	if (slen > end - pos || slen < 2) {
   1267 		wpa_msg(hapd->msg_ctx, MSG_DEBUG,
   1268 			"GAS: Invalid IE in GAS Initial Request");
   1269 		return;
   1270 	}
   1271 	next = pos + slen;
   1272 	pos++; /* skip QueryRespLenLimit and PAME-BI */
   1273 
   1274 	if (*pos != ACCESS_NETWORK_QUERY_PROTOCOL) {
   1275 		struct wpabuf *buf;
   1276 		wpa_msg(hapd->msg_ctx, MSG_DEBUG,
   1277 			"GAS: Unsupported GAS advertisement protocol id %u",
   1278 			*pos);
   1279 		if (sa[0] & 0x01)
   1280 			return; /* Invalid source address - drop silently */
   1281 		buf = gas_build_initial_resp(
   1282 			dialog_token, WLAN_STATUS_GAS_ADV_PROTO_NOT_SUPPORTED,
   1283 			0, 2 + slen + 2);
   1284 		if (buf == NULL)
   1285 			return;
   1286 		wpabuf_put_data(buf, adv_proto, 2 + slen);
   1287 		wpabuf_put_le16(buf, 0); /* Query Response Length */
   1288 		if (prot)
   1289 			convert_to_protected_dual(buf);
   1290 		hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
   1291 					wpabuf_head(buf), wpabuf_len(buf));
   1292 		wpabuf_free(buf);
   1293 		return;
   1294 	}
   1295 
   1296 	pos = next;
   1297 	/* Query Request */
   1298 	if (end - pos < 2)
   1299 		return;
   1300 	slen = WPA_GET_LE16(pos);
   1301 	pos += 2;
   1302 	if (slen > end - pos)
   1303 		return;
   1304 	end = pos + slen;
   1305 
   1306 	/* ANQP Query Request */
   1307 	while (pos < end) {
   1308 		u16 info_id, elen;
   1309 
   1310 		if (end - pos < 4)
   1311 			return;
   1312 
   1313 		info_id = WPA_GET_LE16(pos);
   1314 		pos += 2;
   1315 		elen = WPA_GET_LE16(pos);
   1316 		pos += 2;
   1317 
   1318 		if (elen > end - pos) {
   1319 			wpa_printf(MSG_DEBUG, "ANQP: Invalid Query Request");
   1320 			return;
   1321 		}
   1322 
   1323 		switch (info_id) {
   1324 		case ANQP_QUERY_LIST:
   1325 			rx_anqp_query_list(hapd, pos, pos + elen, &qi);
   1326 			break;
   1327 #ifdef CONFIG_HS20
   1328 		case ANQP_VENDOR_SPECIFIC:
   1329 			rx_anqp_vendor_specific(hapd, pos, pos + elen, &qi);
   1330 			break;
   1331 #endif /* CONFIG_HS20 */
   1332 		default:
   1333 			wpa_printf(MSG_DEBUG, "ANQP: Unsupported Query "
   1334 				   "Request element %u", info_id);
   1335 			break;
   1336 		}
   1337 
   1338 		pos += elen;
   1339 	}
   1340 
   1341 	gas_serv_req_local_processing(hapd, sa, dialog_token, &qi, prot);
   1342 }
   1343 
   1344 
   1345 static void gas_serv_rx_gas_comeback_req(struct hostapd_data *hapd,
   1346 					 const u8 *sa,
   1347 					 const u8 *data, size_t len, int prot)
   1348 {
   1349 	struct gas_dialog_info *dialog;
   1350 	struct wpabuf *buf, *tx_buf;
   1351 	u8 dialog_token;
   1352 	size_t frag_len;
   1353 	int more = 0;
   1354 
   1355 	wpa_hexdump(MSG_DEBUG, "GAS: RX GAS Comeback Request", data, len);
   1356 	if (len < 1)
   1357 		return;
   1358 	dialog_token = *data;
   1359 	wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Dialog Token: %u",
   1360 		dialog_token);
   1361 
   1362 	dialog = gas_serv_dialog_find(hapd, sa, dialog_token);
   1363 	if (!dialog) {
   1364 		wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: No pending SD "
   1365 			"response fragment for " MACSTR " dialog token %u",
   1366 			MAC2STR(sa), dialog_token);
   1367 
   1368 		if (sa[0] & 0x01)
   1369 			return; /* Invalid source address - drop silently */
   1370 		tx_buf = gas_anqp_build_comeback_resp_buf(
   1371 			dialog_token, WLAN_STATUS_NO_OUTSTANDING_GAS_REQ, 0, 0,
   1372 			0, NULL);
   1373 		if (tx_buf == NULL)
   1374 			return;
   1375 		goto send_resp;
   1376 	}
   1377 
   1378 	frag_len = wpabuf_len(dialog->sd_resp) - dialog->sd_resp_pos;
   1379 	if (frag_len > hapd->gas_frag_limit) {
   1380 		frag_len = hapd->gas_frag_limit;
   1381 		more = 1;
   1382 	}
   1383 	wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: resp frag_len %u",
   1384 		(unsigned int) frag_len);
   1385 	buf = wpabuf_alloc_copy(wpabuf_head_u8(dialog->sd_resp) +
   1386 				dialog->sd_resp_pos, frag_len);
   1387 	if (buf == NULL) {
   1388 		wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Failed to allocate "
   1389 			"buffer");
   1390 		gas_serv_dialog_clear(dialog);
   1391 		return;
   1392 	}
   1393 	tx_buf = gas_anqp_build_comeback_resp_buf(dialog_token,
   1394 						  WLAN_STATUS_SUCCESS,
   1395 						  dialog->sd_frag_id,
   1396 						  more, 0, buf);
   1397 	wpabuf_free(buf);
   1398 	if (tx_buf == NULL) {
   1399 		gas_serv_dialog_clear(dialog);
   1400 		return;
   1401 	}
   1402 	wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Tx GAS Comeback Response "
   1403 		"(frag_id %d more=%d frag_len=%d)",
   1404 		dialog->sd_frag_id, more, (int) frag_len);
   1405 	dialog->sd_frag_id++;
   1406 	dialog->sd_resp_pos += frag_len;
   1407 
   1408 	if (more) {
   1409 		wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: %d more bytes remain "
   1410 			"to be sent",
   1411 			(int) (wpabuf_len(dialog->sd_resp) -
   1412 			       dialog->sd_resp_pos));
   1413 	} else {
   1414 		wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: All fragments of "
   1415 			"SD response sent");
   1416 		gas_serv_dialog_clear(dialog);
   1417 		gas_serv_free_dialogs(hapd, sa);
   1418 	}
   1419 
   1420 send_resp:
   1421 	if (prot)
   1422 		convert_to_protected_dual(tx_buf);
   1423 	hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
   1424 				wpabuf_head(tx_buf), wpabuf_len(tx_buf));
   1425 	wpabuf_free(tx_buf);
   1426 }
   1427 
   1428 
   1429 static void gas_serv_rx_public_action(void *ctx, const u8 *buf, size_t len,
   1430 				      int freq)
   1431 {
   1432 	struct hostapd_data *hapd = ctx;
   1433 	const struct ieee80211_mgmt *mgmt;
   1434 	const u8 *sa, *data;
   1435 	int prot;
   1436 
   1437 	mgmt = (const struct ieee80211_mgmt *) buf;
   1438 	if (len < IEEE80211_HDRLEN + 2)
   1439 		return;
   1440 	if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
   1441 	    mgmt->u.action.category != WLAN_ACTION_PROTECTED_DUAL)
   1442 		return;
   1443 	/*
   1444 	 * Note: Public Action and Protected Dual of Public Action frames share
   1445 	 * the same payload structure, so it is fine to use definitions of
   1446 	 * Public Action frames to process both.
   1447 	 */
   1448 	prot = mgmt->u.action.category == WLAN_ACTION_PROTECTED_DUAL;
   1449 	sa = mgmt->sa;
   1450 	len -= IEEE80211_HDRLEN + 1;
   1451 	data = buf + IEEE80211_HDRLEN + 1;
   1452 	switch (data[0]) {
   1453 	case WLAN_PA_GAS_INITIAL_REQ:
   1454 		gas_serv_rx_gas_initial_req(hapd, sa, data + 1, len - 1, prot);
   1455 		break;
   1456 	case WLAN_PA_GAS_COMEBACK_REQ:
   1457 		gas_serv_rx_gas_comeback_req(hapd, sa, data + 1, len - 1, prot);
   1458 		break;
   1459 	}
   1460 }
   1461 
   1462 
   1463 int gas_serv_init(struct hostapd_data *hapd)
   1464 {
   1465 	hapd->public_action_cb2 = gas_serv_rx_public_action;
   1466 	hapd->public_action_cb2_ctx = hapd;
   1467 	hapd->gas_frag_limit = 1400;
   1468 	if (hapd->conf->gas_frag_limit > 0)
   1469 		hapd->gas_frag_limit = hapd->conf->gas_frag_limit;
   1470 	return 0;
   1471 }
   1472 
   1473 
   1474 void gas_serv_deinit(struct hostapd_data *hapd)
   1475 {
   1476 }
   1477