diff --git a/src/include/datastorage.h b/src/include/datastorage.h index 70c8592..1bed488 100644 --- a/src/include/datastorage.h +++ b/src/include/datastorage.h @@ -27,12 +27,50 @@ typedef struct probe_entry_s { int counter; } probe_entry; +typedef struct { + uint32_t freq; +} client_request; + +typedef struct client_s { + uint8_t bssid_addr[ETH_ALEN]; + uint8_t client_addr[ETH_ALEN]; + 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; +} client; + // Array + +#define ARRAY_CLIENT_LEN 1000 +#define TIME_THRESHOLD_CLIENT 60 + +struct client_s client_array[ARRAY_CLIENT_LEN]; +pthread_mutex_t client_array_mutex; + +void insert_client_to_array(client entry); + +void client_array_insert(client entry); +client* client_array_delete(client entry); +void print_client_array(); +void print_client_entry(client entry); +void *remove_client_array_thread(void *arg); + #define ARRAY_LEN 1000 struct probe_entry_s probe_array[ARRAY_LEN]; +pthread_mutex_t probe_array_mutex; void insert_to_array(probe_entry entry, int inc_counter); void probe_array_insert(probe_entry entry); @@ -40,10 +78,6 @@ probe_entry* probe_array_delete(probe_entry entry); void print_array(); void *remove_array_thread(void *arg); -pthread_mutex_t probe_array_mutex; - - - diff --git a/src/include/ubus.h b/src/include/ubus.h index 9a5ec03..419c0a0 100644 --- a/src/include/ubus.h +++ b/src/include/ubus.h @@ -7,5 +7,9 @@ int dawn_init_ubus(const char *ubus_socket, char *hostapd_dir); int parse_to_probe_req(struct blob_attr *msg, probe_entry *prob_req); +int parse_to_clients(struct blob_attr *msg); +void *update_clients_thread(void *arg); + +char* hostapd_dir_glob; #endif diff --git a/src/include/utils.h b/src/include/utils.h index 0b38086..f739fae 100644 --- a/src/include/utils.h +++ b/src/include/utils.h @@ -2,6 +2,8 @@ #define __DAWN_UTILS_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] + static int hex_to_bin(char ch) { if ((ch >= '0') && (ch <= '9')) return ch - '0'; diff --git a/src/main.c b/src/main.c index e03d91e..bb2c095 100644 --- a/src/main.c +++ b/src/main.c @@ -35,6 +35,7 @@ int main(int argc, char **argv) { case 'h': snprintf(opt_hostapd_dir, BUFSIZE_DIR, "%s", optarg); printf("hostapd dir: %s\n", opt_hostapd_dir); + hostapd_dir_glob = optarg; default: break; } @@ -53,10 +54,24 @@ int main(int argc, char **argv) { return 1; } + if (pthread_mutex_init(&client_array_mutex, NULL) != 0) { + printf("\n mutex init failed\n"); + return 1; + } + init_socket_runopts(opt_broadcast_ip, opt_broadcast_port, 0); - pthread_t tid; - pthread_create(&tid, NULL, &remove_array_thread, NULL); + pthread_t tid_probe; + pthread_create(&tid_probe, NULL, &remove_array_thread, NULL); + + pthread_t tid_client; + pthread_create(&tid_client, NULL, &remove_client_array_thread, NULL); + + pthread_t tid_get_client; + pthread_create(&tid_get_client, NULL, &update_clients_thread, NULL); + + + //pthread_create(&tid, NULL, &remove_thread, NULL); dawn_init_ubus(ubus_socket, opt_hostapd_dir); diff --git a/src/network/networksocket.c b/src/network/networksocket.c index cf30bdf..1344500 100644 --- a/src/network/networksocket.c +++ b/src/network/networksocket.c @@ -16,7 +16,7 @@ #include "ubus.h" /* Network Defines */ -#define MAX_RECV_STRING 255 +#define MAX_RECV_STRING 1500 #define NET_CONFIG_PATH "/etc/wlancontroller/networkconfig.conf" /* Network Attributes */ @@ -69,13 +69,31 @@ void *receive_msg(void *args) { blob_buf_init(&b, 0); blobmsg_add_json_from_string(&b, recv_string); - recv_string[recv_string_len] = '\0'; + //recv_string[recv_string_len] = '\0'; char *str; str = blobmsg_format_json(b.head, true); - printf("Parsed: '%s'\n", str); - parse_to_probe_req(b.head, &prob_req); - insert_to_array(prob_req, 0); + + /* + TODO: REFACTOR THIS!!! (just workaround) + OTHERWISE NULLPOINTER?! + */ + + if(strstr(str, "clients") != NULL) { + parse_to_clients(b.head); + } else + { + if(parse_to_probe_req(b.head, &prob_req) == 0) + { + insert_to_array(prob_req, 0); + } + } + + //if(parse_to_probe_req(b.head, &prob_req) == 0) + //{ + // insert_to_array(prob_req, 0); + //} + // insert to list //insert_to_list(prob_req, 0); diff --git a/src/storage/datastorage.c b/src/storage/datastorage.c index 31d6788..0871a7b 100644 --- a/src/storage/datastorage.c +++ b/src/storage/datastorage.c @@ -11,7 +11,126 @@ int mac_is_greater(uint8_t addr1[], uint8_t addr2[]); void print_probe_entry(probe_entry entry); void remove_old_probe_entries(time_t current_time, long long int threshold); +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, + client next_entry); +void remove_old_client_entries(time_t current_time, long long int threshold); + int probe_entry_last = -1; +int client_entry_last = -1; + +int client_array_go_next_help(char sort_order[], int i, client entry, + client next_entry) { + switch (sort_order[i]) { + // bssid-mac + case 'b': + return mac_is_greater(entry.bssid_addr, next_entry.bssid_addr) && + mac_is_equal(entry.client_addr, next_entry.client_addr); + break; + + // client-mac + case 'c': + return mac_is_greater(entry.client_addr, next_entry.client_addr); + break; + + // frequency + // mac is 5 ghz or 2.4 ghz? + // case 'f': + // return //entry.freq < next_entry.freq && + // entry.freq < 5000 && + // next_entry.freq >= 5000 && + // //entry.freq < 5 && + // mac_is_equal(entry.client_addr, next_entry.client_addr); + // break; + + // signal strength (RSSI) + //case 's': + // return entry.signal < next_entry.signal && + // mac_is_equal(entry.client_addr, next_entry.client_addr); + // break; + + default: + return 0; + break; + } +} + +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++) { + i &= !(client_array_go_next(sort_order, j, entry, next_entry)); + } + return conditions && client_array_go_next_help(sort_order, i, entry, next_entry); +} + +void client_array_insert(client entry) +{ + if(client_entry_last == -1) + { + client_array[0] = entry; + client_entry_last++; + return; + } + + int i; + for(i = 0; i <= client_entry_last; i++) + { + if(!client_array_go_next("bc", 2, entry, client_array[i])) + { + break; + } + } + for(int j = client_entry_last; j >= i; j--) + { + if(j + 1 <= ARRAY_LEN) + { + client_array[j + 1] = client_array[j]; + } + } + client_array[i] = entry; + + if(client_entry_last < ARRAY_LEN) + { + client_entry_last++; + } +} + +client* client_array_delete(client entry) +{ + + int i; + int found_in_array = 0; + client* tmp = NULL; + + if(client_entry_last == -1) + { + return NULL; + } + + for(i = 0; i <= client_entry_last; i++) + { + if(mac_is_equal(entry.bssid_addr, client_array[i].bssid_addr) && + mac_is_equal(entry.client_addr, client_array[i].client_addr)) + { + found_in_array = 1; + tmp = &client_array[i]; + break; + } + } + + for(int j = i; j <= client_entry_last; j++) + { + client_array[j] = client_array[j + 1]; + } + + if(client_entry_last > -1 && found_in_array) + { + client_entry_last--; + } + return tmp; +} void probe_array_insert(probe_entry entry) @@ -114,6 +233,17 @@ void insert_to_array(probe_entry entry, int inc_counter) pthread_mutex_unlock(&probe_array_mutex); } +void remove_old_client_entries(time_t current_time, long long int threshold) +{ + for(int i = 0; i < probe_entry_last; i++) + { + if (client_array[i].time < current_time - threshold) + { + client_array_delete(client_array[i]); + } + } +} + void remove_old_probe_entries(time_t current_time, long long int threshold) { for(int i = 0; i < probe_entry_last; i++) @@ -136,8 +266,29 @@ void *remove_array_thread(void *arg) { return 0; } +void *remove_client_array_thread(void *arg) { + while (1) { + sleep(TIME_THRESHOLD_CLIENT); + pthread_mutex_lock(&client_array_mutex); + printf("[Thread] : Removing old client entries!\n"); + remove_old_client_entries(time(0), TIME_THRESHOLD_CLIENT); + pthread_mutex_unlock(&client_array_mutex); + } + return 0; +} +void insert_client_to_array(client entry) +{ + pthread_mutex_lock(&client_array_mutex); + entry.time = time(0); + + client_array_delete(entry); + client_array_insert(entry); + + pthread_mutex_unlock(&client_array_mutex); +} + @@ -462,4 +613,25 @@ void print_probe_entry(probe_entry entry) { "%d, counter: %d\n", mac_buf_ap, mac_buf_client, mac_buf_target, entry.signal, entry.freq, entry.counter); +} + +void print_client_entry(client entry) { + char mac_buf_ap[20]; + char mac_buf_client[20]; + + sprintf(mac_buf_ap, "%x:%x:%x:%x:%x:%x", MAC2STR(entry.bssid_addr)); + sprintf(mac_buf_client, "%x:%x:%x:%x:%x:%x", MAC2STR(entry.client_addr)); + + printf("bssid_addr: %s, client_addr: %s, freq: %d\n", + mac_buf_ap, mac_buf_client, entry.freq); +} + +void print_client_array() { + printf("--------Clients------\n"); + printf("Probe Entry Last: %d\n", client_entry_last); + for(int i = 0; i <= client_entry_last; i++) + { + print_client_entry(client_array[i]); + } + printf("------------------\n"); } \ No newline at end of file diff --git a/src/utils/ubus.c b/src/utils/ubus.c index e07e87f..2a6a3d7 100644 --- a/src/utils/ubus.c +++ b/src/utils/ubus.c @@ -33,6 +33,52 @@ static const struct blobmsg_policy prob_policy[__PROB_MAX] = { [PROB_FREQ] = {.name = "freq", .type = BLOBMSG_TYPE_INT32}, }; +enum { + CLIENT_TABLE, + CLIENT_TABLE_BSSID, + CLIENT_TABLE_FREQ, + __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_FREQ] = {.name = "freq", .type = BLOBMSG_TYPE_INT32}, +}; + +enum { + //CLIENT_TABLE, + //CLIENT_TABLE_FREQ, + CLIENT_AUTH, + CLIENT_ASSOC, + CLIENT_AUTHORIZED, + CLIENT_PREAUTH, + CLIENT_WDS, + CLIENT_WMM, + CLIENT_HT, + CLIENT_VHT, + CLIENT_WPS, + CLIENT_MFP, + CLIENT_AID, + __CLIENT_MAX, +}; + +static const struct blobmsg_policy client_policy[__CLIENT_MAX] = { + //[CLIENT_TABLE] = {.name = "clients", .type = BLOBMSG_TYPE_TABLE}, + //[CLIENT_TABLE_FREQ] = {.name = "freq", .type = BLOBMSG_TYPE_INT32}, + [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}, +}; + /* Function Definitions */ static void hostapd_handle_remove(struct ubus_context *ctx, struct ubus_subscriber *s, uint32_t id); @@ -66,6 +112,7 @@ static void hostapd_handle_remove(struct ubus_context *ctx, 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)) @@ -79,11 +126,20 @@ int parse_to_probe_req(struct blob_attr *msg, probe_entry *prob_req) { if (tb[PROB_SIGNAL]) { prob_req->signal = blobmsg_get_u32(tb[PROB_SIGNAL]); + } + else + { + return -1; } if (tb[PROB_FREQ]) { prob_req->freq = blobmsg_get_u32(tb[PROB_FREQ]); } + else + { + return -1; + } + return 0; } @@ -184,24 +240,136 @@ int dawn_init_ubus(const char *ubus_socket, char *hostapd_dir) { return 0; } +static void +dump_client(struct blob_attr **tb, uint8_t client_addr[], const char* bssid_addr, uint32_t freq) +{ + client client_entry; + + hwaddr_aton(bssid_addr, client_entry.bssid_addr); + + memcpy(client_entry.client_addr, client_addr, ETH_ALEN * sizeof(uint8_t)); + + char mac_buf_client[20]; + char mac_buf_ap[20]; + + sprintf(mac_buf_ap, "%x:%x:%x:%x:%x:%x", MAC2STR(client_entry.bssid_addr)); + sprintf(mac_buf_client, "%x:%x:%x:%x:%x:%x", MAC2STR(client_entry.client_addr)); + client_entry.freq = freq; + + 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]); + } + + insert_client_to_array(client_entry); +} + +static void +dump_client_table(struct blob_attr *head, int len, const char* bssid_addr, uint32_t freq) +{ + struct blob_attr *attr; + struct blobmsg_hdr *hdr; + + __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, "%x:%x:%x:%x:%x:%x", 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); + } +} + +int parse_to_clients(struct blob_attr *msg) { + struct blob_attr *tb[__CLIENT_TABLE_MAX]; + + 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]) { + 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])); + } + + return 0; +} + static void ubus_get_clients_cb(struct ubus_request *req, int type, struct blob_attr *msg) { - char *str; if (!msg) return; - str = blobmsg_format_json_indent(msg, true, -1); - printf("%s\n", str); - free(str); + parse_to_clients(msg); + + char *str = blobmsg_format_json(msg, true); + send_string(str); + print_client_array(); + + // TODO SEND CLIENT VIA NETWORK! } static int ubus_get_clients() { - uint32_t id; - int ret = ubus_lookup_id(ctx, "hostapd.wlan0", &id); - if (ret) - return ret; - int timeout = 1; - int ubus_shit = ubus_invoke(ctx, id, "get_clients", NULL, ubus_get_clients_cb, NULL, timeout * 1000); - printf("Ubus Shit: %d", ubus_shit); - return ubus_shit; + DIR *dirp; + struct dirent *entry; + + dirp = opendir(hostapd_dir_glob); // error handling? + while ((entry = readdir(dirp)) != NULL) { + if (entry->d_type == DT_SOCK) { + char hostapd_iface[256]; + uint32_t id; + sprintf(hostapd_iface, "hostapd.%s", entry->d_name); + int ret = ubus_lookup_id(ctx, hostapd_iface, &id); + if(!ret) + { + int timeout = 1; + ubus_invoke(ctx, id, "get_clients", NULL, ubus_get_clients_cb, NULL, timeout * 1000); + } + } + } + return 0; +} + +void *update_clients_thread(void *arg) +{ + while (1){ + sleep(TIME_THRESHOLD_CLIENT); + printf("[Thread] : Updating clients!\n"); + ubus_get_clients(); + } + return 0; } \ No newline at end of file