first version

This commit is contained in:
Polynomialdivision 2020-03-23 19:18:13 +01:00
commit f03f55ff92
28 changed files with 5682 additions and 0 deletions

356
src/utils/dawn_iwinfo.c Normal file
View file

@ -0,0 +1,356 @@
#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]
int call_iwinfo(char *client_addr);
int parse_rssi(char *iwinfo_string);
int get_rssi(const char *ifname, uint8_t *client_addr);
int get_bandwidth(const char *ifname, uint8_t *client_addr, float *rx_rate, float *tx_rate);
#define IWINFO_BUFSIZE 24 * 1024
#define IWINFO_ESSID_MAX_SIZE 32
int compare_essid_iwinfo(__uint8_t *bssid_addr, __uint8_t *bssid_addr_to_compare) {
const struct iwinfo_ops *iw;
char mac_buf[20];
char mac_buf_to_compare[20];
sprintf(mac_buf, MACSTR, MAC2STR(bssid_addr));
sprintf(mac_buf_to_compare, MACSTR, MAC2STR(bssid_addr_to_compare));
DIR *dirp;
struct dirent *entry;
dirp = opendir(hostapd_dir_glob); // error handling?
if (!dirp) {
fprintf(stderr, "[COMPARE ESSID] Failed to open %s\n", hostapd_dir_glob);
return 0;
}
char *essid = NULL;
char *essid_to_compare = NULL;
char buf_essid[IWINFO_ESSID_MAX_SIZE + 1] = {0};
char buf_essid_to_compare[IWINFO_ESSID_MAX_SIZE + 1] = {0};
while ((entry = readdir(dirp)) != NULL && (essid == NULL || essid_to_compare == NULL)) {
if (entry->d_type == DT_SOCK) {
iw = iwinfo_backend(entry->d_name);
static char buf_bssid[18] = {0};
if (iw->bssid(entry->d_name, buf_bssid))
snprintf(buf_bssid, sizeof(buf_bssid), "00:00:00:00:00:00");
if (strcmp(mac_buf, buf_bssid) == 0) {
if (iw->ssid(entry->d_name, buf_essid))
memset(buf_essid, 0, sizeof(buf_essid));
essid = buf_essid;
}
if (strcmp(mac_buf_to_compare, buf_bssid) == 0) {
if (iw->ssid(entry->d_name, buf_essid_to_compare))
memset(buf_essid_to_compare, 0, sizeof(buf_essid_to_compare));
essid_to_compare = buf_essid_to_compare;
}
}
}
closedir(dirp);
printf("Comparing: %s with %s\n", essid, essid_to_compare);
if (essid == NULL || essid_to_compare == NULL) {
return -1;
}
if (strcmp(essid, essid_to_compare) == 0) {
return 0;
}
return -1;
}
int get_bandwidth_iwinfo(__uint8_t *client_addr, float *rx_rate, float *tx_rate) {
DIR *dirp;
struct dirent *entry;
dirp = opendir(hostapd_dir_glob); // error handling?
if (!dirp) {
fprintf(stderr, "[BANDWITH INFO] Failed to open %s\n", hostapd_dir_glob);
return 0;
}
int sucess = 0;
while ((entry = readdir(dirp)) != NULL) {
if (entry->d_type == DT_SOCK) {
if (get_bandwidth(entry->d_name, client_addr, rx_rate, tx_rate)) {
sucess = 1;
break;
}
}
}
closedir(dirp);
return sucess;
}
int get_bandwidth(const char *ifname, uint8_t *client_addr, float *rx_rate, float *tx_rate) {
int i, len;
char buf[IWINFO_BUFSIZE];
struct iwinfo_assoclist_entry *e;
const struct iwinfo_ops *iw;
iw = iwinfo_backend(ifname);
if (iw->assoclist(ifname, buf, &len)) {
fprintf(stderr, "No information available\n");
iwinfo_finish();
return 0;
} else if (len <= 0) {
fprintf(stderr, "No station connected\n");
iwinfo_finish();
return 0;
}
for (i = 0; i < len; i += sizeof(struct iwinfo_assoclist_entry)) {
e = (struct iwinfo_assoclist_entry *) &buf[i];
if (mac_is_equal(client_addr, e->mac)) {
*rx_rate = e->rx_rate.rate / 1000;
*tx_rate = e->tx_rate.rate / 1000;
return 1;
}
}
return 0;
}
int get_rssi_iwinfo(__uint8_t *client_addr) {
DIR *dirp;
struct dirent *entry;
dirp = opendir(hostapd_dir_glob); // error handling?
if (!dirp) {
fprintf(stderr, "[RSSI INFO] No hostapd sockets!\n");
return INT_MIN;
}
int rssi = INT_MIN;
while ((entry = readdir(dirp)) != NULL) {
if (entry->d_type == DT_SOCK) {
rssi = get_rssi(entry->d_name, client_addr);
if (rssi != INT_MIN)
break;
}
}
closedir(dirp);
return rssi;
}
int get_rssi(const char *ifname, uint8_t *client_addr) {
int i, len;
char buf[IWINFO_BUFSIZE];
struct iwinfo_assoclist_entry *e;
const struct iwinfo_ops *iw;
iw = iwinfo_backend(ifname);
if (iw->assoclist(ifname, buf, &len)) {
fprintf(stderr, "No information available\n");
iwinfo_finish();
return INT_MIN;
} else if (len <= 0) {
fprintf(stderr, "No station connected\n");
iwinfo_finish();
return INT_MIN;
}
for (i = 0; i < len; i += sizeof(struct iwinfo_assoclist_entry)) {
e = (struct iwinfo_assoclist_entry *) &buf[i];
if (mac_is_equal(client_addr, e->mac))
return e->signal;
}
iwinfo_finish();
return INT_MIN;
}
int get_expected_throughput_iwinfo(__uint8_t *client_addr) {
DIR *dirp;
struct dirent *entry;
dirp = opendir(hostapd_dir_glob); // error handling?
if (!dirp) {
fprintf(stderr, "[RSSI INFO] Failed to open dir:%s\n", hostapd_dir_glob);
return INT_MIN;
}
int exp_thr = INT_MIN;
while ((entry = readdir(dirp)) != NULL) {
if (entry->d_type == DT_SOCK) {
exp_thr = get_expected_throughput(entry->d_name, client_addr);
if (exp_thr != INT_MIN)
break;
}
}
closedir(dirp);
return exp_thr;
}
int get_expected_throughput(const char *ifname, uint8_t *client_addr) {
int i, len;
char buf[IWINFO_BUFSIZE];
struct iwinfo_assoclist_entry *e;
const struct iwinfo_ops *iw;
iw = iwinfo_backend(ifname);
if (iw->assoclist(ifname, buf, &len)) {
fprintf(stderr, "No information available\n");
return INT_MIN;
} else if (len <= 0) {
fprintf(stderr, "No station connected\n");
return INT_MIN;
}
for (i = 0; i < len; i += sizeof(struct iwinfo_assoclist_entry)) {
e = (struct iwinfo_assoclist_entry *) &buf[i];
if (mac_is_equal(client_addr, e->mac))
return e->thr;
}
iwinfo_finish();
return INT_MIN;
}
int get_bssid(const char *ifname, uint8_t *bssid_addr) {
const struct iwinfo_ops *iw;
iw = iwinfo_backend(ifname);
static char buf[18] = { 0 };
if (iw->bssid(ifname, buf))
snprintf(buf, sizeof(buf), "00:00:00:00:00:00");
hwaddr_aton(buf,bssid_addr);
iwinfo_finish();
return 0;
}
int get_ssid(const char *ifname, char* ssid) {
const struct iwinfo_ops *iw;
char buf[IWINFO_ESSID_MAX_SIZE+1] = { 0 };
iw = iwinfo_backend(ifname);
if (iw->ssid(ifname, buf))
memset(buf, 0, sizeof(buf));
memcpy(ssid, buf, (SSID_MAX_LEN) * sizeof(char));
strcpy(ssid, buf);
return 0;
}
int get_channel_utilization(const char *ifname, uint64_t *last_channel_time, uint64_t *last_channel_time_busy) {
int len;
const struct iwinfo_ops *iw;
char buf[IWINFO_BUFSIZE];
struct iwinfo_survey_entry *e;
int ret = 0;
iw = iwinfo_backend(ifname);
int freq;
if (iw->frequency(ifname, &freq))
{
return 0;
}
if (iw->survey(ifname, buf, &len))
{
fprintf(stderr, "Survey not possible!\n\n");
return 0;
}
else if (len <= 0)
{
fprintf(stderr, "No survey results\n\n");
return 0;
}
for (int i = 0, x = 1; i < len; i += sizeof(struct iwinfo_survey_entry), x++)
{
e = (struct iwinfo_survey_entry *) &buf[i];
if(e->mhz == freq)
{
uint64_t dividend = e->busy_time - *last_channel_time_busy;
uint64_t divisor = e->active_time - *last_channel_time;
*last_channel_time = e->active_time;
*last_channel_time_busy = e->busy_time;
if(divisor)
ret = (int)(dividend * 255 / divisor);
break;
}
}
iwinfo_finish();
return ret;
}
int support_ht(const char *ifname) {
const struct iwinfo_ops *iw;
iw = iwinfo_backend(ifname);
int htmodes = 0;
if (iw->htmodelist(ifname, &htmodes))
{
printf("No HT mode information available\n");
return 0;
}
uint32_t ht_support_bitmask = (1 << 0) | (1 << 2);
int ret = htmodes & ht_support_bitmask ? 1 : 0;
iwinfo_finish();
return ret;
}
int support_vht(const char *ifname) {
const struct iwinfo_ops *iw;
iw = iwinfo_backend(ifname);
int htmodes = 0;
if (iw->htmodelist(ifname, &htmodes))
{
fprintf(stderr, "No VHT mode information available\n");
return 0;
}
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();
return ret;
}

