Coverage Report

Created: 2026-02-26 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hostap/wpa_supplicant/bss.c
Line
Count
Source
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
  char *pos, *end;
594
0
  int ret = 0;
595
596
0
  bss = os_zalloc(sizeof(*bss) + res->ie_len + res->beacon_ie_len);
597
0
  if (bss == NULL)
598
0
    return NULL;
599
0
  bss->id = wpa_s->bss_next_id++;
600
0
  bss->last_update_idx = wpa_s->bss_update_idx;
601
0
  wpa_bss_copy_res(bss, res, fetch_time);
602
0
  os_memcpy(bss->ssid, ssid, ssid_len);
603
0
  bss->ssid_len = ssid_len;
604
0
  bss->ie_len = res->ie_len;
605
0
  bss->beacon_ie_len = res->beacon_ie_len;
606
0
  os_memcpy(bss->ies, res + 1, res->ie_len + res->beacon_ie_len);
607
0
  wpa_bss_set_hessid(bss);
608
609
0
  wpa_bss_parse_basic_ml_element(wpa_s, bss);
610
611
0
  if (wpa_s->num_bss + 1 > wpa_s->conf->bss_max_count &&
612
0
      wpa_bss_remove_oldest(wpa_s) != 0) {
613
0
    wpa_printf(MSG_ERROR, "Increasing the MAX BSS count to %d "
614
0
         "because all BSSes are in use. We should normally "
615
0
         "not get here!", (int) wpa_s->num_bss + 1);
616
0
    wpa_s->conf->bss_max_count = wpa_s->num_bss + 1;
617
0
  }
618
619
0
  dl_list_add_tail(&wpa_s->bss, &bss->list);
620
0
  dl_list_add_tail(&wpa_s->bss_id, &bss->list_id);
621
0
  wpa_s->num_bss++;
622
623
0
  extra[0] = '\0';
624
0
  pos = extra;
625
0
  end = pos + sizeof(extra);
626
0
  if (!is_zero_ether_addr(bss->hessid))
627
0
    ret = os_snprintf(pos, end - pos, " HESSID " MACSTR,
628
0
          MAC2STR(bss->hessid));
629
630
0
  if (!is_zero_ether_addr(bss->mld_addr) &&
631
0
      !os_snprintf_error(end - pos, ret)) {
632
0
    pos += ret;
633
0
    ret = os_snprintf(pos, end - pos, " MLD ADDR " MACSTR,
634
0
          MAC2STR(bss->mld_addr));
635
0
  }
636
637
0
  wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Add new id %u BSSID " MACSTR
638
0
    " SSID '%s' freq %d%s",
639
0
    bss->id, MAC2STR(bss->bssid), wpa_ssid_txt(ssid, ssid_len),
640
0
    bss->freq, extra);
641
0
  wpas_notify_bss_added(wpa_s, bss->bssid, bss->id);
642
0
  return bss;
643
0
}
644
645
646
static int are_ies_equal(const struct wpa_bss *old,
647
       const struct wpa_scan_res *new_res, u32 ie)
648
0
{
649
0
  const u8 *old_ie, *new_ie;
650
0
  struct wpabuf *old_ie_buff = NULL;
651
0
  struct wpabuf *new_ie_buff = NULL;
652
0
  int new_ie_len, old_ie_len, ret, is_multi;
653
654
0
  switch (ie) {
655
0
  case WPA_IE_VENDOR_TYPE:
656
0
    old_ie = wpa_bss_get_vendor_ie(old, ie);
657
0
    new_ie = wpa_scan_get_vendor_ie(new_res, ie);
658
0
    is_multi = 0;
659
0
    break;
660
0
  case WPS_IE_VENDOR_TYPE:
661
0
    old_ie_buff = wpa_bss_get_vendor_ie_multi(old, ie);
662
0
    new_ie_buff = wpa_scan_get_vendor_ie_multi(new_res, ie);
663
0
    is_multi = 1;
664
0
    break;
665
0
  case WLAN_EID_RSN:
666
0
  case WLAN_EID_SUPP_RATES:
667
0
  case WLAN_EID_EXT_SUPP_RATES:
668
0
    old_ie = wpa_bss_get_ie(old, ie);
669
0
    new_ie = wpa_scan_get_ie(new_res, ie);
670
0
    is_multi = 0;
671
0
    break;
672
0
  default:
673
0
    wpa_printf(MSG_DEBUG, "bss: %s: cannot compare IEs", __func__);
674
0
    return 0;
675
0
  }
676
677
0
  if (is_multi) {
678
    /* in case of multiple IEs stored in buffer */
679
0
    old_ie = old_ie_buff ? wpabuf_head_u8(old_ie_buff) : NULL;
680
0
    new_ie = new_ie_buff ? wpabuf_head_u8(new_ie_buff) : NULL;
681
0
    old_ie_len = old_ie_buff ? wpabuf_len(old_ie_buff) : 0;
682
0
    new_ie_len = new_ie_buff ? wpabuf_len(new_ie_buff) : 0;
683
0
  } else {
684
    /* in case of single IE */
685
0
    old_ie_len = old_ie ? old_ie[1] + 2 : 0;
686
0
    new_ie_len = new_ie ? new_ie[1] + 2 : 0;
687
0
  }
688
689
0
  if (!old_ie || !new_ie)
690
0
    ret = !old_ie && !new_ie;
691
0
  else
692
0
    ret = (old_ie_len == new_ie_len &&
693
0
           os_memcmp(old_ie, new_ie, old_ie_len) == 0);
694
695
0
  wpabuf_free(old_ie_buff);
696
0
  wpabuf_free(new_ie_buff);
697
698
0
  return ret;
699
0
}
700
701
702
static u32 wpa_bss_compare_res(const struct wpa_bss *old,
703
             const struct wpa_scan_res *new_res)
704
0
{
705
0
  u32 changes = 0;
706
0
  int caps_diff = old->caps ^ new_res->caps;
707
708
0
  if (old->freq != new_res->freq)
709
0
    changes |= WPA_BSS_FREQ_CHANGED_FLAG;
710
711
0
  if (old->level != new_res->level)
712
0
    changes |= WPA_BSS_SIGNAL_CHANGED_FLAG;
713
714
0
  if (caps_diff & IEEE80211_CAP_PRIVACY)
715
0
    changes |= WPA_BSS_PRIVACY_CHANGED_FLAG;
716
717
0
  if (caps_diff & IEEE80211_CAP_IBSS)
718
0
    changes |= WPA_BSS_MODE_CHANGED_FLAG;
719
720
0
  if (old->ie_len == new_res->ie_len &&
721
0
      os_memcmp(wpa_bss_ie_ptr(old), new_res + 1, old->ie_len) == 0)
722
0
    return changes;
723
0
  changes |= WPA_BSS_IES_CHANGED_FLAG;
724
725
0
  if (!are_ies_equal(old, new_res, WPA_IE_VENDOR_TYPE))
726
0
    changes |= WPA_BSS_WPAIE_CHANGED_FLAG;
727
728
0
  if (!are_ies_equal(old, new_res, WLAN_EID_RSN))
729
0
    changes |= WPA_BSS_RSNIE_CHANGED_FLAG;
730
731
0
  if (!are_ies_equal(old, new_res, WPS_IE_VENDOR_TYPE))
732
0
    changes |= WPA_BSS_WPS_CHANGED_FLAG;
733
734
0
  if (!are_ies_equal(old, new_res, WLAN_EID_SUPP_RATES) ||
735
0
      !are_ies_equal(old, new_res, WLAN_EID_EXT_SUPP_RATES))
736
0
    changes |= WPA_BSS_RATES_CHANGED_FLAG;
737
738
0
  return changes;
739
0
}
740
741
742
void notify_bss_changes(struct wpa_supplicant *wpa_s, u32 changes,
743
      const struct wpa_bss *bss)
744
0
{
745
0
  if (changes & WPA_BSS_FREQ_CHANGED_FLAG)
746
0
    wpas_notify_bss_freq_changed(wpa_s, bss->id);
747
748
0
  if (changes & WPA_BSS_SIGNAL_CHANGED_FLAG)
749
0
    wpas_notify_bss_signal_changed(wpa_s, bss->id);
750
751
0
  if (changes & WPA_BSS_PRIVACY_CHANGED_FLAG)
752
0
    wpas_notify_bss_privacy_changed(wpa_s, bss->id);
753
754
0
  if (changes & WPA_BSS_MODE_CHANGED_FLAG)
755
0
    wpas_notify_bss_mode_changed(wpa_s, bss->id);
756
757
0
  if (changes & WPA_BSS_WPAIE_CHANGED_FLAG)
758
0
    wpas_notify_bss_wpaie_changed(wpa_s, bss->id);
759
760
0
  if (changes & WPA_BSS_RSNIE_CHANGED_FLAG)
761
0
    wpas_notify_bss_rsnie_changed(wpa_s, bss->id);
762
763
0
  if (changes & WPA_BSS_WPS_CHANGED_FLAG)
764
0
    wpas_notify_bss_wps_changed(wpa_s, bss->id);
765
766
0
  if (changes & WPA_BSS_IES_CHANGED_FLAG)
767
0
    wpas_notify_bss_ies_changed(wpa_s, bss->id);
768
769
0
  if (changes & WPA_BSS_RATES_CHANGED_FLAG)
770
0
    wpas_notify_bss_rates_changed(wpa_s, bss->id);
771
772
0
  wpas_notify_bss_seen(wpa_s, bss->id);
773
0
}
774
775
776
static struct wpa_bss *
777
wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
778
         struct wpa_scan_res *res, struct os_reltime *fetch_time)
