diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index a19ac269a..03234589a 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -55,6 +55,7 @@ static void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) { dl_list_del(&bss->list); + dl_list_del(&bss->list_id); wpa_s->num_bss--; wpa_printf(MSG_DEBUG, "BSS: Remove id %u BSSID " MACSTR " SSID '%s'", bss->id, MAC2STR(bss->bssid), @@ -122,6 +123,7 @@ static void wpa_bss_add(struct wpa_supplicant *wpa_s, os_memcpy(bss + 1, res + 1, res->ie_len); dl_list_add_tail(&wpa_s->bss, &bss->list); + dl_list_add_tail(&wpa_s->bss_id, &bss->list_id); wpa_s->num_bss++; wpa_printf(MSG_DEBUG, "BSS: Add new id %u BSSID " MACSTR " SSID '%s'", bss->id, MAC2STR(bss->bssid), wpa_ssid_txt(ssid, ssid_len)); @@ -247,6 +249,7 @@ static void wpa_bss_timeout(void *eloop_ctx, void *timeout_ctx) int wpa_bss_init(struct wpa_supplicant *wpa_s) { dl_list_init(&wpa_s->bss); + dl_list_init(&wpa_s->bss_id); eloop_register_timeout(WPA_BSS_EXPIRATION_PERIOD, 0, wpa_bss_timeout, wpa_s, NULL); return 0; @@ -260,3 +263,96 @@ void wpa_bss_deinit(struct wpa_supplicant *wpa_s) dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) wpa_bss_remove(wpa_s, bss); } + + +struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s, + const u8 *bssid) +{ + struct wpa_bss *bss; + dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { + if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0) + return bss; + } + return NULL; +} + + +struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id) +{ + struct wpa_bss *bss; + dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { + if (bss->id == id) + return bss; + } + return NULL; +} + + +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; +} + + +const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type) +{ + 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] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && + vendor_type == WPA_GET_BE32(&pos[2])) + return pos; + pos += 2 + pos[1]; + } + + return NULL; +} + + +struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss, + u32 vendor_type) +{ + struct wpabuf *buf; + const u8 *end, *pos; + + buf = wpabuf_alloc(bss->ie_len); + if (buf == NULL) + return NULL; + + pos = (const u8 *) (bss + 1); + end = pos + bss->ie_len; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && + vendor_type == WPA_GET_BE32(&pos[2])) + wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4); + pos += 2 + pos[1]; + } + + if (wpabuf_len(buf) == 0) { + wpabuf_free(buf); + buf = NULL; + } + + return buf; +} diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index dde4ed9b6..e861e8a3e 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -25,6 +25,7 @@ /** * struct wpa_bss - BSS table * @list: List entry for struct wpa_supplicant::bss + * @list_id: List entry for struct wpa_supplicant::bss_id * @id: Unique identifier for this BSS entry * @scan_miss_count: Number of counts without seeing this BSS * @flags: information flags about the BSS/IBSS (WPA_BSS_*) @@ -45,6 +46,7 @@ */ struct wpa_bss { struct dl_list list; + struct dl_list list_id; unsigned int id; unsigned int scan_miss_count; unsigned int last_update_idx; @@ -70,5 +72,12 @@ void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s, void wpa_bss_update_end(struct wpa_supplicant *wpa_s); int wpa_bss_init(struct wpa_supplicant *wpa_s); void wpa_bss_deinit(struct wpa_supplicant *wpa_s); +struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s, + const u8 *bssid); +struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id); +const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie); +const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type); +struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss, + u32 vendor_type); #endif /* BSS_H */ diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 67f67b5ed..03d85f146 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -346,6 +346,7 @@ struct wpa_supplicant { struct wpa_scan_results *scan_res; struct dl_list bss; /* struct wpa_bss::list */ + struct dl_list bss_id; /* struct wpa_bss::list_id */ size_t num_bss; unsigned int bss_update_idx; unsigned int bss_next_id;