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