779
0
{
780
0
  u32 changes;
781
782
0
  if (bss->last_update_idx == wpa_s->bss_update_idx) {
783
0
    struct os_reltime update_time;
784
785
    /*
786
     * Some drivers (e.g., cfg80211) include multiple BSS entries
787
     * for the same BSS if that BSS's channel changes. The BSS list
788
     * implementation in wpa_supplicant does not do that and we need
789
     * to filter out the obsolete results here to make sure only the
790
     * most current BSS information remains in the table.
791
     */
792
0
    wpa_printf(MSG_DEBUG, "BSS: " MACSTR
793
0
         " has multiple entries in the scan results - select the most current one",
794
0
         MAC2STR(bss->bssid));
795
0
    calculate_update_time(fetch_time, res->age, &update_time);
796
0
    wpa_printf(MSG_DEBUG,
797
0
         "Previous last_update: %u.%06u (freq %d%s)",
798
0
         (unsigned int) bss->last_update.sec,
799
0
         (unsigned int) bss->last_update.usec,
800
0
         bss->freq,
801
0
         (bss->flags & WPA_BSS_ASSOCIATED) ? " assoc" : "");
802
0
    wpa_printf(MSG_DEBUG, "New last_update: %u.%06u (freq %d%s)",
803
0
         (unsigned int) update_time.sec,
804
0
         (unsigned int) update_time.usec,
805
0
         res->freq,
806
0
         (res->flags & WPA_SCAN_ASSOCIATED) ? " assoc" : "");
807
0
    if ((bss->flags & WPA_BSS_ASSOCIATED) ||
808
0
        (!(res->flags & WPA_SCAN_ASSOCIATED) &&
809
0
         !os_reltime_before(&bss->last_update, &update_time))) {
810
0
      wpa_printf(MSG_DEBUG,
811
0
           "Ignore this BSS entry since the previous update looks more current");
812
0
      return bss;
813
0
    }
814
0
    wpa_printf(MSG_DEBUG,
815
0
         "Accept this BSS entry since it looks more current than the previous update");
816
0
  }
817
818
0
  changes = wpa_bss_compare_res(bss, res);
819
0
  if (changes & WPA_BSS_FREQ_CHANGED_FLAG)
820
0
    wpa_printf(MSG_DEBUG, "BSS: " MACSTR " changed freq %d --> %d",
821
0
         MAC2STR(bss->bssid), bss->freq, res->freq);
822
0
  bss->scan_miss_count = 0;
823
0
  bss->last_update_idx = wpa_s->bss_update_idx;
824
0
  wpa_bss_copy_res(bss, res, fetch_time);
825
  /* Move the entry to the end of the list */
826
0
  dl_list_del(&bss->list);
827
#ifdef CONFIG_P2P
828
  if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) &&
829
      !wpa_scan_get_vendor_ie(res, P2P_IE_VENDOR_TYPE) &&
830
      !(changes & WPA_BSS_FREQ_CHANGED_FLAG)) {
831
    /*
832
     * This can happen when non-P2P station interface runs a scan
833
     * without P2P IE in the Probe Request frame. P2P GO would reply
834
     * to that with a Probe Response that does not include P2P IE.
835
     * Do not update the IEs in this BSS entry to avoid such loss of
836
     * information that may be needed for P2P operations to
837
     * determine group information.
838
     */
839
    wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Do not update scan IEs for "
840
      MACSTR " since that would remove P2P IE information",
841
      MAC2STR(bss->bssid));
842
  } else
843
#endif /* CONFIG_P2P */
844
0
  if (bss->ie_len + bss->beacon_ie_len >=
845
0
      res->ie_len + res->beacon_ie_len) {
846
0
    os_memcpy(bss->ies, res + 1, res->ie_len + res->beacon_ie_len);
847
0
    bss->ie_len = res->ie_len;
848
0
    bss->beacon_ie_len = res->beacon_ie_len;
849
0
  } else {
850
0
    struct wpa_bss *nbss;
851
0
    struct dl_list *prev = bss->list_id.prev;
852
0
    struct wpa_connect_work *cwork;
853
0
    unsigned int i, j;
854
0
    bool update_current_bss = wpa_s->current_bss == bss;
855
0
    bool update_ml_probe_bss = wpa_s->ml_connect_probe_bss == bss;
856
0
    int update_link_bss = -1;
857
858
0
    for (j = 0; j < MAX_NUM_MLD_LINKS; j++) {
859
0
      if (wpa_s->links[j].bss == bss) {
860
0
        update_link_bss = j;
861
0
        break;
862
0
      }
863
0
    }
864
865
0
    cwork = wpa_bss_check_pending_connect(wpa_s, bss);
866
867
0
    for (i = 0; i < wpa_s->last_scan_res_used; i++) {
868
0
      if (wpa_s->last_scan_res[i] == bss)
869
0
        break;
870
0
    }
871
872
0
    dl_list_del(&bss->list_id);
873
0
    nbss = os_realloc(bss, sizeof(*bss) + res->ie_len +
874
0
          res->beacon_ie_len);
875
0
    if (nbss) {
876
0
      if (i != wpa_s->last_scan_res_used)
877
0
        wpa_s->last_scan_res[i] = nbss;
878
879
0
      if (update_current_bss)
880
0
        wpa_s->current_bss = nbss;
881
882
0
      if (update_ml_probe_bss)
883
0
        wpa_s->ml_connect_probe_bss = nbss;
884
885
0
      if (update_link_bss >= 0)
886
0
        wpa_s->links[update_link_bss].bss = nbss;
887
888
0
      if (cwork)
889
0
        wpa_bss_update_pending_connect(cwork, nbss);
890
891
0
      bss = nbss;
892
0
      os_memcpy(bss->ies, res + 1,
893
0
          res->ie_len + res->beacon_ie_len);
894
0
      bss->ie_len = res->ie_len;
895
0
      bss->beacon_ie_len = res->beacon_ie_len;
896
0
    }
897
0
    dl_list_add(prev, &bss->list_id);
898
0
  }
899
0
  if (changes & WPA_BSS_IES_CHANGED_FLAG) {
900
0
    wpa_bss_set_hessid(bss);
901
902
0
    wpa_bss_parse_basic_ml_element(wpa_s, bss);
903
0
  }
904
0
  dl_list_add_tail(&wpa_s->bss, &bss->list);
905
906
0
  notify_bss_changes(wpa_s, changes, bss);
907
908
0
  return bss;
909
0
}
910
911
912
/**
913
 * wpa_bss_update_start - Start a BSS table update from scan results
914
 * @wpa_s: Pointer to wpa_supplicant data
915
 *
916
 * This function is called at the start of each BSS table update round for new
917
 * scan results. The actual scan result entries are indicated with calls to
918
 * wpa_bss_update_scan_res() and the update round is finished with a call to
919
 * wpa_bss_update_end().
920
 */
921
void wpa_bss_update_start(struct wpa_supplicant *wpa_s)
922
0
{
923
0
  wpa_s->bss_update_idx++;
924
0
  wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Start scan result update %u",
925
0
    wpa_s->bss_update_idx);
926
0
  wpa_s->last_scan_res_used = 0;
927
0
}
928
929
930
/**
931
 * wpa_bss_update_scan_res - Update a BSS table entry based on a scan result
932
 * @wpa_s: Pointer to wpa_supplicant data
933
 * @res: Scan result
934
 * @fetch_time: Time when the result was fetched from the driver
935
 *
936
 * This function updates a BSS table entry (or adds one) based on a scan result.
937
 * This is called separately for each scan result between the calls to
938
 * wpa_bss_update_start() and wpa_bss_update_end().
939
 */
940
void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
941
           struct wpa_scan_res *res,
942
           struct os_reltime *fetch_time)
943
0
{
944
0
  const u8 *ssid, *p2p, *mesh;
945
0
  struct wpa_bss *bss;
946
947
0
  if (wpa_s->conf->ignore_old_scan_res) {
948
0
    struct os_reltime update;
949
0
    calculate_update_time(fetch_time, res->age, &update);
950
0
    if (os_reltime_before(&update, &wpa_s->scan_trigger_time)) {
951
0
      struct os_reltime age;
952
0
      os_reltime_sub(&wpa_s->scan_trigger_time, &update,
953
0
               &age);
954
0
      wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Ignore driver BSS "
955
0
        "table entry that is %u.%06u seconds older "
956
0
        "than our scan trigger",
957
0
        (unsigned int) age.sec,
958
0
        (unsigned int) age.usec);
959
0
      return;
960
0
    }
961
0
  }
962
963
0
  ssid = wpa_scan_get_ie(res, WLAN_EID_SSID);
964
0
  if (ssid == NULL) {
965
0
    wpa_dbg(wpa_s, MSG_DEBUG, "BSS: No SSID IE included for "
966
0
      MACSTR, MAC2STR(res->bssid));
967
0
    return;
968
0
  }
969
0
  if (ssid[1] > SSID_MAX_LEN) {
970
0
    wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Too long SSID IE included for "
971
0
      MACSTR, MAC2STR(res->bssid));
972
0
    return;
973
0
  }
974
975
0
  p2p = wpa_scan_get_vendor_ie(res, P2P_IE_VENDOR_TYPE);
976
#ifdef CONFIG_P2P
977
  if (p2p == NULL &&
978
      wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE) {
979
    /*
980
     * If it's a P2P specific interface, then don't update
981
     * the scan result without a P2P IE.
982
     */
983
    wpa_printf(MSG_DEBUG, "BSS: No P2P IE - skipping BSS " MACSTR
984
         " update for P2P interface", MAC2STR(res->bssid));
985
    return;
986
  }
987
#endif /* CONFIG_P2P */
988
0
  if (p2p && ssid[1] == P2P_WILDCARD_SSID_LEN &&
989
0
      os_memcmp(ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0)
990
0
    return; /* Skip P2P listen discovery results here */
991
992
  /* TODO: add option for ignoring BSSes we are not interested in
993
   * (to save memory) */
994
995
0
  mesh = wpa_scan_get_ie(res, WLAN_EID_MESH_ID);
996
0
  if (mesh && mesh[1] <= SSID_MAX_LEN)
997
0
    ssid = mesh;
998
999
0
  bss = wpa_bss_get(wpa_s, res->bssid, ssid + 2, ssid[1]);
1000
0
  if (bss == NULL)
1001
0
    bss = wpa_bss_add(wpa_s, ssid + 2, ssid[1], res, fetch_time);
1002
0
  else {
1003
0
    bss = wpa_bss_update(wpa_s, bss, res, fetch_time);
1004
0
    if (wpa_s->last_scan_res) {
1005
0
      unsigned int i;
1006
0
      for (i = 0; i < wpa_s->last_scan_res_used; i++) {
1007
0
        if (bss == wpa_s->last_scan_res[i]) {
1008
          /* Already in the list */
1009
0
          return;
1010
0
        }
1011
0
      }
1012
0
    }
1013
0
  }
1014
1015
0
  if (bss == NULL)
1016
0
    return;
1017
0
  if (wpa_s->last_scan_res_used >= wpa_s->last_scan_res_size) {
1018
0
    struct wpa_bss **n;
1019
0
    unsigned int siz;
1020
0
    if (wpa_s->last_scan_res_size == 0)
1021
0
      siz = 32;
1022
0
    else
1023
0
      siz = wpa_s->last_scan_res_size * 2;
1024
0
    n = os_realloc_array(wpa_s->last_scan_res, siz,
1025
0
             sizeof(struct wpa_bss *));
1026
0
    if (n == NULL)
1027
0
      return;
1028
0
    wpa_s->last_scan_res = n;
1029
0
    wpa_s->last_scan_res_size = siz;
1030
0
  }
1031
1032
0
  if (wpa_s->last_scan_res)
1033
0
    wpa_s->last_scan_res[wpa_s->last_scan_res_used++] = bss;
1034
0
}
1035
1036
1037
static int wpa_bss_included_in_scan(const struct wpa_bss *bss,
1038
            const struct scan_info *info)
