common: Add candidate list parsing helper function
Add a helper function that parses candidate list from command line arguments. This function will be used (in the following commits) to add a candidate list to BSS transition management query. Signed-off-by: Avraham Stern <avraham.stern@intel.com>
This commit is contained in:
parent
13bf18eda5
commit
e044a9d1e0
3 changed files with 112 additions and 97 deletions
|
@ -838,7 +838,7 @@ static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
|
||||||
char *url = NULL;
|
char *url = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
u8 nei_rep[1000];
|
u8 nei_rep[1000];
|
||||||
u8 *nei_pos = nei_rep;
|
int nei_len;
|
||||||
u8 mbo[10];
|
u8 mbo[10];
|
||||||
size_t mbo_len = 0;
|
size_t mbo_len = 0;
|
||||||
|
|
||||||
|
@ -888,99 +888,10 @@ static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
|
||||||
WPA_PUT_LE16(&bss_term_dur[10], atoi(end));
|
WPA_PUT_LE16(&bss_term_dur[10], atoi(end));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nei_len = ieee802_11_parse_candidate_list(cmd, nei_rep,
|
||||||
/*
|
sizeof(nei_rep));
|
||||||
* BSS Transition Candidate List Entries - Neighbor Report elements
|
if (nei_len < 0)
|
||||||
* neighbor=<BSSID>,<BSSID Information>,<Operating Class>,
|
return -1;
|
||||||
* <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>]
|
|
||||||
*/
|
|
||||||
pos = cmd;
|
|
||||||
while (pos) {
|
|
||||||
u8 *nei_start;
|
|
||||||
long int val;
|
|
||||||
char *endptr, *tmp;
|
|
||||||
|
|
||||||
pos = os_strstr(pos, " neighbor=");
|
|
||||||
if (!pos)
|
|
||||||
break;
|
|
||||||
if (nei_pos + 15 > nei_rep + sizeof(nei_rep)) {
|
|
||||||
wpa_printf(MSG_DEBUG,
|
|
||||||
"Not enough room for additional neighbor");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
pos += 10;
|
|
||||||
|
|
||||||
nei_start = nei_pos;
|
|
||||||
*nei_pos++ = WLAN_EID_NEIGHBOR_REPORT;
|
|
||||||
nei_pos++; /* length to be filled in */
|
|
||||||
|
|
||||||
if (hwaddr_aton(pos, nei_pos)) {
|
|
||||||
wpa_printf(MSG_DEBUG, "Invalid BSSID");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
nei_pos += ETH_ALEN;
|
|
||||||
pos += 17;
|
|
||||||
if (*pos != ',') {
|
|
||||||
wpa_printf(MSG_DEBUG, "Missing BSSID Information");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
pos++;
|
|
||||||
|
|
||||||
val = strtol(pos, &endptr, 0);
|
|
||||||
WPA_PUT_LE32(nei_pos, val);
|
|
||||||
nei_pos += 4;
|
|
||||||
if (*endptr != ',') {
|
|
||||||
wpa_printf(MSG_DEBUG, "Missing Operating Class");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
pos = endptr + 1;
|
|
||||||
|
|
||||||
*nei_pos++ = atoi(pos); /* Operating Class */
|
|
||||||
pos = os_strchr(pos, ',');
|
|
||||||
if (pos == NULL) {
|
|
||||||
wpa_printf(MSG_DEBUG, "Missing Channel Number");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
pos++;
|
|
||||||
|
|
||||||
*nei_pos++ = atoi(pos); /* Channel Number */
|
|
||||||
pos = os_strchr(pos, ',');
|
|
||||||
if (pos == NULL) {
|
|
||||||
wpa_printf(MSG_DEBUG, "Missing PHY Type");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
pos++;
|
|
||||||
|
|
||||||
*nei_pos++ = atoi(pos); /* PHY Type */
|
|
||||||
end = os_strchr(pos, ' ');
|
|
||||||
tmp = os_strchr(pos, ',');
|
|
||||||
if (tmp && (!end || tmp < end)) {
|
|
||||||
/* Optional Subelements (hexdump) */
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
pos = tmp + 1;
|
|
||||||
end = os_strchr(pos, ' ');
|
|
||||||
if (end)
|
|
||||||
len = end - pos;
|
|
||||||
else
|
|
||||||
len = os_strlen(pos);
|
|
||||||
if (nei_pos + len / 2 > nei_rep + sizeof(nei_rep)) {
|
|
||||||
wpa_printf(MSG_DEBUG,
|
|
||||||
"Not enough room for neighbor subelements");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (len & 0x01 ||
|
|
||||||
hexstr2bin(pos, nei_pos, len / 2) < 0) {
|
|
||||||
wpa_printf(MSG_DEBUG,
|
|
||||||
"Invalid neighbor subelement info");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
nei_pos += len / 2;
|
|
||||||
pos = end;
|
|
||||||
}
|
|
||||||
|
|
||||||
nei_start[1] = nei_pos - nei_start - 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = os_strstr(cmd, " url=");
|
pos = os_strstr(cmd, " url=");
|
||||||
if (pos) {
|
if (pos) {
|
||||||
|
@ -1067,9 +978,8 @@ static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
|
||||||
|
|
||||||
ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer,
|
ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer,
|
||||||
valid_int, bss_term_dur, url,
|
valid_int, bss_term_dur, url,
|
||||||
nei_pos > nei_rep ? nei_rep : NULL,
|
nei_len ? nei_rep : NULL, nei_len,
|
||||||
nei_pos - nei_rep, mbo_len ? mbo : NULL,
|
mbo_len ? mbo : NULL, mbo_len);
|
||||||
mbo_len);
|
|
||||||
#ifdef CONFIG_MBO
|
#ifdef CONFIG_MBO
|
||||||
fail:
|
fail:
|
||||||
#endif /* CONFIG_MBO */
|
#endif /* CONFIG_MBO */
|
||||||
|
|
|
@ -1594,3 +1594,105 @@ const struct oper_class_map * get_oper_class(const char *country, u8 op_class)
|
||||||
|
|
||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
|
||||||
|
size_t nei_rep_len)
|
||||||
|
{
|
||||||
|
u8 *nei_pos = nei_rep;
|
||||||
|
const char *end;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BSS Transition Candidate List Entries - Neighbor Report elements
|
||||||
|
* neighbor=<BSSID>,<BSSID Information>,<Operating Class>,
|
||||||
|
* <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>]
|
||||||
|
*/
|
||||||
|
while (pos) {
|
||||||
|
u8 *nei_start;
|
||||||
|
long int val;
|
||||||
|
char *endptr, *tmp;
|
||||||
|
|
||||||
|
pos = os_strstr(pos, " neighbor=");
|
||||||
|
if (!pos)
|
||||||
|
break;
|
||||||
|
if (nei_pos + 15 > nei_rep + nei_rep_len) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Not enough room for additional neighbor");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pos += 10;
|
||||||
|
|
||||||
|
nei_start = nei_pos;
|
||||||
|
*nei_pos++ = WLAN_EID_NEIGHBOR_REPORT;
|
||||||
|
nei_pos++; /* length to be filled in */
|
||||||
|
|
||||||
|
if (hwaddr_aton(pos, nei_pos)) {
|
||||||
|
wpa_printf(MSG_DEBUG, "Invalid BSSID");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
nei_pos += ETH_ALEN;
|
||||||
|
pos += 17;
|
||||||
|
if (*pos != ',') {
|
||||||
|
wpa_printf(MSG_DEBUG, "Missing BSSID Information");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
|
||||||
|
val = strtol(pos, &endptr, 0);
|
||||||
|
WPA_PUT_LE32(nei_pos, val);
|
||||||
|
nei_pos += 4;
|
||||||
|
if (*endptr != ',') {
|
||||||
|
wpa_printf(MSG_DEBUG, "Missing Operating Class");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pos = endptr + 1;
|
||||||
|
|
||||||
|
*nei_pos++ = atoi(pos); /* Operating Class */
|
||||||
|
pos = os_strchr(pos, ',');
|
||||||
|
if (pos == NULL) {
|
||||||
|
wpa_printf(MSG_DEBUG, "Missing Channel Number");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
|
||||||
|
*nei_pos++ = atoi(pos); /* Channel Number */
|
||||||
|
pos = os_strchr(pos, ',');
|
||||||
|
if (pos == NULL) {
|
||||||
|
wpa_printf(MSG_DEBUG, "Missing PHY Type");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
|
||||||
|
*nei_pos++ = atoi(pos); /* PHY Type */
|
||||||
|
end = os_strchr(pos, ' ');
|
||||||
|
tmp = os_strchr(pos, ',');
|
||||||
|
if (tmp && (!end || tmp < end)) {
|
||||||
|
/* Optional Subelements (hexdump) */
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
pos = tmp + 1;
|
||||||
|
end = os_strchr(pos, ' ');
|
||||||
|
if (end)
|
||||||
|
len = end - pos;
|
||||||
|
else
|
||||||
|
len = os_strlen(pos);
|
||||||
|
if (nei_pos + len / 2 > nei_rep + nei_rep_len) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Not enough room for neighbor subelements");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (len & 0x01 ||
|
||||||
|
hexstr2bin(pos, nei_pos, len / 2) < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Invalid neighbor subelement info");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
nei_pos += len / 2;
|
||||||
|
pos = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
nei_start[1] = nei_pos - nei_start - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nei_pos - nei_rep;
|
||||||
|
}
|
||||||
|
|
|
@ -186,4 +186,7 @@ u8 country_to_global_op_class(const char *country, u8 op_class);
|
||||||
|
|
||||||
const struct oper_class_map * get_oper_class(const char *country, u8 op_class);
|
const struct oper_class_map * get_oper_class(const char *country, u8 op_class);
|
||||||
|
|
||||||
|
int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
|
||||||
|
size_t nei_rep_len);
|
||||||
|
|
||||||
#endif /* IEEE802_11_COMMON_H */
|
#endif /* IEEE802_11_COMMON_H */
|
||||||
|
|
Loading…
Reference in a new issue