From: David Spinadel <david.spinadel@xxxxxxxxx> Add an option to request LCI and location civic in neighbor report request, as described in ieee802.11 spec 8.6.7.6. Signed-off-by: David Spinadel <david.spinadel@xxxxxxxxx> --- tests/hwsim/test_wpas_ctrl.py | 4 +-- wpa_supplicant/ctrl_iface.c | 34 ++++++++++++++++------ wpa_supplicant/wpa_cli.c | 5 ++-- wpa_supplicant/wpa_supplicant.c | 60 +++++++++++++++++++++++++++++++++++++-- wpa_supplicant/wpa_supplicant_i.h | 3 +- 5 files changed, 91 insertions(+), 15 deletions(-) diff --git a/tests/hwsim/test_wpas_ctrl.py b/tests/hwsim/test_wpas_ctrl.py index 8bbacd2..48421d3 100644 --- a/tests/hwsim/test_wpas_ctrl.py +++ b/tests/hwsim/test_wpas_ctrl.py @@ -1278,7 +1278,7 @@ def test_wpas_ctrl_neighbor_rep_req(dev, apdev): dev[0].connect("test", key_mgmt="NONE", scan_freq="2412") if "FAIL" not in dev[0].request("NEIGHBOR_REP_REQUEST"): raise Exception("Request succeeded unexpectedly") - if "FAIL" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=abcdef"): + if "FAIL" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"abcdef\""): raise Exception("Request succeeded unexpectedly") dev[0].request("DISCONNECT") @@ -1300,7 +1300,7 @@ def test_wpas_ctrl_neighbor_rep_req(dev, apdev): raise Exception("RRM report result not indicated") logger.info("RRM result: " + ev) - if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=abcdef"): + if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"abcdef\""): raise Exception("Request failed") ev = dev[0].wait_event([ "RRM-NEIGHBOR-REP-RECEIVED", "RRM-NEIGHBOR-REP-REQUEST-FAILED" ], timeout=10) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 8574437..6e91e31 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -8222,19 +8222,37 @@ static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep) static int wpas_ctrl_iface_send_neigbor_rep(struct wpa_supplicant *wpa_s, char *cmd) { - struct wpa_ssid ssid; - struct wpa_ssid *ssid_p = NULL; - int ret = 0; + struct wpa_ssid_value ssid, *ssid_p = NULL; + int lci = 0, civic = 0; + int ret; + char *ssid_s; - if (os_strncmp(cmd, " ssid=", 6) == 0) { - ssid.ssid_len = os_strlen(cmd + 6); - if (ssid.ssid_len > SSID_MAX_LEN) + ssid_s = os_strstr(cmd, "ssid="); + if (ssid_s) { + if (ssid_parse(ssid_s + 5, &ssid)) { + wpa_printf(MSG_ERROR, + "CTRL: send neighbor rep: bad ssid"); return -1; - ssid.ssid = (u8 *) (cmd + 6); + } + ssid_p = &ssid; + + /* Move cmd after the SSID text that may include "lci" or + * "civic". + */ + cmd = os_strchr(ssid_s + 6, ssid_s[5] == '"' ? '"' : ' '); + if (cmd) + cmd++; + } - ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p, + if (cmd && os_strstr(cmd, "lci")) + lci = 1; + + if (cmd && os_strstr(cmd, "civic")) + civic = 1; + + ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p, lci, civic, wpas_ctrl_neighbor_rep_cb, wpa_s); diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 36a7a4e..911ee3e 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -3455,8 +3455,9 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = { }, { "neighbor_rep_request", wpa_cli_cmd_neighbor_rep_request, NULL, cli_cmd_flag_none, - "[ssid=<SSID>] = Trigger request to AP for neighboring AP report " - "(with optional given SSID, default: current SSID)" + "[ssid=<SSID>] [lci] [civic] = Trigger request to AP for neighboring " + "AP report (with optional given SSID in hex or enclosesd in double quotes, " + "default: current SSID; with optional LCI and location civic request)" }, { "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none, "= flush ERP keys" }, diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 51bb245..8b30c98 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -6152,11 +6152,19 @@ void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s, #define ECANCELED -1 #endif +/* Measure request + location subject + max age subelement */ +#define MEASURE_REQUEST_LCI_LEN (3 + 1 + 4) +/* Measure request + location civic request */ +#define MEASURE_REQUEST_CIVIC_LEN (3 + 5) + + /** * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP * @wpa_s: Pointer to wpa_supplicant * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE * is sent in the request. + * @lci: if set, neighbor request will include LCI request + * @civic: if set, neighbor request will include civic location request * @cb: Callback function to be called once the requested report arrives, or * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds. * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's @@ -6170,7 +6178,8 @@ void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s, * Request must contain a callback function. */ int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s, - const struct wpa_ssid *ssid, + const struct wpa_ssid_value *ssid, + int lci, int civic, void (*cb)(void *ctx, struct wpabuf *neighbor_rep), void *cb_ctx) @@ -6211,7 +6220,9 @@ int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s, } /* 3 = action category + action code + dialog token */ - buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0)); + buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0) + + (lci ? 2 + MEASURE_REQUEST_LCI_LEN : 0) + + (civic ? 2 + MEASURE_REQUEST_CIVIC_LEN : 0)); if (buf == NULL) { wpa_printf(MSG_DEBUG, "RRM: Failed to allocate Neighbor Report Request"); @@ -6231,6 +6242,51 @@ int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s, wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len); } + if (lci) { + wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST); + wpabuf_put_u8(buf, MEASURE_REQUEST_LCI_LEN); + /* Measurement token; unique among the measurement requests in a + * particular frame + */ + wpabuf_put_u8(buf, 1); + /* Parallel, enable, request and report bits are 0, duration is + * reserved + */ + wpabuf_put_u8(buf, 0); + wpabuf_put_u8(buf, MEASURE_TYPE_LCI); + + wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE); + + /* Max age subelement is required, otherwise the AP can send + * only data that was determined after receiving the request. + * Setting it here to unlimited age. + */ + wpabuf_put_u8(buf, LCI_REQ_SUBELEMENT_MAX_AGE); + wpabuf_put_u8(buf, 2); + wpabuf_put_le16(buf, 0xffff); + } + + if (civic) { + wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST); + wpabuf_put_u8(buf, MEASURE_REQUEST_CIVIC_LEN); + + /* Measurement token; unique among the mesurement requests in a + * particular frame + */ + wpabuf_put_u8(buf, 2); + /* Parallel, enable, request and report bits are 0, duration is + * reserved + */ + wpabuf_put_u8(buf, 0); + wpabuf_put_u8(buf, MEASURE_TYPE_LOCATION_CIVIC); + + wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE); + wpabuf_put_u8(buf, 0); /* Location civic type IETF RFC 4776 */ + wpabuf_put_u8(buf, 0); /* Location service interval units */ + /* Location service interval 0 - Only one report is required */ + wpabuf_put_le16(buf, 0); + } + wpa_s->rrm.next_neighbor_rep_token++; if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index e6fc457..211f4d1 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1163,7 +1163,8 @@ void wpas_rrm_reset(struct wpa_supplicant *wpa_s); void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s, const u8 *report, size_t report_len); int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s, - const struct wpa_ssid *ssid, + const struct wpa_ssid_value *ssid, + int lci, int civic, void (*cb)(void *ctx, struct wpabuf *neighbor_rep), void *cb_ctx); -- 1.9.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap