Coverage Report

Created: 2025-07-18 06:03

/src/hostap/wpa_supplicant/bss.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * BSS table
3
 * Copyright (c) 2009-2019, Jouni Malinen <j@w1.fi>
4
 *
5
 * This software may be distributed under the terms of the BSD license.
6
 * See README for more details.
7
 */
8
9
#include "utils/includes.h"
10
11
#include "utils/common.h"
12
#include "utils/eloop.h"
13
#include "common/ieee802_11_defs.h"
14
#include "drivers/driver.h"
15
#include "eap_peer/eap.h"
16
#include "rsn_supp/wpa.h"
17
#include "wpa_supplicant_i.h"
18
#include "config.h"
19
#include "notify.h"
20
#include "scan.h"
21
#include "bssid_ignore.h"
22
#include "bss.h"
23
24
static void wpa_bss_set_hessid(struct wpa_bss *bss)
25
0
{
26
0
#ifdef CONFIG_INTERWORKING
27
0
  const u8 *ie = wpa_bss_get_ie(bss, WLAN_EID_INTERWORKING);
28
0
  if (ie == NULL || (ie[1] != 7 && ie[1] != 9)) {
29
0
    os_memset(bss->hessid, 0, ETH_ALEN);
30
0
    return;
31
0
  }
32
0
  if (ie[1] == 7)
33
0
    os_memcpy(bss->hessid, ie + 3, ETH_ALEN);
34
0
  else
35
0
    os_memcpy(bss->hessid, ie + 5, ETH_ALEN);
36
0
#endif /* CONFIG_INTERWORKING */
37
0
}
38
39
40
/**
41
 * wpa_bss_anqp_alloc - Allocate ANQP data structure for a BSS entry
42
 * Returns: Allocated ANQP data structure or %NULL on failure
43
 *
44
 * The allocated ANQP data structure has its users count set to 1. It may be
45
 * shared by multiple BSS entries and each shared entry is freed with
46
 * wpa_bss_anqp_free().
47
 */
48
struct wpa_bss_anqp * wpa_bss_anqp_alloc(void)
49
0
{
50
0
  struct wpa_bss_anqp *anqp;
51
0
  anqp = os_zalloc(sizeof(*anqp));
52
0
  if (anqp == NULL)
53
0
    return NULL;
54
0
#ifdef CONFIG_INTERWORKING
55
0
  dl_list_init(&anqp->anqp_elems);
56
0
#endif /* CONFIG_INTERWORKING */
57
0
  anqp->users = 1;
58
0
  return anqp;
59
0
}
60
61
62
/**
63
 * wpa_bss_anqp_clone - Clone an ANQP data structure
64
 * @anqp: ANQP data structure from wpa_bss_anqp_alloc()
65
 * Returns: Cloned ANQP data structure or %NULL on failure
66
 */
67
static struct wpa_bss_anqp * wpa_bss_anqp_clone(struct wpa_bss_anqp *anqp)
68
0
{
69
0
  struct wpa_bss_anqp *n;
70
71
0
  n = os_zalloc(sizeof(*n));
72
0
  if (n == NULL)
73
0
    return NULL;
74
75
0
#define ANQP_DUP(f) if (anqp->f) n->f = wpabuf_dup(anqp->f)
76
0
#ifdef CONFIG_INTERWORKING
77
0
  dl_list_init(&n->anqp_elems);
78
0
  ANQP_DUP(capability_list);
79
0
  ANQP_DUP(venue_name);
80
0
  ANQP_DUP(network_auth_type);
81
0
  ANQP_DUP(roaming_consortium);
82
0
  ANQP_DUP(ip_addr_type_availability);
83
0
  ANQP_DUP(nai_realm);
84
0
  ANQP_DUP(anqp_3gpp);
85
0
  ANQP_DUP(domain_name);
86
0
  ANQP_DUP(fils_realm_info);
87
0
#endif /* CONFIG_INTERWORKING */
88
0
#ifdef CONFIG_HS20
89
0
  ANQP_DUP(hs20_capability_list);
90
0
  ANQP_DUP(hs20_operator_friendly_name);
91
0
  ANQP_DUP(hs20_wan_metrics);
92
0
  ANQP_DUP(hs20_connection_capability);
93
0
  ANQP_DUP(hs20_operating_class);
94
0
#endif /* CONFIG_HS20 */
95
0
#undef ANQP_DUP
96
97
0
  return n;
98
0
}
99
100
101
/**
102
 * wpa_bss_anqp_unshare_alloc - Unshare ANQP data (if shared) in a BSS entry
103
 * @bss: BSS entry
104
 * Returns: 0 on success, -1 on failure
105
 *
106
 * This function ensures the specific BSS entry has an ANQP data structure that
107
 * is not shared with any other BSS entry.
108
 */
109
int wpa_bss_anqp_unshare_alloc(struct wpa_bss *bss)
110
0
{
111
0
  struct wpa_bss_anqp *anqp;
112
113
0
  if (bss->anqp && bss->anqp->users > 1) {
114
    /* allocated, but shared - clone an unshared copy */
115
0
    anqp = wpa_bss_anqp_clone(bss->anqp);
116
0
    if (anqp == NULL)
117
0
      return -1;
118
0
    anqp->users = 1;
119
0
    bss->anqp->users--;
120
0
    bss->anqp = anqp;
121
0
    return 0;
122
0
  }
123
124
0
  if (bss->anqp)
125
0
    return 0; /* already allocated and not shared */
126
127
  /* not allocated - allocate a new storage area */
128
0
  bss->anqp = wpa_bss_anqp_alloc();
129
0
  return bss->anqp ? 0 : -1;
130
0
}
131
132
133
/**
134
 * wpa_bss_anqp_free - Free an ANQP data structure
135
 * @anqp: ANQP data structure from wpa_bss_anqp_alloc() or wpa_bss_anqp_clone()
136
 */
137
static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp)
138
0
{
139
0
#ifdef CONFIG_INTERWORKING
140
0
  struct wpa_bss_anqp_elem *elem;
141
0
#endif /* CONFIG_INTERWORKING */
142
143
0
  if (anqp == NULL)
144
0
    return;
145
146
0
  anqp->users--;
147
0
  if (anqp->users > 0) {
148
    /* Another BSS entry holds a pointer to this ANQP info */
149
0
    return;
150
0
  }
151
152
0
#ifdef CONFIG_INTERWORKING
153
0
  wpabuf_free(anqp->capability_list);
154
0
  wpabuf_free(anqp->venue_name);
155
0
  wpabuf_free(anqp->network_auth_type);
156
0
  wpabuf_free(anqp->roaming_consortium);
157
0
  wpabuf_free(anqp->ip_addr_type_availability);
158
0
  wpabuf_free(anqp->nai_realm);
159
0
  wpabuf_free(anqp->anqp_3gpp);
160
0
  wpabuf_free(anqp->domain_name);
161
0
  wpabuf_free(anqp->fils_realm_info);
162
163
0
  while ((elem = dl_list_first(&anqp->anqp_elems,
164
0
             struct wpa_bss_anqp_elem, list))) {
165
0
    dl_list_del(&elem->list);
166
0
    wpabuf_free(elem->payload);
167
0
    os_free(elem);
168
0
  }
169
0
#endif /* CONFIG_INTERWORKING */
170
0
#ifdef CONFIG_HS20
171
0
  wpabuf_free(anqp->hs20_capability_list);
172
0
  wpabuf_free(anqp->hs20_operator_friendly_name);
173
0
  wpabuf_free(anqp->hs20_wan_metrics);
174
0
  wpabuf_free(anqp->hs20_connection_capability);
175
0
  wpabuf_free(anqp->hs20_operating_class);
176
0
#endif /* CONFIG_HS20 */
177
178
0
  os_free(anqp);
179
0
}
180
181
182
static struct wpa_connect_work *
183
wpa_bss_check_pending_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
184
0
{
185
0
  struct wpa_radio_work *work;
186
0
  struct wpa_connect_work *cwork;
187
188
0
  work = radio_work_pending(wpa_s, "sme-connect");
189
0
  if (!work)
190
0
    work = radio_work_pending(wpa_s, "connect");
191
0
  if (!work)
192
0
    return NULL;
193
194
0
  cwork = work->ctx;
195
0
  if (cwork->bss != bss)
196
0
    return NULL;
197
198
0
  return cwork;
199
0
}
200
201
202
static void wpa_bss_update_pending_connect(struct wpa_connect_work *cwork,
203
             struct wpa_bss *new_bss)
204
0
{
205
0
  wpa_printf(MSG_DEBUG,
206
0
       "Update BSS pointer for the pending connect radio work");
207
0
  cwork->bss = new_bss;
208
0
  if (!new_bss)
209
0
    cwork->bss_removed = 1;
210
0
}
211
212
213
void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
214
        const char *reason)
215
0
{
216
0
  struct wpa_connect_work *cwork;
217
0
  unsigned int j;
218
219
0
  if (wpa_s->last_scan_res) {
220
0
    unsigned int i;
221
0
    for (i = 0; i < wpa_s->last_scan_res_used; i++) {
222
0
      if (wpa_s->last_scan_res[i] == bss) {
223
0
        os_memmove(&wpa_s->last_scan_res[i],
224
0
             &wpa_s->last_scan_res[i + 1],
225
0
             (wpa_s->last_scan_res_used - i - 1)
226
0
             * sizeof(struct wpa_bss *));
227
0
        wpa_s->last_scan_res_used--;
228
0
        break;
229
0
      }
230
0
    }
231
0
  }
232
0
  cwork = wpa_bss_check_pending_connect(wpa_s, bss);
233
0
  if (cwork)
234
0
    wpa_bss_update_pending_connect(cwork, NULL);
235
0
  dl_list_del(&bss->list);
236
0
  dl_list_del(&bss->list_id);
237
0
  wpa_s->num_bss--;
238
0
  wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Remove id %u BSSID " MACSTR
239
0
    " SSID '%s' due to %s", bss->id, MAC2STR(bss->bssid),
240
0
    wpa_ssid_txt(bss->ssid, bss->ssid_len), reason);
241
0
  wpas_notify_bss_removed(wpa_s, bss->bssid, bss->id);
242
0
  wpa_bss_anqp_free(bss->anqp);
243
244
0
  if (wpa_s->current_bss == bss) {
245
0
    wpa_printf(MSG_DEBUG,
246
0
         "BSS: Clear current_bss due to bss removal");
247
0
    wpa_s->current_bss = NULL;
248
0
  }
249
250
0
#ifdef CONFIG_INTERWORKING
251
0
  if (wpa_s->interworking_gas_bss == bss) {
252
0
    wpa_printf(MSG_DEBUG,
253
0
         "BSS: Clear interworking_gas_bss due to bss removal");
254
0
    wpa_s->interworking_gas_bss = NULL;
255
0
  }
256
0
#endif /* CONFIG_INTERWORKING */
257
258
0
#ifdef CONFIG_WNM
259
0
  if (wpa_s->wnm_target_bss == bss) {
260
0
    wpa_printf(MSG_DEBUG,
261
0
         "BSS: Clear wnm_target_bss due to bss removal");
262
0
    wpa_s->wnm_target_bss = NULL;
263
0
  }
264
0
#endif /* CONFIG_WNM */
265
266
0
  if (wpa_s->ml_connect_probe_bss == bss) {
267
0
    wpa_printf(MSG_DEBUG,
268
0
         "BSS: Clear ml_connect_probe_bss due to bss removal");
269
0
    wpa_s->ml_connect_probe_bss = NULL;
270
0
  }
271
272
0
  for (j = 0; j < MAX_NUM_MLD_LINKS; j++) {
273
0
    if (wpa_s->links[j].bss == bss) {
274
0
      wpa_printf(MSG_DEBUG,
275
0
           "BSS: Clear links[%d].bss due to bss removal",
276
0
           j);
277
0
      wpa_s->valid_links &= ~BIT(j);
278
0
      wpa_s->links[j].bss = NULL;
279
0
    }
280
0
  }
281
282
0
  os_free(bss);
283
0
}
284
285
286
/**
287
 * wpa_bss_get - Fetch a BSS table entry based on BSSID and SSID
288
 * @wpa_s: Pointer to wpa_supplicant data
289
 * @bssid: BSSID, or %NULL to match any BSSID
290
 * @ssid: SSID
291
 * @ssid_len: Length of @ssid
292
 * Returns: Pointer to the BSS entry or %NULL if not found
293
 */
