From 1fdea9b2d326d78607ea9c10827b4aaa527c6504 Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Wed, 24 Jul 2019 13:09:46 -0700 Subject: [PATCH] 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. --- src/network.c | 2 +- src/scan.c | 11 +++++++---- src/scan.h | 3 ++- src/station.c | 11 +++++++---- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/network.c b/src/network.c index 46205b97..d2203916 100644 --- a/src/network.c +++ b/src/network.c @@ -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; diff --git a/src/scan.c b/src/scan.c index b8c790d9..6804096f 100644 --- a/src/scan.c +++ b/src/scan.c @@ -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); } diff --git a/src/scan.h b/src/scan.h index 4d482681..d2c336b8 100644 --- a/src/scan.h +++ b/src/scan.h @@ -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 { diff --git a/src/station.c b/src/station.c index 9f881cfd..cb2537d0 100644 --- a/src/station.c +++ b/src/station.c @@ -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++; /*