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