294
struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid,
295
           const u8 *ssid, size_t ssid_len)
296
0
{
297
0
  struct wpa_bss *bss;
298
299
0
  if (bssid && !wpa_supplicant_filter_bssid_match(wpa_s, bssid))
300
0
    return NULL;
301
0
  dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
302
0
    if ((!bssid || ether_addr_equal(bss->bssid, bssid)) &&
303
0
        bss->ssid_len == ssid_len &&
304
0
        os_memcmp(bss->ssid, ssid, ssid_len) == 0)
305
0
      return bss;
306
0
  }
307
0
  return NULL;
308
0
}
309
310
/**
311
 * wpa_bss_get_connection - Fetch a BSS table entry based on BSSID and SSID.
312
 * @wpa_s: Pointer to wpa_supplicant data
313
 * @bssid: BSSID, or %NULL to match any BSSID
314
 * @ssid: SSID
315
 * @ssid_len: Length of @ssid
316
 * Returns: Pointer to the BSS entry or %NULL if not found
317
 *
318
 * This function is similar to wpa_bss_get() but it will also return OWE
319
 * transition mode encrypted networks for which transition-element matches
320
 * @ssid.
321
 */
322
struct wpa_bss * wpa_bss_get_connection(struct wpa_supplicant *wpa_s,
323
          const u8 *bssid,
324
          const u8 *ssid, size_t ssid_len)
325
0
{
326
0
  struct wpa_bss *bss;
327
#ifdef CONFIG_OWE
328
  const u8 *owe, *owe_bssid, *owe_ssid;
329
  size_t owe_ssid_len;
330
#endif /* CONFIG_OWE */
331
332
0
  if (bssid && !wpa_supplicant_filter_bssid_match(wpa_s, bssid))
333
0
    return NULL;
334
0
  dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
335
0
    if (bssid && !ether_addr_equal(bss->bssid, bssid))
336
0
      continue;
337
338
0
    if (bss->ssid_len == ssid_len &&
339
0
        os_memcmp(bss->ssid, ssid, ssid_len) == 0)
340
0
      return bss;
341
342
#ifdef CONFIG_OWE
343
    /* Check if OWE transition mode element is present and matches
344
     * the SSID */
345
    owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
346
    if (!owe)
347
      continue;
348
349
    if (wpas_get_owe_trans_network(owe, &owe_bssid, &owe_ssid,
350
                 &owe_ssid_len))
351
      continue;
352
353
    if (bss->ssid_len &&
354
        owe_ssid_len == ssid_len &&
355
        os_memcmp(owe_ssid, ssid, ssid_len) == 0)
356
      return bss;
357
#endif /* CONFIG_OWE */
358
0
  }
359
0
  return NULL;
360
0
}
361
362
363
void calculate_update_time(const struct os_reltime *fetch_time,
364
         unsigned int age_ms,
365
         struct os_reltime *update_time)
366
0
{
367
0
  os_time_t usec;
368
369
0
  update_time->sec = fetch_time->sec;
370
0
  update_time->usec = fetch_time->usec;
371
0
  update_time->sec -= age_ms / 1000;
372
0
  usec = (age_ms % 1000) * 1000;
373
0
  if (update_time->usec < usec) {
374
0
    update_time->sec--;
375
0
    update_time->usec += 1000000;
376
0
  }
377
0
  update_time->usec -= usec;
378
0
}
379
380
381
static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src,
382
           struct os_reltime *fetch_time)
383
0
{
384
0
  dst->flags = src->flags;
385
0
  os_memcpy(dst->bssid, src->bssid, ETH_ALEN);
386
0
  dst->freq = src->freq;
387
0
  dst->max_cw = src->max_cw;
388
0
  dst->beacon_int = src->beacon_int;
389
0
  dst->caps = src->caps;
390
0
  dst->qual = src->qual;
391
0
  dst->noise = src->noise;
392
0
  dst->level = src->level;
393
0
  dst->tsf = src->tsf;
394
0
  dst->beacon_newer = src->beacon_newer;
395
0
  dst->est_throughput = src->est_throughput;
396
0
  dst->snr = src->snr;
397
398
0
  calculate_update_time(fetch_time, src->age, &dst->last_update);
399
0
}
400
401
402
static int wpa_bss_is_wps_candidate(struct wpa_supplicant *wpa_s,
403
            struct wpa_bss *bss)
404
0
{
405
#ifdef CONFIG_WPS
406
  struct wpa_ssid *ssid;
407
  struct wpabuf *wps_ie;
408
  int pbc = 0, ret;
409
410
  wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
411
  if (!wps_ie)
412
    return 0;
413
414
  if (wps_is_selected_pbc_registrar(wps_ie)) {
415
    pbc = 1;
416
  } else if (!wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1)) {
417
    wpabuf_free(wps_ie);
418
    return 0;
419
  }
420
421
  for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
422
    if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS))
423
      continue;
424
    if (ssid->ssid_len &&
425
        (ssid->ssid_len != bss->ssid_len ||
426
         os_memcmp(ssid->ssid, bss->ssid, ssid->ssid_len) != 0))
427
      continue;
428
429
    if (pbc)
430
      ret = eap_is_wps_pbc_enrollee(&ssid->eap);
431
    else
432
      ret = eap_is_wps_pin_enrollee(&ssid->eap);
433
    wpabuf_free(wps_ie);
434
    return ret;
435
  }
436
  wpabuf_free(wps_ie);
437
#endif /* CONFIG_WPS */
438
439
0
  return 0;
440
0
}
441
442
443
static bool is_p2p_pending_bss(struct wpa_supplicant *wpa_s,
444
             struct wpa_bss *bss)
445
0
{
446
#ifdef CONFIG_P2P
447
  u8 addr[ETH_ALEN];
448
449
  if (ether_addr_equal(bss->bssid, wpa_s->pending_join_iface_addr))
450
    return true;
451
  if (!is_zero_ether_addr(wpa_s->pending_join_dev_addr) &&
452
      p2p_parse_dev_addr(wpa_bss_ie_ptr(bss), bss->ie_len, addr) == 0 &&
453
      ether_addr_equal(addr, wpa_s->pending_join_dev_addr))
454
    return true;
455
#endif /* CONFIG_P2P */
456
0
  return false;
457
0
}
458
459
460
#ifdef CONFIG_OWE
461
static int wpa_bss_owe_trans_known(struct wpa_supplicant *wpa_s,
462
           struct wpa_bss *bss,
463
           const u8 *entry_ssid, size_t entry_ssid_len)
464
{
465
  const u8 *owe, *owe_bssid, *owe_ssid;
466
  size_t owe_ssid_len;
467
468
  owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
469
  if (!owe)
470
    return 0;
471
472
  if (wpas_get_owe_trans_network(owe, &owe_bssid, &owe_ssid,
473
               &owe_ssid_len))
474
    return 0;
475
476
  return entry_ssid_len == owe_ssid_len &&
477
    os_memcmp(owe_ssid, entry_ssid, owe_ssid_len) == 0;
478
}
479
#endif /* CONFIG_OWE */
480
481
482
static int wpa_bss_known(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
483
0
{
484
0
  struct wpa_ssid *ssid;
485
486
0
  if (is_p2p_pending_bss(wpa_s, bss))
487
0
    return 1;
488
489
0
  for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
490
0
    if (ssid->ssid == NULL || ssid->ssid_len == 0)
491
0
      continue;
492
0
    if (ssid->ssid_len == bss->ssid_len &&
493
0
        os_memcmp(ssid->ssid, bss->ssid, ssid->ssid_len) == 0)
494
0
      return 1;
495
#ifdef CONFIG_OWE
496
    if (wpa_bss_owe_trans_known(wpa_s, bss, ssid->ssid,
497
              ssid->ssid_len))
498
      return 1;
499
#endif /* CONFIG_OWE */
500
0
  }
501
502
0
  return 0;
503
0
}
504
505
506
static int wpa_bss_in_use(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
507
0
{
508
0
  int i;
509
510
0
  if (bss == wpa_s->current_bss)
511
0
    return 1;
512
513
0
  if (bss == wpa_s->ml_connect_probe_bss)
514
0
    return 1;
515
516
0
#ifdef CONFIG_WNM
517
0
  if (bss == wpa_s->wnm_target_bss)
518
0
    return 1;
519
0
#endif /* CONFIG_WNM */
520
521
0
  if (wpa_s->current_bss &&
522
0
      (bss->ssid_len != wpa_s->current_bss->ssid_len ||
523
0
       os_memcmp(bss->ssid, wpa_s->current_bss->ssid,
524
0
           bss->ssid_len) != 0))
525
0
    return 0; /* SSID has changed */
526
527
0
  if (!is_zero_ether_addr(bss->bssid) &&
528
0
      (ether_addr_equal(bss->bssid, wpa_s->bssid) ||
529
0
       ether_addr_equal(bss->bssid, wpa_s->pending_bssid)))
530
0
    return 1;
531
532
0
  if (!wpa_s->valid_links)
533
0
    return 0;
534
535
0
  for_each_link(wpa_s->valid_links, i) {
536
0
    if (ether_addr_equal(bss->bssid, wpa_s->links[i].bssid))
537
0
      return 1;
538
0
  }
539
540
0
  return 0;
541
0
}
542
543
544
static int wpa_bss_remove_oldest_unknown(struct wpa_supplicant *wpa_s)
545
0
{
546
0
  struct wpa_bss *bss;
547
548
0
  dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
549
0
    if (!wpa_bss_known(wpa_s, bss) &&
550
0
        !wpa_bss_in_use(wpa_s, bss) &&
551
0
        !wpa_bss_is_wps_candidate(wpa_s, bss)) {
552
0
      wpa_bss_remove(wpa_s, bss, __func__);
553
0
      return 0;
554
0
    }
555
0
  }
556
557
0
  return -1;
558
0
}
559
560
561
static int wpa_bss_remove_oldest(struct wpa_supplicant *wpa_s)
562
0
{
563
0
  struct wpa_bss *bss;
564
565
  /*
566
   * Remove the oldest entry that does not match with any configured
567
   * network.
568
   */
569
0
  if (wpa_bss_remove_oldest_unknown(wpa_s) == 0)
570
0
    return 0;
571
572
  /*
573
   * Remove the oldest entry that isn't currently in use.
574
   */
575
0
  dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
576
0
    if (!wpa_bss_in_use(wpa_s, bss)) {
577
0
      wpa_bss_remove(wpa_s, bss, __func__);
578
0
      return 0;
579
0
    }
580
0
  }
581
582
0
  return -1;
583
0
}
584
585
586
static struct wpa_bss * wpa_bss_add(struct wpa_supplicant *wpa_s,
587
            const u8 *ssid, size_t ssid_len,
588
            struct wpa_scan_res *res,
589
            struct os_reltime *fetch_time)