202
src/utils/dawn_uci.c Normal file
View file

@ -0,0 +1,202 @@
#include <uci.h>
#include <stdlib.h>
#include <datastorage.h>
#include "dawn_uci.h"
static struct uci_context *uci_ctx;
static struct uci_package *uci_pkg;
// why is this not included in uci lib...?!
// found here: https://github.com/br101/pingcheck/blob/master/uci.c
static int uci_lookup_option_int(struct uci_context *uci, struct uci_section *s,
const char *name) {
const char *str = uci_lookup_option_string(uci, s, name);
return str == NULL ? -1 : atoi(str);
}
struct time_config_s uci_get_time_config() {
struct time_config_s ret;
struct uci_element *e;
uci_foreach_element(&uci_pkg->sections, e)
{
struct uci_section *s = uci_to_section(e);
if (strcmp(s->type, "times") == 0) {
ret.update_client = uci_lookup_option_int(uci_ctx, s, "update_client");
ret.remove_client = uci_lookup_option_int(uci_ctx, s, "remove_client");
ret.remove_probe = uci_lookup_option_int(uci_ctx, s, "remove_probe");
ret.update_hostapd = uci_lookup_option_int(uci_ctx, s, "update_hostapd");
ret.remove_ap = uci_lookup_option_int(uci_ctx, s, "remove_ap");
ret.update_tcp_con = uci_lookup_option_int(uci_ctx, s, "update_tcp_con");
ret.denied_req_threshold = uci_lookup_option_int(uci_ctx, s, "denied_req_threshold");
ret.update_chan_util = uci_lookup_option_int(uci_ctx, s, "update_chan_util");
return ret;
}
}
return ret;
}
struct probe_metric_s uci_get_dawn_metric() {
struct probe_metric_s ret;
struct uci_element *e;
uci_foreach_element(&uci_pkg->sections, e)
{
struct uci_section *s = uci_to_section(e);
if (strcmp(s->type, "metric") == 0) {
ret.ap_weight = uci_lookup_option_int(uci_ctx, s, "ap_weight");
ret.kicking = uci_lookup_option_int(uci_ctx, s, "kicking");
ret.ht_support = uci_lookup_option_int(uci_ctx, s, "ht_support");
ret.vht_support = uci_lookup_option_int(uci_ctx, s, "vht_support");
ret.no_ht_support = uci_lookup_option_int(uci_ctx, s, "no_ht_support");
ret.no_vht_support = uci_lookup_option_int(uci_ctx, s, "no_vht_support");
ret.rssi = uci_lookup_option_int(uci_ctx, s, "rssi");
ret.freq = uci_lookup_option_int(uci_ctx, s, "freq");
ret.rssi_val = uci_lookup_option_int(uci_ctx, s, "rssi_val");
ret.chan_util = uci_lookup_option_int(uci_ctx, s, "chan_util");
ret.max_chan_util = uci_lookup_option_int(uci_ctx, s, "max_chan_util");
ret.chan_util_val = uci_lookup_option_int(uci_ctx, s, "chan_util_val");
ret.max_chan_util_val = uci_lookup_option_int(uci_ctx, s, "max_chan_util_val");
ret.min_probe_count = uci_lookup_option_int(uci_ctx, s, "min_probe_count");
ret.low_rssi = uci_lookup_option_int(uci_ctx, s, "low_rssi");
ret.low_rssi_val = uci_lookup_option_int(uci_ctx, s, "low_rssi_val");
ret.bandwith_threshold = uci_lookup_option_int(uci_ctx, s, "bandwith_threshold");
ret.use_station_count = uci_lookup_option_int(uci_ctx, s, "use_station_count");
ret.eval_probe_req = uci_lookup_option_int(uci_ctx, s, "eval_probe_req");
ret.eval_auth_req = uci_lookup_option_int(uci_ctx, s, "eval_auth_req");
ret.eval_assoc_req = uci_lookup_option_int(uci_ctx, s, "eval_assoc_req");
ret.deny_auth_reason = uci_lookup_option_int(uci_ctx, s, "deny_auth_reason");
ret.deny_assoc_reason = uci_lookup_option_int(uci_ctx, s, "deny_assoc_reason");
ret.max_station_diff = uci_lookup_option_int(uci_ctx, s, "max_station_diff");
ret.use_driver_recog = uci_lookup_option_int(uci_ctx, s, "use_driver_recog");
ret.min_kick_count = uci_lookup_option_int(uci_ctx, s, "min_number_to_kick");
ret.chan_util_avg_period = uci_lookup_option_int(uci_ctx, s, "chan_util_avg_period");
return ret;
}
}
return ret;
}
struct network_config_s uci_get_dawn_network() {
struct network_config_s ret;
struct uci_element *e;
uci_foreach_element(&uci_pkg->sections, e)
{
struct uci_section *s = uci_to_section(e);
if (strcmp(s->type, "network") == 0) {
ret.broadcast_ip = uci_lookup_option_string(uci_ctx, s, "broadcast_ip");
ret.broadcast_port = uci_lookup_option_int(uci_ctx, s, "broadcast_port");
ret.bool_multicast = uci_lookup_option_int(uci_ctx, s, "multicast");
ret.shared_key = uci_lookup_option_string(uci_ctx, s, "shared_key");
ret.iv = uci_lookup_option_string(uci_ctx, s, "iv");
ret.network_option = uci_lookup_option_int(uci_ctx, s, "network_option");
ret.tcp_port = uci_lookup_option_int(uci_ctx, s, "tcp_port");
ret.use_symm_enc = uci_lookup_option_int(uci_ctx, s, "use_symm_enc");
ret.collision_domain = uci_lookup_option_int(uci_ctx, s, "collision_domain");
ret.bandwidth = uci_lookup_option_int(uci_ctx, s, "bandwidth");
return ret;
}
}
return ret;
}
const char *uci_get_dawn_hostapd_dir() {
struct uci_element *e;
uci_foreach_element(&uci_pkg->sections, e)
{
struct uci_section *s = uci_to_section(e);
if (strcmp(s->type, "hostapd") == 0) {
return uci_lookup_option_string(uci_ctx, s, "hostapd_dir");
}
}
return NULL;
}
const char *uci_get_dawn_sort_order() {
struct uci_element *e;
uci_foreach_element(&uci_pkg->sections, e)
{
struct uci_section *s = uci_to_section(e);
if (strcmp(s->type, "ordering") == 0) {
return uci_lookup_option_string(uci_ctx, s, "sort_order");
}
}
return NULL;
}
int uci_reset()
{
uci_unload(uci_ctx, uci_pkg);
uci_load(uci_ctx, "dawn", &uci_pkg);
return 0;
}
int uci_init() {
struct uci_context *ctx = uci_ctx;
if (!ctx) {
ctx = uci_alloc_context();
uci_ctx = ctx;
ctx->flags &= ~UCI_FLAG_STRICT;
} else {
// shouldn't happen?
uci_pkg = uci_lookup_package(ctx, "dawn");
if (uci_pkg)
uci_unload(ctx, uci_pkg);
}
if (uci_load(ctx, "dawn", &uci_pkg))
return -1;
return 1;
}
int uci_clear() {
if (uci_pkg != NULL) {
uci_unload(uci_ctx, uci_pkg);
}
if (uci_ctx != NULL) {
uci_free_context(uci_ctx);
}
return 1;
}
int uci_set_network(char* uci_cmd)
{
struct uci_ptr ptr;
int ret = UCI_OK;
struct uci_context *ctx;
ctx = uci_alloc_context();
ctx->flags |= UCI_FLAG_STRICT;
if (uci_lookup_ptr(ctx, &ptr, uci_cmd, 1) != UCI_OK) {
return 1;
}
ret = uci_set(ctx, &ptr);
if (uci_lookup_ptr(ctx, &ptr, "dawn", 1) != UCI_OK) {
return 1;
}
if (uci_commit(ctx, &ptr.p, 0) != UCI_OK) {
fprintf(stderr, "Failed to commit UCI cmd: %s\n", uci_cmd);
}
return ret;
}

