wpa_supplicant: Add LCI and civic request to Neighbor Report Request
Add an option to request LCI and Location Civic Measurement in Neighbor Report Request frame, as described in IEEE P802.11-REVmc/D5.0, 9.6.7.6. Note: This changes the encoding format of the NEIGHBOR_REP_REQUEST ssid=<val> parameter. This used to be parsed as raw SSID data which is problematic for accepting additional parameters. The new encoding allows either a string within double-quotation marks or a hexdump of the raw SSID. Thew new format: NEIGHBOR_REP_REQUEST [ssid=<SSID>] [lci] [civic] Signed-off-by: David Spinadel <david.spinadel@intel.com>
This commit is contained in:
parent
624b8a061f
commit
d41a5352fe
4 changed files with 108 additions and 13 deletions
|
@ -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,
|
static int wpas_ctrl_iface_send_neigbor_rep(struct wpa_supplicant *wpa_s,
|
||||||
char *cmd)
|
char *cmd)
|
||||||
{
|
{
|
||||||
struct wpa_ssid ssid;
|
struct wpa_ssid_value ssid, *ssid_p = NULL;
|
||||||
struct wpa_ssid *ssid_p = NULL;
|
int ret, lci = 0, civic = 0;
|
||||||
int ret = 0;
|
char *ssid_s;
|
||||||
|
|
||||||
if (os_strncmp(cmd, " ssid=", 6) == 0) {
|
ssid_s = os_strstr(cmd, "ssid=");
|
||||||
ssid.ssid_len = os_strlen(cmd + 6);
|
if (ssid_s) {
|
||||||
if (ssid.ssid_len > SSID_MAX_LEN)
|
if (ssid_parse(ssid_s + 5, &ssid)) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"CTRL: Send Neighbor Report: bad SSID");
|
||||||
return -1;
|
return -1;
|
||||||
ssid.ssid = (u8 *) (cmd + 6);
|
}
|
||||||
|
|
||||||
ssid_p = &ssid;
|
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,
|
wpas_ctrl_neighbor_rep_cb,
|
||||||
wpa_s);
|
wpa_s);
|
||||||
|
|
||||||
|
|
|
@ -3455,8 +3455,7 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = {
|
||||||
},
|
},
|
||||||
{ "neighbor_rep_request",
|
{ "neighbor_rep_request",
|
||||||
wpa_cli_cmd_neighbor_rep_request, NULL, cli_cmd_flag_none,
|
wpa_cli_cmd_neighbor_rep_request, NULL, cli_cmd_flag_none,
|
||||||
"[ssid=<SSID>] = Trigger request to AP for neighboring AP report "
|
"[ssid=<SSID>] [lci] [civic] = Trigger request to AP for neighboring AP report (with optional given SSID in hex or enclosed in double quotes, default: current SSID; with optional LCI and location civic request)"
|
||||||
"(with optional given SSID, default: current SSID)"
|
|
||||||
},
|
},
|
||||||
{ "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none,
|
{ "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none,
|
||||||
"= flush ERP keys" },
|
"= flush ERP keys" },
|
||||||
|
|
|
@ -6162,11 +6162,19 @@ void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
|
||||||
#define ECANCELED -1
|
#define ECANCELED -1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Measurement Request element + Location Subject + Maximum Age subelement */
|
||||||
|
#define MEASURE_REQUEST_LCI_LEN (3 + 1 + 4)
|
||||||
|
/* Measurement Request element + Location Civic Request */
|
||||||
|
#define MEASURE_REQUEST_CIVIC_LEN (3 + 5)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
|
* wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
|
||||||
* @wpa_s: Pointer to wpa_supplicant
|
* @wpa_s: Pointer to wpa_supplicant
|
||||||
* @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
|
* @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
|
||||||
* is sent in the request.
|
* 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
|
* @cb: Callback function to be called once the requested report arrives, or
|
||||||
* timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
|
* timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
|
||||||
* In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
|
* In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
|
||||||
|
@ -6180,7 +6188,8 @@ void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
|
||||||
* Request must contain a callback function.
|
* Request must contain a callback function.
|
||||||
*/
|
*/
|
||||||
int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
|
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,
|
void (*cb)(void *ctx,
|
||||||
struct wpabuf *neighbor_rep),
|
struct wpabuf *neighbor_rep),
|
||||||
void *cb_ctx)
|
void *cb_ctx)
|
||||||
|
@ -6221,7 +6230,9 @@ int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 3 = action category + action code + dialog token */
|
/* 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) {
|
if (buf == NULL) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"RRM: Failed to allocate Neighbor Report Request");
|
"RRM: Failed to allocate Neighbor Report Request");
|
||||||
|
@ -6241,6 +6252,72 @@ int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
|
||||||
wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
|
wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lci) {
|
||||||
|
/* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
|
||||||
|
wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
|
||||||
|
wpabuf_put_u8(buf, MEASURE_REQUEST_LCI_LEN);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Measurement token; nonzero number that is unique among the
|
||||||
|
* Measurement Request elements in a particular frame.
|
||||||
|
*/
|
||||||
|
wpabuf_put_u8(buf, 1); /* Measurement Token */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parallel, Enable, Request, and Report bits are 0, Duration is
|
||||||
|
* reserved.
|
||||||
|
*/
|
||||||
|
wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
|
||||||
|
wpabuf_put_u8(buf, MEASURE_TYPE_LCI); /* Measurement Type */
|
||||||
|
|
||||||
|
/* IEEE P802.11-REVmc/D5.0 9.4.2.21.10 - LCI request */
|
||||||
|
/* Location Subject */
|
||||||
|
wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
|
||||||
|
|
||||||
|
/* Optional Subelements */
|
||||||
|
/*
|
||||||
|
* IEEE P802.11-REVmc/D5.0 Figure 9-170
|
||||||
|
* The Maximum 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_SUBELEM_MAX_AGE);
|
||||||
|
wpabuf_put_u8(buf, 2);
|
||||||
|
wpabuf_put_le16(buf, 0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (civic) {
|
||||||
|
/* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
|
||||||
|
wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
|
||||||
|
wpabuf_put_u8(buf, MEASURE_REQUEST_CIVIC_LEN);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Measurement token; nonzero number that is unique among the
|
||||||
|
* Measurement Request elements in a particular frame.
|
||||||
|
*/
|
||||||
|
wpabuf_put_u8(buf, 2); /* Measurement Token */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parallel, Enable, Request, and Report bits are 0, Duration is
|
||||||
|
* reserved.
|
||||||
|
*/
|
||||||
|
wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
|
||||||
|
/* Measurement Type */
|
||||||
|
wpabuf_put_u8(buf, MEASURE_TYPE_LOCATION_CIVIC);
|
||||||
|
|
||||||
|
/* IEEE P802.11-REVmc/D5.0 9.4.2.21.14:
|
||||||
|
* Location Civic request */
|
||||||
|
/* Location Subject */
|
||||||
|
wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
|
||||||
|
wpabuf_put_u8(buf, 0); /* Civic Location Type: IETF RFC 4776 */
|
||||||
|
/* Location Service Interval Units: Seconds */
|
||||||
|
wpabuf_put_u8(buf, 0);
|
||||||
|
/* Location Service Interval: 0 - Only one report is requested
|
||||||
|
*/
|
||||||
|
wpabuf_put_le16(buf, 0);
|
||||||
|
/* No optional subelements */
|
||||||
|
}
|
||||||
|
|
||||||
wpa_s->rrm.next_neighbor_rep_token++;
|
wpa_s->rrm.next_neighbor_rep_token++;
|
||||||
|
|
||||||
if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
|
if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
|
||||||
|
|
|
@ -1163,7 +1163,8 @@ void wpas_rrm_reset(struct wpa_supplicant *wpa_s);
|
||||||
void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
|
void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
|
||||||
const u8 *report, size_t report_len);
|
const u8 *report, size_t report_len);
|
||||||
int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
|
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,
|
void (*cb)(void *ctx,
|
||||||
struct wpabuf *neighbor_rep),
|
struct wpabuf *neighbor_rep),
|
||||||
void *cb_ctx);
|
void *cb_ctx);
|
||||||
|
|
Loading…
Reference in a new issue