1/*
2 * BSS table
3 * Copyright (c) 2009-2012, 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 "wpa_supplicant_i.h"
16#include "config.h"
17#include "notify.h"
18#include "scan.h"
19#include "bss.h"
20
21
22/**
23 * WPA_BSS_EXPIRATION_PERIOD - Period of expiration run in seconds
24 */
25#define WPA_BSS_EXPIRATION_PERIOD 10
26
27#define WPA_BSS_FREQ_CHANGED_FLAG	BIT(0)
28#define WPA_BSS_SIGNAL_CHANGED_FLAG	BIT(1)
29#define WPA_BSS_PRIVACY_CHANGED_FLAG	BIT(2)
30#define WPA_BSS_MODE_CHANGED_FLAG	BIT(3)
31#define WPA_BSS_WPAIE_CHANGED_FLAG	BIT(4)
32#define WPA_BSS_RSNIE_CHANGED_FLAG	BIT(5)
33#define WPA_BSS_WPS_CHANGED_FLAG	BIT(6)
34#define WPA_BSS_RATES_CHANGED_FLAG	BIT(7)
35#define WPA_BSS_IES_CHANGED_FLAG	BIT(8)
36
37
38static void wpa_bss_set_hessid(struct wpa_bss *bss)
39{
40#ifdef CONFIG_INTERWORKING
41	const u8 *ie = wpa_bss_get_ie(bss, WLAN_EID_INTERWORKING);
42	if (ie == NULL || (ie[1] != 7 && ie[1] != 9)) {
43		os_memset(bss->hessid, 0, ETH_ALEN);
44		return;
45	}
46	if (ie[1] == 7)
47		os_memcpy(bss->hessid, ie + 3, ETH_ALEN);
48	else
49		os_memcpy(bss->hessid, ie + 5, ETH_ALEN);
50#endif /* CONFIG_INTERWORKING */
51}
52
53
54/**
55 * wpa_bss_anqp_alloc - Allocate ANQP data structure for a BSS entry
56 * Returns: Allocated ANQP data structure or %NULL on failure
57 *
58 * The allocated ANQP data structure has its users count set to 1. It may be
59 * shared by multiple BSS entries and each shared entry is freed with
60 * wpa_bss_anqp_free().
61 */
62struct wpa_bss_anqp * wpa_bss_anqp_alloc(void)
63{
64	struct wpa_bss_anqp *anqp;
65	anqp = os_zalloc(sizeof(*anqp));
66	if (anqp == NULL)
67		return NULL;
68	anqp->users = 1;
69	return anqp;
70}
71
72
73/**
74 * wpa_bss_anqp_clone - Clone an ANQP data structure
75 * @anqp: ANQP data structure from wpa_bss_anqp_alloc()
76 * Returns: Cloned ANQP data structure or %NULL on failure
77 */
78static struct wpa_bss_anqp * wpa_bss_anqp_clone(struct wpa_bss_anqp *anqp)
79{
80	struct wpa_bss_anqp *n;
81
82	n = os_zalloc(sizeof(*n));
83	if (n == NULL)
84		return NULL;
85
86#define ANQP_DUP(f) if (anqp->f) n->f = wpabuf_dup(anqp->f)
87#ifdef CONFIG_INTERWORKING
88	ANQP_DUP(venue_name);
89	ANQP_DUP(network_auth_type);
90	ANQP_DUP(roaming_consortium);
91	ANQP_DUP(ip_addr_type_availability);
92	ANQP_DUP(nai_realm);
93	ANQP_DUP(anqp_3gpp);
94	ANQP_DUP(domain_name);
95#endif /* CONFIG_INTERWORKING */
96#ifdef CONFIG_HS20
97	ANQP_DUP(hs20_operator_friendly_name);
98	ANQP_DUP(hs20_wan_metrics);
99	ANQP_DUP(hs20_connection_capability);
100	ANQP_DUP(hs20_operating_class);
101	ANQP_DUP(hs20_osu_providers_list);
102#endif /* CONFIG_HS20 */
103#undef ANQP_DUP
104
105	return n;
106}
107
108
109/**
110 * wpa_bss_anqp_unshare_alloc - Unshare ANQP data (if shared) in a BSS entry
111 * @bss: BSS entry
112 * Returns: 0 on success, -1 on failure
113 *
114 * This function ensures the specific BSS entry has an ANQP data structure that
115 * is not shared with any other BSS entry.
116 */
117int wpa_bss_anqp_unshare_alloc(struct wpa_bss *bss)
118{
119	struct wpa_bss_anqp *anqp;
120
121	if (bss->anqp && bss->anqp->users > 1) {
122		/* allocated, but shared - clone an unshared copy */
123		anqp = wpa_bss_anqp_clone(bss->anqp);
124		if (anqp == NULL)
125			return -1;
126		anqp->users = 1;
127		bss->anqp->users--;
128		bss->anqp = anqp;
129		return 0;
130	}
131
132	if (bss->anqp)
133		return 0; /* already allocated and not shared */
134
135	/* not allocated - allocate a new storage area */
136	bss->anqp = wpa_bss_anqp_alloc();
137	return bss->anqp ? 0 : -1;
138}
139
140
141/**
142 * wpa_bss_anqp_free - Free an ANQP data structure
143 * @anqp: ANQP data structure from wpa_bss_anqp_alloc() or wpa_bss_anqp_clone()
144 */
145static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp)
146{
147	if (anqp == NULL)
148		return;
149
150	anqp->users--;
151	if (anqp->users > 0) {
152		/* Another BSS entry holds a pointer to this ANQP info */
153		return;
154	}
155
156#ifdef CONFIG_INTERWORKING
157	wpabuf_free(anqp->venue_name);
158	wpabuf_free(anqp->network_auth_type);
159	wpabuf_free(anqp->roaming_consortium);
160	wpabuf_free(anqp->ip_addr_type_availability);
161	wpabuf_free(anqp->nai_realm);
162	wpabuf_free(anqp->anqp_3gpp);
163	wpabuf_free(anqp->domain_name);
164#endif /* CONFIG_INTERWORKING */
165#ifdef CONFIG_HS20
166	wpabuf_free(anqp->hs20_operator_friendly_name);
167	wpabuf_free(anqp->hs20_wan_metrics);
168	wpabuf_free(anqp->hs20_connection_capability);
169	wpabuf_free(anqp->hs20_operating_class);
170	wpabuf_free(anqp->hs20_osu_providers_list);
171#endif /* CONFIG_HS20 */
172
173	os_free(anqp);
174}
175
176
177static void wpa_bss_update_pending_connect(struct wpa_supplicant *wpa_s,
178					   struct wpa_bss *old_bss,
179					   struct wpa_bss *new_bss)
180{
181	struct wpa_radio_work *work;
182	struct wpa_connect_work *cwork;
183
184	work = radio_work_pending(wpa_s, "sme-connect");
185	if (!work)
186		work = radio_work_pending(wpa_s, "connect");
187	if (!work)
188		return;
189
190	cwork = work->ctx;
191	if (cwork->bss != old_bss)
192		return;
193
194	wpa_printf(MSG_DEBUG,
195		   "Update BSS pointer for the pending connect radio work");
196	cwork->bss = new_bss;
197	if (!new_bss)
198		cwork->bss_removed = 1;
199}
200
201
202static void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
203			   const char *reason)
204{
205	if (wpa_s->last_scan_res) {
206		unsigned int i;
207		for (i = 0; i < wpa_s->last_scan_res_used; i++) {
208			if (wpa_s->last_scan_res[i] == bss) {
209				os_memmove(&wpa_s->last_scan_res[i],
210					   &wpa_s->last_scan_res[i + 1],
211					   (wpa_s->last_scan_res_used - i - 1)
212					   * sizeof(struct wpa_bss *));
213				wpa_s->last_scan_res_used--;
214				break;
215			}
216		}
217	}
218	wpa_bss_update_pending_connect(wpa_s, bss, NULL);
219	dl_list_del(&bss->list);
220	dl_list_del(&bss->list_id);
221	wpa_s->num_bss--;
222	wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Remove id %u BSSID " MACSTR
223		" SSID '%s' due to %s", bss->id, MAC2STR(bss->bssid),
224		wpa_ssid_txt(bss->ssid, bss->ssid_len), reason);
225	wpas_notify_bss_removed(wpa_s, bss->bssid, bss->id);
226	wpa_bss_anqp_free(bss->anqp);
227	os_free(bss);
228}
229
230
231/**
232 * wpa_bss_get - Fetch a BSS table entry based on BSSID and SSID
233 * @wpa_s: Pointer to wpa_supplicant data
234 * @bssid: BSSID
235 * @ssid: SSID
236 * @ssid_len: Length of @ssid
237 * Returns: Pointer to the BSS entry or %NULL if not found
238 */
239struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid,
240			     const u8 *ssid, size_t ssid_len)
241{
242	struct wpa_bss *bss;
243	if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
244		return NULL;
245	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
246		if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
247		    bss->ssid_len == ssid_len &&
248		    os_memcmp(bss->ssid, ssid, ssid_len) == 0)
249			return bss;
250	}
251	return NULL;
252}
253
254
255static void calculate_update_time(const struct os_reltime *fetch_time,
256				  unsigned int age_ms,
257				  struct os_reltime *update_time)
258{
259	os_time_t usec;
260
261	update_time->sec = fetch_time->sec;
262	update_time->usec = fetch_time->usec;
263	update_time->sec -= age_ms / 1000;
264	usec = (age_ms % 1000) * 1000;
265	if (update_time->usec < usec) {
266		update_time->sec--;
267		update_time->usec += 1000000;
268	}
269	update_time->usec -= usec;
270}
271
272
273static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src,
274			     struct os_reltime *fetch_time)
275{
276	dst->flags = src->flags;
277	os_memcpy(dst->bssid, src->bssid, ETH_ALEN);
278	dst->freq = src->freq;
279	dst->beacon_int = src->beacon_int;
280	dst->caps = src->caps;
281	dst->qual = src->qual;
282	dst->noise = src->noise;
283	dst->level = src->level;
284	dst->tsf = src->tsf;
285
286	calculate_update_time(fetch_time, src->age, &dst->last_update);
287}
288
289
290static int wpa_bss_known(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
291{
292	struct wpa_ssid *ssid;
293
294	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
295		if (ssid->ssid == NULL || ssid->ssid_len == 0)
296			continue;
297		if (ssid->ssid_len == bss->ssid_len &&
298		    os_memcmp(ssid->ssid, bss->ssid, ssid->ssid_len) == 0)
299			return 1;
300	}
301
302	return 0;
303}
304
305
306static int wpa_bss_in_use(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
307{
308	return bss == wpa_s->current_bss ||
309		os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) == 0 ||
310		os_memcmp(bss->bssid, wpa_s->pending_bssid, ETH_ALEN) == 0;
311}
312
313
314static int wpa_bss_remove_oldest_unknown(struct wpa_supplicant *wpa_s)
315{
316	struct wpa_bss *bss;
317
318	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
319		if (!wpa_bss_known(wpa_s, bss)) {
320			wpa_bss_remove(wpa_s, bss, __func__);
321			return 0;
322		}
323	}
324
325	return -1;
326}
327
328
329static int wpa_bss_remove_oldest(struct wpa_supplicant *wpa_s)
330{
331	struct wpa_bss *bss;
332
333	/*
334	 * Remove the oldest entry that does not match with any configured
335	 * network.
336	 */
337	if (wpa_bss_remove_oldest_unknown(wpa_s) == 0)
338		return 0;
339
340	/*
341	 * Remove the oldest entry that isn't currently in use.
342	 */
343	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
344		if (!wpa_bss_in_use(wpa_s, bss)) {
345			wpa_bss_remove(wpa_s, bss, __func__);
346			return 0;
347		}
348	}
349
350	return -1;
351}
352
353
354static struct wpa_bss * wpa_bss_add(struct wpa_supplicant *wpa_s,
355				    const u8 *ssid, size_t ssid_len,
356				    struct wpa_scan_res *res,
357				    struct os_reltime *fetch_time)
358{
359	struct wpa_bss *bss;
360
361	bss = os_zalloc(sizeof(*bss) + res->ie_len + res->beacon_ie_len);
362	if (bss == NULL)
363		return NULL;
364	bss->id = wpa_s->bss_next_id++;
365	bss->last_update_idx = wpa_s->bss_update_idx;
366	wpa_bss_copy_res(bss, res, fetch_time);
367	os_memcpy(bss->ssid, ssid, ssid_len);
368	bss->ssid_len = ssid_len;
369	bss->ie_len = res->ie_len;
370	bss->beacon_ie_len = res->beacon_ie_len;
371	os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len);
372	wpa_bss_set_hessid(bss);
373
374	if (wpa_s->num_bss + 1 > wpa_s->conf->bss_max_count &&
375	    wpa_bss_remove_oldest(wpa_s) != 0) {
376		wpa_printf(MSG_ERROR, "Increasing the MAX BSS count to %d "
377			   "because all BSSes are in use. We should normally "
378			   "not get here!", (int) wpa_s->num_bss + 1);
379		wpa_s->conf->bss_max_count = wpa_s->num_bss + 1;
380	}
381
382	dl_list_add_tail(&wpa_s->bss, &bss->list);
383	dl_list_add_tail(&wpa_s->bss_id, &bss->list_id);
384	wpa_s->num_bss++;
385	wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Add new id %u BSSID " MACSTR
386		" SSID '%s'",
387		bss->id, MAC2STR(bss->bssid), wpa_ssid_txt(ssid, ssid_len));
388	wpas_notify_bss_added(wpa_s, bss->bssid, bss->id);
389	return bss;
390}
391
392
393static int are_ies_equal(const struct wpa_bss *old,
394			 const struct wpa_scan_res *new, u32 ie)
395{
396	const u8 *old_ie, *new_ie;
397	struct wpabuf *old_ie_buff = NULL;
398	struct wpabuf *new_ie_buff = NULL;
399	int new_ie_len, old_ie_len, ret, is_multi;
400
401	switch (ie) {
402	case WPA_IE_VENDOR_TYPE:
403		old_ie = wpa_bss_get_vendor_ie(old, ie);
404		new_ie = wpa_scan_get_vendor_ie(new, ie);
405		is_multi = 0;
406		break;
407	case WPS_IE_VENDOR_TYPE:
408		old_ie_buff = wpa_bss_get_vendor_ie_multi(old, ie);
409		new_ie_buff = wpa_scan_get_vendor_ie_multi(new, ie);
410		is_multi = 1;
411		break;
412	case WLAN_EID_RSN:
413	case WLAN_EID_SUPP_RATES:
414	case WLAN_EID_EXT_SUPP_RATES:
415		old_ie = wpa_bss_get_ie(old, ie);
416		new_ie = wpa_scan_get_ie(new, ie);
417		is_multi = 0;
418		break;
419	default:
420		wpa_printf(MSG_DEBUG, "bss: %s: cannot compare IEs", __func__);
421		return 0;
422	}
423
424	if (is_multi) {
425		/* in case of multiple IEs stored in buffer */
426		old_ie = old_ie_buff ? wpabuf_head_u8(old_ie_buff) : NULL;
427		new_ie = new_ie_buff ? wpabuf_head_u8(new_ie_buff) : NULL;
428		old_ie_len = old_ie_buff ? wpabuf_len(old_ie_buff) : 0;
429		new_ie_len = new_ie_buff ? wpabuf_len(new_ie_buff) : 0;
430	} else {
431		/* in case of single IE */
432		old_ie_len = old_ie ? old_ie[1] + 2 : 0;
433		new_ie_len = new_ie ? new_ie[1] + 2 : 0;
434	}
435
436	if (!old_ie || !new_ie)
437		ret = !old_ie && !new_ie;
438	else
439		ret = (old_ie_len == new_ie_len &&
440		       os_memcmp(old_ie, new_ie, old_ie_len) == 0);
441
442	wpabuf_free(old_ie_buff);
443	wpabuf_free(new_ie_buff);
444
445	return ret;
446}
447
448
449static u32 wpa_bss_compare_res(const struct wpa_bss *old,
450			       const struct wpa_scan_res *new)
451{
452	u32 changes = 0;
453	int caps_diff = old->caps ^ new->caps;
454
455	if (old->freq != new->freq)
456		changes |= WPA_BSS_FREQ_CHANGED_FLAG;
457
458	if (old->level != new->level)
459		changes |= WPA_BSS_SIGNAL_CHANGED_FLAG;
460
461	if (caps_diff & IEEE80211_CAP_PRIVACY)
462		changes |= WPA_BSS_PRIVACY_CHANGED_FLAG;
463
464	if (caps_diff & IEEE80211_CAP_IBSS)
465		changes |= WPA_BSS_MODE_CHANGED_FLAG;
466
467	if (old->ie_len == new->ie_len &&
468	    os_memcmp(old + 1, new + 1, old->ie_len) == 0)
469		return changes;
470	changes |= WPA_BSS_IES_CHANGED_FLAG;
471
472	if (!are_ies_equal(old, new, WPA_IE_VENDOR_TYPE))
473		changes |= WPA_BSS_WPAIE_CHANGED_FLAG;
474
475	if (!are_ies_equal(old, new, WLAN_EID_RSN))
476		changes |= WPA_BSS_RSNIE_CHANGED_FLAG;
477
478	if (!are_ies_equal(old, new, WPS_IE_VENDOR_TYPE))
479		changes |= WPA_BSS_WPS_CHANGED_FLAG;
480
481	if (!are_ies_equal(old, new, WLAN_EID_SUPP_RATES) ||
482	    !are_ies_equal(old, new, WLAN_EID_EXT_SUPP_RATES))
483		changes |= WPA_BSS_RATES_CHANGED_FLAG;
484
485	return changes;
486}
487
488
489static void notify_bss_changes(struct wpa_supplicant *wpa_s, u32 changes,
490			       const struct wpa_bss *bss)
491{
492	if (changes & WPA_BSS_FREQ_CHANGED_FLAG)
493		wpas_notify_bss_freq_changed(wpa_s, bss->id);
494
495	if (changes & WPA_BSS_SIGNAL_CHANGED_FLAG)
496		wpas_notify_bss_signal_changed(wpa_s, bss->id);
497
498	if (changes & WPA_BSS_PRIVACY_CHANGED_FLAG)
499		wpas_notify_bss_privacy_changed(wpa_s, bss->id);
500
501	if (changes & WPA_BSS_MODE_CHANGED_FLAG)
502		wpas_notify_bss_mode_changed(wpa_s, bss->id);
503
504	if (changes & WPA_BSS_WPAIE_CHANGED_FLAG)
505		wpas_notify_bss_wpaie_changed(wpa_s, bss->id);
506
507	if (changes & WPA_BSS_RSNIE_CHANGED_FLAG)
508		wpas_notify_bss_rsnie_changed(wpa_s, bss->id);
509
510	if (changes & WPA_BSS_WPS_CHANGED_FLAG)
511		wpas_notify_bss_wps_changed(wpa_s, bss->id);
512
513	if (changes & WPA_BSS_IES_CHANGED_FLAG)
514		wpas_notify_bss_ies_changed(wpa_s, bss->id);
515
516	if (changes & WPA_BSS_RATES_CHANGED_FLAG)
517		wpas_notify_bss_rates_changed(wpa_s, bss->id);
518
519	wpas_notify_bss_seen(wpa_s, bss->id);
520}
521
522
523static struct wpa_bss *
524wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
525	       struct wpa_scan_res *res, struct os_reltime *fetch_time)
526{
527	u32 changes;
528
529	changes = wpa_bss_compare_res(bss, res);
530	bss->scan_miss_count = 0;
531	bss->last_update_idx = wpa_s->bss_update_idx;
532	wpa_bss_copy_res(bss, res, fetch_time);
533	/* Move the entry to the end of the list */
534	dl_list_del(&bss->list);
535#ifdef CONFIG_P2P
536	if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) &&
537	    !wpa_scan_get_vendor_ie(res, P2P_IE_VENDOR_TYPE)) {
538		/*
539		 * This can happen when non-P2P station interface runs a scan
540		 * without P2P IE in the Probe Request frame. P2P GO would reply
541		 * to that with a Probe Response that does not include P2P IE.
542		 * Do not update the IEs in this BSS entry to avoid such loss of
543		 * information that may be needed for P2P operations to
544		 * determine group information.
545		 */
546		wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Do not update scan IEs for "
547			MACSTR " since that would remove P2P IE information",
548			MAC2STR(bss->bssid));
549	} else
550#endif /* CONFIG_P2P */
551	if (bss->ie_len + bss->beacon_ie_len >=
552	    res->ie_len + res->beacon_ie_len) {
553		os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len);
554		bss->ie_len = res->ie_len;
555		bss->beacon_ie_len = res->beacon_ie_len;
556	} else {
557		struct wpa_bss *nbss;
558		struct dl_list *prev = bss->list_id.prev;
559		dl_list_del(&bss->list_id);
560		nbss = os_realloc(bss, sizeof(*bss) + res->ie_len +
561				  res->beacon_ie_len);
562		if (nbss) {
563			unsigned int i;
564			for (i = 0; i < wpa_s->last_scan_res_used; i++) {
565				if (wpa_s->last_scan_res[i] == bss) {
566					wpa_s->last_scan_res[i] = nbss;
567					break;
568				}
569			}
570			if (wpa_s->current_bss == bss)
571				wpa_s->current_bss = nbss;
572			wpa_bss_update_pending_connect(wpa_s, bss, nbss);
573			bss = nbss;
574			os_memcpy(bss + 1, res + 1,
575				  res->ie_len + res->beacon_ie_len);
576			bss->ie_len = res->ie_len;
577			bss->beacon_ie_len = res->beacon_ie_len;
578		}
579		dl_list_add(prev, &bss->list_id);
580	}
581	if (changes & WPA_BSS_IES_CHANGED_FLAG)
582		wpa_bss_set_hessid(bss);
583	dl_list_add_tail(&wpa_s->bss, &bss->list);
584
585	notify_bss_changes(wpa_s, changes, bss);
586
587	return bss;
588}
589
590
591/**
592 * wpa_bss_update_start - Start a BSS table update from scan results
593 * @wpa_s: Pointer to wpa_supplicant data
594 *
595 * This function is called at the start of each BSS table update round for new
596 * scan results. The actual scan result entries are indicated with calls to
597 * wpa_bss_update_scan_res() and the update round is finished with a call to
598 * wpa_bss_update_end().
599 */
600void wpa_bss_update_start(struct wpa_supplicant *wpa_s)
601{
602	wpa_s->bss_update_idx++;
603	wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Start scan result update %u",
604		wpa_s->bss_update_idx);
605	wpa_s->last_scan_res_used = 0;
606}
607
608
609/**
610 * wpa_bss_update_scan_res - Update a BSS table entry based on a scan result
611 * @wpa_s: Pointer to wpa_supplicant data
612 * @res: Scan result
613 * @fetch_time: Time when the result was fetched from the driver
614 *
615 * This function updates a BSS table entry (or adds one) based on a scan result.
616 * This is called separately for each scan result between the calls to
617 * wpa_bss_update_start() and wpa_bss_update_end().
618 */
619void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
620			     struct wpa_scan_res *res,
621			     struct os_reltime *fetch_time)
622{
623	const u8 *ssid, *p2p;
624	struct wpa_bss *bss;
625
626	if (wpa_s->conf->ignore_old_scan_res) {
627		struct os_reltime update;
628		calculate_update_time(fetch_time, res->age, &update);
629		if (os_reltime_before(&update, &wpa_s->scan_trigger_time)) {
630			struct os_reltime age;
631			os_reltime_sub(&wpa_s->scan_trigger_time, &update,
632				       &age);
633			wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Ignore driver BSS "
634				"table entry that is %u.%06u seconds older "
635				"than our scan trigger",
636				(unsigned int) age.sec,
637				(unsigned int) age.usec);
638			return;
639		}
640	}
641
642	ssid = wpa_scan_get_ie(res, WLAN_EID_SSID);
643	if (ssid == NULL) {
644		wpa_dbg(wpa_s, MSG_DEBUG, "BSS: No SSID IE included for "
645			MACSTR, MAC2STR(res->bssid));
646		return;
647	}
648	if (ssid[1] > 32) {
649		wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Too long SSID IE included for "
650			MACSTR, MAC2STR(res->bssid));
651		return;
652	}
653
654	p2p = wpa_scan_get_vendor_ie(res, P2P_IE_VENDOR_TYPE);
655#ifdef CONFIG_P2P
656	if (p2p == NULL &&
657	    wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE) {
658		/*
659		 * If it's a P2P specific interface, then don't update
660		 * the scan result without a P2P IE.
661		 */
662		wpa_printf(MSG_DEBUG, "BSS: No P2P IE - skipping BSS " MACSTR
663			   " update for P2P interface", MAC2STR(res->bssid));
664		return;
665	}
666#endif /* CONFIG_P2P */
667	if (p2p && ssid[1] == P2P_WILDCARD_SSID_LEN &&
668	    os_memcmp(ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0)
669		return; /* Skip P2P listen discovery results here */
670
671	/* TODO: add option for ignoring BSSes we are not interested in
672	 * (to save memory) */
673	bss = wpa_bss_get(wpa_s, res->bssid, ssid + 2, ssid[1]);
674	if (bss == NULL)
675		bss = wpa_bss_add(wpa_s, ssid + 2, ssid[1], res, fetch_time);
676	else {
677		bss = wpa_bss_update(wpa_s, bss, res, fetch_time);
678		if (wpa_s->last_scan_res) {
679			unsigned int i;
680			for (i = 0; i < wpa_s->last_scan_res_used; i++) {
681				if (bss == wpa_s->last_scan_res[i]) {
682					/* Already in the list */
683					return;
684				}
685			}
686		}
687	}
688
689	if (bss == NULL)
690		return;
691	if (wpa_s->last_scan_res_used >= wpa_s->last_scan_res_size) {
692		struct wpa_bss **n;
693		unsigned int siz;
694		if (wpa_s->last_scan_res_size == 0)
695			siz = 32;
696		else
697			siz = wpa_s->last_scan_res_size * 2;
698		n = os_realloc_array(wpa_s->last_scan_res, siz,
699				     sizeof(struct wpa_bss *));
700		if (n == NULL)
701			return;
702		wpa_s->last_scan_res = n;
703		wpa_s->last_scan_res_size = siz;
704	}
705
706	if (wpa_s->last_scan_res)
707		wpa_s->last_scan_res[wpa_s->last_scan_res_used++] = bss;
708}
709
710
711static int wpa_bss_included_in_scan(const struct wpa_bss *bss,
712				    const struct scan_info *info)
713{
714	int found;
715	size_t i;
716
717	if (info == NULL)
718		return 1;
719
720	if (info->num_freqs) {
721		found = 0;
722		for (i = 0; i < info->num_freqs; i++) {
723			if (bss->freq == info->freqs[i]) {
724				found = 1;
725				break;
726			}
727		}
728		if (!found)
729			return 0;
730	}
731
732	if (info->num_ssids) {
733		found = 0;
734		for (i = 0; i < info->num_ssids; i++) {
735			const struct wpa_driver_scan_ssid *s = &info->ssids[i];
736			if ((s->ssid == NULL || s->ssid_len == 0) ||
737			    (s->ssid_len == bss->ssid_len &&
738			     os_memcmp(s->ssid, bss->ssid, bss->ssid_len) ==
739			     0)) {
740				found = 1;
741				break;
742			}
743		}
744		if (!found)
745			return 0;
746	}
747
748	return 1;
749}
750
751
752/**
753 * wpa_bss_update_end - End a BSS table update from scan results
754 * @wpa_s: Pointer to wpa_supplicant data
755 * @info: Information about scan parameters
756 * @new_scan: Whether this update round was based on a new scan
757 *
758 * This function is called at the end of each BSS table update round for new
759 * scan results. The start of the update was indicated with a call to
760 * wpa_bss_update_start().
761 */
762void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info,
763			int new_scan)
764{
765	struct wpa_bss *bss, *n;
766
767	os_get_reltime(&wpa_s->last_scan);
768	if (!new_scan)
769		return; /* do not expire entries without new scan */
770
771	dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
772		if (wpa_bss_in_use(wpa_s, bss))
773			continue;
774		if (!wpa_bss_included_in_scan(bss, info))
775			continue; /* expire only BSSes that were scanned */
776		if (bss->last_update_idx < wpa_s->bss_update_idx)
777			bss->scan_miss_count++;
778		if (bss->scan_miss_count >=
779		    wpa_s->conf->bss_expiration_scan_count) {
780			wpa_bss_remove(wpa_s, bss, "no match in scan");
781		}
782	}
783
784	wpa_printf(MSG_DEBUG, "BSS: last_scan_res_used=%u/%u",
785		   wpa_s->last_scan_res_used, wpa_s->last_scan_res_size);
786}
787
788
789/**
790 * wpa_bss_flush_by_age - Flush old BSS entries
791 * @wpa_s: Pointer to wpa_supplicant data
792 * @age: Maximum entry age in seconds
793 *
794 * Remove BSS entries that have not been updated during the last @age seconds.
795 */
796void wpa_bss_flush_by_age(struct wpa_supplicant *wpa_s, int age)
797{
798	struct wpa_bss *bss, *n;
799	struct os_reltime t;
800
801	if (dl_list_empty(&wpa_s->bss))
802		return;
803
804	os_get_reltime(&t);
805	t.sec -= age;
806
807	dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
808		if (wpa_bss_in_use(wpa_s, bss))
809			continue;
810
811		if (os_reltime_before(&bss->last_update, &t)) {
812			wpa_bss_remove(wpa_s, bss, __func__);
813		} else
814			break;
815	}
816}
817
818
819static void wpa_bss_timeout(void *eloop_ctx, void *timeout_ctx)
820{
821	struct wpa_supplicant *wpa_s = eloop_ctx;
822
823	wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
824	eloop_register_timeout(WPA_BSS_EXPIRATION_PERIOD, 0,
825			       wpa_bss_timeout, wpa_s, NULL);
826}
827
828
829/**
830 * wpa_bss_init - Initialize BSS table
831 * @wpa_s: Pointer to wpa_supplicant data
832 * Returns: 0 on success, -1 on failure
833 *
834 * This prepares BSS table lists and timer for periodic updates. The BSS table
835 * is deinitialized with wpa_bss_deinit() once not needed anymore.
836 */
837int wpa_bss_init(struct wpa_supplicant *wpa_s)
838{
839	dl_list_init(&wpa_s->bss);
840	dl_list_init(&wpa_s->bss_id);
841	eloop_register_timeout(WPA_BSS_EXPIRATION_PERIOD, 0,
842			       wpa_bss_timeout, wpa_s, NULL);
843	return 0;
844}
845
846
847/**
848 * wpa_bss_flush - Flush all unused BSS entries
849 * @wpa_s: Pointer to wpa_supplicant data
850 */
851void wpa_bss_flush(struct wpa_supplicant *wpa_s)
852{
853	struct wpa_bss *bss, *n;
854
855	wpa_s->clear_driver_scan_cache = 1;
856
857	if (wpa_s->bss.next == NULL)
858		return; /* BSS table not yet initialized */
859
860	dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
861		if (wpa_bss_in_use(wpa_s, bss))
862			continue;
863		wpa_bss_remove(wpa_s, bss, __func__);
864	}
865}
866
867
868/**
869 * wpa_bss_deinit - Deinitialize BSS table
870 * @wpa_s: Pointer to wpa_supplicant data
871 */
872void wpa_bss_deinit(struct wpa_supplicant *wpa_s)
873{
874	eloop_cancel_timeout(wpa_bss_timeout, wpa_s, NULL);
875	wpa_bss_flush(wpa_s);
876}
877
878
879/**
880 * wpa_bss_get_bssid - Fetch a BSS table entry based on BSSID
881 * @wpa_s: Pointer to wpa_supplicant data
882 * @bssid: BSSID
883 * Returns: Pointer to the BSS entry or %NULL if not found
884 */
885struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s,
886				   const u8 *bssid)
887{
888	struct wpa_bss *bss;
889	if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
890		return NULL;
891	dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
892		if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
893			return bss;
894	}
895	return NULL;
896}
897
898
899/**
900 * wpa_bss_get_bssid_latest - Fetch the latest BSS table entry based on BSSID
901 * @wpa_s: Pointer to wpa_supplicant data
902 * @bssid: BSSID
903 * Returns: Pointer to the BSS entry or %NULL if not found
904 *
905 * This function is like wpa_bss_get_bssid(), but full BSS table is iterated to
906 * find the entry that has the most recent update. This can help in finding the
907 * correct entry in cases where the SSID of the AP may have changed recently
908 * (e.g., in WPS reconfiguration cases).
909 */
910struct wpa_bss * wpa_bss_get_bssid_latest(struct wpa_supplicant *wpa_s,
911					  const u8 *bssid)
912{
913	struct wpa_bss *bss, *found = NULL;
914	if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
915		return NULL;
916	dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
917		if (os_memcmp(bss->bssid, bssid, ETH_ALEN) != 0)
918			continue;
919		if (found == NULL ||
920		    os_reltime_before(&found->last_update, &bss->last_update))
921			found = bss;
922	}
923	return found;
924}
925
926
927#ifdef CONFIG_P2P
928/**
929 * wpa_bss_get_p2p_dev_addr - Fetch a BSS table entry based on P2P Device Addr
930 * @wpa_s: Pointer to wpa_supplicant data
931 * @dev_addr: P2P Device Address of the GO
932 * Returns: Pointer to the BSS entry or %NULL if not found
933 */
934struct wpa_bss * wpa_bss_get_p2p_dev_addr(struct wpa_supplicant *wpa_s,
935					  const u8 *dev_addr)
936{
937	struct wpa_bss *bss;
938	dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
939		u8 addr[ETH_ALEN];
940		if (p2p_parse_dev_addr((const u8 *) (bss + 1), bss->ie_len,
941				       addr) == 0 &&
942		    os_memcmp(addr, dev_addr, ETH_ALEN) == 0)
943			return bss;
944	}
945	return NULL;
946}
947#endif /* CONFIG_P2P */
948
949
950/**
951 * wpa_bss_get_id - Fetch a BSS table entry based on identifier
952 * @wpa_s: Pointer to wpa_supplicant data
953 * @id: Unique identifier (struct wpa_bss::id) assigned for the entry
954 * Returns: Pointer to the BSS entry or %NULL if not found
955 */
956struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id)
957{
958	struct wpa_bss *bss;
959	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
960		if (bss->id == id)
961			return bss;
962	}
963	return NULL;
964}
965
966
967/**
968 * wpa_bss_get_id_range - Fetch a BSS table entry based on identifier range
969 * @wpa_s: Pointer to wpa_supplicant data
970 * @idf: Smallest allowed identifier assigned for the entry
971 * @idf: Largest allowed identifier assigned for the entry
972 * Returns: Pointer to the BSS entry or %NULL if not found
973 *
974 * This function is similar to wpa_bss_get_id() but allows a BSS entry with the
975 * smallest id value to be fetched within the specified range without the
976 * caller having to know the exact id.
977 */
978struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s,
979				      unsigned int idf, unsigned int idl)
980{
981	struct wpa_bss *bss;
982	dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
983		if (bss->id >= idf && bss->id <= idl)
984			return bss;
985	}
986	return NULL;
987}
988
989
990/**
991 * wpa_bss_get_ie - Fetch a specified information element from a BSS entry
992 * @bss: BSS table entry
993 * @ie: Information element identitifier (WLAN_EID_*)
994 * Returns: Pointer to the information element (id field) or %NULL if not found
995 *
996 * This function returns the first matching information element in the BSS
997 * entry.
998 */
999const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie)
1000{
1001	const u8 *end, *pos;
1002
1003	pos = (const u8 *) (bss + 1);
1004	end = pos + bss->ie_len;
1005
1006	while (pos + 1 < end) {
1007		if (pos + 2 + pos[1] > end)
1008			break;
1009		if (pos[0] == ie)
1010			return pos;
1011		pos += 2 + pos[1];
1012	}
1013
1014	return NULL;
1015}
1016
1017
1018/**
1019 * wpa_bss_get_vendor_ie - Fetch a vendor information element from a BSS entry
1020 * @bss: BSS table entry
1021 * @vendor_type: Vendor type (four octets starting the IE payload)
1022 * Returns: Pointer to the information element (id field) or %NULL if not found
1023 *
1024 * This function returns the first matching information element in the BSS
1025 * entry.
1026 */
1027const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type)
1028{
1029	const u8 *end, *pos;
1030
1031	pos = (const u8 *) (bss + 1);
1032	end = pos + bss->ie_len;
1033
1034	while (pos + 1 < end) {
1035		if (pos + 2 + pos[1] > end)
1036			break;
1037		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
1038		    vendor_type == WPA_GET_BE32(&pos[2]))
1039			return pos;
1040		pos += 2 + pos[1];
1041	}
1042
1043	return NULL;
1044}
1045
1046
1047/**
1048 * wpa_bss_get_vendor_ie_beacon - Fetch a vendor information from a BSS entry
1049 * @bss: BSS table entry
1050 * @vendor_type: Vendor type (four octets starting the IE payload)
1051 * Returns: Pointer to the information element (id field) or %NULL if not found
1052 *
1053 * This function returns the first matching information element in the BSS
1054 * entry.
1055 *
1056 * This function is like wpa_bss_get_vendor_ie(), but uses IE buffer only
1057 * from Beacon frames instead of either Beacon or Probe Response frames.
1058 */
1059const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss,
1060					u32 vendor_type)
1061{
1062	const u8 *end, *pos;
1063
1064	if (bss->beacon_ie_len == 0)
1065		return NULL;
1066
1067	pos = (const u8 *) (bss + 1);
1068	pos += bss->ie_len;
1069	end = pos + bss->beacon_ie_len;
1070
1071	while (pos + 1 < end) {
1072		if (pos + 2 + pos[1] > end)
1073			break;
1074		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
1075		    vendor_type == WPA_GET_BE32(&pos[2]))
1076			return pos;
1077		pos += 2 + pos[1];
1078	}
1079
1080	return NULL;
1081}
1082
1083
1084/**
1085 * wpa_bss_get_vendor_ie_multi - Fetch vendor IE data from a BSS entry
1086 * @bss: BSS table entry
1087 * @vendor_type: Vendor type (four octets starting the IE payload)
1088 * Returns: Pointer to the information element payload or %NULL if not found
1089 *
1090 * This function returns concatenated payload of possibly fragmented vendor
1091 * specific information elements in the BSS entry. The caller is responsible for
1092 * freeing the returned buffer.
1093 */
1094struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss,
1095					    u32 vendor_type)
1096{
1097	struct wpabuf *buf;
1098	const u8 *end, *pos;
1099
1100	buf = wpabuf_alloc(bss->ie_len);
1101	if (buf == NULL)
1102		return NULL;
1103
1104	pos = (const u8 *) (bss + 1);
1105	end = pos + bss->ie_len;
1106
1107	while (pos + 1 < end) {
1108		if (pos + 2 + pos[1] > end)
1109			break;
1110		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
1111		    vendor_type == WPA_GET_BE32(&pos[2]))
1112			wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4);
1113		pos += 2 + pos[1];
1114	}
1115
1116	if (wpabuf_len(buf) == 0) {
1117		wpabuf_free(buf);
1118		buf = NULL;
1119	}
1120
1121	return buf;
1122}
1123
1124
1125/**
1126 * wpa_bss_get_vendor_ie_multi_beacon - Fetch vendor IE data from a BSS entry
1127 * @bss: BSS table entry
1128 * @vendor_type: Vendor type (four octets starting the IE payload)
1129 * Returns: Pointer to the information element payload or %NULL if not found
1130 *
1131 * This function returns concatenated payload of possibly fragmented vendor
1132 * specific information elements in the BSS entry. The caller is responsible for
1133 * freeing the returned buffer.
1134 *
1135 * This function is like wpa_bss_get_vendor_ie_multi(), but uses IE buffer only
1136 * from Beacon frames instead of either Beacon or Probe Response frames.
1137 */
1138struct wpabuf * wpa_bss_get_vendor_ie_multi_beacon(const struct wpa_bss *bss,
1139						   u32 vendor_type)
1140{
1141	struct wpabuf *buf;
1142	const u8 *end, *pos;
1143
1144	buf = wpabuf_alloc(bss->beacon_ie_len);
1145	if (buf == NULL)
1146		return NULL;
1147
1148	pos = (const u8 *) (bss + 1);
1149	pos += bss->ie_len;
1150	end = pos + bss->beacon_ie_len;
1151
1152	while (pos + 1 < end) {
1153		if (pos + 2 + pos[1] > end)
1154			break;
1155		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
1156		    vendor_type == WPA_GET_BE32(&pos[2]))
1157			wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4);
1158		pos += 2 + pos[1];
1159	}
1160
1161	if (wpabuf_len(buf) == 0) {
1162		wpabuf_free(buf);
1163		buf = NULL;
1164	}
1165
1166	return buf;
1167}
1168
1169
1170/**
1171 * wpa_bss_get_max_rate - Get maximum legacy TX rate supported in a BSS
1172 * @bss: BSS table entry
1173 * Returns: Maximum legacy rate in units of 500 kbps
1174 */
1175int wpa_bss_get_max_rate(const struct wpa_bss *bss)
1176{
1177	int rate = 0;
1178	const u8 *ie;
1179	int i;
1180
1181	ie = wpa_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
1182	for (i = 0; ie && i < ie[1]; i++) {
1183		if ((ie[i + 2] & 0x7f) > rate)
1184			rate = ie[i + 2] & 0x7f;
1185	}
1186
1187	ie = wpa_bss_get_ie(bss, WLAN_EID_EXT_SUPP_RATES);
1188	for (i = 0; ie && i < ie[1]; i++) {
1189		if ((ie[i + 2] & 0x7f) > rate)
1190			rate = ie[i + 2] & 0x7f;
1191	}
1192
1193	return rate;
1194}
1195
1196
1197/**
1198 * wpa_bss_get_bit_rates - Get legacy TX rates supported in a BSS
1199 * @bss: BSS table entry
1200 * @rates: Buffer for returning a pointer to the rates list (units of 500 kbps)
1201 * Returns: number of legacy TX rates or -1 on failure
1202 *
1203 * The caller is responsible for freeing the returned buffer with os_free() in
1204 * case of success.
1205 */
1206int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates)
1207{
1208	const u8 *ie, *ie2;
1209	int i, j;
1210	unsigned int len;
1211	u8 *r;
1212
1213	ie = wpa_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
1214	ie2 = wpa_bss_get_ie(bss, WLAN_EID_EXT_SUPP_RATES);
1215
1216	len = (ie ? ie[1] : 0) + (ie2 ? ie2[1] : 0);
1217
1218	r = os_malloc(len);
1219	if (!r)
1220		return -1;
1221
1222	for (i = 0; ie && i < ie[1]; i++)
1223		r[i] = ie[i + 2] & 0x7f;
1224
1225	for (j = 0; ie2 && j < ie2[1]; j++)
1226		r[i + j] = ie2[j + 2] & 0x7f;
1227
1228	*rates = r;
1229	return len;
1230}
1231