590
0
{
591
0
  struct wpa_bss *bss;
592
0
  char extra[100];
593
0
  const u8 *ml_ie;
594
0
  char *pos, *end;
595
0
  int ret = 0;
596
0
  const u8 *mld_addr;
597
598
0
  bss = os_zalloc(sizeof(*bss) + res->ie_len + res->beacon_ie_len);
599
0
  if (bss == NULL)
600
0
    return NULL;
601
0
  bss->id = wpa_s->bss_next_id++;
602
0
  bss->last_update_idx = wpa_s->bss_update_idx;
603
0
  wpa_bss_copy_res(bss, res, fetch_time);
604
0
  os_memcpy(bss->ssid, ssid, ssid_len);
605
0
  bss->ssid_len = ssid_len;
606
0
  bss->ie_len = res->ie_len;
607
0
  bss->beacon_ie_len = res->beacon_ie_len;
608
0
  os_memcpy(bss->ies, res + 1, res->ie_len + res->beacon_ie_len);
609
0
  wpa_bss_set_hessid(bss);
610
611
0
  os_memset(bss->mld_addr, 0, ETH_ALEN);
612
0
  ml_ie = wpa_scan_get_ml_ie(res, MULTI_LINK_CONTROL_TYPE_BASIC);
613
0
  if (ml_ie) {
614
0
    mld_addr = get_basic_mle_mld_addr(&ml_ie[3], ml_ie[1] - 1);
615
0
    if (mld_addr)
616
0
      os_memcpy(bss->mld_addr, mld_addr, ETH_ALEN);
617
0
  }
618
619
0
  if (wpa_s->num_bss + 1 > wpa_s->conf->bss_max_count &&
620
0
      wpa_bss_remove_oldest(wpa_s) != 0) {
621
0
    wpa_printf(MSG_ERROR, "Increasing the MAX BSS count to %d "
622
0
         "because all BSSes are in use. We should normally "
623
0
         "not get here!", (int) wpa_s->num_bss + 1);
624
0
    wpa_s->conf->bss_max_count = wpa_s->num_bss + 1;
625
0
  }
626
627
0
  dl_list_add_tail(&wpa_s->bss, &bss->list);
628
0
  dl_list_add_tail(&wpa_s->bss_id, &bss->list_id);
629
0
  wpa_s->num_bss++;
630
631
0
  extra[0] = '\0';
632
0
  pos = extra;
633
0
  end = pos + sizeof(extra);
634
0
  if (!is_zero_ether_addr(bss->hessid))
635
0
    ret = os_snprintf(pos, end - pos, " HESSID " MACSTR,
636
0
          MAC2STR(bss->hessid));
637
638
0
  if (!is_zero_ether_addr(bss->mld_addr) &&
639
0
      !os_snprintf_error(end - pos, ret)) {
640
0
    pos += ret;
641
0
    ret = os_snprintf(pos, end - pos, " MLD ADDR " MACSTR,
642
0
          MAC2STR(bss->mld_addr));
643
0
  }
644
645
0
  wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Add new id %u BSSID " MACSTR
646
0
    " SSID '%s' freq %d%s",
647
0
    bss->id, MAC2STR(bss->bssid), wpa_ssid_txt(ssid, ssid_len),
648
0
    bss->freq, extra);
649
0
  wpas_notify_bss_added(wpa_s, bss->bssid, bss->id);
650
0
  return bss;
651
0
}
652
653
654
static int are_ies_equal(const struct wpa_bss *old,
655
       const struct wpa_scan_res *new_res, u32 ie)
656
0
{
657
0
  const u8 *old_ie, *new_ie;
658
0
  struct wpabuf *old_ie_buff = NULL;
659
0
  struct wpabuf *new_ie_buff = NULL;
660
0
  int new_ie_len, old_ie_len, ret, is_multi;
661
662
0
  switch (ie) {
663
0
  case WPA_IE_VENDOR_TYPE:
664
0
    old_ie = wpa_bss_get_vendor_ie(old, ie);
665
0
    new_ie = wpa_scan_get_vendor_ie(new_res, ie);
666
0
    is_multi = 0;
667
0
    break;
668
0
  case WPS_IE_VENDOR_TYPE:
669
0
    old_ie_buff = wpa_bss_get_vendor_ie_multi(old, ie);
670
0
    new_ie_buff = wpa_scan_get_vendor_ie_multi(new_res, ie);
671
0
    is_multi = 1;
672
0
    break;
673
0
  case WLAN_EID_RSN:
674
0
  case WLAN_EID_SUPP_RATES:
675
0
  case WLAN_EID_EXT_SUPP_RATES:
676
0
    old_ie = wpa_bss_get_ie(old, ie);
677
0
    new_ie = wpa_scan_get_ie(new_res, ie);
678
0
    is_multi = 0;
679
0
    break;
680
0
  default:
681
0
    wpa_printf(MSG_DEBUG, "bss: %s: cannot compare IEs", __func__);
682
0
    return 0;
683
0
  }
684
685
0
  if (is_multi) {
686
    /* in case of multiple IEs stored in buffer */
687
0
    old_ie = old_ie_buff ? wpabuf_head_u8(old_ie_buff) : NULL;
688
0
    new_ie = new_ie_buff ? wpabuf_head_u8(new_ie_buff) : NULL;
689
0
    old_ie_len = old_ie_buff ? wpabuf_len(old_ie_buff) : 0;
690
0
    new_ie_len = new_ie_buff ? wpabuf_len(new_ie_buff) : 0;
691
0
  } else {
692
    /* in case of single IE */
693
0
    old_ie_len = old_ie ? old_ie[1] + 2 : 0;
694
0
    new_ie_len = new_ie ? new_ie[1] + 2 : 0;
695
0
  }
696
697
0
  if (!old_ie || !new_ie)
698
0
    ret = !old_ie && !new_ie;
699
0
  else
700
0
    ret = (old_ie_len == new_ie_len &&
701
0
           os_memcmp(old_ie, new_ie, old_ie_len) == 0);
702
703
0
  wpabuf_free(old_ie_buff);
704
0
  wpabuf_free(new_ie_buff);
705
706
0
  return ret;
707
0
}
708
709
710
static u32 wpa_bss_compare_res(const struct wpa_bss *old,
711
             const struct wpa_scan_res *new_res)
712
0
{
713
0
  u32 changes = 0;
714
0
  int caps_diff = old->caps ^ new_res->caps;
715
716
0
  if (old->freq != new_res->freq)
717
0
    changes |= WPA_BSS_FREQ_CHANGED_FLAG;
718
719
0
  if (old->level != new_res->level)
720
0
    changes |= WPA_BSS_SIGNAL_CHANGED_FLAG;
721
722
0
  if (caps_diff & IEEE80211_CAP_PRIVACY)
723
0
    changes |= WPA_BSS_PRIVACY_CHANGED_FLAG;
724
725
0
  if (caps_diff & IEEE80211_CAP_IBSS)
726
0
    changes |= WPA_BSS_MODE_CHANGED_FLAG;
727
728
0
  if (old->ie_len == new_res->ie_len &&
729
0
      os_memcmp(wpa_bss_ie_ptr(old), new_res + 1, old->ie_len) == 0)
730
0
    return changes;
731
0
  changes |= WPA_BSS_IES_CHANGED_FLAG;
732
733
0
  if (!are_ies_equal(old, new_res, WPA_IE_VENDOR_TYPE))
734
0
    changes |= WPA_BSS_WPAIE_CHANGED_FLAG;
735
736
0
  if (!are_ies_equal(old, new_res, WLAN_EID_RSN))
737
0
    changes |= WPA_BSS_RSNIE_CHANGED_FLAG;
738
739
0
  if (!are_ies_equal(old, new_res, WPS_IE_VENDOR_TYPE))
740
0
    changes |= WPA_BSS_WPS_CHANGED_FLAG;
741
742
0
  if (!are_ies_equal(old, new_res, WLAN_EID_SUPP_RATES) ||
743
0
      !are_ies_equal(old, new_res, WLAN_EID_EXT_SUPP_RATES))
744
0
    changes |= WPA_BSS_RATES_CHANGED_FLAG;
745
746
0
  return changes;
747
0
}
748
749
750
void notify_bss_changes(struct wpa_supplicant *wpa_s, u32 changes,
751
      const struct wpa_bss *bss)
752
0
{
753
0
  if (changes & WPA_BSS_FREQ_CHANGED_FLAG)
754
0
    wpas_notify_bss_freq_changed(wpa_s, bss->id);
755
756
0
  if (changes & WPA_BSS_SIGNAL_CHANGED_FLAG)
757
0
    wpas_notify_bss_signal_changed(wpa_s, bss->id);
758
759
0
  if (changes & WPA_BSS_PRIVACY_CHANGED_FLAG)
760
0
    wpas_notify_bss_privacy_changed(wpa_s, bss->id);
761
762
0
  if (changes & WPA_BSS_MODE_CHANGED_FLAG)
763
0
    wpas_notify_bss_mode_changed(wpa_s, bss->id);
764
765
0
  if (changes & WPA_BSS_WPAIE_CHANGED_FLAG)
766
0
    wpas_notify_bss_wpaie_changed(wpa_s, bss->id);
767
768
0
  if (changes & WPA_BSS_RSNIE_CHANGED_FLAG)
769
0
    wpas_notify_bss_rsnie_changed(wpa_s, bss->id);
770
771
0
  if (changes & WPA_BSS_WPS_CHANGED_FLAG)
772
0
    wpas_notify_bss_wps_changed(wpa_s, bss->id);
773
774
0
  if (changes & WPA_BSS_IES_CHANGED_FLAG)
775
0
    wpas_notify_bss_ies_changed(wpa_s, bss->id);
776
777
0
  if (changes & WPA_BSS_RATES_CHANGED_FLAG)
778
0
    wpas_notify_bss_rates_changed(wpa_s, bss->id);
779
780
0
  wpas_notify_bss_seen(wpa_s, bss->id);
781
0
}
782
783
784
static struct wpa_bss *
785
wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
786
         struct wpa_scan_res *res, struct os_reltime *fetch_time)
787
0
{
788
0
  u32 changes;
789
790
0
  if (bss->last_update_idx == wpa_s->bss_update_idx) {
791
0
    struct os_reltime update_time;
792
793
    /*
794
     * Some drivers (e.g., cfg80211) include multiple BSS entries
795
     * for the same BSS if that BSS's channel changes. The BSS list
796
     * implementation in wpa_supplicant does not do that and we need
797
     * to filter out the obsolete results here to make sure only the
798
     * most current BSS information remains in the table.
799
     */
800
0
    wpa_printf(MSG_DEBUG, "BSS: " MACSTR
801
0
         " has multiple entries in the scan results - select the most current one",
802
0
         MAC2STR(bss->bssid));
803
0
    calculate_update_time(fetch_time, res->age, &update_time);
804
0
    wpa_printf(MSG_DEBUG,
805
0
         "Previous last_update: %u.%06u (freq %d%s)",
806
0
         (unsigned int) bss->last_update.sec,
807
0
         (unsigned int) bss->last_update.usec,
808
0
         bss->freq,
809
0
         (bss->flags & WPA_BSS_ASSOCIATED) ? " assoc" : "");
810
0
    wpa_printf(MSG_DEBUG, "New last_update: %u.%06u (freq %d%s)",
811
0
         (unsigned int) update_time.sec,
812
0
         (unsigned int) update_time.usec,
813
0
         res->freq,
814
0
         (res->flags & WPA_SCAN_ASSOCIATED) ? " assoc" : "");
815
0
    if ((bss->flags & WPA_BSS_ASSOCIATED) ||
816
0
        (!(res->flags & WPA_SCAN_ASSOCIATED) &&
817
0
         !os_reltime_before(&bss->last_update, &update_time))) {
818
0
      wpa_printf(MSG_DEBUG,
819
0
           "Ignore this BSS entry since the previous update looks more current");
820
0
      return bss;
821
0
    }
822
0
    wpa_printf(MSG_DEBUG,
823
0
         "Accept this BSS entry since it looks more current than the previous update");
824
0
  }
825
826
0
  changes = wpa_bss_compare_res(bss, res);
827
0
  if (changes & WPA_BSS_FREQ_CHANGED_FLAG)
828
0
    wpa_printf(MSG_DEBUG, "BSS: " MACSTR " changed freq %d --> %d",
829
0
         MAC2STR(bss->bssid), bss->freq, res->freq);
830
0
  bss->scan_miss_count = 0;
831
0
  bss->last_update_idx = wpa_s->bss_update_idx;
832
0
  wpa_bss_copy_res(bss, res, fetch_time);
833
  /* Move the entry to the end of the list */
834
0
  dl_list_del(&bss->list);
835
#ifdef CONFIG_P2P
836
  if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) &&
837
      !wpa_scan_get_vendor_ie(res, P2P_IE_VENDOR_TYPE) &&
838
      !(changes & WPA_BSS_FREQ_CHANGED_FLAG)) {
839
    /*
840
     * This can happen when non-P2P station interface runs a scan
841
     * without P2P IE in the Probe Request frame. P2P GO would reply
842
     * to that with a Probe Response that does not include P2P IE.
843
     * Do not update the IEs in this BSS entry to avoid such loss of
844
     * information that may be needed for P2P operations to
845
     * determine group information.
846
     */
847
    wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Do not update scan IEs for "
848
      MACSTR " since that would remove P2P IE information",
849
      MAC2STR(bss->bssid));
850
  } else
