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 22static 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 29static struct gas_dialog_info * 30gas_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 87struct gas_dialog_info * 88gas_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 113void 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 120static 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 141static 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 171static 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 186static 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 206static 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 218static 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 279static 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 302static 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 317static 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 337static 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 351static 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 372static 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 389static 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 483static 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 521static 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 537static 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 553static 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 577static 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 592static 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 608static 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 624static 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 701static 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 731static 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 789static 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 807static struct wpabuf * 808gas_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 889struct 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 901static 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 913static 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 1006static 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 1022static 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 1061static 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 1078static 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 1095static 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 1167static 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 1236static 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 1345static 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 1420send_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 1429static 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 1463int 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 1474void gas_serv_deinit(struct hostapd_data *hapd) 1475{ 1476} 1477