1039
0
{
1040
0
  int found;
1041
0
  size_t i;
1042
1043
0
  if (info == NULL)
1044
0
    return 1;
1045
1046
0
  if (info->num_freqs) {
1047
0
    found = 0;
1048
0
    for (i = 0; i < info->num_freqs; i++) {
1049
0
      if (bss->freq == info->freqs[i]) {
1050
0
        found = 1;
1051
0
        break;
1052
0
      }
1053
0
    }
1054
0
    if (!found)
1055
0
      return 0;
1056
0
  }
1057
1058
0
  if (info->num_ssids) {
1059
0
    found = 0;
1060
0
    for (i = 0; i < info->num_ssids; i++) {
1061
0
      const struct wpa_driver_scan_ssid *s = &info->ssids[i];
1062
0
      if ((s->ssid == NULL || s->ssid_len == 0) ||
1063
0
          (s->ssid_len == bss->ssid_len &&
1064
0
           os_memcmp(s->ssid, bss->ssid, bss->ssid_len) ==
1065
0
           0)) {
1066
0
        found = 1;
1067
0
        break;
1068
0
      }
1069
0
    }
1070
0
    if (!found)
1071
0
      return 0;
1072
0
  }
1073
1074
0
  return 1;
1075
0
}
1076
1077
1078
/**
1079
 * wpa_bss_update_end - End a BSS table update from scan results
1080
 * @wpa_s: Pointer to wpa_supplicant data
1081
 * @info: Information about scan parameters
1082
 * @new_scan: Whether this update round was based on a new scan
1083
 *
1084
 * This function is called at the end of each BSS table update round for new
1085
 * scan results. The start of the update was indicated with a call to
1086
 * wpa_bss_update_start().
1087
 */
1088
void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info,
1089
      int new_scan)
1090
0
{
1091
0
  struct wpa_bss *bss, *n;
1092
1093
0
  os_get_reltime(&wpa_s->last_scan);
1094
0
  if ((info && info->aborted) || !new_scan)
1095
0
    return; /* do not expire entries without new scan */
1096
1097
0
  dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
1098
0
    if (wpa_bss_in_use(wpa_s, bss))
1099
0
      continue;
1100
0
    if (!wpa_bss_included_in_scan(bss, info))
1101
0
      continue; /* expire only BSSes that were scanned */
1102
0
    if (bss->last_update_idx < wpa_s->bss_update_idx)
1103
0
      bss->scan_miss_count++;
1104
0
    if (bss->scan_miss_count >=
1105
0
        wpa_s->conf->bss_expiration_scan_count) {
1106
0
      wpa_bss_remove(wpa_s, bss, "no match in scan");
1107
0
    }
1108
0
  }
1109
1110
0
  wpa_printf(MSG_DEBUG, "BSS: last_scan_res_used=%zu/%zu",
1111
0
       wpa_s->last_scan_res_used, wpa_s->last_scan_res_size);
1112
0
}
1113
1114
1115
/**
1116
 * wpa_bss_flush_by_age - Flush old BSS entries
1117
 * @wpa_s: Pointer to wpa_supplicant data
1118
 * @age: Maximum entry age in seconds
1119
 *
1120
 * Remove BSS entries that have not been updated during the last @age seconds.
1121
 */
1122
void wpa_bss_flush_by_age(struct wpa_supplicant *wpa_s, int age)
1123
0
{
1124
0
  struct wpa_bss *bss, *n;
1125
0
  struct os_reltime t;
1126
1127
0
  if (dl_list_empty(&wpa_s->bss))
1128
0
    return;
1129
1130
0
  os_get_reltime(&t);
1131
1132
0
  if (t.sec < age)
1133
0
    return; /* avoid underflow; there can be no older entries */
1134
1135
0
  t.sec -= age;
1136
1137
0
  dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
1138
0
    if (wpa_bss_in_use(wpa_s, bss))
1139
0
      continue;
1140
1141
0
    if (wpa_s->reassoc_same_ess &&
1142
0
        wpa_s->wpa_state != WPA_COMPLETED &&
1143
0
        wpa_s->last_ssid &&
1144
0
        wpa_s->last_ssid->ssid &&
1145
0
        bss->ssid_len == wpa_s->last_ssid->ssid_len &&
1146
0
        os_memcmp(bss->ssid, wpa_s->last_ssid->ssid,
1147
0
            bss->ssid_len) == 0)
1148
0
      continue;
1149
1150
0
    if (os_reltime_before(&bss->last_update, &t)) {
1151
0
      wpa_bss_remove(wpa_s, bss, __func__);
1152
0
    } else
1153
0
      break;
1154
0
  }
1155
0
}
1156
1157
1158
/**
1159
 * wpa_bss_init - Initialize BSS table
1160
 * @wpa_s: Pointer to wpa_supplicant data
1161
 * Returns: 0 on success, -1 on failure
1162
 *
1163
 * This prepares BSS table lists and timer for periodic updates. The BSS table
1164
 * is deinitialized with wpa_bss_deinit() once not needed anymore.
1165
 */
1166
int wpa_bss_init(struct wpa_supplicant *wpa_s)
1167
1.61k
{
1168
1.61k
  dl_list_init(&wpa_s->bss);
1169
1.61k
  dl_list_init(&wpa_s->bss_id);
1170
1.61k
  return 0;
1171
1.61k
}
1172
1173
1174
/**
1175
 * wpa_bss_flush - Flush all unused BSS entries
1176
 * @wpa_s: Pointer to wpa_supplicant data
1177
 */
1178
void wpa_bss_flush(struct wpa_supplicant *wpa_s)
1179
1.61k
{
1180
1.61k
  struct wpa_bss *bss, *n;
1181
1182
1.61k
  wpa_s->clear_driver_scan_cache = 1;
1183
1184
1.61k
  if (wpa_s->bss.next == NULL)
1185
0
    return; /* BSS table not yet initialized */
1186
1187
1.61k
  dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
1188
0
    if (wpa_bss_in_use(wpa_s, bss))
1189
0
      continue;
1190
0
    wpa_bss_remove(wpa_s, bss, __func__);
1191
0
  }
1192
1.61k
}
1193
1194
1195
/**
1196
 * wpa_bss_deinit - Deinitialize BSS table
1197
 * @wpa_s: Pointer to wpa_supplicant data
1198
 */
1199
void wpa_bss_deinit(struct wpa_supplicant *wpa_s)
1200
0
{
1201
0
  wpa_bss_flush(wpa_s);
1202
0
}
1203
1204
1205
/**
1206
 * wpa_bss_get_bssid - Fetch a BSS table entry based on BSSID
1207
 * @wpa_s: Pointer to wpa_supplicant data
1208
 * @bssid: BSSID
1209
 * Returns: Pointer to the BSS entry or %NULL if not found
1210
 */
1211
struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s,
1212
           const u8 *bssid)
1213
0
{
1214
0
  struct wpa_bss *bss;
1215
0
  if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
1216
0
    return NULL;
1217
0
  dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
1218
0
    if (ether_addr_equal(bss->bssid, bssid))
1219
0
      return bss;
1220
0
  }
1221
0
  return NULL;
1222
0
}
1223
1224
1225
/**
1226
 * wpa_bss_get_bssid_latest - Fetch the latest BSS table entry based on BSSID
1227
 * @wpa_s: Pointer to wpa_supplicant data
1228
 * @bssid: BSSID
1229
 * Returns: Pointer to the BSS entry or %NULL if not found
1230
 *
1231
 * This function is like wpa_bss_get_bssid(), but full BSS table is iterated to
1232
 * find the entry that has the most recent update. This can help in finding the
1233
 * correct entry in cases where the SSID of the AP may have changed recently
1234
 * (e.g., in WPS reconfiguration cases).
1235
 */
1236
struct wpa_bss * wpa_bss_get_bssid_latest(struct wpa_supplicant *wpa_s,
1237
            const u8 *bssid)
1238
0
{
1239
0
  struct wpa_bss *bss, *found = NULL;
1240
0
  if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
1241
0
    return NULL;
1242
0
  dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
1243
0
    if (!ether_addr_equal(bss->bssid, bssid))
1244
0
      continue;
1245
0
    if (found == NULL ||
1246
0
        os_reltime_before(&found->last_update, &bss->last_update))
1247
0
      found = bss;
1248
0
  }
1249
0
  return found;
1250
0
}
1251
1252
1253
#ifdef CONFIG_P2P
1254
/**
1255
 * wpa_bss_get_p2p_dev_addr - Fetch the latest BSS table entry based on P2P Device Addr
1256
 * @wpa_s: Pointer to wpa_supplicant data
1257
 * @dev_addr: P2P Device Address of the GO
1258
 * Returns: Pointer to the BSS entry or %NULL if not found
1259
 *
1260
 * This function tries to find the entry that has the most recent update. This
1261
 * can help in finding the correct entry in cases where the SSID of the P2P
1262
 * Device may have changed recently.
1263
 */
1264
struct wpa_bss * wpa_bss_get_p2p_dev_addr(struct wpa_supplicant *wpa_s,
1265
            const u8 *dev_addr)
1266
{
1267
  struct wpa_bss *bss, *found = NULL;
1268
  dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
1269
    u8 addr[ETH_ALEN];
1270
    if (p2p_parse_dev_addr(wpa_bss_ie_ptr(bss), bss->ie_len,
1271
               addr) != 0 ||
1272
        !ether_addr_equal(addr, dev_addr))
1273
      continue;
1274
    if (!found ||
1275
        os_reltime_before(&found->last_update, &bss->last_update))
1276
      found = bss;
1277
  }
1278
  return found;
