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