View file

@ -0,0 +1,11 @@
#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);
}

1619
src/utils/ubus.c Normal file

File diff suppressed because it is too large Load diff

80
src/utils/utils.c Normal file
View file

@ -0,0 +1,80 @@
#include "utils.h"
#include "ubus.h"
int string_is_greater(uint8_t *str, uint8_t *str_2) {
int length_1 = strlen((char *) str);
int length_2 = strlen((char *) str_2);
int length = length_1 < length_2 ? length_1 : length_2;
for (int i = 0; i < length; i++) {
if (str[i] > str_2[i]) {
return 1;
}
if (str[i] < str_2[i]) {
return 0;
}
}
return length_1 > length_2;
}
// source: https://elixir.bootlin.com/linux/v4.9/source/lib/hexdump.c#L28
int hex_to_bin(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;
if (i < 5 && *txt++ != ':') return -1;
}
return 0;
}
int convert_mac(char *in, char *out) {
int i, j = 0;
for (i = 0; i < 6; i++) {
if (in[j + 1] != ':' && in[j + 1] != '\0') {
out[3 * i] = toupper(in[j]);
out[(3 * i) + 1] = toupper(in[j + 1]);
out[(3 * i) + 2] = in[j + 2];
j += 3;
} else {
out[3 * i] = '0';
out[(3 * i) + 1] = toupper(in[j]);
out[(3 * i) + 2] = toupper(in[j + 1]);
j += 2;
}
}
return 0;
}
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);
}