xref: /freebsd/contrib/wpa/wpa_supplicant/interworking.c (revision a03411e84728e9b267056fd31c7d1d9d1dc1b01e)
1 /*
2  * Interworking (IEEE 802.11u)
3  * Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
4  * Copyright (c) 2011-2014, Jouni Malinen <j@w1.fi>
5  *
6  * This software may be distributed under the terms of the BSD license.
7  * See README for more details.
8  */
9 
10 #include "includes.h"
11 
12 #include "common.h"
13 #include "common/ieee802_11_defs.h"
14 #include "common/gas.h"
15 #include "common/wpa_ctrl.h"
16 #include "utils/pcsc_funcs.h"
17 #include "utils/eloop.h"
18 #include "drivers/driver.h"
19 #include "eap_common/eap_defs.h"
20 #include "eap_peer/eap.h"
21 #include "eap_peer/eap_methods.h"
22 #include "eapol_supp/eapol_supp_sm.h"
23 #include "rsn_supp/wpa.h"
24 #include "wpa_supplicant_i.h"
25 #include "config.h"
26 #include "config_ssid.h"
27 #include "bss.h"
28 #include "scan.h"
29 #include "notify.h"
30 #include "driver_i.h"
31 #include "gas_query.h"
32 #include "hs20_supplicant.h"
33 #include "interworking.h"
34 
35 
36 #if defined(EAP_SIM) | defined(EAP_SIM_DYNAMIC)
37 #define INTERWORKING_3GPP
38 #else
39 #if defined(EAP_AKA) | defined(EAP_AKA_DYNAMIC)
40 #define INTERWORKING_3GPP
41 #else
42 #if defined(EAP_AKA_PRIME) | defined(EAP_AKA_PRIME_DYNAMIC)
43 #define INTERWORKING_3GPP
44 #endif
45 #endif
46 #endif
47 
48 static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s);
49 static struct wpa_cred * interworking_credentials_available_realm(
50 	struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw,
51 	int *excluded);
52 static struct wpa_cred * interworking_credentials_available_3gpp(
53 	struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw,
54 	int *excluded);
55 
56 
57 static int cred_prio_cmp(const struct wpa_cred *a, const struct wpa_cred *b)
58 {
59 	if (a->priority > b->priority)
60 		return 1;
61 	if (a->priority < b->priority)
62 		return -1;
63 	if (a->provisioning_sp == NULL || b->provisioning_sp == NULL ||
64 	    os_strcmp(a->provisioning_sp, b->provisioning_sp) != 0)
65 		return 0;
66 	if (a->sp_priority < b->sp_priority)
67 		return 1;
68 	if (a->sp_priority > b->sp_priority)
69 		return -1;
70 	return 0;
71 }
72 
73 
74 static void interworking_reconnect(struct wpa_supplicant *wpa_s)
75 {
76 	unsigned int tried;
77 
78 	if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
79 		wpa_supplicant_cancel_sched_scan(wpa_s);
80 		wpa_s->own_disconnect_req = 1;
81 		wpa_supplicant_deauthenticate(wpa_s,
82 					      WLAN_REASON_DEAUTH_LEAVING);
83 	}
84 	wpa_s->disconnected = 0;
85 	wpa_s->reassociate = 1;
86 	tried = wpa_s->interworking_fast_assoc_tried;
87 	wpa_s->interworking_fast_assoc_tried = 1;
88 
89 	if (!tried && wpa_supplicant_fast_associate(wpa_s) >= 0)
90 		return;
91 
92 	wpa_s->interworking_fast_assoc_tried = 0;
93 	wpa_supplicant_req_scan(wpa_s, 0, 0);
94 }
95 
96 
97 static struct wpabuf * anqp_build_req(u16 info_ids[], size_t num_ids,
98 				      struct wpabuf *extra)
99 {
100 	struct wpabuf *buf;
101 	size_t i;
102 	u8 *len_pos;
103 
104 	buf = gas_anqp_build_initial_req(0, 4 + num_ids * 2 +
105 					 (extra ? wpabuf_len(extra) : 0));
106 	if (buf == NULL)
107 		return NULL;
108 
109 	if (num_ids > 0) {
110 		len_pos = gas_anqp_add_element(buf, ANQP_QUERY_LIST);
111 		for (i = 0; i < num_ids; i++)
112 			wpabuf_put_le16(buf, info_ids[i]);
113 		gas_anqp_set_element_len(buf, len_pos);
114 	}
115 	if (extra)
116 		wpabuf_put_buf(buf, extra);
117 
118 	gas_anqp_set_len(buf);
119 
120 	return buf;
121 }
122 
123 
124 static void interworking_anqp_resp_cb(void *ctx, const u8 *dst,
125 				      u8 dialog_token,
126 				      enum gas_query_result result,
127 				      const struct wpabuf *adv_proto,
128 				      const struct wpabuf *resp,
129 				      u16 status_code)
130 {
131 	struct wpa_supplicant *wpa_s = ctx;
132 
133 	wpa_printf(MSG_DEBUG, "ANQP: Response callback dst=" MACSTR
134 		   " dialog_token=%u result=%d status_code=%u",
135 		   MAC2STR(dst), dialog_token, result, status_code);
136 	anqp_resp_cb(wpa_s, dst, dialog_token, result, adv_proto, resp,
137 		     status_code);
138 	interworking_next_anqp_fetch(wpa_s);
139 }
140 
141 
142 static int cred_with_roaming_consortium(struct wpa_supplicant *wpa_s)
143 {
144 	struct wpa_cred *cred;
145 
146 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
147 		if (cred->roaming_consortium_len)
148 			return 1;
149 		if (cred->required_roaming_consortium_len)
150 			return 1;
151 		if (cred->num_roaming_consortiums)
152 			return 1;
153 	}
154 	return 0;
155 }
156 
157 
158 static int cred_with_3gpp(struct wpa_supplicant *wpa_s)
159 {
160 	struct wpa_cred *cred;
161 
162 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
163 		if (cred->pcsc || cred->imsi)
164 			return 1;
165 	}
166 	return 0;
167 }
168 
169 
170 static int cred_with_nai_realm(struct wpa_supplicant *wpa_s)
171 {
172 	struct wpa_cred *cred;
173 
174 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
175 		if (cred->pcsc || cred->imsi)
176 			continue;
177 		if (!cred->eap_method)
178 			return 1;
179 		if (cred->realm)
180 			return 1;
181 	}
182 	return 0;
183 }
184 
185 
186 static int cred_with_domain(struct wpa_supplicant *wpa_s)
187 {
188 	struct wpa_cred *cred;
189 
190 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
191 		if (cred->domain || cred->pcsc || cred->imsi ||
192 		    cred->roaming_partner)
193 			return 1;
194 	}
195 	return 0;
196 }
197 
198 
199 #ifdef CONFIG_HS20
200 
201 static int cred_with_min_backhaul(struct wpa_supplicant *wpa_s)
202 {
203 	struct wpa_cred *cred;
204 
205 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
206 		if (cred->min_dl_bandwidth_home ||
207 		    cred->min_ul_bandwidth_home ||
208 		    cred->min_dl_bandwidth_roaming ||
209 		    cred->min_ul_bandwidth_roaming)
210 			return 1;
211 	}
212 	return 0;
213 }
214 
215 
216 static int cred_with_conn_capab(struct wpa_supplicant *wpa_s)
217 {
218 	struct wpa_cred *cred;
219 
220 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
221 		if (cred->num_req_conn_capab)
222 			return 1;
223 	}
224 	return 0;
225 }
226 
227 #endif /* CONFIG_HS20 */
228 
229 
230 static int additional_roaming_consortiums(struct wpa_bss *bss)
231 {
232 	const u8 *ie;
233 	ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM);
234 	if (ie == NULL || ie[1] == 0)
235 		return 0;
236 	return ie[2]; /* Number of ANQP OIs */
237 }
238 
239 
240 static void interworking_continue_anqp(void *eloop_ctx, void *sock_ctx)
241 {
242 	struct wpa_supplicant *wpa_s = eloop_ctx;
243 	interworking_next_anqp_fetch(wpa_s);
244 }
245 
246 
247 static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s,
248 				      struct wpa_bss *bss)
249 {
250 	struct wpabuf *buf;
251 	int ret = 0;
252 	int res;
253 	u16 info_ids[8];
254 	size_t num_info_ids = 0;
255 	struct wpabuf *extra = NULL;
256 	int all = wpa_s->fetch_all_anqp;
257 
258 	wpa_msg(wpa_s, MSG_DEBUG, "Interworking: ANQP Query Request to " MACSTR,
259 		MAC2STR(bss->bssid));
260 	wpa_s->interworking_gas_bss = bss;
261 
262 	info_ids[num_info_ids++] = ANQP_CAPABILITY_LIST;
263 	if (all) {
264 		info_ids[num_info_ids++] = ANQP_VENUE_NAME;
265 		info_ids[num_info_ids++] = ANQP_NETWORK_AUTH_TYPE;
266 	}
267 	if (all || (cred_with_roaming_consortium(wpa_s) &&
268 		    additional_roaming_consortiums(bss)))
269 		info_ids[num_info_ids++] = ANQP_ROAMING_CONSORTIUM;
270 	if (all)
271 		info_ids[num_info_ids++] = ANQP_IP_ADDR_TYPE_AVAILABILITY;
272 	if (all || cred_with_nai_realm(wpa_s))
273 		info_ids[num_info_ids++] = ANQP_NAI_REALM;
274 	if (all || cred_with_3gpp(wpa_s)) {
275 		info_ids[num_info_ids++] = ANQP_3GPP_CELLULAR_NETWORK;
276 		wpa_supplicant_scard_init(wpa_s, NULL);
277 	}
278 	if (all || cred_with_domain(wpa_s))
279 		info_ids[num_info_ids++] = ANQP_DOMAIN_NAME;
280 	wpa_hexdump(MSG_DEBUG, "Interworking: ANQP Query info",
281 		    (u8 *) info_ids, num_info_ids * 2);
282 
283 #ifdef CONFIG_HS20
284 	if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) {
285 		u8 *len_pos;
286 
287 		extra = wpabuf_alloc(100);
288 		if (!extra)
289 			return -1;
290 
291 		len_pos = gas_anqp_add_element(extra, ANQP_VENDOR_SPECIFIC);
292 		wpabuf_put_be24(extra, OUI_WFA);
293 		wpabuf_put_u8(extra, HS20_ANQP_OUI_TYPE);
294 		wpabuf_put_u8(extra, HS20_STYPE_QUERY_LIST);
295 		wpabuf_put_u8(extra, 0); /* Reserved */
296 		wpabuf_put_u8(extra, HS20_STYPE_CAPABILITY_LIST);
297 		if (all)
298 			wpabuf_put_u8(extra,
299 				      HS20_STYPE_OPERATOR_FRIENDLY_NAME);
300 		if (all || cred_with_min_backhaul(wpa_s))
301 			wpabuf_put_u8(extra, HS20_STYPE_WAN_METRICS);
302 		if (all || cred_with_conn_capab(wpa_s))
303 			wpabuf_put_u8(extra, HS20_STYPE_CONNECTION_CAPABILITY);
304 		if (all)
305 			wpabuf_put_u8(extra, HS20_STYPE_OPERATING_CLASS);
306 		if (all) {
307 			wpabuf_put_u8(extra, HS20_STYPE_OSU_PROVIDERS_LIST);
308 			wpabuf_put_u8(extra, HS20_STYPE_OSU_PROVIDERS_NAI_LIST);
309 		}
310 		gas_anqp_set_element_len(extra, len_pos);
311 	}
312 #endif /* CONFIG_HS20 */
313 
314 	buf = anqp_build_req(info_ids, num_info_ids, extra);
315 	wpabuf_free(extra);
316 	if (buf == NULL)
317 		return -1;
318 
319 	res = gas_query_req(wpa_s->gas, bss->bssid, bss->freq, 0, 0, buf,
320 			    interworking_anqp_resp_cb, wpa_s);
321 	if (res < 0) {
322 		wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Failed to send Query Request");
323 		wpabuf_free(buf);
324 		ret = -1;
325 		eloop_register_timeout(0, 0, interworking_continue_anqp, wpa_s,
326 				       NULL);
327 	} else
328 		wpa_msg(wpa_s, MSG_DEBUG,
329 			"ANQP: Query started with dialog token %u", res);
330 
331 	return ret;
332 }
333 
334 
335 struct nai_realm_eap {
336 	u8 method;
337 	u8 inner_method;
338 	enum nai_realm_eap_auth_inner_non_eap inner_non_eap;
339 	u8 cred_type;
340 	u8 tunneled_cred_type;
341 };
342 
343 struct nai_realm {
344 	u8 encoding;
345 	char *realm;
346 	u8 eap_count;
347 	struct nai_realm_eap *eap;
348 };
349 
350 
351 static void nai_realm_free(struct nai_realm *realms, u16 count)
352 {
353 	u16 i;
354 
355 	if (realms == NULL)
356 		return;
357 	for (i = 0; i < count; i++) {
358 		os_free(realms[i].eap);
359 		os_free(realms[i].realm);
360 	}
361 	os_free(realms);
362 }
363 
364 
365 static const u8 * nai_realm_parse_eap(struct nai_realm_eap *e, const u8 *pos,
366 				      const u8 *end)
367 {
368 	u8 elen, auth_count, a;
369 	const u8 *e_end;
370 
371 	if (end - pos < 3) {
372 		wpa_printf(MSG_DEBUG, "No room for EAP Method fixed fields");
373 		return NULL;
374 	}
375 
376 	elen = *pos++;
377 	if (elen > end - pos || elen < 2) {
378 		wpa_printf(MSG_DEBUG, "No room for EAP Method subfield");
379 		return NULL;
380 	}
381 	e_end = pos + elen;
382 	e->method = *pos++;
383 	auth_count = *pos++;
384 	wpa_printf(MSG_DEBUG, "EAP Method: len=%u method=%u auth_count=%u",
385 		   elen, e->method, auth_count);
386 
387 	for (a = 0; a < auth_count; a++) {
388 		u8 id, len;
389 
390 		if (end - pos < 2) {
391 			wpa_printf(MSG_DEBUG,
392 				   "No room for Authentication Parameter subfield header");
393 			return NULL;
394 		}
395 
396 		id = *pos++;
397 		len = *pos++;
398 		if (len > end - pos) {
399 			wpa_printf(MSG_DEBUG,
400 				   "No room for Authentication Parameter subfield");
401 			return NULL;
402 		}
403 
404 		switch (id) {
405 		case NAI_REALM_EAP_AUTH_NON_EAP_INNER_AUTH:
406 			if (len < 1)
407 				break;
408 			e->inner_non_eap = *pos;
409 			if (e->method != EAP_TYPE_TTLS)
410 				break;
411 			switch (*pos) {
412 			case NAI_REALM_INNER_NON_EAP_PAP:
413 				wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP");
414 				break;
415 			case NAI_REALM_INNER_NON_EAP_CHAP:
416 				wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP");
417 				break;
418 			case NAI_REALM_INNER_NON_EAP_MSCHAP:
419 				wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP");
420 				break;
421 			case NAI_REALM_INNER_NON_EAP_MSCHAPV2:
422 				wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2");
423 				break;
424 			}
425 			break;
426 		case NAI_REALM_EAP_AUTH_INNER_AUTH_EAP_METHOD:
427 			if (len < 1)
428 				break;
429 			e->inner_method = *pos;
430 			wpa_printf(MSG_DEBUG, "Inner EAP method: %u",
431 				   e->inner_method);
432 			break;
433 		case NAI_REALM_EAP_AUTH_CRED_TYPE:
434 			if (len < 1)
435 				break;
436 			e->cred_type = *pos;
437 			wpa_printf(MSG_DEBUG, "Credential Type: %u",
438 				   e->cred_type);
439 			break;
440 		case NAI_REALM_EAP_AUTH_TUNNELED_CRED_TYPE:
441 			if (len < 1)
442 				break;
443 			e->tunneled_cred_type = *pos;
444 			wpa_printf(MSG_DEBUG, "Tunneled EAP Method Credential "
445 				   "Type: %u", e->tunneled_cred_type);
446 			break;
447 		default:
448 			wpa_printf(MSG_DEBUG, "Unsupported Authentication "
449 				   "Parameter: id=%u len=%u", id, len);
450 			wpa_hexdump(MSG_DEBUG, "Authentication Parameter "
451 				    "Value", pos, len);
452 			break;
453 		}
454 
455 		pos += len;
456 	}
457 
458 	return e_end;
459 }
460 
461 
462 static const u8 * nai_realm_parse_realm(struct nai_realm *r, const u8 *pos,
463 					const u8 *end)
464 {
465 	u16 len;
466 	const u8 *f_end;
467 	u8 realm_len, e;
468 
469 	if (end - pos < 4) {
470 		wpa_printf(MSG_DEBUG, "No room for NAI Realm Data "
471 			   "fixed fields");
472 		return NULL;
473 	}
474 
475 	len = WPA_GET_LE16(pos); /* NAI Realm Data field Length */
476 	pos += 2;
477 	if (len > end - pos || len < 3) {
478 		wpa_printf(MSG_DEBUG, "No room for NAI Realm Data "
479 			   "(len=%u; left=%u)",
480 			   len, (unsigned int) (end - pos));
481 		return NULL;
482 	}
483 	f_end = pos + len;
484 
485 	r->encoding = *pos++;
486 	realm_len = *pos++;
487 	if (realm_len > f_end - pos) {
488 		wpa_printf(MSG_DEBUG, "No room for NAI Realm "
489 			   "(len=%u; left=%u)",
490 			   realm_len, (unsigned int) (f_end - pos));
491 		return NULL;
492 	}
493 	wpa_hexdump_ascii(MSG_DEBUG, "NAI Realm", pos, realm_len);
494 	r->realm = dup_binstr(pos, realm_len);
495 	if (r->realm == NULL)
496 		return NULL;
497 	pos += realm_len;
498 
499 	if (f_end - pos < 1) {
500 		wpa_printf(MSG_DEBUG, "No room for EAP Method Count");
501 		return NULL;
502 	}
503 	r->eap_count = *pos++;
504 	wpa_printf(MSG_DEBUG, "EAP Count: %u", r->eap_count);
505 	if (r->eap_count * 3 > f_end - pos) {
506 		wpa_printf(MSG_DEBUG, "No room for EAP Methods");
507 		return NULL;
508 	}
509 	r->eap = os_calloc(r->eap_count, sizeof(struct nai_realm_eap));
510 	if (r->eap == NULL)
511 		return NULL;
512 
513 	for (e = 0; e < r->eap_count; e++) {
514 		pos = nai_realm_parse_eap(&r->eap[e], pos, f_end);
515 		if (pos == NULL)
516 			return NULL;
517 	}
518 
519 	return f_end;
520 }
521 
522 
523 static struct nai_realm * nai_realm_parse(struct wpabuf *anqp, u16 *count)
524 {
525 	struct nai_realm *realm;
526 	const u8 *pos, *end;
527 	u16 i, num;
528 	size_t left;
529 
530 	if (anqp == NULL)
531 		return NULL;
532 	left = wpabuf_len(anqp);
533 	if (left < 2)
534 		return NULL;
535 
536 	pos = wpabuf_head_u8(anqp);
537 	end = pos + left;
538 	num = WPA_GET_LE16(pos);
539 	wpa_printf(MSG_DEBUG, "NAI Realm Count: %u", num);
540 	pos += 2;
541 	left -= 2;
542 
543 	if (num > left / 5) {
544 		wpa_printf(MSG_DEBUG, "Invalid NAI Realm Count %u - not "
545 			   "enough data (%u octets) for that many realms",
546 			   num, (unsigned int) left);
547 		return NULL;
548 	}
549 
550 	realm = os_calloc(num, sizeof(struct nai_realm));
551 	if (realm == NULL)
552 		return NULL;
553 
554 	for (i = 0; i < num; i++) {
555 		pos = nai_realm_parse_realm(&realm[i], pos, end);
556 		if (pos == NULL) {
557 			nai_realm_free(realm, num);
558 			return NULL;
559 		}
560 	}
561 
562 	*count = num;
563 	return realm;
564 }
565 
566 
567 static int nai_realm_match(struct nai_realm *realm, const char *home_realm)
568 {
569 	char *tmp, *pos, *end;
570 	int match = 0;
571 
572 	if (realm->realm == NULL || home_realm == NULL)
573 		return 0;
574 
575 	if (os_strchr(realm->realm, ';') == NULL)
576 		return os_strcasecmp(realm->realm, home_realm) == 0;
577 
578 	tmp = os_strdup(realm->realm);
579 	if (tmp == NULL)
580 		return 0;
581 
582 	pos = tmp;
583 	while (*pos) {
584 		end = os_strchr(pos, ';');
585 		if (end)
586 			*end = '\0';
587 		if (os_strcasecmp(pos, home_realm) == 0) {
588 			match = 1;
589 			break;
590 		}
591 		if (end == NULL)
592 			break;
593 		pos = end + 1;
594 	}
595 
596 	os_free(tmp);
597 
598 	return match;
599 }
600 
601 
602 static int nai_realm_cred_username(struct wpa_supplicant *wpa_s,
603 				   struct nai_realm_eap *eap)
604 {
605 	if (eap_get_name(EAP_VENDOR_IETF, eap->method) == NULL) {
606 		wpa_msg(wpa_s, MSG_DEBUG,
607 			"nai-realm-cred-username: EAP method not supported: %d",
608 			eap->method);
609 		return 0; /* method not supported */
610 	}
611 
612 	if (eap->method != EAP_TYPE_TTLS && eap->method != EAP_TYPE_PEAP &&
613 	    eap->method != EAP_TYPE_FAST) {
614 		/* Only tunneled methods with username/password supported */
615 		wpa_msg(wpa_s, MSG_DEBUG,
616 			"nai-realm-cred-username: Method: %d is not TTLS, PEAP, or FAST",
617 			eap->method);
618 		return 0;
619 	}
620 
621 	if (eap->method == EAP_TYPE_PEAP || eap->method == EAP_TYPE_FAST) {
622 		if (eap->inner_method &&
623 		    eap_get_name(EAP_VENDOR_IETF, eap->inner_method) == NULL) {
624 			wpa_msg(wpa_s, MSG_DEBUG,
625 				"nai-realm-cred-username: PEAP/FAST: Inner method not supported: %d",
626 				eap->inner_method);
627 			return 0;
628 		}
629 		if (!eap->inner_method &&
630 		    eap_get_name(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2) == NULL) {
631 			wpa_msg(wpa_s, MSG_DEBUG,
632 				"nai-realm-cred-username: MSCHAPv2 not supported");
633 			return 0;
634 		}
635 	}
636 
637 	if (eap->method == EAP_TYPE_TTLS) {
638 		if (eap->inner_method == 0 && eap->inner_non_eap == 0)
639 			return 1; /* Assume TTLS/MSCHAPv2 is used */
640 		if (eap->inner_method &&
641 		    eap_get_name(EAP_VENDOR_IETF, eap->inner_method) == NULL) {
642 			wpa_msg(wpa_s, MSG_DEBUG,
643 				"nai-realm-cred-username: TTLS, but inner not supported: %d",
644 				eap->inner_method);
645 			return 0;
646 		}
647 		if (eap->inner_non_eap &&
648 		    eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_PAP &&
649 		    eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_CHAP &&
650 		    eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_MSCHAP &&
651 		    eap->inner_non_eap != NAI_REALM_INNER_NON_EAP_MSCHAPV2) {
652 			wpa_msg(wpa_s, MSG_DEBUG,
653 				"nai-realm-cred-username: TTLS, inner-non-eap not supported: %d",
654 				eap->inner_non_eap);
655 			return 0;
656 		}
657 	}
658 
659 	if (eap->inner_method &&
660 	    eap->inner_method != EAP_TYPE_GTC &&
661 	    eap->inner_method != EAP_TYPE_MSCHAPV2) {
662 		wpa_msg(wpa_s, MSG_DEBUG,
663 			"nai-realm-cred-username: inner-method not GTC or MSCHAPv2: %d",
664 			eap->inner_method);
665 		return 0;
666 	}
667 
668 	return 1;
669 }
670 
671 
672 static int nai_realm_cred_cert(struct wpa_supplicant *wpa_s,
673 			       struct nai_realm_eap *eap)
674 {
675 	if (eap_get_name(EAP_VENDOR_IETF, eap->method) == NULL) {
676 		wpa_msg(wpa_s, MSG_DEBUG,
677 			"nai-realm-cred-cert: Method not supported: %d",
678 			eap->method);
679 		return 0; /* method not supported */
680 	}
681 
682 	if (eap->method != EAP_TYPE_TLS) {
683 		/* Only EAP-TLS supported for credential authentication */
684 		wpa_msg(wpa_s, MSG_DEBUG,
685 			"nai-realm-cred-cert: Method not TLS: %d",
686 			eap->method);
687 		return 0;
688 	}
689 
690 	return 1;
691 }
692 
693 
694 static struct nai_realm_eap * nai_realm_find_eap(struct wpa_supplicant *wpa_s,
695 						 struct wpa_cred *cred,
696 						 struct nai_realm *realm)
697 {
698 	u8 e;
699 
700 	if (cred->username == NULL ||
701 	    cred->username[0] == '\0' ||
702 	    ((cred->password == NULL ||
703 	      cred->password[0] == '\0') &&
704 	     (cred->private_key == NULL ||
705 	      cred->private_key[0] == '\0') &&
706 	     (!cred->key_id || cred->key_id[0] == '\0'))) {
707 		wpa_msg(wpa_s, MSG_DEBUG,
708 			"nai-realm-find-eap: incomplete cred info: username: %s  password: %s private_key: %s key_id: %s",
709 			cred->username ? cred->username : "NULL",
710 			cred->password ? cred->password : "NULL",
711 			cred->private_key ? cred->private_key : "NULL",
712 			cred->key_id ? cred->key_id : "NULL");
713 		return NULL;
714 	}
715 
716 	for (e = 0; e < realm->eap_count; e++) {
717 		struct nai_realm_eap *eap = &realm->eap[e];
718 		if (cred->password && cred->password[0] &&
719 		    nai_realm_cred_username(wpa_s, eap))
720 			return eap;
721 		if (((cred->private_key && cred->private_key[0]) ||
722 		     (cred->key_id && cred->key_id[0])) &&
723 		    nai_realm_cred_cert(wpa_s, eap))
724 			return eap;
725 	}
726 
727 	return NULL;
728 }
729 
730 
731 #ifdef INTERWORKING_3GPP
732 
733 static int plmn_id_match(struct wpabuf *anqp, const char *imsi, int mnc_len)
734 {
735 	u8 plmn[3], plmn2[3];
736 	const u8 *pos, *end;
737 	u8 udhl;
738 
739 	/*
740 	 * See Annex A of 3GPP TS 24.234 v8.1.0 for description. The network
741 	 * operator is allowed to include only two digits of the MNC, so allow
742 	 * matches based on both two and three digit MNC assumptions. Since some
743 	 * SIM/USIM cards may not expose MNC length conveniently, we may be
744 	 * provided the default MNC length 3 here and as such, checking with MNC
745 	 * length 2 is justifiable even though 3GPP TS 24.234 does not mention
746 	 * that case. Anyway, MCC/MNC pair where both 2 and 3 digit MNC is used
747 	 * with otherwise matching values would not be good idea in general, so
748 	 * this should not result in selecting incorrect networks.
749 	 */
750 	/* Match with 3 digit MNC */
751 	plmn[0] = (imsi[0] - '0') | ((imsi[1] - '0') << 4);
752 	plmn[1] = (imsi[2] - '0') | ((imsi[5] - '0') << 4);
753 	plmn[2] = (imsi[3] - '0') | ((imsi[4] - '0') << 4);
754 	/* Match with 2 digit MNC */
755 	plmn2[0] = (imsi[0] - '0') | ((imsi[1] - '0') << 4);
756 	plmn2[1] = (imsi[2] - '0') | 0xf0;
757 	plmn2[2] = (imsi[3] - '0') | ((imsi[4] - '0') << 4);
758 
759 	if (anqp == NULL)
760 		return 0;
761 	pos = wpabuf_head_u8(anqp);
762 	end = pos + wpabuf_len(anqp);
763 	if (end - pos < 2)
764 		return 0;
765 	if (*pos != 0) {
766 		wpa_printf(MSG_DEBUG, "Unsupported GUD version 0x%x", *pos);
767 		return 0;
768 	}
769 	pos++;
770 	udhl = *pos++;
771 	if (udhl > end - pos) {
772 		wpa_printf(MSG_DEBUG, "Invalid UDHL");
773 		return 0;
774 	}
775 	end = pos + udhl;
776 
777 	wpa_printf(MSG_DEBUG, "Interworking: Matching against MCC/MNC alternatives: %02x:%02x:%02x or %02x:%02x:%02x (IMSI %s, MNC length %d)",
778 		   plmn[0], plmn[1], plmn[2], plmn2[0], plmn2[1], plmn2[2],
779 		   imsi, mnc_len);
780 
781 	while (end - pos >= 2) {
782 		u8 iei, len;
783 		const u8 *l_end;
784 		iei = *pos++;
785 		len = *pos++ & 0x7f;
786 		if (len > end - pos)
787 			break;
788 		l_end = pos + len;
789 
790 		if (iei == 0 && len > 0) {
791 			/* PLMN List */
792 			u8 num, i;
793 			wpa_hexdump(MSG_DEBUG, "Interworking: PLMN List information element",
794 				    pos, len);
795 			num = *pos++;
796 			for (i = 0; i < num; i++) {
797 				if (l_end - pos < 3)
798 					break;
799 				if (os_memcmp(pos, plmn, 3) == 0 ||
800 				    os_memcmp(pos, plmn2, 3) == 0)
801 					return 1; /* Found matching PLMN */
802 				pos += 3;
803 			}
804 		} else {
805 			wpa_hexdump(MSG_DEBUG, "Interworking: Unrecognized 3GPP information element",
806 				    pos, len);
807 		}
808 
809 		pos = l_end;
810 	}
811 
812 	return 0;
813 }
814 
815 
816 static int build_root_nai(char *nai, size_t nai_len, const char *imsi,
817 			  size_t mnc_len, char prefix)
818 {
819 	const char *sep, *msin;
820 	char *end, *pos;
821 	size_t msin_len, plmn_len;
822 
823 	/*
824 	 * TS 23.003, Clause 14 (3GPP to WLAN Interworking)
825 	 * Root NAI:
826 	 * <aka:0|sim:1><IMSI>@wlan.mnc<MNC>.mcc<MCC>.3gppnetwork.org
827 	 * <MNC> is zero-padded to three digits in case two-digit MNC is used
828 	 */
829 
830 	if (imsi == NULL || os_strlen(imsi) > 16) {
831 		wpa_printf(MSG_DEBUG, "No valid IMSI available");
832 		return -1;
833 	}
834 	sep = os_strchr(imsi, '-');
835 	if (sep) {
836 		plmn_len = sep - imsi;
837 		msin = sep + 1;
838 	} else if (mnc_len && os_strlen(imsi) >= 3 + mnc_len) {
839 		plmn_len = 3 + mnc_len;
840 		msin = imsi + plmn_len;
841 	} else
842 		return -1;
843 	if (plmn_len != 5 && plmn_len != 6)
844 		return -1;
845 	msin_len = os_strlen(msin);
846 
847 	pos = nai;
848 	end = nai + nai_len;
849 	if (prefix)
850 		*pos++ = prefix;
851 	os_memcpy(pos, imsi, plmn_len);
852 	pos += plmn_len;
853 	os_memcpy(pos, msin, msin_len);
854 	pos += msin_len;
855 	pos += os_snprintf(pos, end - pos, "@wlan.mnc");
856 	if (plmn_len == 5) {
857 		*pos++ = '0';
858 		*pos++ = imsi[3];
859 		*pos++ = imsi[4];
860 	} else {
861 		*pos++ = imsi[3];
862 		*pos++ = imsi[4];
863 		*pos++ = imsi[5];
864 	}
865 	os_snprintf(pos, end - pos, ".mcc%c%c%c.3gppnetwork.org",
866 		    imsi[0], imsi[1], imsi[2]);
867 
868 	return 0;
869 }
870 
871 
872 static int set_root_nai(struct wpa_ssid *ssid, const char *imsi, char prefix)
873 {
874 	char nai[100];
875 	if (build_root_nai(nai, sizeof(nai), imsi, 0, prefix) < 0)
876 		return -1;
877 	return wpa_config_set_quoted(ssid, "identity", nai);
878 }
879 
880 #endif /* INTERWORKING_3GPP */
881 
882 
883 static int already_connected(struct wpa_supplicant *wpa_s,
884 			     struct wpa_cred *cred, struct wpa_bss *bss)
885 {
886 	struct wpa_ssid *ssid, *sel_ssid;
887 	struct wpa_bss *selected;
888 
889 	if (wpa_s->wpa_state < WPA_ASSOCIATED || wpa_s->current_ssid == NULL)
890 		return 0;
891 
892 	ssid = wpa_s->current_ssid;
893 	if (ssid->parent_cred != cred)
894 		return 0;
895 
896 	if (ssid->ssid_len != bss->ssid_len ||
897 	    os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) != 0)
898 		return 0;
899 
900 	sel_ssid = NULL;
901 	selected = wpa_supplicant_pick_network(wpa_s, &sel_ssid);
902 	if (selected && sel_ssid && sel_ssid->priority > ssid->priority)
903 		return 0; /* higher priority network in scan results */
904 
905 	return 1;
906 }
907 
908 
909 static void remove_duplicate_network(struct wpa_supplicant *wpa_s,
910 				     struct wpa_cred *cred,
911 				     struct wpa_bss *bss)
912 {
913 	struct wpa_ssid *ssid;
914 
915 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
916 		if (ssid->parent_cred != cred)
917 			continue;
918 		if (ssid->ssid_len != bss->ssid_len ||
919 		    os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) != 0)
920 			continue;
921 
922 		break;
923 	}
924 
925 	if (ssid == NULL)
926 		return;
927 
928 	wpa_printf(MSG_DEBUG, "Interworking: Remove duplicate network entry for the same credential");
929 
930 	if (ssid == wpa_s->current_ssid) {
931 		wpa_sm_set_config(wpa_s->wpa, NULL);
932 		eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
933 		wpa_s->own_disconnect_req = 1;
934 		wpa_supplicant_deauthenticate(wpa_s,
935 					      WLAN_REASON_DEAUTH_LEAVING);
936 	}
937 
938 	wpas_notify_network_removed(wpa_s, ssid);
939 	wpa_config_remove_network(wpa_s->conf, ssid->id);
940 }
941 
942 
943 static int interworking_set_hs20_params(struct wpa_supplicant *wpa_s,
944 					struct wpa_ssid *ssid)
945 {
946 	const char *key_mgmt = NULL;
947 #ifdef CONFIG_IEEE80211R
948 	int res;
949 	struct wpa_driver_capa capa;
950 
951 	res = wpa_drv_get_capa(wpa_s, &capa);
952 	if (res == 0 && capa.key_mgmt_iftype[WPA_IF_STATION] &
953 	    WPA_DRIVER_CAPA_KEY_MGMT_FT) {
954 		key_mgmt = wpa_s->conf->pmf != NO_MGMT_FRAME_PROTECTION ?
955 			"WPA-EAP WPA-EAP-SHA256 FT-EAP" :
956 			"WPA-EAP FT-EAP";
957 	}
958 #endif /* CONFIG_IEEE80211R */
959 
960 	if (!key_mgmt)
961 		key_mgmt = wpa_s->conf->pmf != NO_MGMT_FRAME_PROTECTION ?
962 			"WPA-EAP WPA-EAP-SHA256" : "WPA-EAP";
963 	if (wpa_config_set(ssid, "key_mgmt", key_mgmt, 0) < 0 ||
964 	    wpa_config_set(ssid, "proto", "RSN", 0) < 0 ||
965 	    wpa_config_set(ssid, "ieee80211w",
966 			   wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_REQUIRED ?
967 			   "2" : "1", 0) < 0 ||
968 	    wpa_config_set(ssid, "pairwise", "CCMP", 0) < 0)
969 		return -1;
970 	return 0;
971 }
972 
973 
974 static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s,
975 				     struct wpa_cred *cred,
976 				     struct wpa_bss *bss, int only_add)
977 {
978 #ifdef INTERWORKING_3GPP
979 	struct wpa_ssid *ssid;
980 	int eap_type;
981 	int res;
982 	char prefix;
983 
984 	if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL)
985 		return -1;
986 
987 	wpa_msg(wpa_s, MSG_DEBUG, "Interworking: Connect with " MACSTR
988 		" (3GPP)", MAC2STR(bss->bssid));
989 
990 	if (already_connected(wpa_s, cred, bss)) {
991 		wpa_msg(wpa_s, MSG_INFO, INTERWORKING_ALREADY_CONNECTED MACSTR,
992 			MAC2STR(bss->bssid));
993 		return wpa_s->current_ssid->id;
994 	}
995 
996 	remove_duplicate_network(wpa_s, cred, bss);
997 
998 	ssid = wpa_config_add_network(wpa_s->conf);
999 	if (ssid == NULL)
1000 		return -1;
1001 	ssid->parent_cred = cred;
1002 
1003 	wpas_notify_network_added(wpa_s, ssid);
1004 	wpa_config_set_network_defaults(ssid);
1005 	ssid->priority = cred->priority;
1006 	ssid->temporary = 1;
1007 	ssid->ssid = os_zalloc(bss->ssid_len + 1);
1008 	if (ssid->ssid == NULL)
1009 		goto fail;
1010 	os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len);
1011 	ssid->ssid_len = bss->ssid_len;
1012 	ssid->eap.sim_num = cred->sim_num;
1013 
1014 	if (interworking_set_hs20_params(wpa_s, ssid) < 0)
1015 		goto fail;
1016 
1017 	eap_type = EAP_TYPE_SIM;
1018 	if (cred->pcsc && wpa_s->scard && scard_supports_umts(wpa_s->scard))
1019 		eap_type = EAP_TYPE_AKA;
1020 	if (cred->eap_method && cred->eap_method[0].vendor == EAP_VENDOR_IETF) {
1021 		if (cred->eap_method[0].method == EAP_TYPE_SIM ||
1022 		    cred->eap_method[0].method == EAP_TYPE_AKA ||
1023 		    cred->eap_method[0].method == EAP_TYPE_AKA_PRIME)
1024 			eap_type = cred->eap_method[0].method;
1025 	}
1026 
1027 	switch (eap_type) {
1028 	case EAP_TYPE_SIM:
1029 		prefix = '1';
1030 		res = wpa_config_set(ssid, "eap", "SIM", 0);
1031 		break;
1032 	case EAP_TYPE_AKA:
1033 		prefix = '0';
1034 		res = wpa_config_set(ssid, "eap", "AKA", 0);
1035 		break;
1036 	case EAP_TYPE_AKA_PRIME:
1037 		prefix = '6';
1038 		res = wpa_config_set(ssid, "eap", "AKA'", 0);
1039 		break;
1040 	default:
1041 		res = -1;
1042 		break;
1043 	}
1044 	if (res < 0) {
1045 		wpa_msg(wpa_s, MSG_DEBUG,
1046 			"Selected EAP method (%d) not supported", eap_type);
1047 		goto fail;
1048 	}
1049 
1050 	if (!cred->pcsc && set_root_nai(ssid, cred->imsi, prefix) < 0) {
1051 		wpa_msg(wpa_s, MSG_DEBUG, "Failed to set Root NAI");
1052 		goto fail;
1053 	}
1054 
1055 	if (cred->milenage && cred->milenage[0]) {
1056 		if (wpa_config_set_quoted(ssid, "password",
1057 					  cred->milenage) < 0)
1058 			goto fail;
1059 	} else if (cred->pcsc) {
1060 		if (wpa_config_set_quoted(ssid, "pcsc", "") < 0)
1061 			goto fail;
1062 		if (wpa_s->conf->pcsc_pin &&
1063 		    wpa_config_set_quoted(ssid, "pin", wpa_s->conf->pcsc_pin)
1064 		    < 0)
1065 			goto fail;
1066 	}
1067 
1068 	wpa_s->next_ssid = ssid;
1069 	wpa_config_update_prio_list(wpa_s->conf);
1070 	if (!only_add)
1071 		interworking_reconnect(wpa_s);
1072 
1073 	return ssid->id;
1074 
1075 fail:
1076 	wpas_notify_network_removed(wpa_s, ssid);
1077 	wpa_config_remove_network(wpa_s->conf, ssid->id);
1078 #endif /* INTERWORKING_3GPP */
1079 	return -1;
1080 }
1081 
1082 
1083 static int roaming_consortium_element_match(const u8 *ie, const u8 *rc_id,
1084 					    size_t rc_len)
1085 {
1086 	const u8 *pos, *end;
1087 	u8 lens;
1088 
1089 	if (ie == NULL)
1090 		return 0;
1091 
1092 	pos = ie + 2;
1093 	end = ie + 2 + ie[1];
1094 
1095 	/* Roaming Consortium element:
1096 	 * Number of ANQP OIs
1097 	 * OI #1 and #2 lengths
1098 	 * OI #1, [OI #2], [OI #3]
1099 	 */
1100 
1101 	if (end - pos < 2)
1102 		return 0;
1103 
1104 	pos++; /* skip Number of ANQP OIs */
1105 	lens = *pos++;
1106 	if ((lens & 0x0f) + (lens >> 4) > end - pos)
1107 		return 0;
1108 
1109 	if ((lens & 0x0f) == rc_len && os_memcmp(pos, rc_id, rc_len) == 0)
1110 		return 1;
1111 	pos += lens & 0x0f;
1112 
1113 	if ((lens >> 4) == rc_len && os_memcmp(pos, rc_id, rc_len) == 0)
1114 		return 1;
1115 	pos += lens >> 4;
1116 
1117 	if (pos < end && (size_t) (end - pos) == rc_len &&
1118 	    os_memcmp(pos, rc_id, rc_len) == 0)
1119 		return 1;
1120 
1121 	return 0;
1122 }
1123 
1124 
1125 static int roaming_consortium_anqp_match(const struct wpabuf *anqp,
1126 					 const u8 *rc_id, size_t rc_len)
1127 {
1128 	const u8 *pos, *end;
1129 	u8 len;
1130 
1131 	if (anqp == NULL)
1132 		return 0;
1133 
1134 	pos = wpabuf_head(anqp);
1135 	end = pos + wpabuf_len(anqp);
1136 
1137 	/* Set of <OI Length, OI> duples */
1138 	while (pos < end) {
1139 		len = *pos++;
1140 		if (len > end - pos)
1141 			break;
1142 		if (len == rc_len && os_memcmp(pos, rc_id, rc_len) == 0)
1143 			return 1;
1144 		pos += len;
1145 	}
1146 
1147 	return 0;
1148 }
1149 
1150 
1151 static int roaming_consortium_match(const u8 *ie, const struct wpabuf *anqp,
1152 				    const u8 *rc_id, size_t rc_len)
1153 {
1154 	return roaming_consortium_element_match(ie, rc_id, rc_len) ||
1155 		roaming_consortium_anqp_match(anqp, rc_id, rc_len);
1156 }
1157 
1158 
1159 static int cred_roaming_consortiums_match(const u8 *ie,
1160 					  const struct wpabuf *anqp,
1161 					  const struct wpa_cred *cred)
1162 {
1163 	unsigned int i;
1164 
1165 	for (i = 0; i < cred->num_roaming_consortiums; i++) {
1166 		if (roaming_consortium_match(ie, anqp,
1167 					     cred->roaming_consortiums[i],
1168 					     cred->roaming_consortiums_len[i]))
1169 			return 1;
1170 	}
1171 
1172 	return 0;
1173 }
1174 
1175 
1176 static int cred_no_required_oi_match(struct wpa_cred *cred, struct wpa_bss *bss)
1177 {
1178 	const u8 *ie;
1179 
1180 	if (cred->required_roaming_consortium_len == 0)
1181 		return 0;
1182 
1183 	ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM);
1184 
1185 	if (ie == NULL &&
1186 	    (bss->anqp == NULL || bss->anqp->roaming_consortium == NULL))
1187 		return 1;
1188 
1189 	return !roaming_consortium_match(ie,
1190 					 bss->anqp ?
1191 					 bss->anqp->roaming_consortium : NULL,
1192 					 cred->required_roaming_consortium,
1193 					 cred->required_roaming_consortium_len);
1194 }
1195 
1196 
1197 static int cred_excluded_ssid(struct wpa_cred *cred, struct wpa_bss *bss)
1198 {
1199 	size_t i;
1200 
1201 	if (!cred->excluded_ssid)
1202 		return 0;
1203 
1204 	for (i = 0; i < cred->num_excluded_ssid; i++) {
1205 		struct excluded_ssid *e = &cred->excluded_ssid[i];
1206 		if (bss->ssid_len == e->ssid_len &&
1207 		    os_memcmp(bss->ssid, e->ssid, e->ssid_len) == 0)
1208 			return 1;
1209 	}
1210 
1211 	return 0;
1212 }
1213 
1214 
1215 static int cred_below_min_backhaul(struct wpa_supplicant *wpa_s,
1216 				   struct wpa_cred *cred, struct wpa_bss *bss)
1217 {
1218 #ifdef CONFIG_HS20
1219 	int res;
1220 	unsigned int dl_bandwidth, ul_bandwidth;
1221 	const u8 *wan;
1222 	u8 wan_info, dl_load, ul_load;
1223 	u16 lmd;
1224 	u32 ul_speed, dl_speed;
1225 
1226 	if (!cred->min_dl_bandwidth_home &&
1227 	    !cred->min_ul_bandwidth_home &&
1228 	    !cred->min_dl_bandwidth_roaming &&
1229 	    !cred->min_ul_bandwidth_roaming)
1230 		return 0; /* No bandwidth constraint specified */
1231 
1232 	if (bss->anqp == NULL || bss->anqp->hs20_wan_metrics == NULL)
1233 		return 0; /* No WAN Metrics known - ignore constraint */
1234 
1235 	wan = wpabuf_head(bss->anqp->hs20_wan_metrics);
1236 	wan_info = wan[0];
1237 	if (wan_info & BIT(3))
1238 		return 1; /* WAN link at capacity */
1239 	lmd = WPA_GET_LE16(wan + 11);
1240 	if (lmd == 0)
1241 		return 0; /* Downlink/Uplink Load was not measured */
1242 	dl_speed = WPA_GET_LE32(wan + 1);
1243 	ul_speed = WPA_GET_LE32(wan + 5);
1244 	dl_load = wan[9];
1245 	ul_load = wan[10];
1246 
1247 	if (dl_speed >= 0xffffff)
1248 		dl_bandwidth = dl_speed / 255 * (255 - dl_load);
1249 	else
1250 		dl_bandwidth = dl_speed * (255 - dl_load) / 255;
1251 
1252 	if (ul_speed >= 0xffffff)
1253 		ul_bandwidth = ul_speed / 255 * (255 - ul_load);
1254 	else
1255 		ul_bandwidth = ul_speed * (255 - ul_load) / 255;
1256 
1257 	res = interworking_home_sp_cred(wpa_s, cred, bss->anqp ?
1258 					bss->anqp->domain_name : NULL);
1259 	if (res > 0) {
1260 		if (cred->min_dl_bandwidth_home > dl_bandwidth)
1261 			return 1;
1262 		if (cred->min_ul_bandwidth_home > ul_bandwidth)
1263 			return 1;
1264 	} else {
1265 		if (cred->min_dl_bandwidth_roaming > dl_bandwidth)
1266 			return 1;
1267 		if (cred->min_ul_bandwidth_roaming > ul_bandwidth)
1268 			return 1;
1269 	}
1270 #endif /* CONFIG_HS20 */
1271 
1272 	return 0;
1273 }
1274 
1275 
1276 static int cred_over_max_bss_load(struct wpa_supplicant *wpa_s,
1277 				  struct wpa_cred *cred, struct wpa_bss *bss)
1278 {
1279 	const u8 *ie;
1280 	int res;
1281 
1282 	if (!cred->max_bss_load)
1283 		return 0; /* No BSS Load constraint specified */
1284 
1285 	ie = wpa_bss_get_ie(bss, WLAN_EID_BSS_LOAD);
1286 	if (ie == NULL || ie[1] < 3)
1287 		return 0; /* No BSS Load advertised */
1288 
1289 	res = interworking_home_sp_cred(wpa_s, cred, bss->anqp ?
1290 					bss->anqp->domain_name : NULL);
1291 	if (res <= 0)
1292 		return 0; /* Not a home network */
1293 
1294 	return ie[4] > cred->max_bss_load;
1295 }
1296 
1297 
1298 #ifdef CONFIG_HS20
1299 
1300 static int has_proto_match(const u8 *pos, const u8 *end, u8 proto)
1301 {
1302 	while (end - pos >= 4) {
1303 		if (pos[0] == proto && pos[3] == 1 /* Open */)
1304 			return 1;
1305 		pos += 4;
1306 	}
1307 
1308 	return 0;
1309 }
1310 
1311 
1312 static int has_proto_port_match(const u8 *pos, const u8 *end, u8 proto,
1313 				u16 port)
1314 {
1315 	while (end - pos >= 4) {
1316 		if (pos[0] == proto && WPA_GET_LE16(&pos[1]) == port &&
1317 		    pos[3] == 1 /* Open */)
1318 			return 1;
1319 		pos += 4;
1320 	}
1321 
1322 	return 0;
1323 }
1324 
1325 #endif /* CONFIG_HS20 */
1326 
1327 
1328 static int cred_conn_capab_missing(struct wpa_supplicant *wpa_s,
1329 				   struct wpa_cred *cred, struct wpa_bss *bss)
1330 {
1331 #ifdef CONFIG_HS20
1332 	int res;
1333 	const u8 *capab, *end;
1334 	unsigned int i, j;
1335 	int *ports;
1336 
1337 	if (!cred->num_req_conn_capab)
1338 		return 0; /* No connection capability constraint specified */
1339 
1340 	if (bss->anqp == NULL || bss->anqp->hs20_connection_capability == NULL)
1341 		return 0; /* No Connection Capability known - ignore constraint
1342 			   */
1343 
1344 	res = interworking_home_sp_cred(wpa_s, cred, bss->anqp ?
1345 					bss->anqp->domain_name : NULL);
1346 	if (res > 0)
1347 		return 0; /* No constraint in home network */
1348 
1349 	capab = wpabuf_head(bss->anqp->hs20_connection_capability);
1350 	end = capab + wpabuf_len(bss->anqp->hs20_connection_capability);
1351 
1352 	for (i = 0; i < cred->num_req_conn_capab; i++) {
1353 		ports = cred->req_conn_capab_port[i];
1354 		if (!ports) {
1355 			if (!has_proto_match(capab, end,
1356 					     cred->req_conn_capab_proto[i]))
1357 				return 1;
1358 		} else {
1359 			for (j = 0; ports[j] > -1; j++) {
1360 				if (!has_proto_port_match(
1361 					    capab, end,
1362 					    cred->req_conn_capab_proto[i],
1363 					    ports[j]))
1364 					return 1;
1365 			}
1366 		}
1367 	}
1368 #endif /* CONFIG_HS20 */
1369 
1370 	return 0;
1371 }
1372 
1373 
1374 static struct wpa_cred * interworking_credentials_available_roaming_consortium(
1375 	struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw,
1376 	int *excluded)
1377 {
1378 	struct wpa_cred *cred, *selected = NULL;
1379 	const u8 *ie;
1380 	const struct wpabuf *anqp;
1381 	int is_excluded = 0;
1382 
1383 	ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM);
1384 	anqp = bss->anqp ? bss->anqp->roaming_consortium : NULL;
1385 
1386 	if (!ie && !anqp)
1387 		return NULL;
1388 
1389 	if (wpa_s->conf->cred == NULL)
1390 		return NULL;
1391 
1392 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
1393 		if (cred->roaming_consortium_len == 0 &&
1394 		    cred->num_roaming_consortiums == 0)
1395 			continue;
1396 
1397 		if (!cred->eap_method)
1398 			continue;
1399 
1400 		if ((cred->roaming_consortium_len == 0 ||
1401 		     !roaming_consortium_match(ie, anqp,
1402 					       cred->roaming_consortium,
1403 					       cred->roaming_consortium_len)) &&
1404 		    !cred_roaming_consortiums_match(ie, anqp, cred) &&
1405 		    (cred->required_roaming_consortium_len == 0 ||
1406 		     !roaming_consortium_match(
1407 			     ie, anqp, cred->required_roaming_consortium,
1408 			     cred->required_roaming_consortium_len)))
1409 			continue;
1410 
1411 		if (cred_no_required_oi_match(cred, bss))
1412 			continue;
1413 		if (!ignore_bw && cred_below_min_backhaul(wpa_s, cred, bss))
1414 			continue;
1415 		if (!ignore_bw && cred_over_max_bss_load(wpa_s, cred, bss))
1416 			continue;
1417 		if (!ignore_bw && cred_conn_capab_missing(wpa_s, cred, bss))
1418 			continue;
1419 		if (cred_excluded_ssid(cred, bss)) {
1420 			if (excluded == NULL)
1421 				continue;
1422 			if (selected == NULL) {
1423 				selected = cred;
1424 				is_excluded = 1;
1425 			}
1426 		} else {
1427 			if (selected == NULL || is_excluded ||
1428 			    cred_prio_cmp(selected, cred) < 0) {
1429 				selected = cred;
1430 				is_excluded = 0;
1431 			}
1432 		}
1433 	}
1434 
1435 	if (excluded)
1436 		*excluded = is_excluded;
1437 
1438 	return selected;
1439 }
1440 
1441 
1442 static int interworking_set_eap_params(struct wpa_ssid *ssid,
1443 				       struct wpa_cred *cred, int ttls)
1444 {
1445 	if (cred->eap_method) {
1446 		ttls = cred->eap_method->vendor == EAP_VENDOR_IETF &&
1447 			cred->eap_method->method == EAP_TYPE_TTLS;
1448 
1449 		os_free(ssid->eap.eap_methods);
1450 		ssid->eap.eap_methods =
1451 			os_malloc(sizeof(struct eap_method_type) * 2);
1452 		if (ssid->eap.eap_methods == NULL)
1453 			return -1;
1454 		os_memcpy(ssid->eap.eap_methods, cred->eap_method,
1455 			  sizeof(*cred->eap_method));
1456 		ssid->eap.eap_methods[1].vendor = EAP_VENDOR_IETF;
1457 		ssid->eap.eap_methods[1].method = EAP_TYPE_NONE;
1458 	}
1459 
1460 	if (ttls && cred->username && cred->username[0]) {
1461 		const char *pos;
1462 		char *anon;
1463 		/* Use anonymous NAI in Phase 1 */
1464 		pos = os_strchr(cred->username, '@');
1465 		if (pos) {
1466 			size_t buflen = 9 + os_strlen(pos) + 1;
1467 			anon = os_malloc(buflen);
1468 			if (anon == NULL)
1469 				return -1;
1470 			os_snprintf(anon, buflen, "anonymous%s", pos);
1471 		} else if (cred->realm) {
1472 			size_t buflen = 10 + os_strlen(cred->realm) + 1;
1473 			anon = os_malloc(buflen);
1474 			if (anon == NULL)
1475 				return -1;
1476 			os_snprintf(anon, buflen, "anonymous@%s", cred->realm);
1477 		} else {
1478 			anon = os_strdup("anonymous");
1479 			if (anon == NULL)
1480 				return -1;
1481 		}
1482 		if (wpa_config_set_quoted(ssid, "anonymous_identity", anon) <
1483 		    0) {
1484 			os_free(anon);
1485 			return -1;
1486 		}
1487 		os_free(anon);
1488 	}
1489 
1490 	if (!ttls && cred->username && cred->username[0] && cred->realm &&
1491 	    !os_strchr(cred->username, '@')) {
1492 		char *id;
1493 		size_t buflen;
1494 		int res;
1495 
1496 		buflen = os_strlen(cred->username) + 1 +
1497 			os_strlen(cred->realm) + 1;
1498 
1499 		id = os_malloc(buflen);
1500 		if (!id)
1501 			return -1;
1502 		os_snprintf(id, buflen, "%s@%s", cred->username, cred->realm);
1503 		res = wpa_config_set_quoted(ssid, "identity", id);
1504 		os_free(id);
1505 		if (res < 0)
1506 			return -1;
1507 	} else if (cred->username && cred->username[0] &&
1508 	    wpa_config_set_quoted(ssid, "identity", cred->username) < 0)
1509 		return -1;
1510 
1511 	if (cred->password && cred->password[0]) {
1512 		if (cred->ext_password &&
1513 		    wpa_config_set(ssid, "password", cred->password, 0) < 0)
1514 			return -1;
1515 		if (!cred->ext_password &&
1516 		    wpa_config_set_quoted(ssid, "password", cred->password) <
1517 		    0)
1518 			return -1;
1519 	}
1520 
1521 	if (cred->client_cert && cred->client_cert[0] &&
1522 	    wpa_config_set_quoted(ssid, "client_cert", cred->client_cert) < 0)
1523 		return -1;
1524 
1525 #ifdef ANDROID
1526 	if (cred->private_key &&
1527 	    os_strncmp(cred->private_key, "keystore://", 11) == 0) {
1528 		/* Use OpenSSL engine configuration for Android keystore */
1529 		if (wpa_config_set_quoted(ssid, "engine_id", "keystore") < 0 ||
1530 		    wpa_config_set_quoted(ssid, "key_id",
1531 					  cred->private_key + 11) < 0 ||
1532 		    wpa_config_set(ssid, "engine", "1", 0) < 0)
1533 			return -1;
1534 	} else
1535 #endif /* ANDROID */
1536 	if (cred->private_key && cred->private_key[0] &&
1537 	    wpa_config_set_quoted(ssid, "private_key", cred->private_key) < 0)
1538 		return -1;
1539 
1540 	if (cred->private_key_passwd && cred->private_key_passwd[0] &&
1541 	    wpa_config_set_quoted(ssid, "private_key_passwd",
1542 				  cred->private_key_passwd) < 0)
1543 		return -1;
1544 
1545 	if (cred->ca_cert_id && cred->ca_cert_id[0] &&
1546 	    wpa_config_set_quoted(ssid, "ca_cert_id", cred->ca_cert_id) < 0)
1547 		return -1;
1548 
1549 	if (cred->cert_id && cred->cert_id[0] &&
1550 	    wpa_config_set_quoted(ssid, "cert_id", cred->cert_id) < 0)
1551 		return -1;
1552 
1553 	if (cred->key_id && cred->key_id[0] &&
1554 	    wpa_config_set_quoted(ssid, "key_id", cred->key_id) < 0)
1555 		return -1;
1556 
1557 	if (cred->engine_id && cred->engine_id[0] &&
1558 	    wpa_config_set_quoted(ssid, "engine_id", cred->engine_id) < 0)
1559 		return -1;
1560 
1561 	ssid->eap.cert.engine = cred->engine;
1562 
1563 	if (cred->phase1) {
1564 		os_free(ssid->eap.phase1);
1565 		ssid->eap.phase1 = os_strdup(cred->phase1);
1566 	}
1567 	if (cred->phase2) {
1568 		os_free(ssid->eap.phase2);
1569 		ssid->eap.phase2 = os_strdup(cred->phase2);
1570 	}
1571 
1572 	if (cred->ca_cert && cred->ca_cert[0] &&
1573 	    wpa_config_set_quoted(ssid, "ca_cert", cred->ca_cert) < 0)
1574 		return -1;
1575 
1576 	if (cred->domain_suffix_match && cred->domain_suffix_match[0] &&
1577 	    wpa_config_set_quoted(ssid, "domain_suffix_match",
1578 				  cred->domain_suffix_match) < 0)
1579 		return -1;
1580 
1581 	ssid->eap.cert.ocsp = cred->ocsp;
1582 
1583 	return 0;
1584 }
1585 
1586 
1587 static int interworking_connect_roaming_consortium(
1588 	struct wpa_supplicant *wpa_s, struct wpa_cred *cred,
1589 	struct wpa_bss *bss, int only_add)
1590 {
1591 	struct wpa_ssid *ssid;
1592 	const u8 *ie;
1593 	const struct wpabuf *anqp;
1594 	unsigned int i;
1595 
1596 	wpa_msg(wpa_s, MSG_DEBUG, "Interworking: Connect with " MACSTR
1597 		" based on roaming consortium match", MAC2STR(bss->bssid));
1598 
1599 	if (already_connected(wpa_s, cred, bss)) {
1600 		wpa_msg(wpa_s, MSG_INFO, INTERWORKING_ALREADY_CONNECTED MACSTR,
1601 			MAC2STR(bss->bssid));
1602 		return wpa_s->current_ssid->id;
1603 	}
1604 
1605 	remove_duplicate_network(wpa_s, cred, bss);
1606 
1607 	ssid = wpa_config_add_network(wpa_s->conf);
1608 	if (ssid == NULL)
1609 		return -1;
1610 	ssid->parent_cred = cred;
1611 	wpas_notify_network_added(wpa_s, ssid);
1612 	wpa_config_set_network_defaults(ssid);
1613 	ssid->priority = cred->priority;
1614 	ssid->temporary = 1;
1615 	ssid->ssid = os_zalloc(bss->ssid_len + 1);
1616 	if (ssid->ssid == NULL)
1617 		goto fail;
1618 	os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len);
1619 	ssid->ssid_len = bss->ssid_len;
1620 
1621 	if (interworking_set_hs20_params(wpa_s, ssid) < 0)
1622 		goto fail;
1623 
1624 	ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM);
1625 	anqp = bss->anqp ? bss->anqp->roaming_consortium : NULL;
1626 	for (i = 0; (ie || anqp) && i < cred->num_roaming_consortiums; i++) {
1627 		if (!roaming_consortium_match(
1628 			    ie, anqp, cred->roaming_consortiums[i],
1629 			    cred->roaming_consortiums_len[i]))
1630 			continue;
1631 
1632 		ssid->roaming_consortium_selection =
1633 			os_malloc(cred->roaming_consortiums_len[i]);
1634 		if (!ssid->roaming_consortium_selection)
1635 			goto fail;
1636 		os_memcpy(ssid->roaming_consortium_selection,
1637 			  cred->roaming_consortiums[i],
1638 			  cred->roaming_consortiums_len[i]);
1639 		ssid->roaming_consortium_selection_len =
1640 			cred->roaming_consortiums_len[i];
1641 		break;
1642 	}
1643 
1644 	if (cred->eap_method == NULL) {
1645 		wpa_msg(wpa_s, MSG_DEBUG,
1646 			"Interworking: No EAP method set for credential using roaming consortium");
1647 		goto fail;
1648 	}
1649 
1650 	if (interworking_set_eap_params(
1651 		    ssid, cred,
1652 		    cred->eap_method->vendor == EAP_VENDOR_IETF &&
1653 		    cred->eap_method->method == EAP_TYPE_TTLS) < 0)
1654 		goto fail;
1655 
1656 	wpa_s->next_ssid = ssid;
1657 	wpa_config_update_prio_list(wpa_s->conf);
1658 	if (!only_add)
1659 		interworking_reconnect(wpa_s);
1660 
1661 	return ssid->id;
1662 
1663 fail:
1664 	wpas_notify_network_removed(wpa_s, ssid);
1665 	wpa_config_remove_network(wpa_s->conf, ssid->id);
1666 	return -1;
1667 }
1668 
1669 
1670 int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
1671 			 int only_add)
1672 {
1673 	struct wpa_cred *cred, *cred_rc, *cred_3gpp;
1674 	struct wpa_ssid *ssid;
1675 	struct nai_realm *realm;
1676 	struct nai_realm_eap *eap = NULL;
1677 	u16 count, i;
1678 	char buf[100];
1679 	int excluded = 0, *excl = &excluded;
1680 	const char *name;
1681 
1682 	if (wpa_s->conf->cred == NULL || bss == NULL)
1683 		return -1;
1684 	if (disallowed_bssid(wpa_s, bss->bssid) ||
1685 	    disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) {
1686 		wpa_msg(wpa_s, MSG_DEBUG,
1687 			"Interworking: Reject connection to disallowed BSS "
1688 			MACSTR, MAC2STR(bss->bssid));
1689 		return -1;
1690 	}
1691 
1692 	wpa_printf(MSG_DEBUG, "Interworking: Considering BSS " MACSTR
1693 		   " for connection",
1694 		   MAC2STR(bss->bssid));
1695 
1696 	if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) {
1697 		/*
1698 		 * We currently support only HS 2.0 networks and those are
1699 		 * required to use WPA2-Enterprise.
1700 		 */
1701 		wpa_msg(wpa_s, MSG_DEBUG,
1702 			"Interworking: Network does not use RSN");
1703 		return -1;
1704 	}
1705 
1706 	cred_rc = interworking_credentials_available_roaming_consortium(
1707 		wpa_s, bss, 0, excl);
1708 	if (cred_rc) {
1709 		wpa_msg(wpa_s, MSG_DEBUG,
1710 			"Interworking: Highest roaming consortium matching credential priority %d sp_priority %d",
1711 			cred_rc->priority, cred_rc->sp_priority);
1712 		if (excl && !(*excl))
1713 			excl = NULL;
1714 	}
1715 
1716 	cred = interworking_credentials_available_realm(wpa_s, bss, 0, excl);
1717 	if (cred) {
1718 		wpa_msg(wpa_s, MSG_DEBUG,
1719 			"Interworking: Highest NAI Realm list matching credential priority %d sp_priority %d",
1720 			cred->priority, cred->sp_priority);
1721 		if (excl && !(*excl))
1722 			excl = NULL;
1723 	}
1724 
1725 	cred_3gpp = interworking_credentials_available_3gpp(wpa_s, bss, 0,
1726 							    excl);
1727 	if (cred_3gpp) {
1728 		wpa_msg(wpa_s, MSG_DEBUG,
1729 			"Interworking: Highest 3GPP matching credential priority %d sp_priority %d",
1730 			cred_3gpp->priority, cred_3gpp->sp_priority);
1731 		if (excl && !(*excl))
1732 			excl = NULL;
1733 	}
1734 
1735 	if (!cred_rc && !cred && !cred_3gpp) {
1736 		wpa_msg(wpa_s, MSG_DEBUG,
1737 			"Interworking: No full credential matches - consider options without BW(etc.) limits");
1738 		cred_rc = interworking_credentials_available_roaming_consortium(
1739 			wpa_s, bss, 1, excl);
1740 		if (cred_rc) {
1741 			wpa_msg(wpa_s, MSG_DEBUG,
1742 				"Interworking: Highest roaming consortium matching credential priority %d sp_priority %d (ignore BW)",
1743 				cred_rc->priority, cred_rc->sp_priority);
1744 			if (excl && !(*excl))
1745 				excl = NULL;
1746 		}
1747 
1748 		cred = interworking_credentials_available_realm(wpa_s, bss, 1,
1749 								excl);
1750 		if (cred) {
1751 			wpa_msg(wpa_s, MSG_DEBUG,
1752 				"Interworking: Highest NAI Realm list matching credential priority %d sp_priority %d (ignore BW)",
1753 				cred->priority, cred->sp_priority);
1754 			if (excl && !(*excl))
1755 				excl = NULL;
1756 		}
1757 
1758 		cred_3gpp = interworking_credentials_available_3gpp(wpa_s, bss,
1759 								    1, excl);
1760 		if (cred_3gpp) {
1761 			wpa_msg(wpa_s, MSG_DEBUG,
1762 				"Interworking: Highest 3GPP matching credential priority %d sp_priority %d (ignore BW)",
1763 				cred_3gpp->priority, cred_3gpp->sp_priority);
1764 			if (excl && !(*excl))
1765 				excl = NULL;
1766 		}
1767 	}
1768 
1769 	if (cred_rc &&
1770 	    (cred == NULL || cred_prio_cmp(cred_rc, cred) >= 0) &&
1771 	    (cred_3gpp == NULL || cred_prio_cmp(cred_rc, cred_3gpp) >= 0))
1772 		return interworking_connect_roaming_consortium(wpa_s, cred_rc,
1773 							       bss, only_add);
1774 
1775 	if (cred_3gpp &&
1776 	    (cred == NULL || cred_prio_cmp(cred_3gpp, cred) >= 0)) {
1777 		return interworking_connect_3gpp(wpa_s, cred_3gpp, bss,
1778 						 only_add);
1779 	}
1780 
1781 	if (cred == NULL) {
1782 		wpa_msg(wpa_s, MSG_DEBUG,
1783 			"Interworking: No matching credentials found for "
1784 			MACSTR, MAC2STR(bss->bssid));
1785 		return -1;
1786 	}
1787 
1788 	realm = nai_realm_parse(bss->anqp ? bss->anqp->nai_realm : NULL,
1789 				&count);
1790 	if (realm == NULL) {
1791 		wpa_msg(wpa_s, MSG_DEBUG,
1792 			"Interworking: Could not parse NAI Realm list from "
1793 			MACSTR, MAC2STR(bss->bssid));
1794 		return -1;
1795 	}
1796 
1797 	for (i = 0; i < count; i++) {
1798 		if (!nai_realm_match(&realm[i], cred->realm))
1799 			continue;
1800 		eap = nai_realm_find_eap(wpa_s, cred, &realm[i]);
1801 		if (eap)
1802 			break;
1803 	}
1804 
1805 	if (!eap) {
1806 		wpa_msg(wpa_s, MSG_DEBUG,
1807 			"Interworking: No matching credentials and EAP method found for "
1808 			MACSTR, MAC2STR(bss->bssid));
1809 		nai_realm_free(realm, count);
1810 		return -1;
1811 	}
1812 
1813 	wpa_msg(wpa_s, MSG_DEBUG, "Interworking: Connect with " MACSTR,
1814 		MAC2STR(bss->bssid));
1815 
1816 	if (already_connected(wpa_s, cred, bss)) {
1817 		wpa_msg(wpa_s, MSG_INFO, INTERWORKING_ALREADY_CONNECTED MACSTR,
1818 			MAC2STR(bss->bssid));
1819 		nai_realm_free(realm, count);
1820 		return 0;
1821 	}
1822 
1823 	remove_duplicate_network(wpa_s, cred, bss);
1824 
1825 	ssid = wpa_config_add_network(wpa_s->conf);
1826 	if (ssid == NULL) {
1827 		nai_realm_free(realm, count);
1828 		return -1;
1829 	}
1830 	ssid->parent_cred = cred;
1831 	wpas_notify_network_added(wpa_s, ssid);
1832 	wpa_config_set_network_defaults(ssid);
1833 	ssid->priority = cred->priority;
1834 	ssid->temporary = 1;
1835 	ssid->ssid = os_zalloc(bss->ssid_len + 1);
1836 	if (ssid->ssid == NULL)
1837 		goto fail;
1838 	os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len);
1839 	ssid->ssid_len = bss->ssid_len;
1840 
1841 	if (interworking_set_hs20_params(wpa_s, ssid) < 0)
1842 		goto fail;
1843 
1844 	if (wpa_config_set(ssid, "eap", eap_get_name(EAP_VENDOR_IETF,
1845 						     eap->method), 0) < 0)
1846 		goto fail;
1847 
1848 	switch (eap->method) {
1849 	case EAP_TYPE_TTLS:
1850 		if (eap->inner_method) {
1851 			name = eap_get_name(EAP_VENDOR_IETF, eap->inner_method);
1852 			if (!name)
1853 				goto fail;
1854 			os_snprintf(buf, sizeof(buf), "\"autheap=%s\"", name);
1855 			if (wpa_config_set(ssid, "phase2", buf, 0) < 0)
1856 				goto fail;
1857 			break;
1858 		}
1859 		switch (eap->inner_non_eap) {
1860 		case NAI_REALM_INNER_NON_EAP_PAP:
1861 			if (wpa_config_set(ssid, "phase2", "\"auth=PAP\"", 0) <
1862 			    0)
1863 				goto fail;
1864 			break;
1865 		case NAI_REALM_INNER_NON_EAP_CHAP:
1866 			if (wpa_config_set(ssid, "phase2", "\"auth=CHAP\"", 0)
1867 			    < 0)
1868 				goto fail;
1869 			break;
1870 		case NAI_REALM_INNER_NON_EAP_MSCHAP:
1871 			if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAP\"",
1872 					   0) < 0)
1873 				goto fail;
1874 			break;
1875 		case NAI_REALM_INNER_NON_EAP_MSCHAPV2:
1876 			if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAPV2\"",
1877 					   0) < 0)
1878 				goto fail;
1879 			break;
1880 		default:
1881 			/* EAP params were not set - assume TTLS/MSCHAPv2 */
1882 			if (wpa_config_set(ssid, "phase2", "\"auth=MSCHAPV2\"",
1883 					   0) < 0)
1884 				goto fail;
1885 			break;
1886 		}
1887 		break;
1888 	case EAP_TYPE_PEAP:
1889 	case EAP_TYPE_FAST:
1890 		if (wpa_config_set(ssid, "phase1", "\"fast_provisioning=2\"",
1891 				   0) < 0)
1892 			goto fail;
1893 		if (wpa_config_set(ssid, "pac_file",
1894 				   "\"blob://pac_interworking\"", 0) < 0)
1895 			goto fail;
1896 		name = eap_get_name(EAP_VENDOR_IETF,
1897 				    eap->inner_method ? eap->inner_method :
1898 				    EAP_TYPE_MSCHAPV2);
1899 		if (name == NULL)
1900 			goto fail;
1901 		os_snprintf(buf, sizeof(buf), "\"auth=%s\"", name);
1902 		if (wpa_config_set(ssid, "phase2", buf, 0) < 0)
1903 			goto fail;
1904 		break;
1905 	case EAP_TYPE_TLS:
1906 		break;
1907 	}
1908 
1909 	if (interworking_set_eap_params(ssid, cred,
1910 					eap->method == EAP_TYPE_TTLS) < 0)
1911 		goto fail;
1912 
1913 	nai_realm_free(realm, count);
1914 
1915 	wpa_s->next_ssid = ssid;
1916 	wpa_config_update_prio_list(wpa_s->conf);
1917 	if (!only_add)
1918 		interworking_reconnect(wpa_s);
1919 
1920 	return ssid->id;
1921 
1922 fail:
1923 	wpas_notify_network_removed(wpa_s, ssid);
1924 	wpa_config_remove_network(wpa_s->conf, ssid->id);
1925 	nai_realm_free(realm, count);
1926 	return -1;
1927 }
1928 
1929 
1930 #ifdef PCSC_FUNCS
1931 static int interworking_pcsc_read_imsi(struct wpa_supplicant *wpa_s)
1932 {
1933 	size_t len;
1934 
1935 	if (wpa_s->imsi[0] && wpa_s->mnc_len)
1936 		return 0;
1937 
1938 	len = sizeof(wpa_s->imsi) - 1;
1939 	if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
1940 		scard_deinit(wpa_s->scard);
1941 		wpa_s->scard = NULL;
1942 		wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
1943 		return -1;
1944 	}
1945 	wpa_s->imsi[len] = '\0';
1946 	wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
1947 	wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
1948 		   wpa_s->imsi, wpa_s->mnc_len);
1949 
1950 	return 0;
1951 }
1952 #endif /* PCSC_FUNCS */
1953 
1954 
1955 static struct wpa_cred * interworking_credentials_available_3gpp(
1956 	struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw,
1957 	int *excluded)
1958 {
1959 	struct wpa_cred *selected = NULL;
1960 #ifdef INTERWORKING_3GPP
1961 	struct wpa_cred *cred;
1962 	int ret;
1963 	int is_excluded = 0;
1964 
1965 	if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL) {
1966 		wpa_msg(wpa_s, MSG_DEBUG,
1967 			"interworking-avail-3gpp: not avail, anqp: %p  anqp_3gpp: %p",
1968 			bss->anqp, bss->anqp ? bss->anqp->anqp_3gpp : NULL);
1969 		return NULL;
1970 	}
1971 
1972 #ifdef CONFIG_EAP_PROXY
1973 	if (!wpa_s->imsi[0]) {
1974 		size_t len;
1975 		wpa_msg(wpa_s, MSG_DEBUG,
1976 			"Interworking: IMSI not available - try to read again through eap_proxy");
1977 		wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,
1978 							     wpa_s->imsi,
1979 							     &len);
1980 		if (wpa_s->mnc_len > 0) {
1981 			wpa_s->imsi[len] = '\0';
1982 			wpa_msg(wpa_s, MSG_DEBUG,
1983 				"eap_proxy: IMSI %s (MNC length %d)",
1984 				wpa_s->imsi, wpa_s->mnc_len);
1985 		} else {
1986 			wpa_msg(wpa_s, MSG_DEBUG,
1987 				"eap_proxy: IMSI not available");
1988 		}
1989 	}
1990 #endif /* CONFIG_EAP_PROXY */
1991 
1992 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
1993 		char *sep;
1994 		const char *imsi;
1995 		int mnc_len;
1996 		char imsi_buf[16];
1997 		size_t msin_len;
1998 
1999 #ifdef PCSC_FUNCS
2000 		if (cred->pcsc && wpa_s->scard) {
2001 			if (interworking_pcsc_read_imsi(wpa_s) < 0)
2002 				continue;
2003 			imsi = wpa_s->imsi;
2004 			mnc_len = wpa_s->mnc_len;
2005 			goto compare;
2006 		}
2007 #endif /* PCSC_FUNCS */
2008 #ifdef CONFIG_EAP_PROXY
2009 		if (cred->pcsc && wpa_s->mnc_len > 0 && wpa_s->imsi[0]) {
2010 			imsi = wpa_s->imsi;
2011 			mnc_len = wpa_s->mnc_len;
2012 			goto compare;
2013 		}
2014 #endif /* CONFIG_EAP_PROXY */
2015 
2016 		if (cred->imsi == NULL || !cred->imsi[0] ||
2017 		    (!wpa_s->conf->external_sim &&
2018 		     (cred->milenage == NULL || !cred->milenage[0])))
2019 			continue;
2020 
2021 		sep = os_strchr(cred->imsi, '-');
2022 		if (sep == NULL ||
2023 		    (sep - cred->imsi != 5 && sep - cred->imsi != 6))
2024 			continue;
2025 		mnc_len = sep - cred->imsi - 3;
2026 		os_memcpy(imsi_buf, cred->imsi, 3 + mnc_len);
2027 		sep++;
2028 		msin_len = os_strlen(cred->imsi);
2029 		if (3 + mnc_len + msin_len >= sizeof(imsi_buf) - 1)
2030 			msin_len = sizeof(imsi_buf) - 3 - mnc_len - 1;
2031 		os_memcpy(&imsi_buf[3 + mnc_len], sep, msin_len);
2032 		imsi_buf[3 + mnc_len + msin_len] = '\0';
2033 		imsi = imsi_buf;
2034 
2035 #if defined(PCSC_FUNCS) || defined(CONFIG_EAP_PROXY)
2036 	compare:
2037 #endif /* PCSC_FUNCS || CONFIG_EAP_PROXY */
2038 		wpa_msg(wpa_s, MSG_DEBUG,
2039 			"Interworking: Parsing 3GPP info from " MACSTR,
2040 			MAC2STR(bss->bssid));
2041 		ret = plmn_id_match(bss->anqp->anqp_3gpp, imsi, mnc_len);
2042 		wpa_msg(wpa_s, MSG_DEBUG, "PLMN match %sfound",
2043 			ret ? "" : "not ");
2044 		if (ret) {
2045 			if (cred_no_required_oi_match(cred, bss))
2046 				continue;
2047 			if (!ignore_bw &&
2048 			    cred_below_min_backhaul(wpa_s, cred, bss))
2049 				continue;
2050 			if (!ignore_bw &&
2051 			    cred_over_max_bss_load(wpa_s, cred, bss))
2052 				continue;
2053 			if (!ignore_bw &&
2054 			    cred_conn_capab_missing(wpa_s, cred, bss))
2055 				continue;
2056 			if (cred_excluded_ssid(cred, bss)) {
2057 				if (excluded == NULL)
2058 					continue;
2059 				if (selected == NULL) {
2060 					selected = cred;
2061 					is_excluded = 1;
2062 				}
2063 			} else {
2064 				if (selected == NULL || is_excluded ||
2065 				    cred_prio_cmp(selected, cred) < 0) {
2066 					selected = cred;
2067 					is_excluded = 0;
2068 				}
2069 			}
2070 		}
2071 	}
2072 
2073 	if (excluded)
2074 		*excluded = is_excluded;
2075 #endif /* INTERWORKING_3GPP */
2076 	return selected;
2077 }
2078 
2079 
2080 static struct wpa_cred * interworking_credentials_available_realm(
2081 	struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw,
2082 	int *excluded)
2083 {
2084 	struct wpa_cred *cred, *selected = NULL;
2085 	struct nai_realm *realm;
2086 	u16 count, i;
2087 	int is_excluded = 0;
2088 
2089 	if (bss->anqp == NULL || bss->anqp->nai_realm == NULL)
2090 		return NULL;
2091 
2092 	if (wpa_s->conf->cred == NULL)
2093 		return NULL;
2094 
2095 	wpa_msg(wpa_s, MSG_DEBUG, "Interworking: Parsing NAI Realm list from "
2096 		MACSTR, MAC2STR(bss->bssid));
2097 	realm = nai_realm_parse(bss->anqp->nai_realm, &count);
2098 	if (realm == NULL) {
2099 		wpa_msg(wpa_s, MSG_DEBUG,
2100 			"Interworking: Could not parse NAI Realm list from "
2101 			MACSTR, MAC2STR(bss->bssid));
2102 		return NULL;
2103 	}
2104 
2105 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
2106 		if (cred->realm == NULL)
2107 			continue;
2108 
2109 		for (i = 0; i < count; i++) {
2110 			if (!nai_realm_match(&realm[i], cred->realm))
2111 				continue;
2112 			if (nai_realm_find_eap(wpa_s, cred, &realm[i])) {
2113 				if (cred_no_required_oi_match(cred, bss))
2114 					continue;
2115 				if (!ignore_bw &&
2116 				    cred_below_min_backhaul(wpa_s, cred, bss))
2117 					continue;
2118 				if (!ignore_bw &&
2119 				    cred_over_max_bss_load(wpa_s, cred, bss))
2120 					continue;
2121 				if (!ignore_bw &&
2122 				    cred_conn_capab_missing(wpa_s, cred, bss))
2123 					continue;
2124 				if (cred_excluded_ssid(cred, bss)) {
2125 					if (excluded == NULL)
2126 						continue;
2127 					if (selected == NULL) {
2128 						selected = cred;
2129 						is_excluded = 1;
2130 					}
2131 				} else {
2132 					if (selected == NULL || is_excluded ||
2133 					    cred_prio_cmp(selected, cred) < 0)
2134 					{
2135 						selected = cred;
2136 						is_excluded = 0;
2137 					}
2138 				}
2139 				break;
2140 			} else {
2141 				wpa_msg(wpa_s, MSG_DEBUG,
2142 					"Interworking: realm-find-eap returned false");
2143 			}
2144 		}
2145 	}
2146 
2147 	nai_realm_free(realm, count);
2148 
2149 	if (excluded)
2150 		*excluded = is_excluded;
2151 
2152 	return selected;
2153 }
2154 
2155 
2156 static struct wpa_cred * interworking_credentials_available_helper(
2157 	struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int ignore_bw,
2158 	int *excluded)
2159 {
2160 	struct wpa_cred *cred, *cred2;
2161 	int excluded1, excluded2 = 0;
2162 
2163 	if (disallowed_bssid(wpa_s, bss->bssid) ||
2164 	    disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) {
2165 		wpa_printf(MSG_DEBUG, "Interworking: Ignore disallowed BSS "
2166 			   MACSTR, MAC2STR(bss->bssid));
2167 		return NULL;
2168 	}
2169 
2170 	cred = interworking_credentials_available_realm(wpa_s, bss, ignore_bw,
2171 							&excluded1);
2172 	cred2 = interworking_credentials_available_3gpp(wpa_s, bss, ignore_bw,
2173 							&excluded2);
2174 	if (cred && cred2 &&
2175 	    (cred_prio_cmp(cred2, cred) >= 0 || (!excluded2 && excluded1))) {
2176 		cred = cred2;
2177 		excluded1 = excluded2;
2178 	}
2179 	if (!cred) {
2180 		cred = cred2;
2181 		excluded1 = excluded2;
2182 	}
2183 
2184 	cred2 = interworking_credentials_available_roaming_consortium(
2185 		wpa_s, bss, ignore_bw, &excluded2);
2186 	if (cred && cred2 &&
2187 	    (cred_prio_cmp(cred2, cred) >= 0 || (!excluded2 && excluded1))) {
2188 		cred = cred2;
2189 		excluded1 = excluded2;
2190 	}
2191 	if (!cred) {
2192 		cred = cred2;
2193 		excluded1 = excluded2;
2194 	}
2195 
2196 	if (excluded)
2197 		*excluded = excluded1;
2198 	return cred;
2199 }
2200 
2201 
2202 static struct wpa_cred * interworking_credentials_available(
2203 	struct wpa_supplicant *wpa_s, struct wpa_bss *bss, int *excluded)
2204 {
2205 	struct wpa_cred *cred;
2206 
2207 	if (excluded)
2208 		*excluded = 0;
2209 	cred = interworking_credentials_available_helper(wpa_s, bss, 0,
2210 							 excluded);
2211 	if (cred)
2212 		return cred;
2213 	return interworking_credentials_available_helper(wpa_s, bss, 1,
2214 							 excluded);
2215 }
2216 
2217 
2218 int domain_name_list_contains(struct wpabuf *domain_names,
2219 			      const char *domain, int exact_match)
2220 {
2221 	const u8 *pos, *end;
2222 	size_t len;
2223 
2224 	len = os_strlen(domain);
2225 	pos = wpabuf_head(domain_names);
2226 	end = pos + wpabuf_len(domain_names);
2227 
2228 	while (end - pos > 1) {
2229 		u8 elen;
2230 
2231 		elen = *pos++;
2232 		if (elen > end - pos)
2233 			break;
2234 
2235 		wpa_hexdump_ascii(MSG_DEBUG, "Interworking: AP domain name",
2236 				  pos, elen);
2237 		if (elen == len &&
2238 		    os_strncasecmp(domain, (const char *) pos, len) == 0)
2239 			return 1;
2240 		if (!exact_match && elen > len && pos[elen - len - 1] == '.') {
2241 			const char *ap = (const char *) pos;
2242 			int offset = elen - len;
2243 
2244 			if (os_strncasecmp(domain, ap + offset, len) == 0)
2245 				return 1;
2246 		}
2247 
2248 		pos += elen;
2249 	}
2250 
2251 	return 0;
2252 }
2253 
2254 
2255 int interworking_home_sp_cred(struct wpa_supplicant *wpa_s,
2256 			      struct wpa_cred *cred,
2257 			      struct wpabuf *domain_names)
2258 {
2259 	size_t i;
2260 	int ret = -1;
2261 #ifdef INTERWORKING_3GPP
2262 	char nai[100], *realm;
2263 
2264 	char *imsi = NULL;
2265 	int mnc_len = 0;
2266 	if (cred->imsi)
2267 		imsi = cred->imsi;
2268 #ifdef PCSC_FUNCS
2269 	else if (cred->pcsc && wpa_s->scard) {
2270 		if (interworking_pcsc_read_imsi(wpa_s) < 0)
2271 			return -1;
2272 		imsi = wpa_s->imsi;
2273 		mnc_len = wpa_s->mnc_len;
2274 	}
2275 #endif /* PCSC_FUNCS */
2276 #ifdef CONFIG_EAP_PROXY
2277 	else if (cred->pcsc && wpa_s->mnc_len > 0 && wpa_s->imsi[0]) {
2278 		imsi = wpa_s->imsi;
2279 		mnc_len = wpa_s->mnc_len;
2280 	}
2281 #endif /* CONFIG_EAP_PROXY */
2282 	if (domain_names &&
2283 	    imsi && build_root_nai(nai, sizeof(nai), imsi, mnc_len, 0) == 0) {
2284 		realm = os_strchr(nai, '@');
2285 		if (realm)
2286 			realm++;
2287 		wpa_msg(wpa_s, MSG_DEBUG,
2288 			"Interworking: Search for match with SIM/USIM domain %s",
2289 			realm ? realm : "[NULL]");
2290 		if (realm &&
2291 		    domain_name_list_contains(domain_names, realm, 1))
2292 			return 1;
2293 		if (realm)
2294 			ret = 0;
2295 	}
2296 #endif /* INTERWORKING_3GPP */
2297 
2298 	if (domain_names == NULL || cred->domain == NULL)
2299 		return ret;
2300 
2301 	for (i = 0; i < cred->num_domain; i++) {
2302 		wpa_msg(wpa_s, MSG_DEBUG,
2303 			"Interworking: Search for match with home SP FQDN %s",
2304 			cred->domain[i]);
2305 		if (domain_name_list_contains(domain_names, cred->domain[i], 1))
2306 			return 1;
2307 	}
2308 
2309 	return 0;
2310 }
2311 
2312 
2313 static int interworking_home_sp(struct wpa_supplicant *wpa_s,
2314 				struct wpabuf *domain_names)
2315 {
2316 	struct wpa_cred *cred;
2317 
2318 	if (domain_names == NULL || wpa_s->conf->cred == NULL)
2319 		return -1;
2320 
2321 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
2322 		int res = interworking_home_sp_cred(wpa_s, cred, domain_names);
2323 		if (res)
2324 			return res;
2325 	}
2326 
2327 	return 0;
2328 }
2329 
2330 
2331 static int interworking_find_network_match(struct wpa_supplicant *wpa_s)
2332 {
2333 	struct wpa_bss *bss;
2334 	struct wpa_ssid *ssid;
2335 
2336 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2337 		for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
2338 			if (wpas_network_disabled(wpa_s, ssid) ||
2339 			    ssid->mode != WPAS_MODE_INFRA)
2340 				continue;
2341 			if (ssid->ssid_len != bss->ssid_len ||
2342 			    os_memcmp(ssid->ssid, bss->ssid, ssid->ssid_len) !=
2343 			    0)
2344 				continue;
2345 			/*
2346 			 * TODO: Consider more accurate matching of security
2347 			 * configuration similarly to what is done in events.c
2348 			 */
2349 			return 1;
2350 		}
2351 	}
2352 
2353 	return 0;
2354 }
2355 
2356 
2357 static int roaming_partner_match(struct wpa_supplicant *wpa_s,
2358 				 struct roaming_partner *partner,
2359 				 struct wpabuf *domain_names)
2360 {
2361 	wpa_printf(MSG_DEBUG, "Interworking: Comparing roaming_partner info fqdn='%s' exact_match=%d priority=%u country='%s'",
2362 		   partner->fqdn, partner->exact_match, partner->priority,
2363 		   partner->country);
2364 	wpa_hexdump_ascii(MSG_DEBUG, "Interworking: Domain names",
2365 			  wpabuf_head(domain_names),
2366 			  wpabuf_len(domain_names));
2367 	if (!domain_name_list_contains(domain_names, partner->fqdn,
2368 				       partner->exact_match))
2369 		return 0;
2370 	/* TODO: match Country */
2371 	return 1;
2372 }
2373 
2374 
2375 static u8 roaming_prio(struct wpa_supplicant *wpa_s, struct wpa_cred *cred,
2376 		       struct wpa_bss *bss)
2377 {
2378 	size_t i;
2379 
2380 	if (bss->anqp == NULL || bss->anqp->domain_name == NULL) {
2381 		wpa_printf(MSG_DEBUG, "Interworking: No ANQP domain name info -> use default roaming partner priority 128");
2382 		return 128; /* cannot check preference with domain name */
2383 	}
2384 
2385 	if (interworking_home_sp_cred(wpa_s, cred, bss->anqp->domain_name) > 0)
2386 	{
2387 		wpa_printf(MSG_DEBUG, "Interworking: Determined to be home SP -> use maximum preference 0 as roaming partner priority");
2388 		return 0; /* max preference for home SP network */
2389 	}
2390 
2391 	for (i = 0; i < cred->num_roaming_partner; i++) {
2392 		if (roaming_partner_match(wpa_s, &cred->roaming_partner[i],
2393 					  bss->anqp->domain_name)) {
2394 			wpa_printf(MSG_DEBUG, "Interworking: Roaming partner preference match - priority %u",
2395 				   cred->roaming_partner[i].priority);
2396 			return cred->roaming_partner[i].priority;
2397 		}
2398 	}
2399 
2400 	wpa_printf(MSG_DEBUG, "Interworking: No roaming partner preference match - use default roaming partner priority 128");
2401 	return 128;
2402 }
2403 
2404 
2405 static struct wpa_bss * pick_best_roaming_partner(struct wpa_supplicant *wpa_s,
2406 						  struct wpa_bss *selected,
2407 						  struct wpa_cred *cred)
2408 {
2409 	struct wpa_bss *bss;
2410 	u8 best_prio, prio;
2411 	struct wpa_cred *cred2;
2412 
2413 	/*
2414 	 * Check if any other BSS is operated by a more preferred roaming
2415 	 * partner.
2416 	 */
2417 
2418 	best_prio = roaming_prio(wpa_s, cred, selected);
2419 	wpa_printf(MSG_DEBUG, "Interworking: roaming_prio=%u for selected BSS "
2420 		   MACSTR " (cred=%d)", best_prio, MAC2STR(selected->bssid),
2421 		   cred->id);
2422 
2423 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2424 		if (bss == selected)
2425 			continue;
2426 		cred2 = interworking_credentials_available(wpa_s, bss, NULL);
2427 		if (!cred2)
2428 			continue;
2429 		if (!wpa_bss_get_ie(bss, WLAN_EID_RSN))
2430 			continue;
2431 		prio = roaming_prio(wpa_s, cred2, bss);
2432 		wpa_printf(MSG_DEBUG, "Interworking: roaming_prio=%u for BSS "
2433 			   MACSTR " (cred=%d)", prio, MAC2STR(bss->bssid),
2434 			   cred2->id);
2435 		if (prio < best_prio) {
2436 			int bh1, bh2, load1, load2, conn1, conn2;
2437 			bh1 = cred_below_min_backhaul(wpa_s, cred, selected);
2438 			load1 = cred_over_max_bss_load(wpa_s, cred, selected);
2439 			conn1 = cred_conn_capab_missing(wpa_s, cred, selected);
2440 			bh2 = cred_below_min_backhaul(wpa_s, cred2, bss);
2441 			load2 = cred_over_max_bss_load(wpa_s, cred2, bss);
2442 			conn2 = cred_conn_capab_missing(wpa_s, cred2, bss);
2443 			wpa_printf(MSG_DEBUG, "Interworking: old: %d %d %d  new: %d %d %d",
2444 				   bh1, load1, conn1, bh2, load2, conn2);
2445 			if (bh1 || load1 || conn1 || !(bh2 || load2 || conn2)) {
2446 				wpa_printf(MSG_DEBUG, "Interworking: Better roaming partner " MACSTR " selected", MAC2STR(bss->bssid));
2447 				best_prio = prio;
2448 				selected = bss;
2449 			}
2450 		}
2451 	}
2452 
2453 	return selected;
2454 }
2455 
2456 
2457 static void interworking_select_network(struct wpa_supplicant *wpa_s)
2458 {
2459 	struct wpa_bss *bss, *selected = NULL, *selected_home = NULL;
2460 	struct wpa_bss *selected2 = NULL, *selected2_home = NULL;
2461 	unsigned int count = 0;
2462 	const char *type;
2463 	int res;
2464 	struct wpa_cred *cred, *selected_cred = NULL;
2465 	struct wpa_cred *selected_home_cred = NULL;
2466 	struct wpa_cred *selected2_cred = NULL;
2467 	struct wpa_cred *selected2_home_cred = NULL;
2468 
2469 	wpa_s->network_select = 0;
2470 
2471 	wpa_printf(MSG_DEBUG, "Interworking: Select network (auto_select=%d)",
2472 		   wpa_s->auto_select);
2473 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2474 		int excluded = 0;
2475 		int bh, bss_load, conn_capab;
2476 		cred = interworking_credentials_available(wpa_s, bss,
2477 							  &excluded);
2478 		if (!cred)
2479 			continue;
2480 
2481 		if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) {
2482 			/*
2483 			 * We currently support only HS 2.0 networks and those
2484 			 * are required to use WPA2-Enterprise.
2485 			 */
2486 			wpa_msg(wpa_s, MSG_DEBUG,
2487 				"Interworking: Credential match with " MACSTR
2488 				" but network does not use RSN",
2489 				MAC2STR(bss->bssid));
2490 			continue;
2491 		}
2492 		if (!excluded)
2493 			count++;
2494 		res = interworking_home_sp(wpa_s, bss->anqp ?
2495 					   bss->anqp->domain_name : NULL);
2496 		if (res > 0)
2497 			type = "home";
2498 		else if (res == 0)
2499 			type = "roaming";
2500 		else
2501 			type = "unknown";
2502 		bh = cred_below_min_backhaul(wpa_s, cred, bss);
2503 		bss_load = cred_over_max_bss_load(wpa_s, cred, bss);
2504 		conn_capab = cred_conn_capab_missing(wpa_s, cred, bss);
2505 		wpas_notify_interworking_ap_added(wpa_s, bss, cred, excluded,
2506 						  type, bh, bss_load,
2507 						  conn_capab);
2508 		if (excluded)
2509 			continue;
2510 		if (wpa_s->auto_select ||
2511 		    (wpa_s->conf->auto_interworking &&
2512 		     wpa_s->auto_network_select)) {
2513 			if (bh || bss_load || conn_capab) {
2514 				if (selected2_cred == NULL ||
2515 				    cred_prio_cmp(cred, selected2_cred) > 0) {
2516 					wpa_printf(MSG_DEBUG, "Interworking: Mark as selected2");
2517 					selected2 = bss;
2518 					selected2_cred = cred;
2519 				}
2520 				if (res > 0 &&
2521 				    (selected2_home_cred == NULL ||
2522 				     cred_prio_cmp(cred, selected2_home_cred) >
2523 				     0)) {
2524 					wpa_printf(MSG_DEBUG, "Interworking: Mark as selected2_home");
2525 					selected2_home = bss;
2526 					selected2_home_cred = cred;
2527 				}
2528 			} else {
2529 				if (selected_cred == NULL ||
2530 				    cred_prio_cmp(cred, selected_cred) > 0) {
2531 					wpa_printf(MSG_DEBUG, "Interworking: Mark as selected");
2532 					selected = bss;
2533 					selected_cred = cred;
2534 				}
2535 				if (res > 0 &&
2536 				    (selected_home_cred == NULL ||
2537 				     cred_prio_cmp(cred, selected_home_cred) >
2538 				     0)) {
2539 					wpa_printf(MSG_DEBUG, "Interworking: Mark as selected_home");
2540 					selected_home = bss;
2541 					selected_home_cred = cred;
2542 				}
2543 			}
2544 		}
2545 	}
2546 
2547 	if (selected_home && selected_home != selected &&
2548 	    selected_home_cred &&
2549 	    (selected_cred == NULL ||
2550 	     cred_prio_cmp(selected_home_cred, selected_cred) >= 0)) {
2551 		/* Prefer network operated by the Home SP */
2552 		wpa_printf(MSG_DEBUG, "Interworking: Overrode selected with selected_home");
2553 		selected = selected_home;
2554 		selected_cred = selected_home_cred;
2555 	}
2556 
2557 	if (!selected) {
2558 		if (selected2_home) {
2559 			wpa_printf(MSG_DEBUG, "Interworking: Use home BSS with BW limit mismatch since no other network could be selected");
2560 			selected = selected2_home;
2561 			selected_cred = selected2_home_cred;
2562 		} else if (selected2) {
2563 			wpa_printf(MSG_DEBUG, "Interworking: Use visited BSS with BW limit mismatch since no other network could be selected");
2564 			selected = selected2;
2565 			selected_cred = selected2_cred;
2566 		}
2567 	}
2568 
2569 	if (count == 0) {
2570 		/*
2571 		 * No matching network was found based on configured
2572 		 * credentials. Check whether any of the enabled network blocks
2573 		 * have matching APs.
2574 		 */
2575 		if (interworking_find_network_match(wpa_s)) {
2576 			wpa_msg(wpa_s, MSG_DEBUG,
2577 				"Interworking: Possible BSS match for enabled network configurations");
2578 			if (wpa_s->auto_select) {
2579 				interworking_reconnect(wpa_s);
2580 				return;
2581 			}
2582 		}
2583 
2584 		if (wpa_s->auto_network_select) {
2585 			wpa_msg(wpa_s, MSG_DEBUG,
2586 				"Interworking: Continue scanning after ANQP fetch");
2587 			wpa_supplicant_req_scan(wpa_s, wpa_s->scan_interval,
2588 						0);
2589 			return;
2590 		}
2591 
2592 		wpa_msg(wpa_s, MSG_INFO, INTERWORKING_NO_MATCH "No network "
2593 			"with matching credentials found");
2594 		if (wpa_s->wpa_state == WPA_SCANNING)
2595 			wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2596 	}
2597 
2598 	wpas_notify_interworking_select_done(wpa_s);
2599 
2600 	if (selected) {
2601 		wpa_printf(MSG_DEBUG, "Interworking: Selected " MACSTR,
2602 			   MAC2STR(selected->bssid));
2603 		selected = pick_best_roaming_partner(wpa_s, selected,
2604 						     selected_cred);
2605 		wpa_printf(MSG_DEBUG, "Interworking: Selected " MACSTR
2606 			   " (after best roaming partner selection)",
2607 			   MAC2STR(selected->bssid));
2608 		wpa_msg(wpa_s, MSG_INFO, INTERWORKING_SELECTED MACSTR,
2609 			MAC2STR(selected->bssid));
2610 		interworking_connect(wpa_s, selected, 0);
2611 	} else if (wpa_s->wpa_state == WPA_SCANNING)
2612 		wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2613 }
2614 
2615 
2616 static struct wpa_bss_anqp *
2617 interworking_match_anqp_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
2618 {
2619 	struct wpa_bss *other;
2620 
2621 	if (is_zero_ether_addr(bss->hessid))
2622 		return NULL; /* Cannot be in the same homegenous ESS */
2623 
2624 	dl_list_for_each(other, &wpa_s->bss, struct wpa_bss, list) {
2625 		if (other == bss)
2626 			continue;
2627 		if (other->anqp == NULL)
2628 			continue;
2629 		if (other->anqp->roaming_consortium == NULL &&
2630 		    other->anqp->nai_realm == NULL &&
2631 		    other->anqp->anqp_3gpp == NULL &&
2632 		    other->anqp->domain_name == NULL)
2633 			continue;
2634 		if (!(other->flags & WPA_BSS_ANQP_FETCH_TRIED))
2635 			continue;
2636 		if (os_memcmp(bss->hessid, other->hessid, ETH_ALEN) != 0)
2637 			continue;
2638 		if (bss->ssid_len != other->ssid_len ||
2639 		    os_memcmp(bss->ssid, other->ssid, bss->ssid_len) != 0)
2640 			continue;
2641 
2642 		wpa_msg(wpa_s, MSG_DEBUG,
2643 			"Interworking: Share ANQP data with already fetched BSSID "
2644 			MACSTR " and " MACSTR,
2645 			MAC2STR(other->bssid), MAC2STR(bss->bssid));
2646 		other->anqp->users++;
2647 		return other->anqp;
2648 	}
2649 
2650 	return NULL;
2651 }
2652 
2653 
2654 static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s)
2655 {
2656 	struct wpa_bss *bss;
2657 	int found = 0;
2658 
2659 	wpa_printf(MSG_DEBUG, "Interworking: next_anqp_fetch - "
2660 		   "fetch_anqp_in_progress=%d fetch_osu_icon_in_progress=%d",
2661 		   wpa_s->fetch_anqp_in_progress,
2662 		   wpa_s->fetch_osu_icon_in_progress);
2663 
2664 	if (eloop_terminated() || !wpa_s->fetch_anqp_in_progress) {
2665 		wpa_printf(MSG_DEBUG, "Interworking: Stop next-ANQP-fetch");
2666 		return;
2667 	}
2668 
2669 #ifdef CONFIG_HS20
2670 	if (wpa_s->fetch_osu_icon_in_progress) {
2671 		wpa_printf(MSG_DEBUG, "Interworking: Next icon (in progress)");
2672 		hs20_next_osu_icon(wpa_s);
2673 		return;
2674 	}
2675 #endif /* CONFIG_HS20 */
2676 
2677 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2678 		if (!(bss->caps & IEEE80211_CAP_ESS))
2679 			continue;
2680 		if (!wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_INTERWORKING))
2681 			continue; /* AP does not support Interworking */
2682 		if (disallowed_bssid(wpa_s, bss->bssid) ||
2683 		    disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len))
2684 			continue; /* Disallowed BSS */
2685 
2686 		if (!(bss->flags & WPA_BSS_ANQP_FETCH_TRIED)) {
2687 			if (bss->anqp == NULL) {
2688 				bss->anqp = interworking_match_anqp_info(wpa_s,
2689 									 bss);
2690 				if (bss->anqp) {
2691 					/* Shared data already fetched */
2692 					continue;
2693 				}
2694 				bss->anqp = wpa_bss_anqp_alloc();
2695 				if (bss->anqp == NULL)
2696 					break;
2697 			}
2698 			found++;
2699 			bss->flags |= WPA_BSS_ANQP_FETCH_TRIED;
2700 			wpa_msg(wpa_s, MSG_INFO, "Starting ANQP fetch for "
2701 				MACSTR " (HESSID " MACSTR ")",
2702 				MAC2STR(bss->bssid), MAC2STR(bss->hessid));
2703 			interworking_anqp_send_req(wpa_s, bss);
2704 			break;
2705 		}
2706 	}
2707 
2708 	if (found == 0) {
2709 #ifdef CONFIG_HS20
2710 		if (wpa_s->fetch_osu_info) {
2711 			if (wpa_s->num_prov_found == 0 &&
2712 			    wpa_s->fetch_osu_waiting_scan &&
2713 			    wpa_s->num_osu_scans < 3) {
2714 				wpa_printf(MSG_DEBUG, "HS 2.0: No OSU providers seen - try to scan again");
2715 				hs20_start_osu_scan(wpa_s);
2716 				return;
2717 			}
2718 			wpa_printf(MSG_DEBUG, "Interworking: Next icon");
2719 			hs20_osu_icon_fetch(wpa_s);
2720 			return;
2721 		}
2722 #endif /* CONFIG_HS20 */
2723 		wpa_msg(wpa_s, MSG_INFO, "ANQP fetch completed");
2724 		wpa_s->fetch_anqp_in_progress = 0;
2725 		if (wpa_s->network_select)
2726 			interworking_select_network(wpa_s);
2727 	}
2728 }
2729 
2730 
2731 void interworking_start_fetch_anqp(struct wpa_supplicant *wpa_s)
2732 {
2733 	struct wpa_bss *bss;
2734 
2735 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list)
2736 		bss->flags &= ~WPA_BSS_ANQP_FETCH_TRIED;
2737 
2738 	wpa_s->fetch_anqp_in_progress = 1;
2739 
2740 	/*
2741 	 * Start actual ANQP operation from eloop call to make sure the loop
2742 	 * does not end up using excessive recursion.
2743 	 */
2744 	eloop_register_timeout(0, 0, interworking_continue_anqp, wpa_s, NULL);
2745 }
2746 
2747 
2748 int interworking_fetch_anqp(struct wpa_supplicant *wpa_s)
2749 {
2750 	if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select)
2751 		return 0;
2752 
2753 	wpa_s->network_select = 0;
2754 	wpa_s->fetch_all_anqp = 1;
2755 	wpa_s->fetch_osu_info = 0;
2756 
2757 	interworking_start_fetch_anqp(wpa_s);
2758 
2759 	return 0;
2760 }
2761 
2762 
2763 void interworking_stop_fetch_anqp(struct wpa_supplicant *wpa_s)
2764 {
2765 	if (!wpa_s->fetch_anqp_in_progress)
2766 		return;
2767 
2768 	wpa_s->fetch_anqp_in_progress = 0;
2769 }
2770 
2771 
2772 int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, int freq,
2773 		  u16 info_ids[], size_t num_ids, u32 subtypes,
2774 		  u32 mbo_subtypes)
2775 {
2776 	struct wpabuf *buf;
2777 	struct wpabuf *extra_buf = NULL;
2778 	int ret = 0;
2779 	struct wpa_bss *bss;
2780 	int res;
2781 
2782 	bss = wpa_bss_get_bssid(wpa_s, dst);
2783 	if (!bss && !freq) {
2784 		wpa_printf(MSG_WARNING,
2785 			   "ANQP: Cannot send query without BSS freq info");
2786 		return -1;
2787 	}
2788 
2789 	if (bss)
2790 		wpa_bss_anqp_unshare_alloc(bss);
2791 	if (bss && !freq)
2792 		freq = bss->freq;
2793 
2794 	wpa_msg(wpa_s, MSG_DEBUG,
2795 		"ANQP: Query Request to " MACSTR " for %u id(s)",
2796 		MAC2STR(dst), (unsigned int) num_ids);
2797 
2798 #ifdef CONFIG_HS20
2799 	if (subtypes != 0) {
2800 		extra_buf = wpabuf_alloc(100);
2801 		if (extra_buf == NULL)
2802 			return -1;
2803 		hs20_put_anqp_req(subtypes, NULL, 0, extra_buf);
2804 	}
2805 #endif /* CONFIG_HS20 */
2806 
2807 #ifdef CONFIG_MBO
2808 	if (mbo_subtypes) {
2809 		struct wpabuf *mbo;
2810 
2811 		if (!bss) {
2812 			wpa_printf(MSG_WARNING,
2813 				   "ANQP: Cannot send MBO query to unknown BSS "
2814 				   MACSTR, MAC2STR(dst));
2815 			wpabuf_free(extra_buf);
2816 			return -1;
2817 		}
2818 
2819 		mbo = mbo_build_anqp_buf(wpa_s, bss, mbo_subtypes);
2820 		if (mbo) {
2821 			if (wpabuf_resize(&extra_buf, wpabuf_len(mbo))) {
2822 				wpabuf_free(extra_buf);
2823 				wpabuf_free(mbo);
2824 				return -1;
2825 			}
2826 			wpabuf_put_buf(extra_buf, mbo);
2827 			wpabuf_free(mbo);
2828 		}
2829 	}
2830 #endif /* CONFIG_MBO */
2831 
2832 	buf = anqp_build_req(info_ids, num_ids, extra_buf);
2833 	wpabuf_free(extra_buf);
2834 	if (buf == NULL)
2835 		return -1;
2836 
2837 	res = gas_query_req(wpa_s->gas, dst, freq, 0, 0, buf, anqp_resp_cb,
2838 			    wpa_s);
2839 	if (res < 0) {
2840 		wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Failed to send Query Request");
2841 		wpabuf_free(buf);
2842 		ret = -1;
2843 	} else {
2844 		wpa_msg(wpa_s, MSG_DEBUG,
2845 			"ANQP: Query started with dialog token %u", res);
2846 	}
2847 
2848 	return ret;
2849 }
2850 
2851 
2852 static void anqp_add_extra(struct wpa_supplicant *wpa_s,
2853 			   struct wpa_bss_anqp *anqp, u16 info_id,
2854 			   const u8 *data, size_t slen, bool protected_response)
2855 {
2856 	struct wpa_bss_anqp_elem *tmp, *elem = NULL;
2857 
2858 	if (!anqp)
2859 		return;
2860 
2861 	dl_list_for_each(tmp, &anqp->anqp_elems, struct wpa_bss_anqp_elem,
2862 			 list) {
2863 		if (tmp->infoid == info_id) {
2864 			elem = tmp;
2865 			break;
2866 		}
2867 	}
2868 
2869 	if (!elem) {
2870 		elem = os_zalloc(sizeof(*elem));
2871 		if (!elem)
2872 			return;
2873 		elem->infoid = info_id;
2874 		dl_list_add(&anqp->anqp_elems, &elem->list);
2875 	} else {
2876 		wpabuf_free(elem->payload);
2877 	}
2878 
2879 	elem->protected_response = protected_response;
2880 	elem->payload = wpabuf_alloc_copy(data, slen);
2881 	if (!elem->payload) {
2882 		dl_list_del(&elem->list);
2883 		os_free(elem);
2884 	}
2885 }
2886 
2887 
2888 static void interworking_parse_venue_url(struct wpa_supplicant *wpa_s,
2889 					 const u8 *data, size_t len)
2890 {
2891 	const u8 *pos = data, *end = data + len;
2892 	char url[255];
2893 
2894 	while (end - pos >= 2) {
2895 		u8 slen, num;
2896 
2897 		slen = *pos++;
2898 		if (slen < 1 || slen > end - pos) {
2899 			wpa_printf(MSG_DEBUG,
2900 				   "ANQP: Truncated Venue URL Duple field");
2901 			return;
2902 		}
2903 
2904 		num = *pos++;
2905 		os_memcpy(url, pos, slen - 1);
2906 		url[slen - 1] = '\0';
2907 		wpa_msg(wpa_s, MSG_INFO, RX_VENUE_URL "%u %s", num, url);
2908 		pos += slen - 1;
2909 	}
2910 }
2911 
2912 
2913 static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
2914 					    struct wpa_bss *bss, const u8 *sa,
2915 					    u16 info_id,
2916 					    const u8 *data, size_t slen,
2917 					    u8 dialog_token)
2918 {
2919 	const u8 *pos = data;
2920 	struct wpa_bss_anqp *anqp = NULL;
2921 	u8 type;
2922 	bool protected_response;
2923 
2924 	if (bss)
2925 		anqp = bss->anqp;
2926 
2927 	switch (info_id) {
2928 	case ANQP_CAPABILITY_LIST:
2929 		wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
2930 			" ANQP Capability list", MAC2STR(sa));
2931 		wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Capability list",
2932 				  pos, slen);
2933 		if (anqp) {
2934 			wpabuf_free(anqp->capability_list);
2935 			anqp->capability_list = wpabuf_alloc_copy(pos, slen);
2936 		}
2937 		break;
2938 	case ANQP_VENUE_NAME:
2939 		wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
2940 			" Venue Name", MAC2STR(sa));
2941 		wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Venue Name", pos, slen);
2942 		if (anqp) {
2943 			wpabuf_free(anqp->venue_name);
2944 			anqp->venue_name = wpabuf_alloc_copy(pos, slen);
2945 		}
2946 		break;
2947 	case ANQP_NETWORK_AUTH_TYPE:
2948 		wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
2949 			" Network Authentication Type information",
2950 			MAC2STR(sa));
2951 		wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Network Authentication "
2952 				  "Type", pos, slen);
2953 		if (anqp) {
2954 			wpabuf_free(anqp->network_auth_type);
2955 			anqp->network_auth_type = wpabuf_alloc_copy(pos, slen);
2956 		}
2957 		break;
2958 	case ANQP_ROAMING_CONSORTIUM:
2959 		wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
2960 			" Roaming Consortium list", MAC2STR(sa));
2961 		wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Roaming Consortium",
2962 				  pos, slen);
2963 		if (anqp) {
2964 			wpabuf_free(anqp->roaming_consortium);
2965 			anqp->roaming_consortium = wpabuf_alloc_copy(pos, slen);
2966 		}
2967 		break;
2968 	case ANQP_IP_ADDR_TYPE_AVAILABILITY:
2969 		wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
2970 			" IP Address Type Availability information",
2971 			MAC2STR(sa));
2972 		wpa_hexdump(MSG_MSGDUMP, "ANQP: IP Address Availability",
2973 			    pos, slen);
2974 		if (anqp) {
2975 			wpabuf_free(anqp->ip_addr_type_availability);
2976 			anqp->ip_addr_type_availability =
2977 				wpabuf_alloc_copy(pos, slen);
2978 		}
2979 		break;
2980 	case ANQP_NAI_REALM:
2981 		wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
2982 			" NAI Realm list", MAC2STR(sa));
2983 		wpa_hexdump_ascii(MSG_DEBUG, "ANQP: NAI Realm", pos, slen);
2984 		if (anqp) {
2985 			wpabuf_free(anqp->nai_realm);
2986 			anqp->nai_realm = wpabuf_alloc_copy(pos, slen);
2987 		}
2988 		break;
2989 	case ANQP_3GPP_CELLULAR_NETWORK:
2990 		wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
2991 			" 3GPP Cellular Network information", MAC2STR(sa));
2992 		wpa_hexdump_ascii(MSG_DEBUG, "ANQP: 3GPP Cellular Network",
2993 				  pos, slen);
2994 		if (anqp) {
2995 			wpabuf_free(anqp->anqp_3gpp);
2996 			anqp->anqp_3gpp = wpabuf_alloc_copy(pos, slen);
2997 		}
2998 		break;
2999 	case ANQP_DOMAIN_NAME:
3000 		wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
3001 			" Domain Name list", MAC2STR(sa));
3002 		wpa_hexdump_ascii(MSG_MSGDUMP, "ANQP: Domain Name", pos, slen);
3003 		if (anqp) {
3004 			wpabuf_free(anqp->domain_name);
3005 			anqp->domain_name = wpabuf_alloc_copy(pos, slen);
3006 		}
3007 		break;
3008 #ifdef CONFIG_FILS
3009 	case ANQP_FILS_REALM_INFO:
3010 		wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
3011 			" FILS Realm Information", MAC2STR(sa));
3012 		wpa_hexdump_ascii(MSG_MSGDUMP, "ANQP: FILS Realm Information",
3013 			pos, slen);
3014 		if (anqp) {
3015 			wpabuf_free(anqp->fils_realm_info);
3016 			anqp->fils_realm_info = wpabuf_alloc_copy(pos, slen);
3017 		}
3018 		break;
3019 #endif /* CONFIG_FILS */
3020 	case ANQP_VENUE_URL:
3021 		wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR " Venue URL",
3022 			MAC2STR(sa));
3023 		protected_response = pmf_in_use(wpa_s, sa);
3024 		anqp_add_extra(wpa_s, anqp, info_id, pos, slen,
3025 			       protected_response);
3026 
3027 		if (!protected_response) {
3028 			wpa_printf(MSG_DEBUG,
3029 				   "ANQP: Ignore Venue URL since PMF was not enabled");
3030 			break;
3031 		}
3032 		interworking_parse_venue_url(wpa_s, pos, slen);
3033 		break;
3034 	case ANQP_VENDOR_SPECIFIC:
3035 		if (slen < 3)
3036 			return;
3037 
3038 		switch (WPA_GET_BE24(pos)) {
3039 		case OUI_WFA:
3040 			pos += 3;
3041 			slen -= 3;
3042 
3043 			if (slen < 1)
3044 				return;
3045 			type = *pos++;
3046 			slen--;
3047 
3048 			switch (type) {
3049 #ifdef CONFIG_HS20
3050 			case HS20_ANQP_OUI_TYPE:
3051 				hs20_parse_rx_hs20_anqp_resp(wpa_s, bss, sa,
3052 							     pos, slen,
3053 							     dialog_token);
3054 				break;
3055 #endif /* CONFIG_HS20 */
3056 #ifdef CONFIG_MBO
3057 			case MBO_ANQP_OUI_TYPE:
3058 				mbo_parse_rx_anqp_resp(wpa_s, bss, sa,
3059 						       pos, slen);
3060 				break;
3061 #endif /* CONFIG_MBO */
3062 			default:
3063 				wpa_msg(wpa_s, MSG_DEBUG,
3064 					"ANQP: Unsupported ANQP vendor type %u",
3065 					type);
3066 				break;
3067 			}
3068 			break;
3069 		default:
3070 			wpa_msg(wpa_s, MSG_DEBUG,
3071 				"Interworking: Unsupported vendor-specific ANQP OUI %06x",
3072 				WPA_GET_BE24(pos));
3073 			return;
3074 		}
3075 		break;
3076 	default:
3077 		wpa_msg(wpa_s, MSG_DEBUG,
3078 			"Interworking: Unsupported ANQP Info ID %u", info_id);
3079 		anqp_add_extra(wpa_s, anqp, info_id, data, slen,
3080 			       pmf_in_use(wpa_s, sa));
3081 		break;
3082 	}
3083 }
3084 
3085 
3086 void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token,
3087 		  enum gas_query_result result,
3088 		  const struct wpabuf *adv_proto,
3089 		  const struct wpabuf *resp, u16 status_code)
3090 {
3091 	struct wpa_supplicant *wpa_s = ctx;
3092 	const u8 *pos;
3093 	const u8 *end;
3094 	u16 info_id;
3095 	u16 slen;
3096 	struct wpa_bss *bss = NULL, *tmp;
3097 	const char *anqp_result = "SUCCESS";
3098 
3099 	wpa_printf(MSG_DEBUG, "Interworking: anqp_resp_cb dst=" MACSTR
3100 		   " dialog_token=%u result=%d status_code=%u",
3101 		   MAC2STR(dst), dialog_token, result, status_code);
3102 	if (result != GAS_QUERY_SUCCESS) {
3103 #ifdef CONFIG_HS20
3104 		if (wpa_s->fetch_osu_icon_in_progress)
3105 			hs20_icon_fetch_failed(wpa_s);
3106 #endif /* CONFIG_HS20 */
3107 		anqp_result = "FAILURE";
3108 		goto out;
3109 	}
3110 
3111 	pos = wpabuf_head(adv_proto);
3112 	if (wpabuf_len(adv_proto) < 4 || pos[0] != WLAN_EID_ADV_PROTO ||
3113 	    pos[1] < 2 || pos[3] != ACCESS_NETWORK_QUERY_PROTOCOL) {
3114 		wpa_msg(wpa_s, MSG_DEBUG,
3115 			"ANQP: Unexpected Advertisement Protocol in response");
3116 #ifdef CONFIG_HS20
3117 		if (wpa_s->fetch_osu_icon_in_progress)
3118 			hs20_icon_fetch_failed(wpa_s);
3119 #endif /* CONFIG_HS20 */
3120 		anqp_result = "INVALID_FRAME";
3121 		goto out;
3122 	}
3123 
3124 	/*
3125 	 * If possible, select the BSS entry based on which BSS entry was used
3126 	 * for the request. This can help in cases where multiple BSS entries
3127 	 * may exist for the same AP.
3128 	 */
3129 	dl_list_for_each_reverse(tmp, &wpa_s->bss, struct wpa_bss, list) {
3130 		if (tmp == wpa_s->interworking_gas_bss &&
3131 		    os_memcmp(tmp->bssid, dst, ETH_ALEN) == 0) {
3132 			bss = tmp;
3133 			break;
3134 		}
3135 	}
3136 	if (bss == NULL)
3137 		bss = wpa_bss_get_bssid(wpa_s, dst);
3138 
3139 	pos = wpabuf_head(resp);
3140 	end = pos + wpabuf_len(resp);
3141 
3142 	while (pos < end) {
3143 		unsigned int left = end - pos;
3144 
3145 		if (left < 4) {
3146 			wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Invalid element");
3147 			anqp_result = "INVALID_FRAME";
3148 			goto out_parse_done;
3149 		}
3150 		info_id = WPA_GET_LE16(pos);
3151 		pos += 2;
3152 		slen = WPA_GET_LE16(pos);
3153 		pos += 2;
3154 		left -= 4;
3155 		if (left < slen) {
3156 			wpa_msg(wpa_s, MSG_DEBUG,
3157 				"ANQP: Invalid element length for Info ID %u",
3158 				info_id);
3159 			anqp_result = "INVALID_FRAME";
3160 			goto out_parse_done;
3161 		}
3162 		interworking_parse_rx_anqp_resp(wpa_s, bss, dst, info_id, pos,
3163 						slen, dialog_token);
3164 		pos += slen;
3165 	}
3166 
3167 out_parse_done:
3168 #ifdef CONFIG_HS20
3169 	hs20_notify_parse_done(wpa_s);
3170 #endif /* CONFIG_HS20 */
3171 out:
3172 	wpa_msg(wpa_s, MSG_INFO, ANQP_QUERY_DONE "addr=" MACSTR " result=%s",
3173 		MAC2STR(dst), anqp_result);
3174 }
3175 
3176 
3177 static void interworking_scan_res_handler(struct wpa_supplicant *wpa_s,
3178 					  struct wpa_scan_results *scan_res)
3179 {
3180 	wpa_msg(wpa_s, MSG_DEBUG,
3181 		"Interworking: Scan results available - start ANQP fetch");
3182 	interworking_start_fetch_anqp(wpa_s);
3183 }
3184 
3185 
3186 int interworking_select(struct wpa_supplicant *wpa_s, int auto_select,
3187 			int *freqs)
3188 {
3189 	interworking_stop_fetch_anqp(wpa_s);
3190 	wpa_s->network_select = 1;
3191 	wpa_s->auto_network_select = 0;
3192 	wpa_s->auto_select = !!auto_select;
3193 	wpa_s->fetch_all_anqp = 0;
3194 	wpa_s->fetch_osu_info = 0;
3195 	wpa_msg(wpa_s, MSG_DEBUG,
3196 		"Interworking: Start scan for network selection");
3197 	wpa_s->scan_res_handler = interworking_scan_res_handler;
3198 	wpa_s->normal_scans = 0;
3199 	wpa_s->scan_req = MANUAL_SCAN_REQ;
3200 	os_free(wpa_s->manual_scan_freqs);
3201 	wpa_s->manual_scan_freqs = freqs;
3202 	wpa_s->after_wps = 0;
3203 	wpa_s->known_wps_freq = 0;
3204 	wpa_supplicant_req_scan(wpa_s, 0, 0);
3205 
3206 	return 0;
3207 }
3208 
3209 
3210 static void gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
3211 			enum gas_query_result result,
3212 			const struct wpabuf *adv_proto,
3213 			const struct wpabuf *resp, u16 status_code)
3214 {
3215 	struct wpa_supplicant *wpa_s = ctx;
3216 	struct wpabuf *n;
3217 
3218 	wpa_msg(wpa_s, MSG_INFO, GAS_RESPONSE_INFO "addr=" MACSTR
3219 		" dialog_token=%d status_code=%d resp_len=%d",
3220 		MAC2STR(addr), dialog_token, status_code,
3221 		resp ? (int) wpabuf_len(resp) : -1);
3222 	if (!resp)
3223 		return;
3224 
3225 	n = wpabuf_dup(resp);
3226 	if (n == NULL)
3227 		return;
3228 	wpabuf_free(wpa_s->prev_gas_resp);
3229 	wpa_s->prev_gas_resp = wpa_s->last_gas_resp;
3230 	os_memcpy(wpa_s->prev_gas_addr, wpa_s->last_gas_addr, ETH_ALEN);
3231 	wpa_s->prev_gas_dialog_token = wpa_s->last_gas_dialog_token;
3232 	wpa_s->last_gas_resp = n;
3233 	os_memcpy(wpa_s->last_gas_addr, addr, ETH_ALEN);
3234 	wpa_s->last_gas_dialog_token = dialog_token;
3235 }
3236 
3237 
3238 int gas_send_request(struct wpa_supplicant *wpa_s, const u8 *dst,
3239 		     const struct wpabuf *adv_proto,
3240 		     const struct wpabuf *query)
3241 {
3242 	struct wpabuf *buf;
3243 	int ret = 0;
3244 	int freq;
3245 	struct wpa_bss *bss;
3246 	int res;
3247 	size_t len;
3248 	u8 query_resp_len_limit = 0;
3249 
3250 	freq = wpa_s->assoc_freq;
3251 	bss = wpa_bss_get_bssid(wpa_s, dst);
3252 	if (bss)
3253 		freq = bss->freq;
3254 	if (freq <= 0)
3255 		return -1;
3256 
3257 	wpa_msg(wpa_s, MSG_DEBUG, "GAS request to " MACSTR " (freq %d MHz)",
3258 		MAC2STR(dst), freq);
3259 	wpa_hexdump_buf(MSG_DEBUG, "Advertisement Protocol ID", adv_proto);
3260 	wpa_hexdump_buf(MSG_DEBUG, "GAS Query", query);
3261 
3262 	len = 3 + wpabuf_len(adv_proto) + 2;
3263 	if (query)
3264 		len += wpabuf_len(query);
3265 	buf = gas_build_initial_req(0, len);
3266 	if (buf == NULL)
3267 		return -1;
3268 
3269 	/* Advertisement Protocol IE */
3270 	wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO);
3271 	wpabuf_put_u8(buf, 1 + wpabuf_len(adv_proto)); /* Length */
3272 	wpabuf_put_u8(buf, query_resp_len_limit & 0x7f);
3273 	wpabuf_put_buf(buf, adv_proto);
3274 
3275 	/* GAS Query */
3276 	if (query) {
3277 		wpabuf_put_le16(buf, wpabuf_len(query));
3278 		wpabuf_put_buf(buf, query);
3279 	} else
3280 		wpabuf_put_le16(buf, 0);
3281 
3282 	res = gas_query_req(wpa_s->gas, dst, freq, 0, 0, buf, gas_resp_cb,
3283 			    wpa_s);
3284 	if (res < 0) {
3285 		wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request");
3286 		wpabuf_free(buf);
3287 		ret = -1;
3288 	} else
3289 		wpa_msg(wpa_s, MSG_DEBUG,
3290 			"GAS: Query started with dialog token %u", res);
3291 
3292 	return ret;
3293 }
3294