aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvraham Stern <avraham.stern@intel.com>2017-03-08 12:37:39 (GMT)
committerJouni Malinen <j@w1.fi>2017-03-11 08:36:15 (GMT)
commite044a9d1e0b23c1d8193065469983374505acaf2 (patch)
treec0c3c8306e234fe0da1fa4067acee9cd98844c71
parent13bf18eda56fc64abfdb481caeeae9d9a7d18ba8 (diff)
downloadhostap-e044a9d1e0b23c1d8193065469983374505acaf2.zip
hostap-e044a9d1e0b23c1d8193065469983374505acaf2.tar.gz
hostap-e044a9d1e0b23c1d8193065469983374505acaf2.tar.bz2
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>
-rw-r--r--hostapd/ctrl_iface.c104
-rw-r--r--src/common/ieee802_11_common.c102
-rw-r--r--src/common/ieee802_11_common.h3
3 files changed, 112 insertions, 97 deletions
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 62feaa4..0d649cd 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -838,7 +838,7 @@ static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
char *url = NULL;
int ret;
u8 nei_rep[1000];
- u8 *nei_pos = nei_rep;
+ int nei_len;
u8 mbo[10];
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));
}
-
- /*
- * BSS Transition Candidate List Entries - Neighbor Report elements
- * neighbor=<BSSID>,<BSSID Information>,<Operating Class>,
- * <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;
- }
+ nei_len = ieee802_11_parse_candidate_list(cmd, nei_rep,
+ sizeof(nei_rep));
+ if (nei_len < 0)
+ return -1;
pos = os_strstr(cmd, " url=");
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,
valid_int, bss_term_dur, url,
- nei_pos > nei_rep ? nei_rep : NULL,
- nei_pos - nei_rep, mbo_len ? mbo : NULL,
- mbo_len);
+ nei_len ? nei_rep : NULL, nei_len,
+ mbo_len ? mbo : NULL, mbo_len);
#ifdef CONFIG_MBO
fail:
#endif /* CONFIG_MBO */
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index a8d68e5..4a04915 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -1594,3 +1594,105 @@ const struct oper_class_map * get_oper_class(const char *country, u8 op_class)
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;
+}
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index 966eeac..b3a74f1 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -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);
+int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
+ size_t nei_rep_len);
+
#endif /* IEEE802_11_COMMON_H */