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) if (bss->rc_ie && !network->rc_ie)
network->rc_ie = l_memdup(bss->rc_ie, bss->rc_ie[1] + 2); 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; network->is_hs20 = true;
return 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); bss->wpa = l_memdup(data - 2, len + 2);
else if (!bss->osen && is_ie_wfa_ie(data, len, IE_WFA_OI_OSEN)) else if (!bss->osen && is_ie_wfa_ie(data, len, IE_WFA_OI_OSEN))
bss->osen = l_memdup(data - 2, len + 2); bss->osen = l_memdup(data - 2, len + 2);
else if (is_ie_wfa_ie(data, len, IE_WFA_OI_HS20_INDICATION)) else if (is_ie_wfa_ie(data, len, IE_WFA_OI_HS20_INDICATION)) {
bss->hs20_ie = l_memdup(data - 2, len + 2); if (ie_parse_hs20_indication_from_data(data - 2, len + 2,
else &bss->hs20_version, NULL, NULL) < 0)
return false;
bss->hs20_capable = true;
} else
return false; return false;
return true; return true;
@ -1132,7 +1136,6 @@ void scan_bss_free(struct scan_bss *bss)
l_free(bss->p2p); l_free(bss->p2p);
l_free(bss->osen); l_free(bss->osen);
l_free(bss->rc_ie); l_free(bss->rc_ie);
l_free(bss->hs20_ie);
l_free(bss); l_free(bss);
} }

View File

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

View File

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