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