851
#endif /* CONFIG_P2P */
852
0
  if (bss->ie_len + bss->beacon_ie_len >=
853
0
      res->ie_len + res->beacon_ie_len) {
854
0
    os_memcpy(bss->ies, res + 1, res->ie_len + res->beacon_ie_len);
855
0
    bss->ie_len = res->ie_len;
856
0
    bss->beacon_ie_len = res->beacon_ie_len;
857
0
  } else {
858
0
    struct wpa_bss *nbss;
859
0
    struct dl_list *prev = bss->list_id.prev;
860
0
    struct wpa_connect_work *cwork;
861
0
    unsigned int i, j;
862
0
    bool update_current_bss = wpa_s->current_bss == bss;
863
0
    bool update_ml_probe_bss = wpa_s->ml_connect_probe_bss == bss;
864
0
    int update_link_bss = -1;
865
866
0
    for (j = 0; j < MAX_NUM_MLD_LINKS; j++) {
867
0
      if (wpa_s->links[j].bss == bss) {
868
0
        update_link_bss = j;
869
0
        break;
870
0
      }
871
0
    }
872
873
0
    cwork = wpa_bss_check_pending_connect(wpa_s, bss);
874
875
0
    for (i = 0; i < wpa_s->last_scan_res_used; i++) {
876
0
      if (wpa_s->last_scan_res[i] == bss)
877
0
        break;
878
0
    }
879
880
0
    dl_list_del(&bss->list_id);
881
0
    nbss = os_realloc(bss, sizeof(*bss) + res->ie_len +
882
0
          res->beacon_ie_len);
883
0
    if (nbss) {
884
0
      if (i != wpa_s->last_scan_res_used)
885
0
        wpa_s->last_scan_res[i] = nbss;
886
887
0
      if (update_current_bss)
888
0
        wpa_s->current_bss = nbss;
889
890
0
      if (update_ml_probe_bss)
891
0
        wpa_s->ml_connect_probe_bss = nbss;
892
893
0
      if (update_link_bss >= 0)
894
0
        wpa_s->links[update_link_bss].bss = nbss;
895
896
0
      if (cwork)
897
0
        wpa_bss_update_pending_connect(cwork, nbss);
898
899
0
      bss = nbss;
900
0
      os_memcpy(bss->ies, res + 1,
901
0
          res->ie_len + res->beacon_ie_len);
902
0
      bss->ie_len = res->ie_len;
903
0
      bss->beacon_ie_len = res->beacon_ie_len;
904
0
    }
905
0
    dl_list_add(prev, &bss->list_id);
906
0
  }
907
0
  if (changes & WPA_BSS_IES_CHANGED_FLAG) {
908
0
    const u8 *ml_ie, *mld_addr;
909
910
0
    wpa_bss_set_hessid(bss);
911
0
    os_memset(bss->mld_addr, 0, ETH_ALEN);
912
0
    ml_ie = wpa_scan_get_ml_ie(res, MULTI_LINK_CONTROL_TYPE_BASIC);
913
0
    if (ml_ie) {
914
0
      mld_addr = get_basic_mle_mld_addr(&ml_ie[3],
915
0
                ml_ie[1] - 1);
916
0
      if (mld_addr)
917
0
        os_memcpy(bss->mld_addr, mld_addr, ETH_ALEN);
918
0
    }
919
0
  }
920
0
  dl_list_add_tail(&wpa_s->bss, &bss->list);
921
922
0
  notify_bss_changes(wpa_s, changes, bss);
923
924
0
  return bss;
925
0
}
926
927
928
/**
929
 * wpa_bss_update_start - Start a BSS table update from scan results
930
 * @wpa_s: Pointer to wpa_supplicant data
931
 *
932
 * This function is called at the start of each BSS table update round for new
933
 * scan results. The actual scan result entries are indicated with calls to
934
 * wpa_bss_update_scan_res() and the update round is finished with a call to
935
 * wpa_bss_update_end().
936
 */
937
void wpa_bss_update_start(struct wpa_supplicant *wpa_s)
938
0
{
939
0
  wpa_s->bss_update_idx++;
940
0
  wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Start scan result update %u",
941
0
    wpa_s->bss_update_idx);
942
0
  wpa_s->last_scan_res_used = 0;
943
0
}
944
945
946
/**
947
 * wpa_bss_update_scan_res - Update a BSS table entry based on a scan result
948
 * @wpa_s: Pointer to wpa_supplicant data
949
 * @res: Scan result
950
 * @fetch_time: Time when the result was fetched from the driver
951
 *
952
 * This function updates a BSS table entry (or adds one) based on a scan result.
953
 * This is called separately for each scan result between the calls to
954
 * wpa_bss_update_start() and wpa_bss_update_end().
955
 */
956
void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
957
           struct wpa_scan_res *res,
958
           struct os_reltime *fetch_time)
959
0
{
960
0
  const u8 *ssid, *p2p, *mesh;
961
0
  struct wpa_bss *bss;
962
963
0
  if (wpa_s->conf->ignore_old_scan_res) {
964
0
    struct os_reltime update;
965
0
    calculate_update_time(fetch_time, res->age, &update);
966
0
    if (os_reltime_before(&update, &wpa_s->scan_trigger_time)) {
967
0
      struct os_reltime age;
968
0
      os_reltime_sub(&wpa_s->scan_trigger_time, &update,
969
0
               &age);
970
0
      wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Ignore driver BSS "
971
0
        "table entry that is %u.%06u seconds older "
972
0
        "than our scan trigger",
973
0
        (unsigned int) age.sec,
974
0
        (unsigned int) age.usec);
975
0
      return;
976
0
    }
977
0
  }
978
979
0
  ssid = wpa_scan_get_ie(res, WLAN_EID_SSID);
980
0
  if (ssid == NULL) {
981
0
    wpa_dbg(wpa_s, MSG_DEBUG, "BSS: No SSID IE included for "
982
0
      MACSTR, MAC2STR(res->bssid));
983
0
    return;
984
0
  }
985
0
  if (ssid[1] > SSID_MAX_LEN) {
986
0
    wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Too long SSID IE included for "
987
0
      MACSTR, MAC2STR(res->bssid));
988
0
    return;
989
0
  }
990
991
0
  p2p = wpa_scan_get_vendor_ie(res, P2P_IE_VENDOR_TYPE);
992
#ifdef CONFIG_P2P
993
  if (p2p == NULL &&
994
      wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE) {
995
    /*
996
     * If it's a P2P specific interface, then don't update
997
     * the scan result without a P2P IE.
998
     */
999
    wpa_printf(MSG_DEBUG, "BSS: No P2P IE - skipping BSS " MACSTR
1000
         " update for P2P interface", MAC2STR(res->bssid));
1001
    return;
1002
  }
1003
#endif /* CONFIG_P2P */
1004
0
  if (p2p && ssid[1] == P2P_WILDCARD_SSID_LEN &&
1005
0
      os_memcmp(ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0)
1006
0
    return; /* Skip P2P listen discovery results here */
1007
1008
  /* TODO: add option for ignoring BSSes we are not interested in
1009
   * (to save memory) */
1010
1011
0
  mesh = wpa_scan_get_ie(res, WLAN_EID_MESH_ID);
1012
0
  if (mesh && mesh[1] <= SSID_MAX_LEN)
1013
0
    ssid = mesh;
1014
1015
0
  bss = wpa_bss_get(wpa_s, res->bssid, ssid + 2, ssid[1]);
1016
0
  if (bss == NULL)
1017
0
    bss = wpa_bss_add(wpa_s, ssid + 2, ssid[1], res, fetch_time);
1018
0
  else {
1019
0
    bss = wpa_bss_update(wpa_s, bss, res, fetch_time);
1020
0
    if (wpa_s->last_scan_res) {
1021
0
      unsigned int i;
1022
0
      for (i = 0; i < wpa_s->last_scan_res_used; i++) {
1023
0
        if (bss == wpa_s->last_scan_res[i]) {
1024
          /* Already in the list */
1025
0
          return;
1026
0
        }
1027
0
      }
1028
0
    }
1029
0
  }
1030
1031
0
  if (bss == NULL)
1032
0
    return;
1033
0
  if (wpa_s->last_scan_res_used >= wpa_s->last_scan_res_size) {
1034
0
    struct wpa_bss **n;
1035
0
    unsigned int siz;
1036
0
    if (wpa_s->last_scan_res_size == 0)
1037
0
      siz = 32;
1038
0
    else
1039
0
      siz = wpa_s->last_scan_res_size * 2;
1040
0
    n = os_realloc_array(wpa_s->last_scan_res, siz,
1041
0
             sizeof(struct wpa_bss *));
1042
0
    if (n == NULL)
1043
0
      return;
1044
0
    wpa_s->last_scan_res = n;
1045
0
    wpa_s->last_scan_res_size = siz;
1046
0
  }
1047
1048
0
  if (wpa_s->last_scan_res)
1049
0
    wpa_s->last_scan_res[wpa_s->last_scan_res_used++] = bss;
1050
0
}
1051
1052
1053
static int wpa_bss_included_in_scan(const struct wpa_bss *bss,
1054
            const struct scan_info *info)
1055
0
{
1056
0
  int found;
1057
0
  size_t i;
1058
1059
0
  if (info == NULL)
1060
0
    return 1;
1061
1062
0
  if (info->num_freqs) {
1063
0
    found = 0;
1064
0
    for (i = 0; i < info->num_freqs; i++) {
1065
0
      if (bss->freq == info->freqs[i]) {
1066
0
        found = 1;
1067
0
        break;
1068
0
      }
1069
0
    }
1070
0
    if (!found)
1071
0
      return 0;
1072
0
  }
1073
1074
0
  if (info->num_ssids) {
1075
0
    found = 0;
1076
0
    for (i = 0; i < info->num_ssids; i++) {
1077
0
      const struct wpa_driver_scan_ssid *s = &info->ssids[i];
1078
0
      if ((s->ssid == NULL || s->ssid_len == 0) ||
1079
0
          (s->ssid_len == bss->ssid_len &&
1080
0
           os_memcmp(s->ssid, bss->ssid, bss->ssid_len) ==
1081
0
           0)) {
1082
0
        found = 1;
1083
0
        break;
1084
0
      }
1085
0
    }
1086
0
    if (!found)
1087
0
      return 0;
1088
0
  }
1089
1090
0
  return 1;
1091
0
}
1092
1093
1094
/**
1095
 * wpa_bss_update_end - End a BSS table update from scan results
1096
 * @wpa_s: Pointer to wpa_supplicant data
1097
 * @info: Information about scan parameters
1098
 * @new_scan: Whether this update round was based on a new scan
1099
 *
1100
 * This function is called at the end of each BSS table update round for new
1101
 * scan results. The start of the update was indicated with a call to
1102
 * wpa_bss_update_start().
1103
 */
1104
void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info,
1105
      int new_scan)
1106
0
{
1107
0
  struct wpa_bss *bss, *n;
1108
1109
0
  os_get_reltime(&wpa_s->last_scan);
1110
0
  if ((info && info->aborted) || !new_scan)
1111
0
    return; /* do not expire entries without new scan */
1112
1113
0
  dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
1114
0
    if (wpa_bss_in_use(wpa_s, bss))
1115
0
      continue;
1116
0
    if (!wpa_bss_included_in_scan(bss, info))
1117
0
      continue; /* expire only BSSes that were scanned */
1118
0
    if (bss->last_update_idx < wpa_s->bss_update_idx)
1119
0
      bss->scan_miss_count++;
1120
0
    if (bss->scan_miss_count >=
1121
0
        wpa_s->conf->bss_expiration_scan_count) {
1122
0
      wpa_bss_remove(wpa_s, bss, "no match in scan");
1123
0
    }
1124
0
  }
1125
1126
0
  wpa_printf(MSG_DEBUG, "BSS: last_scan_res_used=%zu/%zu",
1127
0
       wpa_s->last_scan_res_used, wpa_s->last_scan_res_size);
1128
0
}
1129
1130
1131
/**
1132
 * wpa_bss_flush_by_age - Flush old BSS entries
1133
 * @wpa_s: Pointer to wpa_supplicant data
1134
 * @age: Maximum entry age in seconds
1135
 *
1136
 * Remove BSS entries that have not been updated during the last @age seconds.
1137
 */
