test_storage: extend test harness; datastorage: two bug fixes

datastorage (bug fix): deleting expired array item would fail to test next item
test_storage: extended to cover all required datastorage entry points
test_storage: added ability to read script file
test_storage: added new and revised test scripts
TESTING.md: added to describe testing approach
general: added various TODO notes on things to come back to
general: revised #includes to make each "self-compiling"
general: revised #includes to minimise usage across source files
general: moved declarations and defintions to simplify and rationalise code
datastorage: refactor to support scalability testing
datastorage: made independent of time() calls to support testing
datastorage: fixed redundant use of both SORT_NUM and SORT_LENGTH defines
datastorage: fake kicking to test clients move between access points
msghandler: new module to reduce compile time interdependencies
mshhandler: (issue #100?) fixed SEGV memcpy() in dump_client() using strncpy()
ubus: merged uface into ubus
mac_utils: new module for MAC address utilites
test_header: added target to help #include rationalisation

Tested-by: Nick Hainke <vincent@systemli.org>
This commit is contained in:
Ian Clowes 2020-05-27 19:25:04 +01:00 committed by Polynomialdivision
parent 0f63e00c43
commit 67c3ed0d0a
46 changed files with 2947 additions and 1476 deletions

View file

@ -13,9 +13,6 @@ SET(SOURCES
storage/datastorage.c
include/datastorage.h
storage/uface.c
include/uface.h
network/networksocket.c
include/networksocket.h
@ -28,6 +25,9 @@ SET(SOURCES
utils/ubus.c
include/ubus.h
utils/msghandler.c
include/msghandler.h
utils/dawn_uci.c
include/dawn_uci.h
@ -37,6 +37,9 @@ SET(SOURCES
include/utils.h
utils/utils.c
utils/mac_utils.c
include/mac_utils.h
include/tcpsocket.h
network/tcpsocket.c
@ -48,23 +51,31 @@ SET(SOURCES
SET(SOURCES_TEST_STORAGE
test/test_storage.c
include/test_storage.h
include/uface.h
include/ubus.h
utils/utils.c
include/utils.h
utils/mac_utils.c
include/mac_utils.h
storage/datastorage.c
include/datastorage.h
utils/ieee80211_utils.c
include/ieee80211_utils.h)
SET(SOURCES_TEST_HEADER
test/test_header.c)
SET(LIBS
ubox ubus json-c blobmsg_json uci gcrypt iwinfo)
ADD_EXECUTABLE(dawn ${SOURCES})
ADD_EXECUTABLE(test_storage ${SOURCES_TEST_STORAGE})
ADD_EXECUTABLE(test_header ${SOURCES_TEST_HEADER})
TARGET_LINK_LIBRARIES(dawn ${LIBS})

View file

@ -1,11 +1,9 @@
// based on:
// https://github.com/vedantk/gcrypt-example/blob/master/gcry.cc
#include "crypto.h"
#include <stdio.h>
#include <gcrypt.h>
#include <stdint.h>
#include "crypto.h"
#define GCRY_CIPHER GCRY_CIPHER_AES128 // Pick the cipher here
#define GCRY_C_MODE GCRY_CIPHER_MODE_ECB // Pick the cipher mode here
@ -70,7 +68,7 @@ char *gcrypt_encrypt_msg(char *msg, size_t msg_length, int *out_length) {
if (!out){
fprintf(stderr, "gcry_cipher_encrypt error: not enought memory\n");
return NULL;
}
}
gcry_error_handle = gcry_cipher_encrypt(gcry_cipher_hd, out, msg_length, msg, msg_length);
if (gcry_error_handle) {
fprintf(stderr, "gcry_cipher_encrypt failed: %s/%s\n",
@ -91,7 +89,7 @@ char *gcrypt_decrypt_msg(char *msg, size_t msg_length) {
if (!out_buffer){
fprintf(stderr, "gcry_cipher_decrypt error: not enought memory\n");
return NULL;
}
}
gcry_error_handle = gcry_cipher_decrypt(gcry_cipher_hd, out_buffer, msg_length, msg, msg_length);
if (gcry_error_handle) {
fprintf(stderr, "gcry_cipher_decrypt failed: %s/%s\n",

View file

@ -1,6 +1,7 @@
#ifndef __DAWN_BROADCASTSOCKET_H
#define __DAWN_BROADCASTSOCKET_H
#include <arpa/inet.h>
/**
* Function that setups a broadcast socket.

View file

@ -1,7 +1,7 @@
#ifndef DAWN_CRYPTO_H
#define DAWN_CRYPTO_H
#include <stdlib.h>
#include <stddef.h>
/**
* Initialize gcrypt.

View file

@ -3,16 +3,11 @@
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <limits.h>
#ifndef ETH_ALEN
#define ETH_ALEN 6
#endif
#include "mac_utils.h"
#include "utils.h"
/* Mac */
@ -20,7 +15,7 @@
#define MAC_LIST_LENGTH 100
// ---------------- Global variables ----------------
uint8_t mac_list[MAC_LIST_LENGTH][ETH_ALEN];
extern uint8_t mac_list[][ETH_ALEN];
// ---------------- Functions ----------
void insert_macs_from_file();
@ -29,39 +24,37 @@ int insert_to_maclist(uint8_t mac[]);
int mac_in_maclist(uint8_t mac[]);
int mac_is_equal(uint8_t addr1[], uint8_t addr2[]);
int mac_is_greater(uint8_t addr1[], uint8_t addr2[]);
/* Metric */
// ---------------- Global variables ----------------
/*** Metrics and configuration data ***/
// ---------------- Structs ----------------
struct probe_metric_s {
int ap_weight;
int ht_support;
int vht_support;
int no_ht_support;
int no_vht_support;
int rssi;
int low_rssi;
int freq;
int chan_util;
int max_chan_util;
int rssi_val;
int low_rssi_val;
int chan_util_val;
int max_chan_util_val;
int ap_weight; // TODO: Never evaluated?
int ht_support; // eval_probe_metric()()
int vht_support; // eval_probe_metric()()
int no_ht_support; // eval_probe_metric()()
int no_vht_support; // eval_probe_metric()()
int rssi; // eval_probe_metric()()
int low_rssi; // eval_probe_metric()()
int freq; // eval_probe_metric()()
int chan_util; // eval_probe_metric()()
int max_chan_util; // eval_probe_metric()()
int rssi_val; // eval_probe_metric()()
int low_rssi_val; // eval_probe_metric()()
int chan_util_val; // eval_probe_metric()()
int max_chan_util_val; // eval_probe_metric()()
int min_probe_count;
int bandwidth_threshold;
int use_station_count;
int max_station_diff;
int bandwidth_threshold; // kick_clients()
int use_station_count; // better_ap_available()
int max_station_diff; // compare_station_count() <- better_ap_available()
int eval_probe_req;
int eval_auth_req;
int eval_assoc_req;
int deny_auth_reason;
int deny_assoc_reason;
int use_driver_recog;
int min_kick_count;
int min_kick_count; // kick_clients()
int chan_util_avg_period;
int set_hostapd_nr;
int kicking;
@ -98,12 +91,18 @@ struct network_config_s {
int bandwidth;
};
// ---------------- Global variables ----------------
struct network_config_s network_config;
struct time_config_s timeout_config;
extern struct network_config_s network_config;
extern struct time_config_s timeout_config;
extern struct probe_metric_s dawn_metric;
struct probe_metric_s dawn_metric;
extern int probe_entry_last;
/*** Core DAWN data structures for tracking network devices and status ***/
// Define this to remove printing / reporing of fields, and hence observe
// which fields are evaluated in use.
// #define DAWN_NO_OUTPUT
// TODO notes:
// Never used? = No code reference
// Never evaluated? = Set and passed in ubus, etc but never evaluated for outcomes
/* Probe, Auth, Assoc */
@ -111,16 +110,18 @@ extern int probe_entry_last;
typedef struct probe_entry_s {
uint8_t bssid_addr[ETH_ALEN];
uint8_t client_addr[ETH_ALEN];
uint8_t target_addr[ETH_ALEN];
uint32_t signal;
uint32_t freq;
uint8_t ht_capabilities;
uint8_t vht_capabilities;
time_t time;
uint8_t target_addr[ETH_ALEN]; // TODO: Never evaluated?
uint32_t signal; // eval_probe_metric()
uint32_t freq; // eval_probe_metric()
uint8_t ht_capabilities; // eval_probe_metric()
uint8_t vht_capabilities; // eval_probe_metric()
time_t time; // remove_old...entries
int counter;
int deny_counter;
uint8_t max_supp_datarate;
uint8_t min_supp_datarate;
#ifndef DAWN_NO_OUTPUT
int deny_counter; // TODO: Never used?
uint8_t max_supp_datarate; // TODO: Never used?
uint8_t min_supp_datarate; // TODO: Never used?
#endif
uint32_t rcpi;
uint32_t rsni;
} probe_entry;
@ -128,10 +129,10 @@ typedef struct probe_entry_s {
typedef struct auth_entry_s {
uint8_t bssid_addr[ETH_ALEN];
uint8_t client_addr[ETH_ALEN];
uint8_t target_addr[ETH_ALEN];
uint32_t signal;
uint32_t freq;
time_t time;
uint8_t target_addr[ETH_ALEN]; // TODO: Never evaluated?
uint32_t signal; // TODO: Never evaluated?
uint32_t freq; // TODO: Never evaluated?
time_t time; // Never used for removal?
int counter;
} auth_entry;
@ -150,13 +151,13 @@ typedef struct auth_entry_s assoc_entry;
#define NEIGHBOR_REPORT_LEN 200
// ---------------- Global variables ----------------
struct auth_entry_s denied_req_array[DENY_REQ_ARRAY_LEN];
extern struct auth_entry_s denied_req_array[];
extern int denied_req_last;
pthread_mutex_t denied_array_mutex;
extern pthread_mutex_t denied_array_mutex;
struct probe_entry_s probe_array[PROBE_ARRAY_LEN];
extern struct probe_entry_s probe_array[];
extern int probe_entry_last;
pthread_mutex_t probe_array_mutex;
extern pthread_mutex_t probe_array_mutex;
// ---------------- Functions ----------------
probe_entry insert_to_array(probe_entry entry, int inc_counter, int save_80211k, int is_beacon);
@ -192,39 +193,39 @@ void print_auth_entry(auth_entry entry);
typedef struct client_s {
uint8_t bssid_addr[ETH_ALEN];
uint8_t client_addr[ETH_ALEN];
char signature[SIGNATURE_LEN];
uint8_t ht_supported;
uint8_t vht_supported;
uint32_t freq;
uint8_t auth;
uint8_t assoc;
uint8_t authorized;
uint8_t preauth;
uint8_t wds;
uint8_t wmm;
uint8_t ht;
uint8_t vht;
uint8_t wps;
uint8_t mfp;
time_t time;
uint32_t aid;
uint32_t kick_count;
char signature[SIGNATURE_LEN]; // TODO: Never evaluated?
uint8_t ht_supported; // TODO: Never evaluated?
uint8_t vht_supported; // TODO: Never evaluated?
uint32_t freq; // TODO: Never evaluated?
uint8_t auth; // TODO: Never evaluated?
uint8_t assoc; // TODO: Never evaluated?
uint8_t authorized; // TODO: Never evaluated?
uint8_t preauth; // TODO: Never evaluated?
uint8_t wds; // TODO: Never evaluated?
uint8_t wmm; // TODO: Never evaluated?
uint8_t ht; // TODO: Never evaluated?
uint8_t vht; // TODO: Never evaluated?
uint8_t wps; // TODO: Never evaluated?
uint8_t mfp; // TODO: Never evaluated?
time_t time; // remove_old...entries
uint32_t aid; // TODO: Never evaluated?
uint32_t kick_count; // kick_clients()
uint8_t rrm_enabled_capa; //the first byte is enough
} client;
typedef struct ap_s {
uint8_t bssid_addr[ETH_ALEN];
uint32_t freq;
uint8_t ht_support;
uint8_t vht_support;
uint32_t channel_utilization;
time_t time;
uint32_t station_count;
uint8_t ssid[SSID_MAX_LEN];
uint32_t freq; // TODO: Never evaluated?
uint8_t ht_support; // eval_probe_metric()
uint8_t vht_support; // eval_probe_metric()
uint32_t channel_utilization; // eval_probe_metric()
time_t time; // remove_old...entries
uint32_t station_count; // compare_station_count() <- better_ap_available()
uint8_t ssid[SSID_MAX_LEN]; // compare_sid() < -better_ap_available()
char neighbor_report[NEIGHBOR_REPORT_LEN];
uint32_t collision_domain;
uint32_t bandwidth;
uint32_t ap_weight;
uint32_t collision_domain; // TODO: ap_get_collision_count() never evaluated?
uint32_t bandwidth; // TODO: Never evaluated?
uint32_t ap_weight; // eval_probe_metric()
char iface[MAX_INTERFACE_NAME];
char hostname[HOST_NAME_MAX];
} ap;
@ -232,19 +233,20 @@ typedef struct ap_s {
// ---------------- Defines ----------------
#define ARRAY_AP_LEN 50
#define TIME_THRESHOLD_AP 30
#define ARRAY_CLIENT_LEN 1000
#define TIME_THRESHOLD_CLIENT 30
#define TIME_THRESHOLD_CLIENT_UPDATE 10
#define TIME_THRESHOLD_CLIENT_KICK 60
// ---------------- Global variables ----------------
struct ap_s ap_array[ARRAY_AP_LEN];
extern struct ap_s ap_array[];
extern int ap_entry_last;
pthread_mutex_t ap_array_mutex;
extern pthread_mutex_t ap_array_mutex;
struct client_s client_array[ARRAY_CLIENT_LEN];
extern struct client_s client_array[];
extern int client_entry_last;
pthread_mutex_t client_array_mutex;
extern pthread_mutex_t client_array_mutex;
// ---------------- Functions ----------------
@ -256,10 +258,14 @@ void remove_old_client_entries(time_t current_time, long long int threshold);
void insert_client_to_array(client entry);
void kick_clients(uint8_t bssid[], uint32_t id);
int kick_clients(uint8_t bssid[], uint32_t id);
void update_iw_info(uint8_t bssid[]);
void client_array_insert(client entry);
client client_array_get_client(const uint8_t* client_addr);
client client_array_delete(client entry);
void print_client_array();
@ -278,20 +284,20 @@ ap ap_array_get_ap(uint8_t bssid_addr[]);
int probe_array_set_all_probe_count(uint8_t client_addr[], uint32_t probe_count);
#ifndef DAWN_NO_OUTPUT
int ap_get_collision_count(int col_domain);
#endif
void send_beacon_reports(uint8_t bssid[], int id);
/* Utils */
// ---------------- Defines -------------------
#define SORT_NUM 5
// ---------------- Global variables ----------------
#define SORT_LENGTH 5
char sort_string[SORT_LENGTH];
extern char sort_string[];
// ---------------- Functions -------------------
int better_ap_available(uint8_t bssid_addr[], uint8_t client_addr[], char* neighbor_report, int automatic_kick);
// All users of datastorage should call init_ / destroy_mutex at initialisation and termination respectively
int init_mutex();
void destroy_mutex();
#endif

View file

@ -1,12 +1,13 @@
#ifndef DAWN_RSSI_H
#define DAWN_RSSI_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <stddef.h>
#include <stdint.h>
// ---------------- Global variables ----------------
#define HOSTAPD_DIR_LEN 200
extern char hostapd_dir_glob[];
/**
* Get RSSI using the mac adress of the client.
* Function uses libiwinfo and searches through all interfaces that are existing.
@ -58,7 +59,7 @@ int get_expected_throughput(const char *ifname, uint8_t *client_addr);
int get_bssid(const char *ifname, uint8_t *bssid_addr);
int get_ssid(const char *ifname, char *ssid);
int get_ssid(const char *ifname, char *ssid, size_t ssidmax);
int get_channel_utilization(const char *ifname, uint64_t *last_channel_time, uint64_t *last_channel_time_busy);

View file

@ -1,6 +1,9 @@
#ifndef DAWN_UCI_H
#define DAWN_UCI_H
#include <time.h>
#include <stdbool.h>
/**
* Init uci. Call this function before using the other functions!
* @return if call was successful.

View file

@ -17,4 +17,11 @@ double iee80211_calculate_bitrate(uint8_t supp_rate_val);
*/
double iee80211_calculate_expected_throughput_mbit(int exp_thr);
/**
* Convert 802.11k RCPI value to RSSI dB
* @param rcpi
* @return
*/
int rcpi_to_rssi(int rcpi);
#endif //DAWN_IEEE80211_UTILS_H

43
src/include/mac_utils.h Normal file
View file

@ -0,0 +1,43 @@
#ifndef __DAWN_MAC_UTILS_H
#define __DAWN_MAC_UTILS_H
#include <stdint.h>
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
#define STR2MAC(a) &(a)[0], &(a)[1], &(a)[2], &(a)[3], &(a)[4], &(a)[5]
#define MACSTR "%02X:%02X:%02X:%02X:%02X:%02X"
#define MACSTRLOWER "%02x:%02x:%02x:%02x:%02x:%02x"
#ifndef ETH_ALEN
#define ETH_ALEN 6
#endif
/**
* Convert mac adress string to mac adress.
* @param txt
* @param addr
* @return
*/
int hwaddr_aton(const char* txt, uint8_t* addr);
/**
* Convert mac to use big characters.
* @param in
* @param out
* @return
*/
int convert_mac(char* in, char* out);
/**
* Write mac to a file.
* @param path
* @param addr
*/
void write_mac_to_file(char* path, uint8_t addr[]);
int mac_is_equal(const uint8_t addr1[], const uint8_t addr2[]);
int mac_is_greater(const uint8_t addr1[], const uint8_t addr2[]);
#endif

47
src/include/msghandler.h Normal file
View file

@ -0,0 +1,47 @@
#ifndef __DAWN_MSGHANDLER_H
#define __DAWN_MSGHANDLER_H
#include <libubox/blobmsg_json.h>
#include "datastorage.h"
/**
* Parse to probe request.
* @param msg
* @param prob_req
* @return
*/
int parse_to_probe_req(struct blob_attr* msg, probe_entry* prob_req);
/**
* Dump a client array into the database.
* @param msg - message to parse.
* @param do_kick - use the automatic kick function when updating the clients.
* @param id - ubus id.
* @return
*/
int parse_to_clients(struct blob_attr* msg, int do_kick, uint32_t id);
/**
* Parse to hostapd notify.
* Notify are such notifications like:
* + Disassociation
* + Deauthentication
* + ...
* @param msg
* @param notify_req
* @return
*/
int parse_to_hostapd_notify(struct blob_attr* msg, hostapd_notify_entry* notify_req);
/**
* Handle network messages.
* @param msg
* @return
*/
int handle_network_msg(char* msg);
int handle_deauth_req(struct blob_attr* msg);
#endif

View file

@ -1,6 +1,8 @@
#ifndef __DAWN_MULTICASTSTSOCKET_H
#define __DAWN_MULTICASTSSOCKET_H
#include <arpa/inet.h>
/**
* Setup a multicast socket.
* Setup permissions. Join the multicast group, etc. ...

View file

@ -3,8 +3,6 @@
#include <pthread.h>
pthread_mutex_t send_mutex;
/**
* Init a socket using the runopts.
* @param _ip - ip to use.

View file

@ -3,7 +3,6 @@
#include <libubox/ustream.h>
#include <netinet/in.h>
#include <pthread.h>
#define ARRAY_NETWORK_LEN 50

View file

@ -0,0 +1,14 @@
#ifndef __DAWN_TESTSTORAGE_H
#define __DAWN_TESTSTORAGE_H
#include "datastorage.h"
/*
** Contains declerations, etc needed across datastorage and its test harness,
** but not more widely.
*/
void ap_array_insert(ap entry);
ap ap_array_delete(ap entry);
#endif

View file

@ -4,7 +4,6 @@
#include <libubox/blobmsg_json.h>
#include <libubox/uloop.h>
#include "datastorage.h"
// 802.11 Status codes
@ -17,9 +16,6 @@
#define UNSPECIFIED_REASON 0
#define NO_MORE_STAS 5
#define HOSTAPD_DIR_LEN 200
char hostapd_dir_glob[HOSTAPD_DIR_LEN];
/**
* Init ubus.
* Setup tcp socket.
@ -41,14 +37,6 @@ void start_umdns_update();
*/
int ubus_call_umdns();
/**
* Parse to probe request.
* @param msg
* @param prob_req
* @return
*/
int parse_to_probe_req(struct blob_attr *msg, probe_entry *prob_req);
/**
* Parse to authentication request.
* @param msg
@ -65,27 +53,6 @@ int parse_to_auth_req(struct blob_attr *msg, auth_entry *auth_req);
*/
int parse_to_assoc_req(struct blob_attr *msg, assoc_entry *assoc_req);
/**
* Dump a client array into the database.
* @param msg - message to parse.
* @param do_kick - use the automatic kick function when updating the clients.
* @param id - ubus id.
* @return
*/
int parse_to_clients(struct blob_attr *msg, int do_kick, uint32_t id);
/**
* Parse to hostapd notify.
* Notify are such notifications like:
* + Disassociation
* + Deauthentication
* + ...
* @param msg
* @param notify_req
* @return
*/
int parse_to_hostapd_notify(struct blob_attr *msg, hostapd_notify_entry *notify_req);
/**
* Kick client from all hostapd interfaces.
* @param client_addr - the client adress of the client to kick.
@ -102,19 +69,34 @@ void del_client_all_interfaces(const uint8_t *client_addr, uint32_t reason, uint
void update_hostapd_sockets(struct uloop_timeout *t);
/**
* Handle network messages.
* @param msg
* Send control message to all hosts to add the mac to a don't control list.
* @param client_addr
* @return
*/
int handle_network_msg(char *msg);
int send_add_mac(uint8_t *client_addr);
void ubus_send_beacon_report(uint8_t client[], int id);
void uloop_add_data_cbs();
int uci_send_via_network();
int build_hearing_map_sort_client(struct blob_buf* b);
int build_network_overview(struct blob_buf* b);
int ap_get_nr(struct blob_buf* b, uint8_t own_bssid_addr[]);
int parse_add_mac_to_file(struct blob_attr* msg);
int handle_auth_req(struct blob_attr* msg);
/**
* Send message via network.
* @param msg
* @param method
* Send probe message via the network.
* @param probe_entry
* @return
*/
int send_blob_attr_via_network(struct blob_attr *msg, char *method);
int ubus_send_probe_via_network(struct probe_entry_s probe_entry);
/**
* Add mac to a list that contains addresses of clients that can not be controlled.
@ -125,18 +107,45 @@ int send_blob_attr_via_network(struct blob_attr *msg, char *method);
void blobmsg_add_macaddr(struct blob_buf *buf, const char *name, const uint8_t *addr);
/**
* Send control message to all hosts to add the mac to a don't control list.
* Send message via network.
* @param msg
* @param method
* @return
*/
int send_blob_attr_via_network(struct blob_attr* msg, char* method);
/**
* Set client timer for updating the clients.
* @param time
*/
void add_client_update_timer(time_t time);
/**
* Kick client from hostapd interface.
* @param id - the ubus id.
* @param client_addr - the client adress of the client to kick.
* @param reason - the reason to kick the client.
* @param deauth - if the client should be deauthenticated.
* @param ban_time - the ban time the client is not allowed to connect again.
*/
void del_client_interface(uint32_t id, const uint8_t* client_addr, uint32_t reason, uint8_t deauth, uint32_t ban_time);
/**
* Function to set the probe counter to the min probe request.
* This allows that the client is able to connect directly without sending multiple probe requests to the Access Point.
* @param client_addr
* @return
*/
int send_add_mac(uint8_t *client_addr);
int send_set_probe(uint8_t client_addr[]);
int uci_send_via_network();
int build_hearing_map_sort_client(struct blob_buf *b);
int build_network_overview(struct blob_buf *b);
int ap_get_nr(struct blob_buf *b, uint8_t own_bssid_addr[]);
/**
* Function to tell a client that it is about to be disconnected.
* @param id
* @param client_addr
* @param dest_ap
* @param duration
* @return - 0 = asynchronous (client has been told to remove itself, and caller should manage arrays); 1 = synchronous (caller should assume arrays are updated)
*/
int wnm_disassoc_imminent(uint32_t id, const uint8_t* client_addr, char* dest_ap, uint32_t duration);
#endif

View file

@ -1,41 +0,0 @@
#ifndef __DAWN_UFACE_H
#define __DAWN_UFACE_H
/**
* Set client timer for updating the clients.
* @param time
*/
void add_client_update_timer(time_t time);
/**
* Kick client from hostapd interface.
* @param id - the ubus id.
* @param client_addr - the client adress of the client to kick.
* @param reason - the reason to kick the client.
* @param deauth - if the client should be deauthenticated.
* @param ban_time - the ban time the client is not allowed to connect again.
*/
void del_client_interface(uint32_t id, const uint8_t *client_addr, uint32_t reason, uint8_t deauth, uint32_t ban_time);
/**
* Function to set the probe counter to the min probe request.
* This allows that the client is able to connect directly without sending multiple probe requests to the Access Point.
* @param client_addr
* @return
*/
int send_set_probe(uint8_t client_addr[]);
void ubus_send_beacon_report(uint8_t client[], int id);
/**
* Send probe message via the network.
* @param probe_entry
* @return
*/
int ubus_send_probe_via_network(struct probe_entry_s probe_entry);
void uloop_add_data_cbs();
void wnm_disassoc_imminent(uint32_t id, const uint8_t *client_addr, char* dest_ap, uint32_t duration);
#endif // __DAWN_UFACE_H

View file

@ -2,43 +2,13 @@
#define __DAWN_UTILS_H
#include <stdint.h>
#include <ctype.h>
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
#define STR2MAC(a) &(a)[0], &(a)[1], &(a)[2], &(a)[3], &(a)[4], &(a)[5]
#define MACSTR "%02X:%02X:%02X:%02X:%02X:%02X"
#define MACSTRLOWER "%02x:%02x:%02x:%02x:%02x:%02x"
/**
* Convert char to binary.
* @param ch
* @return
*/
int hex_to_bin(char ch);
/**
* Convert mac adress string to mac adress.
* @param txt
* @param addr
* @return
*/
int hwaddr_aton(const char *txt, uint8_t *addr);
/**
* Convert mac to use big characters.
* @param in
* @param out
* @return
*/
int convert_mac(char *in, char *out);
/**
* Write mac to a file.
* @param path
* @param addr
*/
void write_mac_to_file(char *path, uint8_t addr[]);
int hex_to_dec(char ch);
/**
* Check if a string is greater than another one.
@ -48,6 +18,4 @@ void write_mac_to_file(char *path, uint8_t addr[]);
*/
int string_is_greater(uint8_t *str, uint8_t *str_2);
int rcpi_to_rssi(int rcpi);
#endif

View file

@ -8,6 +8,7 @@
#include "networksocket.h"
#include "ubus.h"
#include "dawn_uci.h"
#include "dawn_iwinfo.h"
#include "tcpsocket.h"
#include "crypto.h"
@ -15,8 +16,6 @@ void daemon_shutdown();
void signal_handler(int sig);
int init_mutex();
struct sigaction signal_action;
void daemon_shutdown() {
@ -25,11 +24,7 @@ void daemon_shutdown() {
uci_clear();
uloop_cancelled = true;
// free resources
fprintf(stdout, "Freeing mutex resources\n");
pthread_mutex_destroy(&probe_array_mutex);
pthread_mutex_destroy(&client_array_mutex);
pthread_mutex_destroy(&ap_array_mutex);
destroy_mutex();
}
void signal_handler(int sig) {
@ -49,30 +44,6 @@ void signal_handler(int sig) {
}
}
int init_mutex() {
if (pthread_mutex_init(&probe_array_mutex, NULL) != 0) {
fprintf(stderr, "Mutex init failed!\n");
return 1;
}
if (pthread_mutex_init(&client_array_mutex, NULL) != 0) {
fprintf(stderr, "Mutex init failed!\n");
return 1;
}
if (pthread_mutex_init(&ap_array_mutex, NULL) != 0) {
fprintf(stderr, "Mutex init failed!\n");
return 1;
}
if (pthread_mutex_init(&denied_array_mutex, NULL) != 0) {
fprintf(stderr, "Mutex init failed!\n");
return 1;
}
return 0;
}
int main(int argc, char **argv) {
const char *ubus_socket = NULL;
@ -89,6 +60,7 @@ int main(int argc, char **argv) {
sigaction(SIGINT, &signal_action, NULL);
uci_init();
// TODO: Why the extra loacl struct to retuen into?
struct network_config_s net_config = uci_get_dawn_network();
network_config = net_config;
@ -96,6 +68,7 @@ int main(int argc, char **argv) {
gcrypt_init();
gcrypt_set_key_and_iv(net_config.shared_key, net_config.iv);
// TODO: Why the extra loacl struct to retuen into?
struct time_config_s time_config = uci_get_time_config();
timeout_config = time_config; // TODO: Refactor...

View file

@ -1,11 +1,7 @@
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include "networksocket.h"
#include "broadcastsocket.h"
int setup_broadcast_socket(const char *_broadcast_ip, unsigned short _broadcast_port, struct sockaddr_in *addr) {

View file

@ -1,13 +1,6 @@
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "multicastsocket.h"

View file

@ -1,28 +1,29 @@
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libubox/blobmsg_json.h>
#include "networksocket.h"
#include "datastorage.h"
#include "multicastsocket.h"
#include "broadcastsocket.h"
#include "ubus.h"
#include "msghandler.h"
#include "crypto.h"
#include "datastorage.h"
#include "networksocket.h"
/* Network Defines */
#define MAX_RECV_STRING 2048
/* Network Attributes */
int sock;
struct sockaddr_in addr;
const char *ip;
unsigned short port;
char recv_string[MAX_RECV_STRING + 1];
int recv_string_len;
int multicast_socket;
static int sock;
static struct sockaddr_in addr;
static const char *ip;
static unsigned short port;
static char recv_string[MAX_RECV_STRING + 1];
static int recv_string_len;
static int multicast_socket;
static pthread_mutex_t send_mutex;
void *receive_msg(void *args);
@ -102,7 +103,7 @@ void *receive_msg_enc(void *args) {
if (!base64_dec_str){
fprintf(stderr, "Received network error: not enought memory\n");
return 0;
}
}
int base64_dec_length = b64_decode(recv_string, base64_dec_str, B64_DECODE_LEN(strlen(recv_string)));
char *dec = gcrypt_decrypt_msg(base64_dec_str, base64_dec_length);
if (!dec){
@ -147,7 +148,7 @@ int send_string_enc(char *msg) {
fprintf(stderr, "sendto() error: not enought memory\n");
pthread_mutex_unlock(&send_mutex);
exit(EXIT_FAILURE);
}
}
char *base64_enc_str = malloc(B64_ENCODE_LEN(length_enc));
if (!base64_enc_str){
@ -155,7 +156,7 @@ int send_string_enc(char *msg) {
fprintf(stderr, "sendto() error: not enought memory\n");
pthread_mutex_unlock(&send_mutex);
exit(EXIT_FAILURE);
}
}
size_t base64_enc_length = b64_encode(enc, length_enc, base64_enc_str, B64_ENCODE_LEN(length_enc));
if (sendto(sock,

View file

@ -1,15 +1,14 @@
#include <libubox/usock.h>
#include <libubox/ustream.h>
#include <libubox/uloop.h>
#include <libubox/utils.h> // base64 encoding
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tcpsocket.h"
#include <arpa/inet.h>
#include "ubus.h"
#include <inttypes.h>
#include "msghandler.h"
#include "crypto.h"
#include "datastorage.h"
#include "tcpsocket.h"
#define STR_EVAL(x) #x
#define STR_QUOTE(x) STR_EVAL(x)
LIST_HEAD(tcp_sock_list);
@ -82,39 +81,43 @@ static void client_to_server_state(struct ustream *s) {
static void client_read_cb(struct ustream *s, int bytes) {
char *str, *str_tmp;
int len = 0;
uint32_t final_len = sizeof(uint32_t);
uint32_t final_len = sizeof(uint32_t); // big enough to get msg length
str = malloc(final_len);
if (!str) {
fprintf(stderr,"not enough memory\n");
fprintf(stderr,"not enough memory (" STR_QUOTE(__LINE__) ")\n");
goto nofree;
}
if ((len = ustream_pending_data(s, false)) < final_len){//ensure recv sizeof(uint32_t).
fprintf(stdout,"not complete msg, len:%d, expected len:%u\n", len, final_len);
goto out;
}
ustream_read(s, str, final_len);
final_len = ntohl(*(uint32_t *)str) - sizeof(uint32_t);//the final_len in headder includes header itself
if (ustream_read(s, str, final_len) != final_len) // read msg length bytes
{
fprintf(stdout,"msg length read failed\n");
goto out;
}
final_len = ntohl(*(uint32_t *)str) - final_len;//the final_len in headder includes header itself
str_tmp = realloc(str, final_len);
if (!str_tmp) {
fprintf(stderr,"not enough memory\n");
goto out;//On failure, realloc returns a null pointer. The original pointer str remains valid
fprintf(stderr,"not enough memory (%" PRIu32 " @ " STR_QUOTE(__LINE__) ")\n", final_len);
goto out;//On failure, realloc returns a null pointer. The original pointer str remains valid
//and may need to be deallocated with free() or realloc().
}
str = str_tmp;
if ((len = ustream_pending_data(s, false)) < final_len){//ensure recv final_len bytes.
fprintf(stdout,"not complete msg, len:%d, expected len:%u\n", len, final_len);
goto out;
}
ustream_read(s, str, final_len);
if (network_config.use_symm_enc) {
char *dec = gcrypt_decrypt_msg(str, final_len);//len of str is final_len
if (network_config.use_symm_enc) {
char *dec = gcrypt_decrypt_msg(str, final_len);//len of str is final_len
if (!dec) {
fprintf(stderr,"not enough memory\n");
fprintf(stderr,"not enough memory (" STR_QUOTE(__LINE__) ")\n");
goto out;
}
}
handle_network_msg(dec);
free(dec);
} else {
@ -247,17 +250,17 @@ void send_tcp(char *msg) {
size_t msglen = strlen(msg)+1;
char *enc = gcrypt_encrypt_msg(msg, msglen, &length_enc);
if (!enc){
fprintf(stderr, "Ustream error: not enought memory\n");
fprintf(stderr, "Ustream error: not enought memory (" STR_QUOTE(__LINE__) ")\n");
return;
}
}
uint32_t final_len = length_enc + sizeof(final_len);
char *final_str = malloc(final_len);
if (!final_str){
free(enc);
fprintf(stderr, "Ustream error: not enought memory\n");
fprintf(stderr, "Ustream error: not enought memory (" STR_QUOTE(__LINE__) ")\n");
return;
}
}
uint32_t *msg_header = (uint32_t *)final_str;
*msg_header = htonl(final_len);
memcpy(final_str+sizeof(final_len), enc, length_enc);
@ -267,14 +270,14 @@ void send_tcp(char *msg) {
int len_ustream = ustream_write(&con->stream.stream, final_str, final_len, 0);
printf("Ustream send: %d\n", len_ustream);
if (len_ustream <= 0) {
fprintf(stderr,"Ustream error!\n");
fprintf(stderr,"Ustream error(" STR_QUOTE(__LINE__) ")!\n");
//ERROR HANDLING!
if (con->stream.stream.write_error) {
ustream_free(&con->stream.stream);
close(con->fd.fd);
list_del(&con->list);
free(con);
}
}
}
}
@ -287,9 +290,9 @@ void send_tcp(char *msg) {
uint32_t final_len = msglen + sizeof(final_len);
char *final_str = malloc(final_len);
if (!final_str){
fprintf(stderr, "Ustream error: not enought memory\n");
fprintf(stderr, "Ustream error: not enought memory (" STR_QUOTE(__LINE__) ")\n");
return;
}
}
uint32_t *msg_header = (uint32_t *)final_str;
*msg_header = htonl(final_len);
memcpy(final_str+sizeof(final_len), msg, msglen);
@ -301,13 +304,13 @@ void send_tcp(char *msg) {
printf("Ustream send: %d\n", len_ustream);
if (len_ustream <= 0) {
//ERROR HANDLING!
fprintf(stderr,"Ustream error!\n");
fprintf(stderr,"Ustream error(" STR_QUOTE(__LINE__) ")!\n");
if (con->stream.stream.write_error) {
ustream_free(&con->stream.stream);
close(con->fd.fd);
list_del(&con->list);
free(con);
}
}
}
}
}

View file

@ -1,11 +1,20 @@
#include <stdbool.h>
#include "dawn_iwinfo.h"
#include "utils.h"
#include "dawn_uci.h"
#include "mac_utils.h"
#include "ieee80211_utils.h"
#include "datastorage.h"
#include "uface.h"
#include "test_storage.h"
#include "msghandler.h"
#include "ubus.h"
struct probe_metric_s dawn_metric;
struct network_config_s network_config;
struct time_config_s timeout_config;
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
@ -16,45 +25,62 @@
#define WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE BIT(5)
#define WLAN_RRM_CAPS_BEACON_REPORT_TABLE BIT(6)
int go_next_help(char sort_order[], int i, probe_entry entry,
static int go_next_help(char sort_order[], int i, probe_entry entry,
probe_entry next_entry);
int go_next(char sort_order[], int i, probe_entry entry,
static int go_next(char sort_order[], int i, probe_entry entry,
probe_entry next_entry);
int client_array_go_next(char sort_order[], int i, client entry,
static int client_array_go_next(char sort_order[], int i, client entry,
client next_entry);
int client_array_go_next_help(char sort_order[], int i, client entry,
static int client_array_go_next_help(char sort_order[], int i, client entry,
client next_entry);
int kick_client(struct client_s client_entry, char* neighbor_report);
static int kick_client(struct client_s client_entry, char* neighbor_report);
void ap_array_insert(ap entry);
static void print_ap_entry(ap entry);
ap ap_array_delete(ap entry);
static int is_connected(uint8_t bssid_addr[], uint8_t client_addr[]);
void print_ap_entry(ap entry);
int is_connected(uint8_t bssid_addr[], uint8_t client_addr[]);
int compare_station_count(uint8_t *bssid_addr_own, uint8_t *bssid_addr_to_compare, uint8_t *client_addr,
static int compare_station_count(uint8_t *bssid_addr_own, uint8_t *bssid_addr_to_compare, uint8_t *client_addr,
int automatic_kick);
int compare_ssid(uint8_t *bssid_addr_own, uint8_t *bssid_addr_to_compare);
static int compare_ssid(uint8_t *bssid_addr_own, uint8_t *bssid_addr_to_compare);
int denied_req_array_go_next(char sort_order[], int i, auth_entry entry,
static int denied_req_array_go_next(char sort_order[], int i, auth_entry entry,
auth_entry next_entry);
int denied_req_array_go_next_help(char sort_order[], int i, auth_entry entry,
static int denied_req_array_go_next_help(char sort_order[], int i, auth_entry entry,
auth_entry next_entry);
// ---------------- Global variables ----------------
struct auth_entry_s denied_req_array[DENY_REQ_ARRAY_LEN];
extern int denied_req_last;
pthread_mutex_t denied_array_mutex;
struct probe_entry_s probe_array[PROBE_ARRAY_LEN];
extern int probe_entry_last;
pthread_mutex_t probe_array_mutex;
struct ap_s ap_array[ARRAY_AP_LEN];
extern int ap_entry_last;
pthread_mutex_t ap_array_mutex;
struct client_s client_array[ARRAY_CLIENT_LEN];
extern int client_entry_last;
pthread_mutex_t client_array_mutex;
char sort_string[SORT_LENGTH];
int probe_entry_last = -1;
int client_entry_last = -1;
int ap_entry_last = -1;
int mac_list_entry_last = -1;
int denied_req_last = -1;
uint8_t mac_list[MAC_LIST_LENGTH][ETH_ALEN];
void send_beacon_reports(uint8_t bssid[], int id) {
pthread_mutex_lock(&client_array_mutex);
@ -72,9 +98,9 @@ void send_beacon_reports(uint8_t bssid[], int id) {
if (!mac_is_equal(client_array[j].bssid_addr, bssid)) {
break;
}
if (client_array[j].rrm_enabled_capa &
if (client_array[j].rrm_enabled_capa &
(WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE |
WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE |
WLAN_RRM_CAPS_BEACON_REPORT_TABLE))
ubus_send_beacon_report(client_array[j].client_addr, id);
}
@ -92,14 +118,14 @@ int eval_probe_metric(struct probe_entry_s probe_entry) {
// check if ap entry is available
if (mac_is_equal(ap_entry.bssid_addr, probe_entry.bssid_addr)) {
score += probe_entry.ht_capabilities && ap_entry.ht_support ? dawn_metric.ht_support : 0;
score += !probe_entry.ht_capabilities && !ap_entry.ht_support ? dawn_metric.no_ht_support : 0;
score += !probe_entry.ht_capabilities && !ap_entry.ht_support ? dawn_metric.no_ht_support : 0; // TODO: Is both devices not having a capability worthy of scoring?
// performance anomaly?
if (network_config.bandwidth >= 1000 || network_config.bandwidth == -1) {
score += probe_entry.vht_capabilities && ap_entry.vht_support ? dawn_metric.vht_support : 0;
}
score += !probe_entry.vht_capabilities && !ap_entry.vht_support ? dawn_metric.no_vht_support : 0;
score += !probe_entry.vht_capabilities && !ap_entry.vht_support ? dawn_metric.no_vht_support : 0; // TODO: Is both devices not having a capability worthy of scoring?
score += ap_entry.channel_utilization <= dawn_metric.chan_util_val ? dawn_metric.chan_util : 0;
score += ap_entry.channel_utilization > dawn_metric.max_chan_util_val ? dawn_metric.max_chan_util : 0;
@ -107,9 +133,15 @@ int eval_probe_metric(struct probe_entry_s probe_entry) {
}
score += (probe_entry.freq > 5000) ? dawn_metric.freq : 0;
// TODO: Should RCPI be used here as well?
// TODO: Check higher value means more signal, not more -dB :)
// TODO: Should this be more scaled? Should -63dB on current and -77dB on other both score 0 if low / high are -80db and -60dB?
// TODO: That then lets device capabilites dominate score - making them more important than RSSI difference of 14dB.
score += (probe_entry.signal >= dawn_metric.rssi_val) ? dawn_metric.rssi : 0;
score += (probe_entry.signal <= dawn_metric.low_rssi_val) ? dawn_metric.low_rssi : 0;
// TODO: This magic value never checked by caller. What does it achieve?
if (score < 0)
score = -2; // -1 already used...
@ -119,7 +151,7 @@ int eval_probe_metric(struct probe_entry_s probe_entry) {
return score;
}
int compare_ssid(uint8_t *bssid_addr_own, uint8_t *bssid_addr_to_compare) {
static int compare_ssid(uint8_t *bssid_addr_own, uint8_t *bssid_addr_to_compare) {
ap ap_entry_own = ap_array_get_ap(bssid_addr_own);
ap ap_entry_to_compre = ap_array_get_ap(bssid_addr_to_compare);
@ -130,7 +162,7 @@ int compare_ssid(uint8_t *bssid_addr_own, uint8_t *bssid_addr_to_compare) {
return 0;
}
int compare_station_count(uint8_t *bssid_addr_own, uint8_t *bssid_addr_to_compare, uint8_t *client_addr,
static int compare_station_count(uint8_t *bssid_addr_own, uint8_t *bssid_addr_to_compare, uint8_t *client_addr,
int automatic_kick) {
ap ap_entry_own = ap_array_get_ap(bssid_addr_own);
@ -185,7 +217,7 @@ int better_ap_available(uint8_t bssid_addr[], uint8_t client_addr[], char* neigh
}
if (mac_is_equal(bssid_addr, probe_array[j].bssid_addr)) {
printf("Calculating own score!\n");
own_score = eval_probe_metric(probe_array[j]);
own_score = eval_probe_metric(probe_array[j]); //TODO: Should the -2 return be handled?
break;
}
}
@ -196,7 +228,7 @@ int better_ap_available(uint8_t bssid_addr[], uint8_t client_addr[], char* neigh
}
int k;
int max_score = 0;
int max_score = 0; //TODO: Set this to own_score so we are just looking for AP that are better?
int kick = 0;
for (k = i; k <= probe_entry_last; k++) {
int score_to_compare;
@ -241,6 +273,8 @@ int better_ap_available(uint8_t bssid_addr[], uint8_t client_addr[], char* neigh
//return 1;
}
// TODO: Not sure this is correct. Isn't it always checking against current AP, but should be using
// TODO: previous max_score AP and new candidate? Also is absolute number meaningful when AP have diffeent capacity?
if (dawn_metric.use_station_count > 0 && own_score == score_to_compare && score_to_compare > max_score) {
// only compare if score is bigger or equal 0
@ -270,14 +304,19 @@ int better_ap_available(uint8_t bssid_addr[], uint8_t client_addr[], char* neigh
return kick;
}
int kick_client(struct client_s client_entry, char* neighbor_report) {
// TODO: mac_in_maclist() returns 0 or 1; better_ap_available() returns -1, 0, or 1.
// What is the intended behaviour for 1 && -1 -> 1? Is this relying on undocumented side-effects to get -1?
static int kick_client(struct client_s client_entry, char* neighbor_report) {
return !mac_in_maclist(client_entry.client_addr) &&
better_ap_available(client_entry.bssid_addr, client_entry.client_addr, neighbor_report, 1);
}
void kick_clients(uint8_t bssid[], uint32_t id) {
int kick_clients(uint8_t bssid[], uint32_t id) {
pthread_mutex_lock(&client_array_mutex);
pthread_mutex_lock(&probe_array_mutex);
int kicked_clients = 0;
printf("-------- KICKING CLIENTS!!!---------\n");
char mac_buf_ap[20];
sprintf(mac_buf_ap, MACSTR, MAC2STR(bssid));
@ -291,6 +330,130 @@ void kick_clients(uint8_t bssid[], uint32_t id) {
}
}
// Go threw clients
int j = i;
while (j <= client_entry_last) {
if (!mac_is_equal(client_array[j].bssid_addr, bssid)) {
break;
}
char neighbor_report[NEIGHBOR_REPORT_LEN] = "";
strcpy(neighbor_report, "This is a test");
int do_kick = kick_client(client_array[j], neighbor_report);
printf("Chosen AP %s\n", neighbor_report);
// better ap available
if (do_kick > 0) {
// kick after algorithm decided to kick several times
// + rssi is changing a lot
// + chan util is changing a lot
// + ping pong behavior of clients will be reduced
client_array[j].kick_count++;
printf("Comparing kick count! kickcount: %d to min_kick_count: %d!\n", client_array[j].kick_count,
dawn_metric.min_kick_count);
if (client_array[j].kick_count < dawn_metric.min_kick_count) {
j++;
}
else
{
printf("Better AP available. Kicking client:\n");
print_client_entry(client_array[j]);
printf("Check if client is active receiving!\n");
float rx_rate, tx_rate;
if (get_bandwidth_iwinfo(client_array[j].client_addr, &rx_rate, &tx_rate)) {
printf("No active transmission data for client. Don't kick!\n");
j++;
}
else
{
// only use rx_rate for indicating if transmission is going on
// <= 6MBits <- probably no transmission
// tx_rate has always some weird value so don't use ist
if (rx_rate > dawn_metric.bandwidth_threshold) {
printf("Client is probably in active transmisison. Don't kick! RxRate is: %f\n", rx_rate);
j++;
}
else
{
printf("Client is probably NOT in active transmisison. KICK! RxRate is: %f\n", rx_rate);
// here we should send a messsage to set the probe.count for all aps to the min that there is no delay between switching
// the hearing map is full...
send_set_probe(client_array[j].client_addr);
// don't deauth station? <- deauth is better!
// maybe we can use handovers...
//del_client_interface(id, client_array[j].client_addr, NO_MORE_STAS, 1, 1000);
int sync_kick = wnm_disassoc_imminent(id, client_array[j].client_addr, neighbor_report, 12);
// Synchronous kick is a test harness feature to indicate arrays have been updated, so don't change further
if (sync_kick)
{
kicked_clients++;
}
else
{
client_array_delete(client_array[j]);
// don't delete clients in a row. use update function again...
// -> chan_util update, ...
add_client_update_timer(timeout_config.update_client * 1000 / 4);
break;
}
}
}
}
}
// no entry in probe array for own bssid
// TODO: Is test against -1 from (1 && -1) portable?
else if (do_kick == -1) {
printf("No Information about client. Force reconnect:\n");
print_client_entry(client_array[j]);
del_client_interface(id, client_array[j].client_addr, 0, 1, 0);
j++;
}
// ap is best
else {
printf("AP is best. Client will stay:\n");
print_client_entry(client_array[j]);
// set kick counter to 0 again
client_array[j].kick_count = 0;
j++;
}
}
printf("---------------------------\n");
pthread_mutex_unlock(&probe_array_mutex);
pthread_mutex_unlock(&client_array_mutex);
return kicked_clients;
}
void update_iw_info(uint8_t bssid[]) {
pthread_mutex_lock(&client_array_mutex);
pthread_mutex_lock(&probe_array_mutex);
printf("-------- IW INFO UPDATE!!!---------\n");
char mac_buf_ap[20];
sprintf(mac_buf_ap, MACSTR, MAC2STR(bssid));
printf("EVAL %s\n", mac_buf_ap);
// Seach for BSSID
int i;
for (i = 0; i <= client_entry_last; i++) {
if (mac_is_equal(client_array[i].bssid_addr, bssid)) {
break;
}
}
// Go threw clients
int j;
for (j = i; j <= client_entry_last; j++) {
@ -308,75 +471,13 @@ void kick_clients(uint8_t bssid[], uint32_t id) {
pthread_mutex_unlock(&probe_array_mutex);
if (!probe_array_update_rssi(client_array[j].bssid_addr, client_array[j].client_addr, rssi, true)) {
printf("Failed to update rssi!\n");
} else {
}
else {
printf("Updated rssi: %d\n", rssi);
}
pthread_mutex_lock(&probe_array_mutex);
}
char neighbor_report[NEIGHBOR_REPORT_LEN] = "";
int do_kick = kick_client(client_array[j], neighbor_report);
printf("Chosen AP %s\n",neighbor_report);
// better ap available
if (do_kick > 0) {
// kick after algorithm decided to kick several times
// + rssi is changing a lot
// + chan util is changing a lot
// + ping pong behavior of clients will be reduced
client_array[j].kick_count++;
printf("Comparing kick count! kickcount: %d to min_kick_count: %d!\n", client_array[j].kick_count,
dawn_metric.min_kick_count);
if (client_array[j].kick_count < dawn_metric.min_kick_count) {
continue;
}
printf("Better AP available. Kicking client:\n");
print_client_entry(client_array[j]);
printf("Check if client is active receiving!\n");
float rx_rate, tx_rate;
if (get_bandwidth_iwinfo(client_array[j].client_addr, &rx_rate, &tx_rate)) {
// only use rx_rate for indicating if transmission is going on
// <= 6MBits <- probably no transmission
// tx_rate has always some weird value so don't use ist
if (rx_rate > dawn_metric.bandwidth_threshold) {
printf("Client is probably in active transmisison. Don't kick! RxRate is: %f\n", rx_rate);
continue;
}
}
printf("Client is probably NOT in active transmisison. KICK! RxRate is: %f\n", rx_rate);
// here we should send a messsage to set the probe.count for all aps to the min that there is no delay between switching
// the hearing map is full...
send_set_probe(client_array[j].client_addr);
// don't deauth station? <- deauth is better!
// maybe we can use handovers...
//del_client_interface(id, client_array[j].client_addr, NO_MORE_STAS, 1, 1000);
wnm_disassoc_imminent(id, client_array[j].client_addr, neighbor_report, 12);
client_array_delete(client_array[j]);
// don't delete clients in a row. use update function again...
// -> chan_util update, ...
add_client_update_timer(timeout_config.update_client * 1000 / 4);
break;
// no entry in probe array for own bssid
} else if (do_kick == -1) {
printf("No Information about client. Force reconnect:\n");
print_client_entry(client_array[j]);
del_client_interface(id, client_array[j].client_addr, 0, 1, 0);
// ap is best
} else {
printf("AP is best. Client will stay:\n");
print_client_entry(client_array[j]);
// set kick counter to 0 again
client_array[j].kick_count = 0;
}
}
printf("---------------------------\n");
@ -402,7 +503,7 @@ int is_connected_somehwere(uint8_t client_addr[]) {
return found_in_array;
}
int is_connected(uint8_t bssid_addr[], uint8_t client_addr[]) {
static int is_connected(uint8_t bssid_addr[], uint8_t client_addr[]) {
int i;
int found_in_array = 0;
@ -421,7 +522,7 @@ int is_connected(uint8_t bssid_addr[], uint8_t client_addr[]) {
return found_in_array;
}
int client_array_go_next_help(char sort_order[], int i, client entry,
static int client_array_go_next_help(char sort_order[], int i, client entry,
client next_entry) {
switch (sort_order[i]) {
// bssid-mac
@ -437,7 +538,7 @@ int client_array_go_next_help(char sort_order[], int i, client entry,
return 0;
}
int client_array_go_next(char sort_order[], int i, client entry,
static int client_array_go_next(char sort_order[], int i, client entry,
client next_entry) {
int conditions = 1;
for (int j = 0; j < i; j++) {
@ -471,6 +572,26 @@ void client_array_insert(client entry) {
}
}
client client_array_get_client(const uint8_t* client_addr) {
if (client_entry_last == -1) {
client nc = { .client_addr = {0, 0, 0, 0, 0, 0} };
return nc;
}
//pthread_mutex_lock(&client_array_mutex);
int i;
for (i = 0; i <= client_entry_last; i++) {
if (mac_is_equal(client_addr, client_array[i].client_addr)) {
break;
}
}
//pthread_mutex_unlock(&client_array_mutex);
return client_array[i];
}
client client_array_delete(client entry) {
int i;
@ -482,7 +603,7 @@ client client_array_delete(client entry) {
}
for (i = 0; i <= client_entry_last; i++) {
if (mac_is_equal(entry.bssid_addr, client_array[i].bssid_addr) &&
if (mac_is_equal(entry.bssid_addr, client_array[i].bssid_addr) && // TODO: Why check BSSID here? Aren't entries unique by client MAC?
mac_is_equal(entry.client_addr, client_array[i].client_addr)) {
found_in_array = 1;
tmp = client_array[i];
@ -510,7 +631,7 @@ void probe_array_insert(probe_entry entry) {
int i;
for (i = 0; i <= probe_entry_last; i++) {
if (!go_next(sort_string, SORT_NUM, entry, probe_array[i])) {
if (!go_next(sort_string, SORT_LENGTH, entry, probe_array[i])) {
break;
}
}
@ -668,7 +789,6 @@ void print_probe_array() {
probe_entry insert_to_array(probe_entry entry, int inc_counter, int save_80211k, int is_beacon) {
pthread_mutex_lock(&probe_array_mutex);
entry.time = time(0);
entry.counter = 0;
probe_entry tmp = probe_array_delete(entry);
@ -700,7 +820,6 @@ probe_entry insert_to_array(probe_entry entry, int inc_counter, int save_80211k,
ap insert_to_ap_array(ap entry) {
pthread_mutex_lock(&ap_array_mutex);
entry.time = time(0);
ap_array_delete(entry);
ap_array_insert(entry);
pthread_mutex_unlock(&ap_array_mutex);
@ -709,6 +828,7 @@ ap insert_to_ap_array(ap entry) {
}
// TODO: What is collision domain used for?
int ap_get_collision_count(int col_domain) {
int ret_sta_count = 0;
@ -806,33 +926,43 @@ ap ap_array_delete(ap entry) {
}
void remove_old_client_entries(time_t current_time, long long int threshold) {
for (int i = 0; i <= client_entry_last; i++) {
int i = 0;
while (i <= client_entry_last) {
if (client_array[i].time < current_time - threshold) {
client_array_delete(client_array[i]);
}
else {
i++;
}
}
}
void remove_old_probe_entries(time_t current_time, long long int threshold) {
for (int i = 0; i <= probe_entry_last; i++) {
if (probe_array[i].time < current_time - threshold) {
if (!is_connected(probe_array[i].bssid_addr, probe_array[i].client_addr))
probe_array_delete(probe_array[i]);
int i = 0;
while (i <= probe_entry_last) {
if ((probe_array[i].time < current_time - threshold) && !is_connected(probe_array[i].bssid_addr, probe_array[i].client_addr)) {
probe_array_delete(probe_array[i]);
}
else {
i++;
}
}
}
void remove_old_ap_entries(time_t current_time, long long int threshold) {
for (int i = 0; i <= ap_entry_last; i++) {
int i = 0;
while (i <= ap_entry_last) {
if (ap_array[i].time < current_time - threshold) {
ap_array_delete(ap_array[i]);
}
else {
i++;
}
}
}
void insert_client_to_array(client entry) {
pthread_mutex_lock(&client_array_mutex);
entry.time = time(0);
entry.kick_count = 0;
client client_tmp = client_array_delete(entry);
@ -883,6 +1013,8 @@ void insert_macs_from_file() {
//exit(EXIT_SUCCESS);
}
// TODO: This list only ever seems to get longer. WHy do we need it?
int insert_to_maclist(uint8_t mac[]) {
if (mac_in_maclist(mac)) {
return -1;
@ -909,7 +1041,6 @@ int mac_in_maclist(uint8_t mac[]) {
auth_entry insert_to_denied_req_array(auth_entry entry, int inc_counter) {
pthread_mutex_lock(&denied_array_mutex);
entry.time = time(0);
entry.counter = 0;
auth_entry tmp = denied_req_array_delete(entry);
@ -930,7 +1061,7 @@ auth_entry insert_to_denied_req_array(auth_entry entry, int inc_counter) {
return entry;
}
int denied_req_array_go_next_help(char sort_order[], int i, auth_entry entry,
static int denied_req_array_go_next_help(char sort_order[], int i, auth_entry entry,
auth_entry next_entry) {
switch (sort_order[i]) {
// bssid-mac
@ -946,7 +1077,7 @@ int denied_req_array_go_next_help(char sort_order[], int i, auth_entry entry,
return 0;
}
int denied_req_array_go_next(char sort_order[], int i, auth_entry entry,
static int denied_req_array_go_next(char sort_order[], int i, auth_entry entry,
auth_entry next_entry) {
int conditions = 1;
for (int j = 0; j < i; j++) {
@ -1009,7 +1140,7 @@ auth_entry denied_req_array_delete(auth_entry entry) {
return tmp;
}
int go_next_help(char sort_order[], int i, probe_entry entry,
static int go_next_help(char sort_order[], int i, probe_entry entry,
probe_entry next_entry) {
switch (sort_order[i]) {
// bssid-mac
@ -1045,7 +1176,7 @@ int go_next_help(char sort_order[], int i, probe_entry entry,
}
}
int go_next(char sort_order[], int i, probe_entry entry,
static int go_next(char sort_order[], int i, probe_entry entry,
probe_entry next_entry) {
int conditions = 1;
for (int j = 0; j < i; j++) {
@ -1054,25 +1185,9 @@ int go_next(char sort_order[], int i, probe_entry entry,
return conditions && go_next_help(sort_order, i, entry, next_entry);
}
int mac_is_equal(uint8_t addr1[], uint8_t addr2[]) {
return memcmp(addr1, addr2, ETH_ALEN * sizeof(uint8_t)) == 0;
}
int mac_is_greater(uint8_t addr1[], uint8_t addr2[]) {
for (int i = 0; i < ETH_ALEN; i++) {
if (addr1[i] > addr2[i]) {
return 1;
}
if (addr1[i] < addr2[i]) {
return 0;
}
// if equal continue...
}
return 0;
}
void print_probe_entry(probe_entry entry) {
#ifndef DAWN_NO_OUTPUT
char mac_buf_ap[20];
char mac_buf_client[20];
char mac_buf_target[20];
@ -1081,14 +1196,17 @@ void print_probe_entry(probe_entry entry) {
sprintf(mac_buf_client, MACSTR, MAC2STR(entry.client_addr));
sprintf(mac_buf_target, MACSTR, MAC2STR(entry.target_addr));
printf(
"bssid_addr: %s, client_addr: %s, signal: %d, freq: "
"%d, counter: %d, vht: %d, min_rate: %d, max_rate: %d\n",
mac_buf_ap, mac_buf_client, entry.signal, entry.freq, entry.counter, entry.vht_capabilities,
entry.min_supp_datarate, entry.max_supp_datarate);
#endif
}
void print_auth_entry(auth_entry entry) {
#ifndef DAWN_NO_OUTPUT
char mac_buf_ap[20];
char mac_buf_client[20];
char mac_buf_target[20];
@ -1101,9 +1219,11 @@ void print_auth_entry(auth_entry entry) {
"bssid_addr: %s, client_addr: %s, signal: %d, freq: "
"%d\n",
mac_buf_ap, mac_buf_client, entry.signal, entry.freq);
#endif
}
void print_client_entry(client entry) {
#ifndef DAWN_NO_OUTPUT
char mac_buf_ap[20];
char mac_buf_client[20];
@ -1113,6 +1233,7 @@ void print_client_entry(client entry) {
printf("bssid_addr: %s, client_addr: %s, freq: %d, ht_supported: %d, vht_supported: %d, ht: %d, vht: %d, kick: %d\n",
mac_buf_ap, mac_buf_client, entry.freq, entry.ht_supported, entry.vht_supported, entry.ht, entry.vht,
entry.kick_count);
#endif
}
void print_client_array() {
@ -1124,7 +1245,8 @@ void print_client_array() {
printf("------------------\n");
}
void print_ap_entry(ap entry) {
static void print_ap_entry(ap entry) {
#ifndef DAWN_NO_OUTPUT
char mac_buf_ap[20];
sprintf(mac_buf_ap, MACSTR, MAC2STR(entry.bssid_addr));
@ -1133,6 +1255,7 @@ void print_ap_entry(ap entry) {
entry.channel_utilization, entry.collision_domain, entry.bandwidth,
ap_get_collision_count(entry.collision_domain), entry.neighbor_report
);
#endif
}
void print_ap_array() {
@ -1142,3 +1265,38 @@ void print_ap_array() {
}
printf("------------------\n");
}
void destroy_mutex() {
// free resources
fprintf(stdout, "Freeing mutex resources\n");
pthread_mutex_destroy(&probe_array_mutex);
pthread_mutex_destroy(&client_array_mutex);
pthread_mutex_destroy(&ap_array_mutex);
return;
}
int init_mutex() {
if (pthread_mutex_init(&probe_array_mutex, NULL) != 0) {
fprintf(stderr, "Mutex init failed!\n");
return 1;
}
if (pthread_mutex_init(&client_array_mutex, NULL) != 0) {
fprintf(stderr, "Mutex init failed!\n");
return 1;
}
if (pthread_mutex_init(&ap_array_mutex, NULL) != 0) {
fprintf(stderr, "Mutex init failed!\n");
return 1;
}
if (pthread_mutex_init(&denied_array_mutex, NULL) != 0) {
fprintf(stderr, "Mutex init failed!\n");
return 1;
}
return 0;
}

View file

@ -1,96 +0,0 @@
#include <libubox/uloop.h>
#include "datastorage.h"
#include "utils.h"
#include "ubus.h"
#include "uface.h"
void remove_probe_array_cb(struct uloop_timeout *t);
struct uloop_timeout probe_timeout = {
.cb = remove_probe_array_cb
};
void remove_client_array_cb(struct uloop_timeout *t);
struct uloop_timeout client_timeout = {
.cb = remove_client_array_cb
};
void remove_ap_array_cb(struct uloop_timeout *t);
struct uloop_timeout ap_timeout = {
.cb = remove_ap_array_cb
};
void denied_req_array_cb(struct uloop_timeout *t);
struct uloop_timeout denied_req_timeout = {
.cb = denied_req_array_cb
};
void uloop_add_data_cbs() {
uloop_timeout_add(&probe_timeout);
uloop_timeout_add(&client_timeout);
uloop_timeout_add(&ap_timeout);
if (dawn_metric.use_driver_recog) {
uloop_timeout_add(&denied_req_timeout);
}
}
void remove_probe_array_cb(struct uloop_timeout *t) {
pthread_mutex_lock(&probe_array_mutex);
printf("[Thread] : Removing old probe entries!\n");
remove_old_probe_entries(time(0), timeout_config.remove_probe);
printf("[Thread] : Removing old entries finished!\n");
pthread_mutex_unlock(&probe_array_mutex);
uloop_timeout_set(&probe_timeout, timeout_config.remove_probe * 1000);
}
void remove_client_array_cb(struct uloop_timeout *t) {
pthread_mutex_lock(&client_array_mutex);
printf("[Thread] : Removing old client entries!\n");
remove_old_client_entries(time(0), timeout_config.update_client);
pthread_mutex_unlock(&client_array_mutex);
uloop_timeout_set(&client_timeout, timeout_config.update_client * 1000);
}
void remove_ap_array_cb(struct uloop_timeout *t) {
pthread_mutex_lock(&ap_array_mutex);
printf("[ULOOP] : Removing old ap entries!\n");
remove_old_ap_entries(time(0), timeout_config.remove_ap);
pthread_mutex_unlock(&ap_array_mutex);
uloop_timeout_set(&ap_timeout, timeout_config.remove_ap * 1000);
}
void denied_req_array_cb(struct uloop_timeout *t) {
pthread_mutex_lock(&denied_array_mutex);
printf("[ULOOP] : Processing denied authentication!\n");
time_t current_time = time(0);
for (int i = 0; i <= denied_req_last; i++) {
// check counter
//check timer
if (denied_req_array[i].time < current_time - timeout_config.denied_req_threshold) {
// client is not connected for a given time threshold!
if (!is_connected_somehwere(denied_req_array[i].client_addr)) {
printf("Client has probably a bad driver!\n");
// problem that somehow station will land into this list
// maybe delete again?
if (insert_to_maclist(denied_req_array[i].client_addr) == 0) {
send_add_mac(denied_req_array[i].client_addr);
// TODO: File can grow arbitarily large. Resource consumption risk.
// TODO: Consolidate use of file across source: shared resource for name, single point of access?
write_mac_to_file("/tmp/dawn_mac_list", denied_req_array[i].client_addr);
}
}
denied_req_array_delete(denied_req_array[i]);
}
}
pthread_mutex_unlock(&denied_array_mutex);
uloop_timeout_set(&denied_req_timeout, timeout_config.denied_req_threshold * 1000);
}

25
src/test/faketime.script Normal file
View file

@ -0,0 +1,25 @@
faketime set 2000
faketime show
faketime add 100
faketime show
faketime auto
faketime show
faketime show
faketime show
faketime show
faketime show
faketime show
faketime show
faketime show
faketime show
faketime show
faketime show
faketime show
faketime show
faketime show
faketime show
faketime show
faketime show
faketime show
faketime show
faketime show

3
src/test/load_ap.script Normal file
View file

@ -0,0 +1,3 @@
ap_show
ap bssid=00:11:22:33:44:55 freq=1 ht_sup=2 vht_sup=3 util=4 time=5 stations=6 ssid=helloWorld col_d=7 bandwidth=8 neighbors=
ap_show

View file

@ -0,0 +1,3 @@
auth_entry_show
auth_entry bssid=00:11:22:33:44:55 client=ff:ee:dd:cc:bb:aa target=99:99:99:99:99:99 signal=1 freq=2 counter=3
auth_entry_show

View file

@ -0,0 +1,3 @@
client_show
client bssid=00:11:22:33:44:55 client=ff:ee:dd:cc:bb:aa freq=1 ht_sup=2 vht_sup=3 ht=4 vht=5 kick=6
client_show

View file

@ -0,0 +1,5 @@
elapsed
probe_show
probe bssid=00:11:22:33:44:55 client=ff:ee:dd:cc:bb:aa signal=1 freq=2 counter=3 vht_cap=4 min_rate=5 max_rate=6
probe_show
elapsed

View file

@ -0,0 +1,4 @@
macadd aa:bb:cc:dd:ee:ff
macadd 11:22:33:44:55:66
macget aa:bb:cc:dd:ee:ff
macget 99:aa:bb:cc:dd:ee

31
src/test/old_ap.script Normal file
View file

@ -0,0 +1,31 @@
faketime set 100
ap_show
remove_old_ap_entries 50
faketime show
ap bssid=00:11:22:33:44:55 freq=1 ht_sup=2 vht_sup=3 util=4 stations=6 ssid=helloWorld col_d=7 bandwidth=8 neighbors=
faketime add 25
faketime show
ap bssid=01:11:22:33:44:55 freq=1 ht_sup=2 vht_sup=3 util=4 stations=6 ssid=helloWorld col_d=7 bandwidth=8 neighbors=
faketime add 25
faketime show
ap bssid=02:11:22:33:44:55 freq=1 ht_sup=2 vht_sup=3 util=4 stations=6 ssid=helloWorld col_d=7 bandwidth=8 neighbors=
faketime add 25
faketime show
ap bssid=03:11:22:33:44:55 freq=1 ht_sup=2 vht_sup=3 util=4 stations=6 ssid=helloWorld col_d=7 bandwidth=8 neighbors=
faketime add 25
faketime show
ap bssid=04:11:22:33:44:55 freq=1 ht_sup=2 vht_sup=3 util=4 stations=6 ssid=helloWorld col_d=7 bandwidth=8 neighbors=
ap_show
remove_old_ap_entries 50
ap_show
faketime add 25
remove_old_ap_entries 0
ap_show

30
src/test/old_auth.script Normal file
View file

@ -0,0 +1,30 @@
faketime set 100
auth_entry_show
remove_old_auth_entries 50
faketime show
auth_entry bssid=00:11:22:33:44:55 client=ff:ee:dd:cc:bb:aa
faketime add 25
faketime show
auth_entry bssid=01:11:22:33:44:55 client=ff:ee:dd:cc:bb:aa
faketime add 25
faketime show
auth_entry bssid=02:11:22:33:44:55 client=ff:ee:dd:cc:bb:aa
faketime add 25
faketime show
auth_entry bssid=03:11:22:33:44:55 client=ff:ee:dd:cc:bb:aa
faketime add 25
faketime show
auth_entry bssid=04:11:22:33:44:55 client=ff:ee:dd:cc:bb:aa
auth_entry_show
remove_old_auth_entries 50
auth_entry_show
remove_old_auth_entries 0
auth_entry_show

View file

@ -0,0 +1,31 @@
faketime set 100
client_show
remove_old_client_entries 50
faketime show
client bssid=00:11:22:33:44:55 client=ff:ee:dd:cc:bb:aa
faketime add 25
faketime show
client bssid=01:11:22:33:44:55 client=ff:ee:dd:cc:bb:aa
faketime add 25
faketime show
client bssid=02:11:22:33:44:55 client=ff:ee:dd:cc:bb:aa
faketime add 25
faketime show
client bssid=03:11:22:33:44:55 client=ff:ee:dd:cc:bb:aa
faketime add 25
faketime show
client bssid=04:11:22:33:44:55 client=ff:ee:dd:cc:bb:aa
client_show
remove_old_client_entries 50
client_show
faketime add 25
remove_old_client_entries 0
client_show

44
src/test/old_probe.script Normal file
View file

@ -0,0 +1,44 @@
faketime set 100
probe_show
remove_old_probe_entries 50
faketime show
probe bssid=00:11:22:33:44:55 client=ff:ee:dd:cc:bb:aa
faketime add 25
faketime show
probe bssid=01:11:22:33:44:55 client=ff:ee:dd:cc:bb:aa
faketime add 25
faketime show
probe bssid=02:11:22:33:44:55 client=ff:ee:dd:cc:bb:aa
faketime add 25
faketime show
probe bssid=03:11:22:33:44:55 client=ff:ee:dd:cc:bb:aa
faketime add 25
faketime show
probe bssid=04:11:22:33:44:55 client=ff:ee:dd:cc:bb:aa
probe_show
remove_old_probe_entries 50
probe_show
faketime add 25
remove_old_probe_entries 0
probe_show
# Test that a still connected client is not removed
faketime set 500
faketime show
client bssid=00:11:22:33:44:55 client=ff:ee:dd:cc:bb:aa
probe bssid=00:11:22:33:44:55 client=ff:ee:dd:cc:bb:aa
probe bssid=01:11:22:33:44:55 client=ff:ee:dd:cc:bb:aa
probe_show
faketime add 25
remove_old_probe_entries 0
probe_show

View file

@ -1,5 +1,4 @@
# Basic test of array entry handling
probe_sort bcfs
probe_add_auto 10 20
probe_show
probe_del_auto 10 20

View file

@ -0,0 +1,420 @@
elapsed
# DAWN mertics to help testing output review
dawn default
dawn ht_support=8
dawn vht_support=16
dawn max_chan_util=0
dawn ap_weight=4
dawn rssi=32
dawn low_rssi=0
dawn min_kick_count=1
#AP
ap bssid=0A:7B:AA:00:01:00 ht_sup=1 vht_sup=1 util=156 stations=13 ssid=aTestSSID weight=10 neighbors=0A:7B:AA:00:01:00
ap bssid=02:67:AA:00:02:00 ht_sup=1 vht_sup=1 util=195 stations=13 ssid=aTestSSID weight=10 neighbors=02:67:AA:00:02:00
ap bssid=14:02:AA:00:03:00 ht_sup=1 vht_sup=1 util=126 stations=9 ssid=aTestSSID weight=10 neighbors=14:02:AA:00:03:00
ap bssid=1F:36:AA:00:04:00 ht_sup=0 vht_sup=0 util=120 stations=8 ssid=aTestSSID weight=10 neighbors=1F:36:AA:00:04:00
ap bssid=69:E9:AA:00:05:00 ht_sup=0 vht_sup=0 util=44 stations=4 ssid=aTestSSID weight=10 neighbors=69:E9:AA:00:05:00
ap bssid=6A:97:AA:00:06:00 ht_sup=0 vht_sup=0 util=110 stations=11 ssid=aTestSSID weight=10 neighbors=6A:97:AA:00:06:00
ap bssid=45:63:AA:00:07:00 ht_sup=0 vht_sup=0 util=55 stations=5 ssid=aTestSSID weight=10 neighbors=45:63:AA:00:07:00
ap bssid=07:1E:AA:00:08:00 ht_sup=1 vht_sup=1 util=88 stations=8 ssid=aTestSSID weight=10 neighbors=07:1E:AA:00:08:00
ap bssid=45:A2:AA:00:09:00 ht_sup=0 vht_sup=0 util=120 stations=12 ssid=aTestSSID weight=10 neighbors=45:A2:AA:00:09:00
ap bssid=4C:4D:AA:00:0A:00 ht_sup=1 vht_sup=1 util=195 stations=13 ssid=aTestSSID weight=10 neighbors=4C:4D:AA:00:0A:00
#Client
client client=50:7B:DD:00:01:00 bssid=45:A2:AA:00:09:00 freq=2500 ht_cap=1 vht_cap=1
client client=22:87:DD:00:02:00 bssid=4C:4D:AA:00:0A:00 freq=5500 ht_cap=0 vht_cap=0
client client=54:1A:DD:00:03:00 bssid=14:02:AA:00:03:00 freq=5500 ht_cap=1 vht_cap=0
client client=60:79:DD:00:04:00 bssid=0A:7B:AA:00:01:00 freq=5500 ht_cap=1 vht_cap=0
client client=20:EE:DD:00:05:00 bssid=07:1E:AA:00:08:00 freq=2500 ht_cap=0 vht_cap=0
client client=33:D2:DD:00:06:00 bssid=45:63:AA:00:07:00 freq=5500 ht_cap=1 vht_cap=1
client client=44:B6:DD:00:07:00 bssid=69:E9:AA:00:05:00 freq=2500 ht_cap=1 vht_cap=1
client client=3A:D6:DD:00:08:00 bssid=1F:36:AA:00:04:00 freq=2500 ht_cap=0 vht_cap=0
client client=3C:BB:DD:00:09:00 bssid=69:E9:AA:00:05:00 freq=5500 ht_cap=1 vht_cap=0
client client=2D:3F:DD:00:0A:00 bssid=14:02:AA:00:03:00 freq=5500 ht_cap=1 vht_cap=1
client client=00:08:DD:00:0B:00 bssid=45:A2:AA:00:09:00 freq=5500 ht_cap=0 vht_cap=0
client client=64:5A:DD:00:0C:00 bssid=45:A2:AA:00:09:00 freq=2500 ht_cap=0 vht_cap=0
client client=13:ED:DD:00:0D:00 bssid=14:02:AA:00:03:00 freq=2500 ht_cap=1 vht_cap=0
client client=3B:43:DD:00:0E:00 bssid=1F:36:AA:00:04:00 freq=2500 ht_cap=0 vht_cap=0
client client=10:6A:DD:00:0F:00 bssid=14:02:AA:00:03:00 freq=2500 ht_cap=0 vht_cap=0
client client=0D:BE:DD:00:10:00 bssid=6A:97:AA:00:06:00 freq=5500 ht_cap=1 vht_cap=0
client client=3E:B5:DD:00:11:00 bssid=07:1E:AA:00:08:00 freq=2500 ht_cap=0 vht_cap=0
client client=41:C2:DD:00:12:00 bssid=0A:7B:AA:00:01:00 freq=5500 ht_cap=0 vht_cap=0
client client=2A:75:DD:00:13:00 bssid=6A:97:AA:00:06:00 freq=5500 ht_cap=0 vht_cap=0
client client=31:FB:DD:00:14:00 bssid=02:67:AA:00:02:00 freq=2500 ht_cap=1 vht_cap=0
client client=2E:B8:DD:00:15:00 bssid=14:02:AA:00:03:00 freq=5500 ht_cap=0 vht_cap=0
client client=40:50:DD:00:16:00 bssid=69:E9:AA:00:05:00 freq=5500 ht_cap=0 vht_cap=0
client client=0D:7F:DD:00:17:00 bssid=1F:36:AA:00:04:00 freq=5500 ht_cap=1 vht_cap=0
client client=40:C7:DD:00:18:00 bssid=1F:36:AA:00:04:00 freq=5500 ht_cap=1 vht_cap=1
client client=31:F5:DD:00:19:00 bssid=14:02:AA:00:03:00 freq=5500 ht_cap=1 vht_cap=0
client client=56:C7:DD:00:1A:00 bssid=07:1E:AA:00:08:00 freq=2500 ht_cap=0 vht_cap=0
client client=09:77:DD:00:1B:00 bssid=69:E9:AA:00:05:00 freq=5500 ht_cap=0 vht_cap=0
client client=53:C7:DD:00:1C:00 bssid=14:02:AA:00:03:00 freq=5500 ht_cap=0 vht_cap=0
client client=07:CC:DD:00:1D:00 bssid=02:67:AA:00:02:00 freq=2500 ht_cap=1 vht_cap=1
client client=37:13:DD:00:1E:00 bssid=45:63:AA:00:07:00 freq=2500 ht_cap=1 vht_cap=0
client client=1A:ED:DD:00:1F:00 bssid=4C:4D:AA:00:0A:00 freq=2500 ht_cap=0 vht_cap=0
client client=78:22:DD:00:20:00 bssid=0A:7B:AA:00:01:00 freq=5500 ht_cap=0 vht_cap=0
client client=7D:52:DD:00:21:00 bssid=45:A2:AA:00:09:00 freq=2500 ht_cap=0 vht_cap=0
client client=75:45:DD:00:22:00 bssid=07:1E:AA:00:08:00 freq=2500 ht_cap=0 vht_cap=0
#Probe
probe bssid=0A:7B:AA:00:01:00 client=50:7B:DD:00:01:00 signal=-65 freq=2500 ht_cap=1 vht_cap=1
probe bssid=0A:7B:AA:00:01:00 client=22:87:DD:00:02:00 signal=-71 freq=5500 ht_cap=0 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=54:1A:DD:00:03:00 signal=-76 freq=5500 ht_cap=1 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=60:79:DD:00:04:00 signal=-84 freq=5500 ht_cap=1 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=20:EE:DD:00:05:00 signal=-65 freq=2500 ht_cap=0 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=33:D2:DD:00:06:00 signal=-77 freq=5500 ht_cap=1 vht_cap=1
probe bssid=0A:7B:AA:00:01:00 client=44:B6:DD:00:07:00 signal=-79 freq=2500 ht_cap=1 vht_cap=1
probe bssid=0A:7B:AA:00:01:00 client=3A:D6:DD:00:08:00 signal=-82 freq=2500 ht_cap=0 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=3C:BB:DD:00:09:00 signal=-91 freq=5500 ht_cap=1 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=2D:3F:DD:00:0A:00 signal=-82 freq=5500 ht_cap=1 vht_cap=1
probe bssid=0A:7B:AA:00:01:00 client=00:08:DD:00:0B:00 signal=-85 freq=5500 ht_cap=0 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=64:5A:DD:00:0C:00 signal=-80 freq=2500 ht_cap=0 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=13:ED:DD:00:0D:00 signal=-78 freq=2500 ht_cap=1 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=3B:43:DD:00:0E:00 signal=-69 freq=2500 ht_cap=0 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=10:6A:DD:00:0F:00 signal=-83 freq=2500 ht_cap=0 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=0D:BE:DD:00:10:00 signal=-81 freq=5500 ht_cap=1 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=3E:B5:DD:00:11:00 signal=-86 freq=2500 ht_cap=0 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=41:C2:DD:00:12:00 signal=-78 freq=5500 ht_cap=0 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=2A:75:DD:00:13:00 signal=-91 freq=5500 ht_cap=0 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=31:FB:DD:00:14:00 signal=-69 freq=2500 ht_cap=1 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=2E:B8:DD:00:15:00 signal=-78 freq=5500 ht_cap=0 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=40:50:DD:00:16:00 signal=-81 freq=5500 ht_cap=0 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=0D:7F:DD:00:17:00 signal=-86 freq=5500 ht_cap=1 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=40:C7:DD:00:18:00 signal=-91 freq=5500 ht_cap=1 vht_cap=1
probe bssid=0A:7B:AA:00:01:00 client=31:F5:DD:00:19:00 signal=-84 freq=5500 ht_cap=1 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=56:C7:DD:00:1A:00 signal=-84 freq=2500 ht_cap=0 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=09:77:DD:00:1B:00 signal=-87 freq=5500 ht_cap=0 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=53:C7:DD:00:1C:00 signal=-75 freq=5500 ht_cap=0 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=07:CC:DD:00:1D:00 signal=-88 freq=2500 ht_cap=1 vht_cap=1
probe bssid=0A:7B:AA:00:01:00 client=37:13:DD:00:1E:00 signal=-79 freq=2500 ht_cap=1 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=1A:ED:DD:00:1F:00 signal=-81 freq=2500 ht_cap=0 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=78:22:DD:00:20:00 signal=-89 freq=5500 ht_cap=0 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=7D:52:DD:00:21:00 signal=-89 freq=2500 ht_cap=0 vht_cap=0
probe bssid=0A:7B:AA:00:01:00 client=75:45:DD:00:22:00 signal=-79 freq=2500 ht_cap=0 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=50:7B:DD:00:01:00 signal=-82 freq=2500 ht_cap=1 vht_cap=1
probe bssid=02:67:AA:00:02:00 client=22:87:DD:00:02:00 signal=-81 freq=5500 ht_cap=0 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=54:1A:DD:00:03:00 signal=-86 freq=5500 ht_cap=1 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=60:79:DD:00:04:00 signal=-72 freq=5500 ht_cap=1 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=20:EE:DD:00:05:00 signal=-84 freq=2500 ht_cap=0 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=33:D2:DD:00:06:00 signal=-84 freq=5500 ht_cap=1 vht_cap=1
probe bssid=02:67:AA:00:02:00 client=44:B6:DD:00:07:00 signal=-73 freq=2500 ht_cap=1 vht_cap=1
probe bssid=02:67:AA:00:02:00 client=3A:D6:DD:00:08:00 signal=-86 freq=2500 ht_cap=0 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=3C:BB:DD:00:09:00 signal=-88 freq=5500 ht_cap=1 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=2D:3F:DD:00:0A:00 signal=-83 freq=5500 ht_cap=1 vht_cap=1
probe bssid=02:67:AA:00:02:00 client=00:08:DD:00:0B:00 signal=-76 freq=5500 ht_cap=0 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=64:5A:DD:00:0C:00 signal=-87 freq=2500 ht_cap=0 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=13:ED:DD:00:0D:00 signal=-84 freq=2500 ht_cap=1 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=3B:43:DD:00:0E:00 signal=-84 freq=2500 ht_cap=0 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=10:6A:DD:00:0F:00 signal=-91 freq=2500 ht_cap=0 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=0D:BE:DD:00:10:00 signal=-76 freq=5500 ht_cap=1 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=3E:B5:DD:00:11:00 signal=-74 freq=2500 ht_cap=0 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=41:C2:DD:00:12:00 signal=-84 freq=5500 ht_cap=0 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=2A:75:DD:00:13:00 signal=-88 freq=5500 ht_cap=0 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=31:FB:DD:00:14:00 signal=-80 freq=2500 ht_cap=1 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=2E:B8:DD:00:15:00 signal=-84 freq=5500 ht_cap=0 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=40:50:DD:00:16:00 signal=-89 freq=5500 ht_cap=0 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=0D:7F:DD:00:17:00 signal=-71 freq=5500 ht_cap=1 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=40:C7:DD:00:18:00 signal=-86 freq=5500 ht_cap=1 vht_cap=1
probe bssid=02:67:AA:00:02:00 client=31:F5:DD:00:19:00 signal=-62 freq=5500 ht_cap=1 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=56:C7:DD:00:1A:00 signal=-78 freq=2500 ht_cap=0 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=09:77:DD:00:1B:00 signal=-79 freq=5500 ht_cap=0 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=53:C7:DD:00:1C:00 signal=-83 freq=5500 ht_cap=0 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=07:CC:DD:00:1D:00 signal=-89 freq=2500 ht_cap=1 vht_cap=1
probe bssid=02:67:AA:00:02:00 client=37:13:DD:00:1E:00 signal=-78 freq=2500 ht_cap=1 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=1A:ED:DD:00:1F:00 signal=-74 freq=2500 ht_cap=0 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=78:22:DD:00:20:00 signal=-87 freq=5500 ht_cap=0 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=7D:52:DD:00:21:00 signal=-86 freq=2500 ht_cap=0 vht_cap=0
probe bssid=02:67:AA:00:02:00 client=75:45:DD:00:22:00 signal=-71 freq=2500 ht_cap=0 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=50:7B:DD:00:01:00 signal=-65 freq=2500 ht_cap=1 vht_cap=1
probe bssid=14:02:AA:00:03:00 client=22:87:DD:00:02:00 signal=-83 freq=5500 ht_cap=0 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=54:1A:DD:00:03:00 signal=-84 freq=5500 ht_cap=1 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=60:79:DD:00:04:00 signal=-90 freq=5500 ht_cap=1 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=20:EE:DD:00:05:00 signal=-62 freq=2500 ht_cap=0 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=33:D2:DD:00:06:00 signal=-86 freq=5500 ht_cap=1 vht_cap=1
probe bssid=14:02:AA:00:03:00 client=44:B6:DD:00:07:00 signal=-87 freq=2500 ht_cap=1 vht_cap=1
probe bssid=14:02:AA:00:03:00 client=3A:D6:DD:00:08:00 signal=-89 freq=2500 ht_cap=0 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=3C:BB:DD:00:09:00 signal=-95 freq=5500 ht_cap=1 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=2D:3F:DD:00:0A:00 signal=-89 freq=5500 ht_cap=1 vht_cap=1
probe bssid=14:02:AA:00:03:00 client=00:08:DD:00:0B:00 signal=-86 freq=5500 ht_cap=0 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=64:5A:DD:00:0C:00 signal=-87 freq=2500 ht_cap=0 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=13:ED:DD:00:0D:00 signal=-71 freq=2500 ht_cap=1 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=3B:43:DD:00:0E:00 signal=-60 freq=2500 ht_cap=0 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=10:6A:DD:00:0F:00 signal=-87 freq=2500 ht_cap=0 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=0D:BE:DD:00:10:00 signal=-89 freq=5500 ht_cap=1 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=3E:B5:DD:00:11:00 signal=-91 freq=2500 ht_cap=0 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=41:C2:DD:00:12:00 signal=-69 freq=5500 ht_cap=0 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=2A:75:DD:00:13:00 signal=-95 freq=5500 ht_cap=0 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=31:FB:DD:00:14:00 signal=-70 freq=2500 ht_cap=1 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=2E:B8:DD:00:15:00 signal=-86 freq=5500 ht_cap=0 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=40:50:DD:00:16:00 signal=-67 freq=5500 ht_cap=0 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=0D:7F:DD:00:17:00 signal=-89 freq=5500 ht_cap=1 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=40:C7:DD:00:18:00 signal=-95 freq=5500 ht_cap=1 vht_cap=1
probe bssid=14:02:AA:00:03:00 client=31:F5:DD:00:19:00 signal=-88 freq=5500 ht_cap=1 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=56:C7:DD:00:1A:00 signal=-84 freq=2500 ht_cap=0 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=09:77:DD:00:1B:00 signal=-92 freq=5500 ht_cap=0 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=53:C7:DD:00:1C:00 signal=-68 freq=5500 ht_cap=0 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=07:CC:DD:00:1D:00 signal=-92 freq=2500 ht_cap=1 vht_cap=1
probe bssid=14:02:AA:00:03:00 client=37:13:DD:00:1E:00 signal=-78 freq=2500 ht_cap=1 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=1A:ED:DD:00:1F:00 signal=-88 freq=2500 ht_cap=0 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=78:22:DD:00:20:00 signal=-94 freq=5500 ht_cap=0 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=7D:52:DD:00:21:00 signal=-94 freq=2500 ht_cap=0 vht_cap=0
probe bssid=14:02:AA:00:03:00 client=75:45:DD:00:22:00 signal=-87 freq=2500 ht_cap=0 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=50:7B:DD:00:01:00 signal=-80 freq=2500 ht_cap=1 vht_cap=1
probe bssid=1F:36:AA:00:04:00 client=22:87:DD:00:02:00 signal=-87 freq=5500 ht_cap=0 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=54:1A:DD:00:03:00 signal=-90 freq=5500 ht_cap=1 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=60:79:DD:00:04:00 signal=-86 freq=5500 ht_cap=1 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=20:EE:DD:00:05:00 signal=-83 freq=2500 ht_cap=0 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=33:D2:DD:00:06:00 signal=-89 freq=5500 ht_cap=1 vht_cap=1
probe bssid=1F:36:AA:00:04:00 client=44:B6:DD:00:07:00 signal=-86 freq=2500 ht_cap=1 vht_cap=1
probe bssid=1F:36:AA:00:04:00 client=3A:D6:DD:00:08:00 signal=-91 freq=2500 ht_cap=0 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=3C:BB:DD:00:09:00 signal=-95 freq=5500 ht_cap=1 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=2D:3F:DD:00:0A:00 signal=-91 freq=5500 ht_cap=1 vht_cap=1
probe bssid=1F:36:AA:00:04:00 client=00:08:DD:00:0B:00 signal=-67 freq=5500 ht_cap=0 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=64:5A:DD:00:0C:00 signal=-91 freq=2500 ht_cap=0 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=13:ED:DD:00:0D:00 signal=-75 freq=2500 ht_cap=1 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=3B:43:DD:00:0E:00 signal=-81 freq=2500 ht_cap=0 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=10:6A:DD:00:0F:00 signal=-94 freq=2500 ht_cap=0 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=0D:BE:DD:00:10:00 signal=-88 freq=5500 ht_cap=1 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=3E:B5:DD:00:11:00 signal=-87 freq=2500 ht_cap=0 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=41:C2:DD:00:12:00 signal=-76 freq=5500 ht_cap=0 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=2A:75:DD:00:13:00 signal=-94 freq=5500 ht_cap=0 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=31:FB:DD:00:14:00 signal=-77 freq=2500 ht_cap=1 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=2E:B8:DD:00:15:00 signal=-90 freq=5500 ht_cap=0 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=40:50:DD:00:16:00 signal=-84 freq=5500 ht_cap=0 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=0D:7F:DD:00:17:00 signal=-77 freq=5500 ht_cap=1 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=40:C7:DD:00:18:00 signal=-93 freq=5500 ht_cap=1 vht_cap=1
probe bssid=1F:36:AA:00:04:00 client=31:F5:DD:00:19:00 signal=-77 freq=5500 ht_cap=1 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=56:C7:DD:00:1A:00 signal=-50 freq=2500 ht_cap=0 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=09:77:DD:00:1B:00 signal=-89 freq=5500 ht_cap=0 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=53:C7:DD:00:1C:00 signal=-76 freq=5500 ht_cap=0 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=07:CC:DD:00:1D:00 signal=-94 freq=2500 ht_cap=1 vht_cap=1
probe bssid=1F:36:AA:00:04:00 client=37:13:DD:00:1E:00 signal=-64 freq=2500 ht_cap=1 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=1A:ED:DD:00:1F:00 signal=-86 freq=2500 ht_cap=0 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=78:22:DD:00:20:00 signal=-93 freq=5500 ht_cap=0 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=7D:52:DD:00:21:00 signal=-93 freq=2500 ht_cap=0 vht_cap=0
probe bssid=1F:36:AA:00:04:00 client=75:45:DD:00:22:00 signal=-85 freq=2500 ht_cap=0 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=50:7B:DD:00:01:00 signal=-69 freq=2500 ht_cap=1 vht_cap=1
probe bssid=69:E9:AA:00:05:00 client=22:87:DD:00:02:00 signal=-74 freq=5500 ht_cap=0 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=54:1A:DD:00:03:00 signal=-75 freq=5500 ht_cap=1 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=60:79:DD:00:04:00 signal=-87 freq=5500 ht_cap=1 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=20:EE:DD:00:05:00 signal=-64 freq=2500 ht_cap=0 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=33:D2:DD:00:06:00 signal=-78 freq=5500 ht_cap=1 vht_cap=1
probe bssid=69:E9:AA:00:05:00 client=44:B6:DD:00:07:00 signal=-83 freq=2500 ht_cap=1 vht_cap=1
probe bssid=69:E9:AA:00:05:00 client=3A:D6:DD:00:08:00 signal=-83 freq=2500 ht_cap=0 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=3C:BB:DD:00:09:00 signal=-92 freq=5500 ht_cap=1 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=2D:3F:DD:00:0A:00 signal=-84 freq=5500 ht_cap=1 vht_cap=1
probe bssid=69:E9:AA:00:05:00 client=00:08:DD:00:0B:00 signal=-88 freq=5500 ht_cap=0 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=64:5A:DD:00:0C:00 signal=-80 freq=2500 ht_cap=0 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=13:ED:DD:00:0D:00 signal=-79 freq=2500 ht_cap=1 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=3B:43:DD:00:0E:00 signal=-69 freq=2500 ht_cap=0 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=10:6A:DD:00:0F:00 signal=-81 freq=2500 ht_cap=0 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=0D:BE:DD:00:10:00 signal=-84 freq=5500 ht_cap=1 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=3E:B5:DD:00:11:00 signal=-89 freq=2500 ht_cap=0 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=41:C2:DD:00:12:00 signal=-79 freq=5500 ht_cap=0 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=2A:75:DD:00:13:00 signal=-92 freq=5500 ht_cap=0 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=31:FB:DD:00:14:00 signal=-74 freq=2500 ht_cap=1 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=2E:B8:DD:00:15:00 signal=-79 freq=5500 ht_cap=0 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=40:50:DD:00:16:00 signal=-80 freq=5500 ht_cap=0 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=0D:7F:DD:00:17:00 signal=-89 freq=5500 ht_cap=1 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=40:C7:DD:00:18:00 signal=-92 freq=5500 ht_cap=1 vht_cap=1
probe bssid=69:E9:AA:00:05:00 client=31:F5:DD:00:19:00 signal=-87 freq=5500 ht_cap=1 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=56:C7:DD:00:1A:00 signal=-86 freq=2500 ht_cap=0 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=09:77:DD:00:1B:00 signal=-89 freq=5500 ht_cap=0 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=53:C7:DD:00:1C:00 signal=-77 freq=5500 ht_cap=0 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=07:CC:DD:00:1D:00 signal=-88 freq=2500 ht_cap=1 vht_cap=1
probe bssid=69:E9:AA:00:05:00 client=37:13:DD:00:1E:00 signal=-82 freq=2500 ht_cap=1 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=1A:ED:DD:00:1F:00 signal=-85 freq=2500 ht_cap=0 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=78:22:DD:00:20:00 signal=-90 freq=5500 ht_cap=0 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=7D:52:DD:00:21:00 signal=-90 freq=2500 ht_cap=0 vht_cap=0
probe bssid=69:E9:AA:00:05:00 client=75:45:DD:00:22:00 signal=-83 freq=2500 ht_cap=0 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=50:7B:DD:00:01:00 signal=-70 freq=2500 ht_cap=1 vht_cap=1
probe bssid=6A:97:AA:00:06:00 client=22:87:DD:00:02:00 signal=-79 freq=5500 ht_cap=0 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=54:1A:DD:00:03:00 signal=-79 freq=5500 ht_cap=1 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=60:79:DD:00:04:00 signal=-89 freq=5500 ht_cap=1 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=20:EE:DD:00:05:00 signal=-64 freq=2500 ht_cap=0 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=33:D2:DD:00:06:00 signal=-82 freq=5500 ht_cap=1 vht_cap=1
probe bssid=6A:97:AA:00:06:00 client=44:B6:DD:00:07:00 signal=-86 freq=2500 ht_cap=1 vht_cap=1
probe bssid=6A:97:AA:00:06:00 client=3A:D6:DD:00:08:00 signal=-86 freq=2500 ht_cap=0 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=3C:BB:DD:00:09:00 signal=-94 freq=5500 ht_cap=1 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=2D:3F:DD:00:0A:00 signal=-87 freq=5500 ht_cap=1 vht_cap=1
probe bssid=6A:97:AA:00:06:00 client=00:08:DD:00:0B:00 signal=-89 freq=5500 ht_cap=0 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=64:5A:DD:00:0C:00 signal=-83 freq=2500 ht_cap=0 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=13:ED:DD:00:0D:00 signal=-79 freq=2500 ht_cap=1 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=3B:43:DD:00:0E:00 signal=-69 freq=2500 ht_cap=0 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=10:6A:DD:00:0F:00 signal=-82 freq=2500 ht_cap=0 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=0D:BE:DD:00:10:00 signal=-87 freq=5500 ht_cap=1 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=3E:B5:DD:00:11:00 signal=-90 freq=2500 ht_cap=0 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=41:C2:DD:00:12:00 signal=-79 freq=5500 ht_cap=0 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=2A:75:DD:00:13:00 signal=-94 freq=5500 ht_cap=0 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=31:FB:DD:00:14:00 signal=-75 freq=2500 ht_cap=1 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=2E:B8:DD:00:15:00 signal=-82 freq=5500 ht_cap=0 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=40:50:DD:00:16:00 signal=-78 freq=5500 ht_cap=0 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=0D:7F:DD:00:17:00 signal=-90 freq=5500 ht_cap=1 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=40:C7:DD:00:18:00 signal=-94 freq=5500 ht_cap=1 vht_cap=1
probe bssid=6A:97:AA:00:06:00 client=31:F5:DD:00:19:00 signal=-89 freq=5500 ht_cap=1 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=56:C7:DD:00:1A:00 signal=-87 freq=2500 ht_cap=0 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=09:77:DD:00:1B:00 signal=-91 freq=5500 ht_cap=0 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=53:C7:DD:00:1C:00 signal=-77 freq=5500 ht_cap=0 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=07:CC:DD:00:1D:00 signal=-90 freq=2500 ht_cap=1 vht_cap=1
probe bssid=6A:97:AA:00:06:00 client=37:13:DD:00:1E:00 signal=-83 freq=2500 ht_cap=1 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=1A:ED:DD:00:1F:00 signal=-87 freq=2500 ht_cap=0 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=78:22:DD:00:20:00 signal=-92 freq=5500 ht_cap=0 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=7D:52:DD:00:21:00 signal=-92 freq=2500 ht_cap=0 vht_cap=0
probe bssid=6A:97:AA:00:06:00 client=75:45:DD:00:22:00 signal=-86 freq=2500 ht_cap=0 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=50:7B:DD:00:01:00 signal=-69 freq=2500 ht_cap=1 vht_cap=1
probe bssid=45:63:AA:00:07:00 client=22:87:DD:00:02:00 signal=-83 freq=5500 ht_cap=0 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=54:1A:DD:00:03:00 signal=-86 freq=5500 ht_cap=1 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=60:79:DD:00:04:00 signal=-86 freq=5500 ht_cap=1 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=20:EE:DD:00:05:00 signal=-74 freq=2500 ht_cap=0 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=33:D2:DD:00:06:00 signal=-86 freq=5500 ht_cap=1 vht_cap=1
probe bssid=45:63:AA:00:07:00 client=44:B6:DD:00:07:00 signal=-84 freq=2500 ht_cap=1 vht_cap=1
probe bssid=45:63:AA:00:07:00 client=3A:D6:DD:00:08:00 signal=-89 freq=2500 ht_cap=0 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=3C:BB:DD:00:09:00 signal=-94 freq=5500 ht_cap=1 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=2D:3F:DD:00:0A:00 signal=-88 freq=5500 ht_cap=1 vht_cap=1
probe bssid=45:63:AA:00:07:00 client=00:08:DD:00:0B:00 signal=-78 freq=5500 ht_cap=0 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=64:5A:DD:00:0C:00 signal=-88 freq=2500 ht_cap=0 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=13:ED:DD:00:0D:00 signal=-60 freq=2500 ht_cap=1 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=3B:43:DD:00:0E:00 signal=-70 freq=2500 ht_cap=0 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=10:6A:DD:00:0F:00 signal=-90 freq=2500 ht_cap=0 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=0D:BE:DD:00:10:00 signal=-86 freq=5500 ht_cap=1 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=3E:B5:DD:00:11:00 signal=-88 freq=2500 ht_cap=0 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=41:C2:DD:00:12:00 signal=-64 freq=5500 ht_cap=0 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=2A:75:DD:00:13:00 signal=-94 freq=5500 ht_cap=0 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=31:FB:DD:00:14:00 signal=-62 freq=2500 ht_cap=1 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=2E:B8:DD:00:15:00 signal=-87 freq=5500 ht_cap=0 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=40:50:DD:00:16:00 signal=-77 freq=5500 ht_cap=0 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=0D:7F:DD:00:17:00 signal=-82 freq=5500 ht_cap=1 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=40:C7:DD:00:18:00 signal=-93 freq=5500 ht_cap=1 vht_cap=1
probe bssid=45:63:AA:00:07:00 client=31:F5:DD:00:19:00 signal=-81 freq=5500 ht_cap=1 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=56:C7:DD:00:1A:00 signal=-74 freq=2500 ht_cap=0 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=09:77:DD:00:1B:00 signal=-89 freq=5500 ht_cap=0 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=53:C7:DD:00:1C:00 signal=-58 freq=5500 ht_cap=0 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=07:CC:DD:00:1D:00 signal=-93 freq=2500 ht_cap=1 vht_cap=1
probe bssid=45:63:AA:00:07:00 client=37:13:DD:00:1E:00 signal=-60 freq=2500 ht_cap=1 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=1A:ED:DD:00:1F:00 signal=-85 freq=2500 ht_cap=0 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=78:22:DD:00:20:00 signal=-92 freq=5500 ht_cap=0 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=7D:52:DD:00:21:00 signal=-92 freq=2500 ht_cap=0 vht_cap=0
probe bssid=45:63:AA:00:07:00 client=75:45:DD:00:22:00 signal=-83 freq=2500 ht_cap=0 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=50:7B:DD:00:01:00 signal=-76 freq=2500 ht_cap=1 vht_cap=1
probe bssid=07:1E:AA:00:08:00 client=22:87:DD:00:02:00 signal=-83 freq=5500 ht_cap=0 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=54:1A:DD:00:03:00 signal=-87 freq=5500 ht_cap=1 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=60:79:DD:00:04:00 signal=-82 freq=5500 ht_cap=1 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=20:EE:DD:00:05:00 signal=-79 freq=2500 ht_cap=0 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=33:D2:DD:00:06:00 signal=-86 freq=5500 ht_cap=1 vht_cap=1
probe bssid=07:1E:AA:00:08:00 client=44:B6:DD:00:07:00 signal=-80 freq=2500 ht_cap=1 vht_cap=1
probe bssid=07:1E:AA:00:08:00 client=3A:D6:DD:00:08:00 signal=-88 freq=2500 ht_cap=0 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=3C:BB:DD:00:09:00 signal=-92 freq=5500 ht_cap=1 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=2D:3F:DD:00:0A:00 signal=-87 freq=5500 ht_cap=1 vht_cap=1
probe bssid=07:1E:AA:00:08:00 client=00:08:DD:00:0B:00 signal=-71 freq=5500 ht_cap=0 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=64:5A:DD:00:0C:00 signal=-88 freq=2500 ht_cap=0 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=13:ED:DD:00:0D:00 signal=-75 freq=2500 ht_cap=1 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=3B:43:DD:00:0E:00 signal=-78 freq=2500 ht_cap=0 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=10:6A:DD:00:0F:00 signal=-91 freq=2500 ht_cap=0 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=0D:BE:DD:00:10:00 signal=-83 freq=5500 ht_cap=1 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=3E:B5:DD:00:11:00 signal=-84 freq=2500 ht_cap=0 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=41:C2:DD:00:12:00 signal=-76 freq=5500 ht_cap=0 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=2A:75:DD:00:13:00 signal=-92 freq=5500 ht_cap=0 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=31:FB:DD:00:14:00 signal=-72 freq=2500 ht_cap=1 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=2E:B8:DD:00:15:00 signal=-86 freq=5500 ht_cap=0 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=40:50:DD:00:16:00 signal=-83 freq=5500 ht_cap=0 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=0D:7F:DD:00:17:00 signal=-76 freq=5500 ht_cap=1 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=40:C7:DD:00:18:00 signal=-91 freq=5500 ht_cap=1 vht_cap=1
probe bssid=07:1E:AA:00:08:00 client=31:F5:DD:00:19:00 signal=-74 freq=5500 ht_cap=1 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=56:C7:DD:00:1A:00 signal=-69 freq=2500 ht_cap=0 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=09:77:DD:00:1B:00 signal=-86 freq=5500 ht_cap=0 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=53:C7:DD:00:1C:00 signal=-74 freq=5500 ht_cap=0 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=07:CC:DD:00:1D:00 signal=-92 freq=2500 ht_cap=1 vht_cap=1
probe bssid=07:1E:AA:00:08:00 client=37:13:DD:00:1E:00 signal=-60 freq=2500 ht_cap=1 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=1A:ED:DD:00:1F:00 signal=-82 freq=2500 ht_cap=0 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=78:22:DD:00:20:00 signal=-91 freq=5500 ht_cap=0 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=7D:52:DD:00:21:00 signal=-91 freq=2500 ht_cap=0 vht_cap=0
probe bssid=07:1E:AA:00:08:00 client=75:45:DD:00:22:00 signal=-79 freq=2500 ht_cap=0 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=50:7B:DD:00:01:00 signal=-84 freq=2500 ht_cap=1 vht_cap=1
probe bssid=45:A2:AA:00:09:00 client=22:87:DD:00:02:00 signal=-86 freq=5500 ht_cap=0 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=54:1A:DD:00:03:00 signal=-90 freq=5500 ht_cap=1 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=60:79:DD:00:04:00 signal=-80 freq=5500 ht_cap=1 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=20:EE:DD:00:05:00 signal=-86 freq=2500 ht_cap=0 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=33:D2:DD:00:06:00 signal=-88 freq=5500 ht_cap=1 vht_cap=1
probe bssid=45:A2:AA:00:09:00 client=44:B6:DD:00:07:00 signal=-81 freq=2500 ht_cap=1 vht_cap=1
probe bssid=45:A2:AA:00:09:00 client=3A:D6:DD:00:08:00 signal=-90 freq=2500 ht_cap=0 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=3C:BB:DD:00:09:00 signal=-92 freq=5500 ht_cap=1 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=2D:3F:DD:00:0A:00 signal=-88 freq=5500 ht_cap=1 vht_cap=1
probe bssid=45:A2:AA:00:09:00 client=00:08:DD:00:0B:00 signal=-62 freq=5500 ht_cap=0 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=64:5A:DD:00:0C:00 signal=-90 freq=2500 ht_cap=0 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=13:ED:DD:00:0D:00 signal=-83 freq=2500 ht_cap=1 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=3B:43:DD:00:0E:00 signal=-85 freq=2500 ht_cap=0 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=10:6A:DD:00:0F:00 signal=-94 freq=2500 ht_cap=0 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=0D:BE:DD:00:10:00 signal=-84 freq=5500 ht_cap=1 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=3E:B5:DD:00:11:00 signal=-81 freq=2500 ht_cap=0 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=41:C2:DD:00:12:00 signal=-84 freq=5500 ht_cap=0 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=2A:75:DD:00:13:00 signal=-91 freq=5500 ht_cap=0 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=31:FB:DD:00:14:00 signal=-82 freq=2500 ht_cap=1 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=2E:B8:DD:00:15:00 signal=-89 freq=5500 ht_cap=0 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=40:50:DD:00:16:00 signal=-89 freq=5500 ht_cap=0 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=0D:7F:DD:00:17:00 signal=-56 freq=5500 ht_cap=1 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=40:C7:DD:00:18:00 signal=-89 freq=5500 ht_cap=1 vht_cap=1
probe bssid=45:A2:AA:00:09:00 client=31:F5:DD:00:19:00 signal=-58 freq=5500 ht_cap=1 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=56:C7:DD:00:1A:00 signal=-72 freq=2500 ht_cap=0 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=09:77:DD:00:1B:00 signal=-84 freq=5500 ht_cap=0 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=53:C7:DD:00:1C:00 signal=-83 freq=5500 ht_cap=0 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=07:CC:DD:00:1D:00 signal=-93 freq=2500 ht_cap=1 vht_cap=1
probe bssid=45:A2:AA:00:09:00 client=37:13:DD:00:1E:00 signal=-76 freq=2500 ht_cap=1 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=1A:ED:DD:00:1F:00 signal=-81 freq=2500 ht_cap=0 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=78:22:DD:00:20:00 signal=-91 freq=5500 ht_cap=0 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=7D:52:DD:00:21:00 signal=-90 freq=2500 ht_cap=0 vht_cap=0
probe bssid=45:A2:AA:00:09:00 client=75:45:DD:00:22:00 signal=-80 freq=2500 ht_cap=0 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=50:7B:DD:00:01:00 signal=-81 freq=2500 ht_cap=1 vht_cap=1
probe bssid=4C:4D:AA:00:0A:00 client=22:87:DD:00:02:00 signal=-87 freq=5500 ht_cap=0 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=54:1A:DD:00:03:00 signal=-90 freq=5500 ht_cap=1 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=60:79:DD:00:04:00 signal=-86 freq=5500 ht_cap=1 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=20:EE:DD:00:05:00 signal=-84 freq=2500 ht_cap=0 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=33:D2:DD:00:06:00 signal=-90 freq=5500 ht_cap=1 vht_cap=1
probe bssid=4C:4D:AA:00:0A:00 client=44:B6:DD:00:07:00 signal=-85 freq=2500 ht_cap=1 vht_cap=1
probe bssid=4C:4D:AA:00:0A:00 client=3A:D6:DD:00:08:00 signal=-91 freq=2500 ht_cap=0 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=3C:BB:DD:00:09:00 signal=-94 freq=5500 ht_cap=1 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=2D:3F:DD:00:0A:00 signal=-90 freq=5500 ht_cap=1 vht_cap=1
probe bssid=4C:4D:AA:00:0A:00 client=00:08:DD:00:0B:00 signal=-60 freq=5500 ht_cap=0 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=64:5A:DD:00:0C:00 signal=-91 freq=2500 ht_cap=0 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=13:ED:DD:00:0D:00 signal=-78 freq=2500 ht_cap=1 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=3B:43:DD:00:0E:00 signal=-82 freq=2500 ht_cap=0 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=10:6A:DD:00:0F:00 signal=-94 freq=2500 ht_cap=0 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=0D:BE:DD:00:10:00 signal=-87 freq=5500 ht_cap=1 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=3E:B5:DD:00:11:00 signal=-87 freq=2500 ht_cap=0 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=41:C2:DD:00:12:00 signal=-79 freq=5500 ht_cap=0 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=2A:75:DD:00:13:00 signal=-94 freq=5500 ht_cap=0 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=31:FB:DD:00:14:00 signal=-79 freq=2500 ht_cap=1 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=2E:B8:DD:00:15:00 signal=-90 freq=5500 ht_cap=0 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=40:50:DD:00:16:00 signal=-85 freq=5500 ht_cap=0 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=0D:7F:DD:00:17:00 signal=-74 freq=5500 ht_cap=1 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=40:C7:DD:00:18:00 signal=-93 freq=5500 ht_cap=1 vht_cap=1
probe bssid=4C:4D:AA:00:0A:00 client=31:F5:DD:00:19:00 signal=-75 freq=5500 ht_cap=1 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=56:C7:DD:00:1A:00 signal=-39 freq=2500 ht_cap=0 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=09:77:DD:00:1B:00 signal=-89 freq=5500 ht_cap=0 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=53:C7:DD:00:1C:00 signal=-78 freq=5500 ht_cap=0 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=07:CC:DD:00:1D:00 signal=-94 freq=2500 ht_cap=1 vht_cap=1
probe bssid=4C:4D:AA:00:0A:00 client=37:13:DD:00:1E:00 signal=-68 freq=2500 ht_cap=1 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=1A:ED:DD:00:1F:00 signal=-86 freq=2500 ht_cap=0 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=78:22:DD:00:20:00 signal=-93 freq=5500 ht_cap=0 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=7D:52:DD:00:21:00 signal=-93 freq=2500 ht_cap=0 vht_cap=0
probe bssid=4C:4D:AA:00:0A:00 client=75:45:DD:00:22:00 signal=-84 freq=2500 ht_cap=0 vht_cap=0
client_show
kick 0A:7B:AA:00:01:00 0
kick 02:67:AA:00:02:00 0
kick 14:02:AA:00:03:00 0
kick 1F:36:AA:00:04:00 0
kick 69:E9:AA:00:05:00 0
kick 6A:97:AA:00:06:00 0
kick 45:63:AA:00:07:00 0
kick 07:1E:AA:00:08:00 0
kick 45:A2:AA:00:09:00 0
kick 4C:4D:AA:00:0A:00 0
client_show
elapsed

View file

@ -0,0 +1,5 @@
dawn min_kick_count=2
ap bssid=11:22:33:44:55:66
client bssid=11:22:33:44:55:66 client=ff:ee:dd:cc:bb:aa
kick 11:22:33:44:55:66 0
kick 11:22:33:44:55:66 0

9
src/test/test_header.c Normal file
View file

@ -0,0 +1,9 @@
// Simple compilation unit to see if a header file can "compile itself"
// Place single header file below to check that it includes anything needed
// to resolve any type references, etc.
#include "datastorage.h"
int main(int argc, char* argv[])
{
return 0;
}

View file

@ -1,27 +1,23 @@
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <ctype.h>
#include "dawn_iwinfo.h"
#include "utils.h"
#include "ieee80211_utils.h"
#include "datastorage.h"
#include "uface.h"
/*** SUT functions we use that are not in header files (like "friend" functions) ***/
void ap_array_insert(ap entry);
ap ap_array_delete(ap entry);
#include "msghandler.h"
#include "ubus.h"
#include "test_storage.h"
/*** Testing structures, etc ***/
// pac_a_mac allows a 6-byte (48-bit) MAC address to be efficiently handled as a 64-bit integer
#define MAC_MASK_PACKED_U64 0xFFFFFFFFFFFF0000
union __attribute__((__packed__)) pac_a_mac
{
struct {
uint8_t pos[6];
uint8_t packing[2];
} u8;
uint64_t u64;
uint8_t u8[6];
uint8_t packing[2]; // Not strictly needed as compiler will allocated space for largest member of union
} unpacked;
uint64_t packed_u64;
};
/*** Test Stub Functions - Called by SUT ***/
@ -36,9 +32,26 @@ int send_set_probe(uint8_t client_addr[])
return 0;
}
void wnm_disassoc_imminent(uint32_t id, const uint8_t* client_addr, char* dest_ap, uint32_t duration)
int wnm_disassoc_imminent(uint32_t id, const uint8_t* client_addr, char* dest_ap, uint32_t duration)
{
int ret = 0;
printf("wnm_disassoc_imminent() was called...\n");
if (dest_ap != NULL)
{
// Fake a client being disassociated and then rejoining on the recommended neoghbor
client mc = client_array_get_client(client_addr);
mc = client_array_delete(mc);
hwaddr_aton(dest_ap, mc.bssid_addr);
client_array_insert(mc);
printf("BSS TRANSITION TO %s\n", dest_ap);
// Tell caller not to change the arrays any further
ret = 1;
}
return ret;
}
void add_client_update_timer(time_t time)
@ -71,11 +84,16 @@ int get_expected_throughput_iwinfo(uint8_t* client_addr)
int get_bandwidth_iwinfo(uint8_t* client_addr, float* rx_rate, float* tx_rate)
{
printf("get_bandwidth_iwinfo() was called...\n");
*rx_rate = 0.0;
*tx_rate = 0.0;
printf("get_bandwidth_iwinfo() was called. Returning rx=%1f, tx=%1f...\n", (double)*rx_rate, (double)*tx_rate);
return 0;
}
/*** Local Function Prototypes ***/
/*** Local Function Prototypes and Related Constants ***/
static int array_auto_helper(int action, int i0, int i1);
#define HELPER_ACTION_ADD 0x0000
#define HELPER_ACTION_DEL 0x1000
#define HELPER_ACTION_MASK 0x1000
@ -85,65 +103,70 @@ int get_bandwidth_iwinfo(uint8_t* client_addr, float* rx_rate, float* tx_rate)
#define HELPER_AUTH_ENTRY 0x0004
#define HELPER_PROBE_ARRAY 0x0008
int array_auto_helper(int action, int i0, int i1);
int client_array_auto_helper(int action, int i0, int i1);
int auth_entry_array_auto_helper(int action, int i0, int i1);
int probe_array_auto_helper(int action, int i0, int i1);
/*** Local globals ***/
static double base_time;
static double last_time;
static bool first_time = true;
/*** Test narness code */
int array_auto_helper(int action, int i0, int i1)
static time_t faketime = 1000;
static bool faketime_auto = true; // true = increment every command; false = scripted updates
/*** Test harness code */
static int array_auto_helper(int action, int i0, int i1)
{
int m = i0;
int step = (i0 > i1) ? -1 : 1;
int ret = 0;
srand(time(0)); // For faketime incrementing
int cont = 1;
while (cont) {
union pac_a_mac this_mac;
this_mac.u64 = m;
this_mac.packed_u64 = m;
switch (action & ~HELPER_ACTION_MASK)
{
case HELPER_AP:
; // Empty statement to allow label before declaration
ap ap0;
memcpy(ap0.bssid_addr, &this_mac.u8.pos[0], sizeof(ap0.bssid_addr));
memcpy(ap0.bssid_addr, &this_mac.unpacked.u8[0], sizeof(ap0.bssid_addr));
if ((action & HELPER_ACTION_MASK) == HELPER_ACTION_ADD)
ap_array_insert(ap0);
insert_to_ap_array(ap0);
else
ap_array_delete(ap0);
break;
case HELPER_CLIENT:
; // Empty statement to allow label before declaration
client client0;
memcpy(client0.bssid_addr, &this_mac.u8.pos[0], sizeof(client0.bssid_addr));
memcpy(client0.client_addr, &this_mac.u8.pos[0], sizeof(client0.client_addr));
memcpy(client0.bssid_addr, &this_mac.unpacked.u8[0], sizeof(client0.bssid_addr));
memcpy(client0.client_addr, &this_mac.unpacked.u8[0], sizeof(client0.client_addr));
if ((action & HELPER_ACTION_MASK) == HELPER_ACTION_ADD)
client_array_insert(client0);
insert_client_to_array(client0);
else
client_array_delete(client0);
break;
case HELPER_PROBE_ARRAY:
; // Empty statement to allow label before declaration
probe_entry probe0;
memcpy(probe0.bssid_addr, &this_mac.u8.pos[0], sizeof(probe0.bssid_addr));
memcpy(probe0.client_addr, &this_mac.u8.pos[0], sizeof(probe0.client_addr));
memcpy(probe0.bssid_addr, &this_mac.unpacked.u8[0], sizeof(probe0.bssid_addr));
memcpy(probe0.client_addr, &this_mac.unpacked.u8[0], sizeof(probe0.client_addr));
if ((action & HELPER_ACTION_MASK) == HELPER_ACTION_ADD)
probe_array_insert(probe0);
insert_to_array(probe0, true, true, true); // TODO: Check bool flags
else
probe_array_delete(probe0);
break;
case HELPER_AUTH_ENTRY:
; // Empty statement to allow label before declaration
auth_entry auth_entry0;
memcpy(auth_entry0.bssid_addr, &this_mac.u8.pos[0], sizeof(auth_entry0.bssid_addr));
memcpy(auth_entry0.client_addr, &this_mac.u8.pos[0], sizeof(auth_entry0.client_addr));
memcpy(auth_entry0.bssid_addr, &this_mac.unpacked.u8[0], sizeof(auth_entry0.bssid_addr));
memcpy(auth_entry0.client_addr, &this_mac.unpacked.u8[0], sizeof(auth_entry0.client_addr));
if ((action & HELPER_ACTION_MASK) == HELPER_ACTION_ADD)
denied_req_array_insert(auth_entry0);
insert_to_denied_req_array(auth_entry0, true); // TODO: Check bool flags
else
denied_req_array_delete(auth_entry0);
break;
@ -161,9 +184,67 @@ int array_auto_helper(int action, int i0, int i1)
return ret;
}
int consume_actions(int argc, char* argv[]);
static int load_u8(uint8_t* v, char* s);
static int load_u8(uint8_t* v, char* s)
{
int ret = 0;
sscanf(s, "%" SCNu8, v);
return ret;
}
int consume_actions(int argc, char* argv[])
static int load_u32(uint32_t* v, char* s);
static int load_u32(uint32_t* v, char* s)
{
int ret = 0;
sscanf(s, "%" SCNu32, v);
return ret;
}
static int load_int(int* v, char* s);
static int load_int(int* v, char* s)
{
int ret = 0;
sscanf(s, "%" "d", v);
return ret;
}
static int load_string(size_t l, char* v, char* s);
static int load_string(size_t l, char* v, char* s)
{
int ret = 0;
strncpy(v, s, l);
return ret;
}
static int load_ssid(uint8_t* v, char* s);
static int load_ssid(uint8_t* v, char* s)
{
int ret = 0;
strncpy((char*)v, s, SSID_MAX_LEN);
return ret;
}
static int load_time(time_t* v, char* s);
static int load_time(time_t* v, char* s)
{
int ret = 0;
sscanf(s, "%" "li", v); // TODO: Check making portable for target SoC environemnts?
return ret;
}
static int load_mac(uint8_t* v, char* s);
static int load_mac(uint8_t* v, char* s)
{
int ret = 0;
//printf("Loading mac from: %s\n", s);
sscanf(s, "%" SCNx8 ":%" SCNx8 ":%" SCNx8 ":%" SCNx8 ":%" SCNx8 ":%" SCNx8, &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
return ret;
}
static int consume_actions(int argc, char* argv[]);
static int consume_actions(int argc, char* argv[])
{
int ret = 0;
int args_required = 0; // Suppress compiler warming by assigning initial value
@ -172,14 +253,76 @@ int consume_actions(int argc, char* argv[])
while (curr_arg < argc && ret == 0)
{
if (strcmp(*argv, "probe_sort") == 0)
if ((strcmp(*argv, "time") == 0) || (strcmp(*argv, "elapsed") == 0)) // "time" is deprecated to avoid confusion with "faketime" commands
{
struct timespec spec;
double curr_time;
args_required = 1;
//TODO: Check portability for SoC devices when benchmarking?
clock_gettime(CLOCK_REALTIME, &spec);
curr_time = spec.tv_sec * 1000.0 + spec.tv_nsec / 1000000.0;
// First call sets base time for script
// Later calls report elapsed time since base, and from previous call
if (first_time)
{
first_time = false;
base_time = curr_time;
last_time = curr_time;
}
printf("Elapsed time: base=%fms, last=%fms\n", curr_time - base_time, curr_time - last_time);
last_time = curr_time;
}
else if (strcmp(*argv, "probe_sort") == 0)
{
args_required = 2;
if (curr_arg + args_required <= argc)
{
// sort_string is a datastorage.c global used for sorting probe entries
strcpy(sort_string, argv[1]);
}
}
else if (strcmp(*argv, "faketime") == 0)
{
args_required = 2;
if (curr_arg + args_required <= argc)
{
if (strcmp(*(argv + 1), "auto") == 0)
{
faketime_auto = true;
}
else if (strcmp(*(argv + 1), "show") == 0)
{
printf("FAKETIME is currently: %ld\n", faketime);
}
else
{
args_required = 3;
if (curr_arg + args_required <= argc)
{
if (strcmp(*(argv + 1), "set") == 0)
{
faketime_auto = false;
faketime = atol(argv[2]);
}
else if (strcmp(*(argv + 1), "add") == 0)
{
faketime_auto = false;
faketime += atol(argv[2]);
}
else
{
printf("FAKETIME \"%s\": Unknown or mangled - stopping!\n", *(argv + 1));
ret = -1;
}
}
}
}
}
else if (strcmp(*argv, "ap_show") == 0)
{
args_required = 1;
@ -272,6 +415,436 @@ int consume_actions(int argc, char* argv[])
ret = array_auto_helper(HELPER_AUTH_ENTRY | HELPER_ACTION_DEL, atoi(*(argv + 1)), atoi(*(argv + 2)));
}
}
else if (strcmp(*argv, "remove_old_ap_entries") == 0)
{
args_required = 2;
if (curr_arg + args_required <= argc)
{
remove_old_ap_entries(faketime, atol(argv[1]));
}
}
else if (strcmp(*argv, "remove_old_client_entries") == 0)
{
args_required = 2;
if (curr_arg + args_required <= argc)
{
remove_old_client_entries(faketime, atol(argv[1]));
}
}
else if (strcmp(*argv, "remove_old_probe_entries") == 0)
{
args_required = 2;
if (curr_arg + args_required <= argc)
{
remove_old_probe_entries(faketime, atol(argv[1]));
}
}
else if (strcmp(*argv, "dawn") == 0) // Load metrics that configure DAWN
{
args_required = 1;
while (ret == 0 && curr_arg + args_required < argc)
{
char* fn = *(argv + args_required);
if (!strcmp(fn, "default"))
{
dawn_metric.ap_weight = 0; // Sum component
dawn_metric.ht_support = 10; // Sum component
dawn_metric.vht_support = 100; // Sum component
dawn_metric.no_ht_support = 0; // Sum component
dawn_metric.no_vht_support = 0; // Sum component
dawn_metric.rssi = 10; // Sum component
dawn_metric.low_rssi = -500; // Sum component
dawn_metric.freq = 100; // Sum component
dawn_metric.chan_util = 0; // Sum component
dawn_metric.max_chan_util = -500; // Sum component
dawn_metric.rssi_val = -60;
dawn_metric.low_rssi_val = -80;
dawn_metric.chan_util_val = 140;
dawn_metric.max_chan_util_val = 170;
dawn_metric.min_probe_count = 2;
dawn_metric.bandwidth_threshold = 6;
dawn_metric.use_station_count = 1;
dawn_metric.max_station_diff = 1;
dawn_metric.eval_probe_req = 1;
dawn_metric.eval_auth_req = 1;
dawn_metric.eval_assoc_req = 1;
dawn_metric.deny_auth_reason = 1;
dawn_metric.deny_assoc_reason = 17;
dawn_metric.use_driver_recog = 1;
dawn_metric.min_kick_count = 3;
dawn_metric.chan_util_avg_period = 3;
dawn_metric.set_hostapd_nr = 1;
dawn_metric.kicking = 0;
dawn_metric.op_class = 0;
dawn_metric.duration = 0;
dawn_metric.mode = 0;
dawn_metric.scan_channel = 0;
}
else if (!strncmp(fn, "ap_weight=", 10)) load_int(&dawn_metric.ap_weight, fn + 10);
else if (!strncmp(fn, "ht_support=", 11)) load_int(&dawn_metric.ht_support, fn + 11);
else if (!strncmp(fn, "vht_support=", 12)) load_int(&dawn_metric.vht_support, fn + 12);
else if (!strncmp(fn, "no_ht_support=", 14)) load_int(&dawn_metric.no_ht_support, fn + 14);
else if (!strncmp(fn, "no_vht_support=", 15)) load_int(&dawn_metric.no_vht_support, fn + 15);
else if (!strncmp(fn, "rssi=", 5)) load_int(&dawn_metric.rssi, fn + 5);
else if (!strncmp(fn, "low_rssi=", 9)) load_int(&dawn_metric.low_rssi, fn + 9);
else if (!strncmp(fn, "freq=", 5)) load_int(&dawn_metric.freq, fn + 5);
else if (!strncmp(fn, "chan_util=", 10)) load_int(&dawn_metric.chan_util, fn + 10);
else if (!strncmp(fn, "max_chan_util=", 14)) load_int(&dawn_metric.max_chan_util, fn + 14);
else if (!strncmp(fn, "rssi_val=", 9)) load_int(&dawn_metric.rssi_val, fn + 9);
else if (!strncmp(fn, "low_rssi_val=", 13)) load_int(&dawn_metric.low_rssi_val, fn + 13);
else if (!strncmp(fn, "chan_util_val=", 14)) load_int(&dawn_metric.chan_util_val, fn + 14);
else if (!strncmp(fn, "max_chan_util_val=", 18)) load_int(&dawn_metric.max_chan_util_val, fn + 18);
else if (!strncmp(fn, "min_probe_count=", 16)) load_int(&dawn_metric.min_probe_count, fn + 16);
else if (!strncmp(fn, "bandwidth_threshold=", 20)) load_int(&dawn_metric.bandwidth_threshold, fn + 20);
else if (!strncmp(fn, "use_station_count=", 18)) load_int(&dawn_metric.use_station_count, fn + 18);
else if (!strncmp(fn, "max_station_diff=", 17)) load_int(&dawn_metric.max_station_diff, fn + 17);
else if (!strncmp(fn, "eval_probe_req=", 15)) load_int(&dawn_metric.eval_probe_req, fn + 15);
else if (!strncmp(fn, "eval_auth_req=", 14)) load_int(&dawn_metric.eval_auth_req, fn + 14);
else if (!strncmp(fn, "eval_assoc_req=", 15)) load_int(&dawn_metric.eval_assoc_req, fn + 15);
else if (!strncmp(fn, "deny_auth_reason=", 17)) load_int(&dawn_metric.deny_auth_reason, fn + 17);
else if (!strncmp(fn, "deny_assoc_reason=", 18)) load_int(&dawn_metric.deny_assoc_reason, fn + 18);
else if (!strncmp(fn, "use_driver_recog=", 17)) load_int(&dawn_metric.use_driver_recog, fn + 17);
else if (!strncmp(fn, "min_kick_count=", 15)) load_int(&dawn_metric.min_kick_count, fn + 15);
else if (!strncmp(fn, "chan_util_avg_period=", 21)) load_int(&dawn_metric.chan_util_avg_period, fn + 21);
else if (!strncmp(fn, "set_hostapd_nr=", 15)) load_int(&dawn_metric.set_hostapd_nr, fn + 15);
else if (!strncmp(fn, "kicking=", 8)) load_int(&dawn_metric.kicking, fn + 8);
else if (!strncmp(fn, "op_class=", 9)) load_int(&dawn_metric.op_class, fn + 9);
else if (!strncmp(fn, "duration=", 9)) load_int(&dawn_metric.duration, fn + 9);
else if (!strncmp(fn, "mode=", 5)) load_int(&dawn_metric.mode, fn + 5);
else if (!strncmp(fn, "scan_channel=", 13)) load_int(&dawn_metric.scan_channel, fn + 13);
else {
printf("ERROR: Loading DAWN control metrics, but don't recognise assignment \"%s\"\n", fn);
ret = 1;
}
if (ret == 0)
args_required++;
}
}
else if (strcmp(*argv, "macadd") == 0)
{
args_required = 2;
if (curr_arg + args_required <= argc)
{
uint8_t mac0[ETH_ALEN];
load_mac(mac0, argv[1]);
insert_to_maclist(mac0);
}
}
else if (strcmp(*argv, "macget") == 0)
{
args_required = 2;
if (curr_arg + args_required <= argc)
{
uint8_t mac0[ETH_ALEN];
load_mac(mac0, argv[1]);
printf("Looking for MAC %s - result %d\n", argv[1], mac_in_maclist(mac0));
}
}
else if (strcmp(*argv, "ap") == 0)
{
ap ap0;
memset(ap0.bssid_addr, 0, ETH_ALEN);
ap0.freq = 0;
ap0.ht_support = 0;
ap0.vht_support = 0;
ap0.channel_utilization = 0;
ap0.time = faketime;
ap0.station_count = 0;
memset(ap0.ssid, '*', SSID_MAX_LEN);
ap0.ssid[SSID_MAX_LEN - 1] = '\0';
ap0.neighbor_report[0] = 0;
ap0.collision_domain = 0;
ap0.bandwidth = 0;
ap0.ap_weight = 0;
args_required = 1;
while (ret == 0 && curr_arg + args_required < argc)
{
char* fn = *(argv + args_required);
//TODO: Somehwat hacky parsing of value strings to get us going...
if (false); // Hack to allow easy paste of generated code
else if (!strncmp(fn, "bssid=", 6)) load_mac(ap0.bssid_addr, fn + 6);
else if (!strncmp(fn, "freq=", 5)) load_u32(&ap0.freq, fn + 5);
else if (!strncmp(fn, "ht_sup=", 7)) load_u8(&ap0.ht_support, fn + 7);
else if (!strncmp(fn, "vht_sup=", 8)) load_u8(&ap0.vht_support, fn + 8);
else if (!strncmp(fn, "util=", 5)) load_u32(&ap0.channel_utilization, fn + 5);
else if (!strncmp(fn, "time=", 5)) load_time(&ap0.time, fn + 5);
else if (!strncmp(fn, "stations=", 9)) load_u32(&ap0.station_count, fn + 9);
else if (!strncmp(fn, "ssid=", 5)) load_ssid(ap0.ssid, fn + 5);
else if (!strncmp(fn, "neighbors=", 10)) load_string(NEIGHBOR_REPORT_LEN, ap0.neighbor_report, fn + 10);
else if (!strncmp(fn, "col_d=", 6)) load_u32(&ap0.collision_domain, fn + 6);
else if (!strncmp(fn, "bandwidth=", 10)) load_u32(&ap0.bandwidth, fn + 10);
else if (!strncmp(fn, "weight=", 7)) load_u32(&ap0.ap_weight, fn + 7);
else {
printf("ERROR: Loading AP, but don't recognise assignment \"%s\"\n", fn);
ret = 1;
}
if (ret == 0)
{
args_required++;
}
}
if (ret == 0)
{
insert_to_ap_array(ap0);
}
}
else if (strcmp(*argv, "client") == 0)
{
client cl0;
memset(cl0.bssid_addr, 0, ETH_ALEN);
memset(cl0.client_addr, 0, ETH_ALEN);
memset(cl0.signature, 0, SIGNATURE_LEN);
cl0.ht_supported = 0;
cl0.vht_supported = 0;
cl0.freq = 0;
cl0.auth = 0;
cl0.assoc = 0;
cl0.authorized = 0;
cl0.preauth = 0;
cl0.wds = 0;
cl0.wmm = 0;
cl0.ht = 0;
cl0.vht = 0;
cl0.wps = 0;
cl0.mfp = 0;
cl0.time = faketime;
cl0.aid = 0;
cl0.kick_count = 0;
args_required = 1;
while (ret == 0 && curr_arg + args_required < argc)
{
char* fn = *(argv + args_required);
//TODO: Somewhat hacky parsing of value strings to get us going...
if (false); // Hack to allow easy paste of generated code
else if (!strncmp(fn, "bssid=", 6)) load_mac(cl0.bssid_addr, fn + 6);
else if (!strncmp(fn, "client=", 7)) load_mac(cl0.client_addr, fn + 7);
else if (!strncmp(fn, "sig=", 4)) load_string(SIGNATURE_LEN, cl0.signature, fn + 4);
else if (!strncmp(fn, "ht_sup=", 7)) load_u8(&cl0.ht_supported, fn + 7);
else if (!strncmp(fn, "vht_sup=", 8)) load_u8(&cl0.vht_supported, fn + 8);
else if (!strncmp(fn, "freq=", 5)) load_u32(&cl0.freq, fn + 5);
else if (!strncmp(fn, "auth=", 5)) load_u8(&cl0.auth, fn + 5);
else if (!strncmp(fn, "assoc=", 6)) load_u8(&cl0.assoc, fn + 6);
else if (!strncmp(fn, "authz=", 6)) load_u8(&cl0.authorized, fn + 6);
else if (!strncmp(fn, "preauth=", 8)) load_u8(&cl0.preauth, fn + 8);
else if (!strncmp(fn, "wds=", 4)) load_u8(&cl0.wds, fn + 4);
else if (!strncmp(fn, "wmm=", 4)) load_u8(&cl0.wmm, fn + 4);
else if (!strncmp(fn, "ht_cap=", 3)) load_u8(&cl0.ht, fn + 3);
else if (!strncmp(fn, "vht_cap=", 4)) load_u8(&cl0.vht, fn + 4);
else if (!strncmp(fn, "wps=", 4)) load_u8(&cl0.wps, fn + 4);
else if (!strncmp(fn, "mfp=", 4)) load_u8(&cl0.mfp, fn + 4);
else if (!strncmp(fn, "time=", 5)) load_time(&cl0.time, fn + 5);
else if (!strncmp(fn, "aid=", 4)) load_u32(&cl0.aid, fn + 4);
else if (!strncmp(fn, "kick=", 5)) load_u32(&cl0.kick_count, fn + 5);
else {
printf("ERROR: Loading CLIENT, but don't recognise assignment \"%s\"\n", fn);
ret = 1;
}
if (ret == 0)
args_required++;
}
if (ret == 0)
{
insert_client_to_array(cl0);
}
}
else if (strcmp(*argv, "probe") == 0)
{
probe_entry pr0;
memset(pr0.bssid_addr, 0, ETH_ALEN);
memset(pr0.client_addr, 0, ETH_ALEN);
memset(pr0.target_addr, 0, ETH_ALEN);
pr0.signal = 0;
pr0.freq = 0;
pr0.ht_capabilities = 0;
pr0.vht_capabilities = 0;
pr0.time = faketime;
pr0.counter = 0;
#ifndef DAWN_NO_OUTPUT
pr0.deny_counter = 0;
pr0.max_supp_datarate = 0;
pr0.min_supp_datarate = 0;
#endif
pr0.rcpi = 0;
pr0.rsni = 0;
args_required = 1;
while (ret == 0 && curr_arg + args_required < argc)
{
char* fn = *(argv + args_required);
//TODO: Somewhat hacky parsing of value strings to get us going...
if (false); // Hack to allow easy paste of generated code
else if (!strncmp(fn, "bssid=", 6)) load_mac(pr0.bssid_addr, fn + 6);
else if (!strncmp(fn, "client=", 7)) load_mac(pr0.client_addr, fn + 7);
else if (!strncmp(fn, "target=", 7)) load_mac(pr0.target_addr, fn + 7);
else if (!strncmp(fn, "signal=", 7)) load_u32(&pr0.signal, fn + 7);
else if (!strncmp(fn, "freq=", 5)) load_u32(&pr0.freq, fn + 5);
else if (!strncmp(fn, "ht_cap=", 7)) load_u8(&pr0.ht_capabilities, fn + 7);
else if (!strncmp(fn, "vht_cap=", 8)) load_u8(&pr0.vht_capabilities, fn + 8);
else if (!strncmp(fn, "time=", 5)) load_time(&pr0.time, fn + 5);
else if (!strncmp(fn, "counter=", 8)) load_int(&pr0.counter, fn + 8);
#ifndef DAWN_NO_OUTPUT
else if (!strncmp(fn, "deny=", 5)) load_int(&pr0.deny_counter, fn + 5);
else if (!strncmp(fn, "max_rate=", 9)) load_u8(&pr0.max_supp_datarate, fn + 9);
else if (!strncmp(fn, "min_rate=", 9)) load_u8(&pr0.min_supp_datarate, fn + 9);
#endif
else if (!strncmp(fn, "rcpi=", 5)) load_u32(&pr0.rcpi, fn + 5);
else if (!strncmp(fn, "rsni=", 5)) load_u32(&pr0.rsni, fn + 5);
else {
printf("ERROR: Loading PROBE, but don't recognise assignment \"%s\"\n", fn);
ret = 1;
}
if (ret == 0)
args_required++;
}
if (ret == 0)
{
insert_to_array(pr0, true, true, true);
}
}
else if (strcmp(*argv, "auth_entry") == 0)
{
auth_entry au0;
memset(au0.bssid_addr, 0, ETH_ALEN);
memset(au0.client_addr, 0, ETH_ALEN);
memset(au0.target_addr, 0, ETH_ALEN);
au0.signal = 0;
au0.freq = 0;
au0.time = faketime;
au0.counter = 0;
args_required = 1;
while (ret == 0 && curr_arg + args_required < argc)
{
char* fn = *(argv + args_required);
//TODO: Somewhat hacky parsing of value strings to get us going...
if (false); // Hack to allow easy paste of generated code
else if (!strncmp(fn, "bssid=", 6)) load_mac(au0.bssid_addr, fn + 6);
else if (!strncmp(fn, "client=", 7)) load_mac(au0.client_addr, fn + 7);
else if (!strncmp(fn, "target=", 7)) load_mac(au0.target_addr, fn + 7);
else if (!strncmp(fn, "signal=", 7)) load_u32(&au0.signal, fn + 7);
else if (!strncmp(fn, "freq=", 5)) load_u32(&au0.freq, fn + 5);
else if (!strncmp(fn, "time=", 5)) load_time(&au0.time, fn + 5);
else if (!strncmp(fn, "counter=", 8)) load_int(&au0.counter, fn + 8);
else {
printf("ERROR: Loading AUTH, but don't recognise assignment \"%s\"\n", fn);
ret = 1;
}
if (ret == 0)
args_required++;
}
if (ret == 0)
{
insert_to_denied_req_array(au0, true);
}
}
else if (strcmp(*argv, "kick") == 0) // Perform kicking evaluation
{
args_required = 3;
if (curr_arg + args_required <= argc)
{
int safety_count = 1000;
uint32_t kick_id;
uint8_t kick_mac[ETH_ALEN];
load_mac(kick_mac, argv[1]);
load_u32(&kick_id, argv[2]);
while ((kick_clients(kick_mac, kick_id) != 0) && safety_count--);
}
}
else if (strcmp(*argv, "better_ap_available") == 0)
{
args_required = 4;
if (curr_arg + args_required <= argc)
{
uint8_t bssid_mac[ETH_ALEN];
uint8_t client_mac[ETH_ALEN];
uint32_t autokick;
int tr = 9999; // Tamper evident value
load_mac(bssid_mac, argv[1]);
load_mac(client_mac, argv[2]);
load_u32(&autokick, argv[3]);
char nb[NEIGHBOR_REPORT_LEN] = "TAMPER EVIDENT NEIGHBOR REPORT INITIALISATION STRING";
if (curr_arg + 5 <= argc)
{
args_required = 5;
if (strcmp(argv[4], "\0") == 0) // Provide a way to set an empty string
{
strcpy(nb, "");
}
else
{
strcpy(nb, argv[4]);
}
tr = better_ap_available(bssid_mac, client_mac, nb, autokick);
}
else
{
tr = better_ap_available(bssid_mac, client_mac, NULL, autokick);
}
printf("better_ap_available returned %d (with neighbour report %s)\n", tr, nb);
}
}
else if (strcmp(*argv, "eval_probe_metric") == 0)
{
args_required = 3;
if (curr_arg + args_required <= argc)
{
uint8_t bssid_mac[ETH_ALEN];
uint8_t client_mac[ETH_ALEN];
load_mac(bssid_mac, argv[1]);
load_mac(client_mac, argv[2]);
probe_entry probe0 = probe_array_get_entry(bssid_mac, client_mac);
union pac_a_mac test_mac;
memcpy(test_mac.unpacked.u8, probe0.bssid_addr, sizeof(probe0.bssid_addr));
if ((test_mac.packed_u64 & MAC_MASK_PACKED_U64) == 0 )
{
printf("eval_probe_metric: Can't find probe entry!\n");
}
else
{
int this_metric = eval_probe_metric(probe0);
printf("eval_probe_metric: Returned %d\n", this_metric);
}
}
}
else
{
args_required = 1;
@ -285,6 +858,17 @@ int consume_actions(int argc, char* argv[])
{
// Still need to continue consuming args
argv += args_required;
// Sometimes move fake time on a second - about 1 in 5 chance
if (faketime_auto && ((rand() & 0xFF) > 200))
{
faketime += 1;
if (!(faketime & 1))
printf("Faketime: tick %ld...\n", faketime);
else
printf("Faketime: tock %ld...\n", faketime);
}
}
else
{
@ -297,26 +881,29 @@ int consume_actions(int argc, char* argv[])
return ret;
}
int process_script_line(char* line, size_t len);
#define MAX_LINE_ARGS 5
int process_script_line(char* line, size_t len)
#define MAX_LINE_ARGS 20
static int process_script_line(char* line, size_t len);
static int process_script_line(char* line, size_t len)
{
int argc = 0;
char* argv[MAX_LINE_ARGS];
bool in_white = true;
bool force_blank = false;
bool force_nul = false;
int ret = 0;
//printf("%lu: \"%s\"\n", len, line);
while (len > 0 && !ret)
{
if (isblank(*line) || (*line == '\n') || (*line == '\r') || (*line == '#') || force_blank)
if (isblank(*line) || (*line == '\n') || (*line == '\r') || (*line == '#') || force_nul)
{
if (*line == '#')
{
//printf("Blanking 0x%02X...\n", *line);
force_blank = true;
force_nul = true;
// Untested - might bring parsing to faster end...
// len = 1;
}
//printf("Zapping 0x%02X...\n", *line);
@ -355,7 +942,7 @@ int process_script_line(char* line, size_t len)
int main(int argc, char* argv[])
{
FILE* fp;
FILE* fp = NULL;
char* line = NULL;
size_t len = 0;
ssize_t read;
@ -377,6 +964,9 @@ int main(int argc, char* argv[])
}
else
{
strcpy(sort_string, "bcfs");
init_mutex();
// Step past command name on args, ie argv[0]
argc--;
argv++;
@ -422,11 +1012,17 @@ int main(int argc, char* argv[])
read = getline(&line, &len, fp);
}
if (fp != stdin)
if (fp && fp != stdin)
{
fclose(fp);
fp = NULL;
}
if (line)
{
free(line);
line = NULL;
}
}
argc--;
@ -438,6 +1034,8 @@ int main(int argc, char* argv[])
// Take direct input on command line
ret = consume_actions(argc, argv);
}
destroy_mutex();
}
printf("\nDAWN datastorage.c test harness - finshed. \n");

View file

@ -1,14 +1,14 @@
#include <iwinfo.h>
#include <limits.h>
#include "mac_utils.h"
#include "datastorage.h"
#include "dawn_iwinfo.h"
#include <limits.h>
#include <iwinfo.h>
#include <dirent.h>
#include "utils.h"
#include "ubus.h"
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
char hostapd_dir_glob[HOSTAPD_DIR_LEN];
int call_iwinfo(char *client_addr);
int parse_rssi(char *iwinfo_string);
@ -271,7 +271,7 @@ int get_bssid(const char *ifname, uint8_t *bssid_addr) {
return 0;
}
int get_ssid(const char *ifname, char* ssid) {
int get_ssid(const char *ifname, char* ssid, size_t ssidmax) {
const struct iwinfo_ops *iw;
char buf[IWINFO_ESSID_MAX_SIZE+1] = { 0 };
if (strcmp(ifname, "global") == 0)
@ -280,7 +280,7 @@ int get_ssid(const char *ifname, char* ssid) {
if (iw->ssid(ifname, buf))
memset(buf, 0, sizeof(buf));
memcpy(ssid, buf, (SSID_MAX_LEN) * sizeof(char));
memcpy(ssid, buf, ssidmax);
strcpy(ssid, buf);
iwinfo_finish();
return 0;
@ -373,6 +373,7 @@ int support_vht(const char *ifname) {
return 0;
}
// TODO: 1 << 2 duplicated here, and also appears as HT mode mask
uint32_t vht_support_bitmask = (1 << 2) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
int ret = htmodes & vht_support_bitmask ? 1 : 0;
iwinfo_finish();

View file

@ -1,8 +1,9 @@
#include <uci.h>
#include <stdlib.h>
#include <datastorage.h>
#include <ubus.h>
#include <string.h>
#include "datastorage.h"
#include "dawn_iwinfo.h"
#include "dawn_uci.h"

View file

@ -1,11 +1,14 @@
#include "ieee80211_utils.h"
#include <stdint.h>
double iee80211_calculate_bitrate(uint8_t supp_rate_val) {
return ((double) supp_rate_val) / 2;
}
double iee80211_calculate_expected_throughput_mbit(int exp_thr) {
return (((double) exp_thr) / 1000);
}
}
int rcpi_to_rssi(int rcpi)
{
return rcpi / 2 - 110;
}

83
src/utils/mac_utils.c Normal file
View file

@ -0,0 +1,83 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "utils.h"
#include "mac_utils.h"
// based on: hostapd src/utils/common.c
int hwaddr_aton(const char* txt, uint8_t* addr) {
int i;
for (i = 0; i < ETH_ALEN; i++) {
int a, b;
a = hex_to_dec(*txt++);
if (a < 0) return -1;
b = hex_to_dec(*txt++);
if (b < 0) return -1;
*addr++ = (a << 4) | b;
// TODO: Should NUL terminator be checked for? Is aa:bb:cc:dd:ee:ff00 valid input?
if (i < (ETH_ALEN - 1) && *txt++ != ':') return -1;
}
return 0;
}
int mac_is_equal(const uint8_t addr1[], const uint8_t addr2[]) {
return memcmp(addr1, addr2, ETH_ALEN * sizeof(uint8_t)) == 0;
}
int mac_is_greater(const uint8_t addr1[], const uint8_t addr2[]) {
for (int i = 0; i < ETH_ALEN; i++) {
if (addr1[i] > addr2[i]) {
return 1;
}
if (addr1[i] < addr2[i]) {
return 0;
}
// if equal continue...
}
return 0;
}
// TODO: Never called in DAWN code. Remove?
#if 0
/* Convert badly formed MAC addresses with single digit element to double digit
** eg 11:2:33:4:55:6 to 11:02:33:04:55:06 */`
int convert_mac(char* in, char* out) {
int i, j = 0;
for (i = 0; i < ETH_ALEN; i++) {
/* Do we have a single-digit element? */
if (in[j + 1] == ':' || in[j + 1] == '\0') {
out[3 * i] = '0';
out[(3 * i) + 1] = toupper(in[j]);
out[(3 * i) + 2] = toupper(in[j + 1]);
j += 2;
}
else {
out[3 * i] = toupper(in[j]);
out[(3 * i) + 1] = toupper(in[j + 1]);
out[(3 * i) + 2] = in[j + 2];
j += 3;
}
}
return 0;
}
#endif
void write_mac_to_file(char* path, uint8_t addr[]) {
FILE* f = fopen(path, "a");
if (f == NULL) {
fprintf(stderr, "Error opening mac file!\n");
exit(1);
}
char mac_buf[20];
sprintf(mac_buf, MACSTR, MAC2STR(addr));
fprintf(f, "%s\n", mac_buf);
fclose(f);
}

792
src/utils/msghandler.c Normal file
View file

@ -0,0 +1,792 @@
#include <libubus.h>
#include "dawn_uci.h"
#include "datastorage.h"
#include "ubus.h"
#include "msghandler.h"
static struct blob_buf network_buf;
static struct blob_buf data_buf;
enum {
NETWORK_METHOD,
NETWORK_DATA,
__NETWORK_MAX,
};
static const struct blobmsg_policy network_policy[__NETWORK_MAX] = {
[NETWORK_METHOD] = {.name = "method", .type = BLOBMSG_TYPE_STRING},
[NETWORK_DATA] = {.name = "data", .type = BLOBMSG_TYPE_STRING},
};
enum {
HOSTAPD_NOTIFY_BSSID_ADDR,
HOSTAPD_NOTIFY_CLIENT_ADDR,
__HOSTAPD_NOTIFY_MAX,
};
static const struct blobmsg_policy hostapd_notify_policy[__HOSTAPD_NOTIFY_MAX] = {
[HOSTAPD_NOTIFY_BSSID_ADDR] = {.name = "bssid", .type = BLOBMSG_TYPE_STRING},
[HOSTAPD_NOTIFY_CLIENT_ADDR] = {.name = "address", .type = BLOBMSG_TYPE_STRING},
};
enum {
PROB_BSSID_ADDR,
PROB_CLIENT_ADDR,
PROB_TARGET_ADDR,
PROB_SIGNAL,
PROB_FREQ,
PROB_HT_CAPABILITIES,
PROB_VHT_CAPABILITIES,
PROB_RCPI,
PROB_RSNI,
__PROB_MAX,
};
static const struct blobmsg_policy prob_policy[__PROB_MAX] = {
[PROB_BSSID_ADDR] = {.name = "bssid", .type = BLOBMSG_TYPE_STRING},
[PROB_CLIENT_ADDR] = {.name = "address", .type = BLOBMSG_TYPE_STRING},
[PROB_TARGET_ADDR] = {.name = "target", .type = BLOBMSG_TYPE_STRING},
[PROB_SIGNAL] = {.name = "signal", .type = BLOBMSG_TYPE_INT32},
[PROB_FREQ] = {.name = "freq", .type = BLOBMSG_TYPE_INT32},
[PROB_HT_CAPABILITIES] = {.name = "ht_capabilities", .type = BLOBMSG_TYPE_TABLE},
[PROB_VHT_CAPABILITIES] = {.name = "vht_capabilities", .type = BLOBMSG_TYPE_TABLE},
[PROB_RCPI] = {.name = "rcpi", .type = BLOBMSG_TYPE_INT32},
[PROB_RSNI] = {.name = "rsni", .type = BLOBMSG_TYPE_INT32},
};
enum {
CLIENT_TABLE,
CLIENT_TABLE_BSSID,
CLIENT_TABLE_SSID,
CLIENT_TABLE_FREQ,
CLIENT_TABLE_HT,
CLIENT_TABLE_VHT,
CLIENT_TABLE_CHAN_UTIL,
CLIENT_TABLE_NUM_STA,
CLIENT_TABLE_COL_DOMAIN,
CLIENT_TABLE_BANDWIDTH,
CLIENT_TABLE_WEIGHT,
CLIENT_TABLE_NEIGHBOR,
CLIENT_TABLE_IFACE,
CLIENT_TABLE_HOSTNAME,
__CLIENT_TABLE_MAX,
};
static const struct blobmsg_policy client_table_policy[__CLIENT_TABLE_MAX] = {
[CLIENT_TABLE] = {.name = "clients", .type = BLOBMSG_TYPE_TABLE},
[CLIENT_TABLE_BSSID] = {.name = "bssid", .type = BLOBMSG_TYPE_STRING},
[CLIENT_TABLE_SSID] = {.name = "ssid", .type = BLOBMSG_TYPE_STRING},
[CLIENT_TABLE_FREQ] = {.name = "freq", .type = BLOBMSG_TYPE_INT32},
[CLIENT_TABLE_HT] = {.name = "ht_supported", .type = BLOBMSG_TYPE_INT8},
[CLIENT_TABLE_VHT] = {.name = "vht_supported", .type = BLOBMSG_TYPE_INT8},
[CLIENT_TABLE_CHAN_UTIL] = {.name = "channel_utilization", .type = BLOBMSG_TYPE_INT32},
[CLIENT_TABLE_NUM_STA] = {.name = "num_sta", .type = BLOBMSG_TYPE_INT32},
[CLIENT_TABLE_COL_DOMAIN] = {.name = "collision_domain", .type = BLOBMSG_TYPE_INT32},
[CLIENT_TABLE_BANDWIDTH] = {.name = "bandwidth", .type = BLOBMSG_TYPE_INT32},
[CLIENT_TABLE_WEIGHT] = {.name = "ap_weight", .type = BLOBMSG_TYPE_INT32},
[CLIENT_TABLE_NEIGHBOR] = {.name = "neighbor_report", .type = BLOBMSG_TYPE_STRING},
[CLIENT_TABLE_IFACE] = {.name = "iface", .type = BLOBMSG_TYPE_STRING},
[CLIENT_TABLE_HOSTNAME] = {.name = "hostname", .type = BLOBMSG_TYPE_STRING},
};
enum {
CLIENT_SIGNATURE,
CLIENT_AUTH,
CLIENT_ASSOC,
CLIENT_AUTHORIZED,
CLIENT_PREAUTH,
CLIENT_WDS,
CLIENT_WMM,
CLIENT_HT,
CLIENT_VHT,
CLIENT_WPS,
CLIENT_MFP,
CLIENT_AID,
CLIENT_RRM,
__CLIENT_MAX,
};
static const struct blobmsg_policy client_policy[__CLIENT_MAX] = {
[CLIENT_SIGNATURE] = {.name = "signature", .type = BLOBMSG_TYPE_STRING},
[CLIENT_AUTH] = {.name = "auth", .type = BLOBMSG_TYPE_INT8},
[CLIENT_ASSOC] = {.name = "assoc", .type = BLOBMSG_TYPE_INT8},
[CLIENT_AUTHORIZED] = {.name = "authorized", .type = BLOBMSG_TYPE_INT8},
[CLIENT_PREAUTH] = {.name = "preauth", .type = BLOBMSG_TYPE_INT8},
[CLIENT_WDS] = {.name = "wds", .type = BLOBMSG_TYPE_INT8},
[CLIENT_WMM] = {.name = "wmm", .type = BLOBMSG_TYPE_INT8},
[CLIENT_HT] = {.name = "ht", .type = BLOBMSG_TYPE_INT8},
[CLIENT_VHT] = {.name = "vht", .type = BLOBMSG_TYPE_INT8},
[CLIENT_WPS] = {.name = "wps", .type = BLOBMSG_TYPE_INT8},
[CLIENT_MFP] = {.name = "mfp", .type = BLOBMSG_TYPE_INT8},
[CLIENT_AID] = {.name = "aid", .type = BLOBMSG_TYPE_INT32},
[CLIENT_RRM] = {.name = "rrm", .type = BLOBMSG_TYPE_ARRAY},
};
static int handle_set_probe(struct blob_attr* msg);
static int handle_uci_config(struct blob_attr* msg);
int parse_to_hostapd_notify(struct blob_attr* msg, hostapd_notify_entry* notify_req) {
struct blob_attr* tb[__HOSTAPD_NOTIFY_MAX];
blobmsg_parse(hostapd_notify_policy, __HOSTAPD_NOTIFY_MAX, tb, blob_data(msg), blob_len(msg));
if (hwaddr_aton(blobmsg_data(tb[HOSTAPD_NOTIFY_BSSID_ADDR]), notify_req->bssid_addr))
return UBUS_STATUS_INVALID_ARGUMENT;
if (hwaddr_aton(blobmsg_data(tb[HOSTAPD_NOTIFY_CLIENT_ADDR]), notify_req->client_addr))
return UBUS_STATUS_INVALID_ARGUMENT;
return 0;
}
int parse_to_probe_req(struct blob_attr* msg, probe_entry* prob_req) {
struct blob_attr* tb[__PROB_MAX];
blobmsg_parse(prob_policy, __PROB_MAX, tb, blob_data(msg), blob_len(msg));
if (hwaddr_aton(blobmsg_data(tb[PROB_BSSID_ADDR]), prob_req->bssid_addr))
return UBUS_STATUS_INVALID_ARGUMENT;
if (hwaddr_aton(blobmsg_data(tb[PROB_CLIENT_ADDR]), prob_req->client_addr))
return UBUS_STATUS_INVALID_ARGUMENT;
if (hwaddr_aton(blobmsg_data(tb[PROB_TARGET_ADDR]), prob_req->target_addr))
return UBUS_STATUS_INVALID_ARGUMENT;
if (tb[PROB_SIGNAL]) {
prob_req->signal = blobmsg_get_u32(tb[PROB_SIGNAL]);
}
if (tb[PROB_FREQ]) {
prob_req->freq = blobmsg_get_u32(tb[PROB_FREQ]);
}
if (tb[PROB_RCPI]) {
prob_req->rcpi = blobmsg_get_u32(tb[PROB_RCPI]);
}
else {
prob_req->rcpi = -1;
}
if (tb[PROB_RSNI]) {
prob_req->rsni = blobmsg_get_u32(tb[PROB_RSNI]);
}
else {
prob_req->rsni = -1;
}
if (tb[PROB_HT_CAPABILITIES]) {
prob_req->ht_capabilities = true;
}
else
{
prob_req->ht_capabilities = false;
}
if (tb[PROB_VHT_CAPABILITIES]) {
prob_req->vht_capabilities = true;
}
else
{
prob_req->vht_capabilities = false;
}
return 0;
}
int handle_deauth_req(struct blob_attr* msg) {
hostapd_notify_entry notify_req;
parse_to_hostapd_notify(msg, &notify_req);
client client_entry;
memcpy(client_entry.bssid_addr, notify_req.bssid_addr, sizeof(uint8_t) * ETH_ALEN);
memcpy(client_entry.client_addr, notify_req.client_addr, sizeof(uint8_t) * ETH_ALEN);
pthread_mutex_lock(&client_array_mutex);
client_array_delete(client_entry);
pthread_mutex_unlock(&client_array_mutex);
printf("[WC] Deauth: %s\n", "deauth");
return 0;
}
static int handle_set_probe(struct blob_attr* msg) {
hostapd_notify_entry notify_req;
parse_to_hostapd_notify(msg, &notify_req);
// TODO: Is a client struct needed nere, ir just a uint8[ETH_ALEN]?
client client_entry;
memcpy(client_entry.bssid_addr, notify_req.bssid_addr, sizeof(uint8_t) * ETH_ALEN);
memcpy(client_entry.client_addr, notify_req.client_addr, sizeof(uint8_t) * ETH_ALEN);
probe_array_set_all_probe_count(client_entry.client_addr, dawn_metric.min_probe_count);
return 0;
}
int handle_network_msg(char* msg) {
struct blob_attr* tb[__NETWORK_MAX];
char* method;
char* data;
blob_buf_init(&network_buf, 0);
blobmsg_add_json_from_string(&network_buf, msg);
blobmsg_parse(network_policy, __NETWORK_MAX, tb, blob_data(network_buf.head), blob_len(network_buf.head));
if (!tb[NETWORK_METHOD] || !tb[NETWORK_DATA]) {
return -1;
}
method = blobmsg_data(tb[NETWORK_METHOD]);
data = blobmsg_data(tb[NETWORK_DATA]);
printf("Network Method new: %s : %s\n", method, msg);
blob_buf_init(&data_buf, 0);
blobmsg_add_json_from_string(&data_buf, data);
if (!data_buf.head) {
return -1;
}
if (blob_len(data_buf.head) <= 0) {
return -1;
}
if (strlen(method) < 2) {
return -1;
}
// add inactive death...
// TODO: strncmp() look wrong - should all tests be for n = 5 characters? Shorthand checks?
if (strncmp(method, "probe", 5) == 0) {
probe_entry entry;
if (parse_to_probe_req(data_buf.head, &entry) == 0) {
entry.time = time(0);
insert_to_array(entry, 0, false, false); // use 802.11k values // TODO: Change 0 to false?
}
}
else if (strncmp(method, "clients", 5) == 0) {
parse_to_clients(data_buf.head, 0, 0);
}
else if (strncmp(method, "deauth", 5) == 0) {
printf("METHOD DEAUTH\n");
handle_deauth_req(data_buf.head);
}
else if (strncmp(method, "setprobe", 5) == 0) {
printf("HANDLING SET PROBE!\n");
handle_set_probe(data_buf.head);
}
else if (strncmp(method, "addmac", 5) == 0) {
parse_add_mac_to_file(data_buf.head);
}
else if (strncmp(method, "macfile", 5) == 0) {
parse_add_mac_to_file(data_buf.head);
}
else if (strncmp(method, "uci", 2) == 0) {
printf("HANDLING UCI!\n");
handle_uci_config(data_buf.head);
}
else if (strncmp(method, "beacon-report", 12) == 0) {
// TODO: Check beacon report stuff
//printf("HANDLING BEACON REPORT NETWORK!\n");
//printf("The Method for beacon-report is: %s\n", method);
// ignore beacon reports send via network!, use probe functions for it
//probe_entry entry; // for now just stay at probe entry stuff...
//parse_to_beacon_rep(data_buf.head, &entry, true);
}
else
{
printf("No method fonud for: %s\n", method);
}
return 0;
}
static uint8_t dump_rrm_data(void* data, int len, int type) //modify from examples/blobmsg-example.c in libubox
{
uint32_t ret = 0;
switch (type) {
case BLOBMSG_TYPE_INT32:
ret = *(uint32_t*)data;
break;
default:
fprintf(stderr, "wrong type of rrm array\n");
}
return (uint8_t)ret;
}
static uint8_t
dump_rrm_table(struct blob_attr* head, int len) //modify from examples/blobmsg-example.c in libubox
{
struct blob_attr* attr;
uint8_t ret = 0;
__blob_for_each_attr(attr, head, len) {
ret = dump_rrm_data(blobmsg_data(attr), blobmsg_data_len(attr), blob_id(attr));
return ret;// get the first rrm byte
}
return ret;
}
// TOOD: Refactor this!
static void
dump_client(struct blob_attr** tb, uint8_t client_addr[], const char* bssid_addr, uint32_t freq, uint8_t ht_supported,
uint8_t vht_supported) {
client client_entry;
hwaddr_aton(bssid_addr, client_entry.bssid_addr);
memcpy(client_entry.client_addr, client_addr, ETH_ALEN * sizeof(uint8_t));
client_entry.freq = freq;
client_entry.ht_supported = ht_supported;
client_entry.vht_supported = vht_supported;
if (tb[CLIENT_AUTH]) {
client_entry.auth = blobmsg_get_u8(tb[CLIENT_AUTH]);
}
if (tb[CLIENT_ASSOC]) {
client_entry.assoc = blobmsg_get_u8(tb[CLIENT_ASSOC]);
}
if (tb[CLIENT_AUTHORIZED]) {
client_entry.authorized = blobmsg_get_u8(tb[CLIENT_AUTHORIZED]);
}
if (tb[CLIENT_PREAUTH]) {
client_entry.preauth = blobmsg_get_u8(tb[CLIENT_PREAUTH]);
}
if (tb[CLIENT_WDS]) {
client_entry.wds = blobmsg_get_u8(tb[CLIENT_WDS]);
}
if (tb[CLIENT_WMM]) {
client_entry.wmm = blobmsg_get_u8(tb[CLIENT_WMM]);
}
if (tb[CLIENT_HT]) {
client_entry.ht = blobmsg_get_u8(tb[CLIENT_HT]);
}
if (tb[CLIENT_VHT]) {
client_entry.vht = blobmsg_get_u8(tb[CLIENT_VHT]);
}
if (tb[CLIENT_WPS]) {
client_entry.wps = blobmsg_get_u8(tb[CLIENT_WPS]);
}
if (tb[CLIENT_MFP]) {
client_entry.mfp = blobmsg_get_u8(tb[CLIENT_MFP]);
}
if (tb[CLIENT_AID]) {
client_entry.aid = blobmsg_get_u32(tb[CLIENT_AID]);
}
/* RRM Caps */
if (tb[CLIENT_RRM]) {
client_entry.rrm_enabled_capa = dump_rrm_table(blobmsg_data(tb[CLIENT_RRM]),
blobmsg_data_len(tb[CLIENT_RRM]));// get the first byte from rrm array
//ap_entry.ap_weight = blobmsg_get_u32(tb[CLIENT_TABLE_RRM]);
}
else {
client_entry.rrm_enabled_capa = 0;
//ap_entry.ap_weight = 0;
}
// copy signature
if (tb[CLIENT_SIGNATURE]) {
strncpy(client_entry.signature, blobmsg_data(tb[CLIENT_SIGNATURE]), SIGNATURE_LEN * sizeof(char));
}
else
{
memset(client_entry.signature, 0, 1024);
}
client_entry.time = time(0);
insert_client_to_array(client_entry);
}
static int
dump_client_table(struct blob_attr* head, int len, const char* bssid_addr, uint32_t freq, uint8_t ht_supported,
uint8_t vht_supported) {
struct blob_attr* attr;
struct blobmsg_hdr* hdr;
int station_count = 0;
__blob_for_each_attr(attr, head, len)
{
hdr = blob_data(attr);
struct blob_attr* tb[__CLIENT_MAX];
blobmsg_parse(client_policy, __CLIENT_MAX, tb, blobmsg_data(attr), blobmsg_len(attr));
//char* str = blobmsg_format_json_indent(attr, true, -1);
int tmp_int_mac[ETH_ALEN];
uint8_t tmp_mac[ETH_ALEN];
sscanf((char*)hdr->name, MACSTR, STR2MAC(tmp_int_mac));
for (int i = 0; i < ETH_ALEN; ++i)
tmp_mac[i] = (uint8_t)tmp_int_mac[i];
dump_client(tb, tmp_mac, bssid_addr, freq, ht_supported, vht_supported);
station_count++;
}
return station_count;
}
int parse_to_clients(struct blob_attr* msg, int do_kick, uint32_t id) {
struct blob_attr* tb[__CLIENT_TABLE_MAX];
if (!msg) {
return -1;
}
if (!blob_data(msg)) {
return -1;
}
if (blob_len(msg) <= 0) {
return -1;
}
blobmsg_parse(client_table_policy, __CLIENT_TABLE_MAX, tb, blob_data(msg), blob_len(msg));
if (tb[CLIENT_TABLE] && tb[CLIENT_TABLE_BSSID] && tb[CLIENT_TABLE_FREQ]) {
int num_stations = 0;
num_stations = dump_client_table(blobmsg_data(tb[CLIENT_TABLE]), blobmsg_data_len(tb[CLIENT_TABLE]),
blobmsg_data(tb[CLIENT_TABLE_BSSID]), blobmsg_get_u32(tb[CLIENT_TABLE_FREQ]),
blobmsg_get_u8(tb[CLIENT_TABLE_HT]), blobmsg_get_u8(tb[CLIENT_TABLE_VHT]));
ap ap_entry;
hwaddr_aton(blobmsg_data(tb[CLIENT_TABLE_BSSID]), ap_entry.bssid_addr);
ap_entry.freq = blobmsg_get_u32(tb[CLIENT_TABLE_FREQ]);
if (tb[CLIENT_TABLE_HT]) {
ap_entry.ht_support = blobmsg_get_u8(tb[CLIENT_TABLE_HT]);
}
else {
ap_entry.ht_support = false;
}
if (tb[CLIENT_TABLE_VHT]) {
ap_entry.vht_support = blobmsg_get_u8(tb[CLIENT_TABLE_VHT]);
}
else
{
ap_entry.vht_support = false;
}
if (tb[CLIENT_TABLE_CHAN_UTIL]) {
ap_entry.channel_utilization = blobmsg_get_u32(tb[CLIENT_TABLE_CHAN_UTIL]);
}
else // if this is not existing set to 0? //TODO: Consider setting to a value that will not mislead eval_probe_metric(), eg dawn_metric.chan_util_val?
{
ap_entry.channel_utilization = 0;
}
if (tb[CLIENT_TABLE_SSID]) {
strcpy((char*)ap_entry.ssid, blobmsg_get_string(tb[CLIENT_TABLE_SSID]));
}
if (tb[CLIENT_TABLE_COL_DOMAIN]) {
ap_entry.collision_domain = blobmsg_get_u32(tb[CLIENT_TABLE_COL_DOMAIN]);
}
else {
ap_entry.collision_domain = -1;
}
if (tb[CLIENT_TABLE_BANDWIDTH]) {
ap_entry.bandwidth = blobmsg_get_u32(tb[CLIENT_TABLE_BANDWIDTH]);
}
else {
ap_entry.bandwidth = -1;
}
ap_entry.station_count = num_stations;
if (tb[CLIENT_TABLE_WEIGHT]) {
ap_entry.ap_weight = blobmsg_get_u32(tb[CLIENT_TABLE_WEIGHT]);
}
else {
ap_entry.ap_weight = 0;
}
if (tb[CLIENT_TABLE_NEIGHBOR]) {
strncpy(ap_entry.neighbor_report, blobmsg_get_string(tb[CLIENT_TABLE_NEIGHBOR]), NEIGHBOR_REPORT_LEN);
}
else {
ap_entry.neighbor_report[0] = '\0';
}
if (tb[CLIENT_TABLE_IFACE]) {
strncpy(ap_entry.iface, blobmsg_get_string(tb[CLIENT_TABLE_IFACE]), MAX_INTERFACE_NAME);
}
else {
ap_entry.iface[0] = '\0';
}
if (tb[CLIENT_TABLE_HOSTNAME]) {
strncpy(ap_entry.hostname, blobmsg_get_string(tb[CLIENT_TABLE_HOSTNAME]), HOST_NAME_MAX);
}
else {
ap_entry.hostname[0] = '\0';
}
ap_entry.time = time(0);
insert_to_ap_array(ap_entry);
if (do_kick && dawn_metric.kicking) {
update_iw_info(ap_entry.bssid_addr);
kick_clients(ap_entry.bssid_addr, id);
}
}
return 0;
}
enum {
UCI_TABLE_METRIC,
UCI_TABLE_TIMES,
__UCI_TABLE_MAX
};
enum {
UCI_HT_SUPPORT,
UCI_VHT_SUPPORT,
UCI_NO_HT_SUPPORT,
UCI_NO_VHT_SUPPORT,
UCI_RSSI,
UCI_LOW_RSSI,
UCI_FREQ,
UCI_CHAN_UTIL,
UCI_MAX_CHAN_UTIL,
UCI_RSSI_VAL,
UCI_LOW_RSSI_VAL,
UCI_CHAN_UTIL_VAL,
UCI_MAX_CHAN_UTIL_VAL,
UCI_MIN_PROBE_COUNT,
UCI_BANDWIDTH_THRESHOLD,
UCI_USE_STATION_COUNT,
UCI_MAX_STATION_DIFF,
UCI_EVAL_PROBE_REQ,
UCI_EVAL_AUTH_REQ,
UCI_EVAL_ASSOC_REQ,
UCI_KICKING,
UCI_DENY_AUTH_REASON,
UCI_DENY_ASSOC_REASON,
UCI_USE_DRIVER_RECOG,
UCI_MIN_NUMBER_TO_KICK,
UCI_CHAN_UTIL_AVG_PERIOD,
UCI_SET_HOSTAPD_NR,
UCI_OP_CLASS,
UCI_DURATION,
UCI_MODE,
UCI_SCAN_CHANNEL,
__UCI_METIC_MAX
};
enum {
UCI_UPDATE_CLIENT,
UCI_DENIED_REQ_THRESHOLD,
UCI_REMOVE_CLIENT,
UCI_REMOVE_PROBE,
UCI_REMOVE_AP,
UCI_UPDATE_HOSTAPD,
UCI_UPDATE_TCP_CON,
UCI_UPDATE_CHAN_UTIL,
UCI_UPDATE_BEACON_REPORTS,
__UCI_TIMES_MAX,
};
static const struct blobmsg_policy uci_table_policy[__UCI_TABLE_MAX] = {
[UCI_TABLE_METRIC] = {.name = "metric", .type = BLOBMSG_TYPE_TABLE},
[UCI_TABLE_TIMES] = {.name = "times", .type = BLOBMSG_TYPE_TABLE}
};
static const struct blobmsg_policy uci_metric_policy[__UCI_METIC_MAX] = {
[UCI_HT_SUPPORT] = {.name = "ht_support", .type = BLOBMSG_TYPE_INT32},
[UCI_VHT_SUPPORT] = {.name = "vht_support", .type = BLOBMSG_TYPE_INT32},
[UCI_NO_HT_SUPPORT] = {.name = "no_ht_support", .type = BLOBMSG_TYPE_INT32},
[UCI_NO_VHT_SUPPORT] = {.name = "no_vht_support", .type = BLOBMSG_TYPE_INT32},
[UCI_RSSI] = {.name = "rssi", .type = BLOBMSG_TYPE_INT32},
[UCI_LOW_RSSI] = {.name = "low_rssi", .type = BLOBMSG_TYPE_INT32},
[UCI_FREQ] = {.name = "freq", .type = BLOBMSG_TYPE_INT32},
[UCI_CHAN_UTIL] = {.name = "chan_util", .type = BLOBMSG_TYPE_INT32},
[UCI_MAX_CHAN_UTIL] = {.name = "max_chan_util", .type = BLOBMSG_TYPE_INT32},
[UCI_RSSI_VAL] = {.name = "rssi_val", .type = BLOBMSG_TYPE_INT32},
[UCI_LOW_RSSI_VAL] = {.name = "low_rssi_val", .type = BLOBMSG_TYPE_INT32},
[UCI_CHAN_UTIL_VAL] = {.name = "chan_util_val", .type = BLOBMSG_TYPE_INT32},
[UCI_MAX_CHAN_UTIL_VAL] = {.name = "max_chan_util_val", .type = BLOBMSG_TYPE_INT32},
[UCI_MIN_PROBE_COUNT] = {.name = "min_probe_count", .type = BLOBMSG_TYPE_INT32},
[UCI_BANDWIDTH_THRESHOLD] = {.name = "bandwidth_threshold", .type = BLOBMSG_TYPE_INT32},
[UCI_USE_STATION_COUNT] = {.name = "use_station_count", .type = BLOBMSG_TYPE_INT32},
[UCI_MAX_STATION_DIFF] = {.name = "max_station_diff", .type = BLOBMSG_TYPE_INT32},
[UCI_EVAL_PROBE_REQ] = {.name = "eval_probe_req", .type = BLOBMSG_TYPE_INT32},
[UCI_EVAL_AUTH_REQ] = {.name = "eval_auth_req", .type = BLOBMSG_TYPE_INT32},
[UCI_EVAL_ASSOC_REQ] = {.name = "eval_assoc_req", .type = BLOBMSG_TYPE_INT32},
[UCI_KICKING] = {.name = "kicking", .type = BLOBMSG_TYPE_INT32},
[UCI_DENY_AUTH_REASON] = {.name = "deny_auth_reason", .type = BLOBMSG_TYPE_INT32},
[UCI_DENY_ASSOC_REASON] = {.name = "deny_assoc_reason", .type = BLOBMSG_TYPE_INT32},
[UCI_USE_DRIVER_RECOG] = {.name = "use_driver_recog", .type = BLOBMSG_TYPE_INT32},
[UCI_MIN_NUMBER_TO_KICK] = {.name = "min_number_to_kick", .type = BLOBMSG_TYPE_INT32},
[UCI_CHAN_UTIL_AVG_PERIOD] = {.name = "chan_util_avg_period", .type = BLOBMSG_TYPE_INT32},
[UCI_SET_HOSTAPD_NR] = {.name = "set_hostapd_nr", .type = BLOBMSG_TYPE_INT32},
[UCI_OP_CLASS] = {.name = "op_class", .type = BLOBMSG_TYPE_INT32},
[UCI_DURATION] = {.name = "duration", .type = BLOBMSG_TYPE_INT32},
[UCI_MODE] = {.name = "mode", .type = BLOBMSG_TYPE_INT32},
[UCI_SCAN_CHANNEL] = {.name = "mode", .type = BLOBMSG_TYPE_INT32},
};
static const struct blobmsg_policy uci_times_policy[__UCI_TIMES_MAX] = {
[UCI_UPDATE_CLIENT] = {.name = "update_client", .type = BLOBMSG_TYPE_INT32},
[UCI_DENIED_REQ_THRESHOLD] = {.name = "denied_req_threshold", .type = BLOBMSG_TYPE_INT32},
[UCI_REMOVE_CLIENT] = {.name = "remove_client", .type = BLOBMSG_TYPE_INT32},
[UCI_REMOVE_PROBE] = {.name = "remove_probe", .type = BLOBMSG_TYPE_INT32},
[UCI_REMOVE_AP] = {.name = "remove_ap", .type = BLOBMSG_TYPE_INT32},
[UCI_UPDATE_HOSTAPD] = {.name = "update_hostapd", .type = BLOBMSG_TYPE_INT32},
[UCI_UPDATE_TCP_CON] = {.name = "update_tcp_con", .type = BLOBMSG_TYPE_INT32},
[UCI_UPDATE_CHAN_UTIL] = {.name = "update_chan_util", .type = BLOBMSG_TYPE_INT32},
[UCI_UPDATE_BEACON_REPORTS] = {.name = "update_beacon_reports", .type = BLOBMSG_TYPE_INT32},
};
static int handle_uci_config(struct blob_attr* msg) {
struct blob_attr* tb[__UCI_TABLE_MAX];
blobmsg_parse(uci_table_policy, __UCI_TABLE_MAX, tb, blob_data(msg), blob_len(msg));
struct blob_attr* tb_metric[__UCI_METIC_MAX];
blobmsg_parse(uci_metric_policy, __UCI_METIC_MAX, tb_metric, blobmsg_data(tb[UCI_TABLE_METRIC]), blobmsg_len(tb[UCI_TABLE_METRIC]));
char cmd_buffer[1024];
sprintf(cmd_buffer, "dawn.@metric[0].ht_support=%d", blobmsg_get_u32(tb_metric[UCI_HT_SUPPORT]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].vht_support=%d", blobmsg_get_u32(tb_metric[UCI_VHT_SUPPORT]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].no_ht_support=%d", blobmsg_get_u32(tb_metric[UCI_NO_HT_SUPPORT]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].no_vht_support=%d", blobmsg_get_u32(tb_metric[UCI_NO_VHT_SUPPORT]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].rssi=%d", blobmsg_get_u32(tb_metric[UCI_RSSI]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].low_rssi=%d", blobmsg_get_u32(tb_metric[UCI_LOW_RSSI]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].freq=%d", blobmsg_get_u32(tb_metric[UCI_FREQ]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].chan_util=%d", blobmsg_get_u32(tb_metric[UCI_CHAN_UTIL]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].rssi_val=%d", blobmsg_get_u32(tb_metric[UCI_RSSI_VAL]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].low_rssi_val=%d", blobmsg_get_u32(tb_metric[UCI_LOW_RSSI_VAL]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].chan_util_val=%d", blobmsg_get_u32(tb_metric[UCI_CHAN_UTIL_VAL]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].max_chan_util=%d", blobmsg_get_u32(tb_metric[UCI_MAX_CHAN_UTIL]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].max_chan_util_val=%d", blobmsg_get_u32(tb_metric[UCI_MAX_CHAN_UTIL_VAL]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].min_probe_count=%d", blobmsg_get_u32(tb_metric[UCI_MIN_PROBE_COUNT]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].bandwidth_threshold=%d", blobmsg_get_u32(tb_metric[UCI_BANDWIDTH_THRESHOLD]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].use_station_count=%d", blobmsg_get_u32(tb_metric[UCI_USE_STATION_COUNT]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].max_station_diff=%d", blobmsg_get_u32(tb_metric[UCI_MAX_STATION_DIFF]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].eval_probe_req=%d", blobmsg_get_u32(tb_metric[UCI_EVAL_PROBE_REQ]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].eval_auth_req=%d", blobmsg_get_u32(tb_metric[UCI_EVAL_AUTH_REQ]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].evalcd_assoc_req=%d", blobmsg_get_u32(tb_metric[UCI_EVAL_ASSOC_REQ]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].kicking=%d", blobmsg_get_u32(tb_metric[UCI_KICKING]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].deny_auth_reason=%d", blobmsg_get_u32(tb_metric[UCI_DENY_AUTH_REASON]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].deny_assoc_reason=%d", blobmsg_get_u32(tb_metric[UCI_DENY_ASSOC_REASON]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].use_driver_recog=%d", blobmsg_get_u32(tb_metric[UCI_USE_DRIVER_RECOG]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].min_number_to_kick=%d", blobmsg_get_u32(tb_metric[UCI_MIN_NUMBER_TO_KICK]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].chan_util_avg_period=%d", blobmsg_get_u32(tb_metric[UCI_CHAN_UTIL_AVG_PERIOD]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].set_hostapd_nr=%d", blobmsg_get_u32(tb_metric[UCI_SET_HOSTAPD_NR]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].op_class=%d", blobmsg_get_u32(tb_metric[UCI_OP_CLASS]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].duration=%d", blobmsg_get_u32(tb_metric[UCI_DURATION]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].mode=%d", blobmsg_get_u32(tb_metric[UCI_MODE]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@metric[0].scan_channel=%d", blobmsg_get_u32(tb_metric[UCI_SCAN_CHANNEL]));
uci_set_network(cmd_buffer);
struct blob_attr* tb_times[__UCI_TIMES_MAX];
blobmsg_parse(uci_times_policy, __UCI_TIMES_MAX, tb_times, blobmsg_data(tb[UCI_TABLE_TIMES]), blobmsg_len(tb[UCI_TABLE_TIMES]));
sprintf(cmd_buffer, "dawn.@times[0].update_client=%d", blobmsg_get_u32(tb_times[UCI_UPDATE_CLIENT]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@times[0].denied_req_threshold=%d", blobmsg_get_u32(tb_times[UCI_DENIED_REQ_THRESHOLD]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@times[0].remove_client=%d", blobmsg_get_u32(tb_times[UCI_REMOVE_CLIENT]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@times[0].remove_probe=%d", blobmsg_get_u32(tb_times[UCI_REMOVE_PROBE]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@times[0].remove_ap=%d", blobmsg_get_u32(tb_times[UCI_REMOVE_AP]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@times[0].update_hostapd=%d", blobmsg_get_u32(tb_times[UCI_UPDATE_HOSTAPD]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@times[0].update_tcp_con=%d", blobmsg_get_u32(tb_times[UCI_UPDATE_TCP_CON]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@times[0].update_chan_util=%d", blobmsg_get_u32(tb_times[UCI_UPDATE_CHAN_UTIL]));
uci_set_network(cmd_buffer);
sprintf(cmd_buffer, "dawn.@times[0].update_beacon_reports=%d", blobmsg_get_u32(tb_times[UCI_UPDATE_BEACON_REPORTS]));
uci_set_network(cmd_buffer);
uci_reset();
dawn_metric = uci_get_dawn_metric();
timeout_config = uci_get_time_config();
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "datastorage.h"
#include <ctype.h>
#include "utils.h"
int string_is_greater(uint8_t *str, uint8_t *str_2) {
@ -23,73 +22,9 @@ int string_is_greater(uint8_t *str, uint8_t *str_2) {
}
// source: https://elixir.bootlin.com/linux/v4.9/source/lib/hexdump.c#L28
int hex_to_bin(char ch) {
int hex_to_dec(char ch) {
if ((ch >= '0') && (ch <= '9')) return ch - '0';
ch = tolower(ch);
if ((ch >= 'a') && (ch <= 'f')) return ch - 'a' + 10;
return -1;
}
// based on: hostapd src/utils/common.c
int hwaddr_aton(const char *txt, uint8_t *addr) {
int i;
for (i = 0; i < ETH_ALEN; i++) {
int a, b;
a = hex_to_bin(*txt++);
if (a < 0) return -1;
b = hex_to_bin(*txt++);
if (b < 0) return -1;
*addr++ = (a << 4) | b;
// TODO: Should NUL terminator be checked for? Is aa:bb:cc:dd:ee:ff00 valid input?
if (i < (ETH_ALEN - 1) && *txt++ != ':') return -1;
}
return 0;
}
// TODO: Never called in DAWN code. Remove?
#if 0
/* Convert badly formed MAC addresses with single digit element to double digit
** eg 11:2:33:4:55:6 to 11:02:33:04:55:06 */`
int convert_mac(char *in, char *out) {
int i, j = 0;
for (i = 0; i < ETH_ALEN; i++) {
/* Do we have a single-digit element? */
if (in[j + 1] == ':' || in[j + 1] == '\0') {
out[3 * i] = '0';
out[(3 * i) + 1] = toupper(in[j]);
out[(3 * i) + 2] = toupper(in[j + 1]);
j += 2;
} else {
out[3 * i] = toupper(in[j]);
out[(3 * i) + 1] = toupper(in[j + 1]);
out[(3 * i) + 2] = in[j + 2];
j += 3;
}
}
return 0;
}
#endif
void write_mac_to_file(char *path, uint8_t addr[]) {
FILE *f = fopen(path, "a");
if (f == NULL) {
fprintf(stderr,"Error opening mac file!\n");
exit(1);
}
char mac_buf[20];
sprintf(mac_buf, MACSTR, MAC2STR(addr));
fprintf(f, "%s\n", mac_buf);
fclose(f);
}
int rcpi_to_rssi(int rcpi)
{
return rcpi / 2 - 110;
}