1 /* 2 * Generic advertisement service (GAS) server 3 * Copyright (c) 2011-2014, Qualcomm Atheros, Inc. 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 11 #include "common.h" 12 #include "common/ieee802_11_defs.h" 13 #include "common/gas.h" 14 #include "utils/eloop.h" 15 #include "hostapd.h" 16 #include "ap_config.h" 17 #include "ap_drv_ops.h" 18 #include "sta_info.h" 19 #include "gas_serv.h" 20 21 22 static void convert_to_protected_dual(struct wpabuf *msg) 23 { 24 u8 *categ = wpabuf_mhead_u8(msg); 25 *categ = WLAN_ACTION_PROTECTED_DUAL; 26 } 27 28 29 static struct gas_dialog_info * 30 gas_dialog_create(struct hostapd_data *hapd, const u8 *addr, u8 dialog_token) 31 { 32 struct sta_info *sta; 33 struct gas_dialog_info *dia = NULL; 34 int i, j; 35 36 sta = ap_get_sta(hapd, addr); 37 if (!sta) { 38 /* 39 * We need a STA entry to be able to maintain state for 40 * the GAS query. 41 */ 42 wpa_printf(MSG_DEBUG, "ANQP: Add a temporary STA entry for " 43 "GAS query"); 44 sta = ap_sta_add(hapd, addr); 45 if (!sta) { 46 wpa_printf(MSG_DEBUG, "Failed to add STA " MACSTR 47 " for GAS query", MAC2STR(addr)); 48 return NULL; 49 } 50 sta->flags |= WLAN_STA_GAS; 51 /* 52 * The default inactivity is 300 seconds. We don't need 53 * it to be that long. 54 */ 55 ap_sta_session_timeout(hapd, sta, 5); 56 } else { 57 ap_sta_replenish_timeout(hapd, sta, 5); 58 } 59 60 if (sta->gas_dialog == NULL) { 61 sta->gas_dialog = os_zalloc(GAS_DIALOG_MAX * 62 sizeof(struct gas_dialog_info)); 63 if (sta->gas_dialog == NULL) 64 return NULL; 65 } 66 67 for (i = sta->gas_dialog_next, j = 0; j < GAS_DIALOG_MAX; i++, j++) { 68 if (i == GAS_DIALOG_MAX) 69 i = 0; 70 if (sta->gas_dialog[i].valid) 71 continue; 72 dia = &sta->gas_dialog[i]; 73 dia->valid = 1; 74 dia->index = i; 75 dia->dialog_token = dialog_token; 76 sta->gas_dialog_next = (++i == GAS_DIALOG_MAX) ? 0 : i; 77 return dia; 78 } 79 80 wpa_msg(hapd->msg_ctx, MSG_ERROR, "ANQP: Could not create dialog for " 81 MACSTR " dialog_token %u. Consider increasing " 82 "GAS_DIALOG_MAX.", MAC2STR(addr), dialog_token); 83 84 return NULL; 85 } 86 87 88 struct gas_dialog_info * 89 gas_serv_dialog_find(struct hostapd_data *hapd, const u8 *addr, 90 u8 dialog_token) 91 { 92 struct sta_info *sta; 93 int i; 94 95 sta = ap_get_sta(hapd, addr); 96 if (!sta) { 97 wpa_printf(MSG_DEBUG, "ANQP: could not find STA " MACSTR, 98 MAC2STR(addr)); 99 return NULL; 100 } 101 for (i = 0; sta->gas_dialog && i < GAS_DIALOG_MAX; i++) { 102 if (sta->gas_dialog[i].dialog_token != dialog_token || 103 !sta->gas_dialog[i].valid) 104 continue; 105 return &sta->gas_dialog[i]; 106 } 107 wpa_printf(MSG_DEBUG, "ANQP: Could not find dialog for " 108 MACSTR " dialog_token %u", MAC2STR(addr), dialog_token); 109 return NULL; 110 } 111 112 113 void gas_serv_dialog_clear(struct gas_dialog_info *dia) 114 { 115 wpabuf_free(dia->sd_resp); 116 os_memset(dia, 0, sizeof(*dia)); 117 } 118 119 120 static void gas_serv_free_dialogs(struct hostapd_data *hapd, 121 const u8 *sta_addr) 122 { 123 struct sta_info *sta; 124 int i; 125 126 sta = ap_get_sta(hapd, sta_addr); 127 if (sta == NULL || sta->gas_dialog == NULL) 128 return; 129 130 for (i = 0; i < GAS_DIALOG_MAX; i++) { 131 if (sta->gas_dialog[i].valid) 132 return; 133 } 134 135 os_free(sta->gas_dialog); 136 sta->gas_dialog = NULL; 137 } 138 139 140 #ifdef CONFIG_HS20 141 static void anqp_add_hs_capab_list(struct hostapd_data *hapd, 142 struct wpabuf *buf) 143 { 144 u8 *len; 145 146 len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC); 147 wpabuf_put_be24(buf, OUI_WFA); 148 wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE); 149 wpabuf_put_u8(buf, HS20_STYPE_CAPABILITY_LIST); 150 wpabuf_put_u8(buf, 0); /* Reserved */ 151 wpabuf_put_u8(buf, HS20_STYPE_CAPABILITY_LIST); 152 if (hapd->conf->hs20_oper_friendly_name) 153 wpabuf_put_u8(buf, HS20_STYPE_OPERATOR_FRIENDLY_NAME); 154 if (hapd->conf->hs20_wan_metrics) 155 wpabuf_put_u8(buf, HS20_STYPE_WAN_METRICS); 156 if (hapd->conf->hs20_connection_capability) 157 wpabuf_put_u8(buf, HS20_STYPE_CONNECTION_CAPABILITY); 158 if (hapd->conf->nai_realm_data) 159 wpabuf_put_u8(buf, HS20_STYPE_NAI_HOME_REALM_QUERY); 160 if (hapd->conf->hs20_operating_class) 161 wpabuf_put_u8(buf, HS20_STYPE_OPERATING_CLASS); 162 gas_anqp_set_element_len(buf, len); 163 } 164 #endif /* CONFIG_HS20 */ 165 166 167 static void anqp_add_capab_list(struct hostapd_data *hapd, 168 struct wpabuf *buf) 169 { 170 u8 *len; 171 172 len = gas_anqp_add_element(buf, ANQP_CAPABILITY_LIST); 173 wpabuf_put_le16(buf, ANQP_CAPABILITY_LIST); 174 if (hapd->conf->venue_name) 175 wpabuf_put_le16(buf, ANQP_VENUE_NAME); 176 if (hapd->conf->network_auth_type) 177 wpabuf_put_le16(buf, ANQP_NETWORK_AUTH_TYPE); 178 if (hapd->conf->roaming_consortium) 179 wpabuf_put_le16(buf, ANQP_ROAMING_CONSORTIUM); 180 if (hapd->conf->ipaddr_type_configured) 181 wpabuf_put_le16(buf, ANQP_IP_ADDR_TYPE_AVAILABILITY); 182 if (hapd->conf->nai_realm_data) 183 wpabuf_put_le16(buf, ANQP_NAI_REALM); 184 if (hapd->conf->anqp_3gpp_cell_net) 185 wpabuf_put_le16(buf, ANQP_3GPP_CELLULAR_NETWORK); 186 if (hapd->conf->domain_name) 187 wpabuf_put_le16(buf, ANQP_DOMAIN_NAME); 188 #ifdef CONFIG_HS20 189 anqp_add_hs_capab_list(hapd, buf); 190 #endif /* CONFIG_HS20 */ 191 gas_anqp_set_element_len(buf, len); 192 } 193 194 195 static void anqp_add_venue_name(struct hostapd_data *hapd, struct wpabuf *buf) 196 { 197 if (hapd->conf->venue_name) { 198 u8 *len; 199 unsigned int i; 200 len = gas_anqp_add_element(buf, ANQP_VENUE_NAME); 201 wpabuf_put_u8(buf, hapd->conf->venue_group); 202 wpabuf_put_u8(buf, hapd->conf->venue_type); 203 for (i = 0; i < hapd->conf->venue_name_count; i++) { 204 struct hostapd_lang_string *vn; 205 vn = &hapd->conf->venue_name[i]; 206 wpabuf_put_u8(buf, 3 + vn->name_len); 207 wpabuf_put_data(buf, vn->lang, 3); 208 wpabuf_put_data(buf, vn->name, vn->name_len); 209 } 210 gas_anqp_set_element_len(buf, len); 211 } 212 } 213 214 215 static void anqp_add_network_auth_type(struct hostapd_data *hapd, 216 struct wpabuf *buf) 217 { 218 if (hapd->conf->network_auth_type) { 219 wpabuf_put_le16(buf, ANQP_NETWORK_AUTH_TYPE); 220 wpabuf_put_le16(buf, hapd->conf->network_auth_type_len); 221 wpabuf_put_data(buf, hapd->conf->network_auth_type, 222 hapd->conf->network_auth_type_len); 223 } 224 } 225 226 227 static void anqp_add_roaming_consortium(struct hostapd_data *hapd, 228 struct wpabuf *buf) 229 { 230 unsigned int i; 231 u8 *len; 232 233 len = gas_anqp_add_element(buf, ANQP_ROAMING_CONSORTIUM); 234 for (i = 0; i < hapd->conf->roaming_consortium_count; i++) { 235 struct hostapd_roaming_consortium *rc; 236 rc = &hapd->conf->roaming_consortium[i]; 237 wpabuf_put_u8(buf, rc->len); 238 wpabuf_put_data(buf, rc->oi, rc->len); 239 } 240 gas_anqp_set_element_len(buf, len); 241 } 242 243 244 static void anqp_add_ip_addr_type_availability(struct hostapd_data *hapd, 245 struct wpabuf *buf) 246 { 247 if (hapd->conf->ipaddr_type_configured) { 248 wpabuf_put_le16(buf, ANQP_IP_ADDR_TYPE_AVAILABILITY); 249 wpabuf_put_le16(buf, 1); 250 wpabuf_put_u8(buf, hapd->conf->ipaddr_type_availability); 251 } 252 } 253 254 255 static void anqp_add_nai_realm_eap(struct wpabuf *buf, 256 struct hostapd_nai_realm_data *realm) 257 { 258 unsigned int i, j; 259 260 wpabuf_put_u8(buf, realm->eap_method_count); 261 262 for (i = 0; i < realm->eap_method_count; i++) { 263 struct hostapd_nai_realm_eap *eap = &realm->eap_method[i]; 264 wpabuf_put_u8(buf, 2 + (3 * eap->num_auths)); 265 wpabuf_put_u8(buf, eap->eap_method); 266 wpabuf_put_u8(buf, eap->num_auths); 267 for (j = 0; j < eap->num_auths; j++) { 268 wpabuf_put_u8(buf, eap->auth_id[j]); 269 wpabuf_put_u8(buf, 1); 270 wpabuf_put_u8(buf, eap->auth_val[j]); 271 } 272 } 273 } 274 275 276 static void anqp_add_nai_realm_data(struct wpabuf *buf, 277 struct hostapd_nai_realm_data *realm, 278 unsigned int realm_idx) 279 { 280 u8 *realm_data_len; 281 282 wpa_printf(MSG_DEBUG, "realm=%s, len=%d", realm->realm[realm_idx], 283 (int) os_strlen(realm->realm[realm_idx])); 284 realm_data_len = wpabuf_put(buf, 2); 285 wpabuf_put_u8(buf, realm->encoding); 286 wpabuf_put_u8(buf, os_strlen(realm->realm[realm_idx])); 287 wpabuf_put_str(buf, realm->realm[realm_idx]); 288 anqp_add_nai_realm_eap(buf, realm); 289 gas_anqp_set_element_len(buf, realm_data_len); 290 } 291 292 293 static int hs20_add_nai_home_realm_matches(struct hostapd_data *hapd, 294 struct wpabuf *buf, 295 const u8 *home_realm, 296 size_t home_realm_len) 297 { 298 unsigned int i, j, k; 299 u8 num_realms, num_matching = 0, encoding, realm_len, *realm_list_len; 300 struct hostapd_nai_realm_data *realm; 301 const u8 *pos, *realm_name, *end; 302 struct { 303 unsigned int realm_data_idx; 304 unsigned int realm_idx; 305 } matches[10]; 306 307 pos = home_realm; 308 end = pos + home_realm_len; 309 if (pos + 1 > end) { 310 wpa_hexdump(MSG_DEBUG, "Too short NAI Home Realm Query", 311 home_realm, home_realm_len); 312 return -1; 313 } 314 num_realms = *pos++; 315 316 for (i = 0; i < num_realms && num_matching < 10; i++) { 317 if (pos + 2 > end) { 318 wpa_hexdump(MSG_DEBUG, 319 "Truncated NAI Home Realm Query", 320 home_realm, home_realm_len); 321 return -1; 322 } 323 encoding = *pos++; 324 realm_len = *pos++; 325 if (pos + realm_len > end) { 326 wpa_hexdump(MSG_DEBUG, 327 "Truncated NAI Home Realm Query", 328 home_realm, home_realm_len); 329 return -1; 330 } 331 realm_name = pos; 332 for (j = 0; j < hapd->conf->nai_realm_count && 333 num_matching < 10; j++) { 334 const u8 *rpos, *rend; 335 realm = &hapd->conf->nai_realm_data[j]; 336 if (encoding != realm->encoding) 337 continue; 338 339 rpos = realm_name; 340 while (rpos < realm_name + realm_len && 341 num_matching < 10) { 342 for (rend = rpos; 343 rend < realm_name + realm_len; rend++) { 344 if (*rend == ';') 345 break; 346 } 347 for (k = 0; k < MAX_NAI_REALMS && 348 realm->realm[k] && 349 num_matching < 10; k++) { 350 if ((int) os_strlen(realm->realm[k]) != 351 rend - rpos || 352 os_strncmp((char *) rpos, 353 realm->realm[k], 354 rend - rpos) != 0) 355 continue; 356 matches[num_matching].realm_data_idx = 357 j; 358 matches[num_matching].realm_idx = k; 359 num_matching++; 360 } 361 rpos = rend + 1; 362 } 363 } 364 pos += realm_len; 365 } 366 367 realm_list_len = gas_anqp_add_element(buf, ANQP_NAI_REALM); 368 wpabuf_put_le16(buf, num_matching); 369 370 /* 371 * There are two ways to format. 1. each realm in a NAI Realm Data unit 372 * 2. all realms that share the same EAP methods in a NAI Realm Data 373 * unit. The first format is likely to be bigger in size than the 374 * second, but may be easier to parse and process by the receiver. 375 */ 376 for (i = 0; i < num_matching; i++) { 377 wpa_printf(MSG_DEBUG, "realm_idx %d, realm_data_idx %d", 378 matches[i].realm_data_idx, matches[i].realm_idx); 379 realm = &hapd->conf->nai_realm_data[matches[i].realm_data_idx]; 380 anqp_add_nai_realm_data(buf, realm, matches[i].realm_idx); 381 } 382 gas_anqp_set_element_len(buf, realm_list_len); 383 return 0; 384 } 385 386 387 static void anqp_add_nai_realm(struct hostapd_data *hapd, struct wpabuf *buf, 388 const u8 *home_realm, size_t home_realm_len, 389 int nai_realm, int nai_home_realm) 390 { 391 if (nai_realm && hapd->conf->nai_realm_data) { 392 u8 *len; 393 unsigned int i, j; 394 len = gas_anqp_add_element(buf, ANQP_NAI_REALM); 395 wpabuf_put_le16(buf, hapd->conf->nai_realm_count); 396 for (i = 0; i < hapd->conf->nai_realm_count; i++) { 397 u8 *realm_data_len, *realm_len; 398 struct hostapd_nai_realm_data *realm; 399 400 realm = &hapd->conf->nai_realm_data[i]; 401 realm_data_len = wpabuf_put(buf, 2); 402 wpabuf_put_u8(buf, realm->encoding); 403 realm_len = wpabuf_put(buf, 1); 404 for (j = 0; realm->realm[j]; j++) { 405 if (j > 0) 406 wpabuf_put_u8(buf, ';'); 407 wpabuf_put_str(buf, realm->realm[j]); 408 } 409 *realm_len = (u8 *) wpabuf_put(buf, 0) - realm_len - 1; 410 anqp_add_nai_realm_eap(buf, realm); 411 gas_anqp_set_element_len(buf, realm_data_len); 412 } 413 gas_anqp_set_element_len(buf, len); 414 } else if (nai_home_realm && hapd->conf->nai_realm_data) { 415 hs20_add_nai_home_realm_matches(hapd, buf, home_realm, 416 home_realm_len); 417 } 418 } 419 420 421 static void anqp_add_3gpp_cellular_network(struct hostapd_data *hapd, 422 struct wpabuf *buf) 423 { 424 if (hapd->conf->anqp_3gpp_cell_net) { 425 wpabuf_put_le16(buf, ANQP_3GPP_CELLULAR_NETWORK); 426 wpabuf_put_le16(buf, 427 hapd->conf->anqp_3gpp_cell_net_len); 428 wpabuf_put_data(buf, hapd->conf->anqp_3gpp_cell_net, 429 hapd->conf->anqp_3gpp_cell_net_len); 430 } 431 } 432 433 434 static void anqp_add_domain_name(struct hostapd_data *hapd, struct wpabuf *buf) 435 { 436 if (hapd->conf->domain_name) { 437 wpabuf_put_le16(buf, ANQP_DOMAIN_NAME); 438 wpabuf_put_le16(buf, hapd->conf->domain_name_len); 439 wpabuf_put_data(buf, hapd->conf->domain_name, 440 hapd->conf->domain_name_len); 441 } 442 } 443 444 445 #ifdef CONFIG_HS20 446 447 static void anqp_add_operator_friendly_name(struct hostapd_data *hapd, 448 struct wpabuf *buf) 449 { 450 if (hapd->conf->hs20_oper_friendly_name) { 451 u8 *len; 452 unsigned int i; 453 len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC); 454 wpabuf_put_be24(buf, OUI_WFA); 455 wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE); 456 wpabuf_put_u8(buf, HS20_STYPE_OPERATOR_FRIENDLY_NAME); 457 wpabuf_put_u8(buf, 0); /* Reserved */ 458 for (i = 0; i < hapd->conf->hs20_oper_friendly_name_count; i++) 459 { 460 struct hostapd_lang_string *vn; 461 vn = &hapd->conf->hs20_oper_friendly_name[i]; 462 wpabuf_put_u8(buf, 3 + vn->name_len); 463 wpabuf_put_data(buf, vn->lang, 3); 464 wpabuf_put_data(buf, vn->name, vn->name_len); 465 } 466 gas_anqp_set_element_len(buf, len); 467 } 468 } 469 470 471 static void anqp_add_wan_metrics(struct hostapd_data *hapd, 472 struct wpabuf *buf) 473 { 474 if (hapd->conf->hs20_wan_metrics) { 475 u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC); 476 wpabuf_put_be24(buf, OUI_WFA); 477 wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE); 478 wpabuf_put_u8(buf, HS20_STYPE_WAN_METRICS); 479 wpabuf_put_u8(buf, 0); /* Reserved */ 480 wpabuf_put_data(buf, hapd->conf->hs20_wan_metrics, 13); 481 gas_anqp_set_element_len(buf, len); 482 } 483 } 484 485 486 static void anqp_add_connection_capability(struct hostapd_data *hapd, 487 struct wpabuf *buf) 488 { 489 if (hapd->conf->hs20_connection_capability) { 490 u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC); 491 wpabuf_put_be24(buf, OUI_WFA); 492 wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE); 493 wpabuf_put_u8(buf, HS20_STYPE_CONNECTION_CAPABILITY); 494 wpabuf_put_u8(buf, 0); /* Reserved */ 495 wpabuf_put_data(buf, hapd->conf->hs20_connection_capability, 496 hapd->conf->hs20_connection_capability_len); 497 gas_anqp_set_element_len(buf, len); 498 } 499 } 500 501 502 static void anqp_add_operating_class(struct hostapd_data *hapd, 503 struct wpabuf *buf) 504 { 505 if (hapd->conf->hs20_operating_class) { 506 u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC); 507 wpabuf_put_be24(buf, OUI_WFA); 508 wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE); 509 wpabuf_put_u8(buf, HS20_STYPE_OPERATING_CLASS); 510 wpabuf_put_u8(buf, 0); /* Reserved */ 511 wpabuf_put_data(buf, hapd->conf->hs20_operating_class, 512 hapd->conf->hs20_operating_class_len); 513 gas_anqp_set_element_len(buf, len); 514 } 515 } 516 517 #endif /* CONFIG_HS20 */ 518 519 520 static struct wpabuf * 521 gas_serv_build_gas_resp_payload(struct hostapd_data *hapd, 522 unsigned int request, 523 struct gas_dialog_info *di, 524 const u8 *home_realm, size_t home_realm_len) 525 { 526 struct wpabuf *buf; 527 528 buf = wpabuf_alloc(1400); 529 if (buf == NULL) 530 return NULL; 531 532 if (request & ANQP_REQ_CAPABILITY_LIST) 533 anqp_add_capab_list(hapd, buf); 534 if (request & ANQP_REQ_VENUE_NAME) 535 anqp_add_venue_name(hapd, buf); 536 if (request & ANQP_REQ_NETWORK_AUTH_TYPE) 537 anqp_add_network_auth_type(hapd, buf); 538 if (request & ANQP_REQ_ROAMING_CONSORTIUM) 539 anqp_add_roaming_consortium(hapd, buf); 540 if (request & ANQP_REQ_IP_ADDR_TYPE_AVAILABILITY) 541 anqp_add_ip_addr_type_availability(hapd, buf); 542 if (request & (ANQP_REQ_NAI_REALM | ANQP_REQ_NAI_HOME_REALM)) 543 anqp_add_nai_realm(hapd, buf, home_realm, home_realm_len, 544 request & ANQP_REQ_NAI_REALM, 545 request & ANQP_REQ_NAI_HOME_REALM); 546 if (request & ANQP_REQ_3GPP_CELLULAR_NETWORK) 547 anqp_add_3gpp_cellular_network(hapd, buf); 548 if (request & ANQP_REQ_DOMAIN_NAME) 549 anqp_add_domain_name(hapd, buf); 550 551 #ifdef CONFIG_HS20 552 if (request & ANQP_REQ_HS_CAPABILITY_LIST) 553 anqp_add_hs_capab_list(hapd, buf); 554 if (request & ANQP_REQ_OPERATOR_FRIENDLY_NAME) 555 anqp_add_operator_friendly_name(hapd, buf); 556 if (request & ANQP_REQ_WAN_METRICS) 557 anqp_add_wan_metrics(hapd, buf); 558 if (request & ANQP_REQ_CONNECTION_CAPABILITY) 559 anqp_add_connection_capability(hapd, buf); 560 if (request & ANQP_REQ_OPERATING_CLASS) 561 anqp_add_operating_class(hapd, buf); 562 #endif /* CONFIG_HS20 */ 563 564 return buf; 565 } 566 567 568 static void gas_serv_clear_cached_ies(void *eloop_data, void *user_ctx) 569 { 570 struct gas_dialog_info *dia = eloop_data; 571 572 wpa_printf(MSG_DEBUG, "GAS: Timeout triggered, clearing dialog for " 573 "dialog token %d", dia->dialog_token); 574 575 gas_serv_dialog_clear(dia); 576 } 577 578 579 struct anqp_query_info { 580 unsigned int request; 581 unsigned int remote_request; 582 const u8 *home_realm_query; 583 size_t home_realm_query_len; 584 u16 remote_delay; 585 }; 586 587 588 static void set_anqp_req(unsigned int bit, const char *name, int local, 589 unsigned int remote, u16 remote_delay, 590 struct anqp_query_info *qi) 591 { 592 qi->request |= bit; 593 if (local) { 594 wpa_printf(MSG_DEBUG, "ANQP: %s (local)", name); 595 } else if (bit & remote) { 596 wpa_printf(MSG_DEBUG, "ANQP: %s (remote)", name); 597 qi->remote_request |= bit; 598 if (remote_delay > qi->remote_delay) 599 qi->remote_delay = remote_delay; 600 } else { 601 wpa_printf(MSG_DEBUG, "ANQP: %s not available", name); 602 } 603 } 604 605 606 static void rx_anqp_query_list_id(struct hostapd_data *hapd, u16 info_id, 607 struct anqp_query_info *qi) 608 { 609 switch (info_id) { 610 case ANQP_CAPABILITY_LIST: 611 set_anqp_req(ANQP_REQ_CAPABILITY_LIST, "Capability List", 1, 0, 612 0, qi); 613 break; 614 case ANQP_VENUE_NAME: 615 set_anqp_req(ANQP_REQ_VENUE_NAME, "Venue Name", 616 hapd->conf->venue_name != NULL, 0, 0, qi); 617 break; 618 case ANQP_NETWORK_AUTH_TYPE: 619 set_anqp_req(ANQP_REQ_NETWORK_AUTH_TYPE, "Network Auth Type", 620 hapd->conf->network_auth_type != NULL, 621 0, 0, qi); 622 break; 623 case ANQP_ROAMING_CONSORTIUM: 624 set_anqp_req(ANQP_REQ_ROAMING_CONSORTIUM, "Roaming Consortium", 625 hapd->conf->roaming_consortium != NULL, 0, 0, qi); 626 break; 627 case ANQP_IP_ADDR_TYPE_AVAILABILITY: 628 set_anqp_req(ANQP_REQ_IP_ADDR_TYPE_AVAILABILITY, 629 "IP Addr Type Availability", 630 hapd->conf->ipaddr_type_configured, 631 0, 0, qi); 632 break; 633 case ANQP_NAI_REALM: 634 set_anqp_req(ANQP_REQ_NAI_REALM, "NAI Realm", 635 hapd->conf->nai_realm_data != NULL, 636 0, 0, qi); 637 break; 638 case ANQP_3GPP_CELLULAR_NETWORK: 639 set_anqp_req(ANQP_REQ_3GPP_CELLULAR_NETWORK, 640 "3GPP Cellular Network", 641 hapd->conf->anqp_3gpp_cell_net != NULL, 642 0, 0, qi); 643 break; 644 case ANQP_DOMAIN_NAME: 645 set_anqp_req(ANQP_REQ_DOMAIN_NAME, "Domain Name", 646 hapd->conf->domain_name != NULL, 647 0, 0, qi); 648 break; 649 default: 650 wpa_printf(MSG_DEBUG, "ANQP: Unsupported Info Id %u", 651 info_id); 652 break; 653 } 654 } 655 656 657 static void rx_anqp_query_list(struct hostapd_data *hapd, 658 const u8 *pos, const u8 *end, 659 struct anqp_query_info *qi) 660 { 661 wpa_printf(MSG_DEBUG, "ANQP: %u Info IDs requested in Query list", 662 (unsigned int) (end - pos) / 2); 663 664 while (pos + 2 <= end) { 665 rx_anqp_query_list_id(hapd, WPA_GET_LE16(pos), qi); 666 pos += 2; 667 } 668 } 669 670 671 #ifdef CONFIG_HS20 672 673 static void rx_anqp_hs_query_list(struct hostapd_data *hapd, u8 subtype, 674 struct anqp_query_info *qi) 675 { 676 switch (subtype) { 677 case HS20_STYPE_CAPABILITY_LIST: 678 set_anqp_req(ANQP_REQ_HS_CAPABILITY_LIST, "HS Capability List", 679 1, 0, 0, qi); 680 break; 681 case HS20_STYPE_OPERATOR_FRIENDLY_NAME: 682 set_anqp_req(ANQP_REQ_OPERATOR_FRIENDLY_NAME, 683 "Operator Friendly Name", 684 hapd->conf->hs20_oper_friendly_name != NULL, 685 0, 0, qi); 686 break; 687 case HS20_STYPE_WAN_METRICS: 688 set_anqp_req(ANQP_REQ_WAN_METRICS, "WAN Metrics", 689 hapd->conf->hs20_wan_metrics != NULL, 690 0, 0, qi); 691 break; 692 case HS20_STYPE_CONNECTION_CAPABILITY: 693 set_anqp_req(ANQP_REQ_CONNECTION_CAPABILITY, 694 "Connection Capability", 695 hapd->conf->hs20_connection_capability != NULL, 696 0, 0, qi); 697 break; 698 case HS20_STYPE_OPERATING_CLASS: 699 set_anqp_req(ANQP_REQ_OPERATING_CLASS, "Operating Class", 700 hapd->conf->hs20_operating_class != NULL, 701 0, 0, qi); 702 break; 703 default: 704 wpa_printf(MSG_DEBUG, "ANQP: Unsupported HS 2.0 subtype %u", 705 subtype); 706 break; 707 } 708 } 709 710 711 static void rx_anqp_hs_nai_home_realm(struct hostapd_data *hapd, 712 const u8 *pos, const u8 *end, 713 struct anqp_query_info *qi) 714 { 715 qi->request |= ANQP_REQ_NAI_HOME_REALM; 716 qi->home_realm_query = pos; 717 qi->home_realm_query_len = end - pos; 718 if (hapd->conf->nai_realm_data != NULL) { 719 wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 NAI Home Realm Query " 720 "(local)"); 721 } else { 722 wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 NAI Home Realm Query not " 723 "available"); 724 } 725 } 726 727 728 static void rx_anqp_vendor_specific(struct hostapd_data *hapd, 729 const u8 *pos, const u8 *end, 730 struct anqp_query_info *qi) 731 { 732 u32 oui; 733 u8 subtype; 734 735 if (pos + 4 > end) { 736 wpa_printf(MSG_DEBUG, "ANQP: Too short vendor specific ANQP " 737 "Query element"); 738 return; 739 } 740 741 oui = WPA_GET_BE24(pos); 742 pos += 3; 743 if (oui != OUI_WFA) { 744 wpa_printf(MSG_DEBUG, "ANQP: Unsupported vendor OUI %06x", 745 oui); 746 return; 747 } 748 749 if (*pos != HS20_ANQP_OUI_TYPE) { 750 wpa_printf(MSG_DEBUG, "ANQP: Unsupported WFA vendor type %u", 751 *pos); 752 return; 753 } 754 pos++; 755 756 if (pos + 1 >= end) 757 return; 758 759 subtype = *pos++; 760 pos++; /* Reserved */ 761 switch (subtype) { 762 case HS20_STYPE_QUERY_LIST: 763 wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 Query List"); 764 while (pos < end) { 765 rx_anqp_hs_query_list(hapd, *pos, qi); 766 pos++; 767 } 768 break; 769 case HS20_STYPE_NAI_HOME_REALM_QUERY: 770 rx_anqp_hs_nai_home_realm(hapd, pos, end, qi); 771 break; 772 default: 773 wpa_printf(MSG_DEBUG, "ANQP: Unsupported HS 2.0 query subtype " 774 "%u", subtype); 775 break; 776 } 777 } 778 779 #endif /* CONFIG_HS20 */ 780 781 782 static void gas_serv_req_local_processing(struct hostapd_data *hapd, 783 const u8 *sa, u8 dialog_token, 784 struct anqp_query_info *qi, int prot) 785 { 786 struct wpabuf *buf, *tx_buf; 787 788 buf = gas_serv_build_gas_resp_payload(hapd, qi->request, NULL, 789 qi->home_realm_query, 790 qi->home_realm_query_len); 791 wpa_hexdump_buf(MSG_MSGDUMP, "ANQP: Locally generated ANQP responses", 792 buf); 793 if (!buf) 794 return; 795 796 if (wpabuf_len(buf) > hapd->gas_frag_limit || 797 hapd->conf->gas_comeback_delay) { 798 struct gas_dialog_info *di; 799 u16 comeback_delay = 1; 800 801 if (hapd->conf->gas_comeback_delay) { 802 /* Testing - allow overriding of the delay value */ 803 comeback_delay = hapd->conf->gas_comeback_delay; 804 } 805 806 wpa_printf(MSG_DEBUG, "ANQP: Too long response to fit in " 807 "initial response - use GAS comeback"); 808 di = gas_dialog_create(hapd, sa, dialog_token); 809 if (!di) { 810 wpa_printf(MSG_INFO, "ANQP: Could not create dialog " 811 "for " MACSTR " (dialog token %u)", 812 MAC2STR(sa), dialog_token); 813 wpabuf_free(buf); 814 return; 815 } 816 di->prot = prot; 817 di->sd_resp = buf; 818 di->sd_resp_pos = 0; 819 tx_buf = gas_anqp_build_initial_resp_buf( 820 dialog_token, WLAN_STATUS_SUCCESS, comeback_delay, 821 NULL); 822 } else { 823 wpa_printf(MSG_DEBUG, "ANQP: Initial response (no comeback)"); 824 tx_buf = gas_anqp_build_initial_resp_buf( 825 dialog_token, WLAN_STATUS_SUCCESS, 0, buf); 826 wpabuf_free(buf); 827 } 828 if (!tx_buf) 829 return; 830 if (prot) 831 convert_to_protected_dual(tx_buf); 832 hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa, 833 wpabuf_head(tx_buf), wpabuf_len(tx_buf)); 834 wpabuf_free(tx_buf); 835 } 836 837 838 static void gas_serv_rx_gas_initial_req(struct hostapd_data *hapd, 839 const u8 *sa, 840 const u8 *data, size_t len, int prot) 841 { 842 const u8 *pos = data; 843 const u8 *end = data + len; 844 const u8 *next; 845 u8 dialog_token; 846 u16 slen; 847 struct anqp_query_info qi; 848 const u8 *adv_proto; 849 850 if (len < 1 + 2) 851 return; 852 853 os_memset(&qi, 0, sizeof(qi)); 854 855 dialog_token = *pos++; 856 wpa_msg(hapd->msg_ctx, MSG_DEBUG, 857 "GAS: GAS Initial Request from " MACSTR " (dialog token %u) ", 858 MAC2STR(sa), dialog_token); 859 860 if (*pos != WLAN_EID_ADV_PROTO) { 861 wpa_msg(hapd->msg_ctx, MSG_DEBUG, 862 "GAS: Unexpected IE in GAS Initial Request: %u", *pos); 863 return; 864 } 865 adv_proto = pos++; 866 867 slen = *pos++; 868 next = pos + slen; 869 if (next > end || slen < 2) { 870 wpa_msg(hapd->msg_ctx, MSG_DEBUG, 871 "GAS: Invalid IE in GAS Initial Request"); 872 return; 873 } 874 pos++; /* skip QueryRespLenLimit and PAME-BI */ 875 876 if (*pos != ACCESS_NETWORK_QUERY_PROTOCOL) { 877 struct wpabuf *buf; 878 wpa_msg(hapd->msg_ctx, MSG_DEBUG, 879 "GAS: Unsupported GAS advertisement protocol id %u", 880 *pos); 881 if (sa[0] & 0x01) 882 return; /* Invalid source address - drop silently */ 883 buf = gas_build_initial_resp( 884 dialog_token, WLAN_STATUS_GAS_ADV_PROTO_NOT_SUPPORTED, 885 0, 2 + slen + 2); 886 if (buf == NULL) 887 return; 888 wpabuf_put_data(buf, adv_proto, 2 + slen); 889 wpabuf_put_le16(buf, 0); /* Query Response Length */ 890 if (prot) 891 convert_to_protected_dual(buf); 892 hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa, 893 wpabuf_head(buf), wpabuf_len(buf)); 894 wpabuf_free(buf); 895 return; 896 } 897 898 pos = next; 899 /* Query Request */ 900 if (pos + 2 > end) 901 return; 902 slen = WPA_GET_LE16(pos); 903 pos += 2; 904 if (pos + slen > end) 905 return; 906 end = pos + slen; 907 908 /* ANQP Query Request */ 909 while (pos < end) { 910 u16 info_id, elen; 911 912 if (pos + 4 > end) 913 return; 914 915 info_id = WPA_GET_LE16(pos); 916 pos += 2; 917 elen = WPA_GET_LE16(pos); 918 pos += 2; 919 920 if (pos + elen > end) { 921 wpa_printf(MSG_DEBUG, "ANQP: Invalid Query Request"); 922 return; 923 } 924 925 switch (info_id) { 926 case ANQP_QUERY_LIST: 927 rx_anqp_query_list(hapd, pos, pos + elen, &qi); 928 break; 929 #ifdef CONFIG_HS20 930 case ANQP_VENDOR_SPECIFIC: 931 rx_anqp_vendor_specific(hapd, pos, pos + elen, &qi); 932 break; 933 #endif /* CONFIG_HS20 */ 934 default: 935 wpa_printf(MSG_DEBUG, "ANQP: Unsupported Query " 936 "Request element %u", info_id); 937 break; 938 } 939 940 pos += elen; 941 } 942 943 gas_serv_req_local_processing(hapd, sa, dialog_token, &qi, prot); 944 } 945 946 947 void gas_serv_tx_gas_response(struct hostapd_data *hapd, const u8 *dst, 948 struct gas_dialog_info *dialog) 949 { 950 struct wpabuf *buf, *tx_buf; 951 u8 dialog_token = dialog->dialog_token; 952 size_t frag_len; 953 954 if (dialog->sd_resp == NULL) { 955 buf = gas_serv_build_gas_resp_payload(hapd, 956 dialog->all_requested, 957 dialog, NULL, 0); 958 wpa_hexdump_buf(MSG_MSGDUMP, "ANQP: Generated ANQP responses", 959 buf); 960 if (!buf) 961 goto tx_gas_response_done; 962 dialog->sd_resp = buf; 963 dialog->sd_resp_pos = 0; 964 } 965 frag_len = wpabuf_len(dialog->sd_resp) - dialog->sd_resp_pos; 966 if (frag_len > hapd->gas_frag_limit || dialog->comeback_delay || 967 hapd->conf->gas_comeback_delay) { 968 u16 comeback_delay_tus = dialog->comeback_delay + 969 GAS_SERV_COMEBACK_DELAY_FUDGE; 970 u32 comeback_delay_secs, comeback_delay_usecs; 971 972 if (hapd->conf->gas_comeback_delay) { 973 /* Testing - allow overriding of the delay value */ 974 comeback_delay_tus = hapd->conf->gas_comeback_delay; 975 } 976 977 wpa_printf(MSG_DEBUG, "GAS: Response frag_len %u (frag limit " 978 "%u) and comeback delay %u, " 979 "requesting comebacks", (unsigned int) frag_len, 980 (unsigned int) hapd->gas_frag_limit, 981 dialog->comeback_delay); 982 tx_buf = gas_anqp_build_initial_resp_buf(dialog_token, 983 WLAN_STATUS_SUCCESS, 984 comeback_delay_tus, 985 NULL); 986 if (tx_buf) { 987 wpa_msg(hapd->msg_ctx, MSG_DEBUG, 988 "GAS: Tx GAS Initial Resp (comeback = 10TU)"); 989 if (dialog->prot) 990 convert_to_protected_dual(tx_buf); 991 hostapd_drv_send_action(hapd, hapd->iface->freq, 0, 992 dst, 993 wpabuf_head(tx_buf), 994 wpabuf_len(tx_buf)); 995 } 996 wpabuf_free(tx_buf); 997 998 /* start a timer of 1.5 * comeback-delay */ 999 comeback_delay_tus = comeback_delay_tus + 1000 (comeback_delay_tus / 2); 1001 comeback_delay_secs = (comeback_delay_tus * 1024) / 1000000; 1002 comeback_delay_usecs = (comeback_delay_tus * 1024) - 1003 (comeback_delay_secs * 1000000); 1004 eloop_register_timeout(comeback_delay_secs, 1005 comeback_delay_usecs, 1006 gas_serv_clear_cached_ies, dialog, 1007 NULL); 1008 goto tx_gas_response_done; 1009 } 1010 1011 buf = wpabuf_alloc_copy(wpabuf_head_u8(dialog->sd_resp) + 1012 dialog->sd_resp_pos, frag_len); 1013 if (buf == NULL) { 1014 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Buffer allocation " 1015 "failed"); 1016 goto tx_gas_response_done; 1017 } 1018 tx_buf = gas_anqp_build_initial_resp_buf(dialog_token, 1019 WLAN_STATUS_SUCCESS, 0, buf); 1020 wpabuf_free(buf); 1021 if (tx_buf == NULL) 1022 goto tx_gas_response_done; 1023 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Tx GAS Initial " 1024 "Response (frag_id %d frag_len %d)", 1025 dialog->sd_frag_id, (int) frag_len); 1026 dialog->sd_frag_id++; 1027 1028 if (dialog->prot) 1029 convert_to_protected_dual(tx_buf); 1030 hostapd_drv_send_action(hapd, hapd->iface->freq, 0, dst, 1031 wpabuf_head(tx_buf), wpabuf_len(tx_buf)); 1032 wpabuf_free(tx_buf); 1033 tx_gas_response_done: 1034 gas_serv_clear_cached_ies(dialog, NULL); 1035 } 1036 1037 1038 static void gas_serv_rx_gas_comeback_req(struct hostapd_data *hapd, 1039 const u8 *sa, 1040 const u8 *data, size_t len, int prot) 1041 { 1042 struct gas_dialog_info *dialog; 1043 struct wpabuf *buf, *tx_buf; 1044 u8 dialog_token; 1045 size_t frag_len; 1046 int more = 0; 1047 1048 wpa_hexdump(MSG_DEBUG, "GAS: RX GAS Comeback Request", data, len); 1049 if (len < 1) 1050 return; 1051 dialog_token = *data; 1052 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Dialog Token: %u", 1053 dialog_token); 1054 1055 dialog = gas_serv_dialog_find(hapd, sa, dialog_token); 1056 if (!dialog) { 1057 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: No pending SD " 1058 "response fragment for " MACSTR " dialog token %u", 1059 MAC2STR(sa), dialog_token); 1060 1061 if (sa[0] & 0x01) 1062 return; /* Invalid source address - drop silently */ 1063 tx_buf = gas_anqp_build_comeback_resp_buf( 1064 dialog_token, WLAN_STATUS_NO_OUTSTANDING_GAS_REQ, 0, 0, 1065 0, NULL); 1066 if (tx_buf == NULL) 1067 return; 1068 goto send_resp; 1069 } 1070 1071 if (dialog->sd_resp == NULL) { 1072 wpa_printf(MSG_DEBUG, "GAS: Remote request 0x%x received 0x%x", 1073 dialog->requested, dialog->received); 1074 if ((dialog->requested & dialog->received) != 1075 dialog->requested) { 1076 wpa_printf(MSG_DEBUG, "GAS: Did not receive response " 1077 "from remote processing"); 1078 gas_serv_dialog_clear(dialog); 1079 tx_buf = gas_anqp_build_comeback_resp_buf( 1080 dialog_token, 1081 WLAN_STATUS_GAS_RESP_NOT_RECEIVED, 0, 0, 0, 1082 NULL); 1083 if (tx_buf == NULL) 1084 return; 1085 goto send_resp; 1086 } 1087 1088 buf = gas_serv_build_gas_resp_payload(hapd, 1089 dialog->all_requested, 1090 dialog, NULL, 0); 1091 wpa_hexdump_buf(MSG_MSGDUMP, "ANQP: Generated ANQP responses", 1092 buf); 1093 if (!buf) 1094 goto rx_gas_comeback_req_done; 1095 dialog->sd_resp = buf; 1096 dialog->sd_resp_pos = 0; 1097 } 1098 frag_len = wpabuf_len(dialog->sd_resp) - dialog->sd_resp_pos; 1099 if (frag_len > hapd->gas_frag_limit) { 1100 frag_len = hapd->gas_frag_limit; 1101 more = 1; 1102 } 1103 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: resp frag_len %u", 1104 (unsigned int) frag_len); 1105 buf = wpabuf_alloc_copy(wpabuf_head_u8(dialog->sd_resp) + 1106 dialog->sd_resp_pos, frag_len); 1107 if (buf == NULL) { 1108 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Failed to allocate " 1109 "buffer"); 1110 goto rx_gas_comeback_req_done; 1111 } 1112 tx_buf = gas_anqp_build_comeback_resp_buf(dialog_token, 1113 WLAN_STATUS_SUCCESS, 1114 dialog->sd_frag_id, 1115 more, 0, buf); 1116 wpabuf_free(buf); 1117 if (tx_buf == NULL) 1118 goto rx_gas_comeback_req_done; 1119 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Tx GAS Comeback Response " 1120 "(frag_id %d more=%d frag_len=%d)", 1121 dialog->sd_frag_id, more, (int) frag_len); 1122 dialog->sd_frag_id++; 1123 dialog->sd_resp_pos += frag_len; 1124 1125 if (more) { 1126 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: %d more bytes remain " 1127 "to be sent", 1128 (int) (wpabuf_len(dialog->sd_resp) - 1129 dialog->sd_resp_pos)); 1130 } else { 1131 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: All fragments of " 1132 "SD response sent"); 1133 gas_serv_dialog_clear(dialog); 1134 gas_serv_free_dialogs(hapd, sa); 1135 } 1136 1137 send_resp: 1138 if (prot) 1139 convert_to_protected_dual(tx_buf); 1140 hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa, 1141 wpabuf_head(tx_buf), wpabuf_len(tx_buf)); 1142 wpabuf_free(tx_buf); 1143 return; 1144 1145 rx_gas_comeback_req_done: 1146 gas_serv_clear_cached_ies(dialog, NULL); 1147 } 1148 1149 1150 static void gas_serv_rx_public_action(void *ctx, const u8 *buf, size_t len, 1151 int freq) 1152 { 1153 struct hostapd_data *hapd = ctx; 1154 const struct ieee80211_mgmt *mgmt; 1155 size_t hdr_len; 1156 const u8 *sa, *data; 1157 int prot; 1158 1159 mgmt = (const struct ieee80211_mgmt *) buf; 1160 hdr_len = (const u8 *) &mgmt->u.action.u.vs_public_action.action - buf; 1161 if (hdr_len > len) 1162 return; 1163 if (mgmt->u.action.category != WLAN_ACTION_PUBLIC && 1164 mgmt->u.action.category != WLAN_ACTION_PROTECTED_DUAL) 1165 return; 1166 /* 1167 * Note: Public Action and Protected Dual of Public Action frames share 1168 * the same payload structure, so it is fine to use definitions of 1169 * Public Action frames to process both. 1170 */ 1171 prot = mgmt->u.action.category == WLAN_ACTION_PROTECTED_DUAL; 1172 sa = mgmt->sa; 1173 len -= hdr_len; 1174 data = &mgmt->u.action.u.public_action.action; 1175 switch (data[0]) { 1176 case WLAN_PA_GAS_INITIAL_REQ: 1177 gas_serv_rx_gas_initial_req(hapd, sa, data + 1, len - 1, prot); 1178 break; 1179 case WLAN_PA_GAS_COMEBACK_REQ: 1180 gas_serv_rx_gas_comeback_req(hapd, sa, data + 1, len - 1, prot); 1181 break; 1182 } 1183 } 1184 1185 1186 int gas_serv_init(struct hostapd_data *hapd) 1187 { 1188 hapd->public_action_cb2 = gas_serv_rx_public_action; 1189 hapd->public_action_cb2_ctx = hapd; 1190 hapd->gas_frag_limit = 1400; 1191 if (hapd->conf->gas_frag_limit > 0) 1192 hapd->gas_frag_limit = hapd->conf->gas_frag_limit; 1193 return 0; 1194 } 1195 1196 1197 void gas_serv_deinit(struct hostapd_data *hapd) 1198 { 1199 } 1200