1279
}
1280
#endif /* CONFIG_P2P */
1281
1282
1283
/**
1284
 * wpa_bss_get_id - Fetch a BSS table entry based on identifier
1285
 * @wpa_s: Pointer to wpa_supplicant data
1286
 * @id: Unique identifier (struct wpa_bss::id) assigned for the entry
1287
 * Returns: Pointer to the BSS entry or %NULL if not found
1288
 */
1289
struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id)
1290
0
{
1291
0
  struct wpa_bss *bss;
1292
0
  dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1293
0
    if (bss->id == id)
1294
0
      return bss;
1295
0
  }
1296
0
  return NULL;
1297
0
}
1298
1299
1300
/**
1301
 * wpa_bss_get_id_range - Fetch a BSS table entry based on identifier range
1302
 * @wpa_s: Pointer to wpa_supplicant data
1303
 * @idf: Smallest allowed identifier assigned for the entry
1304
 * @idf: Largest allowed identifier assigned for the entry
1305
 * Returns: Pointer to the BSS entry or %NULL if not found
1306
 *
1307
 * This function is similar to wpa_bss_get_id() but allows a BSS entry with the
1308
 * smallest id value to be fetched within the specified range without the
1309
 * caller having to know the exact id.
1310
 */
1311
struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s,
1312
              unsigned int idf, unsigned int idl)
1313
0
{
1314
0
  struct wpa_bss *bss;
1315
0
  dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
1316
0
    if (bss->id >= idf && bss->id <= idl)
1317
0
      return bss;
1318
0
  }
1319
0
  return NULL;
1320
0
}
1321
1322
1323
/**
1324
 * wpa_bss_get_ie - Fetch a specified information element from a BSS entry
1325
 * @bss: BSS table entry
1326
 * @ie: Information element identitifier (WLAN_EID_*)
1327
 * Returns: Pointer to the information element (id field) or %NULL if not found
1328
 *
1329
 * This function returns the first matching information element in the BSS
1330
 * entry.
1331
 */
1332
const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie)
1333
2.73k
{
1334
2.73k
  return get_ie(wpa_bss_ie_ptr(bss), bss->ie_len, ie);
1335
2.73k
}
1336
1337
1338
/**
1339
 * wpa_bss_get_ie_beacon - Fetch a specified information element from a BSS entry
1340
 * @bss: BSS table entry
1341
 * @ie: Information element identitifier (WLAN_EID_*)
1342
 * Returns: Pointer to the information element (id field) or %NULL if not found
1343
 *
1344
 * This function returns the first matching information element in the BSS
1345
 * entry.
1346
 *
1347
 * This function is like wpa_bss_get_ie(), but uses IE buffer only from Beacon
1348
 * frames instead of either Beacon or Probe Response frames.
1349
 */
1350
const u8 * wpa_bss_get_ie_beacon(const struct wpa_bss *bss, u8 ie)
1351
0
{
1352
0
  const u8 *ies;
1353
1354
0
  if (bss->beacon_ie_len == 0)
1355
0
    return NULL;
1356
1357
0
  ies = wpa_bss_ie_ptr(bss);
1358
0
  ies += bss->ie_len;
1359
0
  return get_ie(ies, bss->beacon_ie_len, ie);
1360
0
}
1361
1362
1363
/**
1364
 * wpa_bss_get_ie_ext - Fetch a specified extended IE from a BSS entry
1365
 * @bss: BSS table entry
1366
 * @ext: Information element extension identifier (WLAN_EID_EXT_*)
1367
 * Returns: Pointer to the information element (id field) or %NULL if not found
1368
 *
1369
 * This function returns the first matching information element in the BSS
1370
 * entry.
1371
 */
1372
const u8 * wpa_bss_get_ie_ext(const struct wpa_bss *bss, u8 ext)
1373
0
{
1374
0
  return get_ie_ext(wpa_bss_ie_ptr(bss), bss->ie_len, ext);
1375
0
}
1376
1377
1378
/**
1379
 * wpa_bss_get_vendor_ie - Fetch a vendor information element from a BSS entry
1380
 * @bss: BSS table entry
1381
 * @vendor_type: Vendor type (four octets starting the IE payload)
1382
 * Returns: Pointer to the information element (id field) or %NULL if not found
1383
 *
1384
 * This function returns the first matching information element in the BSS
1385
 * entry.
1386
 */
1387
const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type)
1388
0
{
1389
0
  const u8 *ies;
1390
0
  const struct element *elem;
1391
1392
0
  ies = wpa_bss_ie_ptr(bss);
1393
1394
0
  for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, bss->ie_len) {
1395
0
    if (elem->datalen >= 4 &&
1396
0
        vendor_type == WPA_GET_BE32(elem->data))
1397
0
      return &elem->id;
1398
0
  }
1399
1400
0
  return NULL;
1401
0
}
1402
1403
1404
/**
1405
 * wpa_bss_get_vendor_ie_beacon - Fetch a vendor information from a BSS entry
1406
 * @bss: BSS table entry
1407
 * @vendor_type: Vendor type (four octets starting the IE payload)
1408
 * Returns: Pointer to the information element (id field) or %NULL if not found
1409
 *
1410
 * This function returns the first matching information element in the BSS
1411
 * entry.
1412
 *
1413
 * This function is like wpa_bss_get_vendor_ie(), but uses IE buffer only
1414
 * from Beacon frames instead of either Beacon or Probe Response frames.
1415
 */
1416
const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss,
1417
          u32 vendor_type)
1418
0
{
1419
0
  const u8 *ies;
1420
0
  const struct element *elem;
1421
1422
0
  if (bss->beacon_ie_len == 0)
1423
0
    return NULL;
1424
1425
0
  ies = wpa_bss_ie_ptr(bss);
1426
0
  ies += bss->ie_len;
1427
1428
0
  for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies,
1429
0
          bss->beacon_ie_len) {
1430
0
    if (elem->datalen >= 4 &&
1431
0
        vendor_type == WPA_GET_BE32(elem->data))
1432
0
      return &elem->id;
1433
0
  }
1434
1435
0
  return NULL;
1436
0
}
1437
1438
1439
/**
1440
 * wpa_bss_get_vendor_ie_multi - Fetch vendor IE data from a BSS entry
1441
 * @bss: BSS table entry
1442
 * @vendor_type: Vendor type (four octets starting the IE payload)
1443
 * Returns: Pointer to the information element payload or %NULL if not found
1444
 *
1445
 * This function returns concatenated payload of possibly fragmented vendor
1446
 * specific information elements in the BSS entry. The caller is responsible for
1447
 * freeing the returned buffer.
1448
 */
1449
struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss,
1450
              u32 vendor_type)
1451
0
{
1452
0
  struct wpabuf *buf;
1453
0
  const u8 *end, *pos;
1454
1455
0
  buf = wpabuf_alloc(bss->ie_len);
1456
0
  if (buf == NULL)
1457
0
    return NULL;
1458
1459
0
  pos = wpa_bss_ie_ptr(bss);
1460
0
  end = pos + bss->ie_len;
1461
1462
0
  while (end - pos > 1) {
1463
0
    u8 ie, len;
1464
1465
0
    ie = pos[0];
1466
0
    len = pos[1];
1467
0
    if (len > end - pos - 2)
1468
0
      break;
1469
0
    pos += 2;
1470
0
    if (ie == WLAN_EID_VENDOR_SPECIFIC && len >= 4 &&
1471
0
        vendor_type == WPA_GET_BE32(pos))
1472
0
      wpabuf_put_data(buf, pos + 4, len - 4);
1473
0
    pos += len;
1474
0
  }
1475
1476
0
  if (wpabuf_len(buf) == 0) {
1477
0
    wpabuf_free(buf);
1478
0
    buf = NULL;
1479
0
  }
1480
1481
0
  return buf;
1482
0
}
1483
1484
1485
/**
1486
 * wpa_bss_get_vendor_ie_multi_beacon - Fetch vendor IE data from a BSS entry
1487
 * @bss: BSS table entry
1488
 * @vendor_type: Vendor type (four octets starting the IE payload)
1489
 * Returns: Pointer to the information element payload or %NULL if not found
1490
 *
1491
 * This function returns concatenated payload of possibly fragmented vendor
1492
 * specific information elements in the BSS entry. The caller is responsible for
1493
 * freeing the returned buffer.
1494
 *
1495
 * This function is like wpa_bss_get_vendor_ie_multi(), but uses IE buffer only
1496
 * from Beacon frames instead of either Beacon or Probe Response frames.
1497
 */
1498
struct wpabuf * wpa_bss_get_vendor_ie_multi_beacon(const struct wpa_bss *bss,
1499
               u32 vendor_type)
1500
0
{
1501
0
  struct wpabuf *buf;
1502
0
  const u8 *end, *pos;
1503
1504
0
  buf = wpabuf_alloc(bss->beacon_ie_len);
1505
0
  if (buf == NULL)
1506
0
    return NULL;
1507
1508
0
  pos = wpa_bss_ie_ptr(bss);
1509
0
  pos += bss->ie_len;
1510
0
  end = pos + bss->beacon_ie_len;
1511
1512
0
  while (end - pos > 1) {
1513
0
    u8 id, len;
1514
1515
0
    id = *pos++;
1516
0
    len = *pos++;
1517
0
    if (len > end - pos)
1518
0
      break;
1519
0
    if (id == WLAN_EID_VENDOR_SPECIFIC && len >= 4 &&
1520
0
        vendor_type == WPA_GET_BE32(pos))
1521
0
      wpabuf_put_data(buf, pos + 4, len - 4);
1522
0
    pos += len;
1523
0
  }
1524
1525
0
  if (wpabuf_len(buf) == 0) {
1526
0
    wpabuf_free(buf);
1527
0
    buf = NULL;
1528
0
  }
1529
1530
0
  return buf;
1531
0
}
1532
1533
1534
/**
1535
 * wpa_bss_get_max_rate - Get maximum legacy TX rate supported in a BSS
1536
 * @bss: BSS table entry
1537
 * Returns: Maximum legacy rate in units of 500 kbps
1538
 */
