From ee48f48ba1d2168a0891be16b04990e025882739 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Tue, 19 Mar 2019 10:09:50 -0700 Subject: [PATCH] hostapd: Support showing neighbor list through hostapd_cli This lets one know the current neighbor list, and could be used to populate the neighbor list of other hostapd processes. For instance: $ hostapd_cli -i vap0001 show_neighbor 04:f0:21:1e:ae:b0 ssid=04f0211eaeb0af190000802809 nr=04f0211eaeb0af1900008028090603022a00 $ hostapd_cli -i vap0000 set_neighbor 04:f0:21:1e:ae:b0 ssid=04f0211eaeb0af190000802809 nr=04f0211eaeb0af1900008028090603022a00 OK $ hostapd_cli -i vap0000 show_neighbor 04:f0:21:1e:ae:b0 ssid=04f0211eaeb0af190000802809 nr=04f0211eaeb0af1900008028090603022a00 04:f0:21:c3:b2:b0 ssid=04f021c3b2b0af190000802809 nr=04f021c3b2b0af1900008028090603022a00 Signed-off-by: Ben Greear --- hostapd/ctrl_iface.c | 17 ++++++++++++++ hostapd/hostapd_cli.c | 9 ++++++++ src/ap/neighbor_db.c | 54 +++++++++++++++++++++++++++++++++++++++++++ src/ap/neighbor_db.h | 1 + 4 files changed, 81 insertions(+) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 1972d3844..9758881bb 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -2707,6 +2707,20 @@ static int hostapd_ctrl_iface_req_beacon(struct hostapd_data *hapd, } +static int hostapd_ctrl_iface_show_neighbor(struct hostapd_data *hapd, + char *buf, size_t buflen) +{ + if (!(hapd->conf->radio_measurements[0] & + WLAN_RRM_CAPS_NEIGHBOR_REPORT)) { + wpa_printf(MSG_ERROR, + "CTRL: SHOW_NEIGHBOR: Neighbor report is not enabled"); + return -1; + } + + return hostapd_neighbor_show(hapd, buf, buflen); +} + + static int hostapd_ctrl_iface_set_neighbor(struct hostapd_data *hapd, char *buf) { struct wpa_ssid_value ssid; @@ -3255,6 +3269,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, } else if (os_strncmp(buf, "SET_NEIGHBOR ", 13) == 0) { if (hostapd_ctrl_iface_set_neighbor(hapd, buf + 13)) reply_len = -1; + } else if (os_strcmp(buf, "SHOW_NEIGHBOR") == 0) { + reply_len = hostapd_ctrl_iface_show_neighbor(hapd, reply, + reply_size); } else if (os_strncmp(buf, "REMOVE_NEIGHBOR ", 16) == 0) { if (hostapd_ctrl_iface_remove_neighbor(hapd, buf + 16)) reply_len = -1; diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c index 24d8778a1..440664e9b 100644 --- a/hostapd/hostapd_cli.c +++ b/hostapd/hostapd_cli.c @@ -1312,6 +1312,13 @@ static int hostapd_cli_cmd_set_neighbor(struct wpa_ctrl *ctrl, int argc, } +static int hostapd_cli_cmd_show_neighbor(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "SHOW_NEIGHBOR"); +} + + static int hostapd_cli_cmd_remove_neighbor(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -1622,6 +1629,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = { { "set_neighbor", hostapd_cli_cmd_set_neighbor, NULL, " [lci=] [civic=] [stat]\n" " = add AP to neighbor database" }, + { "show_neighbor", hostapd_cli_cmd_show_neighbor, NULL, + " = show neighbor database entries" }, { "remove_neighbor", hostapd_cli_cmd_remove_neighbor, NULL, " [ssid=] = remove AP from neighbor database" }, { "req_lci", hostapd_cli_cmd_req_lci, hostapd_complete_stations, diff --git a/src/ap/neighbor_db.c b/src/ap/neighbor_db.c index 541544322..4012ae4c3 100644 --- a/src/ap/neighbor_db.c +++ b/src/ap/neighbor_db.c @@ -34,6 +34,60 @@ hostapd_neighbor_get(struct hostapd_data *hapd, const u8 *bssid, } +int hostapd_neighbor_show(struct hostapd_data *hapd, char *buf, size_t buflen) +{ + struct hostapd_neighbor_entry *nr; + char *pos, *end; + + pos = buf; + end = buf + buflen; + + dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry, + list) { + int ret; + char nrie[2 * 255 + 1]; + char lci[2 * 255 + 1]; + char civic[2 * 255 + 1]; + char ssid[SSID_MAX_LEN * 2 + 1]; + + ssid[0] = '\0'; + wpa_snprintf_hex(ssid, sizeof(ssid), nr->ssid.ssid, + nr->ssid.ssid_len); + + nrie[0] = '\0'; + if (nr->nr) + wpa_snprintf_hex(nrie, sizeof(nrie), + wpabuf_head(nr->nr), + wpabuf_len(nr->nr)); + + lci[0] = '\0'; + if (nr->lci) + wpa_snprintf_hex(lci, sizeof(lci), + wpabuf_head(nr->lci), + wpabuf_len(nr->lci)); + + civic[0] = '\0'; + if (nr->civic) + wpa_snprintf_hex(civic, sizeof(civic), + wpabuf_head(nr->civic), + wpabuf_len(nr->civic)); + + ret = os_snprintf(pos, end - pos, MACSTR + " ssid=%s%s%s%s%s%s%s%s\n", + MAC2STR(nr->bssid), ssid, + nr->nr ? " nr=" : "", nrie, + nr->lci ? " lci=" : "", lci, + nr->civic ? " civic=" : "", civic, + nr->stationary ? " stat" : ""); + if (os_snprintf_error(end - pos, ret)) + break; + pos += ret; + } + + return pos - buf; +} + + static void hostapd_neighbor_clear_entry(struct hostapd_neighbor_entry *nr) { wpabuf_free(nr->nr); diff --git a/src/ap/neighbor_db.h b/src/ap/neighbor_db.h index 9c8f4f2dd..bed0a2f5f 100644 --- a/src/ap/neighbor_db.h +++ b/src/ap/neighbor_db.h @@ -13,6 +13,7 @@ struct hostapd_neighbor_entry * hostapd_neighbor_get(struct hostapd_data *hapd, const u8 *bssid, const struct wpa_ssid_value *ssid); +int hostapd_neighbor_show(struct hostapd_data *hapd, char *buf, size_t buflen); int hostapd_neighbor_set(struct hostapd_data *hapd, const u8 *bssid, const struct wpa_ssid_value *ssid, const struct wpabuf *nr, const struct wpabuf *lci,