1138
void wpa_bss_flush_by_age(struct wpa_supplicant *wpa_s, int age)
1139
0
{
1140
0
  struct wpa_bss *bss, *n;
1141
0
  struct os_reltime t;
1142
1143
0
  if (dl_list_empty(&wpa_s->bss))
1144
0
    return;
1145
1146
0
  os_get_reltime(&t);
1147
1148
0
  if (t.sec < age)
1149
0
    return; /* avoid underflow; there can be no older entries */
1150
1151
0
  t.sec -= age;
1152
1153
0
  dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
1154
0
    if (wpa_bss_in_use(wpa_s, bss))
1155
0
      continue;
1156
1157
0
    if (wpa_s->reassoc_same_ess &&
1158
0
        wpa_s->wpa_state != WPA_COMPLETED &&
1159
0
        wpa_s->last_ssid &&
1160
0
        wpa_s->last_ssid->ssid &&
1161
0
        bss->ssid_len == wpa_s->last_ssid->ssid_len &&
1162
0
        os_memcmp(bss->ssid, wpa_s->last_ssid->ssid,
1163
0
            bss->ssid_len) == 0)
1164
0
      continue;
1165
1166
0
    if (os_reltime_before(&bss->last_update, &t)) {
1167
0
      wpa_bss_remove(wpa_s, bss, __func__);
1168
0
    } else
1169
0
      break;
1170
0
  }
1171
0
}
1172
1173
1174
/**
1175
 * wpa_bss_init - Initialize BSS table
1176
 * @wpa_s: Pointer to wpa_supplicant data
1177
 * Returns: 0 on success, -1 on failure
1178
 *
1179
 * This prepares BSS table lists and timer for periodic updates. The BSS table
1180
 * is deinitialized with wpa_bss_deinit() once not needed anymore.
1181
 */
1182
int wpa_bss_init(struct wpa_supplicant *wpa_s)
1183
1.40k
{
1184
1.40k
  dl_list_init(&wpa_s->bss);
1185
1.40k
  dl_list_init(&wpa_s->bss_id);
1186
1.40k
  return 0;
1187
1.40k
}
1188
1189
1190
/**
1191
 * wpa_bss_flush - Flush all unused BSS entries
1192
 * @wpa_s: Pointer to wpa_supplicant data
1193
 */
1194
void wpa_bss_flush(struct wpa_supplicant *wpa_s)
1195
1.40k
{
1196
1.40k
  struct wpa_bss *bss, *n;
1197
1198
1.40k
  wpa_s->clear_driver_scan_cache = 1;
1199
1200
1.40k
  if (wpa_s->bss.next == NULL)
1201
0
    return; /* BSS table not yet initialized */
1202
1203
1.40k
  dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
1204
0
    if (wpa_bss_in_use(wpa_s, bss))
1205
0
      continue;
1206
0
    wpa_bss_remove(wpa_s, bss, __func__);
1207
0
  }
1208
1.40k
}
1209
1210
1211
/**
1212
 * wpa_bss_deinit - Deinitialize BSS table
1213
 * @wpa_s: Pointer to wpa_supplicant data
1214
 */
1215
void wpa_bss_deinit(struct wpa_supplicant *wpa_s)
1216
0
{
1217
0
  wpa_bss_flush(wpa_s);
1218
0
}
1219
1220
1221
/**
1222
 * wpa_bss_get_bssid - Fetch a BSS table entry based on BSSID
1223
 * @wpa_s: Pointer to wpa_supplicant data
1224
 * @bssid: BSSID
1225
 * Returns: Pointer to the BSS entry or %NULL if not found
1226
 */
1227
struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s,
1228
           const u8 *bssid)
1229
0
{
1230
0
  struct wpa_bss *bss;
1231
0
  if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
1232
0
    return NULL;
1233
0
  dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
1234
0
    if (ether_addr_equal(bss->bssid, bssid))
1235
0
      return bss;
1236
0
  }
1237
0
  return NULL;
1238
0
}
1239
1240
1241
/**
1242
 * wpa_bss_get_bssid_latest - Fetch the latest BSS table entry based on BSSID
1243
 * @wpa_s: Pointer to wpa_supplicant data
1244
 * @bssid: BSSID
1245
 * Returns: Pointer to the BSS entry or %NULL if not found
1246
 *
1247
 * This function is like wpa_bss_get_bssid(), but full BSS table is iterated to
1248
 * find the entry that has the most recent update. This can help in finding the
1249
 * correct entry in cases where the SSID of the AP may have changed recently
1250
 * (e.g., in WPS reconfiguration cases).
1251
 */
1252
struct wpa_bss * wpa_bss_get_bssid_latest(struct wpa_supplicant *wpa_s,
1253
            const u8 *bssid)
1254
0
{
1255
0
  struct wpa_bss *bss, *found = NULL;
1256
0
  if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
1257
0
    return NULL;
1258
0
  dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
1259
0
    if (!ether_addr_equal(bss->bssid, bssid))
1260
0
      continue;
1261
0
    if (found == NULL ||
1262
0
        os_reltime_before(&found->last_update, &bss->last_update))
1263
0
      found = bss;
1264
0
  }
1265
0
  return found;
1266
0
}
1267
1268
1269
#ifdef CONFIG_P2P
1270
/**
1271
 * wpa_bss_get_p2p_dev_addr - Fetch the latest BSS table entry based on P2P Device Addr
1272
 * @wpa_s: Pointer to wpa_supplicant data
1273
 * @dev_addr: P2P Device Address of the GO
1274
 * Returns: Pointer to the BSS entry or %NULL if not found
1275
 *
1276
 * This function tries to find the entry that has the most recent update. This
1277
 * can help in finding the correct entry in cases where the SSID of the P2P
1278
 * Device may have changed recently.
1279
 */
1280
struct wpa_bss * wpa_bss_get_p2p_dev_addr(struct wpa_supplicant *wpa_s,
1281
            const u8 *dev_addr)
1282
{
1283
  struct wpa_bss *bss, *found = NULL;
1284
  dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
1285
    u8 addr[ETH_ALEN];
1286
    if (p2p_parse_dev_addr(wpa_bss_ie_ptr(bss), bss->ie_len,
1287
               addr) != 0 ||
1288
        !ether_addr_equal(addr, dev_addr))
1289
      continue;
1290
    if (!found ||
1291
        os_reltime_before(&found->last_update, &bss->last_update))
1292
      found = bss;
1293
  }
1294
  return found;
1295
}
1296
#endif /* CONFIG_P2P */
1297
1298
1299
/**
1300
 * wpa_bss_get_id - Fetch a BSS table entry based on identifier
1301
 * @wpa_s: Pointer to wpa_supplicant data
1302
 * @id: Unique identifier (struct wpa_bss::id) assigned for the entry
1303
 * Returns: Pointer to the BSS entry or %NULL if not found
1304
 */
1305
struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id)
1306
0
{
1307
0
  struct wpa_bss *bss;
1308
0
  dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1309
0
    if (bss->id == id)
1310
0
      return bss;
1311
0
  }
1312
0
  return NULL;
1313
0
}
1314
1315
1316
/**
1317
 * wpa_bss_get_id_range - Fetch a BSS table entry based on identifier range
1318
 * @wpa_s: Pointer to wpa_supplicant data
1319
 * @idf: Smallest allowed identifier assigned for the entry
1320
 * @idf: Largest allowed identifier assigned for the entry
1321
 * Returns: Pointer to the BSS entry or %NULL if not found
1322
 *
1323
 * This function is similar to wpa_bss_get_id() but allows a BSS entry with the
1324
 * smallest id value to be fetched within the specified range without the
1325
 * caller having to know the exact id.
1326
 */
1327
struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s,
1328
              unsigned int idf, unsigned int idl)
1329
0
{
1330
0
  struct wpa_bss *bss;
1331
0
  dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
1332
0
    if (bss->id >= idf && bss->id <= idl)
1333
0
      return bss;
1334
0
  }
1335
0
  return NULL;
1336
0
}
1337
1338
1339
/**
1340
 * wpa_bss_get_ie - Fetch a specified information element from a BSS entry
1341
 * @bss: BSS table entry
1342
 * @ie: Information element identitifier (WLAN_EID_*)
1343
 * Returns: Pointer to the information element (id field) or %NULL if not found
1344
 *
1345
 * This function returns the first matching information element in the BSS
1346
 * entry.
1347
 */
1348
const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie)
1349
2.48k
{
1350
2.48k
  return get_ie(wpa_bss_ie_ptr(bss), bss->ie_len, ie);
1351
2.48k
}
1352
1353
1354
/**
1355
 * wpa_bss_get_ie_beacon - Fetch a specified information element from a BSS entry
1356
 * @bss: BSS table entry
1357
 * @ie: Information element identitifier (WLAN_EID_*)
1358
 * Returns: Pointer to the information element (id field) or %NULL if not found
1359
 *
1360
 * This function returns the first matching information element in the BSS
1361
 * entry.
1362
 *
1363
 * This function is like wpa_bss_get_ie(), but uses IE buffer only from Beacon
1364
 * frames instead of either Beacon or Probe Response frames.
1365
 */
1366
const u8 * wpa_bss_get_ie_beacon(const struct wpa_bss *bss, u8 ie)
1367
0
{
1368
0
  const u8 *ies;
1369
1370
0
  if (bss->beacon_ie_len == 0)
1371
0
    return NULL;
1372
1373
0
  ies = wpa_bss_ie_ptr(bss);
1374
0
  ies += bss->ie_len;
1375
0
  return get_ie(ies, bss->beacon_ie_len, ie);
1376
0
}
1377
1378
1379
/**
1380
 * wpa_bss_get_ie_ext - Fetch a specified extended IE from a BSS entry
1381
 * @bss: BSS table entry
1382
 * @ext: Information element extension identifier (WLAN_EID_EXT_*)
1383
 * Returns: Pointer to the information element (id field) or %NULL if not found
1384
 *
1385
 * This function returns the first matching information element in the BSS
1386
 * entry.
1387
 */
1388
const u8 * wpa_bss_get_ie_ext(const struct wpa_bss *bss, u8 ext)
1389
0
{
1390
0
  return get_ie_ext(wpa_bss_ie_ptr(bss), bss->ie_len, ext);
1391
0
}
1392
1393
1394
/**
1395
 * wpa_bss_get_vendor_ie - Fetch a vendor information element from a BSS entry
1396
 * @bss: BSS table entry
1397
 * @vendor_type: Vendor type (four octets starting the IE payload)
1398
 * Returns: Pointer to the information element (id field) or %NULL if not found
1399
 *
1400
 * This function returns the first matching information element in the BSS
1401
 * entry.
1402
 */
1403
const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type)
1404
0
{
1405
0
  const u8 *ies;
1406
0
  const struct element *elem;
1407
1408
0
  ies = wpa_bss_ie_ptr(bss);
1409
1410
0
  for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, bss->ie_len) {
1411
0
    if (elem->datalen >= 4 &&
1412
0
        vendor_type == WPA_GET_BE32(elem->data))
1413
0
      return &elem->id;
1414
0
  }
1415
1416
0
  return NULL;
1417
0
}
1418
1419
1420
/**
1421
 * wpa_bss_get_vendor_ie_beacon - Fetch a vendor information from a BSS entry
1422
 * @bss: BSS table entry
1423
 * @vendor_type: Vendor type (four octets starting the IE payload)
1424
 * Returns: Pointer to the information element (id field) or %NULL if not found
1425
 *
1426
 * This function returns the first matching information element in the BSS
1427
 * entry.
1428
 *
1429
 * This function is like wpa_bss_get_vendor_ie(), but uses IE buffer only
1430
 * from Beacon frames instead of either Beacon or Probe Response frames.
1431
 */
1432
const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss,
1433
          u32 vendor_type)
1434
0
{
1435
0
  const u8 *ies;
1436
0
  const struct element *elem;
1437
1438
0
  if (bss->beacon_ie_len == 0)
1439
0
    return NULL;
1440
1441
0
  ies = wpa_bss_ie_ptr(bss);
1442
0
  ies += bss->ie_len;
1443
1444
0
  for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies,
1445
0
          bss->beacon_ie_len) {
1446
0
    if (elem->datalen >= 4 &&
1447
0
        vendor_type == WPA_GET_BE32(elem->data))
1448
0
      return &elem->id;
1449
0
  }
1450
1451
0
  return NULL;
1452
0
}
1453
1454
1455
/**
1456
 * wpa_bss_get_vendor_ie_multi - Fetch vendor IE data from a BSS entry
1457
 * @bss: BSS table entry
1458
 * @vendor_type: Vendor type (four octets starting the IE payload)
1459
 * Returns: Pointer to the information element payload or %NULL if not found
1460
 *
1461
 * This function returns concatenated payload of possibly fragmented vendor
1462
 * specific information elements in the BSS entry. The caller is responsible for
1463
 * freeing the returned buffer.
1464
 */
1465
struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss,
1466
              u32 vendor_type)