1539
int wpa_bss_get_max_rate(const struct wpa_bss *bss)
1540
0
{
1541
0
  int rate = 0;
1542
0
  const u8 *ie;
1543
0
  int i;
1544
1545
0
  ie = wpa_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
1546
0
  for (i = 0; ie && i < ie[1]; i++) {
1547
0
    if ((ie[i + 2] & 0x7f) > rate)
1548
0
      rate = ie[i + 2] & 0x7f;
1549
0
  }
1550
1551
0
  ie = wpa_bss_get_ie(bss, WLAN_EID_EXT_SUPP_RATES);
1552
0
  for (i = 0; ie && i < ie[1]; i++) {
1553
0
    if ((ie[i + 2] & 0x7f) > rate)
1554
0
      rate = ie[i + 2] & 0x7f;
1555
0
  }
1556
1557
0
  return rate;
1558
0
}
1559
1560
1561
/**
1562
 * wpa_bss_get_bit_rates - Get legacy TX rates supported in a BSS
1563
 * @bss: BSS table entry
1564
 * @rates: Buffer for returning a pointer to the rates list (units of 500 kbps)
1565
 * Returns: number of legacy TX rates or -1 on failure
1566
 *
1567
 * The caller is responsible for freeing the returned buffer with os_free() in
1568
 * case of success.
1569
 */
1570
int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates)
1571
0
{
1572
0
  const u8 *ie, *ie2;
1573
0
  int i, j;
1574
0
  unsigned int len;
1575
0
  u8 *r;
1576
1577
0
  ie = wpa_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
1578
0
  ie2 = wpa_bss_get_ie(bss, WLAN_EID_EXT_SUPP_RATES);
1579
1580
0
  len = (ie ? ie[1] : 0) + (ie2 ? ie2[1] : 0);
1581
1582
0
  r = os_malloc(len);
1583
0
  if (!r)
1584
0
    return -1;
1585
1586
0
  for (i = 0; ie && i < ie[1]; i++)
1587
0
    r[i] = ie[i + 2] & 0x7f;
1588
1589
0
  for (j = 0; ie2 && j < ie2[1]; j++)
1590
0
    r[i + j] = ie2[j + 2] & 0x7f;
1591
1592
0
  *rates = r;
1593
0
  return len;
1594
0
}
1595
1596
1597
#ifdef CONFIG_FILS
1598
const u8 * wpa_bss_get_fils_cache_id(const struct wpa_bss *bss)
1599
{
1600
  const u8 *ie;
1601
1602
  if (bss) {
1603
    ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
1604
    if (ie && ie[1] >= 4 && WPA_GET_LE16(ie + 2) & BIT(7))
1605
      return ie + 4;
1606
  }
1607
1608
  return NULL;
1609
}
1610
#endif /* CONFIG_FILS */
1611
1612
1613
int wpa_bss_ext_capab(const struct wpa_bss *bss, unsigned int capab)
1614
0
{
1615
0
  if (!bss)
1616
0
    return 0;
1617
0
  return ieee802_11_ext_capab(wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB),
1618
0
            capab);
1619
0
}
1620
1621
1622
static void
1623
wpa_bss_parse_ml_rnr_ap_info(struct wpa_supplicant *wpa_s,
1624
           struct wpa_bss *bss, u8 ap_mld_id,
1625
           const struct ieee80211_neighbor_ap_info *ap_info,
1626
           size_t len, u16 *seen)
1627
0
{
1628
0
  const u8 *pos, *end;
1629
0
  const u8 *mld_params;
1630
0
  u8 count, mld_params_offset;
1631
0
  u8 i, type, link_id;
1632
1633
0
  count = RNR_TBTT_INFO_COUNT_VAL(ap_info->tbtt_info_hdr) + 1;
1634
0
  type = ap_info->tbtt_info_hdr & RNR_TBTT_INFO_HDR_TYPE_MSK;
1635
1636
  /* MLD information is at offset 13 or at start */
1637
0
  if (type == 0 && ap_info->tbtt_info_len >= RNR_TBTT_INFO_MLD_LEN) {
1638
    /* MLD info is appended */
1639
0
    mld_params_offset = RNR_TBTT_INFO_LEN;
1640
0
  } else {
1641
    /* TODO: Support NSTR AP */
1642
0
    return;
1643
0
  }
1644
1645
0
  pos = (const u8 *) ap_info;
1646
0
  end = pos + len;
1647
0
  pos += sizeof(*ap_info);
1648
1649
0
  for (i = 0; i < count; i++, pos += ap_info->tbtt_info_len) {
1650
0
    if (end - pos < ap_info->tbtt_info_len)
1651
0
      break;
1652
1653
0
    mld_params = pos + mld_params_offset;
1654
1655
0
    link_id = *(mld_params + 1) & EHT_ML_LINK_ID_MSK;
1656
0
    if (link_id >= MAX_NUM_MLD_LINKS)
1657
0
      continue;
1658
1659
0
    if (*mld_params != ap_mld_id) {
1660
0
      wpa_printf(MSG_DEBUG,
1661
0
           "MLD: Reported link not part of MLD");
1662
0
    } else if (!(BIT(link_id) & *seen)) {
1663
0
      struct mld_link *l;
1664
1665
0
      *seen |= BIT(link_id);
1666
0
      wpa_printf(MSG_DEBUG, "MLD: mld ID=%u, link ID=%u",
1667
0
           *mld_params, link_id);
1668
1669
0
      bss->valid_links |= BIT(link_id);
1670
0
      l = &bss->mld_links[link_id];
1671
0
      os_memcpy(l->bssid, pos + 1, ETH_ALEN);
1672
0
      l->disabled = mld_params[2] &
1673
0
        RNR_TBTT_INFO_MLD_PARAM2_LINK_DISABLED;
1674
0
      l->freq = ieee80211_chan_to_freq(NULL,
1675
0
               ap_info->op_class,
1676
0
               ap_info->channel);
1677
0
    }
1678
0
  }
1679
0
}
1680
1681
1682
/**
1683
 * wpa_bss_validate_rsne_ml - Validate RSN IEs (RSNE/RSNOE/RSNO2E) of a BSS
1684
 * @wpa_s: Pointer to wpa_supplicant data
1685
 * @ssid: Network config
1686
 * @bss: BSS table entry
1687
 * @rsne_type_p: Type of RSNE to validate. If -1 is given, choose as per the
1688
 *  presence of RSN elements (association link); otherwise, validate
1689
 *  against the requested type (other affiliated links).
1690
 * @ref_rsne: Buffer for RSNE data; filled in from the main link to compare
1691
 *  against and used internally
1692
 * Returns: true if the BSS configuration matches local profile and the elements
1693
 * meet MLO requirements, false otherwise
1694
 */
1695
static bool
1696
wpa_bss_validate_rsne_ml(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
1697
       struct wpa_bss *bss, int *rsne_type_p,
1698
       struct wpa_ie_data *ref_rsne)
1699
0
{
1700
0
  struct ieee802_11_elems elems;
1701
0
  struct wpa_ie_data wpa_ie;
1702
0
  const u8 *rsne;
1703
0
  size_t rsne_len;
1704
0
  int rsne_type;
1705
0
  const u8 *ies_pos = wpa_bss_ie_ptr(bss);
1706
0
  size_t ies_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len;
1707
1708
0
  if (ieee802_11_parse_elems(ies_pos, ies_len, &elems, 0) ==
1709
0
      ParseFailed) {
1710
0
    wpa_dbg(wpa_s, MSG_DEBUG, "MLD: Failed to parse elements");
1711
0
    return false;
1712
0
  }
1713
1714
0
  if (elems.rsne_override_2 && wpas_rsn_overriding(wpa_s, ssid)) {
1715
0
    rsne = elems.rsne_override_2;
1716
0
    rsne_len = elems.rsne_override_2_len;
1717
0
    rsne_type = 2;
1718
0
  } else if (elems.rsne_override && wpas_rsn_overriding(wpa_s, ssid)) {
1719
0
    rsne = elems.rsne_override;
1720
0
    rsne_len = elems.rsne_override_len;
1721
0
    rsne_type = 1;
1722
0
  } else {
1723
0
    rsne = elems.rsn_ie;
1724
0
    rsne_len = elems.rsn_ie_len;
1725
0
    rsne_type = 0;
1726
0
  }
1727
1728
0
  if (!rsne ||
1729
0
      wpa_parse_wpa_ie(rsne - 2, 2 + rsne_len, &wpa_ie)) {
1730
0
    wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RSN element");
1731
0
    return false;
1732
0
  }
1733
1734
0
  if (*rsne_type_p != -1 && *rsne_type_p != rsne_type) {
1735
0
    wpa_dbg(wpa_s, MSG_DEBUG,
1736
0
      "MLD: No matching RSN element (RSNO mismatch)");
1737
0
    return false;
1738
0
  }
1739
1740
0
  if (!(wpa_ie.capabilities & WPA_CAPABILITY_MFPC) ||
1741
0
      wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION) {
1742
0
    wpa_dbg(wpa_s, MSG_DEBUG,
1743
0
      "MLD: No management frame protection");
1744
0
    return false;
1745
0
  }
1746
1747
0
  wpa_ie.key_mgmt &= ~(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK |
1748
0
           WPA_KEY_MGMT_PSK_SHA256);
1749
0
  if (!(wpa_ie.key_mgmt & ssid->key_mgmt)) {
1750
0
    wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No valid key management");
1751
0
    return false;
1752
0
  }
1753
0
  wpa_dbg(wpa_s, MSG_DEBUG, "MLD: key_mgmt=0x%x", wpa_ie.key_mgmt);
1754
1755
0
  wpa_ie.pairwise_cipher &= ~(WPA_CIPHER_NONE | WPA_CIPHER_WEP40 |
1756
0
            WPA_CIPHER_WEP104 | WPA_CIPHER_TKIP);
1757
0
  if (!(wpa_ie.pairwise_cipher & ssid->pairwise_cipher)) {
1758
0
    wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No valid pairwise cipher");
1759
0
    return false;
1760
0
  }
1761
1762
0
  if (*rsne_type_p == -1) {
1763
0
    os_memcpy(ref_rsne, &wpa_ie, sizeof(wpa_ie));
1764
1765
0
    *rsne_type_p = rsne_type;
1766
0
  } else {
1767
    /* Verify the neighbor given rsne_type_p and ref_rsne */
1768
0
    if (!(wpa_ie.key_mgmt & ref_rsne->key_mgmt)) {
1769
0
      wpa_dbg(wpa_s, MSG_DEBUG,
1770
0
        "MLD: Neighbor without common AKM");
1771
0
      return false;
1772
0
    }
1773
1774
0
    if (!(wpa_ie.pairwise_cipher & ref_rsne->pairwise_cipher)) {
1775
0
      wpa_dbg(wpa_s, MSG_DEBUG,
1776
0
        "MLD: Neighbor without common pairwise cipher");
1777
0
      return false;
1778
0
    }
1779
0
  }
1780
1781
0
  return true;
1782
0
}
1783
1784
1785
/**
1786
 * wpa_bss_get_usable_links - Retrieve the usable links of the AP MLD
1787
 * @wpa_s: Pointer to wpa_supplicant data
1788
 * @bss: BSS table entry
1789
 * @ssid: Target SSID (or %NULL)
1790
 * @missing_links: Result bitmask of links that were not discovered (or %NULL)
1791
 * Returns: Bitmap of links that are usable, or 0 for non-MLD or failure
1792
 *
1793
 * Validate each link of the MLD to verify that it is compatible and connection
1794
 * to each of the links is allowed.
1795
 */
