@@ -2655,6 +2655,23 @@ static int hostapd_ctrl_iface_req_beacon(struct hostapd_data *hapd,
return ret;
}
+static int hostapd_ctrl_iface_show_neighbor(struct hostapd_data *hapd,
+ char *buf, size_t buflen)
+{
+ struct hostapd_iface *iface = hapd->iface;
+ struct hostapd_sta_info *info;
+ struct os_reltime now;
+
+ 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)
{
@@ -3174,6 +3191,8 @@ 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;
@@ -1303,6 +1303,12 @@ static int hostapd_cli_cmd_set_neighbor(struct wpa_ctrl *ctrl, int argc,
return wpa_ctrl_command(ctrl, cmd);
}
+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[])
@@ -1628,6 +1634,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
{ "set_neighbor", hostapd_cli_cmd_set_neighbor, NULL,
"<addr> <ssid=> <nr=> [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,
"<addr> <ssid=> = remove AP from neighbor database" },
{ "req_lci", hostapd_cli_cmd_req_lci, hostapd_complete_stations,
@@ -33,6 +33,73 @@ hostapd_neighbor_get(struct hostapd_data *hapd, const u8 *bssid,
return NULL;
}
+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[120];
+ char lci[120];
+ char civic[120];
+ char ssid[SSID_MAX_LEN * 2 + 1];
+ int i = 0;
+ static const char* blank = "[BLANK]";
+
+ for (i = 0; i<nr->ssid.ssid_len; i++) {
+ os_snprintf(ssid + i * 2, 3, "%02hx", nr->nr->buf[i]);
+ }
+ if (i == 0)
+ os_snprintf(ssid, sizeof(ssid), "%s", blank);
+
+ i = 0;
+ if (nr->nr) {
+ for (i = 0; i<nr->nr->used; i++) {
+ if (i * 2 + 2 >= sizeof(nrie))
+ break;
+ os_snprintf(nrie + i * 2, 3, "%02hx", nr->nr->buf[i]);
+ }
+ }
+ if (i == 0)
+ os_snprintf(nrie, sizeof(nrie), "%s", blank);
+
+ i = 0;
+ if (nr->lci) {
+ for (i = 0; i<nr->lci->used; i++) {
+ if (i * 2 + 2 >= sizeof(lci))
+ break;
+ os_snprintf(lci + i * 2, 3, "%02hx", nr->lci->buf[i]);
+ }
+ }
+ if (i == 0)
+ os_snprintf(lci, sizeof(lci), "%s", blank);
+
+ i = 0;
+ if (nr->civic) {
+ for (i = 0; i<nr->civic->used; i++) {
+ if (i * 2 + 2 >= sizeof(civic))
+ break;
+ os_snprintf(civic + i * 2, 3, "%02hx", nr->civic->buf[i]);
+ }
+ }
+ if (i == 0)
+ os_snprintf(civic, sizeof(civic), "%s", blank);
+
+ ret = os_snprintf(pos, end - pos, MACSTR " ssid=%s nr=%s lci=%s civic=%s stationary=%i\n",
+ MAC2STR(nr->bssid), ssid, nrie, lci, civic, nr->stationary);
+ if (os_snprintf_error(end - pos, ret))
+ break;
+ pos += ret;
+ }
+ return pos - buf;
+}
+
static void hostapd_neighbor_clear_entry(struct hostapd_neighbor_entry *nr)
{
@@ -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,