Home | History | Annotate | Download | only in wpa_supplicant
      1 /*
      2  * Interworking (IEEE 802.11u)
      3  * Copyright (c) 2011-2012, 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/pcsc_funcs.h"
     16 #include "utils/eloop.h"
     17 #include "drivers/driver.h"
     18 #include "eap_common/eap_defs.h"
     19 #include "eap_peer/eap.h"
     20 #include "eap_peer/eap_methods.h"
     21 #include "wpa_supplicant_i.h"
     22 #include "config.h"
     23 #include "config_ssid.h"
     24 #include "bss.h"
     25 #include "scan.h"
     26 #include "notify.h"
     27 #include "gas_query.h"
     28 #include "hs20_supplicant.h"
     29 #include "interworking.h"
     30 
     31 
     32 #if defined(EAP_SIM) | defined(EAP_SIM_DYNAMIC)
     33 #define INTERWORKING_3GPP
     34 #else
     35 #if defined(EAP_AKA) | defined(EAP_AKA_DYNAMIC)
     36 #define INTERWORKING_3GPP
     37 #else
     38 #if defined(EAP_AKA_PRIME) | defined(EAP_AKA_PRIME_DYNAMIC)
     39 #define INTERWORKING_3GPP
     40 #endif
     41 #endif
     42 #endif
     43 
     44 static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s);
     45 static struct wpa_cred * interworking_credentials_available_realm(
     46 	struct wpa_supplicant *wpa_s, struct wpa_bss *bss);
     47 static struct wpa_cred * interworking_credentials_available_3gpp(
     48 	struct wpa_supplicant *wpa_s, struct wpa_bss *bss);
     49 
     50 
     51 static void interworking_reconnect(struct wpa_supplicant *wpa_s)
     52 {
     53 	if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
     54 		wpa_supplicant_cancel_sched_scan(wpa_s);
     55 		wpa_supplicant_deauthenticate(wpa_s,
     56 					      WLAN_REASON_DEAUTH_LEAVING);
     57 	}
     58 	wpa_s->disconnected = 0;
     59 	wpa_s->reassociate = 1;
     60 
     61 	if (wpa_supplicant_fast_associate(wpa_s) >= 0)
     62 		return;
     63 
     64 	wpa_supplicant_req_scan(wpa_s, 0, 0);
     65 }
     66 
     67 
     68 static struct wpabuf * anqp_build_req(u16 info_ids[], size_t num_ids,
     69 				      struct wpabuf *extra)
     70 {
     71 	struct wpabuf *buf;
     72 	size_t i;
     73 	u8 *len_pos;
     74 
     75 	buf = gas_anqp_build_initial_req(0, 4 + num_ids * 2 +
     76 					 (extra ? wpabuf_len(extra) : 0));
     77 	if (buf == NULL)
     78 		return NULL;
     79 
     80 	len_pos = gas_anqp_add_element(buf, ANQP_QUERY_LIST);
     81 	for (i = 0; i < num_ids; i++)
     82 		wpabuf_put_le16(buf, info_ids[i]);
     83 	gas_anqp_set_element_len(buf, len_pos);
     84 	if (extra)
     85 		wpabuf_put_buf(buf, extra);
     86 
     87 	gas_anqp_set_len(buf);
     88 
     89 	return buf;
     90 }
     91 
     92 
     93 static void interworking_anqp_resp_cb(void *ctx, const u8 *dst,
     94 				      u8 dialog_token,
     95 				      enum gas_query_result result,
     96 				      const struct wpabuf *adv_proto,
     97 				      const struct wpabuf *resp,
     98 				      u16 status_code)
     99 {
    100 	struct wpa_supplicant *wpa_s = ctx;
    101 
    102 	anqp_resp_cb(wpa_s, dst, dialog_token, result, adv_proto, resp,
    103 		     status_code);
    104 	interworking_next_anqp_fetch(wpa_s);
    105 }
    106 
    107 
    108 static int cred_with_roaming_consortium(struct wpa_supplicant *wpa_s)
    109 {
    110 	struct wpa_cred *cred;
    111 
    112 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
    113 		if (cred->roaming_consortium_len)
    114 			return 1;
    115 	}
    116 	return 0;
    117 }
    118 
    119 
    120 static int cred_with_3gpp(struct wpa_supplicant *wpa_s)
    121 {
    122 	struct wpa_cred *cred;
    123 
    124 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
    125 		if (cred->pcsc || cred->imsi)
    126 			return 1;
    127 	}
    128 	return 0;
    129 }
    130 
    131 
    132 static int cred_with_nai_realm(struct wpa_supplicant *wpa_s)
    133 {
    134 	struct wpa_cred *cred;
    135 
    136 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
    137 		if (cred->pcsc || cred->imsi)
    138 			continue;
    139 		if (!cred->eap_method)
    140 			return 1;
    141 		if (cred->realm && cred->roaming_consortium_len == 0)
    142 			return 1;
    143 	}
    144 	return 0;
    145 }
    146 
    147 
    148 static int cred_with_domain(struct wpa_supplicant *wpa_s)
    149 {
    150 	struct wpa_cred *cred;
    151 
    152 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
    153 		if (cred->domain || cred->pcsc || cred->imsi)
    154 			return 1;
    155 	}
    156 	return 0;
    157 }
    158 
    159 
    160 static int additional_roaming_consortiums(struct wpa_bss *bss)
    161 {
    162 	const u8 *ie;
    163 	ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM);
    164 	if (ie == NULL || ie[1] == 0)
    165 		return 0;
    166 	return ie[2]; /* Number of ANQP OIs */
    167 }
    168 
    169 
    170 static void interworking_continue_anqp(void *eloop_ctx, void *sock_ctx)
    171 {
    172 	struct wpa_supplicant *wpa_s = eloop_ctx;
    173 	interworking_next_anqp_fetch(wpa_s);
    174 }
    175 
    176 
    177 static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s,
    178 				      struct wpa_bss *bss)
    179 {
    180 	struct wpabuf *buf;
    181 	int ret = 0;
    182 	int res;
    183 	u16 info_ids[8];
    184 	size_t num_info_ids = 0;
    185 	struct wpabuf *extra = NULL;
    186 	int all = wpa_s->fetch_all_anqp;
    187 
    188 	wpa_printf(MSG_DEBUG, "Interworking: ANQP Query Request to " MACSTR,
    189 		   MAC2STR(bss->bssid));
    190 	wpa_s->interworking_gas_bss = bss;
    191 
    192 	info_ids[num_info_ids++] = ANQP_CAPABILITY_LIST;
    193 	if (all) {
    194 		info_ids[num_info_ids++] = ANQP_VENUE_NAME;
    195 		info_ids[num_info_ids++] = ANQP_NETWORK_AUTH_TYPE;
    196 	}
    197 	if (all || (cred_with_roaming_consortium(wpa_s) &&
    198 		    additional_roaming_consortiums(bss)))
    199 		info_ids[num_info_ids++] = ANQP_ROAMING_CONSORTIUM;
    200 	if (all)
    201 		info_ids[num_info_ids++] = ANQP_IP_ADDR_TYPE_AVAILABILITY;
    202 	if (all || cred_with_nai_realm(wpa_s))
    203 		info_ids[num_info_ids++] = ANQP_NAI_REALM;
    204 	if (all || cred_with_3gpp(wpa_s))
    205 		info_ids[num_info_ids++] = ANQP_3GPP_CELLULAR_NETWORK;
    206 	if (all || cred_with_domain(wpa_s))
    207 		info_ids[num_info_ids++] = ANQP_DOMAIN_NAME;
    208 	wpa_hexdump(MSG_DEBUG, "Interworking: ANQP Query info",
    209 		    (u8 *) info_ids, num_info_ids * 2);
    210 
    211 #ifdef CONFIG_HS20
    212 	if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
    213 		u8 *len_pos;
    214 
    215 		extra = wpabuf_alloc(100);
    216 		if (!extra)
    217 			return -1;
    218 
    219 		len_pos = gas_anqp_add_element(extra, ANQP_VENDOR_SPECIFIC);
    220 		wpabuf_put_be24(extra, OUI_WFA);
    221 		wpabuf_put_u8(extra, HS20_ANQP_OUI_TYPE);
    222 		wpabuf_put_u8(extra, HS20_STYPE_QUERY_LIST);
    223 		wpabuf_put_u8(extra, 0); /* Reserved */
    224 		wpabuf_put_u8(extra, HS20_STYPE_CAPABILITY_LIST);
    225 		if (all) {
    226 			wpabuf_put_u8(extra,
    227 				      HS20_STYPE_OPERATOR_FRIENDLY_NAME);
    228 			wpabuf_put_u8(extra, HS20_STYPE_WAN_METRICS);
    229 			wpabuf_put_u8(extra, HS20_STYPE_CONNECTION_CAPABILITY);
    230 			wpabuf_put_u8(extra, HS20_STYPE_OPERATING_CLASS);
    231 		}
    232 		gas_anqp_set_element_len(extra, len_pos);
    233 	}
    234 #endif /* CONFIG_HS20 */
    235 
    236 	buf = anqp_build_req(info_ids, num_info_ids, extra);
    237 	wpabuf_free(extra);
    238 	if (buf == NULL)
    239 		return -1;
    240 
    241 	res = gas_query_req(wpa_s->gas, bss->bssid, bss->freq, buf,
    242 			    interworking_anqp_resp_cb, wpa_s);
    243 	if (res < 0) {
    244 		wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request");
    245 		ret = -1;
    246 		eloop_register_timeout(0, 0, interworking_continue_anqp, wpa_s,
    247 				       NULL);
    248 	} else
    249 		wpa_printf(MSG_DEBUG, "ANQP: Query started with dialog token "
    250 			   "%u", res);
    251 
    252 	wpabuf_free(buf);
    253 	return ret;
    254 }
    255 
    256 
    257 struct nai_realm_eap {
    258 	u8 method;
    259 	u8 inner_method;
    260 	enum nai_realm_eap_auth_inner_non_eap inner_non_eap;
    261 	u8 cred_type;
    262 	u8 tunneled_cred_type;
    263 };
    264 
    265 struct nai_realm {
    266 	u8 encoding;
    267 	char *realm;
    268 	u8 eap_count;
    269 	struct nai_realm_eap *eap;
    270 };
    271 
    272 
    273 static void nai_realm_free(struct nai_realm *realms, u16 count)
    274 {
    275 	u16 i;
    276 
    277 	if (realms == NULL)
    278 		return;
    279 	for (i = 0; i < count; i++) {
    280 		os_free(realms[i].eap);
    281 		os_free(realms[i].realm);
    282 	}
    283 	os_free(realms);
    284 }
    285 
    286 
    287 static const u8 * nai_realm_parse_eap(struct nai_realm_eap *e, const u8 *pos,
    288 				      const u8 *end)
    289 {
    290 	u8 elen, auth_count, a;
    291 	const u8 *e_end;
    292 
    293 	if (pos + 3 > end) {
    294 		wpa_printf(MSG_DEBUG, "No room for EAP Method fixed fields");
    295 		return NULL;
    296 	}
    297 
    298 	elen = *pos++;
    299 	if (pos + elen > end || elen < 2) {
    300 		wpa_printf(MSG_DEBUG, "No room for EAP Method subfield");
    301 		return NULL;
    302 	}
    303 	e_end = pos + elen;
    304 	e->method = *pos++;
    305 	auth_count = *pos++;
    306 	wpa_printf(MSG_DEBUG, "EAP Method: len=%u method=%u auth_count=%u",
    307 		   elen, e->method, auth_count);
    308 
    309 	for (a = 0; a < auth_count; a++) {
    310 		u8 id, len;
    311 
    312 		if (pos + 2 > end || pos + 2 + pos[1] > end) {
    313 			wpa_printf(MSG_DEBUG, "No room for Authentication "
    314 				   "Parameter subfield");
    315 			return NULL;
    316 		}
    317 
    318 		id = *pos++;
    319 		len = *pos++;
    320 
    321 		switch (id) {
    322 		case NAI_REALM_EAP_AUTH_NON_EAP_INNER_AUTH:
    323 			if (len < 1)
    324 				break;
    325 			e->inner_non_eap = *pos;
    326 			if (e->method != EAP_TYPE_TTLS)
    327 				break;
    328 			switch (*pos) {
    329 			case NAI_REALM_INNER_NON_EAP_PAP:
    330 				wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP");
    331 				break;
    332 			case NAI_REALM_INNER_NON_EAP_CHAP:
    333 				wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP");
    334 				break;
    335 			case NAI_REALM_INNER_NON_EAP_MSCHAP:
    336 				wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP");
    337 				break;
    338 			case NAI_REALM_INNER_NON_EAP_MSCHAPV2:
    339 				wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2");
    340 				break;
    341 			}
    342 			break;
    343 		case NAI_REALM_EAP_AUTH_INNER_AUTH_EAP_METHOD:
    344 			if (len < 1)
    345 				break;
    346 			e->inner_method = *pos;
    347 			wpa_printf(MSG_DEBUG, "Inner EAP method: %u",
    348 				   e->inner_method);
    349 			break;
    350 		case NAI_REALM_EAP_AUTH_CRED_TYPE:
    351 			if (len < 1)
    352 				break;
    353 			e->cred_type = *pos;
    354 			wpa_printf(MSG_DEBUG, "Credential Type: %u",
    355 				   e->cred_type);
    356 			break;
    357 		case NAI_REALM_EAP_AUTH_TUNNELED_CRED_TYPE:
    358 			if (len < 1)
    359 				break;
    360 			e->tunneled_cred_type = *pos;
    361 			wpa_printf(MSG_DEBUG, "Tunneled EAP Method Credential "
    362 				   "Type: %u", e->tunneled_cred_type);
    363 			break;
    364 		default:
    365 			wpa_printf(MSG_DEBUG, "Unsupported Authentication "
    366 				   "Parameter: id=%u len=%u", id, len);
    367 			wpa_hexdump(MSG_DEBUG, "Authentication Parameter "
    368 				    "Value", pos, len);
    369 			break;
    370 		}
    371 
    372 		pos += len;
    373 	}
    374 
    375 	return e_end;
    376 }
    377 
    378 
    379 static const u8 * nai_realm_parse_realm(struct nai_realm *r, const u8 *pos,
    380 					const u8 *end)
    381 {
    382 	u16 len;
    383 	const u8 *f_end;
    384 	u8 realm_len, e;
    385 
    386 	if (end - pos < 4) {
    387 		wpa_printf(MSG_DEBUG, "No room for NAI Realm Data "
    388 			   "fixed fields");
    389 		return NULL;
    390 	}
    391 
    392 	len = WPA_GET_LE16(pos); /* NAI Realm Data field Length */
    393 	pos += 2;
    394 	if (pos + len > end || len < 3) {
    395 		wpa_printf(MSG_DEBUG, "No room for NAI Realm Data "
    396 			   "(len=%u; left=%u)",
    397 			   len, (unsigned int) (end - pos));
    398 		return NULL;
    399 	}
    400 	f_end = pos + len;
    401 
    402 	r->encoding = *pos++;
    403 	realm_len = *pos++;
    404 	if (pos + realm_len > f_end) {
    405 		wpa_printf(MSG_DEBUG, "No room for NAI Realm "
    406 			   "(len=%u; left=%u)",
    407 			   realm_len, (unsigned int) (f_end - pos));
    408 		return NULL;
    409 	}
    410 	wpa_hexdump_ascii(MSG_DEBUG, "NAI Realm", pos, realm_len);
    411 	r->realm = os_malloc(realm_len + 1);
    412 	if (r->realm == NULL)
    413 		return NULL;
    414 	os_memcpy(r->realm, pos, realm_len);
    415 	r->realm[realm_len] = '\0';
    416 	pos += realm_len;
    417 
    418 	if (pos + 1 > f_end) {
    419 		wpa_printf(MSG_DEBUG, "No room for EAP Method Count");
    420 		return NULL;
    421 	}
    422 	r->eap_count = *pos++;
    423 	wpa_printf(MSG_DEBUG, "EAP Count: %u", r->eap_count);
    424 	if (pos + r->eap_count * 3 > f_end) {
    425 		wpa_printf(MSG_DEBUG, "No room for EAP Methods");
    426 		return NULL;
    427 	}
    428 	r->eap = os_calloc(r->eap_count, sizeof(struct nai_realm_eap));
    429 	if (r->eap == NULL)
    430 		return NULL;
    431 
    432 	for (e = 0; e < r->eap_count; e++) {
    433 		pos = nai_realm_parse_eap(&r->eap[e], pos, f_end);
    434 		if (pos == NULL)
    435 			return NULL;
    436 	}
    437 
    438 	return f_end;
    439 }
    440 
    441 
    442 static struct nai_realm * nai_realm_parse(struct wpabuf *anqp, u16 *count)
    443 {
    444 	struct nai_realm *realm;
    445 	const u8 *pos, *end;
    446 	u16 i, num;
    447 
    448 	if (anqp == NULL || wpabuf_len(anqp) < 2)
    449 		return NULL;
    450 
    451 	pos = wpabuf_head_u8(anqp);
    452 	end = pos + wpabuf_len(anqp);
    453 	num = WPA_GET_LE16(pos);
    454 	wpa_printf(MSG_DEBUG, "NAI Realm Count: %u", num);
    455 	pos += 2;
    456 
    457 	if (num * 5 > end - pos) {
    458 		wpa_printf(MSG_DEBUG, "Invalid NAI Realm Count %u - not "
    459 			   "enough data (%u octets) for that many realms",
    460 			   num, (unsigned int) (end - pos));
    461 		return NULL;
    462 	}
    463 
    464 	realm = os_calloc(num, sizeof(struct nai_realm));
    465 	if (realm == NULL)
    466 		return NULL;
    467 
    468 	for (i = 0; i < num; i++) {
    469 		pos = nai_realm_parse_realm(&realm[i], pos, end);
    470 		if (pos == NULL) {
    471 			nai_realm_free(realm, num);
    472 			return NULL;
    473 		}
    474 	}
    475 
    476 	*count = num;
    477 	return realm;
    478 }
    479 
    480 
    481 static int nai_realm_match(struct nai_realm *realm, const char *home_realm)
    482 {
    483 	char *tmp, *pos, *end;
    484 	int match = 0;
    485 
    486 	if (realm->realm == NULL || home_realm == NULL)
    487 		return 0;
    488 
    489 	if (os_strchr(realm->realm, ';') == NULL)
    490 		return os_strcasecmp(realm->realm, home_realm) == 0;
    491 
    492 	tmp = os_strdup(realm->realm);
    493 	if (tmp == NULL)
    494 		return 0;
    495 
    496 	pos = tmp;
    497 	while (*pos) {
    498 		end = os_strchr(pos, ';');
    499 		if (end)
    500 			*end = '\0';
    501 		if (os_strcasecmp(pos, home_realm) == 0) {
    502 			match = 1;
    503 			break;
    504 		}
    505 		if (end == NULL)
    506 			break;
    507 		pos = end + 1;
    508 	}
    509 
    510 	os_free(tmp);
    511 
    512 	return match;
    513 }
    514 
    515 
    516 static int nai_realm_cred_username(struct nai_realm_eap *eap)
    517 {
    518 	if (eap_get_name(EAP_VENDOR_IETF, eap->method) == NULL)
    519 		return 0; /* method not supported */
    520 
    521 	if (eap->method != EAP_TYPE_TTLS && eap->method != EAP_TYPE_PEAP) {
    522 		/* Only tunneled methods with username/password supported */
    523 		return 0;
    524 	}
    525 
    526 	if (eap->method == EAP_TYPE_PEAP) {
    527 		if (eap->inner_method &&
    528 		    eap_get_name(EAP_VENDOR_IETF, eap->inner_method) == NULL)
    529 			return 0;
    530 		if (!eap->inner_method &&
    531 		    eap_get_name(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2) == NULL)
    532 			return 0;
    533 	}
    534 
    535 	if (eap->method == EAP_TYPE_TTLS) {
    536 		if (eap->inner_method == 0 && eap->inner_non_eap == 0)
    537 			return 1; /* Assume TTLS/MSCHAPv2 is used */
    538 		if (eap->inner_method &&
    539 		    eap_get_name(EAP_VENDOR_IETF, eap->inner_method) == NULL)
    540 			return 0;
    541 		if (eap->inner_non_eap &&
    542 		    eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_PAP &&
    543 		    eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_CHAP &&
    544 		    eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_MSCHAP &&
    545 		    eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_MSCHAPV2)
    546 			return 0;
    547 	}
    548 
    549 	if (eap->inner_method &&
    550 	    eap->inner_method != EAP_TYPE_GTC &&
    551 	    eap->inner_method != EAP_TYPE_MSCHAPV2)
    552 		return 0;
    553 
    554 	return 1;
    555 }
    556 
    557 
    558 static int nai_realm_cred_cert(struct nai_realm_eap *eap)
    559 {
    560 	if (eap_get_name(EAP_VENDOR_IETF, eap->method) == NULL)
    561 		return 0; /* method not supported */
    562 
    563 	if (eap->method != EAP_TYPE_TLS) {
    564 		/* Only EAP-TLS supported for credential authentication */
    565 		return 0;
    566 	}
    567 
    568 	return 1;
    569 }
    570 
    571 
    572 static struct nai_realm_eap * nai_realm_find_eap(struct wpa_cred *cred,
    573 						 struct nai_realm *realm)
    574 {
    575 	u8 e;
    576 
    577 	if (cred == NULL ||
    578 	    cred->username == NULL ||
    579 	    cred->username[0] == '\0' ||
    580 	    ((cred->password == NULL ||
    581 	      cred->password[0] == '\0') &&
    582 	     (cred->private_key == NULL ||
    583 	      cred->private_key[0] == '\0')))
    584 		return NULL;
    585 
    586 	for (e = 0; e < realm->eap_count; e++) {
    587 		struct nai_realm_eap *eap = &realm->eap[e];
    588 		if (cred->password && cred->password[0] &&
    589 		    nai_realm_cred_username(eap))
    590 			return eap;
    591 		if (cred->private_key && cred->private_key[0] &&
    592 		    nai_realm_cred_cert(eap))
    593 			return eap;
    594 	}
    595 
    596 	return NULL;
    597 }
    598 
    599 
    600 #ifdef INTERWORKING_3GPP
    601 
    602 static int plmn_id_match(struct wpabuf *anqp, const char *imsi, int mnc_len)
    603 {
    604 	u8 plmn[3];
    605 	const u8 *pos, *end;
    606 	u8 udhl;
    607 
    608 	/* See Annex A of 3GPP TS 24.234 v8.1.0 for description */
    609 	plmn[0] = (imsi[0] - '0') | ((imsi[1] - '0') << 4);
    610 	plmn[1] = imsi[2] - '0';
    611 	/* default to MNC length 3 if unknown */
    612 	if (mnc_len != 2)
    613 		plmn[1] |= (imsi[5] - '0') << 4;
    614 	else
    615 		plmn[1] |= 0xf0;
    616 	plmn[2] = (imsi[3] - '0') | ((imsi[4] - '0') << 4);
    617 
    618 	if (anqp == NULL)
    619 		return 0;
    620 	pos = wpabuf_head_u8(anqp);
    621 	end = pos + wpabuf_len(anqp);
    622 	if (pos + 2 > end)
    623 		return 0;
    624 	if (*pos != 0) {
    625 		wpa_printf(MSG_DEBUG, "Unsupported GUD version 0x%x", *pos);
    626 		return 0;
    627 	}
    628 	pos++;
    629 	udhl = *pos++;
    630 	if (pos + udhl > end) {
    631 		wpa_printf(MSG_DEBUG, "Invalid UDHL");
    632 		return 0;
    633 	}
    634 	end = pos + udhl;
    635 
    636 	while (pos + 2 <= end) {
    637 		u8 iei, len;
    638 		const u8 *l_end;
    639 		iei = *pos++;
    640 		len = *pos++ & 0x7f;
    641 		if (pos + len > end)
    642 			break;
    643 		l_end = pos + len;
    644 
    645 		if (iei == 0 && len > 0) {
    646 			/* PLMN List */
    647 			u8 num, i;
    648 			num = *pos++;
    649 			for (i = 0; i < num; i++) {
    650 				if (pos + 3 > end)
    651 					break;
    652 				if (os_memcmp(pos, plmn, 3) == 0)
    653 					return 1; /* Found matching PLMN */
    654 				pos += 3;
    655 			}
    656 		}
    657 
    658 		pos = l_end;
    659 	}
    660 
    661 	return 0;
    662 }
    663 
    664 
    665 static int build_root_nai(char *nai, size_t nai_len, const char *imsi,
    666 			  size_t mnc_len, char prefix)
    667 {
    668 	const char *sep, *msin;
    669 	char *end, *pos;
    670 	size_t msin_len, plmn_len;
    671 
    672 	/*
    673 	 * TS 23.003, Clause 14 (3GPP to WLAN Interworking)
    674 	 * Root NAI:
    675 	 * <aka:0|sim:1><IMSI>@wlan.mnc<MNC>.mcc<MCC>.3gppnetwork.org
    676 	 * <MNC> is zero-padded to three digits in case two-digit MNC is used
    677 	 */
    678 
    679 	if (imsi == NULL || os_strlen(imsi) > 16) {
    680 		wpa_printf(MSG_DEBUG, "No valid IMSI available");
    681 		return -1;
    682 	}
    683 	sep = os_strchr(imsi, '-');
    684 	if (sep) {
    685 		plmn_len = sep - imsi;
    686 		msin = sep + 1;
    687 	} else if (mnc_len && os_strlen(imsi) >= 3 + mnc_len) {
    688 		plmn_len = 3 + mnc_len;
    689 		msin = imsi + plmn_len;
    690 	} else
    691 		return -1;
    692 	if (plmn_len != 5 && plmn_len != 6)
    693 		return -1;
    694 	msin_len = os_strlen(msin);
    695 
    696 	pos = nai;
    697 	end = nai + nai_len;
    698 	if (prefix)
    699 		*pos++ = prefix;
    700 	os_memcpy(pos, imsi, plmn_len);
    701 	pos += plmn_len;
    702 	os_memcpy(pos, msin, msin_len);
    703 	pos += msin_len;
    704 	pos += os_snprintf(pos, end - pos, "@wlan.mnc");
    705 	if (plmn_len == 5) {
    706 		*pos++ = '0';
    707 		*pos++ = imsi[3];
    708 		*pos++ = imsi[4];
    709 	} else {
    710 		*pos++ = imsi[3];
    711 		*pos++ = imsi[4];
    712 		*pos++ = imsi[5];
    713 	}
    714 	pos += os_snprintf(pos, end - pos, ".mcc%c%c%c.3gppnetwork.org",
    715 			   imsi[0], imsi[1], imsi[2]);
    716 
    717 	return 0;
    718 }
    719 
    720 
    721 static int set_root_nai(struct wpa_ssid *ssid, const char *imsi, char prefix)
    722 {
    723 	char nai[100];
    724 	if (build_root_nai(nai, sizeof(nai), imsi, 0, prefix) < 0)
    725 		return -1;
    726 	return wpa_config_set_quoted(ssid, "identity", nai);
    727 }
    728 
    729 #endif /* INTERWORKING_3GPP */
    730 
    731 
    732 static int interworking_set_hs20_params(struct wpa_supplicant *wpa_s,
    733 					struct wpa_ssid *ssid)
    734 {
    735 	if (wpa_config_set(ssid, "key_mgmt",
    736 			   wpa_s->conf->pmf != NO_MGMT_FRAME_PROTECTION ?
    737 			   "WPA-EAP WPA-EAP-SHA256" : "WPA-EAP", 0) < 0)
    738 		return -1;
    739 	if (wpa_config_set(ssid, "proto", "RSN", 0) < 0)
    740 		return -1;
    741 	if (wpa_config_set(ssid, "pairwise", "CCMP", 0) < 0)
    742 		return -1;
    743 	return 0;
    744 }
    745 
    746 
    747 static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s,
    748 				     struct wpa_cred *cred,
    749 				     struct wpa_bss *bss)
    750 {
    751 #ifdef INTERWORKING_3GPP
    752 	struct wpa_ssid *ssid;
    753 	const u8 *ie;
    754 	int eap_type;
    755 	int res;
    756 	char prefix;
    757 
    758 	if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL)
    759 		return -1;
    760 
    761 	ie = wpa_bss_get_ie(bss, WLAN_EID_SSID);
    762 	if (ie == NULL)
    763 		return -1;
    764 	wpa_printf(MSG_DEBUG, "Interworking: Connect with " MACSTR " (3GPP)",
    765 		   MAC2STR(bss->bssid));
    766 
    767 	ssid = wpa_config_add_network(wpa_s->conf);
    768 	if (ssid == NULL)
    769 		return -1;
    770 	ssid->parent_cred = cred;
    771 
    772 	wpas_notify_network_added(wpa_s, ssid);
    773 	wpa_config_set_network_defaults(ssid);
    774 	ssid->priority = cred->priority;
    775 	ssid->temporary = 1;
    776 	ssid->ssid = os_zalloc(ie[1] + 1);
    777 	if (ssid->ssid == NULL)
    778 		goto fail;
    779 	os_memcpy(ssid->ssid, ie + 2, ie[1]);
    780 	ssid->ssid_len = ie[1];
    781 
    782 	if (interworking_set_hs20_params(wpa_s, ssid) < 0)
    783 		goto fail;
    784 
    785 	eap_type = EAP_TYPE_SIM;
    786 	if (cred->pcsc && wpa_s->scard && scard_supports_umts(wpa_s->scard))
    787 		eap_type = EAP_TYPE_AKA;
    788 	if (cred->eap_method && cred->eap_method[0].vendor == EAP_VENDOR_IETF) {
    789 		if (cred->eap_method[0].method == EAP_TYPE_SIM ||
    790 		    cred->eap_method[0].method == EAP_TYPE_AKA ||
    791 		    cred->eap_method[0].method == EAP_TYPE_AKA_PRIME)
    792 			eap_type = cred->eap_method[0].method;
    793 	}
    794 
    795 	switch (eap_type) {
    796 	case EAP_TYPE_SIM:
    797 		prefix = '1';
    798 		res = wpa_config_set(ssid, "eap", "SIM", 0);
    799 		break;
    800 	case EAP_TYPE_AKA:
    801 		prefix = '0';
    802 		res = wpa_config_set(ssid, "eap", "AKA", 0);
    803 		break;
    804 	case EAP_TYPE_AKA_PRIME:
    805 		prefix = '6';
    806 		res = wpa_config_set(ssid, "eap", "AKA'", 0);
    807 		break;
    808 	default:
    809 		res = -1;
    810 		break;
    811 	}
    812 	if (res < 0) {
    813 		wpa_printf(MSG_DEBUG, "Selected EAP method (%d) not supported",
    814 			   eap_type);
    815 		goto fail;
    816 	}
    817 
    818 	if (!cred->pcsc && set_root_nai(ssid, cred->imsi, prefix) < 0) {
    819 		wpa_printf(MSG_DEBUG, "Failed to set Root NAI");
    820 		goto fail;
    821 	}
    822 
    823 	if (cred->milenage && cred->milenage[0]) {
    824 		if (wpa_config_set_quoted(ssid, "password",
    825 					  cred->milenage) < 0)
    826 			goto fail;
    827 	} else if (cred->pcsc) {
    828 		if (wpa_config_set_quoted(ssid, "pcsc", "") < 0)
    829 			goto fail;
    830 		if (wpa_s->conf->pcsc_pin &&
    831 		    wpa_config_set_quoted(ssid, "pin", wpa_s->conf->pcsc_pin)
    832 		    < 0)
    833 			goto fail;
    834 	}
    835 
    836 	if (cred->password && cred->password[0] &&
    837 	    wpa_config_set_quoted(ssid, "password", cred->password) < 0)
    838 		goto fail;
    839 
    840 	wpa_config_update_prio_list(wpa_s->conf);
    841 	interworking_reconnect(wpa_s);
    842 
    843 	return 0;
    844 
    845 fail:
    846 	wpas_notify_network_removed(wpa_s, ssid);
    847 	wpa_config_remove_network(wpa_s->conf, ssid->id);
    848 #endif /* INTERWORKING_3GPP */
    849 	return -1;
    850 }
    851 
    852 
    853 static int roaming_consortium_element_match(const u8 *ie, const u8 *rc_id,
    854 					    size_t rc_len)
    855 {
    856 	const u8 *pos, *end;
    857 	u8 lens;
    858 
    859 	if (ie == NULL)
    860 		return 0;
    861 
    862 	pos = ie + 2;
    863 	end = ie + 2 + ie[1];
    864 
    865 	/* Roaming Consortium element:
    866 	 * Number of ANQP OIs
    867 	 * OI #1 and #2 lengths
    868 	 * OI #1, [OI #2], [OI #3]
    869 	 */
    870 
    871 	if (pos + 2 > end)
    872 		return 0;
    873 
    874 	pos++; /* skip Number of ANQP OIs */
    875 	lens = *pos++;
    876 	if (pos + (lens & 0x0f) + (lens >> 4) > end)
    877 		return 0;
    878 
    879 	if ((lens & 0x0f) == rc_len && os_memcmp(pos, rc_id, rc_len) == 0)
    880 		return 1;
    881 	pos += lens & 0x0f;
    882 
    883 	if ((lens >> 4) == rc_len && os_memcmp(pos, rc_id, rc_len) == 0)
    884 		return 1;
    885 	pos += lens >> 4;
    886 
    887 	if (pos < end && (size_t) (end - pos) == rc_len &&
    888 	    os_memcmp(pos, rc_id, rc_len) == 0)
    889 		return 1;
    890 
    891 	return 0;
    892 }
    893 
    894 
    895 static int roaming_consortium_anqp_match(const struct wpabuf *anqp,
    896 					 const u8 *rc_id, size_t rc_len)
    897 {
    898 	const u8 *pos, *end;
    899 	u8 len;
    900 
    901 	if (anqp == NULL)
    902 		return 0;
    903 
    904 	pos = wpabuf_head(anqp);
    905 	end = pos + wpabuf_len(anqp);
    906 
    907 	/* Set of <OI Length, OI> duples */
    908 	while (pos < end) {
    909 		len = *pos++;
    910 		if (pos + len > end)
    911 			break;
    912 		if (len == rc_len && os_memcmp(pos, rc_id, rc_len) == 0)
    913 			return 1;
    914 		pos += len;
    915 	}
    916 
    917 	return 0;
    918 }
    919 
    920 
    921 static int roaming_consortium_match(const u8 *ie, const struct wpabuf *anqp,
    922 				    const u8 *rc_id, size_t rc_len)
    923 {
    924 	return roaming_consortium_element_match(ie, rc_id, rc_len) ||
    925 		roaming_consortium_anqp_match(anqp, rc_id, rc_len);
    926 }
    927 
    928 
    929 static int cred_excluded_ssid(struct wpa_cred *cred, struct wpa_bss *bss)
    930 {
    931 	size_t i;
    932 
    933 	if (!cred->excluded_ssid)
    934 		return 0;
    935 
    936 	for (i = 0; i < cred->num_excluded_ssid; i++) {
    937 		struct excluded_ssid *e = &cred->excluded_ssid[i];
    938 		if (bss->ssid_len == e->ssid_len &&
    939 		    os_memcmp(bss->ssid, e->ssid, e->ssid_len) == 0)
    940 			return 1;
    941 	}
    942 
    943 	return 0;
    944 }
    945 
    946 
    947 static struct wpa_cred * interworking_credentials_available_roaming_consortium(
    948 	struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
    949 {
    950 	struct wpa_cred *cred, *selected = NULL;
    951 	const u8 *ie;
    952 
    953 	ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM);
    954 
    955 	if (ie == NULL &&
    956 	    (bss->anqp == NULL || bss->anqp->roaming_consortium == NULL))
    957 		return NULL;
    958 
    959 	if (wpa_s->conf->cred == NULL)
    960 		return NULL;
    961 
    962 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
    963 		if (cred->roaming_consortium_len == 0)
    964 			continue;
    965 
    966 		if (!roaming_consortium_match(ie,
    967 					      bss->anqp ?
    968 					      bss->anqp->roaming_consortium :
    969 					      NULL,
    970 					      cred->roaming_consortium,
    971 					      cred->roaming_consortium_len))
    972 			continue;
    973 
    974 		if (cred_excluded_ssid(cred, bss))
    975 			continue;
    976 
    977 		if (selected == NULL ||
    978 		    selected->priority < cred->priority)
    979 			selected = cred;
    980 	}
    981 
    982 	return selected;
    983 }
    984 
    985 
    986 static int interworking_set_eap_params(struct wpa_ssid *ssid,
    987 				       struct wpa_cred *cred, int ttls)
    988 {
    989 	if (cred->eap_method) {
    990 		ttls = cred->eap_method->vendor == EAP_VENDOR_IETF &&
    991 			cred->eap_method->method == EAP_TYPE_TTLS;
    992 
    993 		os_free(ssid->eap.eap_methods);
    994 		ssid->eap.eap_methods =
    995 			os_malloc(sizeof(struct eap_method_type) * 2);
    996 		if (ssid->eap.eap_methods == NULL)
    997 			return -1;
    998 		os_memcpy(ssid->eap.eap_methods, cred->eap_method,
    999 			  sizeof(*cred->eap_method));
   1000 		ssid->eap.eap_methods[1].vendor = EAP_VENDOR_IETF;
   1001 		ssid->eap.eap_methods[1].method = EAP_TYPE_NONE;
   1002 	}
   1003 
   1004 	if (ttls && cred->username && cred->username[0]) {
   1005 		const char *pos;
   1006 		char *anon;
   1007 		/* Use anonymous NAI in Phase 1 */
   1008 		pos = os_strchr(cred->username, '@');
   1009 		if (pos) {
   1010 			size_t buflen = 9 + os_strlen(pos) + 1;
   1011 			anon = os_malloc(buflen);
   1012 			if (anon == NULL)
   1013 				return -1;
   1014 			os_snprintf(anon, buflen, "anonymous%s", pos);
   1015 		} else if (cred->realm) {
   1016 			size_t buflen = 10 + os_strlen(cred->realm) + 1;
   1017 			anon = os_malloc(buflen);
   1018 			if (anon == NULL)
   1019 				return -1;
   1020 			os_snprintf(anon, buflen, "anonymous@%s", cred->realm);
   1021 		} else {
   1022 			anon = os_strdup("anonymous");
   1023 			if (anon == NULL)
   1024 				return -1;
   1025 		}
   1026 		if (wpa_config_set_quoted(ssid, "anonymous_identity", anon) <
   1027 		    0) {
   1028 			os_free(anon);
   1029 			return -1;
   1030 		}
   1031 		os_free(anon);
   1032 	}
   1033 
   1034 	if (cred->username && cred->username[0] &&
   1035 	    wpa_config_set_quoted(ssid, "identity", cred->username) < 0)
   1036 		return -1;
   1037 
   1038 	if (cred->password && cred->password[0]) {
   1039 		if (cred->ext_password &&
   1040 		    wpa_config_set(ssid, "password", cred->password, 0) < 0)
   1041 			return -1;
   1042 		if (!cred->ext_password &&
   1043 		    wpa_config_set_quoted(ssid, "password", cred->password) <
   1044 		    0)
   1045 			return -1;
   1046 	}
   1047 
   1048 	if (cred->client_cert && cred->client_cert[0] &&
   1049 	    wpa_config_set_quoted(ssid, "client_cert", cred->client_cert) < 0)
   1050 		return -1;
   1051 
   1052 #ifdef ANDROID
   1053 	if (cred->private_key &&
   1054 	    os_strncmp(cred->private_key, "keystore://", 11) == 0) {
   1055 		/* Use OpenSSL engine configuration for Android keystore */
   1056 		if (wpa_config_set_quoted(ssid, "engine_id", "keystore") < 0 ||
   1057 		    wpa_config_set_quoted(ssid, "key_id",
   1058 					  cred->private_key + 11) < 0 ||
   1059 		    wpa_config_set(ssid, "engine", "1", 0) < 0)
   1060 			return -1;
   1061 	} else
   1062 #endif /* ANDROID */
   1063 	if (cred->private_key && cred->private_key[0] &&
   1064 	    wpa_config_set_quoted(ssid, "private_key", cred->private_key) < 0)
   1065 		return -1;
   1066 
   1067 	if (cred->private_key_passwd && cred->private_key_passwd[0] &&
   1068 	    wpa_config_set_quoted(ssid, "private_key_passwd",
   1069 				  cred->private_key_passwd) < 0)
   1070 		return -1;
   1071 
   1072 	if (cred->phase1) {
   1073 		os_free(ssid->eap.phase1);
   1074 		ssid->eap.phase1 = os_strdup(cred->phase1);
   1075 	}
   1076 	if (cred->phase2) {
   1077 		os_free(ssid->eap.phase2);
   1078 		ssid->eap.phase2 = os_strdup(cred->phase2);
   1079 	}
   1080 
   1081 	if (cred->ca_cert && cred->ca_cert[0] &&
   1082 	    wpa_config_set_quoted(ssid, "ca_cert", cred->ca_cert) < 0)
   1083 		return -1;
   1084 
   1085 	return 0;
   1086 }
   1087 
   1088 
   1089 static int interworking_connect_roaming_consortium(
   1090 	struct wpa_supplicant *wpa_s, struct wpa_cred *cred,
   1091 	struct wpa_bss *bss, const u8 *ssid_ie)
   1092 {
   1093 	struct wpa_ssid *ssid;
   1094 
   1095 	wpa_printf(MSG_DEBUG, "Interworking: Connect with " MACSTR " based on "
   1096 		   "roaming consortium match", MAC2STR(bss->bssid));
   1097 
   1098 	ssid = wpa_config_add_network(wpa_s->conf);
   1099 	if (ssid == NULL)
   1100 		return -1;
   1101 	ssid->parent_cred = cred;
   1102 	wpas_notify_network_added(wpa_s, ssid);
   1103 	wpa_config_set_network_defaults(ssid);
   1104 	ssid->priority = cred->priority;
   1105 	ssid->temporary = 1;
   1106 	ssid->ssid = os_zalloc(ssid_ie[1] + 1);
   1107 	if (ssid->ssid == NULL)
   1108 		goto fail;
   1109 	os_memcpy(ssid->ssid, ssid_ie + 2, ssid_ie[1]);
   1110 	ssid->ssid_len = ssid_ie[1];
   1111 
   1112 	if (interworking_set_hs20_params(wpa_s, ssid) < 0)
   1113 		goto fail;
   1114 
   1115 	if (cred->eap_method == NULL) {
   1116 		wpa_printf(MSG_DEBUG, "Interworking: No EAP method set for "
   1117 			   "credential using roaming consortium");
   1118 		goto fail;
   1119 	}
   1120 
   1121 	if (interworking_set_eap_params(
   1122 		    ssid, cred,
   1123 		    cred->eap_method->vendor == EAP_VENDOR_IETF &&
   1124 		    cred->eap_method->method == EAP_TYPE_TTLS) < 0)
   1125 		goto fail;
   1126 
   1127 	wpa_config_update_prio_list(wpa_s->conf);
   1128 	interworking_reconnect(wpa_s);
   1129 
   1130 	return 0;
   1131 
   1132 fail:
   1133 	wpas_notify_network_removed(wpa_s, ssid);
   1134 	wpa_config_remove_network(wpa_s->conf, ssid->id);
   1135 	return -1;
   1136 }
   1137 
   1138 
   1139 int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
   1140 {
   1141 	struct wpa_cred *cred, *cred_rc, *cred_3gpp;
   1142 	struct wpa_ssid *ssid;
   1143 	struct nai_realm *realm;
   1144 	struct nai_realm_eap *eap = NULL;
   1145 	u16 count, i;
   1146 	char buf[100];
   1147 	const u8 *ie;
   1148 
   1149 	if (wpa_s->conf->cred == NULL || bss == NULL)
   1150 		return -1;
   1151 	ie = wpa_bss_get_ie(bss, WLAN_EID_SSID);
   1152 	if (ie == NULL || ie[1] == 0) {
   1153 		wpa_printf(MSG_DEBUG, "Interworking: No SSID known for "
   1154 			   MACSTR, MAC2STR(bss->bssid));
   1155 		return -1;
   1156 	}
   1157 
   1158 	if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) {
   1159 		/*
   1160 		 * We currently support only HS 2.0 networks and those are
   1161 		 * required to use WPA2-Enterprise.
   1162 		 */
   1163 		wpa_printf(MSG_DEBUG, "Interworking: Network does not use "
   1164 			   "RSN");
   1165 		return -1;
   1166 	}
   1167 
   1168 	cred_rc = interworking_credentials_available_roaming_consortium(wpa_s,
   1169 									bss);
   1170 	if (cred_rc) {
   1171 		wpa_printf(MSG_DEBUG, "Interworking: Highest roaming "
   1172 			   "consortium matching credential priority %d",
   1173 			   cred_rc->priority);
   1174 	}
   1175 
   1176 	cred = interworking_credentials_available_realm(wpa_s, bss);
   1177 	if (cred) {
   1178 		wpa_printf(MSG_DEBUG, "Interworking: Highest NAI Realm list "
   1179 			   "matching credential priority %d",
   1180 			   cred->priority);
   1181 	}
   1182 
   1183 	cred_3gpp = interworking_credentials_available_3gpp(wpa_s, bss);
   1184 	if (cred_3gpp) {
   1185 		wpa_printf(MSG_DEBUG, "Interworking: Highest 3GPP matching "
   1186 			   "credential priority %d", cred_3gpp->priority);
   1187 	}
   1188 
   1189 	if (cred_rc &&
   1190 	    (cred == NULL || cred_rc->priority >= cred->priority) &&
   1191 	    (cred_3gpp == NULL || cred_rc->priority >= cred_3gpp->priority))
   1192 		return interworking_connect_roaming_consortium(wpa_s, cred_rc,
   1193 							       bss, ie);
   1194 
   1195 	if (cred_3gpp &&
   1196 	    (cred == NULL || cred_3gpp->priority >= cred->priority)) {
   1197 		return interworking_connect_3gpp(wpa_s, cred_3gpp, bss);
   1198 	}
   1199 
   1200 	if (cred == NULL) {
   1201 		wpa_printf(MSG_DEBUG, "Interworking: No matching credentials "
   1202 			   "found for " MACSTR, MAC2STR(bss->bssid));
   1203 		return -1;
   1204 	}
   1205 
   1206 	realm = nai_realm_parse(bss->anqp ? bss->anqp->nai_realm : NULL,
   1207 				&count);
   1208 	if (realm == NULL) {
   1209 		wpa_printf(MSG_DEBUG, "Interworking: Could not parse NAI "
   1210 			   "Realm list from " MACSTR, MAC2STR(bss->bssid));
   1211 		return -1;
   1212 	}
   1213 
   1214 	for (i = 0; i < count; i++) {
   1215 		if (!nai_realm_match(&realm[i], cred->realm))
   1216 			continue;
   1217 		eap = nai_realm_find_eap(cred, &realm[i]);
   1218 		if (eap)
   1219 			break;
   1220 	}
   1221 
   1222 	if (!eap) {
   1223 		wpa_printf(MSG_DEBUG, "Interworking: No matching credentials "
   1224 			   "and EAP method found for " MACSTR,
   1225 			   MAC2STR(bss->bssid));
   1226 		nai_realm_free(realm, count);
   1227 		return -1;
   1228 	}
   1229 
   1230 	wpa_printf(MSG_DEBUG, "Interworking: Connect with " MACSTR,
   1231 		   MAC2STR(bss->bssid));
   1232 
   1233 	ssid = wpa_config_add_network(wpa_s->conf);
   1234 	if (ssid == NULL) {
   1235 		nai_realm_free(realm, count);
   1236 		return -1;
   1237 	}
   1238 	ssid->parent_cred = cred;
   1239 	wpas_notify_network_added(wpa_s, ssid);
   1240 	wpa_config_set_network_defaults(ssid);
   1241 	ssid->priority = cred->priority;
   1242 	ssid->temporary = 1;
   1243 	ssid->ssid = os_zalloc(ie[1] + 1);
   1244 	if (ssid->ssid == NULL)
   1245 		goto fail;
   1246 	os_memcpy(ssid->ssid, ie + 2, ie[1]);
   1247 	ssid->ssid_len = ie[1];
   1248 
   1249 	if (interworking_set_hs20_params(wpa_s, ssid) < 0)
   1250 		goto fail;
   1251 
   1252 	if (wpa_config_set(ssid, "eap", eap_get_name(EAP_VENDOR_IETF,
   1253 						     eap->method), 0) < 0)
   1254 		goto fail;
   1255 
   1256 	switch (eap->method) {
   1257 	case EAP_TYPE_TTLS:
   1258 		if (eap->inner_method) {
   1259 			os_snprintf(buf, sizeof(buf), "\"autheap=%s\"",
   1260 				    eap_get_name(EAP_VENDOR_IETF,
   1261 						 eap->inner_method));
   1262 			if (wpa_config_set(ssid, "phase2", buf, 0) < 0)
   1263 				goto fail;
   1264 			break;
   1265 		}
   1266 		switch (eap->inner_non_eap) {
   1267 		case NAI_REALM_INNER_NON_EAP_PAP:
   1268 			if (wpa_config_set(ssid, "phase2", "\"auth=PAP\"", 0) <
   1269 			    0)
   1270 				goto fail;
   1271 			break;
   1272 		case NAI_REALM_INNER_NON_EAP_CHAP:
   1273 			if (wpa_config_set(ssid, "phase2", "\"auth=CHAP\"", 0)
   1274 			    < 0)
   1275 				goto fail;
   1276 			break;
   1277 		case NAI_REALM_INNER_NON_EAP_MSCHAP:
   1278 			if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAP\"",
   1279 					   0) < 0)
   1280 				goto fail;
   1281 			break;
   1282 		case NAI_REALM_INNER_NON_EAP_MSCHAPV2:
   1283 			if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAPV2\"",
   1284 					   0) < 0)
   1285 				goto fail;
   1286 			break;
   1287 		default:
   1288 			/* EAP params were not set - assume TTLS/MSCHAPv2 */
   1289 			if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAPV2\"",
   1290 					   0) < 0)
   1291 				goto fail;
   1292 			break;
   1293 		}
   1294 		break;
   1295 	case EAP_TYPE_PEAP:
   1296 		os_snprintf(buf, sizeof(buf), "\"auth=%s\"",
   1297 			    eap_get_name(EAP_VENDOR_IETF,
   1298 					 eap->inner_method ?
   1299 					 eap->inner_method :
   1300 					 EAP_TYPE_MSCHAPV2));
   1301 		if (wpa_config_set(ssid, "phase2", buf, 0) < 0)
   1302 			goto fail;
   1303 		break;
   1304 	case EAP_TYPE_TLS:
   1305 		break;
   1306 	}
   1307 
   1308 	if (interworking_set_eap_params(ssid, cred,
   1309 					eap->method == EAP_TYPE_TTLS) < 0)
   1310 		goto fail;
   1311 
   1312 	nai_realm_free(realm, count);
   1313 
   1314 	wpa_config_update_prio_list(wpa_s->conf);
   1315 	interworking_reconnect(wpa_s);
   1316 
   1317 	return 0;
   1318 
   1319 fail:
   1320 	wpas_notify_network_removed(wpa_s, ssid);
   1321 	wpa_config_remove_network(wpa_s->conf, ssid->id);
   1322 	nai_realm_free(realm, count);
   1323 	return -1;
   1324 }
   1325 
   1326 
   1327 static struct wpa_cred * interworking_credentials_available_3gpp(
   1328 	struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
   1329 {
   1330 	struct wpa_cred *selected = NULL;
   1331 #ifdef INTERWORKING_3GPP
   1332 	struct wpa_cred *cred;
   1333 	int ret;
   1334 
   1335 	if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL)
   1336 		return NULL;
   1337 
   1338 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
   1339 		char *sep;
   1340 		const char *imsi;
   1341 		int mnc_len;
   1342 
   1343 #ifdef PCSC_FUNCS
   1344 		if (cred->pcsc && wpa_s->conf->pcsc_reader && wpa_s->scard &&
   1345 		    wpa_s->imsi[0]) {
   1346 			imsi = wpa_s->imsi;
   1347 			mnc_len = wpa_s->mnc_len;
   1348 			goto compare;
   1349 		}
   1350 #endif /* PCSC_FUNCS */
   1351 
   1352 		if (cred->imsi == NULL || !cred->imsi[0] ||
   1353 		    cred->milenage == NULL || !cred->milenage[0])
   1354 			continue;
   1355 
   1356 		sep = os_strchr(cred->imsi, '-');
   1357 		if (sep == NULL ||
   1358 		    (sep - cred->imsi != 5 && sep - cred->imsi != 6))
   1359 			continue;
   1360 		mnc_len = sep - cred->imsi - 3;
   1361 		imsi = cred->imsi;
   1362 
   1363 #ifdef PCSC_FUNCS
   1364 	compare:
   1365 #endif /* PCSC_FUNCS */
   1366 		wpa_printf(MSG_DEBUG, "Interworking: Parsing 3GPP info from "
   1367 			   MACSTR, MAC2STR(bss->bssid));
   1368 		ret = plmn_id_match(bss->anqp->anqp_3gpp, imsi, mnc_len);
   1369 		wpa_printf(MSG_DEBUG, "PLMN match %sfound", ret ? "" : "not ");
   1370 		if (ret) {
   1371 			if (cred_excluded_ssid(cred, bss))
   1372 				continue;
   1373 			if (selected == NULL ||
   1374 			    selected->priority < cred->priority)
   1375 				selected = cred;
   1376 		}
   1377 	}
   1378 #endif /* INTERWORKING_3GPP */
   1379 	return selected;
   1380 }
   1381 
   1382 
   1383 static struct wpa_cred * interworking_credentials_available_realm(
   1384 	struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
   1385 {
   1386 	struct wpa_cred *cred, *selected = NULL;
   1387 	struct nai_realm *realm;
   1388 	u16 count, i;
   1389 
   1390 	if (bss->anqp == NULL || bss->anqp->nai_realm == NULL)
   1391 		return NULL;
   1392 
   1393 	if (wpa_s->conf->cred == NULL)
   1394 		return NULL;
   1395 
   1396 	wpa_printf(MSG_DEBUG, "Interworking: Parsing NAI Realm list from "
   1397 		   MACSTR, MAC2STR(bss->bssid));
   1398 	realm = nai_realm_parse(bss->anqp->nai_realm, &count);
   1399 	if (realm == NULL) {
   1400 		wpa_printf(MSG_DEBUG, "Interworking: Could not parse NAI "
   1401 			   "Realm list from " MACSTR, MAC2STR(bss->bssid));
   1402 		return NULL;
   1403 	}
   1404 
   1405 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
   1406 		if (cred->realm == NULL)
   1407 			continue;
   1408 
   1409 		for (i = 0; i < count; i++) {
   1410 			if (!nai_realm_match(&realm[i], cred->realm))
   1411 				continue;
   1412 			if (nai_realm_find_eap(cred, &realm[i])) {
   1413 				if (cred_excluded_ssid(cred, bss))
   1414 					continue;
   1415 				if (selected == NULL ||
   1416 				    selected->priority < cred->priority)
   1417 					selected = cred;
   1418 				break;
   1419 			}
   1420 		}
   1421 	}
   1422 
   1423 	nai_realm_free(realm, count);
   1424 
   1425 	return selected;
   1426 }
   1427 
   1428 
   1429 static struct wpa_cred * interworking_credentials_available(
   1430 	struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
   1431 {
   1432 	struct wpa_cred *cred, *cred2;
   1433 
   1434 	cred = interworking_credentials_available_realm(wpa_s, bss);
   1435 	cred2 = interworking_credentials_available_3gpp(wpa_s, bss);
   1436 	if (cred && cred2 && cred2->priority >= cred->priority)
   1437 		cred = cred2;
   1438 	if (!cred)
   1439 		cred = cred2;
   1440 
   1441 	cred2 = interworking_credentials_available_roaming_consortium(wpa_s,
   1442 								      bss);
   1443 	if (cred && cred2 && cred2->priority >= cred->priority)
   1444 		cred = cred2;
   1445 	if (!cred)
   1446 		cred = cred2;
   1447 
   1448 	return cred;
   1449 }
   1450 
   1451 
   1452 static int domain_name_list_contains(struct wpabuf *domain_names,
   1453 				     const char *domain)
   1454 {
   1455 	const u8 *pos, *end;
   1456 	size_t len;
   1457 
   1458 	len = os_strlen(domain);
   1459 	pos = wpabuf_head(domain_names);
   1460 	end = pos + wpabuf_len(domain_names);
   1461 
   1462 	while (pos + 1 < end) {
   1463 		if (pos + 1 + pos[0] > end)
   1464 			break;
   1465 
   1466 		wpa_hexdump_ascii(MSG_DEBUG, "Interworking: AP domain name",
   1467 				  pos + 1, pos[0]);
   1468 		if (pos[0] == len &&
   1469 		    os_strncasecmp(domain, (const char *) (pos + 1), len) == 0)
   1470 			return 1;
   1471 
   1472 		pos += 1 + pos[0];
   1473 	}
   1474 
   1475 	return 0;
   1476 }
   1477 
   1478 
   1479 int interworking_home_sp_cred(struct wpa_supplicant *wpa_s,
   1480 			      struct wpa_cred *cred,
   1481 			      struct wpabuf *domain_names)
   1482 {
   1483 #ifdef INTERWORKING_3GPP
   1484 	char nai[100], *realm;
   1485 
   1486 	char *imsi = NULL;
   1487 	int mnc_len = 0;
   1488 	if (cred->imsi)
   1489 		imsi = cred->imsi;
   1490 #ifdef CONFIG_PCSC
   1491 	else if (cred->pcsc && wpa_s->conf->pcsc_reader &&
   1492 		 wpa_s->scard && wpa_s->imsi[0]) {
   1493 		imsi = wpa_s->imsi;
   1494 		mnc_len = wpa_s->mnc_len;
   1495 	}
   1496 #endif /* CONFIG_PCSC */
   1497 	if (domain_names &&
   1498 	    imsi && build_root_nai(nai, sizeof(nai), imsi, mnc_len, 0) == 0) {
   1499 		realm = os_strchr(nai, '@');
   1500 		if (realm)
   1501 			realm++;
   1502 		wpa_printf(MSG_DEBUG, "Interworking: Search for match "
   1503 			   "with SIM/USIM domain %s", realm);
   1504 		if (realm &&
   1505 		    domain_name_list_contains(domain_names, realm))
   1506 			return 1;
   1507 	}
   1508 #endif /* INTERWORKING_3GPP */
   1509 
   1510 	if (domain_names == NULL || cred->domain == NULL)
   1511 		return 0;
   1512 
   1513 	wpa_printf(MSG_DEBUG, "Interworking: Search for match with "
   1514 		   "home SP FQDN %s", cred->domain);
   1515 	if (domain_name_list_contains(domain_names, cred->domain))
   1516 		return 1;
   1517 
   1518 	return 0;
   1519 }
   1520 
   1521 
   1522 static int interworking_home_sp(struct wpa_supplicant *wpa_s,
   1523 				struct wpabuf *domain_names)
   1524 {
   1525 	struct wpa_cred *cred;
   1526 
   1527 	if (domain_names == NULL || wpa_s->conf->cred == NULL)
   1528 		return -1;
   1529 
   1530 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
   1531 		int res = interworking_home_sp_cred(wpa_s, cred, domain_names);
   1532 		if (res)
   1533 			return res;
   1534 	}
   1535 
   1536 	return 0;
   1537 }
   1538 
   1539 
   1540 static int interworking_find_network_match(struct wpa_supplicant *wpa_s)
   1541 {
   1542 	struct wpa_bss *bss;
   1543 	struct wpa_ssid *ssid;
   1544 
   1545 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
   1546 		for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
   1547 			if (wpas_network_disabled(wpa_s, ssid) ||
   1548 			    ssid->mode != WPAS_MODE_INFRA)
   1549 				continue;
   1550 			if (ssid->ssid_len != bss->ssid_len ||
   1551 			    os_memcmp(ssid->ssid, bss->ssid, ssid->ssid_len) !=
   1552 			    0)
   1553 				continue;
   1554 			/*
   1555 			 * TODO: Consider more accurate matching of security
   1556 			 * configuration similarly to what is done in events.c
   1557 			 */
   1558 			return 1;
   1559 		}
   1560 	}
   1561 
   1562 	return 0;
   1563 }
   1564 
   1565 
   1566 static void interworking_select_network(struct wpa_supplicant *wpa_s)
   1567 {
   1568 	struct wpa_bss *bss, *selected = NULL, *selected_home = NULL;
   1569 	int selected_prio = -999999, selected_home_prio = -999999;
   1570 	unsigned int count = 0;
   1571 	const char *type;
   1572 	int res;
   1573 	struct wpa_cred *cred;
   1574 
   1575 	wpa_s->network_select = 0;
   1576 
   1577 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
   1578 		cred = interworking_credentials_available(wpa_s, bss);
   1579 		if (!cred)
   1580 			continue;
   1581 		if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) {
   1582 			/*
   1583 			 * We currently support only HS 2.0 networks and those
   1584 			 * are required to use WPA2-Enterprise.
   1585 			 */
   1586 			wpa_printf(MSG_DEBUG, "Interworking: Credential match "
   1587 				   "with " MACSTR " but network does not use "
   1588 				   "RSN", MAC2STR(bss->bssid));
   1589 			continue;
   1590 		}
   1591 		count++;
   1592 		res = interworking_home_sp(wpa_s, bss->anqp ?
   1593 					   bss->anqp->domain_name : NULL);
   1594 		if (res > 0)
   1595 			type = "home";
   1596 		else if (res == 0)
   1597 			type = "roaming";
   1598 		else
   1599 			type = "unknown";
   1600 		wpa_msg(wpa_s, MSG_INFO, INTERWORKING_AP MACSTR " type=%s",
   1601 			MAC2STR(bss->bssid), type);
   1602 		if (wpa_s->auto_select ||
   1603 		    (wpa_s->conf->auto_interworking &&
   1604 		     wpa_s->auto_network_select)) {
   1605 			if (selected == NULL ||
   1606 			    cred->priority > selected_prio) {
   1607 				selected = bss;
   1608 				selected_prio = cred->priority;
   1609 			}
   1610 			if (res > 0 &&
   1611 			    (selected_home == NULL ||
   1612 			     cred->priority > selected_home_prio)) {
   1613 				selected_home = bss;
   1614 				selected_home_prio = cred->priority;
   1615 			}
   1616 		}
   1617 	}
   1618 
   1619 	if (selected_home && selected_home != selected &&
   1620 	    selected_home_prio >= selected_prio) {
   1621 		/* Prefer network operated by the Home SP */
   1622 		selected = selected_home;
   1623 	}
   1624 
   1625 	if (count == 0) {
   1626 		/*
   1627 		 * No matching network was found based on configured
   1628 		 * credentials. Check whether any of the enabled network blocks
   1629 		 * have matching APs.
   1630 		 */
   1631 		if (interworking_find_network_match(wpa_s)) {
   1632 			wpa_printf(MSG_DEBUG, "Interworking: Possible BSS "
   1633 				   "match for enabled network configurations");
   1634 			if (wpa_s->auto_select)
   1635 				interworking_reconnect(wpa_s);
   1636 			return;
   1637 		}
   1638 
   1639 		if (wpa_s->auto_network_select) {
   1640 			wpa_printf(MSG_DEBUG, "Interworking: Continue "
   1641 				   "scanning after ANQP fetch");
   1642 			wpa_supplicant_req_scan(wpa_s, wpa_s->scan_interval,
   1643 						0);
   1644 			return;
   1645 		}
   1646 
   1647 		wpa_msg(wpa_s, MSG_INFO, INTERWORKING_NO_MATCH "No network "
   1648 			"with matching credentials found");
   1649 	}
   1650 
   1651 	if (selected)
   1652 		interworking_connect(wpa_s, selected);
   1653 }
   1654 
   1655 
   1656 static struct wpa_bss_anqp *
   1657 interworking_match_anqp_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
   1658 {
   1659 	struct wpa_bss *other;
   1660 
   1661 	if (is_zero_ether_addr(bss->hessid))
   1662 		return NULL; /* Cannot be in the same homegenous ESS */
   1663 
   1664 	dl_list_for_each(other, &wpa_s->bss, struct wpa_bss, list) {
   1665 		if (other == bss)
   1666 			continue;
   1667 		if (other->anqp == NULL)
   1668 			continue;
   1669 		if (other->anqp->roaming_consortium == NULL &&
   1670 		    other->anqp->nai_realm == NULL &&
   1671 		    other->anqp->anqp_3gpp == NULL &&
   1672 		    other->anqp->domain_name == NULL)
   1673 			continue;
   1674 		if (!(other->flags & WPA_BSS_ANQP_FETCH_TRIED))
   1675 			continue;
   1676 		if (os_memcmp(bss->hessid, other->hessid, ETH_ALEN) != 0)
   1677 			continue;
   1678 		if (bss->ssid_len != other->ssid_len ||
   1679 		    os_memcmp(bss->ssid, other->ssid, bss->ssid_len) != 0)
   1680 			continue;
   1681 
   1682 		wpa_printf(MSG_DEBUG, "Interworking: Share ANQP data with "
   1683 			   "already fetched BSSID " MACSTR " and " MACSTR,
   1684 			   MAC2STR(other->bssid), MAC2STR(bss->bssid));
   1685 		other->anqp->users++;
   1686 		return other->anqp;
   1687 	}
   1688 
   1689 	return NULL;
   1690 }
   1691 
   1692 
   1693 static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s)
   1694 {
   1695 	struct wpa_bss *bss;
   1696 	int found = 0;
   1697 	const u8 *ie;
   1698 
   1699 	if (eloop_terminated() || !wpa_s->fetch_anqp_in_progress)
   1700 		return;
   1701 
   1702 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
   1703 		if (!(bss->caps & IEEE80211_CAP_ESS))
   1704 			continue;
   1705 		ie = wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB);
   1706 		if (ie == NULL || ie[1] < 4 || !(ie[5] & 0x80))
   1707 			continue; /* AP does not support Interworking */
   1708 
   1709 		if (!(bss->flags & WPA_BSS_ANQP_FETCH_TRIED)) {
   1710 			if (bss->anqp == NULL) {
   1711 				bss->anqp = interworking_match_anqp_info(wpa_s,
   1712 									 bss);
   1713 				if (bss->anqp) {
   1714 					/* Shared data already fetched */
   1715 					continue;
   1716 				}
   1717 				bss->anqp = wpa_bss_anqp_alloc();
   1718 				if (bss->anqp == NULL)
   1719 					break;
   1720 			}
   1721 			found++;
   1722 			bss->flags |= WPA_BSS_ANQP_FETCH_TRIED;
   1723 			wpa_msg(wpa_s, MSG_INFO, "Starting ANQP fetch for "
   1724 				MACSTR, MAC2STR(bss->bssid));
   1725 			interworking_anqp_send_req(wpa_s, bss);
   1726 			break;
   1727 		}
   1728 	}
   1729 
   1730 	if (found == 0) {
   1731 		wpa_msg(wpa_s, MSG_INFO, "ANQP fetch completed");
   1732 		wpa_s->fetch_anqp_in_progress = 0;
   1733 		if (wpa_s->network_select)
   1734 			interworking_select_network(wpa_s);
   1735 	}
   1736 }
   1737 
   1738 
   1739 void interworking_start_fetch_anqp(struct wpa_supplicant *wpa_s)
   1740 {
   1741 	struct wpa_bss *bss;
   1742 
   1743 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list)
   1744 		bss->flags &= ~WPA_BSS_ANQP_FETCH_TRIED;
   1745 
   1746 	wpa_s->fetch_anqp_in_progress = 1;
   1747 	interworking_next_anqp_fetch(wpa_s);
   1748 }
   1749 
   1750 
   1751 int interworking_fetch_anqp(struct wpa_supplicant *wpa_s)
   1752 {
   1753 	if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select)
   1754 		return 0;
   1755 
   1756 	wpa_s->network_select = 0;
   1757 	wpa_s->fetch_all_anqp = 1;
   1758 
   1759 	interworking_start_fetch_anqp(wpa_s);
   1760 
   1761 	return 0;
   1762 }
   1763 
   1764 
   1765 void interworking_stop_fetch_anqp(struct wpa_supplicant *wpa_s)
   1766 {
   1767 	if (!wpa_s->fetch_anqp_in_progress)
   1768 		return;
   1769 
   1770 	wpa_s->fetch_anqp_in_progress = 0;
   1771 }
   1772 
   1773 
   1774 int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
   1775 		  u16 info_ids[], size_t num_ids)
   1776 {
   1777 	struct wpabuf *buf;
   1778 	int ret = 0;
   1779 	int freq;
   1780 	struct wpa_bss *bss;
   1781 	int res;
   1782 
   1783 	freq = wpa_s->assoc_freq;
   1784 	bss = wpa_bss_get_bssid(wpa_s, dst);
   1785 	if (bss) {
   1786 		wpa_bss_anqp_unshare_alloc(bss);
   1787 		freq = bss->freq;
   1788 	}
   1789 	if (freq <= 0)
   1790 		return -1;
   1791 
   1792 	wpa_printf(MSG_DEBUG, "ANQP: Query Request to " MACSTR " for %u id(s)",
   1793 		   MAC2STR(dst), (unsigned int) num_ids);
   1794 
   1795 	buf = anqp_build_req(info_ids, num_ids, NULL);
   1796 	if (buf == NULL)
   1797 		return -1;
   1798 
   1799 	res = gas_query_req(wpa_s->gas, dst, freq, buf, anqp_resp_cb, wpa_s);
   1800 	if (res < 0) {
   1801 		wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request");
   1802 		ret = -1;
   1803 	} else
   1804 		wpa_printf(MSG_DEBUG, "ANQP: Query started with dialog token "
   1805 			   "%u", res);
   1806 
   1807 	wpabuf_free(buf);
   1808 	return ret;
   1809 }
   1810 
   1811 
   1812 static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
   1813 					    struct wpa_bss *bss, const u8 *sa,
   1814 					    u16 info_id,
   1815 					    const u8 *data, size_t slen)
   1816 {
   1817 	const u8 *pos = data;
   1818 	struct wpa_bss_anqp *anqp = NULL;
   1819 #ifdef CONFIG_HS20
   1820 	u8 type;
   1821 #endif /* CONFIG_HS20 */
   1822 
   1823 	if (bss)
   1824 		anqp = bss->anqp;
   1825 
   1826 	switch (info_id) {
   1827 	case ANQP_CAPABILITY_LIST:
   1828 		wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
   1829 			" ANQP Capability list", MAC2STR(sa));
   1830 		break;
   1831 	case ANQP_VENUE_NAME:
   1832 		wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
   1833 			" Venue Name", MAC2STR(sa));
   1834 		wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Venue Name", pos, slen);
   1835 		if (anqp) {
   1836 			wpabuf_free(anqp->venue_name);
   1837 			anqp->venue_name = wpabuf_alloc_copy(pos, slen);
   1838 		}
   1839 		break;
   1840 	case ANQP_NETWORK_AUTH_TYPE:
   1841 		wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
   1842 			" Network Authentication Type information",
   1843 			MAC2STR(sa));
   1844 		wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Network Authentication "
   1845 				  "Type", pos, slen);
   1846 		if (anqp) {
   1847 			wpabuf_free(anqp->network_auth_type);
   1848 			anqp->network_auth_type = wpabuf_alloc_copy(pos, slen);
   1849 		}
   1850 		break;
   1851 	case ANQP_ROAMING_CONSORTIUM:
   1852 		wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
   1853 			" Roaming Consortium list", MAC2STR(sa));
   1854 		wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Roaming Consortium",
   1855 				  pos, slen);
   1856 		if (anqp) {
   1857 			wpabuf_free(anqp->roaming_consortium);
   1858 			anqp->roaming_consortium = wpabuf_alloc_copy(pos, slen);
   1859 		}
   1860 		break;
   1861 	case ANQP_IP_ADDR_TYPE_AVAILABILITY:
   1862 		wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
   1863 			" IP Address Type Availability information",
   1864 			MAC2STR(sa));
   1865 		wpa_hexdump(MSG_MSGDUMP, "ANQP: IP Address Availability",
   1866 			    pos, slen);
   1867 		if (anqp) {
   1868 			wpabuf_free(anqp->ip_addr_type_availability);
   1869 			anqp->ip_addr_type_availability =
   1870 				wpabuf_alloc_copy(pos, slen);
   1871 		}
   1872 		break;
   1873 	case ANQP_NAI_REALM:
   1874 		wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
   1875 			" NAI Realm list", MAC2STR(sa));
   1876 		wpa_hexdump_ascii(MSG_DEBUG, "ANQP: NAI Realm", pos, slen);
   1877 		if (anqp) {
   1878 			wpabuf_free(anqp->nai_realm);
   1879 			anqp->nai_realm = wpabuf_alloc_copy(pos, slen);
   1880 		}
   1881 		break;
   1882 	case ANQP_3GPP_CELLULAR_NETWORK:
   1883 		wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
   1884 			" 3GPP Cellular Network information", MAC2STR(sa));
   1885 		wpa_hexdump_ascii(MSG_DEBUG, "ANQP: 3GPP Cellular Network",
   1886 				  pos, slen);
   1887 		if (anqp) {
   1888 			wpabuf_free(anqp->anqp_3gpp);
   1889 			anqp->anqp_3gpp = wpabuf_alloc_copy(pos, slen);
   1890 		}
   1891 		break;
   1892 	case ANQP_DOMAIN_NAME:
   1893 		wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
   1894 			" Domain Name list", MAC2STR(sa));
   1895 		wpa_hexdump_ascii(MSG_MSGDUMP, "ANQP: Domain Name", pos, slen);
   1896 		if (anqp) {
   1897 			wpabuf_free(anqp->domain_name);
   1898 			anqp->domain_name = wpabuf_alloc_copy(pos, slen);
   1899 		}
   1900 		break;
   1901 	case ANQP_VENDOR_SPECIFIC:
   1902 		if (slen < 3)
   1903 			return;
   1904 
   1905 		switch (WPA_GET_BE24(pos)) {
   1906 #ifdef CONFIG_HS20
   1907 		case OUI_WFA:
   1908 			pos += 3;
   1909 			slen -= 3;
   1910 
   1911 			if (slen < 1)
   1912 				return;
   1913 			type = *pos++;
   1914 			slen--;
   1915 
   1916 			switch (type) {
   1917 			case HS20_ANQP_OUI_TYPE:
   1918 				hs20_parse_rx_hs20_anqp_resp(wpa_s, sa, pos,
   1919 							     slen);
   1920 				break;
   1921 			default:
   1922 				wpa_printf(MSG_DEBUG, "HS20: Unsupported ANQP "
   1923 					   "vendor type %u", type);
   1924 				break;
   1925 			}
   1926 			break;
   1927 #endif /* CONFIG_HS20 */
   1928 		default:
   1929 			wpa_printf(MSG_DEBUG, "Interworking: Unsupported "
   1930 				   "vendor-specific ANQP OUI %06x",
   1931 				   WPA_GET_BE24(pos));
   1932 			return;
   1933 		}
   1934 		break;
   1935 	default:
   1936 		wpa_printf(MSG_DEBUG, "Interworking: Unsupported ANQP Info ID "
   1937 			   "%u", info_id);
   1938 		break;
   1939 	}
   1940 }
   1941 
   1942 
   1943 void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token,
   1944 		  enum gas_query_result result,
   1945 		  const struct wpabuf *adv_proto,
   1946 		  const struct wpabuf *resp, u16 status_code)
   1947 {
   1948 	struct wpa_supplicant *wpa_s = ctx;
   1949 	const u8 *pos;
   1950 	const u8 *end;
   1951 	u16 info_id;
   1952 	u16 slen;
   1953 	struct wpa_bss *bss = NULL, *tmp;
   1954 
   1955 	if (result != GAS_QUERY_SUCCESS)
   1956 		return;
   1957 
   1958 	pos = wpabuf_head(adv_proto);
   1959 	if (wpabuf_len(adv_proto) < 4 || pos[0] != WLAN_EID_ADV_PROTO ||
   1960 	    pos[1] < 2 || pos[3] != ACCESS_NETWORK_QUERY_PROTOCOL) {
   1961 		wpa_printf(MSG_DEBUG, "ANQP: Unexpected Advertisement "
   1962 			   "Protocol in response");
   1963 		return;
   1964 	}
   1965 
   1966 	/*
   1967 	 * If possible, select the BSS entry based on which BSS entry was used
   1968 	 * for the request. This can help in cases where multiple BSS entries
   1969 	 * may exist for the same AP.
   1970 	 */
   1971 	dl_list_for_each_reverse(tmp, &wpa_s->bss, struct wpa_bss, list) {
   1972 		if (tmp == wpa_s->interworking_gas_bss &&
   1973 		    os_memcmp(tmp->bssid, dst, ETH_ALEN) == 0) {
   1974 			bss = tmp;
   1975 			break;
   1976 		}
   1977 	}
   1978 	if (bss == NULL)
   1979 		bss = wpa_bss_get_bssid(wpa_s, dst);
   1980 
   1981 	pos = wpabuf_head(resp);
   1982 	end = pos + wpabuf_len(resp);
   1983 
   1984 	while (pos < end) {
   1985 		if (pos + 4 > end) {
   1986 			wpa_printf(MSG_DEBUG, "ANQP: Invalid element");
   1987 			break;
   1988 		}
   1989 		info_id = WPA_GET_LE16(pos);
   1990 		pos += 2;
   1991 		slen = WPA_GET_LE16(pos);
   1992 		pos += 2;
   1993 		if (pos + slen > end) {
   1994 			wpa_printf(MSG_DEBUG, "ANQP: Invalid element length "
   1995 				   "for Info ID %u", info_id);
   1996 			break;
   1997 		}
   1998 		interworking_parse_rx_anqp_resp(wpa_s, bss, dst, info_id, pos,
   1999 						slen);
   2000 		pos += slen;
   2001 	}
   2002 }
   2003 
   2004 
   2005 static void interworking_scan_res_handler(struct wpa_supplicant *wpa_s,
   2006 					  struct wpa_scan_results *scan_res)
   2007 {
   2008 	wpa_printf(MSG_DEBUG, "Interworking: Scan results available - start "
   2009 		   "ANQP fetch");
   2010 	interworking_start_fetch_anqp(wpa_s);
   2011 }
   2012 
   2013 
   2014 int interworking_select(struct wpa_supplicant *wpa_s, int auto_select)
   2015 {
   2016 	interworking_stop_fetch_anqp(wpa_s);
   2017 	wpa_s->network_select = 1;
   2018 	wpa_s->auto_network_select = 0;
   2019 	wpa_s->auto_select = !!auto_select;
   2020 	wpa_s->fetch_all_anqp = 0;
   2021 	wpa_printf(MSG_DEBUG, "Interworking: Start scan for network "
   2022 		   "selection");
   2023 	wpa_s->scan_res_handler = interworking_scan_res_handler;
   2024 	wpa_s->scan_req = MANUAL_SCAN_REQ;
   2025 	wpa_supplicant_req_scan(wpa_s, 0, 0);
   2026 
   2027 	return 0;
   2028 }
   2029 
   2030 
   2031 static void gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
   2032 			enum gas_query_result result,
   2033 			const struct wpabuf *adv_proto,
   2034 			const struct wpabuf *resp, u16 status_code)
   2035 {
   2036 	struct wpa_supplicant *wpa_s = ctx;
   2037 
   2038 	wpa_msg(wpa_s, MSG_INFO, GAS_RESPONSE_INFO "addr=" MACSTR
   2039 		" dialog_token=%d status_code=%d resp_len=%d",
   2040 		MAC2STR(addr), dialog_token, status_code,
   2041 		resp ? (int) wpabuf_len(resp) : -1);
   2042 	if (!resp)
   2043 		return;
   2044 
   2045 	wpabuf_free(wpa_s->last_gas_resp);
   2046 	wpa_s->last_gas_resp = wpabuf_dup(resp);
   2047 	if (wpa_s->last_gas_resp == NULL)
   2048 		return;
   2049 	os_memcpy(wpa_s->last_gas_addr, addr, ETH_ALEN);
   2050 	wpa_s->last_gas_dialog_token = dialog_token;
   2051 }
   2052 
   2053 
   2054 int gas_send_request(struct wpa_supplicant *wpa_s, const u8 *dst,
   2055 		     const struct wpabuf *adv_proto,
   2056 		     const struct wpabuf *query)
   2057 {
   2058 	struct wpabuf *buf;
   2059 	int ret = 0;
   2060 	int freq;
   2061 	struct wpa_bss *bss;
   2062 	int res;
   2063 	size_t len;
   2064 	u8 query_resp_len_limit = 0, pame_bi = 0;
   2065 
   2066 	freq = wpa_s->assoc_freq;
   2067 	bss = wpa_bss_get_bssid(wpa_s, dst);
   2068 	if (bss)
   2069 		freq = bss->freq;
   2070 	if (freq <= 0)
   2071 		return -1;
   2072 
   2073 	wpa_printf(MSG_DEBUG, "GAS request to " MACSTR " (freq %d MHz)",
   2074 		   MAC2STR(dst), freq);
   2075 	wpa_hexdump_buf(MSG_DEBUG, "Advertisement Protocol ID", adv_proto);
   2076 	wpa_hexdump_buf(MSG_DEBUG, "GAS Query", query);
   2077 
   2078 	len = 3 + wpabuf_len(adv_proto) + 2;
   2079 	if (query)
   2080 		len += wpabuf_len(query);
   2081 	buf = gas_build_initial_req(0, len);
   2082 	if (buf == NULL)
   2083 		return -1;
   2084 
   2085 	/* Advertisement Protocol IE */
   2086 	wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO);
   2087 	wpabuf_put_u8(buf, 1 + wpabuf_len(adv_proto)); /* Length */
   2088 	wpabuf_put_u8(buf, (query_resp_len_limit & 0x7f) |
   2089 		      (pame_bi ? 0x80 : 0));
   2090 	wpabuf_put_buf(buf, adv_proto);
   2091 
   2092 	/* GAS Query */
   2093 	if (query) {
   2094 		wpabuf_put_le16(buf, wpabuf_len(query));
   2095 		wpabuf_put_buf(buf, query);
   2096 	} else
   2097 		wpabuf_put_le16(buf, 0);
   2098 
   2099 	res = gas_query_req(wpa_s->gas, dst, freq, buf, gas_resp_cb, wpa_s);
   2100 	if (res < 0) {
   2101 		wpa_printf(MSG_DEBUG, "GAS: Failed to send Query Request");
   2102 		ret = -1;
   2103 	} else
   2104 		wpa_printf(MSG_DEBUG, "GAS: Query started with dialog token "
   2105 			   "%u", res);
   2106 
   2107 	wpabuf_free(buf);
   2108 	return ret;
   2109 }
   2110