1796
u16 wpa_bss_get_usable_links(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
1797
           struct wpa_ssid *ssid, u16 *missing_links)
1798
0
{
1799
0
  struct wpa_ie_data rsne;
1800
0
  int rsne_type;
1801
0
  u16 usable_links = 0;
1802
0
  u8 link_id;
1803
1804
0
  if (!bss->valid_links)
1805
0
    return 0;
1806
1807
0
  rsne_type = -1;
1808
0
  os_memset(&rsne, 0, sizeof(rsne));
1809
0
  if (ssid &&
1810
0
      !wpa_bss_validate_rsne_ml(wpa_s, ssid, bss, &rsne_type, &rsne)) {
1811
0
    wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No valid key management");
1812
0
    return 0;
1813
0
  }
1814
1815
0
  usable_links = BIT(bss->mld_link_id);
1816
1817
0
  for_each_link(bss->valid_links, link_id) {
1818
0
    struct wpa_bss *neigh_bss;
1819
0
    u16 ext_mld_capa_mask;
1820
1821
0
    if (link_id == bss->mld_link_id)
1822
0
      continue;
1823
1824
0
    if (ssid && ssid->ssid_len)
1825
0
      neigh_bss = wpa_bss_get(wpa_s,
1826
0
            bss->mld_links[link_id].bssid,
1827
0
            ssid->ssid,
1828
0
            ssid->ssid_len);
1829
0
    else
1830
0
      neigh_bss = wpa_bss_get_bssid(wpa_s,
1831
0
                  bss->mld_links[link_id].bssid);
1832
1833
0
    if (!neigh_bss) {
1834
0
      if (missing_links)
1835
0
        *missing_links |= BIT(link_id);
1836
0
      continue;
1837
0
    }
1838
1839
    /* Check that the affiliated links are for the same AP MLD and
1840
     * the information matches */
1841
0
    if (!neigh_bss->valid_links) {
1842
0
      wpa_dbg(wpa_s, MSG_DEBUG,
1843
0
        "MLD: Neighbor without Multi-Link support");
1844
0
      continue;
1845
0
    }
1846
1847
0
    if (neigh_bss->mld_link_id != link_id) {
1848
0
      wpa_dbg(wpa_s, MSG_DEBUG,
1849
0
        "MLD: Neighbor has unexpected link ID (%d != %d)",
1850
0
        neigh_bss->mld_link_id, link_id);
1851
0
      continue;
1852
0
    }
1853
1854
0
    if (!ether_addr_equal(bss->mld_addr, neigh_bss->mld_addr)) {
1855
0
      wpa_dbg(wpa_s, MSG_DEBUG,
1856
0
        "MLD: Neighbor has a different MLD MAC address ("
1857
0
        MACSTR " != " MACSTR ")",
1858
0
        MAC2STR(neigh_bss->mld_addr),
1859
0
        MAC2STR(bss->mld_addr));
1860
0
      continue;
1861
0
    }
1862
1863
0
    if ((bss->mld_capa & ~EHT_ML_MLD_CAPA_RESERVED) !=
1864
0
        (neigh_bss->mld_capa & ~EHT_ML_MLD_CAPA_RESERVED)) {
1865
0
      wpa_dbg(wpa_s, MSG_DEBUG,
1866
0
        "MLD: Neighbor's MLD Capabilities do not match (0x%04x != 0x%04x)",
1867
0
        neigh_bss->mld_capa, bss->mld_capa);
1868
0
      continue;
1869
0
    }
1870
1871
0
    if ((bss->eml_capa & ~EHT_ML_EML_CAPA_RESERVED) !=
1872
0
        (neigh_bss->eml_capa & ~EHT_ML_EML_CAPA_RESERVED)) {
1873
0
      wpa_dbg(wpa_s, MSG_DEBUG,
1874
0
        "MLD: Neighbor's EML Capabilities do not match (0x%04x != 0x%04x",
1875
0
        neigh_bss->eml_capa, bss->eml_capa);
1876
0
      continue;
1877
0
    }
1878
1879
    /*
1880
     * Check well-defined values in Extended MLD Capabilities.
1881
     * In particular the Recommended Max Simultaneous Links
1882
     * subfield may change over time and is reserved depending on
1883
     * the frame that it is carried in.
1884
     * See IEEE Std 802.11be-2024, Table 9-417o.
1885
     */
1886
0
    ext_mld_capa_mask =
1887
0
      EHT_ML_EXT_MLD_CAPA_OP_PARAM_UPDATE |
1888
0
      EHT_ML_EXT_MLD_CAPA_NSTR_UPDATE |
1889
0
      EHT_ML_EXT_MLD_CAPA_EMLSR_ENA_ONE_LINK;
1890
0
    if ((bss->ext_mld_capa & ext_mld_capa_mask) !=
1891
0
        (neigh_bss->ext_mld_capa & ext_mld_capa_mask)) {
1892
0
      wpa_dbg(wpa_s, MSG_DEBUG,
1893
0
        "MLD: Neighbors Extended MLD Capabilities do not match (0x%04x != 0x%04x)",
1894
0
        neigh_bss->ext_mld_capa, bss->ext_mld_capa);
1895
0
      continue;
1896
0
    }
1897
1898
0
    if (ssid) {
1899
      /* As per IEEE Std 802.11be-2024, 12.6.2 (RSNA
1900
       * selection), all APs affiliated with an AP MLD shall
1901
       * advertise at least one common AKM suite selector in
1902
       * the AKM Suite List field of the RSNE. Discard links
1903
       * that do not have compatible configuration with the
1904
       * association link.
1905
       */
1906
0
      if (!wpa_bss_validate_rsne_ml(wpa_s, ssid, neigh_bss,
1907
0
                  &rsne_type, &rsne)) {
1908
0
        wpa_printf(MSG_DEBUG,
1909
0
             "MLD: Discard link %u due to RSN parameter mismatch",
1910
0
             link_id);
1911
0
        continue;
1912
0
      }
1913
0
    }
1914
1915
0
    if ((!ssid ||
1916
0
         wpa_scan_res_match(wpa_s, 0, neigh_bss, ssid, 1, 0,
1917
0
          true)) &&
1918
0
        !wpa_bssid_ignore_is_listed(wpa_s, neigh_bss->bssid)) {
1919
0
      usable_links |= BIT(link_id);
1920
0
    }
1921
0
  }
1922
1923
0
  return usable_links;
1924
0
}
1925
1926
1927
/**
1928
 * wpa_bss_parse_basic_ml_element - Parse the Basic Multi-Link element
1929
 * @wpa_s: Pointer to wpa_supplicant data
1930
 * @bss: BSS table entry
1931
 *
1932
 * Parses the Basic Multi-Link element of the BSS into @link_info using the scan
1933
 * information stored in the wpa_supplicant data to fill in information for
1934
 * links where possible.
1935
 */
1936
void wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
1937
            struct wpa_bss *bss)
