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