1 /*
2  * Generic advertisement service (GAS) server
3  * Copyright (c) 2011-2014, Qualcomm Atheros, Inc.
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "includes.h"
10 
11 #include "common.h"
12 #include "common/ieee802_11_defs.h"
13 #include "common/gas.h"
14 #include "common/wpa_ctrl.h"
15 #include "utils/eloop.h"
16 #include "hostapd.h"
17 #include "ap_config.h"
18 #include "ap_drv_ops.h"
19 #include "dpp_hostapd.h"
20 #include "sta_info.h"
21 #include "gas_serv.h"
22 
23 
24 #ifdef CONFIG_DPP
gas_serv_write_dpp_adv_proto(struct wpabuf * buf)25 static void gas_serv_write_dpp_adv_proto(struct wpabuf *buf)
26 {
27           wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO);
28           wpabuf_put_u8(buf, 8); /* Length */
29           wpabuf_put_u8(buf, 0x7f);
30           wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
31           wpabuf_put_u8(buf, 5);
32           wpabuf_put_be24(buf, OUI_WFA);
33           wpabuf_put_u8(buf, DPP_OUI_TYPE);
34           wpabuf_put_u8(buf, 0x01);
35 }
36 #endif /* CONFIG_DPP */
37 
38 
convert_to_protected_dual(struct wpabuf * msg)39 static void convert_to_protected_dual(struct wpabuf *msg)
40 {
41           u8 *categ = wpabuf_mhead_u8(msg);
42           *categ = WLAN_ACTION_PROTECTED_DUAL;
43 }
44 
45 
46 static struct gas_dialog_info *
gas_dialog_create(struct hostapd_data * hapd,const u8 * addr,u8 dialog_token)47 gas_dialog_create(struct hostapd_data *hapd, const u8 *addr, u8 dialog_token)
48 {
49           struct sta_info *sta;
50           struct gas_dialog_info *dia = NULL;
51           int i, j;
52 
53           sta = ap_get_sta(hapd, addr);
54           if (!sta) {
55                     /*
56                      * We need a STA entry to be able to maintain state for
57                      * the GAS query.
58                      */
59                     wpa_printf(MSG_DEBUG, "ANQP: Add a temporary STA entry for "
60                                  "GAS query");
61                     sta = ap_sta_add(hapd, addr);
62                     if (!sta) {
63                               wpa_printf(MSG_DEBUG, "Failed to add STA " MACSTR
64                                            " for GAS query", MAC2STR(addr));
65                               return NULL;
66                     }
67                     sta->flags |= WLAN_STA_GAS;
68                     /*
69                      * The default inactivity is 300 seconds. We don't need
70                      * it to be that long. Use five second timeout and increase this
71                      * with the comeback_delay for testing cases.
72                      */
73                     ap_sta_session_timeout(hapd, sta,
74                                                hapd->conf->gas_comeback_delay / 1024 +
75                                                5);
76           } else {
77                     ap_sta_replenish_timeout(hapd, sta, 5);
78           }
79 
80           if (sta->gas_dialog == NULL) {
81                     sta->gas_dialog = os_calloc(GAS_DIALOG_MAX,
82                                                       sizeof(struct gas_dialog_info));
83                     if (sta->gas_dialog == NULL)
84                               return NULL;
85           }
86 
87           for (i = sta->gas_dialog_next, j = 0; j < GAS_DIALOG_MAX; i++, j++) {
88                     if (i == GAS_DIALOG_MAX)
89                               i = 0;
90                     if (sta->gas_dialog[i].valid)
91                               continue;
92                     dia = &sta->gas_dialog[i];
93                     dia->valid = 1;
94                     dia->dialog_token = dialog_token;
95                     sta->gas_dialog_next = (++i == GAS_DIALOG_MAX) ? 0 : i;
96                     return dia;
97           }
98 
99           wpa_msg(hapd->msg_ctx, MSG_ERROR, "ANQP: Could not create dialog for "
100                     MACSTR " dialog_token %u. Consider increasing "
101                     "GAS_DIALOG_MAX.", MAC2STR(addr), dialog_token);
102 
103           return NULL;
104 }
105 
106 
107 struct gas_dialog_info *
gas_serv_dialog_find(struct hostapd_data * hapd,const u8 * addr,u8 dialog_token)108 gas_serv_dialog_find(struct hostapd_data *hapd, const u8 *addr,
109                          u8 dialog_token)
110 {
111           struct sta_info *sta;
112           int i;
113 
114           sta = ap_get_sta(hapd, addr);
115           if (!sta) {
116                     wpa_printf(MSG_DEBUG, "ANQP: could not find STA " MACSTR,
117                                  MAC2STR(addr));
118                     return NULL;
119           }
120           for (i = 0; sta->gas_dialog && i < GAS_DIALOG_MAX; i++) {
121                     if (sta->gas_dialog[i].dialog_token != dialog_token ||
122                         !sta->gas_dialog[i].valid)
123                               continue;
124                     ap_sta_replenish_timeout(hapd, sta, 5);
125                     return &sta->gas_dialog[i];
126           }
127           wpa_printf(MSG_DEBUG, "ANQP: Could not find dialog for "
128                        MACSTR " dialog_token %u", MAC2STR(addr), dialog_token);
129           return NULL;
130 }
131 
132 
gas_serv_dialog_clear(struct gas_dialog_info * dia)133 void gas_serv_dialog_clear(struct gas_dialog_info *dia)
134 {
135           wpabuf_free(dia->sd_resp);
136           os_memset(dia, 0, sizeof(*dia));
137 }
138 
139 
gas_serv_free_dialogs(struct hostapd_data * hapd,const u8 * sta_addr)140 static void gas_serv_free_dialogs(struct hostapd_data *hapd,
141                                           const u8 *sta_addr)
142 {
143           struct sta_info *sta;
144           int i;
145 
146           sta = ap_get_sta(hapd, sta_addr);
147           if (sta == NULL || sta->gas_dialog == NULL)
148                     return;
149 
150           for (i = 0; i < GAS_DIALOG_MAX; i++) {
151                     if (sta->gas_dialog[i].valid)
152                               return;
153           }
154 
155           os_free(sta->gas_dialog);
156           sta->gas_dialog = NULL;
157 }
158 
159 
160 #ifdef CONFIG_HS20
anqp_add_hs_capab_list(struct hostapd_data * hapd,struct wpabuf * buf)161 static void anqp_add_hs_capab_list(struct hostapd_data *hapd,
162                                            struct wpabuf *buf)
163 {
164           u8 *len;
165 
166           len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
167           wpabuf_put_be24(buf, OUI_WFA);
168           wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
169           wpabuf_put_u8(buf, HS20_STYPE_CAPABILITY_LIST);
170           wpabuf_put_u8(buf, 0); /* Reserved */
171           wpabuf_put_u8(buf, HS20_STYPE_CAPABILITY_LIST);
172           if (hapd->conf->hs20_oper_friendly_name)
173                     wpabuf_put_u8(buf, HS20_STYPE_OPERATOR_FRIENDLY_NAME);
174           if (hapd->conf->hs20_wan_metrics)
175                     wpabuf_put_u8(buf, HS20_STYPE_WAN_METRICS);
176           if (hapd->conf->hs20_connection_capability)
177                     wpabuf_put_u8(buf, HS20_STYPE_CONNECTION_CAPABILITY);
178           if (hapd->conf->nai_realm_data)
179                     wpabuf_put_u8(buf, HS20_STYPE_NAI_HOME_REALM_QUERY);
180           if (hapd->conf->hs20_operating_class)
181                     wpabuf_put_u8(buf, HS20_STYPE_OPERATING_CLASS);
182           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 
get_anqp_elem(struct hostapd_data * hapd,u16 infoid)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 
anqp_add_elem(struct hostapd_data * hapd,struct wpabuf * buf,u16 infoid)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 
anqp_add_override(struct hostapd_data * hapd,struct wpabuf * buf,u16 infoid)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 
anqp_add_capab_list(struct hostapd_data * hapd,struct wpabuf * buf)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 
anqp_add_venue_name(struct hostapd_data * hapd,struct wpabuf * buf)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 
anqp_add_venue_url(struct hostapd_data * hapd,struct wpabuf * buf)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 
anqp_add_network_auth_type(struct hostapd_data * hapd,struct wpabuf * buf)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 
anqp_add_roaming_consortium(struct hostapd_data * hapd,struct wpabuf * buf)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 
anqp_add_ip_addr_type_availability(struct hostapd_data * hapd,struct wpabuf * buf)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 
anqp_add_nai_realm_eap(struct wpabuf * buf,struct hostapd_nai_realm_data * realm)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 
anqp_add_nai_realm_data(struct wpabuf * buf,struct hostapd_nai_realm_data * realm,unsigned int realm_idx)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 
hs20_add_nai_home_realm_matches(struct hostapd_data * hapd,struct wpabuf * buf,const u8 * home_realm,size_t home_realm_len)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 
anqp_add_nai_realm(struct hostapd_data * hapd,struct wpabuf * buf,const u8 * home_realm,size_t home_realm_len,int nai_realm,int nai_home_realm)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 
anqp_add_3gpp_cellular_network(struct hostapd_data * hapd,struct wpabuf * buf)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 
anqp_add_domain_name(struct hostapd_data * hapd,struct wpabuf * buf)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
anqp_add_fils_realm_info(struct hostapd_data * hapd,struct wpabuf * buf)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 
anqp_add_operator_friendly_name(struct hostapd_data * hapd,struct wpabuf * buf)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 
anqp_add_wan_metrics(struct hostapd_data * hapd,struct wpabuf * buf)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 
anqp_add_connection_capability(struct hostapd_data * hapd,struct wpabuf * buf)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 
anqp_add_operating_class(struct hostapd_data * hapd,struct wpabuf * buf)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 
anqp_add_icon(struct wpabuf * buf,struct hostapd_bss_config * bss,const char * name)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 
anqp_add_osu_provider(struct wpabuf * buf,struct hostapd_bss_config * bss,struct hs20_osu_provider * p)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 
anqp_add_osu_providers_list(struct hostapd_data * hapd,struct wpabuf * buf)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 
anqp_add_osu_provider_nai(struct wpabuf * buf,struct hs20_osu_provider * p)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 
anqp_add_osu_providers_nai_list(struct hostapd_data * hapd,struct wpabuf * buf)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 
anqp_add_icon_binary_file(struct hostapd_data * hapd,struct wpabuf * buf,const u8 * name,size_t name_len)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 
anqp_add_operator_icon_metadata(struct hostapd_data * hapd,struct wpabuf * buf)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
anqp_add_mbo_cell_data_conn_pref(struct hostapd_data * hapd,struct wpabuf * buf)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 
anqp_get_required_len(struct hostapd_data * hapd,const u16 * infoid,unsigned int num_infoid)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 *
gas_serv_build_gas_resp_payload(struct hostapd_data * hapd,unsigned int request,const u8 * home_realm,size_t home_realm_len,const u8 * icon_name,size_t icon_name_len,const u16 * extra_req,unsigned int num_extra_req)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 
set_anqp_req(unsigned int bit,const char * name,int local,struct anqp_query_info * qi)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 
rx_anqp_query_list_id(struct hostapd_data * hapd,u16 info_id,struct anqp_query_info * qi)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 
rx_anqp_query_list(struct hostapd_data * hapd,const u8 * pos,const u8 * end,struct anqp_query_info * qi)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 
rx_anqp_hs_query_list(struct hostapd_data * hapd,u8 subtype,struct anqp_query_info * qi)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 
rx_anqp_hs_nai_home_realm(struct hostapd_data * hapd,const u8 * pos,const u8 * end,struct anqp_query_info * qi)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 
rx_anqp_hs_icon_request(struct hostapd_data * hapd,const u8 * pos,const u8 * end,struct anqp_query_info * qi)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 
rx_anqp_vendor_specific_hs20(struct hostapd_data * hapd,const u8 * pos,const u8 * end,struct anqp_query_info * qi)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
rx_anqp_vendor_specific_p2p(struct hostapd_data * hapd,struct anqp_query_info * qi)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 
rx_anqp_mbo_query_list(struct hostapd_data * hapd,u8 subtype,struct anqp_query_info * qi)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 
rx_anqp_vendor_specific_mbo(struct hostapd_data * hapd,const u8 * pos,const u8 * end,struct anqp_query_info * qi)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 
rx_anqp_vendor_specific(struct hostapd_data * hapd,const u8 * pos,const u8 * end,struct anqp_query_info * qi)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 
gas_serv_req_local_processing(struct hostapd_data * hapd,const u8 * sa,u8 dialog_token,struct anqp_query_info * qi,int prot,int std_addr3)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
gas_serv_req_dpp_processing(struct hostapd_data * hapd,const u8 * sa,u8 dialog_token,int prot,struct wpabuf * buf,int freq)1525 void gas_serv_req_dpp_processing(struct hostapd_data *hapd,
1526                                          const u8 *sa, u8 dialog_token,
1527                                          int prot, struct wpabuf *buf, int freq)
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                               di->dpp = 1;
1559                               tx_buf = gas_build_initial_resp(
1560                                         dialog_token, WLAN_STATUS_SUCCESS,
1561                                         comeback_delay, 10 + 2);
1562                               if (tx_buf) {
1563                                         gas_serv_write_dpp_adv_proto(tx_buf);
1564                                         wpabuf_put_le16(tx_buf, 0);
1565                               }
1566                     }
1567           } else {
1568                     wpa_printf(MSG_DEBUG,
1569                                  "DPP: GAS Initial response (no comeback)");
1570                     tx_buf = gas_build_initial_resp(
1571                               dialog_token, WLAN_STATUS_SUCCESS, 0,
1572                               10 + 2 + wpabuf_len(buf));
1573                     if (tx_buf) {
1574                               gas_serv_write_dpp_adv_proto(tx_buf);
1575                               wpabuf_put_le16(tx_buf, wpabuf_len(buf));
1576                               wpabuf_put_buf(tx_buf, buf);
1577                               hostapd_dpp_gas_status_handler(hapd, 1);
1578                     }
1579                     wpabuf_free(buf);
1580           }
1581           if (!tx_buf)
1582                     return;
1583           if (prot)
1584                     convert_to_protected_dual(tx_buf);
1585           hostapd_drv_send_action(hapd, freq ? freq : hapd->iface->freq, 0, sa,
1586                                         wpabuf_head(tx_buf),
1587                                         wpabuf_len(tx_buf));
1588           wpabuf_free(tx_buf);
1589 }
1590 #endif /* CONFIG_DPP */
1591 
1592 
gas_serv_rx_gas_initial_req(struct hostapd_data * hapd,const u8 * sa,const u8 * data,size_t len,int prot,int std_addr3,int freq)1593 static void gas_serv_rx_gas_initial_req(struct hostapd_data *hapd,
1594                                                   const u8 *sa,
1595                                                   const u8 *data, size_t len, int prot,
1596                                                   int std_addr3, int freq)
1597 {
1598           const u8 *pos = data;
1599           const u8 *end = data + len;
1600           const u8 *next;
1601           u8 dialog_token;
1602           u16 slen;
1603           struct anqp_query_info qi;
1604           const u8 *adv_proto;
1605 #ifdef CONFIG_DPP
1606           int dpp = 0;
1607 #endif /* CONFIG_DPP */
1608 
1609           if (len < 1 + 2)
1610                     return;
1611 
1612           os_memset(&qi, 0, sizeof(qi));
1613 
1614           dialog_token = *pos++;
1615           wpa_msg(hapd->msg_ctx, MSG_DEBUG,
1616                     "GAS: GAS Initial Request from " MACSTR " (dialog token %u) ",
1617                     MAC2STR(sa), dialog_token);
1618 
1619           if (*pos != WLAN_EID_ADV_PROTO) {
1620                     wpa_msg(hapd->msg_ctx, MSG_DEBUG,
1621                               "GAS: Unexpected IE in GAS Initial Request: %u", *pos);
1622                     return;
1623           }
1624           adv_proto = pos++;
1625 
1626           slen = *pos++;
1627           if (slen > end - pos || slen < 2) {
1628                     wpa_msg(hapd->msg_ctx, MSG_DEBUG,
1629                               "GAS: Invalid IE in GAS Initial Request");
1630                     return;
1631           }
1632           next = pos + slen;
1633           pos++; /* skip QueryRespLenLimit and PAME-BI */
1634 
1635 #ifdef CONFIG_DPP
1636           if (slen == 8 && *pos == WLAN_EID_VENDOR_SPECIFIC &&
1637               pos[1] == 5 && WPA_GET_BE24(&pos[2]) == OUI_WFA &&
1638               pos[5] == DPP_OUI_TYPE && pos[6] == 0x01) {
1639                     wpa_printf(MSG_DEBUG, "DPP: Configuration Request");
1640                     dpp = 1;
1641           } else
1642 #endif /* CONFIG_DPP */
1643 
1644           if (*pos != ACCESS_NETWORK_QUERY_PROTOCOL) {
1645                     struct wpabuf *buf;
1646                     wpa_msg(hapd->msg_ctx, MSG_DEBUG,
1647                               "GAS: Unsupported GAS advertisement protocol id %u",
1648                               *pos);
1649                     if (sa[0] & 0x01)
1650                               return; /* Invalid source address - drop silently */
1651                     buf = gas_build_initial_resp(
1652                               dialog_token, WLAN_STATUS_GAS_ADV_PROTO_NOT_SUPPORTED,
1653                               0, 2 + slen + 2);
1654                     if (buf == NULL)
1655                               return;
1656                     wpabuf_put_data(buf, adv_proto, 2 + slen);
1657                     wpabuf_put_le16(buf, 0); /* Query Response Length */
1658                     if (prot)
1659                               convert_to_protected_dual(buf);
1660                     if (std_addr3)
1661                               hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
1662                                                             wpabuf_head(buf),
1663                                                             wpabuf_len(buf));
1664                     else
1665                               hostapd_drv_send_action_addr3_ap(hapd,
1666                                                                        hapd->iface->freq, 0,
1667                                                                        sa, wpabuf_head(buf),
1668                                                                        wpabuf_len(buf));
1669                     wpabuf_free(buf);
1670                     return;
1671           }
1672 
1673           pos = next;
1674           /* Query Request */
1675           if (end - pos < 2)
1676                     return;
1677           slen = WPA_GET_LE16(pos);
1678           pos += 2;
1679           if (slen > end - pos)
1680                     return;
1681           end = pos + slen;
1682 
1683 #ifdef CONFIG_DPP
1684           if (dpp) {
1685                     struct wpabuf *msg;
1686 
1687                     msg = hostapd_dpp_gas_req_handler(hapd, sa, pos, slen,
1688                                                               data, len);
1689                     if (!msg)
1690                               return;
1691                     gas_serv_req_dpp_processing(hapd, sa, dialog_token, prot, msg,
1692                                                       freq);
1693                     return;
1694           }
1695 #endif /* CONFIG_DPP */
1696 
1697           /* ANQP Query Request */
1698           while (pos < end) {
1699                     u16 info_id, elen;
1700 
1701                     if (end - pos < 4)
1702                               return;
1703 
1704                     info_id = WPA_GET_LE16(pos);
1705                     pos += 2;
1706                     elen = WPA_GET_LE16(pos);
1707                     pos += 2;
1708 
1709                     if (elen > end - pos) {
1710                               wpa_printf(MSG_DEBUG, "ANQP: Invalid Query Request");
1711                               return;
1712                     }
1713 
1714                     switch (info_id) {
1715                     case ANQP_QUERY_LIST:
1716                               rx_anqp_query_list(hapd, pos, pos + elen, &qi);
1717                               break;
1718                     case ANQP_VENDOR_SPECIFIC:
1719                               rx_anqp_vendor_specific(hapd, pos, pos + elen, &qi);
1720                               break;
1721                     default:
1722                               wpa_printf(MSG_DEBUG, "ANQP: Unsupported Query "
1723                                            "Request element %u", info_id);
1724                               break;
1725                     }
1726 
1727                     pos += elen;
1728           }
1729 
1730           gas_serv_req_local_processing(hapd, sa, dialog_token, &qi, prot,
1731                                               std_addr3);
1732 }
1733 
1734 
gas_serv_rx_gas_comeback_req(struct hostapd_data * hapd,const u8 * sa,const u8 * data,size_t len,int prot,int std_addr3)1735 static void gas_serv_rx_gas_comeback_req(struct hostapd_data *hapd,
1736                                                    const u8 *sa,
1737                                                    const u8 *data, size_t len, int prot,
1738                                                    int std_addr3)
1739 {
1740           struct gas_dialog_info *dialog;
1741           struct wpabuf *buf, *tx_buf;
1742           u8 dialog_token;
1743           size_t frag_len;
1744           int more = 0;
1745 
1746           wpa_hexdump(MSG_DEBUG, "GAS: RX GAS Comeback Request", data, len);
1747           if (len < 1)
1748                     return;
1749           dialog_token = *data;
1750           wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Dialog Token: %u",
1751                     dialog_token);
1752 
1753           dialog = gas_serv_dialog_find(hapd, sa, dialog_token);
1754           if (!dialog) {
1755                     wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: No pending SD "
1756                               "response fragment for " MACSTR " dialog token %u",
1757                               MAC2STR(sa), dialog_token);
1758 
1759                     if (sa[0] & 0x01)
1760                               return; /* Invalid source address - drop silently */
1761                     tx_buf = gas_anqp_build_comeback_resp_buf(
1762                               dialog_token, WLAN_STATUS_NO_OUTSTANDING_GAS_REQ, 0, 0,
1763                               0, NULL);
1764                     if (tx_buf == NULL)
1765                               return;
1766                     goto send_resp;
1767           }
1768 
1769           frag_len = wpabuf_len(dialog->sd_resp) - dialog->sd_resp_pos;
1770           if (frag_len > hapd->conf->gas_frag_limit) {
1771                     frag_len = hapd->conf->gas_frag_limit;
1772                     more = 1;
1773           }
1774           wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: resp frag_len %u",
1775                     (unsigned int) frag_len);
1776           buf = wpabuf_alloc_copy(wpabuf_head_u8(dialog->sd_resp) +
1777                                         dialog->sd_resp_pos, frag_len);
1778           if (buf == NULL) {
1779                     wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Failed to allocate "
1780                               "buffer");
1781                     gas_serv_dialog_clear(dialog);
1782                     return;
1783           }
1784 #ifdef CONFIG_DPP
1785           if (dialog->dpp) {
1786                     tx_buf = gas_build_comeback_resp(dialog_token,
1787                                                              WLAN_STATUS_SUCCESS,
1788                                                              dialog->sd_frag_id, more, 0,
1789                                                              10 + 2 + frag_len);
1790                     if (tx_buf) {
1791                               gas_serv_write_dpp_adv_proto(tx_buf);
1792                               wpabuf_put_le16(tx_buf, frag_len);
1793                               wpabuf_put_buf(tx_buf, buf);
1794                     }
1795           } else
1796 #endif /* CONFIG_DPP */
1797           tx_buf = gas_anqp_build_comeback_resp_buf(dialog_token,
1798                                                               WLAN_STATUS_SUCCESS,
1799                                                               dialog->sd_frag_id,
1800                                                               more, 0, buf);
1801           wpabuf_free(buf);
1802           if (tx_buf == NULL) {
1803                     gas_serv_dialog_clear(dialog);
1804                     return;
1805           }
1806           wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Tx GAS Comeback Response "
1807                     "(frag_id %d more=%d frag_len=%d)",
1808                     dialog->sd_frag_id, more, (int) frag_len);
1809           dialog->sd_frag_id++;
1810           dialog->sd_resp_pos += frag_len;
1811 
1812           if (more) {
1813                     wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: %d more bytes remain "
1814                               "to be sent",
1815                               (int) (wpabuf_len(dialog->sd_resp) -
1816                                      dialog->sd_resp_pos));
1817           } else {
1818                     wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: All fragments of "
1819                               "SD response sent");
1820 #ifdef CONFIG_DPP
1821                     if (dialog->dpp)
1822                               hostapd_dpp_gas_status_handler(hapd, 1);
1823 #endif /* CONFIG_DPP */
1824                     gas_serv_dialog_clear(dialog);
1825                     gas_serv_free_dialogs(hapd, sa);
1826           }
1827 
1828 send_resp:
1829           if (prot)
1830                     convert_to_protected_dual(tx_buf);
1831           if (std_addr3)
1832                     hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
1833                                                   wpabuf_head(tx_buf),
1834                                                   wpabuf_len(tx_buf));
1835           else
1836                     hostapd_drv_send_action_addr3_ap(hapd, hapd->iface->freq, 0, sa,
1837                                                              wpabuf_head(tx_buf),
1838                                                              wpabuf_len(tx_buf));
1839           wpabuf_free(tx_buf);
1840 }
1841 
1842 
gas_serv_rx_public_action(void * ctx,const u8 * buf,size_t len,int freq)1843 static void gas_serv_rx_public_action(void *ctx, const u8 *buf, size_t len,
1844                                               int freq)
1845 {
1846           struct hostapd_data *hapd = ctx;
1847           const struct ieee80211_mgmt *mgmt;
1848           const u8 *sa, *data;
1849           int prot, std_addr3;
1850 
1851           mgmt = (const struct ieee80211_mgmt *) buf;
1852           if (len < IEEE80211_HDRLEN + 2)
1853                     return;
1854           if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
1855               mgmt->u.action.category != WLAN_ACTION_PROTECTED_DUAL)
1856                     return;
1857           /*
1858            * Note: Public Action and Protected Dual of Public Action frames share
1859            * the same payload structure, so it is fine to use definitions of
1860            * Public Action frames to process both.
1861            */
1862           prot = mgmt->u.action.category == WLAN_ACTION_PROTECTED_DUAL;
1863           sa = mgmt->sa;
1864           if (hapd->conf->gas_address3 == 1)
1865                     std_addr3 = 1;
1866           else if (hapd->conf->gas_address3 == 2)
1867                     std_addr3 = 0;
1868           else
1869                     std_addr3 = is_broadcast_ether_addr(mgmt->bssid);
1870           len -= IEEE80211_HDRLEN + 1;
1871           data = buf + IEEE80211_HDRLEN + 1;
1872           switch (data[0]) {
1873           case WLAN_PA_GAS_INITIAL_REQ:
1874                     gas_serv_rx_gas_initial_req(hapd, sa, data + 1, len - 1, prot,
1875                                                       std_addr3, freq);
1876                     break;
1877           case WLAN_PA_GAS_COMEBACK_REQ:
1878                     gas_serv_rx_gas_comeback_req(hapd, sa, data + 1, len - 1, prot,
1879                                                        std_addr3);
1880                     break;
1881           }
1882 }
1883 
1884 
gas_serv_init(struct hostapd_data * hapd)1885 int gas_serv_init(struct hostapd_data *hapd)
1886 {
1887           hapd->public_action_cb2 = gas_serv_rx_public_action;
1888           hapd->public_action_cb2_ctx = hapd;
1889           return 0;
1890 }
1891 
1892 
gas_serv_deinit(struct hostapd_data * hapd)1893 void gas_serv_deinit(struct hostapd_data *hapd)
1894 {
1895 }
1896