#include #include #include "dawn_iwinfo.h" #include "memory_utils.h" #include "datastorage.h" #include "mac_utils.h" #include "msghandler.h" #include "ubus.h" #include "test_storage.h" /*** Test Stub Functions - Called by SUT ***/ void ubus_send_beacon_report(struct dawn_mac client, int id) { printf("send_beacon_report() was called...\n"); } int send_set_probe(struct dawn_mac client_addr) { printf("send_set_probe() was called...\n"); return 0; } int wnm_disassoc_imminent(uint32_t id, const struct dawn_mac 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, true); hwaddr_aton(dest_ap, mc->bssid_addr.u8); insert_client_to_array(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) { printf("add_client_update_timer() was called...\n"); } void del_client_interface(uint32_t id, const struct dawn_mac client_addr, uint32_t reason, uint8_t deauth, uint32_t ban_time) { printf("del_client_interface() was called...\n"); } int ubus_send_probe_via_network(struct probe_entry_s *probe_entry) { printf("send_probe_via_network() was called...\n"); return 0; } int get_rssi_iwinfo(struct dawn_mac client_addr) { printf("get_rssi_iwinfo() was called...\n"); return 0; } int get_expected_throughput_iwinfo(struct dawn_mac client_addr) { printf("get_expected_throughput_iwinfo() was called...\n"); return 0; } int get_bandwidth_iwinfo(struct dawn_mac client_addr, float* rx_rate, float* tx_rate) { *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 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 #define HELPER_AP 0x0001 #define HELPER_CLIENT 0x0002 #define HELPER_AUTH_ENTRY 0x0004 #define HELPER_PROBE_ARRAY 0x0008 /*** Local globals ***/ static double base_time; static double last_time; static bool first_time = true; 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) { struct dawn_mac this_mac; *((uint64_t*)(&this_mac.u8)) = m; switch (action & ~HELPER_ACTION_MASK) { case HELPER_AP: ; // Empty statement to allow label before declaration if ((action & HELPER_ACTION_MASK) == HELPER_ACTION_ADD) { ap* ap0 = dawn_malloc(sizeof(struct ap_s)); ap0->bssid_addr = this_mac; insert_to_ap_array(ap0); } else ap_array_delete(ap_array_get_ap(this_mac)); break; case HELPER_CLIENT: ; // Empty statement to allow label before declaration if ((action & HELPER_ACTION_MASK) == HELPER_ACTION_ADD) { client* client0 = dawn_malloc(sizeof(struct client_s)); client0->bssid_addr = this_mac; client0->client_addr = this_mac; insert_client_to_array(client0); } else { client* client0 = client_array_get_client(this_mac); if (client0 != NULL && mac_is_equal_bb(this_mac, client0->client_addr)) client_array_delete(client0, false); } break; case HELPER_PROBE_ARRAY: ; // Empty statement to allow label before declaration probe_entry* probe0 = NULL; if ((action & HELPER_ACTION_MASK) == HELPER_ACTION_ADD) { probe0 = dawn_malloc(sizeof(probe_entry)); probe0->client_addr = this_mac; probe0->bssid_addr = this_mac; insert_to_array(probe0, true, true, true); // TODO: Check bool flags } else { probe0 = probe_array_get_entry(this_mac, this_mac); if (probe0 == NULL) { printf("Can't find entry to delete!\n"); } else { probe_array_delete(probe0); } } break; case HELPER_AUTH_ENTRY: ; // Empty statement to allow label before declaration if ((action & HELPER_ACTION_MASK) == HELPER_ACTION_ADD) { auth_entry* auth_entry0 = dawn_malloc(sizeof(struct auth_entry_s)); auth_entry0->bssid_addr = this_mac; auth_entry0->client_addr = this_mac; insert_to_denied_req_array(auth_entry0, true); // TODO: Check bool flags } else { auth_entry* auth_entry0 = *auth_entry_find_first_entry(this_mac, this_mac); if (auth_entry0 != NULL && mac_is_equal_bb(this_mac, auth_entry0->bssid_addr) && mac_is_equal_bb(this_mac, auth_entry0->client_addr)) denied_req_array_delete(auth_entry0); } break; default: printf("HELPER error - which entity?\n"); ret = -1; } if (m == i1) cont = 0; else m += step; } return ret; } 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; } 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, "%" SCNi64, (int64_t*)v); // TODO: Check making portable for target SoC environemnts? return ret; } static int consume_actions(int argc, char* argv[], int harness_verbosity); static int consume_actions(int argc, char* argv[], int harness_verbosity) { int ret = 0; int args_required = 0; // Suppress compiler warming by assigning initial value int curr_arg = 0; while (curr_arg < argc && ret == 0) { if ((strcmp(*argv, "time") == 0) || (strcmp(*argv, "elapsed") == 0) || (strcmp(*argv, "elapsed_msg") == 0)) // "time" is deprecated to avoid confusion with "faketime" commands { if (strcmp(*argv, "elapsed_msg") == 0) { args_required = 2; } else { args_required = 1; } if (curr_arg + args_required <= argc) { struct timespec spec; double curr_time; //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; } if (strcmp(*argv, "elapsed_msg") == 0) { printf("Elapsed time (%s): base=%fms, last=%fms\n", *(argv + 1), curr_time - base_time, curr_time - last_time); } else { printf("Elapsed time: base=%fms, last=%fms\n", curr_time - base_time, curr_time - last_time); } last_time = curr_time; } } else if (strcmp(*argv, "memleak") == 0) { args_required = 1; char* leaky = dawn_malloc(10); strcpy(leaky, "LEAKED"); // Force use of memory to avoid unused error } else if (strcmp(*argv, "memaudit") == 0) { args_required = 1; dawn_memory_audit(); } 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: %" PRId64 "\n", (int64_t)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; print_ap_array(); } else if (strcmp(*argv, "probe_show") == 0) { args_required = 1; print_probe_array(); } else if (strcmp(*argv, "client_show") == 0) { args_required = 1; print_client_array(); } else if (strcmp(*argv, "auth_entry_show") == 0) { args_required = 1; printf("--------APs------\n"); for (auth_entry *i = denied_req_set; i != NULL; i = i->next_auth) { print_auth_entry(i); } printf("------------------\n"); } else if (strcmp(*argv, "ap_add_auto") == 0) { args_required = 3; if (curr_arg + args_required <= argc) { ret = array_auto_helper(HELPER_AP | HELPER_ACTION_ADD, atoi(*(argv + 1)), atoi(*(argv + 2))); } } else if (strcmp(*argv, "ap_del_auto") == 0) { args_required = 3; if (curr_arg + args_required <= argc) { ret = array_auto_helper(HELPER_AP | HELPER_ACTION_DEL, atoi(*(argv + 1)), atoi(*(argv + 2))); } } else if (strcmp(*argv, "probe_add_auto") == 0) { args_required = 3; if (curr_arg + args_required <= argc) { ret = array_auto_helper(HELPER_PROBE_ARRAY | HELPER_ACTION_ADD, atoi(*(argv + 1)), atoi(*(argv + 2))); } } else if (strcmp(*argv, "probe_del_auto") == 0) { args_required = 3; if (curr_arg + args_required <= argc) { ret = array_auto_helper(HELPER_PROBE_ARRAY | HELPER_ACTION_DEL, atoi(*(argv + 1)), atoi(*(argv + 2))); } } else if (strcmp(*argv, "client_add_auto") == 0) { args_required = 3; if (curr_arg + args_required <= argc) { ret = array_auto_helper(HELPER_CLIENT | HELPER_ACTION_ADD, atoi(*(argv + 1)), atoi(*(argv + 2))); } } else if (strcmp(*argv, "client_del_auto") == 0) { args_required = 3; if (curr_arg + args_required <= argc) { ret = array_auto_helper(HELPER_CLIENT | HELPER_ACTION_DEL, atoi(*(argv + 1)), atoi(*(argv + 2))); } } else if (strcmp(*argv, "auth_entry_add_auto") == 0) { args_required = 3; if (curr_arg + args_required <= argc) { ret = array_auto_helper(HELPER_AUTH_ENTRY | HELPER_ACTION_ADD, atoi(*(argv + 1)), atoi(*(argv + 2))); } } else if (strcmp(*argv, "auth_entry_del_auto") == 0) { args_required = 3; if (curr_arg + args_required <= argc) { 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) { struct dawn_mac mac0; hwaddr_aton(argv[1], mac0.u8); insert_to_maclist(mac0); } } else if (strcmp(*argv, "macget") == 0) { args_required = 2; if (curr_arg + args_required <= argc) { struct dawn_mac mac0; hwaddr_aton(argv[1], mac0.u8); printf("Looking for MAC %s - result %d\n", argv[1], mac_in_maclist(mac0)); } } else if (strcmp(*argv, "ap") == 0) { ap *ap0 = dawn_malloc(sizeof(struct ap_s)); 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)) hwaddr_aton(fn + 6, ap0->bssid_addr.u8); 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 dawn_free(ap0); } else if (strcmp(*argv, "client") == 0) { client *cl0 = dawn_malloc(sizeof(struct client_s)); //TODO: NULL test 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)) hwaddr_aton(fn + 6, cl0->bssid_addr.u8); else if (!strncmp(fn, "client=", 7)) hwaddr_aton(fn + 7, cl0->client_addr.u8); 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 = NULL; struct dawn_mac bmac; struct dawn_mac cmac; int key_check = 1 | 2; 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... // bssid and client must be specified first so we can work out if we need a new entry or update an old one if (false); // Hack to allow easy paste of generated code else if (!strncmp(fn, "bssid=", 6)) { hwaddr_aton(fn + 6, bmac.u8); key_check ^= ~1; } else if (!strncmp(fn, "client=", 7)) { hwaddr_aton(fn + 7, cmac.u8); key_check ^= ~2; } else if (!strncmp(fn, "target=", 7)) hwaddr_aton(fn + 7, pr0->target_addr.u8); 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 (key_check == 0) { key_check = -1; // See if this entry already exists pr0 = probe_array_get_entry(bmac, cmac); // If not, create and initialise it if (pr0 != NULL) { if (harness_verbosity > 1) printf("probe: updating existing entry...\n"); pr0->counter++; } else { if (harness_verbosity > 1) printf("probe: creating new entry...\n"); // MUSTDO: Check all new dawn_malloc() returns pr0 = dawn_malloc(sizeof(probe_entry)); pr0->bssid_addr = bmac; pr0->client_addr = cmac; memset(pr0->target_addr.u8, 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; insert_to_array(pr0, true, true, true); } } if (ret == 0) args_required++; } } else if (strcmp(*argv, "auth_entry") == 0) { auth_entry *au0 = dawn_malloc(sizeof(struct auth_entry_s)); memset(au0->bssid_addr.u8, 0, ETH_ALEN); memset(au0->client_addr.u8, 0, ETH_ALEN); memset(au0->target_addr.u8, 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)) hwaddr_aton(fn + 6, au0->bssid_addr.u8); else if (!strncmp(fn, "client=", 7)) hwaddr_aton(fn + 7, au0->client_addr.u8); else if (!strncmp(fn, "target=", 7)) hwaddr_aton(fn + 7, au0->target_addr.u8); 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; struct dawn_mac kick_mac; uint32_t kick_id; hwaddr_aton(argv[1], kick_mac.u8); load_u32(&kick_id, argv[2]); while ((kick_clients(ap_array_get_ap(kick_mac), kick_id) != 0) && safety_count--); } } else if (strcmp(*argv, "better_ap_available") == 0) { args_required = 4; if (curr_arg + args_required <= argc) { struct dawn_mac bssid_mac; struct dawn_mac client_mac; uint32_t autokick; int tr = 9999; // Tamper evident value hwaddr_aton(argv[1], bssid_mac.u8); hwaddr_aton(argv[2], client_mac.u8); 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(ap_array_get_ap(bssid_mac), client_mac, nb); } else { tr = better_ap_available(ap_array_get_ap(bssid_mac), client_mac, NULL); } 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) { struct dawn_mac client_mac; struct dawn_mac bssid_mac; hwaddr_aton(argv[2], client_mac.u8); hwaddr_aton(argv[1], bssid_mac.u8); probe_entry *pr0 = probe_array_get_entry(bssid_mac, client_mac); if (pr0 == NULL ) { printf("eval_probe_metric: Can't find probe entry!\n"); } else { ap* ap_entry = ap_array_get_ap(pr0->bssid_addr); int this_metric = eval_probe_metric(pr0, ap_entry); printf("eval_probe_metric: Returned %d\n", this_metric); } } } else { args_required = 1; printf("COMMAND \"%s\": Unknown - stopping!\n", *argv); ret = -1; } curr_arg += args_required; if (curr_arg <= argc) { // 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 (harness_verbosity > 0) { if (!(faketime & 1)) printf("Faketime: tick %" PRId64 "...\n", (int64_t)faketime); else printf("Faketime: tock %" PRId64 "...\n", (int64_t)faketime); } } } else { // There aren't enough args left to give the parameters of the current action printf("Commands are mangled at: \"%s\"!\n", *argv); ret = -1; } } return ret; } #define MAX_LINE_ARGS 20 static int process_script_line(char* line, size_t len, int harness_verbosity); static int process_script_line(char* line, size_t len, int harness_verbosity) { int argc = 0; char* argv[MAX_LINE_ARGS]; bool in_white = true; 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_nul) { if (*line == '#') { //printf("Blanking 0x%02X...\n", *line); force_nul = true; // Untested - might bring parsing to faster end... // len = 1; } //printf("Zapping 0x%02X...\n", *line); *line = '\0'; in_white = true; } else { if (in_white) { //printf("Marking 0x%02X...\n", *line); if (argc == MAX_LINE_ARGS) { printf("ERROR: Script line exceeds permitted arg count!\n"); ret = -1; } else { argv[argc] = line; argc++; in_white = false; } } } len--; line++; } if (!ret) ret = consume_actions(argc, argv, harness_verbosity); return ret; } int main(int argc, char* argv[]) { FILE* fp = NULL; char* line = NULL; size_t len = 0; ssize_t read; int ret = 0; int harness_verbosity = 1; printf("DAWN datastorage.c test harness...\n\n"); if ((argc == 1) || !strcmp(*(argv + 1), "help") || !strcmp(*(argv + 1), "--help") || !strcmp(*(argv + 1), "-h")) { printf("Usage: %s [commands]\n\n", *argv); printf(" [action [arg...]]... : Read test actions from command line\n"); printf(" --script [file]... : Read test script from file(s) (NB: \"-\" is a valid name\n"); printf(" indicating STDIN) {-s}\n"); printf(" - : Read test script from STDIN (and remaining arguments\n"); printf(" as script file names)\n"); printf(" --help : This help message {-h, help}\n"); printf("NB: Contents of {braces} indicate equivalent command\n"); } else { strcpy(sort_string, "bcfs"); init_mutex(); // Step past command name on args, ie argv[0] argc--; argv++; if (!strcmp(*argv, "--quiet") || !strcmp(*argv, "-q")) { harness_verbosity = 0; argc--; argv++; } if (!strcmp(*argv, "--verbose") || !strcmp(*argv, "-v")) { harness_verbosity = 2; argc--; argv++; } if (!strcmp(*argv, "--script") || !strcmp(*argv, "-s") || !strcmp(*argv, "-")) { if (!strcmp(*argv, "--script") || !strcmp(*argv, "-s")) { argc--; argv++; } // Read script from file[s] while (argc > 0 && ret == 0) { if (!strcmp(*argv, "-")) { fp = stdin; if (harness_verbosity > 0) printf("Consuming script from STDIN\n"); } else { fp = fopen(*argv, "r"); if (fp == NULL) { printf("Error opening script file: %s\n", *argv); ret = -1; } else { if (harness_verbosity > 0) printf("Consuming script file: %s\n", *argv); } } if (ret == 0) { read = getline(&line, &len, fp); while (!ret && read != -1) { if (harness_verbosity > 0) printf("Processing: %s\n", line); ret = process_script_line(line, read, harness_verbosity); if (!ret) read = getline(&line, &len, fp); } if (fp && fp != stdin) { fclose(fp); fp = NULL; } if (line) { dawn_free(line); line = NULL; } } argc--; argv++; } } else { // Take direct input on command line ret = consume_actions(argc, argv, harness_verbosity); } destroy_mutex(); } if (harness_verbosity > 0) printf("\nDAWN datastorage.c test harness - finshed. \n"); return ret; }