1938
0
{
1939
0
  struct ieee802_11_elems elems;
1940
0
  struct wpabuf *mlbuf = NULL;
1941
0
  const struct element *elem;
1942
0
  size_t ml_ie_len;
1943
0
  const struct ieee80211_eht_ml *eht_ml;
1944
0
  const struct eht_ml_basic_common_info *ml_basic_common_info;
1945
0
  const u8 *mbssid_idx_elem;
1946
0
  u8 i, pos, link_id, ap_mld_id;
1947
0
  const u16 control_mask =
1948
0
    MULTI_LINK_CONTROL_TYPE_MASK |
1949
0
    BASIC_MULTI_LINK_CTRL_PRES_LINK_ID |
1950
0
    BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT |
1951
0
    BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA;
1952
0
  const u16 control =
1953
0
    MULTI_LINK_CONTROL_TYPE_BASIC |
1954
0
    BASIC_MULTI_LINK_CTRL_PRES_LINK_ID |
1955
0
    BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT |
1956
0
    BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA;
1957
0
  u16 seen;
1958
0
  const u8 *ies_pos = wpa_bss_ie_ptr(bss);
1959
0
  size_t ies_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len;
1960
0
  struct mld_link *l;
1961
1962
0
  if (ieee802_11_parse_elems(ies_pos, ies_len, &elems, 1) ==
1963
0
      ParseFailed) {
1964
0
    wpa_dbg(wpa_s, MSG_DEBUG, "MLD: Failed to parse elements");
1965
0
    goto out;
1966
0
  }
1967
1968
0
  mlbuf = ieee802_11_defrag(elems.basic_mle, elems.basic_mle_len, true);
1969
0
  if (!mlbuf) {
1970
0
    wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No Multi-Link element");
1971
0
    goto out;
1972
0
  }
1973
1974
0
  ml_ie_len = wpabuf_len(mlbuf);
1975
1976
  /*
1977
   * for ext ID + 2 control + common info len
1978
   */
1979
0
  if (ml_ie_len < sizeof(*eht_ml) + sizeof(*ml_basic_common_info))
1980
0
    goto out;
1981
1982
0
  eht_ml = (const struct ieee80211_eht_ml *) wpabuf_head(mlbuf);
1983
0
  if ((le_to_host16(eht_ml->ml_control) & control_mask) != control) {
1984
0
    wpa_printf(MSG_DEBUG,
1985
0
         "MLD: Unexpected Multi-Link element control=0x%x (mask 0x%x expected 0x%x)",
1986
0
         le_to_host16(eht_ml->ml_control), control_mask,
1987
0
         control);
1988
0
    goto out;
1989
0
  }
1990
1991
0
  ml_basic_common_info =
1992
0
    (const struct eht_ml_basic_common_info *) eht_ml->variable;
1993
1994
0
  if (ml_ie_len < sizeof(*eht_ml) + ml_basic_common_info->len)
1995
0
    goto out;
1996
1997
  /* Minimum Common info length to be valid */
1998
0
  if (ml_basic_common_info->len <
1999
0
      sizeof(*ml_basic_common_info) + 1 + 1 + 2)
2000
0
    goto out;
2001
2002
  /* Link ID Info, BSS Parameters Change Count (see control/control_mask)
2003
   */
2004
0
  link_id = ml_basic_common_info->variable[0] & EHT_ML_LINK_ID_MSK;
2005
0
  pos = 1 + 1;
2006
2007
  /* Medium Synchronization Delay Information */
2008
0
  if (le_to_host16(eht_ml->ml_control) &
2009
0
      BASIC_MULTI_LINK_CTRL_PRES_MSD_INFO)
2010
0
    pos += 2;
2011
2012
  /* EML Capabilities */
2013
0
  bss->eml_capa = 0;
2014
0
  if (le_to_host16(eht_ml->ml_control) &
2015
0
      BASIC_MULTI_LINK_CTRL_PRES_EML_CAPA) {
2016
0
    bss->eml_capa =
2017
0
      WPA_GET_LE16(&ml_basic_common_info->variable[pos]);
2018
0
    pos += 2;
2019
0
  }
2020
2021
  /* MLD Capabilities And Operations (always present, see
2022
   * control/control_mask) */
2023
0
  bss->mld_capa = WPA_GET_LE16(&ml_basic_common_info->variable[pos]);
2024
0
  pos += 2;
2025
2026
  /* AP MLD ID from MLE if present (see comment below) */
2027
0
  if (le_to_host16(eht_ml->ml_control) &
2028
0
      BASIC_MULTI_LINK_CTRL_PRES_AP_MLD_ID) {
2029
0
    if (ml_basic_common_info->len <
2030
0
        sizeof(*ml_basic_common_info) + pos + 1)
2031
0
      goto out;
2032
2033
0
    ap_mld_id = ml_basic_common_info->variable[pos];
2034
2035
0
    pos++;
2036
0
  } else {
2037
0
    ap_mld_id = 0;
2038
0
  }
2039
2040
  /* Extended MLD Capabilities And Operations */
2041
0
  bss->ext_mld_capa = 0;
2042
0
  if (le_to_host16(eht_ml->ml_control) &
2043
0
      BASIC_MULTI_LINK_CTRL_PRES_EXT_MLD_CAP) {
2044
0
    if (ml_basic_common_info->len <
2045
0
        sizeof(*ml_basic_common_info) + pos + 2)
2046
0
      goto out;
2047
2048
0
    bss->ext_mld_capa =
2049
0
      WPA_GET_LE16(&ml_basic_common_info->variable[pos]);
2050
2051
0
    pos += 2;
2052
0
  }
2053
2054
0
  if (ml_basic_common_info->len < sizeof(*ml_basic_common_info) + pos)
2055
0
    goto out;
2056
2057
0
  link_id = ml_basic_common_info->variable[0] & EHT_ML_LINK_ID_MSK;
2058
2059
0
  os_memcpy(bss->mld_addr, ml_basic_common_info->mld_addr, ETH_ALEN);
2060
2061
0
  bss->mld_link_id = link_id;
2062
0
  bss->valid_links = BIT(link_id);
2063
0
  seen = bss->valid_links;
2064
2065
0
  l = &bss->mld_links[link_id];
2066
0
  os_memcpy(l->bssid, bss->bssid, ETH_ALEN);
2067
0
  l->freq = bss->freq;
2068
2069
0
  bss->mld_bss_non_transmitted = false;
2070
2071
  /*
2072
   * We should be able to rely on the Multiple BSSID Index element
2073
   * to be included if the BSS is nontransmitted. Both if it was
2074
   * extracted from a beacon and if it came from an ML probe
2075
   * response (i.e. not listed in IEEE Std 802.11be-2024, 35.3.3.4).
2076
   *
2077
   * Note that the AP MLD ID and the Multiple-BSSID Index will be
2078
   * identical if the information was reported by the
2079
   * corresponding transmitting AP (IEEE Std 802.11be-2024, 9.4.2.169.2).
2080
   * As an AP MLD ID will not be explicitly provided we need to
2081
   * rely on the Multiple-BSSID Index element. This is generally the case
2082
   * when the BSS information was read from a Multiple-BSSID element.
2083
   *
2084
   * The alternative scenario is a BSS discovered using a
2085
   * Multi-Link Probe Response. In that case, we can still
2086
   * determine whether the BSS is nontransmitted or not using the
2087
   * Multiple BSSID-Index element. However, the AP MLD ID may be
2088
   * different inside the ML Probe Response and the driver also
2089
   * needs to deal with this during inheritance.
2090
   *
2091
   * We assume the driver either
2092
   *  - includes the appropriate AP MLD ID in the MLE it generates
2093
   *    (see above), or
2094
   *  - rewrites the RNR so that the AP MLD ID matches the
2095
   *    Multiple-BSSID Index element.
2096
   */
2097
0
  mbssid_idx_elem = wpa_bss_get_ie(bss, WLAN_EID_MULTIPLE_BSSID_INDEX);
2098
0
  if (mbssid_idx_elem && mbssid_idx_elem[1] >= 1) {
2099
0
    if (!(le_to_host16(eht_ml->ml_control) &
2100
0
          BASIC_MULTI_LINK_CTRL_PRES_AP_MLD_ID))
2101
0
      ap_mld_id = mbssid_idx_elem[2];
2102
0
    bss->mld_bss_non_transmitted = !!mbssid_idx_elem[2];
2103
0
  }
2104
2105
0
  for_each_element_id(elem, WLAN_EID_REDUCED_NEIGHBOR_REPORT,
2106
0
          wpa_bss_ie_ptr(bss),
2107
0
          bss->ie_len ? bss->ie_len : bss->beacon_ie_len) {
2108
0
    const struct ieee80211_neighbor_ap_info *ap_info;
2109
0
    const u8 *ap_info_pos = elem->data;
2110
0
    size_t len = elem->datalen;
2111
2112
    /* RNR IE may contain more than one Neighbor AP Info */
2113
0
    while (sizeof(*ap_info) <= len) {
2114
0
      size_t ap_info_len = sizeof(*ap_info);
2115
0
      u8 count;
2116
2117
0
      ap_info = (const struct ieee80211_neighbor_ap_info *)
2118
0
        ap_info_pos;
2119
0
      count = RNR_TBTT_INFO_COUNT_VAL(ap_info->tbtt_info_hdr) + 1;
2120
0
      ap_info_len += count * ap_info->tbtt_info_len;
2121
2122
0
      if (ap_info_len > len)
2123
0
        goto out;
2124
2125
0
      wpa_bss_parse_ml_rnr_ap_info(wpa_s, bss, ap_mld_id,
2126
0
                 ap_info, len, &seen);
2127
2128
0
      ap_info_pos += ap_info_len;
2129
0
      len -= ap_info_len;
2130
0
    }
2131
0
  }
2132
2133
0
  wpa_printf(MSG_DEBUG, "MLD: valid_links=0x%04hx",
2134
0
       bss->valid_links);
2135
2136
0
  for_each_link(bss->valid_links, i) {
2137
0
    wpa_printf(MSG_DEBUG, "MLD: link=%u, bssid=" MACSTR,
2138
0
         i, MAC2STR(bss->mld_links[i].bssid));
2139
0
  }
2140
2141
0
  wpabuf_free(mlbuf);
2142
0
  return;
2143
2144
0
out:
2145
0
  os_memset(bss->mld_addr, 0, ETH_ALEN);
2146
0
  bss->valid_links = 0;
2147
0
  wpabuf_free(mlbuf);
2148
0
}
2149
2150
2151
/*
2152
 * wpa_bss_parse_reconf_ml_element - Parse the Reconfiguration ML element
2153
 * @wpa_s: Pointer to wpa_supplicant data
2154
 * @bss: BSS table entry
2155
 * Returns: The bitmap of links that are going to be removed
2156
 */
2157
u16 wpa_bss_parse_reconf_ml_element(struct wpa_supplicant *wpa_s,
2158
            struct wpa_bss *bss)
2159
0
{
2160
0
  struct ieee802_11_elems elems;
2161
0
  struct wpabuf *mlbuf;
2162
0
  const u8 *pos = wpa_bss_ie_ptr(bss);
2163
0
  size_t len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len;
2164
0
  const struct ieee80211_eht_ml *ml;
2165
0
  const struct eht_ml_reconf_common_info *common_info;
2166
0
  u16 removed_links = 0;
2167
0
  u8 expected_ml_common_len;
2168
2169
0
  if (ieee802_11_parse_elems(pos, len, &elems, 1) == ParseFailed)
2170
0
    return 0;
2171
2172
0
  if (!elems.reconf_mle || !elems.reconf_mle_len)
2173
0
    return 0;
2174
2175
0
  mlbuf = ieee802_11_defrag(elems.reconf_mle, elems.reconf_mle_len, true);
2176
0
  if (!mlbuf)
2177
0
    return 0;
2178
2179
0
  ml = (const struct ieee80211_eht_ml *) wpabuf_head(mlbuf);
2180
0
  len = wpabuf_len(mlbuf);
2181
2182
  /* There must be at least one octet for the Common Info Length subfield
2183
   */
2184
0
  if (len < sizeof(*ml) + 1UL)
2185
0
    goto out;
2186
2187
0
  expected_ml_common_len = 1;
2188
0
  if (le_to_host16(ml->ml_control) &
2189
0
      RECONF_MULTI_LINK_CTRL_PRES_MLD_MAC_ADDR)
2190
0
    expected_ml_common_len += ETH_ALEN;
2191
2192
0
  common_info = (const struct eht_ml_reconf_common_info *) ml->variable;
2193
0
  if (len < sizeof(*ml) + common_info->len) {
2194
0
    wpa_printf(MSG_DEBUG,
2195
0
         "MLD: Unexpected Reconfiguration ML element length: (%zu < %zu)",
2196
0
         len, sizeof(*ml) + common_info->len);
2197
0
    goto out;
2198
0
  }
2199
2200
0
  if (common_info->len < expected_ml_common_len) {
2201
0
    wpa_printf(MSG_DEBUG,
2202
0
         "MLD: Invalid common info len=%u; min expected=%u",
2203
0
         common_info->len, expected_ml_common_len);
2204
0
    goto out;
2205
0
  }
2206
2207
0
  pos = ml->variable + common_info->len;
2208
0
  len -= sizeof(*ml) + common_info->len;
2209
2210
0
  while (len >= 2 + sizeof(struct ieee80211_eht_per_sta_profile)) {
2211
0
    size_t sub_elem_len;
2212
0
    int num_frag_subelems;
2213
2214
0
    num_frag_subelems =
2215
0
      ieee802_11_defrag_mle_subelem(mlbuf, pos,
2216
0
                  &sub_elem_len);
2217
0
    if (num_frag_subelems < 0) {
2218
0
      wpa_printf(MSG_DEBUG,
2219
0
           "MLD: Failed to parse MLE subelem");
2220
0
      break;
2221
0
    }
2222
2223
0
    len -= num_frag_subelems * 2;
2224
2225
0
    if (2 + sub_elem_len > len) {
2226
0
      wpa_printf(MSG_DEBUG,
2227
0
           "MLD: Invalid link info len: %zu %zu",
2228
0
           2 + sub_elem_len, len);
2229
0
      goto out;
2230
0
    }
2231
2232
0
    if  (*pos == MULTI_LINK_SUB_ELEM_ID_PER_STA_PROFILE &&
2233
0
         sub_elem_len >= 2) {
2234
0
      const struct ieee80211_eht_per_sta_profile *sta_prof =
2235
0
        (const struct ieee80211_eht_per_sta_profile *)
2236
0
        (pos + 2);
2237
0
      u16 control = le_to_host16(sta_prof->sta_control);
2238
0
      u8 link_id;
2239
2240
0
      link_id = control & EHT_PER_STA_RECONF_CTRL_LINK_ID_MSK;
2241
0
      removed_links |= BIT(link_id);
2242
0
    }
2243
2244
0
    pos += 2 + sub_elem_len;
2245
0
    len -= 2 + sub_elem_len;
2246
0
  }
2247
2248
0
  wpa_printf(MSG_DEBUG, "MLD: Reconfiguration: removed_links=0x%x",
2249
0
       removed_links);
2250
0
out:
2251
0
  wpabuf_free(mlbuf);
2252
0
  return removed_links;
2253
0
}
2254
2255
2256
#ifndef CONFIG_NO_WPA
2257
2258
static bool wpa_bss_supported_cipher(struct wpa_supplicant *wpa_s,
2259
             int pairwise_cipher)
