diff --git a/src/core/agent.c b/src/core/agent.c index 102528b31cef307cb65161e5a8c5f926201777a8..defc7d25e56c9a0144898a3621017b8bc590fcdd 100644 --- a/src/core/agent.c +++ b/src/core/agent.c @@ -2600,6 +2600,8 @@ static void parse_radio(struct ubus_request *req, int type, struct blob_attr *msg) { struct wifi_radio_element *re = (struct wifi_radio_element *)req->priv; + fprintf(stdout, "%s ---> %s\n", __func__, re->name); + int rem, remm, rem1, j = 0, i = 0; struct blob_attr *tb[11]; static const struct blobmsg_policy radio_attr[11] = { [0] = { .name = "isup", .type = BLOBMSG_TYPE_BOOL }, @@ -2642,46 +2644,78 @@ static void parse_radio(struct ubus_request *req, int type, re->rx_streams = blobmsg_get_u8(tb[4]); if (tb[5]) { - int rem, rem1, i = 0; - struct blob_attr *cur; - + struct blob_attr *cur, *cur1; re->num_supp_opclass = blobmsg_check_array(tb[5], BLOBMSG_TYPE_TABLE); re->supp_opclass = calloc(re->num_supp_opclass, sizeof(*re->supp_opclass)); if (!re->supp_opclass) { - fprintf(stderr, "|%s:%d| out of memory!\n", __func__, __LINE__); + dbg("|%s:%d| out of memory!\n", __func__, __LINE__); return; } - + re->num_scanresult = 1; + re->scanlist = calloc(re->num_scanresult, sizeof(*re->scanlist)); + if (!re->scanlist) { + dbg("|%s:%d| out of memory!\n", __func__, __LINE__); + return; + } + re->scanlist->num_opclass_scanned = re->num_supp_opclass; + re->scanlist->opclass_scanlist = calloc(re->scanlist->num_opclass_scanned, sizeof(struct wifi_scanres_opclass_element)); + if (!re->scanlist->opclass_scanlist) { + dbg("|%s:%d| out of memory!\n", __func__, __LINE__); + return; + } + // Iterate through all supp_channels (opclasses) in radio + // fprintf(stderr, "|%s:%d| DEBUG!\n", __func__, __LINE__); // DEBUG blobmsg_for_each_attr(cur, tb[5], rem) { - struct blob_attr *data[3], *cur1; - static const struct blobmsg_policy supp_attrs[3] = { + // fprintf(stderr, "|%s:%d| DEBUG!\n", __func__, __LINE__); // DEBUG + struct blob_attr *data[4]; + static const struct blobmsg_policy supp_attrs[4] = { [0] = { .name = "opclass", .type = BLOBMSG_TYPE_INT32 }, [1] = { .name = "txpower", .type = BLOBMSG_TYPE_INT32 }, - [2] = { .name = "channels", .type = BLOBMSG_TYPE_ARRAY } + [2] = { .name = "channels", .type = BLOBMSG_TYPE_ARRAY }, + [3] = { .name = "bandwidth", .type = BLOBMSG_TYPE_INT32} }; int k = 0; if (blobmsg_type(cur) != BLOBMSG_TYPE_TABLE) continue; - blobmsg_parse(supp_attrs, 3, data, blobmsg_data(cur), + blobmsg_parse(supp_attrs, 4, data, blobmsg_data(cur), blobmsg_data_len(cur)); - - if (!data[0] || !data[1] || i >= re->num_supp_opclass) + // for whatever reason it may continue parsing next object + if (!data[0] || !data[1] || !data[2] || !data[3] || i >= re->num_supp_opclass) continue; - re->supp_opclass[i].id = (uint8_t) blobmsg_get_u32(data[0]); re->supp_opclass[i].max_txpower = (int8_t) blobmsg_get_u32(data[1]); - if (data[2]) - re->supp_opclass[i].num_supported_channels = blobmsg_check_array(data[2], BLOBMSG_TYPE_INT32); + if (data[2]) { + struct blob_attr *attr; + j = 0; // reset iterator through channels for current opclass + re->supp_opclass[i].num_supported_channels = blobmsg_check_array(data[2], BLOBMSG_TYPE_INT32); + re->scanlist->opclass_scanlist[i].num_channels_scanned = blobmsg_check_array(data[2], BLOBMSG_TYPE_INT32); //lejla + //fprintf(stdout,"\t debug num_of_ch: %d\n", re->scanlist->opclass_scanlist[i].num_channels_scanned); + re->scanlist->opclass_scanlist[i].channel_scanlist = calloc(re->scanlist->opclass_scanlist[i].num_channels_scanned, + sizeof(struct wifi_scanres_channel_element)); + if (!re->scanlist->opclass_scanlist[i].channel_scanlist) { + dbg("|%s:%d| out of memory!\n", __func__, __LINE__); + return; + } + //fprintf(stdout, "\t debug %s %d\n", __func__, __LINE__); + re->scanlist->opclass_scanlist[i].opclass = blobmsg_get_u32(data[0]); + // Iterate through all channels of the opclass + blobmsg_for_each_attr(attr, data[2], remm) { + if (blobmsg_type(attr) != BLOBMSG_TYPE_INT32) + continue; + re->scanlist->opclass_scanlist[i].channel_scanlist[j].channel = blobmsg_get_u32(attr); + j++; + } + //fprintf(stdout, "\t debug %s %d\n", __func__, __LINE__); + } re->supp_opclass[i].supp_chanlist = calloc(re->supp_opclass[i].num_supported_channels, sizeof(struct supp_channel)); if (!re->supp_opclass[i].supp_chanlist) { - fprintf(stderr, "|%s:%d| out of memory!\n", __func__, __LINE__); + dbg("|%s:%d| out of memory!\n", __func__, __LINE__); return; } - blobmsg_for_each_attr(cur1, data[2], rem1) { re->supp_opclass[i].supp_chanlist[k].channel = blobmsg_get_u32(cur1); re->supp_opclass[i].supp_chanlist[k].pref = 0xff; @@ -2698,11 +2732,11 @@ static void parse_radio(struct ubus_request *req, int type, re->supp_opclass[i].num_exclude_channels * sizeof(uint8_t)); } } - + if (data[3]) + re->scanlist->opclass_scanlist[i].bandwidth = blobmsg_get_u32(data[3]); i++; } } - if (tb[6]) re->current_opclass = (uint8_t) blobmsg_get_u32(tb[6]); @@ -2724,6 +2758,98 @@ static void parse_radio(struct ubus_request *req, int type, } } +static struct wifi_scanres_channel_element *wifi_get_scanres_ch_element(struct wifi_radio_element *re, uint8_t ch, uint8_t num_sr) +{ + uint32_t num_all_channels, opc; + + for (int i = 0; i < num_sr; i++) { + num_all_channels = re->scanlist->opclass_scanlist[i].num_channels_scanned; + opc = re->scanlist->opclass_scanlist[i].opclass; + for (int j = 0; j < num_all_channels; j++) { + if (re->scanlist->opclass_scanlist[i].channel_scanlist[j].channel == ch && re->scanlist->opclass_scanlist[i].bandwidth == 20) + return &re->scanlist->opclass_scanlist[i].channel_scanlist[j]; + } + } + fprintf(stderr, "No operating class with channel %d\n", ch); + return 0; +} + +static void parse_scanresults(struct ubus_request *req, int type, struct blob_attr *msg) +{ + fprintf(stdout, "%s --->\n", __func__); + int rem, i = 0; // i iterator through scanresults + int f = 0; // index for filling neighbors + struct wifi_radio_element *re = (struct wifi_radio_element *)req->priv; + struct blob_attr *tb[1], *cur; + + static const struct blobmsg_policy scan_attr[1] = { + [0] = { .name = "accesspoints", .type = BLOBMSG_TYPE_ARRAY } + }; + + blobmsg_parse(scan_attr, 1, tb, blob_data(msg), blob_len(msg)); + + if (!tb[0]) + fprintf(stderr, "%s | Scanresults not parsed.", __func__); + int num_sr = blobmsg_check_array(tb[0], BLOBMSG_TYPE_TABLE); + + // Iterate through all access points (neighbors) from *scanresult* + blobmsg_for_each_attr(cur, tb[0], rem) { + struct blob_attr *data[7]; + static const struct blobmsg_policy ap_attrs[7] = { + [0] = { .name = "ssid", .type = BLOBMSG_TYPE_STRING }, + [1] = { .name = "bssid", .type = BLOBMSG_TYPE_STRING }, + [2] = { .name = "channel", .type = BLOBMSG_TYPE_INT32 }, + [3] = { .name = "bandwidth", .type = BLOBMSG_TYPE_INT32 }, + [4] = { .name = "rssi", .type = BLOBMSG_TYPE_INT32 }, + [5] = { .name = "load_stas", .type = BLOBMSG_TYPE_INT32 }, + [6] = { .name = "load_utilization", .type = BLOBMSG_TYPE_INT32 } + }; + + // Conditions for parsing the object + if (blobmsg_type(cur) != BLOBMSG_TYPE_TABLE) { + fprintf(stderr, "|%s:%d|\n", __func__, __LINE__); + continue; + } + + //if (missing data){ + if (!data[0] || !data[1] || !data[2] || !data[3] || !data[4] || !data[5] || !data[6] || i >= num_sr) { + fprintf(stderr, "|%s:%d|\n", __func__, __LINE__); + continue; + } + + // Now if the conditions are passed we can parse the object + blobmsg_parse(ap_attrs, 7, data, blobmsg_data(cur), blobmsg_data_len(cur)); + int current_channel_of_scanres_el = blobmsg_get_u32(data[2]); + struct wifi_scanres_channel_element *scanres_el; + scanres_el = wifi_get_scanres_ch_element(re, current_channel_of_scanres_el, num_sr); + if (!scanres_el) + continue; + // if no neighbors, allocated + if (scanres_el->num_neighbors == 0) { + scanres_el->num_neighbors++; + scanres_el->nbrlist = malloc(1 * sizeof(*(scanres_el->nbrlist))); + } + // If has neighbors, allocate one addiotnal neighbor + else { + scanres_el->num_neighbors++; + scanres_el->nbrlist = realloc(scanres_el->nbrlist, scanres_el->num_neighbors * sizeof(*(scanres_el->nbrlist))); + } + f = scanres_el->num_neighbors - 1; // fill index + // Fill in the neoghbour data + char bssid_string[18] = {0}; + char ssid_string[33] = {0}; + + strncpy(scanres_el->nbrlist[f].ssid, blobmsg_data(data[0]), sizeof(scanres_el->nbrlist->ssid) - 1); + strncpy(bssid_string, blobmsg_data(data[1]), sizeof(bssid_string) - 1); + hwaddr_aton(bssid_string, scanres_el->nbrlist[f].bssid); + scanres_el->nbrlist[f].rssi = blobmsg_get_u32(data[4]); + scanres_el->nbrlist[f].bw = blobmsg_get_u32(data[3]); + scanres_el->nbrlist[f].utilization = blobmsg_get_u32(data[6]); + scanres_el->nbrlist[f].num_stations = blobmsg_get_u32(data[5]); + i++; + }; +} + static void _enumerate_wifi_objects(struct ubus_request *req, int type, struct blob_attr *msg) { @@ -2816,9 +2942,17 @@ static void _enumerate_wifi_objects(struct ubus_request *req, int type, // r_objname, f->name); continue; } + // ubus call wifi.radio.wl0 status + ubus_call_object(a, r_wobj, "status", parse_radio, &a->radios[i]); + + // ubus call wifi.radio.wl0 scan + ubus_call_object(a, r_wobj, "scan", NULL, &a->radios[i]); + fprintf(stderr, "Scaning neighbors....."); + sleep(5); // TODO : week 8 + fprintf(stderr, "DONE\n"); - ubus_call_object(a, r_wobj, "status", parse_radio, - &a->radios[i]); + // ubus call wifi.radio.wl0 scanresults + ubus_call_object(a, r_wobj, "scanresults", parse_scanresults, &a->radios[i]); } out_json: diff --git a/src/core/agent.h b/src/core/agent.h index 92eb344bafa106f7dba18d9bbc64dfdbab7567a4..f6e5eb6d71727ba63d3b5cb7893f02803d811145 100644 --- a/src/core/agent.h +++ b/src/core/agent.h @@ -321,6 +321,7 @@ struct wifi_scanres_channel_element { struct wifi_scanres_opclass_element { uint8_t opclass; + uint32_t bandwidth; uint32_t num_channels_scanned; struct wifi_scanres_channel_element *channel_scanlist; }; diff --git a/src/core/agent_map.c b/src/core/agent_map.c index de486af28c531e53470d64cb71b4ae309f753796..eefabba146dc5b6eab2e29b3c2a325aade73081d 100644 --- a/src/core/agent_map.c +++ b/src/core/agent_map.c @@ -7,7 +7,7 @@ * */ - +#include <time.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -609,6 +609,22 @@ struct netif_fh *wifi_get_netif_by_bssid(struct agent *a, uint8_t *bssid) if (hwaddr_equal(fh->bssid, bssid)) return fh; } +} + +static struct wifi_radio_element *wifi_get_radio_index_by_mac(struct agent *a, + uint8_t *hwaddr) +{ + struct wifi_radio_element *radio; + int i; + + for (i = 0; i < a->num_radios; i++) { + radio = a->radios + i; + + if (memcmp(radio->macaddr, hwaddr, 6)) + continue; + + return i; + } return NULL; } @@ -2778,10 +2794,168 @@ out_cmdu: return -1; } +char *get_timestamp(time_t *t, char **tbuf) +{ + char tmpbuf[64] = {0}; + struct tm res; + char sign; + long toff, toff_hour, toff_min; + const time_t now = time(t); + + //if (!tbuf) + // return NULL; + + /* E.g. "2019-02-11T06:42:31.23039-08:00" */ + + localtime_r(&now, &res); + tzset(); + toff = timezone; + sign = toff > 0 ? '-' : '+'; + toff *= -1L; + + toff_hour = toff / 3600; + toff_min = (toff % 3600) / 60; + + snprintf(tmpbuf, 63, "%04d-%02d-%02dT%02d:%02d:%02d%c%02ld:%02ld", + res.tm_year + 1900, res.tm_mon, res.tm_mday, res.tm_hour, res.tm_min, res.tm_sec, sign, toff_hour, toff_min); + if (!*tbuf) { + *tbuf = calloc(1, strlen(tmpbuf) + 1); + if (!*tbuf) + return NULL; + } + + sprintf(*tbuf, "%s", tmpbuf); + return *tbuf; +} + +static void scan_results(struct agent *a, struct tlv_ch_scan_res *p, uint32_t radio_index, uint32_t opclass_index, uint32_t channel_index) +{ + + struct wifi_radio_element *radio = a->radios + radio_index; + struct wifi_scanres_opclass_element *op = radio->scanlist[0].opclass_scanlist + opclass_index; + struct wifi_scanres_channel_element *ch = op->channel_scanlist + channel_index; + int i; + char bw_str[16] = {0}; + + memcpy(p->radio_id, radio->macaddr, 6); + p->op_class = op->opclass; + p->ch = ch->channel; + p->scan_res = CH_SCAN_STATUS_SUCCESS; + if (p->scan_res == CH_SCAN_STATUS_SUCCESS) { + get_timestamp(NULL, &p->timestamp); + p->time_len = strlen(p->timestamp); + p->utilization = ch->utilization; + p->noise = ch->anpi; + p->nbr_neighbors = ch->num_neighbors; + p->neighbor_data = calloc(p->nbr_neighbors, sizeof(*(p->neighbor_data))); + if (p->neighbor_data) { + for (i = 0; i < p->nbr_neighbors; i++) { + struct wifi_scanres_neighbor_element *nbr = ch->nbrlist + i; + + memcpy(p->neighbor_data[i].bssid, nbr->bssid, 6); + p->neighbor_data[i].ssid = strdup(nbr->ssid); + p->neighbor_data[i].ssid_len = strlen(p->neighbor_data[i].ssid); + p->neighbor_data[i].signal_strength = nbr->rssi; + p->neighbor_data[i].bss_load_elm_present = 1; + + snprintf(bw_str, 15, "%d", nbr->bw); + p->neighbor_data[i].ch_bandwidth = strdup(bw_str); + p->neighbor_data[i].ch_band_len = strlen(p->neighbor_data[i].ch_bandwidth); + + if (p->neighbor_data[i].bss_load_elm_present == 1) { + p->neighbor_data[i].ch_util = nbr->utilization; + p->neighbor_data[i].sta_count = nbr->num_stations; + } + } + } + } +} + int handle_channel_scan_request(void *agent, struct cmdu_cstruct *cmdu) { trace("%s: --->\n", __func__); - return 0; + struct agent *a = (struct agent *) agent; + uint16_t tlv_index = 0; + uint32_t i, j, k; + + int radio_index; + int opclass_index; + int channel_index; + + struct cmdu_cstruct *cmdu_data; + int ret; + // The received TLV + uint8_t *tmp = NULL; + + tmp = cmdu->tlvs[0]; + if (*tmp != MAP_TLV_CHANNEL_SCAN_REQ) { + dbg("Wrong received TLV type!\n"); + return -1; + } + struct tlv_ch_scan_req *query = (struct tlv_ch_scan_req *)tmp; + // Allocate the cmdu + cmdu_data = (struct cmdu_cstruct *)calloc(1, sizeof(struct cmdu_cstruct)); + if (!cmdu_data) { + dbg("Out of memory!\n"); + return -1; + } + // Define the cmdu + cmdu_data->message_type = CMDU_CHANNEL_SCAN_REPORT; + cmdu_data->message_id = cmdu->message_id; + strcpy(cmdu_data->intf_name, cmdu->intf_name); + memcpy(cmdu_data->origin, cmdu->origin, 6); + cmdu_data->num_tlvs = 1 + query->radio_data->op_class_data->nbr_ch; + + // Allocate the TLVs + cmdu_data->tlvs = (uint8_t **)calloc(cmdu_data->num_tlvs, sizeof(uint8_t *)); + if (!cmdu_data->tlvs) { + map_free_cmdu(cmdu_data); + return -1; + } + // Define the TLVs + /* Timestamp */ + struct tlv_timestamp *p = (struct tlv_timestamp *)calloc(1, sizeof(struct tlv_timestamp)); + + if (p) { + p->tlv_type = MAP_TLV_TIMESTAMP; + get_timestamp(NULL, &p->time); + p->time_len = strlen(p->time); + cmdu_data->tlvs[tlv_index++] = (uint8_t *)p; + trace("|%s:%d| Added %s\n", __func__, __LINE__, map_stringify_tlv_type(*cmdu_data->tlvs[tlv_index-1])); + } + + /* Channel scan result */ + struct wifi_radio_element *radio = a->radios; + /* Assuming one radio */ + radio_index = wifi_get_radio_index_by_mac(a, query->radio_data->radio_id); + // Go through the channel list from the query + for (int k = 0; k < query->radio_data->op_class_data->nbr_ch; k++) { + uint8_t query_channel = query->radio_data->op_class_data->ch[k]; + + for (int i = 0; i < radio->scanlist->num_opclass_scanned; i++) { + for (int j = 0; j < radio->scanlist->opclass_scanlist[i].num_channels_scanned; j++) { + if (radio->scanlist->opclass_scanlist[i].channel_scanlist[j].channel == query_channel) { + opclass_index = i; + channel_index = j; + struct tlv_ch_scan_res *p1 = (struct tlv_ch_scan_res *)calloc(1, sizeof(struct tlv_ch_scan_res)); + + if (p1) { + p1->tlv_type = MAP_TLV_CHANNEL_SCAN_RES; + scan_results(a, p1, radio_index, opclass_index, channel_index); + cmdu_data->tlvs[tlv_index++] = (uint8_t *)p1; + trace("|%s:%d| Added %s for channel %d\n", __func__, __LINE__, map_stringify_tlv_type(*cmdu_data->tlvs[tlv_index-1]), query_channel); + goto found; + } + } + } + } +found: + continue; + } + // Send cmdu + ret = agent_send_cmdu(a, cmdu_data); + map_free_cmdu(cmdu_data); + return ret; } int handle_cac_request(void *agent, struct cmdu_cstruct *cmdu) @@ -3012,7 +3186,7 @@ static void send_cmdu_cb(struct ubus_request *req, if (json_object_object_get_ex(jobj, "mid", &tmp)) { *mid = json_object_get_int(tmp); - fprintf(stdout, "%s:%d map-mid:%d\n", __func__, __LINE__, *mid); + fprintf(stdout, "%s:%d agent map-mid:%d\n", __func__, __LINE__, *mid); } json_object_put(jobj); @@ -3095,7 +3269,7 @@ int agent_send_cmdu(struct agent *a, struct cmdu_cstruct *cmdu) trace("[%s:%d] not present", __func__, __LINE__); goto out; } - test_cmdu(cmdu); + fprintf(stderr, " %s -", __func__); test_cmdu(cmdu); ret = ubus_invoke(a->ubus_ctx, id, "send", b.head, send_cmdu_cb, (void *)&msgid, @@ -3146,7 +3320,7 @@ int agent_handle_map_event(struct agent *a, uint16_t cmdutype, uint16_t mid, if (f[idx]) { cmdu = map_build_cmdu(cmdutype, mid, rxif, src, tlvs); if (cmdu) { - test_cmdu(cmdu); + fprintf(stderr, " %s -", __func__); test_cmdu(cmdu); ret = f[idx](a, cmdu); map_free_cmdu(cmdu); } else { diff --git a/src/utils/debug.c b/src/utils/debug.c index 411077e287639a7289e88a4814844880288e225f..b2a320b939d78ed358bb617df077fdf0f1dabb86 100644 --- a/src/utils/debug.c +++ b/src/utils/debug.c @@ -196,7 +196,7 @@ void log_test(int level, void *var, int len) btostr(var, len, bstr); - printf("%s %d bstr = %s\n", __func__, __LINE__, bstr); + printf("%s %d agent bstr = %s\n", __func__, __LINE__, bstr); fprintf(testfile, "%s\n", bstr); fflush(testfile);