scan: station: parse HS20 version in scan results

For (Re)Association the HS20 indication element was passed exactly as
it was found in the scan results. The spec defines what bits can be
set and what cannot when this IE is used in (Re)Association. Instead
of assuming the AP's IE conforms to the spec, we now parse the IE and
re-build it for use with (Re)Association.

Since the full IE is no longer used, it was removed from scan_bss, and
replaced with a bit for HS20 support (hs20_capable). This member is
now used the same as hs20_ie was.

The version parsed during scan results is now used when building the
(Re)Association IE.
This commit is contained in:
James Prestwood 2019-07-24 13:09:46 -07:00 committed by Denis Kenzior
parent 6088c06507
commit 1fdea9b2d3
4 changed files with 17 additions and 10 deletions

View File

@ -715,7 +715,7 @@ bool network_bss_add(struct network *network, struct scan_bss *bss)
if (bss->rc_ie && !network->rc_ie)
network->rc_ie = l_memdup(bss->rc_ie, bss->rc_ie[1] + 2);
if (bss->hs20_ie)
if (bss->hs20_capable)
network->is_hs20 = true;
return true;

View File

@ -741,9 +741,13 @@ static bool scan_parse_vendor_specific(struct scan_bss *bss, const void *data,
bss->wpa = l_memdup(data - 2, len + 2);
else if (!bss->osen && is_ie_wfa_ie(data, len, IE_WFA_OI_OSEN))
bss->osen = l_memdup(data - 2, len + 2);
else if (is_ie_wfa_ie(data, len, IE_WFA_OI_HS20_INDICATION))
bss->hs20_ie = l_memdup(data - 2, len + 2);
else
else if (is_ie_wfa_ie(data, len, IE_WFA_OI_HS20_INDICATION)) {
if (ie_parse_hs20_indication_from_data(data - 2, len + 2,
&bss->hs20_version, NULL, NULL) < 0)
return false;
bss->hs20_capable = true;
} else
return false;
return true;
@ -1132,7 +1136,6 @@ void scan_bss_free(struct scan_bss *bss)
l_free(bss->p2p);
l_free(bss->osen);
l_free(bss->rc_ie);
l_free(bss->hs20_ie);
l_free(bss);
}

View File

@ -66,7 +66,7 @@ struct scan_bss {
uint64_t time_stamp;
uint8_t hessid[6];
uint8_t *rc_ie; /* Roaming consortium IE */
uint8_t *hs20_ie;
uint8_t hs20_version;
bool mde_present : 1;
bool cc_present : 1;
bool cap_rm_neighbor_report : 1;
@ -74,6 +74,7 @@ struct scan_bss {
bool ht_capable : 1;
bool vht_capable : 1;
bool anqp_capable : 1;
bool hs20_capable : 1;
};
struct scan_parameters {

View File

@ -460,7 +460,7 @@ static bool station_start_anqp(struct station *station, struct network *network,
struct anqp_entry *entry;
bool anqp_disabled = true;
if (!bss->hs20_ie)
if (!bss->hs20_capable)
return false;
/* Network already has ANQP data/HESSID */
@ -2181,6 +2181,7 @@ int __station_connect_network(struct station *station, struct network *network,
struct scan_bss *bss)
{
const uint8_t *rc = NULL;
uint8_t hs20_ie[7];
size_t rc_len = 0;
uint8_t rc_buf[32];
struct iovec iov[2];
@ -2192,10 +2193,12 @@ int __station_connect_network(struct station *station, struct network *network,
if (!hs)
return -ENOTSUP;
if (bss->hs20_ie) {
if (bss->hs20_capable) {
/* Include HS20 Indication with (Re)Association */
iov[iov_elems].iov_base = bss->hs20_ie;
iov[iov_elems].iov_len = bss->hs20_ie[1] + 2;
ie_build_hs20_indication(bss->hs20_version, hs20_ie);
iov[iov_elems].iov_base = hs20_ie;
iov[iov_elems].iov_len = hs20_ie[1] + 2;
iov_elems++;
/*