scan: use structure for OWE transition parsing

This changes scan_bss from using separate members for each
OWE transition element data type (ssid, ssid_len, and bssid)
to a structure that holds them all.

This is being done because OWE transition has option operating
class and channel bytes which will soon be parsed. This would
end up needing 5 separate members in scan_bss which is a bit
much for a single IE that needs to be parsed.

This makes checking the presense of the IE more convenient
as well since it can be done with a simple NULL pointer check
rather than having to l_memeqzero the BSSID.
This commit is contained in:
James Prestwood 2021-09-22 11:26:51 -07:00 committed by Denis Kenzior
parent 421f068903
commit 22ff2a5f79
6 changed files with 47 additions and 50 deletions

View File

@ -2501,9 +2501,7 @@ int ie_parse_network_cost(const void *data, size_t len,
} }
int ie_parse_owe_transition(const void *data, size_t len, int ie_parse_owe_transition(const void *data, size_t len,
uint8_t bssid[static 6], struct ie_owe_transition_info *info)
uint8_t ssid[static 32],
size_t *ssid_len)
{ {
const uint8_t *ie = data; const uint8_t *ie = data;
size_t slen; size_t slen;
@ -2535,10 +2533,10 @@ int ie_parse_owe_transition(const void *data, size_t len,
if (len != slen + 13) if (len != slen + 13)
return -ENOMSG; return -ENOMSG;
memcpy(bssid, ie + 6, 6); memcpy(info->bssid, ie + 6, 6);
memcpy(ssid, ie + 13, slen); memcpy(info->ssid, ie + 13, slen);
*ssid_len = slen; info->ssid_len = slen;
return 0; return 0;
} }

View File

@ -640,6 +640,4 @@ int ie_parse_network_cost(const void *data, size_t len,
uint16_t *flags, uint16_t *level); uint16_t *flags, uint16_t *level);
int ie_parse_owe_transition(const void *data, size_t len, int ie_parse_owe_transition(const void *data, size_t len,
uint8_t bssid[static 6], struct ie_owe_transition_info *info);
uint8_t ssid[static 32],
size_t *ssid_len);

View File

