LCOV - code coverage report
Current view: top level - wpa_supplicant - hs20_supplicant.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1393793999 Lines: 401 513 78.2 %
Date: 2014-03-02 Functions: 21 23 91.3 %
Branches: 148 248 59.7 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2009, Atheros Communications, Inc.
       3                 :            :  * Copyright (c) 2011-2013, 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 "eloop.h"
      13                 :            : #include "common/ieee802_11_common.h"
      14                 :            : #include "common/ieee802_11_defs.h"
      15                 :            : #include "common/gas.h"
      16                 :            : #include "common/wpa_ctrl.h"
      17                 :            : #include "rsn_supp/wpa.h"
      18                 :            : #include "wpa_supplicant_i.h"
      19                 :            : #include "driver_i.h"
      20                 :            : #include "config.h"
      21                 :            : #include "scan.h"
      22                 :            : #include "bss.h"
      23                 :            : #include "blacklist.h"
      24                 :            : #include "gas_query.h"
      25                 :            : #include "interworking.h"
      26                 :            : #include "hs20_supplicant.h"
      27                 :            : 
      28                 :            : 
      29                 :            : #define OSU_MAX_ITEMS 10
      30                 :            : 
      31                 :            : struct osu_lang_string {
      32                 :            :         char lang[4];
      33                 :            :         char text[253];
      34                 :            : };
      35                 :            : 
      36                 :            : struct osu_icon {
      37                 :            :         u16 width;
      38                 :            :         u16 height;
      39                 :            :         char lang[4];
      40                 :            :         char icon_type[256];
      41                 :            :         char filename[256];
      42                 :            :         unsigned int id;
      43                 :            :         unsigned int failed:1;
      44                 :            : };
      45                 :            : 
      46                 :            : struct osu_provider {
      47                 :            :         u8 bssid[ETH_ALEN];
      48                 :            :         u8 osu_ssid[32];
      49                 :            :         u8 osu_ssid_len;
      50                 :            :         char server_uri[256];
      51                 :            :         u32 osu_methods; /* bit 0 = OMA-DM, bit 1 = SOAP-XML SPP */
      52                 :            :         char osu_nai[256];
      53                 :            :         struct osu_lang_string friendly_name[OSU_MAX_ITEMS];
      54                 :            :         size_t friendly_name_count;
      55                 :            :         struct osu_lang_string serv_desc[OSU_MAX_ITEMS];
      56                 :            :         size_t serv_desc_count;
      57                 :            :         struct osu_icon icon[OSU_MAX_ITEMS];
      58                 :            :         size_t icon_count;
      59                 :            : };
      60                 :            : 
      61                 :            : 
      62                 :        350 : void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id)
      63                 :            : {
      64                 :            :         u8 conf;
      65                 :            : 
      66                 :        350 :         wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
      67         [ +  + ]:        350 :         wpabuf_put_u8(buf, pps_mo_id >= 0 ? 7 : 5);
      68                 :        350 :         wpabuf_put_be24(buf, OUI_WFA);
      69                 :        350 :         wpabuf_put_u8(buf, HS20_INDICATION_OUI_TYPE);
      70                 :        350 :         conf = HS20_VERSION;
      71         [ +  + ]:        350 :         if (pps_mo_id >= 0)
      72                 :         71 :                 conf |= HS20_PPS_MO_ID_PRESENT;
      73                 :        350 :         wpabuf_put_u8(buf, conf);
      74         [ +  + ]:        350 :         if (pps_mo_id >= 0)
      75                 :         71 :                 wpabuf_put_le16(buf, pps_mo_id);
      76                 :        350 : }
      77                 :            : 
      78                 :            : 
      79                 :        701 : int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
      80                 :            :                     struct wpa_bss *bss)
      81                 :            : {
      82 [ +  + ][ -  + ]:        701 :         if (!wpa_s->conf->hs20 || !ssid)
      83                 :        431 :                 return 0;
      84                 :            : 
      85         [ +  + ]:        270 :         if (ssid->parent_cred)
      86                 :         71 :                 return 1;
      87                 :            : 
      88 [ +  - ][ +  - ]:        199 :         if (bss && !wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE))
      89                 :        199 :                 return 0;
      90                 :            : 
      91                 :            :         /*
      92                 :            :          * This may catch some non-Hotspot 2.0 cases, but it is safer to do that
      93                 :            :          * than cause Hotspot 2.0 connections without indication element getting
      94                 :            :          * added. Non-Hotspot 2.0 APs should ignore the unknown vendor element.
      95                 :            :          */
      96                 :            : 
      97         [ #  # ]:          0 :         if (!(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X))
      98                 :          0 :                 return 0;
      99         [ #  # ]:          0 :         if (!(ssid->pairwise_cipher & WPA_CIPHER_CCMP))
     100                 :          0 :                 return 0;
     101         [ #  # ]:          0 :         if (ssid->proto != WPA_PROTO_RSN)
     102                 :          0 :                 return 0;
     103                 :            : 
     104                 :        701 :         return 1;
     105                 :            : }
     106                 :            : 
     107                 :            : 
     108                 :         71 : int hs20_get_pps_mo_id(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
     109                 :            : {
     110                 :            :         struct wpa_cred *cred;
     111                 :            : 
     112 [ +  - ][ -  + ]:         71 :         if (ssid == NULL || ssid->parent_cred == NULL)
     113                 :          0 :                 return 0;
     114                 :            : 
     115         [ +  - ]:         75 :         for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
     116         [ +  + ]:         75 :                 if (ssid->parent_cred == cred)
     117                 :         71 :                         return cred->update_identifier;
     118                 :            :         }
     119                 :            : 
     120                 :         71 :         return 0;
     121                 :            : }
     122                 :            : 
     123                 :            : 
     124                 :          3 : struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
     125                 :            :                                     size_t payload_len)
     126                 :            : {
     127                 :            :         struct wpabuf *buf;
     128                 :            :         u8 *len_pos;
     129                 :            : 
     130                 :          3 :         buf = gas_anqp_build_initial_req(0, 100 + payload_len);
     131         [ -  + ]:          3 :         if (buf == NULL)
     132                 :          0 :                 return NULL;
     133                 :            : 
     134                 :          3 :         len_pos = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
     135                 :          3 :         wpabuf_put_be24(buf, OUI_WFA);
     136                 :          3 :         wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
     137         [ +  + ]:          3 :         if (stypes == BIT(HS20_STYPE_NAI_HOME_REALM_QUERY)) {
     138                 :          1 :                 wpabuf_put_u8(buf, HS20_STYPE_NAI_HOME_REALM_QUERY);
     139                 :          1 :                 wpabuf_put_u8(buf, 0); /* Reserved */
     140         [ +  - ]:          1 :                 if (payload)
     141                 :          1 :                         wpabuf_put_data(buf, payload, payload_len);
     142         [ +  - ]:          2 :         } else if (stypes == BIT(HS20_STYPE_ICON_REQUEST)) {
     143                 :          2 :                 wpabuf_put_u8(buf, HS20_STYPE_ICON_REQUEST);
     144                 :          2 :                 wpabuf_put_u8(buf, 0); /* Reserved */
     145         [ +  - ]:          2 :                 if (payload)
     146                 :          2 :                         wpabuf_put_data(buf, payload, payload_len);
     147                 :            :         } else {
     148                 :            :                 u8 i;
     149                 :          0 :                 wpabuf_put_u8(buf, HS20_STYPE_QUERY_LIST);
     150                 :          0 :                 wpabuf_put_u8(buf, 0); /* Reserved */
     151         [ #  # ]:          0 :                 for (i = 0; i < 32; i++) {
     152         [ #  # ]:          0 :                         if (stypes & BIT(i))
     153                 :          0 :                                 wpabuf_put_u8(buf, i);
     154                 :            :                 }
     155                 :            :         }
     156                 :          3 :         gas_anqp_set_element_len(buf, len_pos);
     157                 :            : 
     158                 :          3 :         gas_anqp_set_len(buf);
     159                 :            : 
     160                 :          3 :         return buf;
     161                 :            : }
     162                 :            : 
     163                 :            : 
     164                 :          3 : int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes,
     165                 :            :                        const u8 *payload, size_t payload_len)
     166                 :            : {
     167                 :            :         struct wpabuf *buf;
     168                 :          3 :         int ret = 0;
     169                 :            :         int freq;
     170                 :            :         struct wpa_bss *bss;
     171                 :            :         int res;
     172                 :            : 
     173                 :          3 :         freq = wpa_s->assoc_freq;
     174                 :          3 :         bss = wpa_bss_get_bssid(wpa_s, dst);
     175         [ +  - ]:          3 :         if (bss) {
     176                 :          3 :                 wpa_bss_anqp_unshare_alloc(bss);
     177                 :          3 :                 freq = bss->freq;
     178                 :            :         }
     179         [ -  + ]:          3 :         if (freq <= 0)
     180                 :          0 :                 return -1;
     181                 :            : 
     182                 :          3 :         wpa_printf(MSG_DEBUG, "HS20: ANQP Query Request to " MACSTR " for "
     183                 :         18 :                    "subtypes 0x%x", MAC2STR(dst), stypes);
     184                 :            : 
     185                 :          3 :         buf = hs20_build_anqp_req(stypes, payload, payload_len);
     186         [ -  + ]:          3 :         if (buf == NULL)
     187                 :          0 :                 return -1;
     188                 :            : 
     189                 :          3 :         res = gas_query_req(wpa_s->gas, dst, freq, buf, anqp_resp_cb, wpa_s);
     190         [ -  + ]:          3 :         if (res < 0) {
     191                 :          0 :                 wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request");
     192                 :          0 :                 wpabuf_free(buf);
     193                 :          0 :                 ret = -1;
     194                 :            :         } else
     195                 :          3 :                 wpa_printf(MSG_DEBUG, "ANQP: Query started with dialog token "
     196                 :            :                            "%u", res);
     197                 :            : 
     198                 :          3 :         return ret;
     199                 :            : }
     200                 :            : 
     201                 :            : 
     202                 :          2 : static int hs20_process_icon_binary_file(struct wpa_supplicant *wpa_s,
     203                 :            :                                          const u8 *sa, const u8 *pos,
     204                 :            :                                          size_t slen)
     205                 :            : {
     206                 :            :         char fname[256];
     207                 :            :         int png;
     208                 :            :         FILE *f;
     209                 :            :         u16 data_len;
     210                 :            : 
     211                 :          2 :         wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR " Icon Binary File",
     212                 :         12 :                 MAC2STR(sa));
     213                 :            : 
     214         [ -  + ]:          2 :         if (slen < 4) {
     215                 :          0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: Too short Icon Binary File "
     216                 :            :                         "value from " MACSTR, MAC2STR(sa));
     217                 :          0 :                 return -1;
     218                 :            :         }
     219                 :            : 
     220                 :          2 :         wpa_printf(MSG_DEBUG, "HS 2.0: Download Status Code %u", *pos);
     221         [ -  + ]:          2 :         if (*pos != 0)
     222                 :          0 :                 return -1;
     223                 :          2 :         pos++;
     224                 :          2 :         slen--;
     225                 :            : 
     226         [ -  + ]:          2 :         if ((size_t) 1 + pos[0] > slen) {
     227                 :          0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: Too short Icon Binary File "
     228                 :            :                         "value from " MACSTR, MAC2STR(sa));
     229                 :          0 :                 return -1;
     230                 :            :         }
     231                 :          2 :         wpa_hexdump_ascii(MSG_DEBUG, "Icon Type", pos + 1, pos[0]);
     232                 :          2 :         png = os_strncasecmp((char *) pos + 1, "image/png", 9) == 0;
     233                 :          2 :         slen -= 1 + pos[0];
     234                 :          2 :         pos += 1 + pos[0];
     235                 :            : 
     236         [ -  + ]:          2 :         if (slen < 2) {
     237                 :          0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: Too short Icon Binary File "
     238                 :            :                         "value from " MACSTR, MAC2STR(sa));
     239                 :          0 :                 return -1;
     240                 :            :         }
     241                 :          2 :         data_len = WPA_GET_LE16(pos);
     242                 :          2 :         pos += 2;
     243                 :          2 :         slen -= 2;
     244                 :            : 
     245         [ -  + ]:          2 :         if (data_len > slen) {
     246                 :          0 :                 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: Too short Icon Binary File "
     247                 :            :                         "value from " MACSTR, MAC2STR(sa));
     248                 :          0 :                 return -1;
     249                 :            :         }
     250                 :            : 
     251                 :          2 :         wpa_printf(MSG_DEBUG, "Icon Binary Data: %u bytes", data_len);
     252         [ -  + ]:          2 :         if (wpa_s->conf->osu_dir == NULL)
     253                 :          0 :                 return -1;
     254                 :            : 
     255                 :          2 :         wpa_s->osu_icon_id++;
     256         [ -  + ]:          2 :         if (wpa_s->osu_icon_id == 0)
     257                 :          0 :                 wpa_s->osu_icon_id++;
     258         [ +  - ]:          2 :         snprintf(fname, sizeof(fname), "%s/osu-icon-%u.%s",
     259                 :          2 :                  wpa_s->conf->osu_dir, wpa_s->osu_icon_id,
     260                 :            :                  png ? "png" : "icon");
     261                 :          2 :         f = fopen(fname, "wb");
     262         [ -  + ]:          2 :         if (f == NULL)
     263                 :          0 :                 return -1;
     264         [ -  + ]:          2 :         if (fwrite(pos, slen, 1, f) != 1) {
     265                 :          0 :                 fclose(f);
     266                 :          0 :                 unlink(fname);
     267                 :          0 :                 return -1;
     268                 :            :         }
     269                 :          2 :         fclose(f);
     270                 :            : 
     271                 :          2 :         wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP-ICON %s", fname);
     272                 :          2 :         return 0;
     273                 :            : }
     274                 :            : 
     275                 :            : 
     276                 :          2 : static void hs20_continue_icon_fetch(void *eloop_ctx, void *sock_ctx)
     277                 :            : {
     278                 :          2 :         struct wpa_supplicant *wpa_s = eloop_ctx;
     279         [ +  - ]:          2 :         if (wpa_s->fetch_osu_icon_in_progress)
     280                 :          2 :                 hs20_next_osu_icon(wpa_s);
     281                 :          2 : }
     282                 :            : 
     283                 :            : 
     284                 :          2 : static void hs20_osu_icon_fetch_result(struct wpa_supplicant *wpa_s, int res)
     285                 :            : {
     286                 :            :         size_t i, j;
     287                 :            :         struct os_reltime now, tmp;
     288                 :            :         int dur;
     289                 :            : 
     290                 :          2 :         os_get_reltime(&now);
     291                 :          2 :         os_reltime_sub(&now, &wpa_s->osu_icon_fetch_start, &tmp);
     292                 :          2 :         dur = tmp.sec * 1000 + tmp.usec / 1000;
     293                 :          2 :         wpa_printf(MSG_DEBUG, "HS 2.0: Icon fetch dur=%d ms res=%d",
     294                 :            :                    dur, res);
     295                 :            : 
     296         [ +  - ]:          3 :         for (i = 0; i < wpa_s->osu_prov_count; i++) {
     297                 :          3 :                 struct osu_provider *osu = &wpa_s->osu_prov[i];
     298         [ +  + ]:          4 :                 for (j = 0; j < osu->icon_count; j++) {
     299                 :          3 :                         struct osu_icon *icon = &osu->icon[j];
     300 [ +  + ][ -  + ]:          3 :                         if (icon->id || icon->failed)
     301                 :          1 :                                 continue;
     302         [ -  + ]:          2 :                         if (res < 0)
     303                 :          0 :                                 icon->failed = 1;
     304                 :            :                         else
     305                 :          2 :                                 icon->id = wpa_s->osu_icon_id;
     306                 :          2 :                         return;
     307                 :            :                 }
     308                 :            :         }
     309                 :            : }
     310                 :            : 
     311                 :            : 
     312                 :        206 : void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
     313                 :            :                                   const u8 *sa, const u8 *data, size_t slen)
     314                 :            : {
     315                 :        206 :         const u8 *pos = data;
     316                 :            :         u8 subtype;
     317                 :        206 :         struct wpa_bss *bss = wpa_bss_get_bssid(wpa_s, sa);
     318                 :        206 :         struct wpa_bss_anqp *anqp = NULL;
     319                 :            :         int ret;
     320                 :            : 
     321         [ -  + ]:        206 :         if (slen < 2)
     322                 :        206 :                 return;
     323                 :            : 
     324         [ +  - ]:        206 :         if (bss)
     325                 :        206 :                 anqp = bss->anqp;
     326                 :            : 
     327                 :        206 :         subtype = *pos++;
     328                 :        206 :         slen--;
     329                 :            : 
     330                 :        206 :         pos++; /* Reserved */
     331                 :        206 :         slen--;
     332                 :            : 
     333   [ +  +  +  +  :        206 :         switch (subtype) {
             +  +  +  - ]
     334                 :            :         case HS20_STYPE_CAPABILITY_LIST:
     335                 :        147 :                 wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
     336                 :        882 :                         " HS Capability List", MAC2STR(sa));
     337                 :        147 :                 wpa_hexdump_ascii(MSG_DEBUG, "HS Capability List", pos, slen);
     338                 :        147 :                 break;
     339                 :            :         case HS20_STYPE_OPERATOR_FRIENDLY_NAME:
     340                 :          2 :                 wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
     341                 :         12 :                         " Operator Friendly Name", MAC2STR(sa));
     342                 :          2 :                 wpa_hexdump_ascii(MSG_DEBUG, "oper friendly name", pos, slen);
     343         [ +  - ]:          2 :                 if (anqp) {
     344                 :          2 :                         wpabuf_free(anqp->hs20_operator_friendly_name);
     345                 :          2 :                         anqp->hs20_operator_friendly_name =
     346                 :          2 :                                 wpabuf_alloc_copy(pos, slen);
     347                 :            :                 }
     348                 :          2 :                 break;
     349                 :            :         case HS20_STYPE_WAN_METRICS:
     350                 :         26 :                 wpa_hexdump(MSG_DEBUG, "WAN Metrics", pos, slen);
     351         [ -  + ]:         26 :                 if (slen < 13) {
     352                 :          0 :                         wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: Too short WAN "
     353                 :            :                                 "Metrics value from " MACSTR, MAC2STR(sa));
     354                 :          0 :                         break;
     355                 :            :                 }
     356                 :         26 :                 wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
     357                 :        156 :                         " WAN Metrics %02x:%u:%u:%u:%u:%u", MAC2STR(sa),
     358                 :         26 :                         pos[0], WPA_GET_LE32(pos + 1), WPA_GET_LE32(pos + 5),
     359                 :         26 :                         pos[9], pos[10], WPA_GET_LE16(pos + 11));
     360         [ +  - ]:         26 :                 if (anqp) {
     361                 :         26 :                         wpabuf_free(anqp->hs20_wan_metrics);
     362                 :         26 :                         anqp->hs20_wan_metrics = wpabuf_alloc_copy(pos, slen);
     363                 :            :                 }
     364                 :         26 :                 break;
     365                 :            :         case HS20_STYPE_CONNECTION_CAPABILITY:
     366                 :         19 :                 wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
     367                 :        114 :                         " Connection Capability", MAC2STR(sa));
     368                 :         19 :                 wpa_hexdump_ascii(MSG_DEBUG, "conn capability", pos, slen);
     369         [ +  - ]:         19 :                 if (anqp) {
     370                 :         19 :                         wpabuf_free(anqp->hs20_connection_capability);
     371                 :         19 :                         anqp->hs20_connection_capability =
     372                 :         19 :                                 wpabuf_alloc_copy(pos, slen);
     373                 :            :                 }
     374                 :         19 :                 break;
     375                 :            :         case HS20_STYPE_OPERATING_CLASS:
     376                 :          8 :                 wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
     377                 :         48 :                         " Operating Class", MAC2STR(sa));
     378                 :          8 :                 wpa_hexdump_ascii(MSG_DEBUG, "Operating Class", pos, slen);
     379         [ +  - ]:          8 :                 if (anqp) {
     380                 :          8 :                         wpabuf_free(anqp->hs20_operating_class);
     381                 :          8 :                         anqp->hs20_operating_class =
     382                 :          8 :                                 wpabuf_alloc_copy(pos, slen);
     383                 :            :                 }
     384                 :          8 :                 break;
     385                 :            :         case HS20_STYPE_OSU_PROVIDERS_LIST:
     386                 :          2 :                 wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
     387                 :         12 :                         " OSU Providers list", MAC2STR(sa));
     388                 :          2 :                 wpa_s->num_prov_found++;
     389         [ +  - ]:          2 :                 if (anqp) {
     390                 :          2 :                         wpabuf_free(anqp->hs20_osu_providers_list);
     391                 :          2 :                         anqp->hs20_osu_providers_list =
     392                 :          2 :                                 wpabuf_alloc_copy(pos, slen);
     393                 :            :                 }
     394                 :          2 :                 break;
     395                 :            :         case HS20_STYPE_ICON_BINARY_FILE:
     396                 :          2 :                 ret = hs20_process_icon_binary_file(wpa_s, sa, pos, slen);
     397         [ +  - ]:          2 :                 if (wpa_s->fetch_osu_icon_in_progress) {
     398                 :          2 :                         hs20_osu_icon_fetch_result(wpa_s, ret);
     399                 :          2 :                         eloop_cancel_timeout(hs20_continue_icon_fetch,
     400                 :            :                                              wpa_s, NULL);
     401                 :          2 :                         eloop_register_timeout(0, 0, hs20_continue_icon_fetch,
     402                 :            :                                                wpa_s, NULL);
     403                 :            :                 }
     404                 :          2 :                 break;
     405                 :            :         default:
     406                 :          0 :                 wpa_printf(MSG_DEBUG, "HS20: Unsupported subtype %u", subtype);
     407                 :          0 :                 break;
     408                 :            :         }
     409                 :            : }
     410                 :            : 
     411                 :            : 
     412                 :        157 : void hs20_notify_parse_done(struct wpa_supplicant *wpa_s)
     413                 :            : {
     414         [ +  + ]:        157 :         if (!wpa_s->fetch_osu_icon_in_progress)
     415                 :        155 :                 return;
     416         [ +  - ]:          2 :         if (eloop_is_timeout_registered(hs20_continue_icon_fetch, wpa_s, NULL))
     417                 :          2 :                 return;
     418                 :            :         /*
     419                 :            :          * We are going through icon fetch, but no icon response was received.
     420                 :            :          * Assume this means the current AP could not provide an answer to avoid
     421                 :            :          * getting stuck in fetch iteration.
     422                 :            :          */
     423                 :        157 :         hs20_icon_fetch_failed(wpa_s);
     424                 :            : }
     425                 :            : 
     426                 :            : 
     427                 :          2 : static void hs20_free_osu_prov_entry(struct osu_provider *prov)
     428                 :            : {
     429                 :          2 : }
     430                 :            : 
     431                 :            : 
     432                 :         42 : void hs20_free_osu_prov(struct wpa_supplicant *wpa_s)
     433                 :            : {
     434                 :            :         size_t i;
     435         [ +  + ]:         44 :         for (i = 0; i < wpa_s->osu_prov_count; i++)
     436                 :          2 :                 hs20_free_osu_prov_entry(&wpa_s->osu_prov[i]);
     437                 :         42 :         os_free(wpa_s->osu_prov);
     438                 :         42 :         wpa_s->osu_prov = NULL;
     439                 :         42 :         wpa_s->osu_prov_count = 0;
     440                 :         42 : }
     441                 :            : 
     442                 :            : 
     443                 :          1 : static void hs20_osu_fetch_done(struct wpa_supplicant *wpa_s)
     444                 :            : {
     445                 :            :         char fname[256];
     446                 :            :         FILE *f;
     447                 :            :         size_t i, j;
     448                 :            : 
     449                 :          1 :         wpa_s->fetch_osu_info = 0;
     450                 :          1 :         wpa_s->fetch_osu_icon_in_progress = 0;
     451                 :            : 
     452         [ -  + ]:          1 :         if (wpa_s->conf->osu_dir == NULL) {
     453                 :          0 :                 hs20_free_osu_prov(wpa_s);
     454                 :          0 :                 wpa_s->fetch_anqp_in_progress = 0;
     455                 :          0 :                 return;
     456                 :            :         }
     457                 :            : 
     458                 :          1 :         snprintf(fname, sizeof(fname), "%s/osu-providers.txt",
     459                 :          1 :                  wpa_s->conf->osu_dir);
     460                 :          1 :         f = fopen(fname, "w");
     461         [ -  + ]:          1 :         if (f == NULL) {
     462                 :          0 :                 hs20_free_osu_prov(wpa_s);
     463                 :          0 :                 return;
     464                 :            :         }
     465         [ +  + ]:          3 :         for (i = 0; i < wpa_s->osu_prov_count; i++) {
     466                 :          2 :                 struct osu_provider *osu = &wpa_s->osu_prov[i];
     467         [ +  + ]:          2 :                 if (i > 0)
     468                 :          1 :                         fprintf(f, "\n");
     469                 :          2 :                 fprintf(f, "OSU-PROVIDER " MACSTR "\n"
     470                 :            :                         "uri=%s\n"
     471                 :            :                         "methods=%08x\n",
     472                 :         12 :                         MAC2STR(osu->bssid), osu->server_uri, osu->osu_methods);
     473         [ +  - ]:          2 :                 if (osu->osu_ssid_len) {
     474                 :          2 :                         fprintf(f, "osu_ssid=%s\n",
     475                 :          2 :                                 wpa_ssid_txt(osu->osu_ssid,
     476                 :          2 :                                              osu->osu_ssid_len));
     477                 :            :                 }
     478         [ -  + ]:          2 :                 if (osu->osu_nai[0])
     479                 :          0 :                         fprintf(f, "osu_nai=%s\n", osu->osu_nai);
     480         [ +  + ]:          6 :                 for (j = 0; j < osu->friendly_name_count; j++) {
     481                 :          4 :                         fprintf(f, "friendly_name=%s:%s\n",
     482                 :          4 :                                 osu->friendly_name[j].lang,
     483                 :          4 :                                 osu->friendly_name[j].text);
     484                 :            :                 }
     485         [ +  + ]:          6 :                 for (j = 0; j < osu->serv_desc_count; j++) {
     486                 :          4 :                         fprintf(f, "desc=%s:%s\n",
     487                 :          4 :                                 osu->serv_desc[j].lang,
     488                 :          4 :                                 osu->serv_desc[j].text);
     489                 :            :                 }
     490         [ +  + ]:          4 :                 for (j = 0; j < osu->icon_count; j++) {
     491                 :          2 :                         struct osu_icon *icon = &osu->icon[j];
     492         [ -  + ]:          2 :                         if (icon->failed)
     493                 :          0 :                                 continue; /* could not fetch icon */
     494                 :          2 :                         fprintf(f, "icon=%u:%u:%u:%s:%s:%s\n",
     495                 :          4 :                                 icon->id, icon->width, icon->height, icon->lang,
     496                 :          2 :                                 icon->icon_type, icon->filename);
     497                 :            :                 }
     498                 :            :         }
     499                 :          1 :         fclose(f);
     500                 :          1 :         hs20_free_osu_prov(wpa_s);
     501                 :            : 
     502                 :          1 :         wpa_msg(wpa_s, MSG_INFO, "OSU provider fetch completed");
     503                 :          1 :         wpa_s->fetch_anqp_in_progress = 0;
     504                 :            : }
     505                 :            : 
     506                 :            : 
     507                 :          3 : void hs20_next_osu_icon(struct wpa_supplicant *wpa_s)
     508                 :            : {
     509                 :            :         size_t i, j;
     510                 :            : 
     511                 :          3 :         wpa_printf(MSG_DEBUG, "HS 2.0: Ready to fetch next icon");
     512                 :            : 
     513         [ +  + ]:          6 :         for (i = 0; i < wpa_s->osu_prov_count; i++) {
     514                 :          5 :                 struct osu_provider *osu = &wpa_s->osu_prov[i];
     515         [ +  + ]:          8 :                 for (j = 0; j < osu->icon_count; j++) {
     516                 :          5 :                         struct osu_icon *icon = &osu->icon[j];
     517 [ +  + ][ -  + ]:          5 :                         if (icon->id || icon->failed)
     518                 :          3 :                                 continue;
     519                 :            : 
     520                 :          2 :                         wpa_printf(MSG_DEBUG, "HS 2.0: Try to fetch icon '%s' "
     521                 :          2 :                                    "from " MACSTR, icon->filename,
     522                 :         12 :                                    MAC2STR(osu->bssid));
     523                 :          2 :                         os_get_reltime(&wpa_s->osu_icon_fetch_start);
     524         [ -  + ]:          2 :                         if (hs20_anqp_send_req(wpa_s, osu->bssid,
     525                 :            :                                                BIT(HS20_STYPE_ICON_REQUEST),
     526                 :          2 :                                                (u8 *) icon->filename,
     527                 :          2 :                                                os_strlen(icon->filename)) < 0) {
     528                 :          0 :                                 icon->failed = 1;
     529                 :          0 :                                 continue;
     530                 :            :                         }
     531                 :          3 :                         return;
     532                 :            :                 }
     533                 :            :         }
     534                 :            : 
     535                 :          1 :         wpa_printf(MSG_DEBUG, "HS 2.0: No more icons to fetch");
     536                 :          1 :         hs20_osu_fetch_done(wpa_s);
     537                 :            : }
     538                 :            : 
     539                 :            : 
     540                 :          2 : static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
     541                 :            :                               const u8 *osu_ssid, u8 osu_ssid_len,
     542                 :            :                               const u8 *pos, size_t len)
     543                 :            : {
     544                 :            :         struct osu_provider *prov;
     545                 :          2 :         const u8 *end = pos + len;
     546                 :            :         u16 len2;
     547                 :            :         const u8 *pos2;
     548                 :            : 
     549                 :          2 :         wpa_hexdump(MSG_DEBUG, "HS 2.0: Parsing OSU Provider", pos, len);
     550                 :          2 :         prov = os_realloc_array(wpa_s->osu_prov,
     551                 :          2 :                                 wpa_s->osu_prov_count + 1,
     552                 :            :                                 sizeof(*prov));
     553         [ -  + ]:          2 :         if (prov == NULL)
     554                 :          0 :                 return;
     555                 :          2 :         wpa_s->osu_prov = prov;
     556                 :          2 :         prov = &prov[wpa_s->osu_prov_count];
     557                 :          2 :         os_memset(prov, 0, sizeof(*prov));
     558                 :            : 
     559                 :          2 :         os_memcpy(prov->bssid, bss->bssid, ETH_ALEN);
     560                 :          2 :         os_memcpy(prov->osu_ssid, osu_ssid, osu_ssid_len);
     561                 :          2 :         prov->osu_ssid_len = osu_ssid_len;
     562                 :            : 
     563                 :            :         /* OSU Friendly Name Length */
     564         [ -  + ]:          2 :         if (pos + 2 > end) {
     565                 :          0 :                 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU "
     566                 :            :                            "Friendly Name Length");
     567                 :          0 :                 return;
     568                 :            :         }
     569                 :          2 :         len2 = WPA_GET_LE16(pos);
     570                 :          2 :         pos += 2;
     571         [ -  + ]:          2 :         if (pos + len2 > end) {
     572                 :          0 :                 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU "
     573                 :            :                            "Friendly Name Duples");
     574                 :          0 :                 return;
     575                 :            :         }
     576                 :          2 :         pos2 = pos;
     577                 :          2 :         pos += len2;
     578                 :            : 
     579                 :            :         /* OSU Friendly Name Duples */
     580 [ +  + ][ +  - ]:          6 :         while (pos2 + 4 <= pos && prov->friendly_name_count < OSU_MAX_ITEMS) {
     581                 :            :                 struct osu_lang_string *f;
     582 [ +  - ][ -  + ]:          4 :                 if (pos2 + 1 + pos2[0] > pos || pos2[0] < 3) {
     583                 :          0 :                         wpa_printf(MSG_DEBUG, "Invalid OSU Friendly Name");
     584                 :          0 :                         break;
     585                 :            :                 }
     586                 :          4 :                 f = &prov->friendly_name[prov->friendly_name_count++];
     587                 :          4 :                 os_memcpy(f->lang, pos2 + 1, 3);
     588                 :          4 :                 os_memcpy(f->text, pos2 + 1 + 3, pos2[0] - 3);
     589                 :          4 :                 pos2 += 1 + pos2[0];
     590                 :            :         }
     591                 :            : 
     592                 :            :         /* OSU Server URI */
     593 [ +  - ][ -  + ]:          2 :         if (pos + 1 > end || pos + 1 + pos[0] > end) {
     594                 :          0 :                 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU Server "
     595                 :            :                            "URI");
     596                 :          0 :                 return;
     597                 :            :         }
     598                 :          2 :         os_memcpy(prov->server_uri, pos + 1, pos[0]);
     599                 :          2 :         pos += 1 + pos[0];
     600                 :            : 
     601                 :            :         /* OSU Method list */
     602 [ +  - ][ -  + ]:          2 :         if (pos + 1 > end || pos + 1 + pos[0] > end) {
     603                 :          0 :                 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU Method "
     604                 :            :                            "list");
     605                 :          0 :                 return;
     606                 :            :         }
     607                 :          2 :         pos2 = pos + 1;
     608                 :          2 :         pos += 1 + pos[0];
     609         [ +  + ]:          4 :         while (pos2 < pos) {
     610         [ +  - ]:          2 :                 if (*pos2 < 32)
     611                 :          2 :                         prov->osu_methods |= BIT(*pos2);
     612                 :          2 :                 pos2++;
     613                 :            :         }
     614                 :            : 
     615                 :            :         /* Icons Available Length */
     616         [ -  + ]:          2 :         if (pos + 2 > end) {
     617                 :          0 :                 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for Icons "
     618                 :            :                            "Available Length");
     619                 :          0 :                 return;
     620                 :            :         }
     621                 :          2 :         len2 = WPA_GET_LE16(pos);
     622                 :          2 :         pos += 2;
     623         [ -  + ]:          2 :         if (pos + len2 > end) {
     624                 :          0 :                 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for Icons "
     625                 :            :                            "Available");
     626                 :          0 :                 return;
     627                 :            :         }
     628                 :          2 :         pos2 = pos;
     629                 :          2 :         pos += len2;
     630                 :            : 
     631                 :            :         /* Icons Available */
     632         [ +  + ]:          4 :         while (pos2 < pos) {
     633                 :          2 :                 struct osu_icon *icon = &prov->icon[prov->icon_count];
     634         [ -  + ]:          2 :                 if (pos2 + 2 + 2 + 3 + 1 + 1 > pos) {
     635                 :          0 :                         wpa_printf(MSG_DEBUG, "HS 2.0: Invalid Icon Metadata");
     636                 :          0 :                         break;
     637                 :            :                 }
     638                 :            : 
     639                 :          2 :                 icon->width = WPA_GET_LE16(pos2);
     640                 :          2 :                 pos2 += 2;
     641                 :          2 :                 icon->height = WPA_GET_LE16(pos2);
     642                 :          2 :                 pos2 += 2;
     643                 :          2 :                 os_memcpy(icon->lang, pos2, 3);
     644                 :          2 :                 pos2 += 3;
     645                 :            : 
     646         [ -  + ]:          2 :                 if (pos2 + 1 + pos2[0] > pos) {
     647                 :          0 :                         wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon Type");
     648                 :          0 :                         break;
     649                 :            :                 }
     650                 :          2 :                 os_memcpy(icon->icon_type, pos2 + 1, pos2[0]);
     651                 :          2 :                 pos2 += 1 + pos2[0];
     652                 :            : 
     653         [ -  + ]:          2 :                 if (pos2 + 1 + pos2[0] > pos) {
     654                 :          0 :                         wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon "
     655                 :            :                                    "Filename");
     656                 :          0 :                         break;
     657                 :            :                 }
     658                 :          2 :                 os_memcpy(icon->filename, pos2 + 1, pos2[0]);
     659                 :          2 :                 pos2 += 1 + pos2[0];
     660                 :            : 
     661                 :          2 :                 prov->icon_count++;
     662                 :            :         }
     663                 :            : 
     664                 :            :         /* OSU_NAI */
     665 [ +  - ][ -  + ]:          2 :         if (pos + 1 > end || pos + 1 + pos[0] > end) {
     666                 :          0 :                 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU_NAI");
     667                 :          0 :                 return;
     668                 :            :         }
     669                 :          2 :         os_memcpy(prov->osu_nai, pos + 1, pos[0]);
     670                 :          2 :         pos += 1 + pos[0];
     671                 :            : 
     672                 :            :         /* OSU Service Description Length */
     673         [ -  + ]:          2 :         if (pos + 2 > end) {
     674                 :          0 :                 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU "
     675                 :            :                            "Service Description Length");
     676                 :          0 :                 return;
     677                 :            :         }
     678                 :          2 :         len2 = WPA_GET_LE16(pos);
     679                 :          2 :         pos += 2;
     680         [ -  + ]:          2 :         if (pos + len2 > end) {
     681                 :          0 :                 wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU "
     682                 :            :                            "Service Description Duples");
     683                 :          0 :                 return;
     684                 :            :         }
     685                 :          2 :         pos2 = pos;
     686                 :          2 :         pos += len2;
     687                 :            : 
     688                 :            :         /* OSU Service Description Duples */
     689 [ +  + ][ +  - ]:          6 :         while (pos2 + 4 <= pos && prov->serv_desc_count < OSU_MAX_ITEMS) {
     690                 :            :                 struct osu_lang_string *f;
     691 [ +  - ][ -  + ]:          4 :                 if (pos2 + 1 + pos2[0] > pos || pos2[0] < 3) {
     692                 :          0 :                         wpa_printf(MSG_DEBUG, "Invalid OSU Service "
     693                 :            :                                    "Description");
     694                 :          0 :                         break;
     695                 :            :                 }
     696                 :          4 :                 f = &prov->serv_desc[prov->serv_desc_count++];
     697                 :          4 :                 os_memcpy(f->lang, pos2 + 1, 3);
     698                 :          4 :                 os_memcpy(f->text, pos2 + 1 + 3, pos2[0] - 3);
     699                 :          4 :                 pos2 += 1 + pos2[0];
     700                 :            :         }
     701                 :            : 
     702                 :          2 :         wpa_printf(MSG_DEBUG, "HS 2.0: Added OSU Provider through " MACSTR,
     703                 :         12 :                    MAC2STR(bss->bssid));
     704                 :          2 :         wpa_s->osu_prov_count++;
     705                 :            : }
     706                 :            : 
     707                 :            : 
     708                 :          1 : void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s)
     709                 :            : {
     710                 :            :         struct wpa_bss *bss;
     711                 :            :         struct wpabuf *prov_anqp;
     712                 :            :         const u8 *pos, *end;
     713                 :            :         u16 len;
     714                 :            :         const u8 *osu_ssid;
     715                 :            :         u8 osu_ssid_len;
     716                 :            :         u8 num_providers;
     717                 :            : 
     718                 :          1 :         hs20_free_osu_prov(wpa_s);
     719                 :            : 
     720         [ +  + ]:          3 :         dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
     721         [ -  + ]:          2 :                 if (bss->anqp == NULL)
     722                 :          0 :                         continue;
     723                 :          2 :                 prov_anqp = bss->anqp->hs20_osu_providers_list;
     724         [ -  + ]:          2 :                 if (prov_anqp == NULL)
     725                 :          0 :                         continue;
     726                 :          2 :                 wpa_printf(MSG_DEBUG, "HS 2.0: Parsing OSU Providers list from "
     727                 :         12 :                            MACSTR, MAC2STR(bss->bssid));
     728                 :          2 :                 wpa_hexdump_buf(MSG_DEBUG, "HS 2.0: OSU Providers list",
     729                 :            :                                 prov_anqp);
     730                 :          2 :                 pos = wpabuf_head(prov_anqp);
     731                 :          2 :                 end = pos + wpabuf_len(prov_anqp);
     732                 :            : 
     733                 :            :                 /* OSU SSID */
     734         [ -  + ]:          2 :                 if (pos + 1 > end)
     735                 :          0 :                         continue;
     736         [ -  + ]:          2 :                 if (pos + 1 + pos[0] > end) {
     737                 :          0 :                         wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for "
     738                 :            :                                    "OSU SSID");
     739                 :          0 :                         continue;
     740                 :            :                 }
     741                 :          2 :                 osu_ssid_len = *pos++;
     742         [ -  + ]:          2 :                 if (osu_ssid_len > 32) {
     743                 :          0 :                         wpa_printf(MSG_DEBUG, "HS 2.0: Invalid OSU SSID "
     744                 :            :                                    "Length %u", osu_ssid_len);
     745                 :          0 :                         continue;
     746                 :            :                 }
     747                 :          2 :                 osu_ssid = pos;
     748                 :          2 :                 pos += osu_ssid_len;
     749                 :            : 
     750         [ -  + ]:          2 :                 if (pos + 1 > end) {
     751                 :          0 :                         wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for "
     752                 :            :                                    "Number of OSU Providers");
     753                 :          0 :                         continue;
     754                 :            :                 }
     755                 :          2 :                 num_providers = *pos++;
     756                 :          2 :                 wpa_printf(MSG_DEBUG, "HS 2.0: Number of OSU Providers: %u",
     757                 :            :                            num_providers);
     758                 :            : 
     759                 :            :                 /* OSU Providers */
     760 [ +  + ][ +  - ]:          4 :                 while (pos + 2 < end && num_providers > 0) {
     761                 :          2 :                         num_providers--;
     762                 :          2 :                         len = WPA_GET_LE16(pos);
     763                 :          2 :                         pos += 2;
     764         [ -  + ]:          2 :                         if (pos + len > end)
     765                 :          0 :                                 break;
     766                 :          2 :                         hs20_osu_add_prov(wpa_s, bss, osu_ssid,
     767                 :            :                                           osu_ssid_len, pos, len);
     768                 :          2 :                         pos += len;
     769                 :            :                 }
     770                 :            : 
     771         [ -  + ]:          2 :                 if (pos != end) {
     772                 :          0 :                         wpa_printf(MSG_DEBUG, "HS 2.0: Ignored %d bytes of "
     773                 :            :                                    "extra data after OSU Providers",
     774                 :          0 :                                    (int) (end - pos));
     775                 :            :                 }
     776                 :            :         }
     777                 :            : 
     778                 :          1 :         wpa_s->fetch_osu_icon_in_progress = 1;
     779                 :          1 :         hs20_next_osu_icon(wpa_s);
     780                 :          1 : }
     781                 :            : 
     782                 :            : 
     783                 :          1 : static void hs20_osu_scan_res_handler(struct wpa_supplicant *wpa_s,
     784                 :            :                                       struct wpa_scan_results *scan_res)
     785                 :            : {
     786                 :          1 :         wpa_printf(MSG_DEBUG, "OSU provisioning fetch scan completed");
     787                 :          1 :         wpa_s->network_select = 0;
     788                 :          1 :         wpa_s->fetch_all_anqp = 1;
     789                 :          1 :         wpa_s->fetch_osu_info = 1;
     790                 :          1 :         wpa_s->fetch_osu_icon_in_progress = 0;
     791                 :            : 
     792                 :          1 :         interworking_start_fetch_anqp(wpa_s);
     793                 :          1 : }
     794                 :            : 
     795                 :            : 
     796                 :          1 : int hs20_fetch_osu(struct wpa_supplicant *wpa_s)
     797                 :            : {
     798         [ -  + ]:          1 :         if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
     799                 :          0 :                 wpa_printf(MSG_DEBUG, "HS 2.0: Cannot start fetch_osu - "
     800                 :            :                            "interface disabled");
     801                 :          0 :                 return -1;
     802                 :            :         }
     803                 :            : 
     804         [ -  + ]:          1 :         if (wpa_s->scanning) {
     805                 :          0 :                 wpa_printf(MSG_DEBUG, "HS 2.0: Cannot start fetch_osu - "
     806                 :            :                            "scanning");
     807                 :          0 :                 return -1;
     808                 :            :         }
     809                 :            : 
     810         [ -  + ]:          1 :         if (wpa_s->conf->osu_dir == NULL) {
     811                 :          0 :                 wpa_printf(MSG_DEBUG, "HS 2.0: Cannot start fetch_osu - "
     812                 :            :                            "osu_dir not configured");
     813                 :          0 :                 return -1;
     814                 :            :         }
     815                 :            : 
     816 [ +  - ][ -  + ]:          1 :         if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) {
     817                 :          0 :                 wpa_printf(MSG_DEBUG, "HS 2.0: Cannot start fetch_osu - "
     818                 :            :                            "fetch in progress (%d, %d)",
     819                 :          0 :                            wpa_s->fetch_anqp_in_progress,
     820                 :          0 :                            wpa_s->network_select);
     821                 :          0 :                 return -1;
     822                 :            :         }
     823                 :            : 
     824                 :          1 :         wpa_msg(wpa_s, MSG_INFO, "Starting OSU provisioning information fetch");
     825                 :          1 :         wpa_s->num_osu_scans = 0;
     826                 :          1 :         wpa_s->num_prov_found = 0;
     827                 :          1 :         hs20_start_osu_scan(wpa_s);
     828                 :            : 
     829                 :          1 :         return 0;
     830                 :            : }
     831                 :            : 
     832                 :            : 
     833                 :          1 : void hs20_start_osu_scan(struct wpa_supplicant *wpa_s)
     834                 :            : {
     835                 :          1 :         wpa_s->num_osu_scans++;
     836                 :          1 :         wpa_s->scan_req = MANUAL_SCAN_REQ;
     837                 :          1 :         wpa_s->scan_res_handler = hs20_osu_scan_res_handler;
     838                 :          1 :         wpa_supplicant_req_scan(wpa_s, 0, 0);
     839                 :          1 : }
     840                 :            : 
     841                 :            : 
     842                 :       1183 : void hs20_cancel_fetch_osu(struct wpa_supplicant *wpa_s)
     843                 :            : {
     844                 :       1183 :         wpa_printf(MSG_DEBUG, "Cancel OSU fetch");
     845                 :       1183 :         interworking_stop_fetch_anqp(wpa_s);
     846                 :       1183 :         wpa_s->network_select = 0;
     847                 :       1183 :         wpa_s->fetch_osu_info = 0;
     848                 :       1183 :         wpa_s->fetch_osu_icon_in_progress = 0;
     849                 :       1183 : }
     850                 :            : 
     851                 :            : 
     852                 :          0 : void hs20_icon_fetch_failed(struct wpa_supplicant *wpa_s)
     853                 :            : {
     854                 :          0 :         hs20_osu_icon_fetch_result(wpa_s, -1);
     855                 :          0 :         eloop_cancel_timeout(hs20_continue_icon_fetch, wpa_s, NULL);
     856                 :          0 :         eloop_register_timeout(0, 0, hs20_continue_icon_fetch, wpa_s, NULL);
     857                 :          0 : }
     858                 :            : 
     859                 :            : 
     860                 :          0 : void hs20_rx_subscription_remediation(struct wpa_supplicant *wpa_s,
     861                 :            :                                       const char *url, u8 osu_method)
     862                 :            : {
     863         [ #  # ]:          0 :         if (url)
     864                 :          0 :                 wpa_msg(wpa_s, MSG_INFO, HS20_SUBSCRIPTION_REMEDIATION "%u %s",
     865                 :            :                         osu_method, url);
     866                 :            :         else
     867                 :          0 :                 wpa_msg(wpa_s, MSG_INFO, HS20_SUBSCRIPTION_REMEDIATION);
     868                 :          0 : }
     869                 :            : 
     870                 :            : 
     871                 :          2 : void hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s, u8 code,
     872                 :            :                                     u16 reauth_delay, const char *url)
     873                 :            : {
     874         [ -  + ]:          2 :         if (!wpa_sm_pmf_enabled(wpa_s->wpa)) {
     875                 :          0 :                 wpa_printf(MSG_DEBUG, "HS 2.0: Ignore deauthentication imminent notice since PMF was not enabled");
     876                 :          0 :                 return;
     877                 :            :         }
     878                 :            : 
     879                 :          2 :         wpa_msg(wpa_s, MSG_INFO, HS20_DEAUTH_IMMINENT_NOTICE "%u %u %s",
     880                 :            :                 code, reauth_delay, url);
     881                 :            : 
     882         [ +  + ]:          2 :         if (code == HS20_DEAUTH_REASON_CODE_BSS) {
     883                 :          1 :                 wpa_printf(MSG_DEBUG, "HS 2.0: Add BSS to blacklist");
     884                 :          1 :                 wpa_blacklist_add(wpa_s, wpa_s->bssid);
     885                 :            :                 /* TODO: For now, disable full ESS since some drivers may not
     886                 :            :                  * support disabling per BSS. */
     887         [ +  - ]:          1 :                 if (wpa_s->current_ssid) {
     888                 :            :                         struct os_reltime now;
     889                 :          1 :                         os_get_reltime(&now);
     890         [ -  + ]:          1 :                         if (now.sec + reauth_delay <=
     891                 :          1 :                             wpa_s->current_ssid->disabled_until.sec)
     892                 :          0 :                                 return;
     893                 :          1 :                         wpa_printf(MSG_DEBUG, "HS 2.0: Disable network for %u seconds (BSS)",
     894                 :            :                                    reauth_delay);
     895                 :          1 :                         wpa_s->current_ssid->disabled_until.sec =
     896                 :          1 :                                 now.sec + reauth_delay;
     897                 :            :                 }
     898                 :            :         }
     899                 :            : 
     900 [ +  + ][ +  - ]:          2 :         if (code == HS20_DEAUTH_REASON_CODE_ESS && wpa_s->current_ssid) {
     901                 :            :                 struct os_reltime now;
     902                 :          1 :                 os_get_reltime(&now);
     903         [ -  + ]:          1 :                 if (now.sec + reauth_delay <=
     904                 :          1 :                     wpa_s->current_ssid->disabled_until.sec)
     905                 :          0 :                         return;
     906                 :          1 :                 wpa_printf(MSG_DEBUG, "HS 2.0: Disable network for %u seconds",
     907                 :            :                            reauth_delay);
     908                 :          2 :                 wpa_s->current_ssid->disabled_until.sec =
     909                 :          1 :                         now.sec + reauth_delay;
     910                 :            :         }
     911                 :            : }

Generated by: LCOV version 1.9