Fetch IEs from both Beacon and Probe Response frames if available
This allows the driver wrappers to return two sets of IEs, so that the BSS code can use information from both Beacon and Probe Response frames if needed. For example, some Cisco APs seem to include more information in Wireless Provisioning Services IE when it is in the Beacon frame.
This commit is contained in:
parent
94627f6cc8
commit
8c0906542c
4 changed files with 45 additions and 13 deletions
|
@ -132,6 +132,7 @@ struct hostapd_hw_modes {
|
||||||
* @age: Age of the information in milliseconds (i.e., how many milliseconds
|
* @age: Age of the information in milliseconds (i.e., how many milliseconds
|
||||||
* ago the last Beacon or Probe Response frame was received)
|
* ago the last Beacon or Probe Response frame was received)
|
||||||
* @ie_len: length of the following IE field in octets
|
* @ie_len: length of the following IE field in octets
|
||||||
|
* @beacon_ie_len: length of the following Beacon IE field in octets
|
||||||
*
|
*
|
||||||
* This structure is used as a generic format for scan results from the
|
* This structure is used as a generic format for scan results from the
|
||||||
* driver. Each driver interface implementation is responsible for converting
|
* driver. Each driver interface implementation is responsible for converting
|
||||||
|
@ -154,7 +155,14 @@ struct wpa_scan_res {
|
||||||
u64 tsf;
|
u64 tsf;
|
||||||
unsigned int age;
|
unsigned int age;
|
||||||
size_t ie_len;
|
size_t ie_len;
|
||||||
/* followed by ie_len octets of IEs */
|
size_t beacon_ie_len;
|
||||||
|
/*
|
||||||
|
* Followed by ie_len octets of IEs from Probe Response frame (or if
|
||||||
|
* the driver does not indicate source of IEs, these may also be from
|
||||||
|
* Beacon frame). After the first set of IEs, another set of IEs may
|
||||||
|
* follow (with beacon_ie_len octets of data) if the driver provides
|
||||||
|
* both IE sets.
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1481,12 +1481,14 @@ static int bss_info_handler(struct nl_msg *msg, void *arg)
|
||||||
[NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
|
[NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
|
||||||
[NL80211_BSS_STATUS] = { .type = NLA_U32 },
|
[NL80211_BSS_STATUS] = { .type = NLA_U32 },
|
||||||
[NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },
|
[NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },
|
||||||
|
[NL80211_BSS_BEACON_IES] = { .type = NLA_UNSPEC },
|
||||||
};
|
};
|
||||||
struct wpa_scan_results *res = arg;
|
struct wpa_scan_results *res = arg;
|
||||||
struct wpa_scan_res **tmp;
|
struct wpa_scan_res **tmp;
|
||||||
struct wpa_scan_res *r;
|
struct wpa_scan_res *r;
|
||||||
const u8 *ie;
|
const u8 *ie, *beacon_ie;
|
||||||
size_t ie_len;
|
size_t ie_len, beacon_ie_len;
|
||||||
|
u8 *pos;
|
||||||
|
|
||||||
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
|
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
|
||||||
genlmsg_attrlen(gnlh, 0), NULL);
|
genlmsg_attrlen(gnlh, 0), NULL);
|
||||||
|
@ -1502,8 +1504,15 @@ static int bss_info_handler(struct nl_msg *msg, void *arg)
|
||||||
ie = NULL;
|
ie = NULL;
|
||||||
ie_len = 0;
|
ie_len = 0;
|
||||||
}
|
}
|
||||||
|
if (bss[NL80211_BSS_BEACON_IES]) {
|
||||||
|
beacon_ie = nla_data(bss[NL80211_BSS_BEACON_IES]);
|
||||||
|
beacon_ie_len = nla_len(bss[NL80211_BSS_BEACON_IES]);
|
||||||
|
} else {
|
||||||
|
beacon_ie = NULL;
|
||||||
|
beacon_ie_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
r = os_zalloc(sizeof(*r) + ie_len);
|
r = os_zalloc(sizeof(*r) + ie_len + beacon_ie_len);
|
||||||
if (r == NULL)
|
if (r == NULL)
|
||||||
return NL_SKIP;
|
return NL_SKIP;
|
||||||
if (bss[NL80211_BSS_BSSID])
|
if (bss[NL80211_BSS_BSSID])
|
||||||
|
@ -1530,8 +1539,14 @@ static int bss_info_handler(struct nl_msg *msg, void *arg)
|
||||||
if (bss[NL80211_BSS_SEEN_MS_AGO])
|
if (bss[NL80211_BSS_SEEN_MS_AGO])
|
||||||
r->age = nla_get_u32(bss[NL80211_BSS_SEEN_MS_AGO]);
|
r->age = nla_get_u32(bss[NL80211_BSS_SEEN_MS_AGO]);
|
||||||
r->ie_len = ie_len;
|
r->ie_len = ie_len;
|
||||||
if (ie)
|
pos = (u8 *) (r + 1);
|
||||||
os_memcpy(r + 1, ie, ie_len);
|
if (ie) {
|
||||||
|
os_memcpy(pos, ie, ie_len);
|
||||||
|
pos += ie_len;
|
||||||
|
}
|
||||||
|
r->beacon_ie_len = beacon_ie_len;
|
||||||
|
if (beacon_ie)
|
||||||
|
os_memcpy(pos, beacon_ie, beacon_ie_len);
|
||||||
|
|
||||||
if (bss[NL80211_BSS_STATUS]) {
|
if (bss[NL80211_BSS_STATUS]) {
|
||||||
enum nl80211_bss_status status;
|
enum nl80211_bss_status status;
|
||||||
|
|
|
@ -120,7 +120,7 @@ static void wpa_bss_add(struct wpa_supplicant *wpa_s,
|
||||||
{
|
{
|
||||||
struct wpa_bss *bss;
|
struct wpa_bss *bss;
|
||||||
|
|
||||||
bss = os_zalloc(sizeof(*bss) + res->ie_len);
|
bss = os_zalloc(sizeof(*bss) + res->ie_len + res->beacon_ie_len);
|
||||||
if (bss == NULL)
|
if (bss == NULL)
|
||||||
return;
|
return;
|
||||||
bss->id = wpa_s->bss_next_id++;
|
bss->id = wpa_s->bss_next_id++;
|
||||||
|
@ -129,7 +129,8 @@ static void wpa_bss_add(struct wpa_supplicant *wpa_s,
|
||||||
os_memcpy(bss->ssid, ssid, ssid_len);
|
os_memcpy(bss->ssid, ssid, ssid_len);
|
||||||
bss->ssid_len = ssid_len;
|
bss->ssid_len = ssid_len;
|
||||||
bss->ie_len = res->ie_len;
|
bss->ie_len = res->ie_len;
|
||||||
os_memcpy(bss + 1, res + 1, res->ie_len);
|
bss->beacon_ie_len = res->beacon_ie_len;
|
||||||
|
os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len);
|
||||||
|
|
||||||
dl_list_add_tail(&wpa_s->bss, &bss->list);
|
dl_list_add_tail(&wpa_s->bss, &bss->list);
|
||||||
dl_list_add_tail(&wpa_s->bss_id, &bss->list_id);
|
dl_list_add_tail(&wpa_s->bss_id, &bss->list_id);
|
||||||
|
@ -273,18 +274,23 @@ static void wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
|
||||||
wpa_bss_copy_res(bss, res);
|
wpa_bss_copy_res(bss, res);
|
||||||
/* Move the entry to the end of the list */
|
/* Move the entry to the end of the list */
|
||||||
dl_list_del(&bss->list);
|
dl_list_del(&bss->list);
|
||||||
if (bss->ie_len >= res->ie_len) {
|
if (bss->ie_len + bss->beacon_ie_len >=
|
||||||
os_memcpy(bss + 1, res + 1, res->ie_len);
|
res->ie_len + res->beacon_ie_len) {
|
||||||
|
os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len);
|
||||||
bss->ie_len = res->ie_len;
|
bss->ie_len = res->ie_len;
|
||||||
|
bss->beacon_ie_len = res->beacon_ie_len;
|
||||||
} else {
|
} else {
|
||||||
struct wpa_bss *nbss;
|
struct wpa_bss *nbss;
|
||||||
struct dl_list *prev = bss->list_id.prev;
|
struct dl_list *prev = bss->list_id.prev;
|
||||||
dl_list_del(&bss->list_id);
|
dl_list_del(&bss->list_id);
|
||||||
nbss = os_realloc(bss, sizeof(*bss) + res->ie_len);
|
nbss = os_realloc(bss, sizeof(*bss) + res->ie_len +
|
||||||
|
res->beacon_ie_len);
|
||||||
if (nbss) {
|
if (nbss) {
|
||||||
bss = nbss;
|
bss = nbss;
|
||||||
os_memcpy(bss + 1, res + 1, res->ie_len);
|
os_memcpy(bss + 1, res + 1,
|
||||||
|
res->ie_len + res->beacon_ie_len);
|
||||||
bss->ie_len = res->ie_len;
|
bss->ie_len = res->ie_len;
|
||||||
|
bss->beacon_ie_len = res->beacon_ie_len;
|
||||||
}
|
}
|
||||||
dl_list_add(prev, &bss->list_id);
|
dl_list_add(prev, &bss->list_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,8 @@ struct wpa_scan_res;
|
||||||
* @level: signal level
|
* @level: signal level
|
||||||
* @tsf: Timestamp of last Beacon/Probe Response frame
|
* @tsf: Timestamp of last Beacon/Probe Response frame
|
||||||
* @last_update: Time of the last update (i.e., Beacon or Probe Response RX)
|
* @last_update: Time of the last update (i.e., Beacon or Probe Response RX)
|
||||||
* @ie_len: length of the following IE field in octets
|
* @ie_len: length of the following IE field in octets (from Probe Response)
|
||||||
|
* @beacon_ie_len: length of the following Beacon IE field in octets
|
||||||
*
|
*
|
||||||
* This structure is used to store information about neighboring BSSes in
|
* This structure is used to store information about neighboring BSSes in
|
||||||
* generic format. It is mainly updated based on scan results from the driver.
|
* generic format. It is mainly updated based on scan results from the driver.
|
||||||
|
@ -65,7 +66,9 @@ struct wpa_bss {
|
||||||
u64 tsf;
|
u64 tsf;
|
||||||
struct os_time last_update;
|
struct os_time last_update;
|
||||||
size_t ie_len;
|
size_t ie_len;
|
||||||
|
size_t beacon_ie_len;
|
||||||
/* followed by ie_len octets of IEs */
|
/* followed by ie_len octets of IEs */
|
||||||
|
/* followed by beacon_ie_len octets of IEs */
|
||||||
};
|
};
|
||||||
|
|
||||||
void wpa_bss_update_start(struct wpa_supplicant *wpa_s);
|
void wpa_bss_update_start(struct wpa_supplicant *wpa_s);
|
||||||
|
|
Loading…
Reference in a new issue