mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2024-11-28 10:18:21 -05:00
hostapd: Add a database of neighboring APs
Add a configurable neighbor database that includes the content of Nighbor Report element, LCI and Location Civic subelements and SSID. All parameters for a neighbor must be updated at once; Neighbor Report element and SSID are mandatory, LCI and civic are optional. The age of LCI is set to the time of neighbor update. The control interface API is: SET_NEIGHBOR <BSSID> <ssid=SSID> <nr=data> [lci=<data>] [civic=<data>] To delete a neighbor use: REMOVE_NEIGHBOR <BSSID> <SSID> Signed-off-by: David Spinadel <david.spinadel@intel.com>
This commit is contained in:
parent
bf767ac136
commit
9b4b226426
@ -96,6 +96,7 @@ OBJS += src/ap/pmksa_cache_auth.c
|
||||
OBJS += src/ap/ieee802_11_shared.c
|
||||
OBJS += src/ap/beacon.c
|
||||
OBJS += src/ap/bss_load.c
|
||||
OBJS += src/ap/neighbor_db.c
|
||||
OBJS_d =
|
||||
OBJS_p =
|
||||
LIBS =
|
||||
|
@ -84,6 +84,7 @@ OBJS += ../src/ap/pmksa_cache_auth.o
|
||||
OBJS += ../src/ap/ieee802_11_shared.o
|
||||
OBJS += ../src/ap/beacon.o
|
||||
OBJS += ../src/ap/bss_load.o
|
||||
OBJS += ../src/ap/neighbor_db.o
|
||||
|
||||
OBJS_c = hostapd_cli.o ../src/common/wpa_ctrl.o ../src/utils/os_$(CONFIG_OS).o
|
||||
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "ap/wnm_ap.h"
|
||||
#include "ap/wpa_auth.h"
|
||||
#include "ap/beacon.h"
|
||||
#include "ap/neighbor_db.h"
|
||||
#include "wps/wps_defs.h"
|
||||
#include "wps/wps.h"
|
||||
#include "fst/fst_ctrl_iface.h"
|
||||
@ -2071,6 +2072,123 @@ static int hostapd_ctrl_iface_track_sta_list(struct hostapd_data *hapd,
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_set_neighbor(struct hostapd_data *hapd, char *buf)
|
||||
{
|
||||
struct wpa_ssid_value ssid;
|
||||
u8 bssid[ETH_ALEN];
|
||||
struct wpabuf *nr, *lci = NULL, *civic = NULL;
|
||||
char *tmp;
|
||||
int ret;
|
||||
|
||||
if (!(hapd->conf->radio_measurements[0] &
|
||||
WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"CTRL: SET_NEIGHBOR: Neighbor report is not enabled");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hwaddr_aton(buf, bssid)) {
|
||||
wpa_printf(MSG_ERROR, "CTRL: SET_NEIGHBOR: Bad BSSID");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp = os_strstr(buf, "ssid=");
|
||||
if (!tmp || ssid_parse(tmp + 5, &ssid)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"CTRL: SET_NEIGHBOR: Bad or missing SSID");
|
||||
return -1;
|
||||
}
|
||||
buf = os_strchr(tmp + 6, tmp[5] == '"' ? '"' : ' ');
|
||||
if (!buf)
|
||||
return -1;
|
||||
|
||||
tmp = os_strstr(buf, "nr=");
|
||||
if (!tmp) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"CTRL: SET_NEIGHBOR: Missing Neighbor Report element");
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf = os_strchr(tmp, ' ');
|
||||
if (buf)
|
||||
*buf++ = '\0';
|
||||
|
||||
nr = wpabuf_parse_bin(tmp + 3);
|
||||
if (!nr) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"CTRL: SET_NEIGHBOR: Bad Neighbor Report element");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!buf)
|
||||
goto set;
|
||||
|
||||
tmp = os_strstr(buf, "lci=");
|
||||
if (tmp) {
|
||||
buf = os_strchr(tmp, ' ');
|
||||
if (buf)
|
||||
*buf++ = '\0';
|
||||
lci = wpabuf_parse_bin(tmp + 4);
|
||||
if (!lci) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"CTRL: SET_NEIGHBOR: Bad LCI subelement");
|
||||
wpabuf_free(nr);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!buf)
|
||||
goto set;
|
||||
|
||||
tmp = os_strstr(buf, "civic=");
|
||||
if (tmp) {
|
||||
buf = os_strchr(tmp, ' ');
|
||||
if (buf)
|
||||
*buf++ = '\0';
|
||||
civic = wpabuf_parse_bin(tmp + 6);
|
||||
if (!civic) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"CTRL: SET_NEIGHBOR: Bad civic subelement");
|
||||
wpabuf_free(nr);
|
||||
wpabuf_free(lci);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
set:
|
||||
ret = hostapd_neighbor_set(hapd, bssid, &ssid, nr, lci, civic);
|
||||
|
||||
wpabuf_free(nr);
|
||||
wpabuf_free(lci);
|
||||
wpabuf_free(civic);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_remove_neighbor(struct hostapd_data *hapd,
|
||||
char *buf)
|
||||
{
|
||||
struct wpa_ssid_value ssid;
|
||||
u8 bssid[ETH_ALEN];
|
||||
char *tmp;
|
||||
|
||||
if (hwaddr_aton(buf, bssid)) {
|
||||
wpa_printf(MSG_ERROR, "CTRL: REMOVE_NEIGHBOR: Bad BSSID");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp = os_strstr(buf, "ssid=");
|
||||
if (!tmp || ssid_parse(tmp + 5, &ssid)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"CTRL: REMOVE_NEIGHBORr: Bad or missing SSID");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return hostapd_neighbor_remove(hapd, bssid, &ssid);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
|
||||
char *buf, char *reply,
|
||||
int reply_size,
|
||||
@ -2315,6 +2433,12 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
|
||||
reply_size);
|
||||
} else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
|
||||
hostapd_ctrl_iface_pmksa_flush(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_strncmp(buf, "REMOVE_NEIGHBOR ", 16) == 0) {
|
||||
if (hostapd_ctrl_iface_remove_neighbor(hapd, buf + 16))
|
||||
reply_len = -1;
|
||||
} else {
|
||||
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
|
||||
reply_len = 16;
|
||||
|
@ -1143,6 +1143,49 @@ static int hostapd_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_set_neighbor(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
char cmd[2048];
|
||||
int res;
|
||||
|
||||
if (argc < 3 || argc > 5) {
|
||||
printf("Invalid set_neighbor command: needs 3-5 arguments\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(cmd, sizeof(cmd), "SET_NEIGHBOR %s %s %s %s %s",
|
||||
argv[0], argv[1], argv[2], argc >= 4 ? argv[3] : "",
|
||||
argc == 5 ? argv[4] : "");
|
||||
if (os_snprintf_error(sizeof(cmd), res)) {
|
||||
printf("Too long SET_NEIGHBOR command.\n");
|
||||
return -1;
|
||||
}
|
||||
return wpa_ctrl_command(ctrl, cmd);
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_cli_cmd_remove_neighbor(struct wpa_ctrl *ctrl, int argc,
|
||||
char *argv[])
|
||||
{
|
||||
char cmd[400];
|
||||
int res;
|
||||
|
||||
if (argc != 2) {
|
||||
printf("Invalid remove_neighbor command: needs 2 arguments\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NEIGHBOR %s %s",
|
||||
argv[0], argv[1]);
|
||||
if (os_snprintf_error(sizeof(cmd), res)) {
|
||||
printf("Too long REMOVE_NEIGHBOR command.\n");
|
||||
return -1;
|
||||
}
|
||||
return wpa_ctrl_command(ctrl, cmd);
|
||||
}
|
||||
|
||||
|
||||
struct hostapd_cli_cmd {
|
||||
const char *cmd;
|
||||
int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
|
||||
@ -1204,6 +1247,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
|
||||
{ "log_level", hostapd_cli_cmd_log_level },
|
||||
{ "pmksa", hostapd_cli_cmd_pmksa },
|
||||
{ "pmksa_flush", hostapd_cli_cmd_pmksa_flush },
|
||||
{ "set_neighbor", hostapd_cli_cmd_set_neighbor },
|
||||
{ "remove_neighbor", hostapd_cli_cmd_remove_neighbor },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "x_snoop.h"
|
||||
#include "dhcp_snoop.h"
|
||||
#include "ndisc_snoop.h"
|
||||
#include "neighbor_db.h"
|
||||
|
||||
|
||||
static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason);
|
||||
@ -335,6 +336,8 @@ static void hostapd_free_hapd_data(struct hostapd_data *hapd)
|
||||
wpabuf_free(hapd->mesh_pending_auth);
|
||||
hapd->mesh_pending_auth = NULL;
|
||||
#endif /* CONFIG_MESH */
|
||||
|
||||
hostpad_free_neighbor_db(hapd);
|
||||
}
|
||||
|
||||
|
||||
@ -906,6 +909,7 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
|
||||
return -1;
|
||||
}
|
||||
hapd->started = 1;
|
||||
dl_list_init(&hapd->nr_db);
|
||||
|
||||
if (!first || first == -1) {
|
||||
u8 *addr = hapd->own_addr;
|
||||
|
@ -99,6 +99,16 @@ struct wps_stat {
|
||||
u8 peer_addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
struct hostapd_neighbor_entry {
|
||||
struct dl_list list;
|
||||
u8 bssid[ETH_ALEN];
|
||||
struct wpa_ssid_value ssid;
|
||||
struct wpabuf *nr;
|
||||
struct wpabuf *lci;
|
||||
struct wpabuf *civic;
|
||||
/* LCI update time */
|
||||
struct os_time lci_date;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct hostapd_data - hostapd per-BSS data structure
|
||||
@ -286,6 +296,8 @@ struct hostapd_data {
|
||||
#ifdef CONFIG_MBO
|
||||
unsigned int mbo_assoc_disallow;
|
||||
#endif /* CONFIG_MBO */
|
||||
|
||||
struct dl_list nr_db;
|
||||
};
|
||||
|
||||
|
||||
|
131
src/ap/neighbor_db.c
Normal file
131
src/ap/neighbor_db.c
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* hostapd / Neighboring APs DB
|
||||
* Copyright(c) 2013 - 2016 Intel Mobile Communications GmbH.
|
||||
* Copyright(c) 2011 - 2016 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "hostapd.h"
|
||||
#include "neighbor_db.h"
|
||||
|
||||
|
||||
static struct hostapd_neighbor_entry *
|
||||
hostapd_neighbor_get(struct hostapd_data *hapd, const u8 *bssid,
|
||||
const struct wpa_ssid_value *ssid)
|
||||
{
|
||||
struct hostapd_neighbor_entry *nr;
|
||||
|
||||
dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
|
||||
list) {
|
||||
if (os_memcmp(bssid, nr->bssid, ETH_ALEN) == 0 &&
|
||||
ssid->ssid_len == nr->ssid.ssid_len &&
|
||||
os_memcmp(ssid->ssid, nr->ssid.ssid, ssid->ssid_len) == 0)
|
||||
return nr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_neighbor_clear_entry(struct hostapd_neighbor_entry *nr)
|
||||
{
|
||||
wpabuf_free(nr->nr);
|
||||
nr->nr = NULL;
|
||||
wpabuf_free(nr->lci);
|
||||
nr->lci = NULL;
|
||||
wpabuf_free(nr->civic);
|
||||
nr->civic = NULL;
|
||||
os_memset(nr->bssid, 0, sizeof(nr->bssid));
|
||||
os_memset(&nr->ssid, 0, sizeof(nr->ssid));
|
||||
}
|
||||
|
||||
|
||||
static struct hostapd_neighbor_entry *
|
||||
hostapd_neighbor_add(struct hostapd_data *hapd)
|
||||
{
|
||||
struct hostapd_neighbor_entry *nr;
|
||||
|
||||
nr = os_zalloc(sizeof(struct hostapd_neighbor_entry));
|
||||
if (!nr)
|
||||
return NULL;
|
||||
|
||||
dl_list_add(&hapd->nr_db, &nr->list);
|
||||
|
||||
return nr;
|
||||
}
|
||||
|
||||
|
||||
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,
|
||||
const struct wpabuf *civic)
|
||||
{
|
||||
struct hostapd_neighbor_entry *entry;
|
||||
|
||||
entry = hostapd_neighbor_get(hapd, bssid, ssid);
|
||||
if (!entry)
|
||||
entry = hostapd_neighbor_add(hapd);
|
||||
if (!entry)
|
||||
return -1;
|
||||
|
||||
hostapd_neighbor_clear_entry(entry);
|
||||
|
||||
os_memcpy(entry->bssid, bssid, ETH_ALEN);
|
||||
os_memcpy(&entry->ssid, ssid, sizeof(entry->ssid));
|
||||
|
||||
entry->nr = wpabuf_dup(nr);
|
||||
if (!entry->nr)
|
||||
goto fail;
|
||||
|
||||
if (lci) {
|
||||
entry->lci = wpabuf_dup(lci);
|
||||
if (!entry->lci || os_get_time(&entry->lci_date))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (civic) {
|
||||
entry->civic = wpabuf_dup(civic);
|
||||
if (!entry->civic)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
hostapd_neighbor_remove(hapd, bssid, ssid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_neighbor_remove(struct hostapd_data *hapd, const u8 *bssid,
|
||||
const struct wpa_ssid_value *ssid)
|
||||
{
|
||||
struct hostapd_neighbor_entry *nr;
|
||||
|
||||
nr = hostapd_neighbor_get(hapd, bssid, ssid);
|
||||
if (!nr)
|
||||
return -1;
|
||||
|
||||
hostapd_neighbor_clear_entry(nr);
|
||||
dl_list_del(&nr->list);
|
||||
os_free(nr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void hostpad_free_neighbor_db(struct hostapd_data *hapd)
|
||||
{
|
||||
struct hostapd_neighbor_entry *nr, *prev;
|
||||
|
||||
dl_list_for_each_safe(nr, prev, &hapd->nr_db,
|
||||
struct hostapd_neighbor_entry, list) {
|
||||
hostapd_neighbor_clear_entry(nr);
|
||||
dl_list_del(&nr->list);
|
||||
os_free(nr);
|
||||
}
|
||||
}
|
21
src/ap/neighbor_db.h
Normal file
21
src/ap/neighbor_db.h
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* hostapd / Neighboring APs DB
|
||||
* Copyright(c) 2013 - 2016 Intel Mobile Communications GmbH.
|
||||
* Copyright(c) 2011 - 2016 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef NEIGHBOR_DB_H
|
||||
#define NEIGHBOR_DB_H
|
||||
|
||||
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,
|
||||
const struct wpabuf *civic);
|
||||
int hostapd_neighbor_remove(struct hostapd_data *hapd, const u8 *bssid,
|
||||
const struct wpa_ssid_value *ssid);
|
||||
void hostpad_free_neighbor_db(struct hostapd_data *hapd);
|
||||
|
||||
#endif /* NEIGHBOR_DB_H */
|
@ -797,6 +797,7 @@ OBJS += src/ap/ap_drv_ops.c
|
||||
OBJS += src/ap/beacon.c
|
||||
OBJS += src/ap/bss_load.c
|
||||
OBJS += src/ap/eap_user_db.c
|
||||
OBJS += src/ap/neighbor_db.c
|
||||
ifdef CONFIG_IEEE80211N
|
||||
OBJS += src/ap/ieee802_11_ht.c
|
||||
ifdef CONFIG_IEEE80211AC
|
||||
|
@ -844,6 +844,7 @@ OBJS += ../src/ap/ap_drv_ops.o
|
||||
OBJS += ../src/ap/beacon.o
|
||||
OBJS += ../src/ap/bss_load.o
|
||||
OBJS += ../src/ap/eap_user_db.o
|
||||
OBJS += ../src/ap/neighbor_db.o
|
||||
ifdef CONFIG_IEEE80211N
|
||||
OBJS += ../src/ap/ieee802_11_ht.o
|
||||
ifdef CONFIG_IEEE80211AC
|
||||
|
Loading…
Reference in New Issue
Block a user