2260
0
{
2261
0
  if (!wpa_s->drv_enc)
2262
0
    return true;
2263
2264
0
  if ((pairwise_cipher & WPA_CIPHER_CCMP) &&
2265
0
      (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_CCMP))
2266
0
    return true;
2267
2268
0
  if ((pairwise_cipher & WPA_CIPHER_GCMP) &&
2269
0
      (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_GCMP))
2270
0
    return true;
2271
2272
0
  if ((pairwise_cipher & WPA_CIPHER_CCMP_256) &&
2273
0
      (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_CCMP_256))
2274
0
    return true;
2275
2276
0
  if ((pairwise_cipher & WPA_CIPHER_GCMP_256) &&
2277
0
      (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_GCMP_256))
2278
0
    return true;
2279
2280
0
  return false;
2281
0
}
2282
2283
2284
static bool wpa_bss_supported_key_mgmt(struct wpa_supplicant *wpa_s,
2285
               int key_mgmt)
2286
0
{
2287
0
  if (!wpa_s->drv_key_mgmt)
2288
0
    return true;
2289
2290
0
  if ((key_mgmt & WPA_KEY_MGMT_IEEE8021X) &&
2291
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA2))
2292
0
    return true;
2293
0
  if ((key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) &&
2294
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_802_1X_SHA256))
2295
0
    return true;
2296
0
  if ((key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) &&
2297
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT))
2298
0
    return true;
2299
0
  if ((key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
2300
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_802_1X_SHA384))
2301
0
    return true;
2302
0
  if ((key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) &&
2303
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B))
2304
0
    return true;
2305
0
  if ((key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) &&
2306
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192))
2307
0
    return true;
2308
0
  if ((key_mgmt & WPA_KEY_MGMT_PSK) &&
2309
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK))
2310
0
    return true;
2311
0
  if ((key_mgmt & WPA_KEY_MGMT_FT_PSK) &&
2312
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK))
2313
0
    return true;
2314
0
  if ((key_mgmt & WPA_KEY_MGMT_PSK_SHA256) &&
2315
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256))
2316
0
    return true;
2317
0
  if ((key_mgmt & WPA_KEY_MGMT_SAE) &&
2318
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE))
2319
0
    return true;
2320
0
  if ((key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) &&
2321
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE_EXT_KEY))
2322
0
    return true;
2323
0
  if ((key_mgmt & WPA_KEY_MGMT_FT_SAE) &&
2324
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE))
2325
0
    return true;
2326
0
  if ((key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) &&
2327
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE_EXT_KEY))
2328
0
    return true;
2329
0
  if ((key_mgmt & WPA_KEY_MGMT_OWE) &&
2330
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE))
2331
0
    return true;
2332
0
  if ((key_mgmt & WPA_KEY_MGMT_DPP) &&
2333
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP))
2334
0
    return true;
2335
0
  if ((key_mgmt & WPA_KEY_MGMT_FILS_SHA256) &&
2336
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256))
2337
0
    return true;
2338
0
  if ((key_mgmt & WPA_KEY_MGMT_FILS_SHA384) &&
2339
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384))
2340
0
    return true;
2341
0
  if ((key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) &&
2342
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256))
2343
0
    return true;
2344
0
  if ((key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) &&
2345
0
      (wpa_s->drv_key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384))
2346
0
    return true;
2347
2348
0
  return false;
2349
0
}
2350
2351
2352
static bool wpa_bss_supported_rsne(struct wpa_supplicant *wpa_s,
2353
           struct wpa_ssid *ssid, const u8 *ie)
2354
0
{
2355
0
  struct wpa_ie_data data;
2356
2357
0
  if (wpa_parse_wpa_ie_rsn(ie, 2 + ie[1], &data) < 0)
2358
0
    return false;
2359
2360
  /* Check that there is a supported AKM and pairwise cipher based on
2361
   * overall capabilities */
2362
0
  if (!data.pairwise_cipher || !data.key_mgmt)
2363
0
    return false;
2364
2365
0
  if (wpa_s->drv_capa_known) {
2366
0
    if (!wpa_bss_supported_cipher(wpa_s, data.pairwise_cipher) ||
2367
0
        !wpa_bss_supported_key_mgmt(wpa_s, data.key_mgmt))
2368
0
      return false;
2369
0
  }
2370
2371
0
  if (ssid) {
2372
    /* Check that there is a supported AKM and pairwise cipher
2373
     * based on the specific network profile. */
2374
0
    if ((ssid->pairwise_cipher & data.pairwise_cipher) == 0)
2375
0
      return false;
2376
0
    if ((ssid->key_mgmt & data.key_mgmt) == 0)
2377
0
      return false;
2378
0
  }
2379
2380
0
  return true;
2381
0
}
2382
2383
#endif /* CONFIG_NO_WPA */
2384
2385
2386
const u8 * wpa_bss_get_rsne(struct wpa_supplicant *wpa_s,
2387
          const struct wpa_bss *bss, struct wpa_ssid *ssid,
2388
          bool mlo)
2389
0
{
2390
0
#ifndef CONFIG_NO_WPA
2391
0
  const u8 *ie;
2392
2393
0
  if (wpas_rsn_overriding(wpa_s, ssid)) {
2394
0
    if (!ssid)
2395
0
      ssid = wpa_s->current_ssid;
2396
2397
    /* MLO cases for RSN overriding are required to use RSNE
2398
     * Override 2 element and RSNXE Override element together. */
2399
0
    ie = wpa_bss_get_vendor_ie(bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
2400
0
    if (mlo && ie &&
2401
0
        !wpa_bss_get_vendor_ie(bss,
2402
0
             RSNXE_OVERRIDE_IE_VENDOR_TYPE)) {
2403
0
      wpa_printf(MSG_DEBUG, "BSS " MACSTR
2404
0
           " advertises RSNE Override 2 element without RSNXE Override element - ignore RSNE Override 2 element for MLO",
2405
0
           MAC2STR(bss->bssid));
2406
0
    } else if (ie && wpa_bss_supported_rsne(wpa_s, ssid, ie)) {
2407
0
      return ie;
2408
0
    }
2409
2410
0
    if (!mlo) {
2411
0
      ie = wpa_bss_get_vendor_ie(
2412
0
        bss, RSNE_OVERRIDE_IE_VENDOR_TYPE);
2413
0
      if (ie && wpa_bss_supported_rsne(wpa_s, ssid, ie))
2414
0
        return ie;
2415
0
    }
2416
0
  }
2417
0
#endif /* CONFIG_NO_WPA */
2418
2419
0
  return wpa_bss_get_ie(bss, WLAN_EID_RSN);
2420
0
}
2421
2422
2423
const u8 * wpa_bss_get_rsnxe(struct wpa_supplicant *wpa_s,
2424
           const struct wpa_bss *bss, struct wpa_ssid *ssid,
2425
           bool mlo)
2426
0
{
2427
0
  const u8 *ie;
2428
2429
0
  if (wpas_rsn_overriding(wpa_s, ssid)) {
2430
0
    ie = wpa_bss_get_vendor_ie(bss, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
2431
0
    if (ie) {
2432
0
      const u8 *tmp;
2433
2434
0
      tmp = wpa_bss_get_rsne(wpa_s, bss, ssid, mlo);
2435
0
      if (!tmp || tmp[0] == WLAN_EID_RSN) {
2436
        /* An acceptable RSNE override element was not
2437
         * found, so need to ignore RSNXE overriding. */
2438
0
        goto out;
2439
0
      }
2440
2441
0
      return ie;
2442
0
    }
2443
2444
    /* MLO cases for RSN overriding are required to use RSNE
2445
     * Override 2 element and RSNXE Override element together. */
2446
0
    if (mlo && wpa_bss_get_vendor_ie(
2447
0
          bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE)) {
2448
0
      wpa_printf(MSG_DEBUG, "BSS " MACSTR
2449
0
           " advertises RSNXE Override element without RSNE Override 2 element - ignore RSNXE Override element for MLO",
2450
0
           MAC2STR(bss->bssid));
2451
0
      goto out;
2452
0
    }
2453
0
  }
2454
2455
0
out:
2456
0
  return wpa_bss_get_ie(bss, WLAN_EID_RSNX);
2457
0
}