@ -1110,11 +1110,6 @@ const struct l_queue_entry *network_bss_list_get_entries(
return l_queue_get_entries(network->bss_list); return l_queue_get_entries(network->bss_list);
} }
static bool bss_is_owe(struct scan_bss *bss)
{
return !l_memeqzero(bss->owe_trans_bssid, 6) && bss->rsne;
}
struct scan_bss *network_bss_select(struct network *network, struct scan_bss *network_bss_select(struct network *network,
bool fallback_to_blacklist) bool fallback_to_blacklist)
{ {
@ -1141,13 +1136,13 @@ struct scan_bss *network_bss_select(struct network *network,
candidate = bss; candidate = bss;
/* OWE Transition BSS */ /* OWE Transition BSS */
if (!l_memeqzero(bss->owe_trans_bssid, 6)) { if (!bss->owe_trans) {
/* Don't want to connect to the Open BSS if possible */ /* Don't want to connect to the Open BSS if possible */
if (!bss->rsne) if (!bss->rsne)
continue; continue;
/* Candidate is not OWE, set this as new candidate */ /* Candidate is not OWE, set this as new candidate */
if (!bss_is_owe(candidate)) if (!(candidate->owe_trans && candidate->rsne))
candidate = bss; candidate = bss;
} }

View File

@ -686,8 +686,8 @@ static void add_owe_scan_cmd(struct scan_context *sc, struct scan_request *sr,
} else } else
params.freqs = freqs; params.freqs = freqs;
params.ssid = bss->owe_trans_ssid; params.ssid = bss->owe_trans->ssid;
params.ssid_len = bss->owe_trans_ssid_len; params.ssid_len = bss->owe_trans->ssid_len;
params.flush = true; params.flush = true;
cmd = scan_build_cmd(sc, ignore_flush, false, &params); cmd = scan_build_cmd(sc, ignore_flush, false, &params);
@ -736,14 +736,14 @@ uint32_t scan_owe_hidden(uint64_t wdev_id, struct l_queue *list,
/* First */ /* First */
if (!ssid) { if (!ssid) {
ssid = bss->owe_trans_ssid; ssid = bss->owe_trans->ssid;
ssid_len = bss->owe_trans_ssid_len; ssid_len = bss->owe_trans->ssid_len;
continue; continue;
} }
if (ssid_len == bss->owe_trans_ssid_len && if (ssid_len == bss->owe_trans->ssid_len &&
!memcmp(ssid, bss->owe_trans_ssid, !memcmp(ssid, bss->owe_trans->ssid,
bss->owe_trans_ssid_len)) bss->owe_trans->ssid_len))
continue; continue;
same_ssid = false; same_ssid = false;
@ -1060,9 +1060,14 @@ static void scan_parse_vendor_specific(struct scan_bss *bss, const void *data,
} }
if (is_ie_wfa_ie(data, len, IE_WFA_OI_OWE_TRANSITION)) { if (is_ie_wfa_ie(data, len, IE_WFA_OI_OWE_TRANSITION)) {
ie_parse_owe_transition(data - 2, len + 2, bss->owe_trans_bssid, bss->owe_trans = l_new(struct ie_owe_transition_info, 1);
bss->owe_trans_ssid,
&bss->owe_trans_ssid_len); if (ie_parse_owe_transition(data - 2, len + 2,
bss->owe_trans) < 0) {
l_free(bss->owe_trans);
bss->owe_trans = NULL;
}
return; return;
} }
@ -1511,6 +1516,7 @@ void scan_bss_free(struct scan_bss *bss)
l_free(bss->osen); l_free(bss->osen);
l_free(bss->rc_ie); l_free(bss->rc_ie);
l_free(bss->wfd); l_free(bss->wfd);
l_free(bss->owe_trans);
switch (bss->source_frame) { switch (bss->source_frame) {
case SCAN_BSS_PROBE_RESP: case SCAN_BSS_PROBE_RESP:

View File

@ -22,6 +22,7 @@
struct scan_freq_set; struct scan_freq_set;
struct ie_rsn_info; struct ie_rsn_info;
struct ie_owe_transition_info;
struct p2p_probe_resp; struct p2p_probe_resp;
struct p2p_probe_req; struct p2p_probe_req;
struct p2p_beacon; struct p2p_beacon;
@ -62,6 +63,7 @@ struct scan_bss {
struct p2p_probe_req *p2p_probe_req_info; struct p2p_probe_req *p2p_probe_req_info;
struct p2p_beacon *p2p_beacon_info; struct p2p_beacon *p2p_beacon_info;
}; };
struct ie_owe_transition_info *owe_trans;
uint8_t mde[3]; uint8_t mde[3];
uint8_t ssid[32]; uint8_t ssid[32];
uint8_t ssid_len; uint8_t ssid_len;
@ -76,9 +78,6 @@ struct scan_bss {
uint64_t parent_tsf; uint64_t parent_tsf;
uint8_t *wfd; /* Concatenated WFD IEs */ uint8_t *wfd; /* Concatenated WFD IEs */
ssize_t wfd_size; /* Size of Concatenated WFD IEs */ ssize_t wfd_size; /* Size of Concatenated WFD IEs */
uint8_t owe_trans_ssid[32];
size_t owe_trans_ssid_len;
uint8_t owe_trans_bssid[6];
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;

View File

@ -400,8 +400,8 @@ static struct network *station_add_seen_bss(struct station *station,
return NULL; return NULL;
/* Hidden OWE transition network */ /* Hidden OWE transition network */
if (security == SECURITY_NONE && bss->rsne && if (security == SECURITY_NONE && bss->rsne && bss->owe_trans) {
!l_memeqzero(bss->owe_trans_bssid, 6)) { struct ie_owe_transition_info *info = bss->owe_trans;
/* /*
* WiFi Alliance OWE Specification v1.1 - Section 2.2.1: * WiFi Alliance OWE Specification v1.1 - Section 2.2.1:
* *
@ -420,18 +420,17 @@ static struct network *station_add_seen_bss(struct station *station,
* we could not look up the network. Note that this is not true * we could not look up the network. Note that this is not true
* for the open BSS IE, it can be non-utf8. * for the open BSS IE, it can be non-utf8.
*/ */
if (!util_ssid_is_utf8(bss->owe_trans_ssid_len, if (!util_ssid_is_utf8(info->ssid_len, info->ssid))
bss->owe_trans_ssid))
return NULL; return NULL;
if (!memcmp(bss->owe_trans_ssid, bss->ssid, bss->ssid_len)) if (!memcmp(info->ssid, bss->ssid, bss->ssid_len))
return NULL; return NULL;
if (!memcmp(bss->owe_trans_bssid, bss->addr, 6)) if (!memcmp(info->bssid, bss->addr, 6))
return NULL; return NULL;
memcpy(ssid, bss->owe_trans_ssid, sizeof(bss->owe_trans_ssid)); memcpy(ssid, info->ssid, info->ssid_len);
ssid[bss->owe_trans_ssid_len] = '\0'; ssid[info->ssid_len] = '\0';
l_debug("Found hidden OWE network, using %s for network lookup", l_debug("Found hidden OWE network, using %s for network lookup",
ssid); ssid);
@ -690,10 +689,12 @@ static bool station_start_anqp(struct station *station, struct network *network,
static bool network_has_open_pair(struct network *network, struct scan_bss *owe) static bool network_has_open_pair(struct network *network, struct scan_bss *owe)
{ {
const struct l_queue_entry *entry; const struct l_queue_entry *entry;
struct ie_owe_transition_info *owe_info = owe->owe_trans;
for (entry = network_bss_list_get_entries(network); entry; for (entry = network_bss_list_get_entries(network); entry;
entry = entry->next) { entry = entry->next) {
struct scan_bss *open = entry->data; struct scan_bss *open = entry->data;
struct ie_owe_transition_info *open_info = open->owe_trans;
/* /*
* Check if this is an Open/Hidden pair: * Check if this is an Open/Hidden pair:
@ -704,14 +705,14 @@ static bool network_has_open_pair(struct network *network, struct scan_bss *owe)
* OWE SSID equals the SSID in Open IE * OWE SSID equals the SSID in Open IE
* OWE BSSID equals the BSSID in Open IE * OWE BSSID equals the BSSID in Open IE
*/ */
if (open->ssid_len == owe->owe_trans_ssid_len && if (open->ssid_len == owe_info->ssid_len &&
open->owe_trans_ssid_len == owe->ssid_len && open_info->ssid_len == owe->ssid_len &&
!memcmp(open->ssid, owe->owe_trans_ssid, !memcmp(open->ssid, owe_info->ssid,
open->ssid_len) && open->ssid_len) &&
!memcmp(open->owe_trans_ssid, owe->ssid, !memcmp(open_info->ssid, owe->ssid,
owe->ssid_len) && owe->ssid_len) &&
!memcmp(open->addr, owe->owe_trans_bssid, 6) && !memcmp(open->addr, owe_info->bssid, 6) &&
!memcmp(open->owe_trans_bssid, owe->addr, 6)) !memcmp(open_info->bssid, owe->addr, 6))
return true; return true;
} }
@ -736,10 +737,10 @@ static bool station_owe_transition_results(int err, struct l_queue *bss_list,
* Don't handle the open BSS, hidden BSS, BSS with no OWE * Don't handle the open BSS, hidden BSS, BSS with no OWE
* Transition IE, or an IE with a non-utf8 SSID * Transition IE, or an IE with a non-utf8 SSID
*/ */
if (!bss->rsne || l_memeqzero(bss->owe_trans_bssid, 6) || if (!bss->rsne || !bss->owe_trans ||
util_ssid_is_hidden(bss->ssid_len, bss->ssid) || util_ssid_is_hidden(bss->ssid_len, bss->ssid) ||
!util_ssid_is_utf8(bss->owe_trans_ssid_len, !util_ssid_is_utf8(bss->owe_trans->ssid_len,
bss->owe_trans_ssid)) bss->owe_trans->ssid))
goto free; goto free;
@ -807,7 +808,7 @@ static void foreach_add_owe_scan(struct network *network, void *data)
entry = entry->next) { entry = entry->next) {
struct scan_bss *open = entry->data; struct scan_bss *open = entry->data;
if (l_memeqzero(open->owe_trans_bssid, 6)) if (!open->owe_trans)
continue; continue;
/* only want the open networks with WFA OWE IE */ /* only want the open networks with WFA OWE IE */
@ -815,7 +816,7 @@ static void foreach_add_owe_scan(struct network *network, void *data)
continue; continue;
/* BSS already in network object */ /* BSS already in network object */
if (network_bss_find_by_addr(network, open->owe_trans_bssid)) if (network_bss_find_by_addr(network, open->owe_trans->bssid))
continue; continue;
if (!list) if (!list)
@ -3037,7 +3038,7 @@ static bool station_hidden_network_scan_results(int err,
memcmp(bss->ssid, ssid, ssid_len)) memcmp(bss->ssid, ssid, ssid_len))
goto next; goto next;
if (!l_memeqzero(bss->owe_trans_bssid, 6)) if (bss->owe_trans)
goto next; goto next;
/* /*
@ -3134,7 +3135,7 @@ static struct l_dbus_message *station_dbus_connect_hidden_network(
struct scan_bss *target = network_bss_select(network, true); struct scan_bss *target = network_bss_select(network, true);
/* Treat OWE transition networks special */ /* Treat OWE transition networks special */
if (!l_memeqzero(target->owe_trans_bssid, 6)) if (target->owe_trans)
goto not_hidden; goto not_hidden;
for (; entry; entry = entry->next) { for (; entry; entry = entry->next) {