1467
0
{
1468
0
  struct wpabuf *buf;
1469
0
  const u8 *end, *pos;
1470
1471
0
  buf = wpabuf_alloc(bss->ie_len);
1472
0
  if (buf == NULL)
1473
0
    return NULL;
1474
1475
0
  pos = wpa_bss_ie_ptr(bss);
1476
0
  end = pos + bss->ie_len;
1477
1478
0
  while (end - pos > 1) {
1479
0
    u8 ie, len;
1480
1481
0
    ie = pos[0];
1482
0
    len = pos[1];
1483
0
    if (len > end - pos - 2)
1484
0
      break;
1485
0
    pos += 2;
1486
0
    if (ie == WLAN_EID_VENDOR_SPECIFIC && len >= 4 &&
1487
0
        vendor_type == WPA_GET_BE32(pos))
1488
0
      wpabuf_put_data(buf, pos + 4, len - 4);
1489
0
    pos += len;
1490
0
  }
1491
1492
0
  if (wpabuf_len(buf) == 0) {
1493
0
    wpabuf_free(buf);
1494
0
    buf = NULL;
1495
0
  }
1496
1497
0
  return buf;
1498
0
}
1499
1500
1501
/**
1502
 * wpa_bss_get_vendor_ie_multi_beacon - Fetch vendor IE data from a BSS entry
1503
 * @bss: BSS table entry
1504
 * @vendor_type: Vendor type (four octets starting the IE payload)
1505
 * Returns: Pointer to the information element payload or %NULL if not found
1506
 *
1507
 * This function returns concatenated payload of possibly fragmented vendor
1508
 * specific information elements in the BSS entry. The caller is responsible for
1509
 * freeing the returned buffer.
1510
 *
1511
 * This function is like wpa_bss_get_vendor_ie_multi(), but uses IE buffer only
1512
 * from Beacon frames instead of either Beacon or Probe Response frames.
1513
 */
1514
struct wpabuf * wpa_bss_get_vendor_ie_multi_beacon(const struct wpa_bss *bss,
1515
               u32 vendor_type)
1516
0
{
1517
0
  struct wpabuf *buf;
1518
0
  const u8 *end, *pos;
1519
1520
0
  buf = wpabuf_alloc(bss->beacon_ie_len);
1521
0
  if (buf == NULL)
1522
0
    return NULL;
1523
1524
0
  pos = wpa_bss_ie_ptr(bss);
1525
0
  pos += bss->ie_len;
1526
0
  end = pos + bss->beacon_ie_len;
1527
1528
0
  while (end - pos > 1) {
1529
0
    u8 id, len;
1530
1531
0
    id = *pos++;
1532
0
    len = *pos++;
1533
0
    if (len > end - pos)
1534
0
      break;
1535
0
    if (id == WLAN_EID_VENDOR_SPECIFIC && len >= 4 &&
1536
0
        vendor_type == WPA_GET_BE32(pos))
1537
0
      wpabuf_put_data(buf, pos + 4, len - 4);
1538
0
    pos += len;
1539
0
  }
1540
1541
0
  if (wpabuf_len(buf) == 0) {
1542
0
    wpabuf_free(buf);
1543
0
    buf = NULL;
1544
0
  }
1545
1546
0
  return buf;
1547
0
}
1548
1549
1550
/**
1551
 * wpa_bss_get_max_rate - Get maximum legacy TX rate supported in a BSS
1552
 * @bss: BSS table entry
1553
 * Returns: Maximum legacy rate in units of 500 kbps
1554
 */
1555
int wpa_bss_get_max_rate(const struct wpa_bss *bss)
1556
0
{
1557
0
  int rate = 0;
1558
0
  const u8 *ie;
1559
0
  int i;
1560
1561
0
  ie = wpa_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
1562
0
  for (i = 0; ie && i < ie[1]; i++) {
1563
0
    if ((ie[i + 2] & 0x7f) > rate)
1564
0
      rate = ie[i + 2] & 0x7f;
1565
0
  }
1566
1567
0
  ie = wpa_bss_get_ie(bss, WLAN_EID_EXT_SUPP_RATES);
1568
0
  for (i = 0; ie && i < ie[1]; i++) {
1569
0
    if ((ie[i + 2] & 0x7f) > rate)
1570
0
      rate = ie[i + 2] & 0x7f;
1571
0
  }
1572
1573
0
  return rate;
1574
0
}
1575
1576
1577
/**
1578
 * wpa_bss_get_bit_rates - Get legacy TX rates supported in a BSS
1579
 * @bss: BSS table entry
1580
 * @rates: Buffer for returning a pointer to the rates list (units of 500 kbps)
1581
 * Returns: number of legacy TX rates or -1 on failure
1582
 *
1583
 * The caller is responsible for freeing the returned buffer with os_free() in
1584
 * case of success.
1585
 */
1586
int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates)
1587
0
{
1588
0
  const u8 *ie, *ie2;
1589
0
  int i, j;
1590
0
  unsigned int len;
1591
0
  u8 *r;
1592
1593
0
  ie = wpa_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
1594
0
  ie2 = wpa_bss_get_ie(bss, WLAN_EID_EXT_SUPP_RATES);
1595
1596
0
  len = (ie ? ie[1] : 0) + (ie2 ? ie2[1] : 0);
1597
1598
0
  r = os_malloc(len);
1599
0
  if (!r)
1600
0
    return -1;
1601
1602
0
  for (i = 0; ie && i < ie[1]; i++)
1603
0
    r[i] = ie[i + 2] & 0x7f;
1604
1605
0
  for (j = 0; ie2 && j < ie2[1]; j++)
1606
0
    r[i + j] = ie2[j + 2] & 0x7f;
1607
1608
0
  *rates = r;
1609
0
  return len;
1610
0
}
1611
1612
1613
#ifdef CONFIG_FILS
1614
const u8 * wpa_bss_get_fils_cache_id(const struct wpa_bss *bss)
1615
{
1616
  const u8 *ie;
1617
1618
  if (bss) {
1619
    ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
1620
    if (ie && ie[1] >= 4 && WPA_GET_LE16(ie + 2) & BIT(7))
1621
      return ie + 4;
1622
  }
1623
1624
  return NULL;
1625
}
1626
#endif /* CONFIG_FILS */
1627
1628
1629
int wpa_bss_ext_capab(const struct wpa_bss *bss, unsigned int capab)
1630
0
{
1631
0
  if (!bss)
1632
0
    return 0;
1633
0
  return ieee802_11_ext_capab(wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB),
1634
0
            capab);
1635
0
}
1636
1637
1638
static void
1639
wpa_bss_parse_ml_rnr_ap_info(struct wpa_supplicant *wpa_s,
1640
           struct wpa_bss *bss, u8 mbssid_idx,
1641
           const struct ieee80211_neighbor_ap_info *ap_info,
1642
           size_t len, u16 *seen, u16 *missing,
1643
           struct wpa_ssid *ssid)
1644
0
{
1645
0
  const u8 *pos, *end;
1646
0
  const u8 *mld_params;
1647
0
  u8 count, mld_params_offset;
1648
0
  u8 i, type, link_id;
1649
1650
0
  count = RNR_TBTT_INFO_COUNT_VAL(ap_info->tbtt_info_hdr) + 1;
1651
0
  type = ap_info->tbtt_info_hdr & RNR_TBTT_INFO_HDR_TYPE_MSK;
1652
1653
  /* MLD information is at offset 13 or at start */
1654
0
  if (type == 0 && ap_info->tbtt_info_len >= RNR_TBTT_INFO_MLD_LEN) {
1655
    /* MLD info is appended */
1656
0
    mld_params_offset = RNR_TBTT_INFO_LEN;
1657
0
  } else {
1658
    /* TODO: Support NSTR AP */
1659
0
    return;
1660
0
  }
1661
1662
0
  pos = (const u8 *) ap_info;
1663
0
  end = pos + len;
1664
0
  pos += sizeof(*ap_info);
1665
1666
0
  for (i = 0; i < count; i++, pos += ap_info->tbtt_info_len) {
1667
0
    if (end - pos < ap_info->tbtt_info_len)
1668
0
      break;
1669
1670
0
    mld_params = pos + mld_params_offset;
1671
1672
0
    link_id = *(mld_params + 1) & EHT_ML_LINK_ID_MSK;
1673
0
    if (link_id >= MAX_NUM_MLD_LINKS)
1674
0
      continue;
1675
1676
0
    if (*mld_params != mbssid_idx) {
1677
0
      wpa_printf(MSG_DEBUG,
1678
0
           "MLD: Reported link not part of MLD");
1679
0
    } else if (!(BIT(link_id) & *seen)) {
1680
0
      struct wpa_bss *neigh_bss;
1681
1682
0
      if (ssid && ssid->ssid_len)
1683
0
        neigh_bss = wpa_bss_get(wpa_s, pos + 1,
1684
0
              ssid->ssid,
1685
0
              ssid->ssid_len);
1686
0
      else
1687
0
        neigh_bss = wpa_bss_get_bssid(wpa_s, pos + 1);
1688
1689
0
      *seen |= BIT(link_id);
1690
0
      wpa_printf(MSG_DEBUG, "MLD: mld ID=%u, link ID=%u",
1691
0
           *mld_params, link_id);
1692
1693
0
      if (!neigh_bss) {
1694
0
        *missing |= BIT(link_id);
1695
0
      } else if ((!ssid ||
1696
0
            wpa_scan_res_match(wpa_s, 0, neigh_bss,
1697
0
                   ssid, 1, 0, true)) &&
1698
0
           !wpa_bssid_ignore_is_listed(
1699
0
             wpa_s, neigh_bss->bssid)) {
1700
0
        struct mld_link *l;
1701
1702
0
        bss->valid_links |= BIT(link_id);
1703
0
        l = &bss->mld_links[link_id];
1704
0
        os_memcpy(l->bssid, pos + 1, ETH_ALEN);
1705
0
        l->freq = neigh_bss->freq;
1706
0
        l->disabled = mld_params[2] &
1707
0
          RNR_TBTT_INFO_MLD_PARAM2_LINK_DISABLED;
1708
0
      }
1709
0
    }
1710
0
  }
1711
0
}
1712
1713
1714
/**
1715
 * wpa_bss_validate_rsne_ml - Validate RSN IEs (RSNE/RSNOE/RSNO2E) of a BSS
1716
 * @wpa_s: Pointer to wpa_supplicant data
1717
 * @ssid: Network config
1718
 * @bss: BSS table entry
1719
 * Returns: true if the BSS configuration matches local profile and the elements
1720
 * meet MLO requirements, false otherwise
1721
 * @key_mgmt: Pointer to store key management
1722
 * @rsne_type_p: Type of RSNE to validate. If -1 is given, choose as per the
1723
 *  presence of RSN elements (association link); otherwise, validate
1724
 *  against the requested type (other affiliated links).
1725
 */
1726
static bool
1727
wpa_bss_validate_rsne_ml(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
1728
       struct wpa_bss *bss, int *key_mgmt, int *rsne_type_p)
