Merge "bandsteering: Robustness to STAs which re-join the network."
diff --git a/hostapd/Makefile b/hostapd/Makefile
index 90645dc..f10556b 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -904,9 +904,9 @@
LIBS_h += -lsqlite3
endif
-ifdef CONFIG_FINGERPRINT
-CFLAGS += -DCONFIG_FINGERPRINT
-OBJS += ../src/ap/fingerprint.o
+ifdef CONFIG_CLIENT_TAXONOMY
+CFLAGS += -DCONFIG_CLIENT_TAXONOMY
+OBJS += ../src/ap/taxonomy.o
endif
OBJS += ../src/ap/steering.o
diff --git a/hostapd/defconfig b/hostapd/defconfig
index afdd7bc..88c2dbc 100644
--- a/hostapd/defconfig
+++ b/hostapd/defconfig
@@ -315,7 +315,7 @@
#
#CONFIG_ACS=y
#
-# Client Fingerprinting
-# Keeps track of fingerprints derived from Assoc and Probe frames per-STA.
+# Client Taxonomy
+# Keeps track of signatures derived from Assoc and Probe frames per-STA.
# These can be used to identfy the Wifi chipset/driver.
-#CONFIG_FINGERPRINT=y
+#CONFIG_CLIENT_TAXONOMY=y
diff --git a/hostapd/main.c b/hostapd/main.c
index 5ba3b9d..0fe7ac8 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -36,7 +36,7 @@
static struct hapd_global global;
char *alivemon_path = NULL;
-char *fingerprint_path = NULL;
+char *taxonomy_path = NULL;
char *steering_timestamp_path = NULL;
char *request_logging_path = NULL;
@@ -596,9 +596,11 @@
case 'f':
log_file = optarg;
break;
+#ifdef CONFIG_CLIENT_TAXONOMY
case 'F':
- fingerprint_path = optarg;
+ taxonomy_path = optarg;
break;
+#endif /* CONFIG_CLIENT_TAXONOMY */
case 'K':
wpa_debug_show_keys++;
break;
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 66b73c2..82fd7c4 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -29,6 +29,9 @@
#include "hs20.h"
#include "dfs.h"
#include "ap/steering.h"
+#ifdef CONFIG_CLIENT_TAXONOMY
+#include "taxonomy.h"
+#endif /* CONFIG_CLIENT_TAXONOMY */
#ifdef NEED_AP_MLME
@@ -622,27 +625,12 @@
}
#endif /* CONFIG_P2P */
-#ifdef CONFIG_FINGERPRINT
+#ifdef CONFIG_CLIENT_TAXONOMY
if (sta) {
- int idx;
- int is_bcast = elems.ssid_len == 0 && elems.ssid_list_len == 0;
-
- if (is_bcast) {
- idx = sta->duration_probe_bcast_idx++;
- sta->duration_probe_bcast[idx] =
- FINGERPRINT_DURATION_PRESENT |
- le_to_host16(mgmt->duration);
- sta->duration_probe_bcast_idx %= FINGERPRINT_NSAMPLES;
- } else {
- idx = sta->duration_probe_idx++;
- sta->duration_probe[idx] =
- FINGERPRINT_DURATION_PRESENT |
- le_to_host16(mgmt->duration);
- sta->duration_probe_idx %= FINGERPRINT_NSAMPLES;
- }
- hostapd_fingerprint_probe_req(sta, ie, ie_len, is_bcast);
+ hostapd_taxonomy_probe_req(sta, ie, ie_len);
+ hostapd_write_sta_taxonomy(sta);
}
-#endif /* CONFIG_FINGERPRINT */
+#endif /* CONFIG_CLIENT_TAXONOMY */
res = ssid_match(hapd, elems.ssid, elems.ssid_len,
elems.ssid_list, elems.ssid_list_len);
diff --git a/src/ap/fingerprint.h b/src/ap/fingerprint.h
deleted file mode 100644
index c26f257..0000000
--- a/src/ap/fingerprint.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * hostapd / Station fingerprinting
- * Copyright (c) 2015 Google, Inc.
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#ifndef FINGERPRINT_H
-#define FINGERPRINT_H
-
-void hostapd_fingerprint_probe_req(struct sta_info *sta,
- const u8 *ie, size_t ie_len, int is_bcast)
-void hostapd_fingerprint_assoc_req(struct sta_info *sta,
- const u8 *ie, size_t ie_len);
-
-#endif /* FINGERPRINT_H */
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 154a780..e291d08 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -15,7 +15,7 @@
#include "drivers/driver.h"
extern char *alivemon_path;
-extern char *fingerprint_path;
+extern char *taxonomy_path;
struct wpa_ctrl_dst;
struct radius_server_data;
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 2d289f6..9140f3e 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -42,6 +42,9 @@
#include "dfs.h"
#include "rm.h"
#include "ap/steering.h"
+#ifdef CONFIG_CLIENT_TAXONOMY
+#include "taxonomy.h"
+#endif /* CONFIG_CLIENT_TAXONOMY */
u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
@@ -1796,12 +1799,10 @@
* remove the STA immediately. */
sta->timeout_next = STA_NULLFUNC;
-#ifdef CONFIG_FINGERPRINT
- sta->duration_assoc[sta->duration_assoc_idx++] =
- FINGERPRINT_DURATION_PRESENT | le_to_host16(mgmt->duration);
- sta->duration_assoc_idx %= FINGERPRINT_NSAMPLES;
- hostapd_fingerprint_assoc_req(sta, pos, left);
-#endif /* CONFIG_FINGERPRINT */
+#ifdef CONFIG_CLIENT_TAXONOMY
+ hostapd_taxonomy_assoc_req(sta, pos, left);
+ hostapd_write_sta_taxonomy(sta);
+#endif /* CONFIG_CLIENT_TAXONOMY */
fail:
send_assoc_resp(hapd, sta, resp, reassoc, pos, left);
diff --git a/src/ap/rm.c b/src/ap/rm.c
index 5da8d90..4c9279e 100644
--- a/src/ap/rm.c
+++ b/src/ap/rm.c
@@ -130,10 +130,10 @@
len = (u8 *)&elements[num_aps] - buf;
hostapd_logger(hapd, m->da, HOSTAPD_MODULE_IEEE80211,
- HOSTAPD_LEVEL_DEBUG, "sending Neighbor List with %d APs",
+ HOSTAPD_LEVEL_NOTICE, "sending Neighbor List with %d APs",
num_aps);
if (hostapd_drv_send_mlme(hapd, m, len, 0) < 0)
- wpa_printf(MSG_INFO, "rm_send_neighbor_report: send failed");
+ wpa_printf(MSG_WARNING, "rm_send_neighbor_report: send failed");
}
@@ -150,7 +150,7 @@
/* Check that the request comes from a valid station. */
if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
- HOSTAPD_LEVEL_DEBUG,
+ HOSTAPD_LEVEL_NOTICE,
"rm action received is not from an associated "
"station");
/* TODO: respond with action frame refused status code */
@@ -166,7 +166,7 @@
}
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
- HOSTAPD_LEVEL_DEBUG,
+ HOSTAPD_LEVEL_INFO,
"hostapd_rm_action - unknown action code %d",
action_code);
}
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index d07c283..9f16b88 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -321,72 +321,47 @@
}
-#ifdef CONFIG_FINGERPRINT
-static void hostapd_write_duration_fingerprint(
- FILE *f, const char *prefix, u32 *fingerprints, int lim)
+#ifdef CONFIG_CLIENT_TAXONOMY
+void hostapd_write_sta_taxonomy(struct sta_info *sta)
{
int i;
- fprintf(f, prefix);
- for (i = 0; i < lim; ++i) {
- if (fingerprints[i] > 0) {
- int d = fingerprints[i] & FINGERPRINT_DURATION_MASK;
- fprintf(f, "%d,", d);
- }
- }
- fprintf(f, "\n");
-}
-
-static void hostapd_write_sta_fingerprints(struct sta_info *sta)
-{
- int i;
- char tmpfile[512], filename[512 + 4];
+ char tmpfile[1024 + 4], filename[1024];
FILE *f;
- if (fingerprint_path == NULL) {
+ if (taxonomy_path == NULL) {
+ return;
+ }
+
+ if ((os_strlen(sta->probe_ie_taxonomy) == 0) ||
+ (os_strlen(sta->assoc_ie_taxonomy) == 0)) {
return;
}
snprintf(filename, sizeof(filename), "%s/" MACSTR,
- fingerprint_path, MAC2STR(sta->addr));
+ taxonomy_path, MAC2STR(sta->addr));
snprintf(tmpfile, sizeof(tmpfile), "%s/" MACSTR ".tmp",
- fingerprint_path, MAC2STR(sta->addr));
+ taxonomy_path, MAC2STR(sta->addr));
if ((f = fopen(tmpfile, "w")) == NULL) {
wpa_printf(MSG_ERROR, "open %s failed", tmpfile);
return;
}
- hostapd_write_duration_fingerprint(
- f, "duration_assoc: ",
- sta->duration_assoc, FINGERPRINT_NSAMPLES);
- hostapd_write_duration_fingerprint(
- f, "duration_auth: ",
- sta->duration_auth, FINGERPRINT_NSAMPLES);
- hostapd_write_duration_fingerprint(
- f, "duration_probe: ",
- sta->duration_probe, FINGERPRINT_NSAMPLES);
- hostapd_write_duration_fingerprint(
- f, "duration_probe_bcast: ",
- sta->duration_probe_bcast, FINGERPRINT_NSAMPLES);
- fprintf(f, "mlme_probe: %s\n",
- sta->probe_ie_fingerprint);
- fprintf(f, "mlme_probe_bcast: %s\n",
- sta->probe_bcast_ie_fingerprint);
- fprintf(f, "mlme_assoc: %s\n",
- sta->assoc_ie_fingerprint);
+ fprintf(f, "wifi|probe:%s|assoc:%s", sta->probe_ie_taxonomy,
+ sta->assoc_ie_taxonomy);
fclose(f);
if (rename(tmpfile, filename)) {
wpa_printf(MSG_ERROR, "rename %s failed", tmpfile);
unlink(tmpfile);
}
}
-static void hostapd_remove_sta_fingerprints(struct sta_info *sta)
+static void hostapd_remove_sta_taxonomy(struct sta_info *sta)
{
char filename[1024];
snprintf(filename, sizeof(filename), "%s/" MACSTR,
- fingerprint_path, MAC2STR(sta->addr));
+ taxonomy_path, MAC2STR(sta->addr));
unlink(filename);
}
-#endif /* CONFIG_FINGERPRINT */
+#endif /* CONFIG_CLIENT_TAXONOMY */
/**
* ap_handle_timer - Per STA timer handler
@@ -410,9 +385,9 @@
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "deauthenticated due to "
"local deauth request");
-#ifdef CONFIG_FINGERPRINT
- hostapd_remove_sta_fingerprints(sta);
-#endif /* CONFIG_FINGERPRINT */
+#ifdef CONFIG_CLIENT_TAXONOMY
+ hostapd_remove_sta_taxonomy(sta);
+#endif /* CONFIG_CLIENT_TAXONOMY */
ap_free_sta(hapd, sta);
return;
}
@@ -472,9 +447,9 @@
next_time = hapd->conf->ap_max_inactivity;
}
-#ifdef CONFIG_FINGERPRINT
- hostapd_write_sta_fingerprints(sta);
-#endif /* CONFIG_FINGERPRINT */
+#ifdef CONFIG_CLIENT_TAXONOMY
+ hostapd_write_sta_taxonomy(sta);
+#endif /* CONFIG_CLIENT_TAXONOMY */
if (next_time) {
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index e6cf3b1..65e71f8 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -168,24 +168,11 @@
/* Last Authentication/(Re)Association Request/Action frame subtype */
u8 last_subtype;
-#ifdef CONFIG_FINGERPRINT
-#define FINGERPRINT_NSAMPLES 64
-#define FINGERPRINT_DURATION_PRESENT 0x00010000
-#define FINGERPRINT_DURATION_MASK 0x0000ffff
- u32 duration_auth[FINGERPRINT_NSAMPLES];
- int duration_auth_idx;
- u32 duration_assoc[FINGERPRINT_NSAMPLES];
- int duration_assoc_idx;
- u32 duration_probe[FINGERPRINT_NSAMPLES];
- int duration_probe_idx;
- u32 duration_probe_bcast[FINGERPRINT_NSAMPLES];
- int duration_probe_bcast_idx;
-
-#define FINGERPRINT_STRING_LEN 256
- char probe_ie_fingerprint[FINGERPRINT_STRING_LEN];
- char probe_bcast_ie_fingerprint[FINGERPRINT_STRING_LEN];
- char assoc_ie_fingerprint[FINGERPRINT_STRING_LEN];
-#endif /* CONFIG_FINGERPRINT */
+#ifdef CONFIG_CLIENT_TAXONOMY
+#define TAXONOMY_STRING_LEN 384
+ char probe_ie_taxonomy[TAXONOMY_STRING_LEN];
+ char assoc_ie_taxonomy[TAXONOMY_STRING_LEN];
+#endif /* CONFIG_CLIENT_TAXONOMY */
};
@@ -216,6 +203,9 @@
void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta);
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
void ap_sta_ip6addr_del(struct hostapd_data *hapd, struct sta_info *sta);
+#ifdef CONFIG_CLIENT_TAXONOMY
+void hostapd_write_sta_taxonomy(struct sta_info *sta);
+#endif /* CONFIG_CLIENT_TAXONOMY */
void hostapd_free_stas(struct hostapd_data *hapd);
void ap_handle_timer(void *eloop_ctx, void *timeout_ctx);
void ap_sta_replenish_timeout(struct hostapd_data *hapd, struct sta_info *sta,
diff --git a/src/ap/fingerprint.c b/src/ap/taxonomy.c
similarity index 83%
rename from src/ap/fingerprint.c
rename to src/ap/taxonomy.c
index d41cbc7..9a8812d 100644
--- a/src/ap/fingerprint.c
+++ b/src/ap/taxonomy.c
@@ -1,5 +1,5 @@
/*
- * hostapd / Station fingerprinting
+ * hostapd / Station client taxonomy
* Copyright (c) 2015 Google, Inc.
*
* This software may be distributed under the terms of the BSD license.
@@ -13,8 +13,8 @@
* ID and subtag are written for vendor options.
*
* Example strings:
- * tag:0,1,50,45,221(00904c,51)
- * tag:0,1,33,36,48,45,221(00904c,51),221(0050f2,2)
+ * 0,1,50,45,221(00904c,51)
+ * 0,1,33,36,48,45,221(00904c,51),221(0050f2,2)
*/
#include "utils/includes.h"
@@ -37,7 +37,7 @@
} else {
/* note that even spaces will be transformed to underscores,
* so 'Nexus 7' will turn into 'Nexus_7'. This is deliberate,
- * to make the fingerprint easier to parse. */
+ * to make the string easier to parse. */
dst[i] = '_';
}
}
@@ -87,8 +87,7 @@
memset(htcap, 0, sizeof(htcap));
memset(vhtcap, 0, sizeof(vhtcap));
memset(wps, 0, sizeof(wps));
- snprintf(fstr, flen, "tag:");
- flen = fstr_len - strlen(fstr) - 1;
+ fstr[0] = '\0';
while (ie_len >= 2) {
u8 id, elen;
@@ -160,28 +159,19 @@
fstr[fstr_len - 1] = '\0';
}
-void hostapd_fingerprint_probe_req(struct sta_info *sta,
- const u8 *ie, size_t ie_len, int is_bcast)
-{
- char *fstr;
- size_t fstr_len;
-
- if (is_bcast) {
- fstr = sta->probe_bcast_ie_fingerprint;
- fstr_len = sizeof(sta->probe_bcast_ie_fingerprint);
- } else {
- fstr = sta->probe_ie_fingerprint;
- fstr_len = sizeof(sta->probe_ie_fingerprint);
- }
-
- ie_to_string(fstr, fstr_len, ie, ie_len);
-}
-
-void hostapd_fingerprint_assoc_req(struct sta_info *sta,
+void hostapd_taxonomy_probe_req(struct sta_info *sta,
const u8 *ie, size_t ie_len)
{
- ie_to_string(sta->assoc_ie_fingerprint,
- sizeof(sta->assoc_ie_fingerprint),
+ ie_to_string(sta->probe_ie_taxonomy,
+ sizeof(sta->probe_ie_taxonomy),
+ ie, ie_len);
+}
+
+void hostapd_taxonomy_assoc_req(struct sta_info *sta,
+ const u8 *ie, size_t ie_len)
+{
+ ie_to_string(sta->assoc_ie_taxonomy,
+ sizeof(sta->assoc_ie_taxonomy),
ie, ie_len);
}
diff --git a/src/ap/taxonomy.h b/src/ap/taxonomy.h
new file mode 100644
index 0000000..e8b37b0
--- /dev/null
+++ b/src/ap/taxonomy.h
@@ -0,0 +1,17 @@
+/*
+ * hostapd / Station client taxonomy
+ * Copyright (c) 2015 Google, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef TAXONOMY_H
+#define TAXONOMY_H
+
+void hostapd_taxonomy_probe_req(struct sta_info *sta,
+ const u8 *ie, size_t ie_len);
+void hostapd_taxonomy_assoc_req(struct sta_info *sta,
+ const u8 *ie, size_t ie_len);
+
+#endif /* TAXONOMY_H */