#include "utils/eloop.h"
#include "common/ieee802_11_defs.h"
#include "drivers/driver.h"
+#include "eap_peer/eap.h"
#include "wpa_supplicant_i.h"
#include "config.h"
#include "notify.h"
anqp = os_zalloc(sizeof(*anqp));
if (anqp == NULL)
return NULL;
+#ifdef CONFIG_INTERWORKING
+ dl_list_init(&anqp->anqp_elems);
+#endif /* CONFIG_INTERWORKING */
anqp->users = 1;
return anqp;
}
#define ANQP_DUP(f) if (anqp->f) n->f = wpabuf_dup(anqp->f)
#ifdef CONFIG_INTERWORKING
+ dl_list_init(&n->anqp_elems);
ANQP_DUP(capability_list);
ANQP_DUP(venue_name);
ANQP_DUP(network_auth_type);
*/
static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp)
{
+#ifdef CONFIG_INTERWORKING
+ struct wpa_bss_anqp_elem *elem;
+#endif /* CONFIG_INTERWORKING */
+
if (anqp == NULL)
return;
wpabuf_free(anqp->nai_realm);
wpabuf_free(anqp->anqp_3gpp);
wpabuf_free(anqp->domain_name);
+
+ while ((elem = dl_list_first(&anqp->anqp_elems,
+ struct wpa_bss_anqp_elem, list))) {
+ dl_list_del(&elem->list);
+ wpabuf_free(elem->payload);
+ os_free(elem);
+ }
#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_HS20
wpabuf_free(anqp->hs20_capability_list);
}
+static int wpa_bss_is_wps_candidate(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss)
+{
+#ifdef CONFIG_WPS
+ struct wpa_ssid *ssid;
+ struct wpabuf *wps_ie;
+ int pbc = 0, ret;
+
+ wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
+ if (!wps_ie)
+ return 0;
+
+ if (wps_is_selected_pbc_registrar(wps_ie)) {
+ pbc = 1;
+ } else if (!wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1)) {
+ wpabuf_free(wps_ie);
+ return 0;
+ }
+
+ for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
+ if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS))
+ continue;
+ if (ssid->ssid_len &&
+ (ssid->ssid_len != bss->ssid_len ||
+ os_memcmp(ssid->ssid, bss->ssid, ssid->ssid_len) != 0))
+ continue;
+
+ if (pbc)
+ ret = eap_is_wps_pbc_enrollee(&ssid->eap);
+ else
+ ret = eap_is_wps_pin_enrollee(&ssid->eap);
+ wpabuf_free(wps_ie);
+ return ret;
+ }
+ wpabuf_free(wps_ie);
+#endif /* CONFIG_WPS */
+
+ return 0;
+}
+
+
static int wpa_bss_known(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
{
struct wpa_ssid *ssid;
static int wpa_bss_in_use(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
{
- return bss == wpa_s->current_bss ||
- (!is_zero_ether_addr(bss->bssid) &&
- (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) == 0 ||
- os_memcmp(bss->bssid, wpa_s->pending_bssid, ETH_ALEN) == 0));
+ if (bss == wpa_s->current_bss)
+ return 1;
+
+ if (wpa_s->current_bss &&
+ (bss->ssid_len != wpa_s->current_bss->ssid_len ||
+ os_memcmp(bss->ssid, wpa_s->current_bss->ssid,
+ bss->ssid_len) != 0))
+ return 0; /* SSID has changed */
+
+ return !is_zero_ether_addr(bss->bssid) &&
+ (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) == 0 ||
+ os_memcmp(bss->bssid, wpa_s->pending_bssid, ETH_ALEN) == 0);
}
struct wpa_bss *bss;
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
- if (!wpa_bss_known(wpa_s, bss)) {
+ if (!wpa_bss_known(wpa_s, bss) &&
+ !wpa_bss_is_wps_candidate(wpa_s, bss)) {
wpa_bss_remove(wpa_s, bss, __func__);
return 0;
}
dl_list_add_tail(&wpa_s->bss_id, &bss->list_id);
wpa_s->num_bss++;
wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Add new id %u BSSID " MACSTR
- " SSID '%s'",
- bss->id, MAC2STR(bss->bssid), wpa_ssid_txt(ssid, ssid_len));
+ " SSID '%s' freq %d",
+ bss->id, MAC2STR(bss->bssid), wpa_ssid_txt(ssid, ssid_len),
+ bss->freq);
wpas_notify_bss_added(wpa_s, bss->bssid, bss->id);
return bss;
}
u32 changes;
changes = wpa_bss_compare_res(bss, res);
+ if (changes & WPA_BSS_FREQ_CHANGED_FLAG)
+ wpa_printf(MSG_DEBUG, "BSS: " MACSTR " changed freq %d --> %d",
+ MAC2STR(bss->bssid), bss->freq, res->freq);
bss->scan_miss_count = 0;
bss->last_update_idx = wpa_s->bss_update_idx;
wpa_bss_copy_res(bss, res, fetch_time);
struct wpa_bss *bss, *n;
os_get_reltime(&wpa_s->last_scan);
- if (!new_scan)
+ if ((info && info->aborted) || !new_scan)
return; /* do not expire entries without new scan */
dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
*/
const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie)
{
- const u8 *end, *pos;
-
- pos = (const u8 *) (bss + 1);
- end = pos + bss->ie_len;
-
- while (pos + 1 < end) {
- if (pos + 2 + pos[1] > end)
- break;
- if (pos[0] == ie)
- return pos;
- pos += 2 + pos[1];
- }
-
- return NULL;
+ return get_ie((const u8 *) (bss + 1), bss->ie_len, ie);
}
pos = (const u8 *) (bss + 1);
end = pos + bss->ie_len;
- while (pos + 1 < end) {
- if (pos + 2 + pos[1] > end)
+ while (end - pos > 1) {
+ if (2 + pos[1] > end - pos)
break;
if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
vendor_type == WPA_GET_BE32(&pos[2]))
pos += bss->ie_len;
end = pos + bss->beacon_ie_len;
- while (pos + 1 < end) {
- if (pos + 2 + pos[1] > end)
+ while (end - pos > 1) {
+ if (2 + pos[1] > end - pos)
break;
if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
vendor_type == WPA_GET_BE32(&pos[2]))
pos = (const u8 *) (bss + 1);
end = pos + bss->ie_len;
- while (pos + 1 < end) {
- if (pos + 2 + pos[1] > end)
+ while (end - pos > 1) {
+ if (2 + pos[1] > end - pos)
break;
if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
vendor_type == WPA_GET_BE32(&pos[2]))
pos += bss->ie_len;
end = pos + bss->beacon_ie_len;
- while (pos + 1 < end) {
- if (pos + 2 + pos[1] > end)
+ while (end - pos > 1) {
+ if (2 + pos[1] > end - pos)
break;
if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
vendor_type == WPA_GET_BE32(&pos[2]))