1729
0
{
1730
0
  struct ieee802_11_elems elems;
1731
0
  struct wpa_ie_data wpa_ie;
1732
0
  const u8 *rsne;
1733
0
  size_t rsne_len;
1734
0
  int rsne_type;
1735
0
  const u8 *ies_pos = wpa_bss_ie_ptr(bss);
1736
0
  size_t ies_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len;
1737
1738
0
  if (ieee802_11_parse_elems(ies_pos, ies_len, &elems, 0) ==
1739
0
      ParseFailed) {
1740
0
    wpa_dbg(wpa_s, MSG_DEBUG, "MLD: Failed to parse elements");
1741
0
    return false;
1742
0
  }
1743
1744
0
  if (elems.rsne_override_2 && wpas_rsn_overriding(wpa_s, ssid)) {
1745
0
    rsne = elems.rsne_override_2;
1746
0
    rsne_len = elems.rsne_override_2_len;
1747
0
    rsne_type = 2;
1748
0
  } else if (elems.rsne_override && wpas_rsn_overriding(wpa_s, ssid)) {
1749
0
    rsne = elems.rsne_override;
1750
0
    rsne_len = elems.rsne_override_len;
1751
0
    rsne_type = 1;
1752
0
  } else {
1753
0
    rsne = elems.rsn_ie;
1754
0
    rsne_len = elems.rsn_ie_len;
1755
0
    rsne_type = 0;
1756
0
  }
1757
1758
0
  if (!rsne ||
1759
0
      wpa_parse_wpa_ie(rsne - 2, 2 + rsne_len, &wpa_ie)) {
1760
0
    wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RSN element");
1761
0
    return false;
1762
0
  }
1763
1764
0
  if (*rsne_type_p != -1 && *rsne_type_p != rsne_type) {
1765
0
    wpa_dbg(wpa_s, MSG_DEBUG,
1766
0
      "MLD: No matching RSN element (RSNO mismatch)");
1767
0
    return false;
1768
0
  }
1769
1770
0
  if (!(wpa_ie.capabilities & WPA_CAPABILITY_MFPC) ||
1771
0
      wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION) {
1772
0
    wpa_dbg(wpa_s, MSG_DEBUG,
1773
0
      "MLD: No management frame protection");
1774
0
    return false;
1775
0
  }
1776
1777
0
  wpa_ie.key_mgmt &= ~(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK |
1778
0
           WPA_KEY_MGMT_PSK_SHA256);
1779
0
  wpa_dbg(wpa_s, MSG_DEBUG, "MLD: key_mgmt=0x%x", wpa_ie.key_mgmt);
1780
1781
0
  if (key_mgmt)
1782
0
    *key_mgmt = wpa_ie.key_mgmt;
1783
1784
0
  *rsne_type_p = rsne_type;
1785
1786
0
  return !!(wpa_ie.key_mgmt & ssid->key_mgmt);
1787
0
}
1788
1789
1790
/**
1791
 * wpa_bss_parse_basic_ml_element - Parse the Basic Multi-Link element
1792
 * @wpa_s: Pointer to wpa_supplicant data
1793
 * @bss: BSS table entry
1794
 * @mld_addr: AP MLD address (or %NULL)
1795
 * @link_info: Array to store link information (or %NULL),
1796
 *   should be initialized and #MAX_NUM_MLD_LINKS elements long
1797
 * @missing_links: Result bitmask of links that were not discovered (or %NULL)
1798
 * @ssid: Target SSID (or %NULL)
1799
 * @ap_mld_id: On return would hold the corresponding AP MLD ID (or %NULL)
1800
 * Returns: 0 on success or -1 for non-MLD or parsing failures
1801
 *
1802
 * Parses the Basic Multi-Link element of the BSS into @link_info using the scan
1803
 * information stored in the wpa_supplicant data to fill in information for
1804
 * links where possible. The @missing_links out parameter will contain any links
1805
 * for which no corresponding BSS was found.
1806
 */
1807
int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
1808
           struct wpa_bss *bss,
1809
           u8 *ap_mld_addr,
1810
           u16 *missing_links,
1811
           struct wpa_ssid *ssid,
1812
           u8 *ap_mld_id)
1813
0
{
1814
0
  struct ieee802_11_elems elems;
1815
0
  struct wpabuf *mlbuf;
1816
0
  const struct element *elem;
1817
0
  u8 mbssid_idx = 0;
1818
0
  size_t ml_ie_len;
1819
0
  const struct ieee80211_eht_ml *eht_ml;
1820
0
  const struct eht_ml_basic_common_info *ml_basic_common_info;
1821
0
  u8 i, link_id;
1822
0
  const u16 control_mask =
1823
0
    MULTI_LINK_CONTROL_TYPE_MASK |
1824
0
    BASIC_MULTI_LINK_CTRL_PRES_LINK_ID |
1825
0
    BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT |
1826
0
    BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA;
1827
0
  const u16 control =
1828
0
    MULTI_LINK_CONTROL_TYPE_BASIC |
1829
0
    BASIC_MULTI_LINK_CTRL_PRES_LINK_ID |
1830
0
    BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT |
1831
0
    BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA;
1832
0
  u16 missing = 0;
1833
0
  u16 seen;
1834
0
  const u8 *ies_pos = wpa_bss_ie_ptr(bss);
1835
0
  size_t ies_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len;
1836
0
  int ret = -1, rsne_type, key_mgmt;
1837
0
  struct mld_link *l;
1838
0
  u16 valid_links;
1839
1840
0
  if (ieee802_11_parse_elems(ies_pos, ies_len, &elems, 1) ==
1841
0
      ParseFailed) {
1842
0
    wpa_dbg(wpa_s, MSG_DEBUG, "MLD: Failed to parse elements");
1843
0
    return ret;
1844
0
  }
1845
1846
0
  mlbuf = ieee802_11_defrag(elems.basic_mle, elems.basic_mle_len, true);
1847
0
  if (!mlbuf) {
1848
0
    wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No Multi-Link element");
1849
0
    return ret;
1850
0
  }
1851
1852
0
  ml_ie_len = wpabuf_len(mlbuf);
1853
1854
0
  rsne_type = -1;
1855
0
  if (ssid &&
1856
0
      !wpa_bss_validate_rsne_ml(wpa_s, ssid, bss, &key_mgmt,
1857
0
              &rsne_type)) {
1858
0
    wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No valid key management");
1859
0
    goto out;
1860
0
  }
1861
1862
  /*
1863
   * for ext ID + 2 control + common info len + MLD address +
1864
   * link info
1865
   */
1866
0
  if (ml_ie_len < 2UL + 1UL + ETH_ALEN + 1UL)
1867
0
    goto out;
1868
1869
0
  eht_ml = (const struct ieee80211_eht_ml *) wpabuf_head(mlbuf);
1870
0
  if ((le_to_host16(eht_ml->ml_control) & control_mask) != control) {
1871
0
    wpa_printf(MSG_DEBUG,
1872
0
         "MLD: Unexpected Multi-Link element control=0x%x (mask 0x%x expected 0x%x)",
1873
0
         le_to_host16(eht_ml->ml_control), control_mask,
1874
0
         control);
1875
0
    goto out;
1876
0
  }
1877
1878
0
  ml_basic_common_info =
1879
0
    (const struct eht_ml_basic_common_info *) eht_ml->variable;
1880
1881
  /* Common info length should be valid */
1882
0
  if (ml_basic_common_info->len < ETH_ALEN + 1UL)
1883
0
    goto out;
1884
1885
  /* Get the MLD address and MLD link ID */
1886
0
  if (ap_mld_addr)
1887
0
    os_memcpy(ap_mld_addr, ml_basic_common_info->mld_addr,
1888
0
        ETH_ALEN);
1889
1890
0
  link_id = ml_basic_common_info->variable[0] & EHT_ML_LINK_ID_MSK;
1891
1892
0
  bss->mld_link_id = link_id;
1893
0
  seen = bss->valid_links = BIT(link_id);
1894
1895
0
  l = &bss->mld_links[link_id];
1896
0
  os_memcpy(l->bssid, bss->bssid, ETH_ALEN);
1897
0
  l->freq = bss->freq;
1898
1899
1900
  /*
1901
   * The AP MLD ID in the RNR corresponds to the MBSSID index, see
1902
   * IEEE P802.11be/D4.0, 9.4.2.169.2 (Neighbor AP Information field).
1903
   *
1904
   * For the transmitting BSSID it is clear that both the MBSSID index
1905
   * and the AP MLD ID in the RNR are zero.
1906
   *
1907
   * For nontransmitted BSSIDs we will have a BSS generated from the
1908
   * MBSSID element(s) using inheritance rules. Included in the elements
1909
   * is the MBSSID Index Element. The RNR is copied from the Beacon/Probe
1910
   * Response frame that was send by the transmitting BSSID. As such, the
1911
   * reported AP MLD ID in the RNR will match the value in the MBSSID
1912
   * Index Element.
1913
   */
1914
0
  elem = (const struct element *)
1915
0
    wpa_bss_get_ie(bss, WLAN_EID_MULTIPLE_BSSID_INDEX);
1916
0
  if (elem && elem->datalen >= 1)
1917
0
    mbssid_idx = elem->data[0];
1918
1919
0
  for_each_element_id(elem, WLAN_EID_REDUCED_NEIGHBOR_REPORT,
1920
0
          wpa_bss_ie_ptr(bss),
1921
0
          bss->ie_len ? bss->ie_len : bss->beacon_ie_len) {
1922
0
    const struct ieee80211_neighbor_ap_info *ap_info;
1923
0
    const u8 *pos = elem->data;
1924
0
    size_t len = elem->datalen;
1925
1926
    /* RNR IE may contain more than one Neighbor AP Info */
1927
0
    while (sizeof(*ap_info) <= len) {
1928
0
      size_t ap_info_len = sizeof(*ap_info);
1929
0
      u8 count;
1930
1931
0
      ap_info = (const struct ieee80211_neighbor_ap_info *)
1932
0
        pos;
1933
0
      count = RNR_TBTT_INFO_COUNT_VAL(ap_info->tbtt_info_hdr) + 1;
1934
0
      ap_info_len += count * ap_info->tbtt_info_len;
1935
1936
0
      if (ap_info_len > len)
1937
0
        goto out;
1938
1939
0
      wpa_bss_parse_ml_rnr_ap_info(wpa_s, bss, mbssid_idx,
1940
0
                 ap_info, ap_info_len,
1941
0
                 &seen, &missing, ssid);
1942
1943
0
      pos += ap_info_len;
1944
0
      len -= ap_info_len;
1945
0
    }
1946
0
  }
1947
1948
0
  wpa_printf(MSG_DEBUG, "MLD: valid_links=%04hx (unresolved: 0x%04hx)",
1949
0
       bss->valid_links, missing);
1950
1951
0
  valid_links = bss->valid_links;
1952
0
  for_each_link(bss->valid_links, i) {
1953
0
    struct wpa_bss *neigh_bss;
1954
0
    int neigh_key_mgmt;
1955
1956
0
    if (!ssid)
1957
0
      break;
1958
1959
0
    if (i == link_id)
1960
0
      continue;
1961
1962
0
    neigh_bss = wpa_bss_get_bssid(wpa_s, bss->mld_links[i].bssid);
1963
0
    if (!neigh_bss) /* cannot be NULL at this point */
1964
0
      continue;
1965
1966
    /* As per IEEE P802.11be/D7.0, 12.6.2 (RSNA selection), all APs
1967
     * affiliated with an AP MLD shall advertise at least one common
1968
     * AKM suite selector in the AKM Suite List field of an RSNE or
1969
     * RSNXE. Discard links that do not have compatibility
1970
     * configuration with the association link.
1971
     */
1972
0
    if (!wpa_bss_validate_rsne_ml(wpa_s, ssid, neigh_bss,
1973
0
                &neigh_key_mgmt, &rsne_type) ||
1974
0
        !(key_mgmt & neigh_key_mgmt)) {
1975
0
      wpa_printf(MSG_DEBUG,
1976
0
           "MLD: Discard link %u due to RSN parameter mismatch",
1977
0
           i);
1978
0
      valid_links &= ~BIT(i);
1979
0
      continue;
1980
0
    }
1981
0
  }
1982
1983
0
  if (valid_links != bss->valid_links) {
1984
0
    wpa_printf(MSG_DEBUG, "MLD: Updated valid links=%04hx",
1985
0
         valid_links);
1986
0
    bss->valid_links = valid_links;
1987
0
  }
1988
1989
0
  for_each_link(bss->valid_links, i) {
1990
0
    wpa_printf(MSG_DEBUG, "MLD: link=%u, bssid=" MACSTR,
1991
0
         i, MAC2STR(bss->mld_links[i].bssid));
1992
0
  }
1993
1994
0
  if (missing_links)
1995
0
    *missing_links = missing;
1996
1997
0
  if (ap_mld_id)
1998
0
    *ap_mld_id = mbssid_idx;
1999
2000
0
  ret = 0;
2001
0
out:
2002
0
  wpabuf_free(mlbuf);
2003
0
  return ret;
2004
0
}
2005
2006
2007
/*
2008
 * wpa_bss_parse_reconf_ml_element - Parse the Reconfiguration ML element
2009
 * @wpa_s: Pointer to wpa_supplicant data
2010
 * @bss: BSS table entry
2011
 * Returns: The bitmap of links that are going to be removed
2012
 */
2013
u16 wpa_bss_parse_reconf_ml_element(struct wpa_supplicant *wpa_s,
2014
            struct wpa_bss *bss)
