vendor/wpa_supplicant: upgrade from 2.1 to 2.9
[dragonfly.git] / contrib / wpa_supplicant / src / ap / gas_serv.c
1 /*
2  * Generic advertisement service (GAS) server
3  * Copyright (c) 2011-2014, Qualcomm Atheros, Inc.
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8
9 #include "includes.h"
10
11 #include "common.h"
12 #include "common/ieee802_11_defs.h"
13 #include "common/gas.h"
14 #include "common/wpa_ctrl.h"
15 #include "utils/eloop.h"
16 #include "hostapd.h"
17 #include "ap_config.h"
18 #include "ap_drv_ops.h"
19 #include "dpp_hostapd.h"
20 #include "sta_info.h"
21 #include "gas_serv.h"
22
23
24 #ifdef CONFIG_DPP
25 static void gas_serv_write_dpp_adv_proto(struct wpabuf *buf)
26 {
27         wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO);
28         wpabuf_put_u8(buf, 8); /* Length */
29         wpabuf_put_u8(buf, 0x7f);
30         wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
31         wpabuf_put_u8(buf, 5);
32         wpabuf_put_be24(buf, OUI_WFA);
33         wpabuf_put_u8(buf, DPP_OUI_TYPE);
34         wpabuf_put_u8(buf, 0x01);
35 }
36 #endif /* CONFIG_DPP */
37
38
39 static void convert_to_protected_dual(struct wpabuf *msg)
40 {
41         u8 *categ = wpabuf_mhead_u8(msg);
42         *categ = WLAN_ACTION_PROTECTED_DUAL;
43 }
44
45
46 static struct gas_dialog_info *
47 gas_dialog_create(struct hostapd_data *hapd, const u8 *addr, u8 dialog_token)
48 {
49         struct sta_info *sta;
50         struct gas_dialog_info *dia = NULL;
51         int i, j;
52
53         sta = ap_get_sta(hapd, addr);
54         if (!sta) {
55                 /*
56                  * We need a STA entry to be able to maintain state for
57                  * the GAS query.
58                  */
59                 wpa_printf(MSG_DEBUG, "ANQP: Add a temporary STA entry for "
60                            "GAS query");
61                 sta = ap_sta_add(hapd, addr);
62                 if (!sta) {
63                         wpa_printf(MSG_DEBUG, "Failed to add STA " MACSTR
64                                    " for GAS query", MAC2STR(addr));
65                         return NULL;
66                 }
67                 sta->flags |= WLAN_STA_GAS;
68                 /*
69                  * The default inactivity is 300 seconds. We don't need
70                  * it to be that long. Use five second timeout and increase this
71                  * with the comeback_delay for testing cases.
72                  */
73                 ap_sta_session_timeout(hapd, sta,
74                                        hapd->conf->gas_comeback_delay / 1024 +
75                                        5);
76         } else {
77                 ap_sta_replenish_timeout(hapd, sta, 5);
78         }
79
80         if (sta->gas_dialog == NULL) {
81                 sta->gas_dialog = os_calloc(GAS_DIALOG_MAX,
82                                             sizeof(struct gas_dialog_info));
83                 if (sta->gas_dialog == NULL)
84                         return NULL;
85         }
86
87         for (i = sta->gas_dialog_next, j = 0; j < GAS_DIALOG_MAX; i++, j++) {
88                 if (i == GAS_DIALOG_MAX)
89                         i = 0;
90                 if (sta->gas_dialog[i].valid)
91                         continue;
92                 dia = &sta->gas_dialog[i];
93                 dia->valid = 1;
94                 dia->dialog_token = dialog_token;
95                 sta->gas_dialog_next = (++i == GAS_DIALOG_MAX) ? 0 : i;
96                 return dia;
97         }
98
99         wpa_msg(hapd->msg_ctx, MSG_ERROR, "ANQP: Could not create dialog for "
100                 MACSTR " dialog_token %u. Consider increasing "
101                 "GAS_DIALOG_MAX.", MAC2STR(addr), dialog_token);
102
103         return NULL;
104 }
105
106
107 struct gas_dialog_info *
108 gas_serv_dialog_find(struct hostapd_data *hapd, const u8 *addr,
109                      u8 dialog_token)
110 {
111         struct sta_info *sta;
112         int i;
113
114         sta = ap_get_sta(hapd, addr);
115         if (!sta) {
116                 wpa_printf(MSG_DEBUG, "ANQP: could not find STA " MACSTR,
117                            MAC2STR(addr));
118                 return NULL;
119         }
120         for (i = 0; sta->gas_dialog && i < GAS_DIALOG_MAX; i++) {
121                 if (sta->gas_dialog[i].dialog_token != dialog_token ||
122                     !sta->gas_dialog[i].valid)
123                         continue;
124                 ap_sta_replenish_timeout(hapd, sta, 5);
125                 return &sta->gas_dialog[i];
126         }
127         wpa_printf(MSG_DEBUG, "ANQP: Could not find dialog for "
128                    MACSTR " dialog_token %u", MAC2STR(addr), dialog_token);
129         return NULL;
130 }
131
132
133 void gas_serv_dialog_clear(struct gas_dialog_info *dia)
134 {
135         wpabuf_free(dia->sd_resp);
136         os_memset(dia, 0, sizeof(*dia));
137 }
138
139
140 static void gas_serv_free_dialogs(struct hostapd_data *hapd,
141                                   const u8 *sta_addr)
142 {
143         struct sta_info *sta;
144         int i;
145
146         sta = ap_get_sta(hapd, sta_addr);
147         if (sta == NULL || sta->gas_dialog == NULL)
148                 return;
149
150         for (i = 0; i < GAS_DIALOG_MAX; i++) {
151                 if (sta->gas_dialog[i].valid)
152                         return;
153         }
154
155         os_free(sta->gas_dialog);
156         sta->gas_dialog = NULL;
157 }
158
159
160 #ifdef CONFIG_HS20
161 static void anqp_add_hs_capab_list(struct hostapd_data *hapd,
162                                    struct wpabuf *buf)
163 {
164         u8 *len;
165
166         len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
167         wpabuf_put_be24(buf, OUI_WFA);
168         wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
169         wpabuf_put_u8(buf, HS20_STYPE_CAPABILITY_LIST);
170         wpabuf_put_u8(buf, 0); /* Reserved */
171         wpabuf_put_u8(buf, HS20_STYPE_CAPABILITY_LIST);
172         if (hapd->conf->hs20_oper_friendly_name)
173                 wpabuf_put_u8(buf, HS20_STYPE_OPERATOR_FRIENDLY_NAME);
174         if (hapd->conf->hs20_wan_metrics)
175                 wpabuf_put_u8(buf, HS20_STYPE_WAN_METRICS);
176         if (hapd->conf->hs20_connection_capability)
177                 wpabuf_put_u8(buf, HS20_STYPE_CONNECTION_CAPABILITY);
178         if (hapd->conf->nai_realm_data)
179                 wpabuf_put_u8(buf, HS20_STYPE_NAI_HOME_REALM_QUERY);
180         if (hapd->conf->hs20_operating_class)
181                 wpabuf_put_u8(buf, HS20_STYPE_OPERATING_CLASS);
182         if (hapd->conf->hs20_osu_providers_count)
183                 wpabuf_put_u8(buf, HS20_STYPE_OSU_PROVIDERS_LIST);
184         if (hapd->conf->hs20_osu_providers_nai_count)
185                 wpabuf_put_u8(buf, HS20_STYPE_OSU_PROVIDERS_NAI_LIST);
186         if (hapd->conf->hs20_icons_count)
187                 wpabuf_put_u8(buf, HS20_STYPE_ICON_REQUEST);
188         if (hapd->conf->hs20_operator_icon_count)
189                 wpabuf_put_u8(buf, HS20_STYPE_OPERATOR_ICON_METADATA);
190         gas_anqp_set_element_len(buf, len);
191 }
192 #endif /* CONFIG_HS20 */
193
194
195 static struct anqp_element * get_anqp_elem(struct hostapd_data *hapd,
196                                            u16 infoid)
197 {
198         struct anqp_element *elem;
199
200         dl_list_for_each(elem, &hapd->conf->anqp_elem, struct anqp_element,
201                          list) {
202                 if (elem->infoid == infoid)
203                         return elem;
204         }
205
206         return NULL;
207 }
208
209
210 static void anqp_add_elem(struct hostapd_data *hapd, struct wpabuf *buf,
211                           u16 infoid)
212 {
213         struct anqp_element *elem;
214
215         elem = get_anqp_elem(hapd, infoid);
216         if (!elem)
217                 return;
218         if (wpabuf_tailroom(buf) < 2 + 2 + wpabuf_len(elem->payload)) {
219                 wpa_printf(MSG_DEBUG, "ANQP: No room for InfoID %u payload",
220                            infoid);
221                 return;
222         }
223
224         wpabuf_put_le16(buf, infoid);
225         wpabuf_put_le16(buf, wpabuf_len(elem->payload));
226         wpabuf_put_buf(buf, elem->payload);
227 }
228
229
230 static int anqp_add_override(struct hostapd_data *hapd, struct wpabuf *buf,
231                              u16 infoid)
232 {
233         if (get_anqp_elem(hapd, infoid)) {
234                 anqp_add_elem(hapd, buf, infoid);
235                 return 1;
236         }
237
238         return 0;
239 }
240
241
242 static void anqp_add_capab_list(struct hostapd_data *hapd,
243                                 struct wpabuf *buf)
244 {
245         u8 *len;
246         u16 id;
247
248         if (anqp_add_override(hapd, buf, ANQP_CAPABILITY_LIST))
249                 return;
250
251         len = gas_anqp_add_element(buf, ANQP_CAPABILITY_LIST);
252         wpabuf_put_le16(buf, ANQP_CAPABILITY_LIST);
253         if (hapd->conf->venue_name || get_anqp_elem(hapd, ANQP_VENUE_NAME))
254                 wpabuf_put_le16(buf, ANQP_VENUE_NAME);
255         if (get_anqp_elem(hapd, ANQP_EMERGENCY_CALL_NUMBER))
256                 wpabuf_put_le16(buf, ANQP_EMERGENCY_CALL_NUMBER);
257         if (hapd->conf->network_auth_type ||
258             get_anqp_elem(hapd, ANQP_NETWORK_AUTH_TYPE))
259                 wpabuf_put_le16(buf, ANQP_NETWORK_AUTH_TYPE);
260         if (hapd->conf->roaming_consortium ||
261             get_anqp_elem(hapd, ANQP_ROAMING_CONSORTIUM))
262                 wpabuf_put_le16(buf, ANQP_ROAMING_CONSORTIUM);
263         if (hapd->conf->ipaddr_type_configured ||
264             get_anqp_elem(hapd, ANQP_IP_ADDR_TYPE_AVAILABILITY))
265                 wpabuf_put_le16(buf, ANQP_IP_ADDR_TYPE_AVAILABILITY);
266         if (hapd->conf->nai_realm_data ||
267             get_anqp_elem(hapd, ANQP_NAI_REALM))
268                 wpabuf_put_le16(buf, ANQP_NAI_REALM);
269         if (hapd->conf->anqp_3gpp_cell_net ||
270             get_anqp_elem(hapd, ANQP_3GPP_CELLULAR_NETWORK))
271                 wpabuf_put_le16(buf, ANQP_3GPP_CELLULAR_NETWORK);
272         if (get_anqp_elem(hapd, ANQP_AP_GEOSPATIAL_LOCATION))
273                 wpabuf_put_le16(buf, ANQP_AP_GEOSPATIAL_LOCATION);
274         if (get_anqp_elem(hapd, ANQP_AP_CIVIC_LOCATION))
275                 wpabuf_put_le16(buf, ANQP_AP_CIVIC_LOCATION);
276         if (get_anqp_elem(hapd, ANQP_AP_LOCATION_PUBLIC_URI))
277                 wpabuf_put_le16(buf, ANQP_AP_LOCATION_PUBLIC_URI);
278         if (hapd->conf->domain_name || get_anqp_elem(hapd, ANQP_DOMAIN_NAME))
279                 wpabuf_put_le16(buf, ANQP_DOMAIN_NAME);
280         if (get_anqp_elem(hapd, ANQP_EMERGENCY_ALERT_URI))
281                 wpabuf_put_le16(buf, ANQP_EMERGENCY_ALERT_URI);
282         if (get_anqp_elem(hapd, ANQP_TDLS_CAPABILITY))
283                 wpabuf_put_le16(buf, ANQP_TDLS_CAPABILITY);
284         if (get_anqp_elem(hapd, ANQP_EMERGENCY_NAI))
285                 wpabuf_put_le16(buf, ANQP_EMERGENCY_NAI);
286         if (get_anqp_elem(hapd, ANQP_NEIGHBOR_REPORT))
287                 wpabuf_put_le16(buf, ANQP_NEIGHBOR_REPORT);
288 #ifdef CONFIG_FILS
289         if (!dl_list_empty(&hapd->conf->fils_realms) ||
290             get_anqp_elem(hapd, ANQP_FILS_REALM_INFO))
291                 wpabuf_put_le16(buf, ANQP_FILS_REALM_INFO);
292 #endif /* CONFIG_FILS */
293         if (get_anqp_elem(hapd, ANQP_CAG))
294                 wpabuf_put_le16(buf, ANQP_CAG);
295         if (hapd->conf->venue_url || get_anqp_elem(hapd, ANQP_VENUE_URL))
296                 wpabuf_put_le16(buf, ANQP_VENUE_URL);
297         if (get_anqp_elem(hapd, ANQP_ADVICE_OF_CHARGE))
298                 wpabuf_put_le16(buf, ANQP_ADVICE_OF_CHARGE);
299         if (get_anqp_elem(hapd, ANQP_LOCAL_CONTENT))
300                 wpabuf_put_le16(buf, ANQP_LOCAL_CONTENT);
301         for (id = 280; id < 300; id++) {
302                 if (get_anqp_elem(hapd, id))
303                         wpabuf_put_le16(buf, id);
304         }
305 #ifdef CONFIG_HS20
306         anqp_add_hs_capab_list(hapd, buf);
307 #endif /* CONFIG_HS20 */
308         gas_anqp_set_element_len(buf, len);
309 }
310
311
312 static void anqp_add_venue_name(struct hostapd_data *hapd, struct wpabuf *buf)
313 {
314         if (anqp_add_override(hapd, buf, ANQP_VENUE_NAME))
315                 return;
316
317         if (hapd->conf->venue_name) {
318                 u8 *len;
319                 unsigned int i;
320                 len = gas_anqp_add_element(buf, ANQP_VENUE_NAME);
321                 wpabuf_put_u8(buf, hapd->conf->venue_group);
322                 wpabuf_put_u8(buf, hapd->conf->venue_type);
323                 for (i = 0; i < hapd->conf->venue_name_count; i++) {
324                         struct hostapd_lang_string *vn;
325                         vn = &hapd->conf->venue_name[i];
326                         wpabuf_put_u8(buf, 3 + vn->name_len);
327                         wpabuf_put_data(buf, vn->lang, 3);
328                         wpabuf_put_data(buf, vn->name, vn->name_len);
329                 }
330                 gas_anqp_set_element_len(buf, len);
331         }
332 }
333
334
335 static void anqp_add_venue_url(struct hostapd_data *hapd, struct wpabuf *buf)
336 {
337         if (anqp_add_override(hapd, buf, ANQP_VENUE_URL))
338                 return;
339
340         if (hapd->conf->venue_url) {
341                 u8 *len;
342                 unsigned int i;
343
344                 len = gas_anqp_add_element(buf, ANQP_VENUE_URL);
345                 for (i = 0; i < hapd->conf->venue_url_count; i++) {
346                         struct hostapd_venue_url *url;
347
348                         url = &hapd->conf->venue_url[i];
349                         wpabuf_put_u8(buf, 1 + url->url_len);
350                         wpabuf_put_u8(buf, url->venue_number);
351                         wpabuf_put_data(buf, url->url, url->url_len);
352                 }
353                 gas_anqp_set_element_len(buf, len);
354         }
355 }
356
357
358 static void anqp_add_network_auth_type(struct hostapd_data *hapd,
359                                        struct wpabuf *buf)
360 {
361         if (anqp_add_override(hapd, buf, ANQP_NETWORK_AUTH_TYPE))
362                 return;
363
364         if (hapd->conf->network_auth_type) {
365                 wpabuf_put_le16(buf, ANQP_NETWORK_AUTH_TYPE);
366                 wpabuf_put_le16(buf, hapd->conf->network_auth_type_len);
367                 wpabuf_put_data(buf, hapd->conf->network_auth_type,
368                                 hapd->conf->network_auth_type_len);
369         }
370 }
371
372
373 static void anqp_add_roaming_consortium(struct hostapd_data *hapd,
374                                         struct wpabuf *buf)
375 {
376         unsigned int i;
377         u8 *len;
378
379         if (anqp_add_override(hapd, buf, ANQP_ROAMING_CONSORTIUM))
380                 return;
381
382         len = gas_anqp_add_element(buf, ANQP_ROAMING_CONSORTIUM);
383         for (i = 0; i < hapd->conf->roaming_consortium_count; i++) {
384                 struct hostapd_roaming_consortium *rc;
385                 rc = &hapd->conf->roaming_consortium[i];
386                 wpabuf_put_u8(buf, rc->len);
387                 wpabuf_put_data(buf, rc->oi, rc->len);
388         }
389         gas_anqp_set_element_len(buf, len);
390 }
391
392
393 static void anqp_add_ip_addr_type_availability(struct hostapd_data *hapd,
394                                                struct wpabuf *buf)
395 {
396         if (anqp_add_override(hapd, buf, ANQP_IP_ADDR_TYPE_AVAILABILITY))
397                 return;
398
399         if (hapd->conf->ipaddr_type_configured) {
400                 wpabuf_put_le16(buf, ANQP_IP_ADDR_TYPE_AVAILABILITY);
401                 wpabuf_put_le16(buf, 1);
402                 wpabuf_put_u8(buf, hapd->conf->ipaddr_type_availability);
403         }
404 }
405
406
407 static void anqp_add_nai_realm_eap(struct wpabuf *buf,
408                                    struct hostapd_nai_realm_data *realm)
409 {
410         unsigned int i, j;
411
412         wpabuf_put_u8(buf, realm->eap_method_count);
413
414         for (i = 0; i < realm->eap_method_count; i++) {
415                 struct hostapd_nai_realm_eap *eap = &realm->eap_method[i];
416                 wpabuf_put_u8(buf, 2 + (3 * eap->num_auths));
417                 wpabuf_put_u8(buf, eap->eap_method);
418                 wpabuf_put_u8(buf, eap->num_auths);
419                 for (j = 0; j < eap->num_auths; j++) {
420                         wpabuf_put_u8(buf, eap->auth_id[j]);
421                         wpabuf_put_u8(buf, 1);
422                         wpabuf_put_u8(buf, eap->auth_val[j]);
423                 }
424         }
425 }
426
427
428 static void anqp_add_nai_realm_data(struct wpabuf *buf,
429                                     struct hostapd_nai_realm_data *realm,
430                                     unsigned int realm_idx)
431 {
432         u8 *realm_data_len;
433
434         wpa_printf(MSG_DEBUG, "realm=%s, len=%d", realm->realm[realm_idx],
435                    (int) os_strlen(realm->realm[realm_idx]));
436         realm_data_len = wpabuf_put(buf, 2);
437         wpabuf_put_u8(buf, realm->encoding);
438         wpabuf_put_u8(buf, os_strlen(realm->realm[realm_idx]));
439         wpabuf_put_str(buf, realm->realm[realm_idx]);
440         anqp_add_nai_realm_eap(buf, realm);
441         gas_anqp_set_element_len(buf, realm_data_len);
442 }
443
444
445 static int hs20_add_nai_home_realm_matches(struct hostapd_data *hapd,
446                                            struct wpabuf *buf,
447                                            const u8 *home_realm,
448                                            size_t home_realm_len)
449 {
450         unsigned int i, j, k;
451         u8 num_realms, num_matching = 0, encoding, realm_len, *realm_list_len;
452         struct hostapd_nai_realm_data *realm;
453         const u8 *pos, *realm_name, *end;
454         struct {
455                 unsigned int realm_data_idx;
456                 unsigned int realm_idx;
457         } matches[10];
458
459         pos = home_realm;
460         end = pos + home_realm_len;
461         if (end - pos < 1) {
462                 wpa_hexdump(MSG_DEBUG, "Too short NAI Home Realm Query",
463                             home_realm, home_realm_len);
464                 return -1;
465         }
466         num_realms = *pos++;
467
468         for (i = 0; i < num_realms && num_matching < 10; i++) {
469                 if (end - pos < 2) {
470                         wpa_hexdump(MSG_DEBUG,
471                                     "Truncated NAI Home Realm Query",
472                                     home_realm, home_realm_len);
473                         return -1;
474                 }
475                 encoding = *pos++;
476                 realm_len = *pos++;
477                 if (realm_len > end - pos) {
478                         wpa_hexdump(MSG_DEBUG,
479                                     "Truncated NAI Home Realm Query",
480                                     home_realm, home_realm_len);
481                         return -1;
482                 }
483                 realm_name = pos;
484                 for (j = 0; j < hapd->conf->nai_realm_count &&
485                              num_matching < 10; j++) {
486                         const u8 *rpos, *rend;
487                         realm = &hapd->conf->nai_realm_data[j];
488                         if (encoding != realm->encoding)
489                                 continue;
490
491                         rpos = realm_name;
492                         while (rpos < realm_name + realm_len &&
493                                num_matching < 10) {
494                                 for (rend = rpos;
495                                      rend < realm_name + realm_len; rend++) {
496                                         if (*rend == ';')
497                                                 break;
498                                 }
499                                 for (k = 0; k < MAX_NAI_REALMS &&
500                                              realm->realm[k] &&
501                                              num_matching < 10; k++) {
502                                         if ((int) os_strlen(realm->realm[k]) !=
503                                             rend - rpos ||
504                                             os_strncmp((char *) rpos,
505                                                        realm->realm[k],
506                                                        rend - rpos) != 0)
507                                                 continue;
508                                         matches[num_matching].realm_data_idx =
509                                                 j;
510                                         matches[num_matching].realm_idx = k;
511                                         num_matching++;
512                                 }
513                                 rpos = rend + 1;
514                         }
515                 }
516                 pos += realm_len;
517         }
518
519         realm_list_len = gas_anqp_add_element(buf, ANQP_NAI_REALM);
520         wpabuf_put_le16(buf, num_matching);
521
522         /*
523          * There are two ways to format. 1. each realm in a NAI Realm Data unit
524          * 2. all realms that share the same EAP methods in a NAI Realm Data
525          * unit. The first format is likely to be bigger in size than the
526          * second, but may be easier to parse and process by the receiver.
527          */
528         for (i = 0; i < num_matching; i++) {
529                 wpa_printf(MSG_DEBUG, "realm_idx %d, realm_data_idx %d",
530                            matches[i].realm_data_idx, matches[i].realm_idx);
531                 realm = &hapd->conf->nai_realm_data[matches[i].realm_data_idx];
532                 anqp_add_nai_realm_data(buf, realm, matches[i].realm_idx);
533         }
534         gas_anqp_set_element_len(buf, realm_list_len);
535         return 0;
536 }
537
538
539 static void anqp_add_nai_realm(struct hostapd_data *hapd, struct wpabuf *buf,
540                                const u8 *home_realm, size_t home_realm_len,
541                                int nai_realm, int nai_home_realm)
542 {
543         if (nai_realm && !nai_home_realm &&
544             anqp_add_override(hapd, buf, ANQP_NAI_REALM))
545                 return;
546
547         if (nai_realm && hapd->conf->nai_realm_data) {
548                 u8 *len;
549                 unsigned int i, j;
550                 len = gas_anqp_add_element(buf, ANQP_NAI_REALM);
551                 wpabuf_put_le16(buf, hapd->conf->nai_realm_count);
552                 for (i = 0; i < hapd->conf->nai_realm_count; i++) {
553                         u8 *realm_data_len, *realm_len;
554                         struct hostapd_nai_realm_data *realm;
555
556                         realm = &hapd->conf->nai_realm_data[i];
557                         realm_data_len = wpabuf_put(buf, 2);
558                         wpabuf_put_u8(buf, realm->encoding);
559                         realm_len = wpabuf_put(buf, 1);
560                         for (j = 0; realm->realm[j]; j++) {
561                                 if (j > 0)
562                                         wpabuf_put_u8(buf, ';');
563                                 wpabuf_put_str(buf, realm->realm[j]);
564                         }
565                         *realm_len = (u8 *) wpabuf_put(buf, 0) - realm_len - 1;
566                         anqp_add_nai_realm_eap(buf, realm);
567                         gas_anqp_set_element_len(buf, realm_data_len);
568                 }
569                 gas_anqp_set_element_len(buf, len);
570         } else if (nai_home_realm && hapd->conf->nai_realm_data && home_realm) {
571                 hs20_add_nai_home_realm_matches(hapd, buf, home_realm,
572                                                 home_realm_len);
573         }
574 }
575
576
577 static void anqp_add_3gpp_cellular_network(struct hostapd_data *hapd,
578                                            struct wpabuf *buf)
579 {
580         if (anqp_add_override(hapd, buf, ANQP_3GPP_CELLULAR_NETWORK))
581                 return;
582
583         if (hapd->conf->anqp_3gpp_cell_net) {
584                 wpabuf_put_le16(buf, ANQP_3GPP_CELLULAR_NETWORK);
585                 wpabuf_put_le16(buf,
586                                 hapd->conf->anqp_3gpp_cell_net_len);
587                 wpabuf_put_data(buf, hapd->conf->anqp_3gpp_cell_net,
588                                 hapd->conf->anqp_3gpp_cell_net_len);
589         }
590 }
591
592
593 static void anqp_add_domain_name(struct hostapd_data *hapd, struct wpabuf *buf)
594 {
595         if (anqp_add_override(hapd, buf, ANQP_DOMAIN_NAME))
596                 return;
597
598         if (hapd->conf->domain_name) {
599                 wpabuf_put_le16(buf, ANQP_DOMAIN_NAME);
600                 wpabuf_put_le16(buf, hapd->conf->domain_name_len);
601                 wpabuf_put_data(buf, hapd->conf->domain_name,
602                                 hapd->conf->domain_name_len);
603         }
604 }
605
606
607 #ifdef CONFIG_FILS
608 static void anqp_add_fils_realm_info(struct hostapd_data *hapd,
609                                      struct wpabuf *buf)
610 {
611         size_t count;
612
613         if (anqp_add_override(hapd, buf, ANQP_FILS_REALM_INFO))
614                 return;
615
616         count = dl_list_len(&hapd->conf->fils_realms);
617         if (count > 10000)
618                 count = 10000;
619         if (count) {
620                 struct fils_realm *realm;
621
622                 wpabuf_put_le16(buf, ANQP_FILS_REALM_INFO);
623                 wpabuf_put_le16(buf, 2 * count);
624
625                 dl_list_for_each(realm, &hapd->conf->fils_realms,
626                                  struct fils_realm, list) {
627                         if (count == 0)
628                                 break;
629                         wpabuf_put_data(buf, realm->hash, 2);
630                         count--;
631                 }
632         }
633 }
634 #endif /* CONFIG_FILS */
635
636
637 #ifdef CONFIG_HS20
638
639 static void anqp_add_operator_friendly_name(struct hostapd_data *hapd,
640                                             struct wpabuf *buf)
641 {
642         if (hapd->conf->hs20_oper_friendly_name) {
643                 u8 *len;
644                 unsigned int i;
645                 len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
646                 wpabuf_put_be24(buf, OUI_WFA);
647                 wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
648                 wpabuf_put_u8(buf, HS20_STYPE_OPERATOR_FRIENDLY_NAME);
649                 wpabuf_put_u8(buf, 0); /* Reserved */
650                 for (i = 0; i < hapd->conf->hs20_oper_friendly_name_count; i++)
651                 {
652                         struct hostapd_lang_string *vn;
653                         vn = &hapd->conf->hs20_oper_friendly_name[i];
654                         wpabuf_put_u8(buf, 3 + vn->name_len);
655                         wpabuf_put_data(buf, vn->lang, 3);
656                         wpabuf_put_data(buf, vn->name, vn->name_len);
657                 }
658                 gas_anqp_set_element_len(buf, len);
659         }
660 }
661
662
663 static void anqp_add_wan_metrics(struct hostapd_data *hapd,
664                                  struct wpabuf *buf)
665 {
666         if (hapd->conf->hs20_wan_metrics) {
667                 u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
668                 wpabuf_put_be24(buf, OUI_WFA);
669                 wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
670                 wpabuf_put_u8(buf, HS20_STYPE_WAN_METRICS);
671                 wpabuf_put_u8(buf, 0); /* Reserved */
672                 wpabuf_put_data(buf, hapd->conf->hs20_wan_metrics, 13);
673                 gas_anqp_set_element_len(buf, len);
674         }
675 }
676
677
678 static void anqp_add_connection_capability(struct hostapd_data *hapd,
679                                            struct wpabuf *buf)
680 {
681         if (hapd->conf->hs20_connection_capability) {
682                 u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
683                 wpabuf_put_be24(buf, OUI_WFA);
684                 wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
685                 wpabuf_put_u8(buf, HS20_STYPE_CONNECTION_CAPABILITY);
686                 wpabuf_put_u8(buf, 0); /* Reserved */
687                 wpabuf_put_data(buf, hapd->conf->hs20_connection_capability,
688                                 hapd->conf->hs20_connection_capability_len);
689                 gas_anqp_set_element_len(buf, len);
690         }
691 }
692
693
694 static void anqp_add_operating_class(struct hostapd_data *hapd,
695                                      struct wpabuf *buf)
696 {
697         if (hapd->conf->hs20_operating_class) {
698                 u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
699                 wpabuf_put_be24(buf, OUI_WFA);
700                 wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
701                 wpabuf_put_u8(buf, HS20_STYPE_OPERATING_CLASS);
702                 wpabuf_put_u8(buf, 0); /* Reserved */
703                 wpabuf_put_data(buf, hapd->conf->hs20_operating_class,
704                                 hapd->conf->hs20_operating_class_len);
705                 gas_anqp_set_element_len(buf, len);
706         }
707 }
708
709
710 static void anqp_add_icon(struct wpabuf *buf, struct hostapd_bss_config *bss,
711                           const char *name)
712 {
713         size_t j;
714         struct hs20_icon *icon = NULL;
715
716         for (j = 0; j < bss->hs20_icons_count && !icon; j++) {
717                 if (os_strcmp(name, bss->hs20_icons[j].name) == 0)
718                         icon = &bss->hs20_icons[j];
719         }
720         if (!icon)
721                 return; /* icon info not found */
722
723         wpabuf_put_le16(buf, icon->width);
724         wpabuf_put_le16(buf, icon->height);
725         wpabuf_put_data(buf, icon->language, 3);
726         wpabuf_put_u8(buf, os_strlen(icon->type));
727         wpabuf_put_str(buf, icon->type);
728         wpabuf_put_u8(buf, os_strlen(icon->name));
729         wpabuf_put_str(buf, icon->name);
730 }
731
732
733 static void anqp_add_osu_provider(struct wpabuf *buf,
734                                   struct hostapd_bss_config *bss,
735                                   struct hs20_osu_provider *p)
736 {
737         u8 *len, *len2, *count;
738         unsigned int i;
739
740         len = wpabuf_put(buf, 2); /* OSU Provider Length to be filled */
741
742         /* OSU Friendly Name Duples */
743         len2 = wpabuf_put(buf, 2);
744         for (i = 0; i < p->friendly_name_count; i++) {
745                 struct hostapd_lang_string *s = &p->friendly_name[i];
746                 wpabuf_put_u8(buf, 3 + s->name_len);
747                 wpabuf_put_data(buf, s->lang, 3);
748                 wpabuf_put_data(buf, s->name, s->name_len);
749         }
750         WPA_PUT_LE16(len2, (u8 *) wpabuf_put(buf, 0) - len2 - 2);
751
752         /* OSU Server URI */
753         if (p->server_uri) {
754                 wpabuf_put_u8(buf, os_strlen(p->server_uri));
755                 wpabuf_put_str(buf, p->server_uri);
756         } else
757                 wpabuf_put_u8(buf, 0);
758
759         /* OSU Method List */
760         count = wpabuf_put(buf, 1);
761         for (i = 0; p->method_list && p->method_list[i] >= 0; i++)
762                 wpabuf_put_u8(buf, p->method_list[i]);
763         *count = i;
764
765         /* Icons Available */
766         len2 = wpabuf_put(buf, 2);
767         for (i = 0; i < p->icons_count; i++)
768                 anqp_add_icon(buf, bss, p->icons[i]);
769         WPA_PUT_LE16(len2, (u8 *) wpabuf_put(buf, 0) - len2 - 2);
770
771         /* OSU_NAI */
772         if (p->osu_nai) {
773                 wpabuf_put_u8(buf, os_strlen(p->osu_nai));
774                 wpabuf_put_str(buf, p->osu_nai);
775         } else
776                 wpabuf_put_u8(buf, 0);
777
778         /* OSU Service Description Duples */
779         len2 = wpabuf_put(buf, 2);
780         for (i = 0; i < p->service_desc_count; i++) {
781                 struct hostapd_lang_string *s = &p->service_desc[i];
782                 wpabuf_put_u8(buf, 3 + s->name_len);
783                 wpabuf_put_data(buf, s->lang, 3);
784                 wpabuf_put_data(buf, s->name, s->name_len);
785         }
786         WPA_PUT_LE16(len2, (u8 *) wpabuf_put(buf, 0) - len2 - 2);
787
788         WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
789 }
790
791
792 static void anqp_add_osu_providers_list(struct hostapd_data *hapd,
793                                         struct wpabuf *buf)
794 {
795         if (hapd->conf->hs20_osu_providers_count) {
796                 size_t i;
797                 u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
798                 wpabuf_put_be24(buf, OUI_WFA);
799                 wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
800                 wpabuf_put_u8(buf, HS20_STYPE_OSU_PROVIDERS_LIST);
801                 wpabuf_put_u8(buf, 0); /* Reserved */
802
803                 /* OSU SSID */
804                 wpabuf_put_u8(buf, hapd->conf->osu_ssid_len);
805                 wpabuf_put_data(buf, hapd->conf->osu_ssid,
806                                 hapd->conf->osu_ssid_len);
807
808                 /* Number of OSU Providers */
809                 wpabuf_put_u8(buf, hapd->conf->hs20_osu_providers_count);
810
811                 for (i = 0; i < hapd->conf->hs20_osu_providers_count; i++) {
812                         anqp_add_osu_provider(
813                                 buf, hapd->conf,
814                                 &hapd->conf->hs20_osu_providers[i]);
815                 }
816
817                 gas_anqp_set_element_len(buf, len);
818         }
819 }
820
821
822 static void anqp_add_osu_provider_nai(struct wpabuf *buf,
823                                       struct hs20_osu_provider *p)
824 {
825         /* OSU_NAI for shared BSS (Single SSID) */
826         if (p->osu_nai2) {
827                 wpabuf_put_u8(buf, os_strlen(p->osu_nai2));
828                 wpabuf_put_str(buf, p->osu_nai2);
829         } else {
830                 wpabuf_put_u8(buf, 0);
831         }
832 }
833
834
835 static void anqp_add_osu_providers_nai_list(struct hostapd_data *hapd,
836                                             struct wpabuf *buf)
837 {
838         if (hapd->conf->hs20_osu_providers_nai_count) {
839                 size_t i;
840                 u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
841                 wpabuf_put_be24(buf, OUI_WFA);
842                 wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
843                 wpabuf_put_u8(buf, HS20_STYPE_OSU_PROVIDERS_NAI_LIST);
844                 wpabuf_put_u8(buf, 0); /* Reserved */
845
846                 for (i = 0; i < hapd->conf->hs20_osu_providers_count; i++) {
847                         anqp_add_osu_provider_nai(
848                                 buf, &hapd->conf->hs20_osu_providers[i]);
849                 }
850
851                 gas_anqp_set_element_len(buf, len);
852         }
853 }
854
855
856 static void anqp_add_icon_binary_file(struct hostapd_data *hapd,
857                                       struct wpabuf *buf,
858                                       const u8 *name, size_t name_len)
859 {
860         struct hs20_icon *icon;
861         size_t i;
862         u8 *len;
863
864         wpa_hexdump_ascii(MSG_DEBUG, "HS 2.0: Requested Icon Filename",
865                           name, name_len);
866         for (i = 0; i < hapd->conf->hs20_icons_count; i++) {
867                 icon = &hapd->conf->hs20_icons[i];
868                 if (name_len == os_strlen(icon->name) &&
869                     os_memcmp(name, icon->name, name_len) == 0)
870                         break;
871         }
872
873         if (i < hapd->conf->hs20_icons_count)
874                 icon = &hapd->conf->hs20_icons[i];
875         else
876                 icon = NULL;
877
878         len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
879         wpabuf_put_be24(buf, OUI_WFA);
880         wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
881         wpabuf_put_u8(buf, HS20_STYPE_ICON_BINARY_FILE);
882         wpabuf_put_u8(buf, 0); /* Reserved */
883
884         if (icon) {
885                 char *data;
886                 size_t data_len;
887
888                 data = os_readfile(icon->file, &data_len);
889                 if (data == NULL || data_len > 65535) {
890                         wpabuf_put_u8(buf, 2); /* Download Status:
891                                                 * Unspecified file error */
892                         wpabuf_put_u8(buf, 0);
893                         wpabuf_put_le16(buf, 0);
894                 } else {
895                         wpabuf_put_u8(buf, 0); /* Download Status: Success */
896                         wpabuf_put_u8(buf, os_strlen(icon->type));
897                         wpabuf_put_str(buf, icon->type);
898                         wpabuf_put_le16(buf, data_len);
899                         wpabuf_put_data(buf, data, data_len);
900                 }
901                 os_free(data);
902         } else {
903                 wpabuf_put_u8(buf, 1); /* Download Status: File not found */
904                 wpabuf_put_u8(buf, 0);
905                 wpabuf_put_le16(buf, 0);
906         }
907
908         gas_anqp_set_element_len(buf, len);
909 }
910
911
912 static void anqp_add_operator_icon_metadata(struct hostapd_data *hapd,
913                                             struct wpabuf *buf)
914 {
915         struct hostapd_bss_config *bss = hapd->conf;
916         size_t i;
917         u8 *len;
918
919         if (!bss->hs20_operator_icon_count)
920                 return;
921
922         len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
923
924         wpabuf_put_be24(buf, OUI_WFA);
925         wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
926         wpabuf_put_u8(buf, HS20_STYPE_OPERATOR_ICON_METADATA);
927         wpabuf_put_u8(buf, 0); /* Reserved */
928
929         for (i = 0; i < bss->hs20_operator_icon_count; i++)
930                 anqp_add_icon(buf, bss, bss->hs20_operator_icon[i]);
931
932         gas_anqp_set_element_len(buf, len);
933 }
934
935 #endif /* CONFIG_HS20 */
936
937
938 #ifdef CONFIG_MBO
939 static void anqp_add_mbo_cell_data_conn_pref(struct hostapd_data *hapd,
940                                              struct wpabuf *buf)
941 {
942         if (hapd->conf->mbo_cell_data_conn_pref >= 0) {
943                 u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
944                 wpabuf_put_be24(buf, OUI_WFA);
945                 wpabuf_put_u8(buf, MBO_ANQP_OUI_TYPE);
946                 wpabuf_put_u8(buf, MBO_ANQP_SUBTYPE_CELL_CONN_PREF);
947                 wpabuf_put_u8(buf, hapd->conf->mbo_cell_data_conn_pref);
948                 gas_anqp_set_element_len(buf, len);
949         }
950 }
951 #endif /* CONFIG_MBO */
952
953
954 static size_t anqp_get_required_len(struct hostapd_data *hapd,
955                                     const u16 *infoid,
956                                     unsigned int num_infoid)
957 {
958         size_t len = 0;
959         unsigned int i;
960
961         for (i = 0; i < num_infoid; i++) {
962                 struct anqp_element *elem = get_anqp_elem(hapd, infoid[i]);
963
964                 if (elem)
965                         len += 2 + 2 + wpabuf_len(elem->payload);
966         }
967
968         return len;
969 }
970
971
972 static struct wpabuf *
973 gas_serv_build_gas_resp_payload(struct hostapd_data *hapd,
974                                 unsigned int request,
975                                 const u8 *home_realm, size_t home_realm_len,
976                                 const u8 *icon_name, size_t icon_name_len,
977                                 const u16 *extra_req,
978                                 unsigned int num_extra_req)
979 {
980         struct wpabuf *buf;
981         size_t len;
982         unsigned int i;
983
984         len = 1400;
985         if (request & (ANQP_REQ_NAI_REALM | ANQP_REQ_NAI_HOME_REALM))
986                 len += 1000;
987         if (request & ANQP_REQ_ICON_REQUEST)
988                 len += 65536;
989 #ifdef CONFIG_FILS
990         if (request & ANQP_FILS_REALM_INFO)
991                 len += 2 * dl_list_len(&hapd->conf->fils_realms);
992 #endif /* CONFIG_FILS */
993         len += anqp_get_required_len(hapd, extra_req, num_extra_req);
994
995         buf = wpabuf_alloc(len);
996         if (buf == NULL)
997                 return NULL;
998
999         if (request & ANQP_REQ_CAPABILITY_LIST)
1000                 anqp_add_capab_list(hapd, buf);
1001         if (request & ANQP_REQ_VENUE_NAME)
1002                 anqp_add_venue_name(hapd, buf);
1003         if (request & ANQP_REQ_EMERGENCY_CALL_NUMBER)
1004                 anqp_add_elem(hapd, buf, ANQP_EMERGENCY_CALL_NUMBER);
1005         if (request & ANQP_REQ_NETWORK_AUTH_TYPE)
1006                 anqp_add_network_auth_type(hapd, buf);
1007         if (request & ANQP_REQ_ROAMING_CONSORTIUM)
1008                 anqp_add_roaming_consortium(hapd, buf);
1009         if (request & ANQP_REQ_IP_ADDR_TYPE_AVAILABILITY)
1010                 anqp_add_ip_addr_type_availability(hapd, buf);
1011         if (request & (ANQP_REQ_NAI_REALM | ANQP_REQ_NAI_HOME_REALM))
1012                 anqp_add_nai_realm(hapd, buf, home_realm, home_realm_len,
1013                                    request & ANQP_REQ_NAI_REALM,
1014                                    request & ANQP_REQ_NAI_HOME_REALM);
1015         if (request & ANQP_REQ_3GPP_CELLULAR_NETWORK)
1016                 anqp_add_3gpp_cellular_network(hapd, buf);
1017         if (request & ANQP_REQ_AP_GEOSPATIAL_LOCATION)
1018                 anqp_add_elem(hapd, buf, ANQP_AP_GEOSPATIAL_LOCATION);
1019         if (request & ANQP_REQ_AP_CIVIC_LOCATION)
1020                 anqp_add_elem(hapd, buf, ANQP_AP_CIVIC_LOCATION);
1021         if (request & ANQP_REQ_AP_LOCATION_PUBLIC_URI)
1022                 anqp_add_elem(hapd, buf, ANQP_AP_LOCATION_PUBLIC_URI);
1023         if (request & ANQP_REQ_DOMAIN_NAME)
1024                 anqp_add_domain_name(hapd, buf);
1025         if (request & ANQP_REQ_EMERGENCY_ALERT_URI)
1026                 anqp_add_elem(hapd, buf, ANQP_EMERGENCY_ALERT_URI);
1027         if (request & ANQP_REQ_TDLS_CAPABILITY)
1028                 anqp_add_elem(hapd, buf, ANQP_TDLS_CAPABILITY);
1029         if (request & ANQP_REQ_EMERGENCY_NAI)
1030                 anqp_add_elem(hapd, buf, ANQP_EMERGENCY_NAI);
1031
1032         for (i = 0; i < num_extra_req; i++) {
1033 #ifdef CONFIG_FILS
1034                 if (extra_req[i] == ANQP_FILS_REALM_INFO) {
1035                         anqp_add_fils_realm_info(hapd, buf);
1036                         continue;
1037                 }
1038 #endif /* CONFIG_FILS */
1039                 if (extra_req[i] == ANQP_VENUE_URL) {
1040                         anqp_add_venue_url(hapd, buf);
1041                         continue;
1042                 }
1043                 anqp_add_elem(hapd, buf, extra_req[i]);
1044         }
1045
1046 #ifdef CONFIG_HS20
1047         if (request & ANQP_REQ_HS_CAPABILITY_LIST)
1048                 anqp_add_hs_capab_list(hapd, buf);
1049         if (request & ANQP_REQ_OPERATOR_FRIENDLY_NAME)
1050                 anqp_add_operator_friendly_name(hapd, buf);
1051         if (request & ANQP_REQ_WAN_METRICS)
1052                 anqp_add_wan_metrics(hapd, buf);
1053         if (request & ANQP_REQ_CONNECTION_CAPABILITY)
1054                 anqp_add_connection_capability(hapd, buf);
1055         if (request & ANQP_REQ_OPERATING_CLASS)
1056                 anqp_add_operating_class(hapd, buf);
1057         if (request & ANQP_REQ_OSU_PROVIDERS_LIST)
1058                 anqp_add_osu_providers_list(hapd, buf);
1059         if (request & ANQP_REQ_ICON_REQUEST)
1060                 anqp_add_icon_binary_file(hapd, buf, icon_name, icon_name_len);
1061         if (request & ANQP_REQ_OPERATOR_ICON_METADATA)
1062                 anqp_add_operator_icon_metadata(hapd, buf);
1063         if (request & ANQP_REQ_OSU_PROVIDERS_NAI_LIST)
1064                 anqp_add_osu_providers_nai_list(hapd, buf);
1065 #endif /* CONFIG_HS20 */
1066
1067 #ifdef CONFIG_MBO
1068         if (request & ANQP_REQ_MBO_CELL_DATA_CONN_PREF)
1069                 anqp_add_mbo_cell_data_conn_pref(hapd, buf);
1070 #endif /* CONFIG_MBO */
1071
1072         return buf;
1073 }
1074
1075
1076 #define ANQP_MAX_EXTRA_REQ 20
1077
1078 struct anqp_query_info {
1079         unsigned int request;
1080         const u8 *home_realm_query;
1081         size_t home_realm_query_len;
1082         const u8 *icon_name;
1083         size_t icon_name_len;
1084         int p2p_sd;
1085         u16 extra_req[ANQP_MAX_EXTRA_REQ];
1086         unsigned int num_extra_req;
1087 };
1088
1089
1090 static void set_anqp_req(unsigned int bit, const char *name, int local,
1091                          struct anqp_query_info *qi)
1092 {
1093         qi->request |= bit;
1094         if (local) {
1095                 wpa_printf(MSG_DEBUG, "ANQP: %s (local)", name);
1096         } else {
1097                 wpa_printf(MSG_DEBUG, "ANQP: %s not available", name);
1098         }
1099 }
1100
1101
1102 static void rx_anqp_query_list_id(struct hostapd_data *hapd, u16 info_id,
1103                                   struct anqp_query_info *qi)
1104 {
1105         switch (info_id) {
1106         case ANQP_CAPABILITY_LIST:
1107                 set_anqp_req(ANQP_REQ_CAPABILITY_LIST, "Capability List", 1,
1108                              qi);
1109                 break;
1110         case ANQP_VENUE_NAME:
1111                 set_anqp_req(ANQP_REQ_VENUE_NAME, "Venue Name",
1112                              hapd->conf->venue_name != NULL, qi);
1113                 break;
1114         case ANQP_EMERGENCY_CALL_NUMBER:
1115                 set_anqp_req(ANQP_REQ_EMERGENCY_CALL_NUMBER,
1116                              "Emergency Call Number",
1117                              get_anqp_elem(hapd, info_id) != NULL, qi);
1118                 break;
1119         case ANQP_NETWORK_AUTH_TYPE:
1120                 set_anqp_req(ANQP_REQ_NETWORK_AUTH_TYPE, "Network Auth Type",
1121                              hapd->conf->network_auth_type != NULL, qi);
1122                 break;
1123         case ANQP_ROAMING_CONSORTIUM:
1124                 set_anqp_req(ANQP_REQ_ROAMING_CONSORTIUM, "Roaming Consortium",
1125                              hapd->conf->roaming_consortium != NULL, qi);
1126                 break;
1127         case ANQP_IP_ADDR_TYPE_AVAILABILITY:
1128                 set_anqp_req(ANQP_REQ_IP_ADDR_TYPE_AVAILABILITY,
1129                              "IP Addr Type Availability",
1130                              hapd->conf->ipaddr_type_configured, qi);
1131                 break;
1132         case ANQP_NAI_REALM:
1133                 set_anqp_req(ANQP_REQ_NAI_REALM, "NAI Realm",
1134                              hapd->conf->nai_realm_data != NULL, qi);
1135                 break;
1136         case ANQP_3GPP_CELLULAR_NETWORK:
1137                 set_anqp_req(ANQP_REQ_3GPP_CELLULAR_NETWORK,
1138                              "3GPP Cellular Network",
1139                              hapd->conf->anqp_3gpp_cell_net != NULL, qi);
1140                 break;
1141         case ANQP_AP_GEOSPATIAL_LOCATION:
1142                 set_anqp_req(ANQP_REQ_AP_GEOSPATIAL_LOCATION,
1143                              "AP Geospatial Location",
1144                              get_anqp_elem(hapd, info_id) != NULL, qi);
1145                 break;
1146         case ANQP_AP_CIVIC_LOCATION:
1147                 set_anqp_req(ANQP_REQ_AP_CIVIC_LOCATION,
1148                              "AP Civic Location",
1149                              get_anqp_elem(hapd, info_id) != NULL, qi);
1150                 break;
1151         case ANQP_AP_LOCATION_PUBLIC_URI:
1152                 set_anqp_req(ANQP_REQ_AP_LOCATION_PUBLIC_URI,
1153                              "AP Location Public URI",
1154                              get_anqp_elem(hapd, info_id) != NULL, qi);
1155                 break;
1156         case ANQP_DOMAIN_NAME:
1157                 set_anqp_req(ANQP_REQ_DOMAIN_NAME, "Domain Name",
1158                              hapd->conf->domain_name != NULL, qi);
1159                 break;
1160         case ANQP_EMERGENCY_ALERT_URI:
1161                 set_anqp_req(ANQP_REQ_EMERGENCY_ALERT_URI,
1162                              "Emergency Alert URI",
1163                              get_anqp_elem(hapd, info_id) != NULL, qi);
1164                 break;
1165         case ANQP_TDLS_CAPABILITY:
1166                 set_anqp_req(ANQP_REQ_TDLS_CAPABILITY,
1167                              "TDLS Capability",
1168                              get_anqp_elem(hapd, info_id) != NULL, qi);
1169                 break;
1170         case ANQP_EMERGENCY_NAI:
1171                 set_anqp_req(ANQP_REQ_EMERGENCY_NAI,
1172                              "Emergency NAI",
1173                              get_anqp_elem(hapd, info_id) != NULL, qi);
1174                 break;
1175         default:
1176 #ifdef CONFIG_FILS
1177                 if (info_id == ANQP_FILS_REALM_INFO &&
1178                     !dl_list_empty(&hapd->conf->fils_realms)) {
1179                         wpa_printf(MSG_DEBUG,
1180                                    "ANQP: FILS Realm Information (local)");
1181                 } else
1182 #endif /* CONFIG_FILS */
1183                 if (info_id == ANQP_VENUE_URL && hapd->conf->venue_url) {
1184                         wpa_printf(MSG_DEBUG,
1185                                    "ANQP: Venue URL (local)");
1186                 } else if (!get_anqp_elem(hapd, info_id)) {
1187                         wpa_printf(MSG_DEBUG, "ANQP: Unsupported Info Id %u",
1188                                    info_id);
1189                         break;
1190                 }
1191                 if (qi->num_extra_req == ANQP_MAX_EXTRA_REQ) {
1192                         wpa_printf(MSG_DEBUG,
1193                                    "ANQP: No more room for extra requests - ignore Info Id %u",
1194                                    info_id);
1195                         break;
1196                 }
1197                 wpa_printf(MSG_DEBUG, "ANQP: Info Id %u (local)", info_id);
1198                 qi->extra_req[qi->num_extra_req] = info_id;
1199                 qi->num_extra_req++;
1200                 break;
1201         }
1202 }
1203
1204
1205 static void rx_anqp_query_list(struct hostapd_data *hapd,
1206                                const u8 *pos, const u8 *end,
1207                                struct anqp_query_info *qi)
1208 {
1209         wpa_printf(MSG_DEBUG, "ANQP: %u Info IDs requested in Query list",
1210                    (unsigned int) (end - pos) / 2);
1211
1212         while (end - pos >= 2) {
1213                 rx_anqp_query_list_id(hapd, WPA_GET_LE16(pos), qi);
1214                 pos += 2;
1215         }
1216 }
1217
1218
1219 #ifdef CONFIG_HS20
1220
1221 static void rx_anqp_hs_query_list(struct hostapd_data *hapd, u8 subtype,
1222                                   struct anqp_query_info *qi)
1223 {
1224         switch (subtype) {
1225         case HS20_STYPE_CAPABILITY_LIST:
1226                 set_anqp_req(ANQP_REQ_HS_CAPABILITY_LIST, "HS Capability List",
1227                              1, qi);
1228                 break;
1229         case HS20_STYPE_OPERATOR_FRIENDLY_NAME:
1230                 set_anqp_req(ANQP_REQ_OPERATOR_FRIENDLY_NAME,
1231                              "Operator Friendly Name",
1232                              hapd->conf->hs20_oper_friendly_name != NULL, qi);
1233                 break;
1234         case HS20_STYPE_WAN_METRICS:
1235                 set_anqp_req(ANQP_REQ_WAN_METRICS, "WAN Metrics",
1236                              hapd->conf->hs20_wan_metrics != NULL, qi);
1237                 break;
1238         case HS20_STYPE_CONNECTION_CAPABILITY:
1239                 set_anqp_req(ANQP_REQ_CONNECTION_CAPABILITY,
1240                              "Connection Capability",
1241                              hapd->conf->hs20_connection_capability != NULL,
1242                              qi);
1243                 break;
1244         case HS20_STYPE_OPERATING_CLASS:
1245                 set_anqp_req(ANQP_REQ_OPERATING_CLASS, "Operating Class",
1246                              hapd->conf->hs20_operating_class != NULL, qi);
1247                 break;
1248         case HS20_STYPE_OSU_PROVIDERS_LIST:
1249                 set_anqp_req(ANQP_REQ_OSU_PROVIDERS_LIST, "OSU Providers list",
1250                              hapd->conf->hs20_osu_providers_count, qi);
1251                 break;
1252         case HS20_STYPE_OPERATOR_ICON_METADATA:
1253                 set_anqp_req(ANQP_REQ_OPERATOR_ICON_METADATA,
1254                              "Operator Icon Metadata",
1255                              hapd->conf->hs20_operator_icon_count, qi);
1256                 break;
1257         case HS20_STYPE_OSU_PROVIDERS_NAI_LIST:
1258                 set_anqp_req(ANQP_REQ_OSU_PROVIDERS_NAI_LIST,
1259                              "OSU Providers NAI List",
1260                              hapd->conf->hs20_osu_providers_nai_count, qi);
1261                 break;
1262         default:
1263                 wpa_printf(MSG_DEBUG, "ANQP: Unsupported HS 2.0 subtype %u",
1264                            subtype);
1265                 break;
1266         }
1267 }
1268
1269
1270 static void rx_anqp_hs_nai_home_realm(struct hostapd_data *hapd,
1271                                       const u8 *pos, const u8 *end,
1272                                       struct anqp_query_info *qi)
1273 {
1274         qi->request |= ANQP_REQ_NAI_HOME_REALM;
1275         qi->home_realm_query = pos;
1276         qi->home_realm_query_len = end - pos;
1277         if (hapd->conf->nai_realm_data != NULL) {
1278                 wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 NAI Home Realm Query "
1279                            "(local)");
1280         } else {
1281                 wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 NAI Home Realm Query not "
1282                            "available");
1283         }
1284 }
1285
1286
1287 static void rx_anqp_hs_icon_request(struct hostapd_data *hapd,
1288                                     const u8 *pos, const u8 *end,
1289                                     struct anqp_query_info *qi)
1290 {
1291         qi->request |= ANQP_REQ_ICON_REQUEST;
1292         qi->icon_name = pos;
1293         qi->icon_name_len = end - pos;
1294         if (hapd->conf->hs20_icons_count) {
1295                 wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 Icon Request Query "
1296                            "(local)");
1297         } else {
1298                 wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 Icon Request Query not "
1299                            "available");
1300         }
1301 }
1302
1303
1304 static void rx_anqp_vendor_specific_hs20(struct hostapd_data *hapd,
1305                                          const u8 *pos, const u8 *end,
1306                                          struct anqp_query_info *qi)
1307 {
1308         u8 subtype;
1309
1310         if (end - pos <= 1)
1311                 return;
1312
1313         subtype = *pos++;
1314         pos++; /* Reserved */
1315         switch (subtype) {
1316         case HS20_STYPE_QUERY_LIST:
1317                 wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 Query List");
1318                 while (pos < end) {
1319                         rx_anqp_hs_query_list(hapd, *pos, qi);
1320                         pos++;
1321                 }
1322                 break;
1323         case HS20_STYPE_NAI_HOME_REALM_QUERY:
1324                 rx_anqp_hs_nai_home_realm(hapd, pos, end, qi);
1325                 break;
1326         case HS20_STYPE_ICON_REQUEST:
1327                 rx_anqp_hs_icon_request(hapd, pos, end, qi);
1328                 break;
1329         default:
1330                 wpa_printf(MSG_DEBUG, "ANQP: Unsupported HS 2.0 query subtype "
1331                            "%u", subtype);
1332                 break;
1333         }
1334 }
1335
1336 #endif /* CONFIG_HS20 */
1337
1338
1339 #ifdef CONFIG_P2P
1340 static void rx_anqp_vendor_specific_p2p(struct hostapd_data *hapd,
1341                                         struct anqp_query_info *qi)
1342 {
1343         /*
1344          * This is for P2P SD and will be taken care of by the P2P
1345          * implementation. This query needs to be ignored in the generic
1346          * GAS server to avoid duplicated response.
1347          */
1348         wpa_printf(MSG_DEBUG,
1349                    "ANQP: Ignore WFA vendor type %u (P2P SD) in generic GAS server",
1350                    P2P_OUI_TYPE);
1351         qi->p2p_sd = 1;
1352         return;
1353 }
1354 #endif /* CONFIG_P2P */
1355
1356
1357 #ifdef CONFIG_MBO
1358
1359 static void rx_anqp_mbo_query_list(struct hostapd_data *hapd, u8 subtype,
1360                                   struct anqp_query_info *qi)
1361 {
1362         switch (subtype) {
1363         case MBO_ANQP_SUBTYPE_CELL_CONN_PREF:
1364                 set_anqp_req(ANQP_REQ_MBO_CELL_DATA_CONN_PREF,
1365                              "Cellular Data Connection Preference",
1366                              hapd->conf->mbo_cell_data_conn_pref >= 0, qi);
1367                 break;
1368         default:
1369                 wpa_printf(MSG_DEBUG, "ANQP: Unsupported MBO subtype %u",
1370                            subtype);
1371                 break;
1372         }
1373 }
1374
1375
1376 static void rx_anqp_vendor_specific_mbo(struct hostapd_data *hapd,
1377                                         const u8 *pos, const u8 *end,
1378                                         struct anqp_query_info *qi)
1379 {
1380         u8 subtype;
1381
1382         if (end - pos < 1)
1383                 return;
1384
1385         subtype = *pos++;
1386         switch (subtype) {
1387         case MBO_ANQP_SUBTYPE_QUERY_LIST:
1388                 wpa_printf(MSG_DEBUG, "ANQP: MBO Query List");
1389                 while (pos < end) {
1390                         rx_anqp_mbo_query_list(hapd, *pos, qi);
1391                         pos++;
1392                 }
1393                 break;
1394         default:
1395                 wpa_printf(MSG_DEBUG, "ANQP: Unsupported MBO query subtype %u",
1396                            subtype);
1397                 break;
1398         }
1399 }
1400
1401 #endif /* CONFIG_MBO */
1402
1403
1404 static void rx_anqp_vendor_specific(struct hostapd_data *hapd,
1405                                     const u8 *pos, const u8 *end,
1406                                     struct anqp_query_info *qi)
1407 {
1408         u32 oui;
1409
1410         if (end - pos < 4) {
1411                 wpa_printf(MSG_DEBUG, "ANQP: Too short vendor specific ANQP "
1412                            "Query element");
1413                 return;
1414         }
1415
1416         oui = WPA_GET_BE24(pos);
1417         pos += 3;
1418         if (oui != OUI_WFA) {
1419                 wpa_printf(MSG_DEBUG, "ANQP: Unsupported vendor OUI %06x",
1420                            oui);
1421                 return;
1422         }
1423
1424         switch (*pos) {
1425 #ifdef CONFIG_P2P
1426         case P2P_OUI_TYPE:
1427                 rx_anqp_vendor_specific_p2p(hapd, qi);
1428                 break;
1429 #endif /* CONFIG_P2P */
1430 #ifdef CONFIG_HS20
1431         case HS20_ANQP_OUI_TYPE:
1432                 rx_anqp_vendor_specific_hs20(hapd, pos + 1, end, qi);
1433                 break;
1434 #endif /* CONFIG_HS20 */
1435 #ifdef CONFIG_MBO
1436         case MBO_ANQP_OUI_TYPE:
1437                 rx_anqp_vendor_specific_mbo(hapd, pos + 1, end, qi);
1438                 break;
1439 #endif /* CONFIG_MBO */
1440         default:
1441                 wpa_printf(MSG_DEBUG, "ANQP: Unsupported WFA vendor type %u",
1442                            *pos);
1443                 break;
1444         }
1445 }
1446
1447
1448 static void gas_serv_req_local_processing(struct hostapd_data *hapd,
1449                                           const u8 *sa, u8 dialog_token,
1450                                           struct anqp_query_info *qi, int prot,
1451                                           int std_addr3)
1452 {
1453         struct wpabuf *buf, *tx_buf;
1454
1455         buf = gas_serv_build_gas_resp_payload(hapd, qi->request,
1456                                               qi->home_realm_query,
1457                                               qi->home_realm_query_len,
1458                                               qi->icon_name, qi->icon_name_len,
1459                                               qi->extra_req, qi->num_extra_req);
1460         wpa_hexdump_buf(MSG_MSGDUMP, "ANQP: Locally generated ANQP responses",
1461                         buf);
1462         if (!buf)
1463                 return;
1464 #ifdef CONFIG_P2P
1465         if (wpabuf_len(buf) == 0 && qi->p2p_sd) {
1466                 wpa_printf(MSG_DEBUG,
1467                            "ANQP: Do not send response to P2P SD from generic GAS service (P2P SD implementation will process this)");
1468                 wpabuf_free(buf);
1469                 return;
1470         }
1471 #endif /* CONFIG_P2P */
1472
1473         if (wpabuf_len(buf) > hapd->conf->gas_frag_limit ||
1474             hapd->conf->gas_comeback_delay) {
1475                 struct gas_dialog_info *di;
1476                 u16 comeback_delay = 1;
1477
1478                 if (hapd->conf->gas_comeback_delay) {
1479                         /* Testing - allow overriding of the delay value */
1480                         comeback_delay = hapd->conf->gas_comeback_delay;
1481                 }
1482
1483                 wpa_printf(MSG_DEBUG, "ANQP: Too long response to fit in "
1484                            "initial response - use GAS comeback");
1485                 di = gas_dialog_create(hapd, sa, dialog_token);
1486                 if (!di) {
1487                         wpa_printf(MSG_INFO, "ANQP: Could not create dialog "
1488                                    "for " MACSTR " (dialog token %u)",
1489                                    MAC2STR(sa), dialog_token);
1490                         wpabuf_free(buf);
1491                         tx_buf = gas_anqp_build_initial_resp_buf(
1492                                 dialog_token, WLAN_STATUS_UNSPECIFIED_FAILURE,
1493                                 0, NULL);
1494                 } else {
1495                         di->prot = prot;
1496                         di->sd_resp = buf;
1497                         di->sd_resp_pos = 0;
1498                         tx_buf = gas_anqp_build_initial_resp_buf(
1499                                 dialog_token, WLAN_STATUS_SUCCESS,
1500                                 comeback_delay, NULL);
1501                 }
1502         } else {
1503                 wpa_printf(MSG_DEBUG, "ANQP: Initial response (no comeback)");
1504                 tx_buf = gas_anqp_build_initial_resp_buf(
1505                         dialog_token, WLAN_STATUS_SUCCESS, 0, buf);
1506                 wpabuf_free(buf);
1507         }
1508         if (!tx_buf)
1509                 return;
1510         if (prot)
1511                 convert_to_protected_dual(tx_buf);
1512         if (std_addr3)
1513                 hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
1514                                         wpabuf_head(tx_buf),
1515                                         wpabuf_len(tx_buf));
1516         else
1517                 hostapd_drv_send_action_addr3_ap(hapd, hapd->iface->freq, 0, sa,
1518                                                  wpabuf_head(tx_buf),
1519                                                  wpabuf_len(tx_buf));
1520         wpabuf_free(tx_buf);
1521 }
1522
1523
1524 #ifdef CONFIG_DPP
1525 void gas_serv_req_dpp_processing(struct hostapd_data *hapd,
1526                                  const u8 *sa, u8 dialog_token,
1527                                  int prot, struct wpabuf *buf)
1528 {
1529         struct wpabuf *tx_buf;
1530
1531         if (wpabuf_len(buf) > hapd->conf->gas_frag_limit ||
1532             hapd->conf->gas_comeback_delay) {
1533                 struct gas_dialog_info *di;
1534                 u16 comeback_delay = 1;
1535
1536                 if (hapd->conf->gas_comeback_delay) {
1537                         /* Testing - allow overriding of the delay value */
1538                         comeback_delay = hapd->conf->gas_comeback_delay;
1539                 }
1540
1541                 wpa_printf(MSG_DEBUG,
1542                            "DPP: Too long response to fit in initial response - use GAS comeback");
1543                 di = gas_dialog_create(hapd, sa, dialog_token);
1544                 if (!di) {
1545                         wpa_printf(MSG_INFO, "DPP: Could not create dialog for "
1546                                    MACSTR " (dialog token %u)",
1547                                    MAC2STR(sa), dialog_token);
1548                         wpabuf_free(buf);
1549                         tx_buf = gas_build_initial_resp(
1550                                 dialog_token, WLAN_STATUS_UNSPECIFIED_FAILURE,
1551                                 0, 10);
1552                         if (tx_buf)
1553                                 gas_serv_write_dpp_adv_proto(tx_buf);
1554                 } else {
1555                         di->prot = prot;
1556                         di->sd_resp = buf;
1557                         di->sd_resp_pos = 0;
1558                         tx_buf = gas_build_initial_resp(
1559                                 dialog_token, WLAN_STATUS_SUCCESS,
1560                                 comeback_delay, 10);
1561                         if (tx_buf)
1562                                 gas_serv_write_dpp_adv_proto(tx_buf);
1563                 }
1564         } else {
1565                 wpa_printf(MSG_DEBUG,
1566                            "DPP: GAS Initial response (no comeback)");
1567                 tx_buf = gas_build_initial_resp(
1568                         dialog_token, WLAN_STATUS_SUCCESS, 0,
1569                         10 + 2 + wpabuf_len(buf));
1570                 if (tx_buf) {
1571                         gas_serv_write_dpp_adv_proto(tx_buf);
1572                         wpabuf_put_le16(tx_buf, wpabuf_len(buf));
1573                         wpabuf_put_buf(tx_buf, buf);
1574                         hostapd_dpp_gas_status_handler(hapd, 1);
1575                 }
1576                 wpabuf_free(buf);
1577         }
1578         if (!tx_buf)
1579                 return;
1580         if (prot)
1581                 convert_to_protected_dual(tx_buf);
1582         hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
1583                                 wpabuf_head(tx_buf),
1584                                 wpabuf_len(tx_buf));
1585         wpabuf_free(tx_buf);
1586 }
1587 #endif /* CONFIG_DPP */
1588
1589
1590 static void gas_serv_rx_gas_initial_req(struct hostapd_data *hapd,
1591                                         const u8 *sa,
1592                                         const u8 *data, size_t len, int prot,
1593                                         int std_addr3)
1594 {
1595         const u8 *pos = data;
1596         const u8 *end = data + len;
1597         const u8 *next;
1598         u8 dialog_token;
1599         u16 slen;
1600         struct anqp_query_info qi;
1601         const u8 *adv_proto;
1602 #ifdef CONFIG_DPP
1603         int dpp = 0;
1604 #endif /* CONFIG_DPP */
1605
1606         if (len < 1 + 2)
1607                 return;
1608
1609         os_memset(&qi, 0, sizeof(qi));
1610
1611         dialog_token = *pos++;
1612         wpa_msg(hapd->msg_ctx, MSG_DEBUG,
1613                 "GAS: GAS Initial Request from " MACSTR " (dialog token %u) ",
1614                 MAC2STR(sa), dialog_token);
1615
1616         if (*pos != WLAN_EID_ADV_PROTO) {
1617                 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
1618                         "GAS: Unexpected IE in GAS Initial Request: %u", *pos);
1619                 return;
1620         }
1621         adv_proto = pos++;
1622
1623         slen = *pos++;
1624         if (slen > end - pos || slen < 2) {
1625                 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
1626                         "GAS: Invalid IE in GAS Initial Request");
1627                 return;
1628         }
1629         next = pos + slen;
1630         pos++; /* skip QueryRespLenLimit and PAME-BI */
1631
1632 #ifdef CONFIG_DPP
1633         if (slen == 8 && *pos == WLAN_EID_VENDOR_SPECIFIC &&
1634             pos[1] == 5 && WPA_GET_BE24(&pos[2]) == OUI_WFA &&
1635             pos[5] == DPP_OUI_TYPE && pos[6] == 0x01) {
1636                 wpa_printf(MSG_DEBUG, "DPP: Configuration Request");
1637                 dpp = 1;
1638         } else
1639 #endif /* CONFIG_DPP */
1640
1641         if (*pos != ACCESS_NETWORK_QUERY_PROTOCOL) {
1642                 struct wpabuf *buf;
1643                 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
1644                         "GAS: Unsupported GAS advertisement protocol id %u",
1645                         *pos);
1646                 if (sa[0] & 0x01)
1647                         return; /* Invalid source address - drop silently */
1648                 buf = gas_build_initial_resp(
1649                         dialog_token, WLAN_STATUS_GAS_ADV_PROTO_NOT_SUPPORTED,
1650                         0, 2 + slen + 2);
1651                 if (buf == NULL)
1652                         return;
1653                 wpabuf_put_data(buf, adv_proto, 2 + slen);
1654                 wpabuf_put_le16(buf, 0); /* Query Response Length */
1655                 if (prot)
1656                         convert_to_protected_dual(buf);
1657                 if (std_addr3)
1658                         hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
1659                                                 wpabuf_head(buf),
1660                                                 wpabuf_len(buf));
1661                 else
1662                         hostapd_drv_send_action_addr3_ap(hapd,
1663                                                          hapd->iface->freq, 0,
1664                                                          sa, wpabuf_head(buf),
1665                                                          wpabuf_len(buf));
1666                 wpabuf_free(buf);
1667                 return;
1668         }
1669
1670         pos = next;
1671         /* Query Request */
1672         if (end - pos < 2)
1673                 return;
1674         slen = WPA_GET_LE16(pos);
1675         pos += 2;
1676         if (slen > end - pos)
1677                 return;
1678         end = pos + slen;
1679
1680 #ifdef CONFIG_DPP
1681         if (dpp) {
1682                 struct wpabuf *msg;
1683
1684                 msg = hostapd_dpp_gas_req_handler(hapd, sa, pos, slen,
1685                                                   data, len);
1686                 if (!msg)
1687                         return;
1688                 gas_serv_req_dpp_processing(hapd, sa, dialog_token, prot, msg);
1689                 return;
1690         }
1691 #endif /* CONFIG_DPP */
1692
1693         /* ANQP Query Request */
1694         while (pos < end) {
1695                 u16 info_id, elen;
1696
1697                 if (end - pos < 4)
1698                         return;
1699
1700                 info_id = WPA_GET_LE16(pos);
1701                 pos += 2;
1702                 elen = WPA_GET_LE16(pos);
1703                 pos += 2;
1704
1705                 if (elen > end - pos) {
1706                         wpa_printf(MSG_DEBUG, "ANQP: Invalid Query Request");
1707                         return;
1708                 }
1709
1710                 switch (info_id) {
1711                 case ANQP_QUERY_LIST:
1712                         rx_anqp_query_list(hapd, pos, pos + elen, &qi);
1713                         break;
1714                 case ANQP_VENDOR_SPECIFIC:
1715                         rx_anqp_vendor_specific(hapd, pos, pos + elen, &qi);
1716                         break;
1717                 default:
1718                         wpa_printf(MSG_DEBUG, "ANQP: Unsupported Query "
1719                                    "Request element %u", info_id);
1720                         break;
1721                 }
1722
1723                 pos += elen;
1724         }
1725
1726         gas_serv_req_local_processing(hapd, sa, dialog_token, &qi, prot,
1727                                       std_addr3);
1728 }
1729
1730
1731 static void gas_serv_rx_gas_comeback_req(struct hostapd_data *hapd,
1732                                          const u8 *sa,
1733                                          const u8 *data, size_t len, int prot,
1734                                          int std_addr3)
1735 {
1736         struct gas_dialog_info *dialog;
1737         struct wpabuf *buf, *tx_buf;
1738         u8 dialog_token;
1739         size_t frag_len;
1740         int more = 0;
1741
1742         wpa_hexdump(MSG_DEBUG, "GAS: RX GAS Comeback Request", data, len);
1743         if (len < 1)
1744                 return;
1745         dialog_token = *data;
1746         wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Dialog Token: %u",
1747                 dialog_token);
1748
1749         dialog = gas_serv_dialog_find(hapd, sa, dialog_token);
1750         if (!dialog) {
1751                 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: No pending SD "
1752                         "response fragment for " MACSTR " dialog token %u",
1753                         MAC2STR(sa), dialog_token);
1754
1755                 if (sa[0] & 0x01)
1756                         return; /* Invalid source address - drop silently */
1757                 tx_buf = gas_anqp_build_comeback_resp_buf(
1758                         dialog_token, WLAN_STATUS_NO_OUTSTANDING_GAS_REQ, 0, 0,
1759                         0, NULL);
1760                 if (tx_buf == NULL)
1761                         return;
1762                 goto send_resp;
1763         }
1764
1765         frag_len = wpabuf_len(dialog->sd_resp) - dialog->sd_resp_pos;
1766         if (frag_len > hapd->conf->gas_frag_limit) {
1767                 frag_len = hapd->conf->gas_frag_limit;
1768                 more = 1;
1769         }
1770         wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: resp frag_len %u",
1771                 (unsigned int) frag_len);
1772         buf = wpabuf_alloc_copy(wpabuf_head_u8(dialog->sd_resp) +
1773                                 dialog->sd_resp_pos, frag_len);
1774         if (buf == NULL) {
1775                 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Failed to allocate "
1776                         "buffer");
1777                 gas_serv_dialog_clear(dialog);
1778                 return;
1779         }
1780 #ifdef CONFIG_DPP
1781         if (dialog->dpp) {
1782                 tx_buf = gas_build_comeback_resp(dialog_token,
1783                                                  WLAN_STATUS_SUCCESS,
1784                                                  dialog->sd_frag_id, more, 0,
1785                                                  10 + frag_len);
1786                 if (tx_buf) {
1787                         gas_serv_write_dpp_adv_proto(tx_buf);
1788                         wpabuf_put_buf(tx_buf, buf);
1789                 }
1790         } else
1791 #endif /* CONFIG_DPP */
1792         tx_buf = gas_anqp_build_comeback_resp_buf(dialog_token,
1793                                                   WLAN_STATUS_SUCCESS,
1794                                                   dialog->sd_frag_id,
1795                                                   more, 0, buf);
1796         wpabuf_free(buf);
1797         if (tx_buf == NULL) {
1798                 gas_serv_dialog_clear(dialog);
1799                 return;
1800         }
1801         wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Tx GAS Comeback Response "
1802                 "(frag_id %d more=%d frag_len=%d)",
1803                 dialog->sd_frag_id, more, (int) frag_len);
1804         dialog->sd_frag_id++;
1805         dialog->sd_resp_pos += frag_len;
1806
1807         if (more) {
1808                 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: %d more bytes remain "
1809                         "to be sent",
1810                         (int) (wpabuf_len(dialog->sd_resp) -
1811                                dialog->sd_resp_pos));
1812         } else {
1813                 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: All fragments of "
1814                         "SD response sent");
1815 #ifdef CONFIG_DPP
1816                 if (dialog->dpp)
1817                         hostapd_dpp_gas_status_handler(hapd, 1);
1818 #endif /* CONFIG_DPP */
1819                 gas_serv_dialog_clear(dialog);
1820                 gas_serv_free_dialogs(hapd, sa);
1821         }
1822
1823 send_resp:
1824         if (prot)
1825                 convert_to_protected_dual(tx_buf);
1826         if (std_addr3)
1827                 hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
1828                                         wpabuf_head(tx_buf),
1829                                         wpabuf_len(tx_buf));
1830         else
1831                 hostapd_drv_send_action_addr3_ap(hapd, hapd->iface->freq, 0, sa,
1832                                                  wpabuf_head(tx_buf),
1833                                                  wpabuf_len(tx_buf));
1834         wpabuf_free(tx_buf);
1835 }
1836
1837
1838 static void gas_serv_rx_public_action(void *ctx, const u8 *buf, size_t len,
1839                                       int freq)
1840 {
1841         struct hostapd_data *hapd = ctx;
1842         const struct ieee80211_mgmt *mgmt;
1843         const u8 *sa, *data;
1844         int prot, std_addr3;
1845
1846         mgmt = (const struct ieee80211_mgmt *) buf;
1847         if (len < IEEE80211_HDRLEN + 2)
1848                 return;
1849         if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
1850             mgmt->u.action.category != WLAN_ACTION_PROTECTED_DUAL)
1851                 return;
1852         /*
1853          * Note: Public Action and Protected Dual of Public Action frames share
1854          * the same payload structure, so it is fine to use definitions of
1855          * Public Action frames to process both.
1856          */
1857         prot = mgmt->u.action.category == WLAN_ACTION_PROTECTED_DUAL;
1858         sa = mgmt->sa;
1859         if (hapd->conf->gas_address3 == 1)
1860                 std_addr3 = 1;
1861         else if (hapd->conf->gas_address3 == 2)
1862                 std_addr3 = 0;
1863         else
1864                 std_addr3 = is_broadcast_ether_addr(mgmt->bssid);
1865         len -= IEEE80211_HDRLEN + 1;
1866         data = buf + IEEE80211_HDRLEN + 1;
1867         switch (data[0]) {
1868         case WLAN_PA_GAS_INITIAL_REQ:
1869                 gas_serv_rx_gas_initial_req(hapd, sa, data + 1, len - 1, prot,
1870                                             std_addr3);
1871                 break;
1872         case WLAN_PA_GAS_COMEBACK_REQ:
1873                 gas_serv_rx_gas_comeback_req(hapd, sa, data + 1, len - 1, prot,
1874                                              std_addr3);
1875                 break;
1876         }
1877 }
1878
1879
1880 int gas_serv_init(struct hostapd_data *hapd)
1881 {
1882         hapd->public_action_cb2 = gas_serv_rx_public_action;
1883         hapd->public_action_cb2_ctx = hapd;
1884         return 0;
1885 }
1886
1887
1888 void gas_serv_deinit(struct hostapd_data *hapd)
1889 {
1890 }