2015
0
{
2016
0
  struct ieee802_11_elems elems;
2017
0
  struct wpabuf *mlbuf;
2018
0
  const u8 *pos = wpa_bss_ie_ptr(bss);
2019
0
  size_t len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len;
2020
0
  const struct ieee80211_eht_ml *ml;
2021
0
  const struct eht_ml_reconf_common_info *common_info;
2022
0
  u16 removed_links = 0;
2023
0
  u8 expected_ml_common_len;
2024
2025
0
  if (ieee802_11_parse_elems(pos, len, &elems, 1) == ParseFailed)
2026
0
    return 0;
2027
2028
0
  if (!elems.reconf_mle || !elems.reconf_mle_len)
2029
0
    return 0;
2030
2031
0
  mlbuf = ieee802_11_defrag(elems.reconf_mle, elems.reconf_mle_len, true);
2032
0
  if (!mlbuf)
2033
0
    return 0;
2034
2035
0
  ml = (const struct ieee80211_eht_ml *) wpabuf_head(mlbuf);
2036
0
  len = wpabuf_len(mlbuf);
2037
2038
  /* There must be at least one octet for the Common Info Length subfield
2039
   */
2040
0
  if (len < sizeof(*ml) + 1UL)
2041
0
    goto out;
2042
2043
0
  expected_ml_common_len = 1;
2044
0
  if (le_to_host16(ml->ml_control) &
2045
0
      RECONF_MULTI_LINK_CTRL_PRES_MLD_MAC_ADDR)
2046
0
    expected_ml_common_len += ETH_ALEN;
2047
2048
0
  common_info = (const struct eht_ml_reconf_common_info *) ml->variable;
2049
0
  if (len < sizeof(*ml) + common_info->len) {
2050
0
    wpa_printf(MSG_DEBUG,
2051
0
         "MLD: Unexpected Reconfiguration ML element length: (%zu < %zu)",
2052
0
         len, sizeof(*ml) + common_info->len);
2053
0
    goto out;
2054
0
  }
2055
2056
0
  if (common_info->len < expected_ml_common_len) {
2057
0
    wpa_printf(MSG_DEBUG,
2058
0
         "MLD: Invalid common info len=%u; min expected=%u",
2059
0
         common_info->len, expected_ml_common_len);
2060
0
    goto out;
2061
0
  }
2062
2063
0
  pos = ml->variable + common_info->len;
2064
0
  len -= sizeof(*ml) + common_info->len;
2065
2066
0
  while (len >= 2 + sizeof(struct ieee80211_eht_per_sta_profile)) {
2067
0
    size_t sub_elem_len;
2068
0
    int num_frag_subelems;
2069
2070
0
    num_frag_subelems =
2071
0
      ieee802_11_defrag_mle_subelem(mlbuf, pos,
2072
0
                  &sub_elem_len);
2073
0
    if (num_frag_subelems < 0) {
2074
0
      wpa_printf(MSG_DEBUG,
2075
0
           "MLD: Failed to parse MLE subelem");
2076
0
      break;
2077
0
    }
2078
2079
0
    len -= num_frag_subelems * 2;
2080
2081
0
    if (2 + sub_elem_len > len) {
2082
0
      wpa_printf(MSG_DEBUG,
2083
0
           "MLD: Invalid link info len: %zu %zu",
2084
0
           2 + sub_elem_len, len);
2085
0
      goto out;
2086
0
    }
2087
2088
0
    if  (*pos == EHT_ML_SUB_ELEM_PER_STA_PROFILE &&
2089
0
         sub_elem_len >= 2) {
2090
0
      const struct ieee80211_eht_per_sta_profile *sta_prof =
2091
0
        (const struct ieee80211_eht_per_sta_profile *)
2092
0
        (pos + 2);
2093
0
      u16 control = le_to_host16(sta_prof->sta_control);
2094
0
      u8 link_id;
2095
2096
0
      link_id = control & EHT_PER_STA_RECONF_CTRL_LINK_ID_MSK;
2097
0
      removed_links |= BIT(link_id);
2098
0
    }
2099
2100
0
    pos += 2 + sub_elem_len;
2101
0
    len -= 2 + sub_elem_len;
2102
0
  }
2103
2104
0
  wpa_printf(MSG_DEBUG, "MLD: Reconfiguration: removed_links=0x%x",
2105
0
       removed_links);
2106
0
out:
2107
0
  wpabuf_free(mlbuf);
2108
0
  return removed_links;
2109
0
}
2110
2111
2112
#ifndef CONFIG_NO_WPA
2113
2114
static bool wpa_bss_supported_cipher(struct wpa_supplicant *wpa_s,
2115
             int pairwise_cipher)
2116
0
{
2117
0
  if (!wpa_s->drv_enc)
2118
0
    return true;
2119
2120
0
  if ((pairwise_cipher & WPA_CIPHER_CCMP) &&
2121
0
      (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_CCMP))
2122
0
    return true;
2123
2124
0
  if ((pairwise_cipher & WPA_CIPHER_GCMP) &&
2125
0
      (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_GCMP))
2126
0
    return true;
2127
2128
0
  if ((pairwise_cipher & WPA_CIPHER_CCMP_256) &&
2129
0
      (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_CCMP_256))
2130
0
    return true;
2131
2132
0
  if ((pairwise_cipher & WPA_CIPHER_GCMP_256) &&
2133
0
      (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_GCMP_256))
2134
0
    return true;
2135
2136
0
  return false;
2137
0
}
2138
2139
2140
static bool wpa_bss_supported_key_mgmt(struct wpa_supplicant *wpa_s,
2141
               int key_mgmt)
2142
0
{
2143
0
  if (!wpa_s->drv_key_mgmt)
2144
0
    return true;
2145
2146
0
  if ((key_mgmt & WPA_KEY_MGMT_IEEE8021X) &&
2147
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA2))
2148
0
    return true;
2149
0
  if ((key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) &&
2150
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_802_1X_SHA256))
2151
0
    return true;
2152
0
  if ((key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) &&
2153
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT))
2154
0
    return true;
2155
0
  if ((key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
2156
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_802_1X_SHA384))
2157
0
    return true;
2158
0
  if ((key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) &&
2159
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B))
2160
0
    return true;
2161
0
  if ((key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) &&
2162
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192))
2163
0
    return true;
2164
0
  if ((key_mgmt & WPA_KEY_MGMT_PSK) &&
2165
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK))
2166
0
    return true;
2167
0
  if ((key_mgmt & WPA_KEY_MGMT_FT_PSK) &&
2168
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK))
2169
0
    return true;
2170
0
  if ((key_mgmt & WPA_KEY_MGMT_PSK_SHA256) &&
2171
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256))
2172
0
    return true;
2173
0
  if ((key_mgmt & WPA_KEY_MGMT_SAE) &&
2174
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE))
2175
0
    return true;
2176
0
  if ((key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) &&
2177
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE_EXT_KEY))
2178
0
    return true;
2179
0
  if ((key_mgmt & WPA_KEY_MGMT_FT_SAE) &&
2180
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE))
2181
0
    return true;
2182
0
  if ((key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) &&
2183
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE_EXT_KEY))
2184
0
    return true;
2185
0
  if ((key_mgmt & WPA_KEY_MGMT_OWE) &&
2186
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE))
2187
0
    return true;
2188
0
  if ((key_mgmt & WPA_KEY_MGMT_DPP) &&
2189
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP))
2190
0
    return true;
2191
0
  if ((key_mgmt & WPA_KEY_MGMT_FILS_SHA256) &&
2192
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256))
2193
0
    return true;
2194
0
  if ((key_mgmt & WPA_KEY_MGMT_FILS_SHA384) &&
2195
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384))
2196
0
    return true;
2197
0
  if ((key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) &&
2198
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256))
2199
0
    return true;
2200
0
  if ((key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) &&
2201
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384))
2202
0
    return true;
2203
2204
0
  return false;
2205
0
}
2206
2207
2208
static bool wpa_bss_supported_rsne(struct wpa_supplicant *wpa_s,
2209
           struct wpa_ssid *ssid, const u8 *ie)
2210
0
{
2211
0
  struct wpa_ie_data data;
2212
2213
0
  if (wpa_parse_wpa_ie_rsn(ie, 2 + ie[1], &data) < 0)
2214
0
    return false;
2215
2216
  /* Check that there is a supported AKM and pairwise cipher based on
2217
   * overall capabilities */
2218
0
  if (!data.pairwise_cipher || !data.key_mgmt)
2219
0
    return false;
2220
2221
0
  if (wpa_s->drv_capa_known) {
2222
0
    if (!wpa_bss_supported_cipher(wpa_s, data.pairwise_cipher) ||
2223
0
        !wpa_bss_supported_key_mgmt(wpa_s, data.key_mgmt))
2224
0
      return false;
2225
0
  }
2226
2227
0
  if (ssid) {
2228
    /* Check that there is a supported AKM and pairwise cipher
2229
     * based on the specific network profile. */
2230
0
    if ((ssid->pairwise_cipher & data.pairwise_cipher) == 0)
2231
0
      return false;
2232
0
    if ((ssid->key_mgmt & data.key_mgmt) == 0)
2233
0
      return false;
2234
0
  }
2235
2236
0
  return true;
2237
0
}
2238
2239
#endif /* CONFIG_NO_WPA */
2240
2241
2242
const u8 * wpa_bss_get_rsne(struct wpa_supplicant *wpa_s,
2243
          const struct wpa_bss *bss, struct wpa_ssid *ssid,
2244
          bool mlo)
2245
0
{
2246
0
#ifndef CONFIG_NO_WPA
2247
0
  const u8 *ie;
2248
2249
0
  if (wpas_rsn_overriding(wpa_s, ssid)) {
2250
0
    if (!ssid)
2251
0
      ssid = wpa_s->current_ssid;
2252
2253
    /* MLO cases for RSN overriding are required to use RSNE
2254
     * Override 2 element and RSNXE Override element together. */
2255
0
    ie = wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
2256
0
    if (mlo && ie &&
2257
0
        !wpa_bss_get_vendor_ie(bss,
2258
0
             RSNXE_OVERRIDE_IE_VENDOR_TYPE)) {
2259
0
      wpa_printf(MSG_DEBUG, "BSS " MACSTR
2260
0
           " advertises RSNE Override 2 element without RSNXE Override element - ignore RSNE Override 2 element for MLO",
2261
0
           MAC2STR(bss->bssid));
2262
0
    } else if (ie && wpa_bss_supported_rsne(wpa_s, ssid, ie)) {
2263
0
      return ie;
2264
0
    }
2265
2266
0
    if (!mlo) {
2267
0
      ie = wpa_bss_get_vendor_ie(
2268
0
        bss, RSNE_OVERRIDE_IE_VENDOR_TYPE);
2269
0
      if (ie && wpa_bss_supported_rsne(wpa_s, ssid, ie))
2270
0
        return ie;
2271
0
    }
2272
0
  }
2273
0
#endif /* CONFIG_NO_WPA */
2274
2275
0
  return wpa_bss_get_ie(bss, WLAN_EID_RSN);
2276
0
}
2277
2278
2279
const u8 * wpa_bss_get_rsnxe(struct wpa_supplicant *wpa_s,
2280
           const struct wpa_bss *bss, struct wpa_ssid *ssid,
2281
           bool mlo)
2282
0
{
2283
0
  const u8 *ie;
2284
2285
0
  if (wpas_rsn_overriding(wpa_s, ssid)) {
2286
0
    ie = wpa_bss_get_vendor_ie(bss, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
2287
0
    if (ie) {
2288
0
      const u8 *tmp;
2289
2290
0
      tmp = wpa_bss_get_rsne(wpa_s, bss, ssid, mlo);
2291
0
      if (!tmp || tmp[0] == WLAN_EID_RSN) {
2292
        /* An acceptable RSNE override element was not
2293
         * found, so need to ignore RSNXE overriding. */
2294
0
        goto out;
2295
0
      }
2296
2297
0
      return ie;
2298
0
    }
2299
2300
    /* MLO cases for RSN overriding are required to use RSNE
2301
     * Override 2 element and RSNXE Override element together. */
2302
0
    if (mlo && wpa_bss_get_vendor_ie(
2303
0
          bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE)) {
2304
0
      wpa_printf(MSG_DEBUG, "BSS " MACSTR
2305
0
           " advertises RSNXE Override element without RSNE Override 2 element - ignore RSNXE Override element for MLO",
2306
0
           MAC2STR(bss->bssid));
2307
0
      goto out;
2308
0
    }
2309
0
  }
2310
2311
0
out:
2312
0
  return wpa_bss_get_ie(bss, WLAN_EID_RSNX);
2313
0
}