diff --git a/src/Makefile b/src/Makefile index 24642f6a2de239b5ab8b8a31e1209f2eb6e1446d..dc001c4fc8868681db04b8db9443cc126a69e633 100644 --- a/src/Makefile +++ b/src/Makefile @@ -5,6 +5,7 @@ CFLAGS+= -g -Wall OBJS = \ utils/debug.o \ utils/liblist.o \ + utils/brcm_nl.o \ utils/utils.o \ IPC_OBJS = \ @@ -19,11 +20,13 @@ AGENT_OBJS = \ core/agent.o \ core/agent_map.o \ core/agent_tlv_generator.o \ + core/agent_cmdu_generator.o \ core/config.o \ core/main.o \ core/plugin.o LIBS = -lubus -lubox -ljson-c -lblobmsg_json -luci -lwifi-6 -leasy -pthread +LIBS += -I/usr/include/libnl3 -lnl-3 -lnl-route-3 LIBS += -rdynamic -ldl LIBS += -lmaputils LIBS += -lwsc diff --git a/src/agent.conf b/src/agent.conf index 5d6f795baef2a2eaf8cd2d75752ab6a9a7ad4426..8edf1b0d1250fbb7f4ef4701b8f2d1fd7a17eef6 100644 --- a/src/agent.conf +++ b/src/agent.conf @@ -1,10 +1,11 @@ -config wifiagent +config agent agent option enabled '1' option debug '6' option profile '2' config fh-iface option ifname 'wl0' + option device 'wl0' option steer 'rssi bssload' list exclude '00:11:22:33:44:55' list exclude_btm '00:aa:bb:cc:dd:ee' @@ -19,6 +20,7 @@ config fh-iface config fh-iface option ifname 'wl1' + option device 'wl1' option steer 'rssi bssload' list exclude '00:11:22:33:44:55' list exclude_btm '00:aa:bb:cc:dd:ee' diff --git a/src/core/agent.c b/src/core/agent.c index 32e63dae0ad7d8029afaafa7b1c4d3436e5a2361..ada6ba07bd35ac074e62e1ba2e0e4c137b63b98f 100644 --- a/src/core/agent.c +++ b/src/core/agent.c @@ -27,6 +27,9 @@ #include <sys/ioctl.h> #include <net/if_arp.h> +#include <netinet/in.h> +#include <net/if.h> + #include <pthread.h> #include <map1905/map2.h> @@ -53,6 +56,9 @@ #include "agent_ubus.h" #include "agent_map.h" #include "plugin.h" +#include "agent_cmdu_generator.h" +#include "brcm_nl.h" + static struct agent *this_agent; static int signal_pending; @@ -92,6 +98,48 @@ static void agent_sighandler(int sig) signal_pending = sig; } + +const char *wifi_ifname_to_radio(struct agent *a, char *ifname) +{ + int i, j; + const char *ret; + + for (i = 0; i < WIFI_DEVICE_MAX_NUM; i++) { + for (j = 0; j < WIFI_IFACE_MAX_NUM; j++) { + if (a->ifs[i].iface[j].name && + a->ifs[i].iface[j].name[0] != '\0' && + !strncmp(a->ifs[i].iface[j].name, ifname, 15)) { + + ret = a->ifs[i].radio; + return ret; + } + } + } + return NULL; +} + +struct wifi_radio_element *wifi_ifname_to_radio_element(struct agent *a, + char *ifname) +{ + int i; + const char *radio; + + radio = wifi_ifname_to_radio(a, ifname); + if (!radio) + return NULL; + + for (i = 0; i < WIFI_DEVICE_MAX_NUM; i++) { + if (a->radios[i].name && + a->radios[i].name[0] != '\0' && + !strncmp(a->radios[i].name, radio, 15)) { + + return &a->radios[i]; + } + } + + return NULL; +} + static void wifiagent_log_steer(struct agent *a, unsigned char *stamac, char *vifname, @@ -1405,7 +1453,7 @@ out: static void wifi_sta_event_handler(void *c, struct blob_attr *msg) { struct agent *a = (struct agent *)c; - const char ifname[16] = {0}, event[16] = {0}; + char ifname[16] = {0}, event[16] = {0}; struct blob_attr *tb[3]; static const struct blobmsg_policy ev_attr[3] = { [0] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING }, @@ -1431,7 +1479,7 @@ static void wifi_sta_event_handler(void *c, struct blob_attr *msg) [0] = { .name = "macaddr", .type = BLOBMSG_TYPE_STRING }, [1] = { .name = "bssid", .type = BLOBMSG_TYPE_STRING }, }; - const char mac_str[18] = {0}, bssid_str[18] = {0}; + char mac_str[18] = {0}, bssid_str[18] = {0}; uint8_t mac[6] = {0}, bssid[6] = {0}; blobmsg_parse(data_attr, 2, data, blobmsg_data(tb[2]), @@ -1461,7 +1509,7 @@ static void wifi_sta_event_handler(void *c, struct blob_attr *msg) [1] = { .name = "target_bssid", .type = BLOBMSG_TYPE_STRING }, [2] = { .name = "status", .type = BLOBMSG_TYPE_STRING }, }; - const char mac_str[18] = {0}, bssid_str[18] = {0}; + char mac_str[18] = {0}, bssid_str[18] = {0}; uint8_t mac[6] = {0}, bssid[6] = {0}; int status; @@ -1499,7 +1547,7 @@ static void wifi_sta_event_handler(void *c, struct blob_attr *msg) static const struct blobmsg_policy data_attr[1] = { [0] = { .name = "macaddr", .type = BLOBMSG_TYPE_STRING }, }; - const char mac_str[18] = {0}; + char mac_str[18] = {0}; uint8_t mac[6] = {0}; struct sta *s; @@ -1541,7 +1589,7 @@ static int wifi_parse_frame(struct agent *a, struct json_object *frameobj) if (!frame) return -1; - if (!strtob(framestr, len, frame)) + if (!strtob((char *)framestr, len, frame)) goto out_frame; new = calloc(1, sizeof(*new)); @@ -1756,6 +1804,95 @@ static void wifi_radio_event_handler(void *c, struct blob_attr *msg) dbg("%s: Unhandled!!! TODO\n", __func__); } +static int wifi_mod_bridge(struct agent *a, char *ifname, char *action) +{ + char bridge[16] = {0}; + char cmd[256] = {0}; + struct blob_buf bb = {0}; + int ret; + uint32_t id; + + if (!uci_get_bridge(ifname, bridge)) + return -1; + + /* add wds iface to bridge */ + + snprintf(cmd, sizeof(cmd), "network.interface.%s", bridge); + + trace("%s interface %s to bridge %s using netifd API\n", + (!strcmp(action, "add") ? "Adding" : "Deleting"), + ifname, bridge); + + blob_buf_init(&bb, 0); + + blobmsg_add_string(&bb, "name", ifname); + + id = ubus_get_object(a->ubus_ctx, cmd); + snprintf(cmd, sizeof(cmd), "%s_device", action); + ret = ubus_invoke(a->ubus_ctx, id, cmd, bb.head, + NULL, NULL, 3 * 1000); + + blob_buf_free(&bb); + return ret; +} + + +static int if_setip(const char *name, uint32_t ipaddr) +{ + int fd; + struct ifreq ifr; + struct sockaddr_in sin; + + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd == -1) + return -1; + + strncpy(ifr.ifr_name, name, IFNAMSIZ); + + memset(&sin, 0, sizeof(struct sockaddr)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = ipaddr; + + memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr)); + if (ioctl(fd, SIOCSIFADDR, &ifr) < 0) + return -1; + + return 0; +} + +static void agent_add_to_bridge(struct agent *a, char *ifname) +{ + struct ip_address addrs[32] = {0}; + int no_addrs = 32; + char buf[256] = {0}; + + if (if_isbridge_interface(ifname) > 0) + return; + + trace("|%s:%d| Triggering dhcp on %s\n", __func__, __LINE__, + ifname); + + /* TODO: can we figure a better solution for chrCmd? */ + chrCmd(buf, sizeof(buf), + "timeout 2 udhcpc -i %s > /dev/null 2>&1", + ifname); + + if_getaddrs(ifname, addrs, &no_addrs); + + dbg("|%s:%d| no_addrs: %d\n", __func__, __LINE__, no_addrs); + + if (no_addrs > 0) { + trace("|%s:%d| first ip addr: %s\n", __func__, __LINE__, + inet_ntoa(addrs[0].addr.ip4)); + trace("|%s:%d| Attempting to add interface (%s) "\ + " to the bridge\n", __func__, __LINE__, + ifname); + wifi_mod_bridge(a, ifname, "add"); + + if_setip(ifname, 0); + } +} + static void wifi_bsta_event_handler(void *c, struct blob_attr *msg) { char ifname[16] = {0}, event[16] = {0}, bssid_str[18] = {0}; @@ -1770,15 +1907,24 @@ static void wifi_bsta_event_handler(void *c, struct blob_attr *msg) struct tlv_backhaul_steer_resp *p; uint8_t bssid[6] = {0}; struct cmdu_cstruct *cmdu; + bool add, del; blobmsg_parse(ev_attr, 3, tb, blob_data(msg), blob_len(msg)); if (!tb[0] || !tb[1] || !tb[2]) return; + strncpy(ifname, blobmsg_data(tb[0]), sizeof(ifname) - 1); strncpy(event, blobmsg_data(tb[1]), sizeof(event) - 1); + bk = find_bkhaul_by_ifname(a, ifname); + if (!bk) + return; + + add = !strcmp(event, "connected"); + del = !strcmp(event, "disconnected"); + if (tb[2]) { struct blob_attr *data[1]; static const struct blobmsg_policy data_attr[1] = { @@ -1792,9 +1938,23 @@ static void wifi_bsta_event_handler(void *c, struct blob_attr *msg) sizeof(bssid_str) - 1); } - bk = find_bkhaul_by_ifname(a, ifname); - if (!bk) - return; + if (add) { + struct cmdu_cstruct *autoconfig_cmdu; + + bk->connected = true; + if (!a->configured) { + time(&a->autocfg); + uloop_timeout_set(&a->autocfg_dispatcher, 2 * 1000); // 2 seconds + } else { + trace("Autoconfig already completed, will not trigger" \ + " again on bsta connection\n"); + /* if (a->cfg.brcm_setup) */ + agent_add_to_bridge(a, ifname); + } + } else if (del) { + bk->connected = false; + wifi_mod_bridge(a, ifname, "remove"); + } cmdu = bk->bsta_steer.cmdu; if (!cmdu) @@ -1807,6 +1967,11 @@ static void wifi_bsta_event_handler(void *c, struct blob_attr *msg) hwaddr_aton(bssid_str, bssid); + /** + * if event bssid and tlv target bssid differ, that means steering + * failed, add an error TLV prior to sending response + */ + //TODO: move to if(add)? if (memcmp(bssid, p->bssid, 6)) { struct tlv_error_code *p1; uint8_t **tlvs; @@ -1844,12 +2009,15 @@ static void wifi_wps_creds_event_handler(void *c, struct blob_attr *msg) char encryption[32] = {0}, ifname[16] = {0}, ssid[33] = {0}, key[64] = {0}; struct blob_attr *tb[4]; + struct wifi_radio_element *radio; + struct agent *a = (struct agent *) c; static const struct blobmsg_policy ap_attr[4] = { [0] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING }, [1] = { .name = "encryption", .type = BLOBMSG_TYPE_STRING }, [2] = { .name = "ssid", .type = BLOBMSG_TYPE_STRING }, [3] = { .name = "key", .type = BLOBMSG_TYPE_STRING }, }; + int ret; blobmsg_parse(ap_attr, 4, tb, blob_data(msg), blob_len(msg)); @@ -1862,6 +2030,25 @@ static void wifi_wps_creds_event_handler(void *c, struct blob_attr *msg) strncpy(key, blobmsg_data(tb[3]), sizeof(key) - 1); wifi_apply_iface_cfg(ifname, encryption, ssid, key); + + /* set agent section to onboarded */ + ret = uci_check_wifi_iface("mapagent", ifname, "bk-iface"); + if (!ret) { + ret = uci_add_wireless_iface_sec("mapagent", ifname, + "bk-iface"); + if (!ret) + return; + } + uci_set_wireless_interface_option("mapagent", "bk-iface", ifname, + "onboarded", "1"); + + uci_reload_services(); + + radio = wifi_ifname_to_radio_element(a, ifname); + if (!radio) + return; + + radio->onboarded = 1; } static void ubus_wifi_event_handler(struct ubus_context *ctx, @@ -1999,9 +2186,9 @@ static void ieee1905_cmdu_event_handler(void *c, struct blob_attr *msg) } static void ubus_1905_event_handler(struct ubus_context *ctx, - struct ubus_event_handler *ev, - const char *type, - struct blob_attr *msg) + struct ubus_event_handler *ev, + const char *type, + struct blob_attr *msg) { int i; char *str; @@ -2394,7 +2581,7 @@ static int run_agent(struct agent *a) return 0; } -static void parse_al_mac(struct ubus_request *req, int type, +static void parse_almac(struct ubus_request *req, int type, struct blob_attr *msg) { struct agent *a = (struct agent *)req->priv; @@ -2409,8 +2596,8 @@ static void parse_al_mac(struct ubus_request *req, int type, char *mac; mac = blobmsg_get_string(tb[0]); - hwaddr_aton(mac, a->al_mac); - dbg("almac = " MACFMT "\n", MAC2STR(a->al_mac)); + hwaddr_aton(mac, a->almac); + dbg("almac = " MACFMT "\n", MAC2STR(a->almac)); } } @@ -2418,8 +2605,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; - struct blob_attr *tb[10]; - static const struct blobmsg_policy radio_attr[10] = { + struct blob_attr *tb[11]; + static const struct blobmsg_policy radio_attr[11] = { [0] = { .name = "isup", .type = BLOBMSG_TYPE_BOOL }, [1] = { .name = "band", .type = BLOBMSG_TYPE_STRING }, [2] = { .name = "noise", .type = BLOBMSG_TYPE_INT32 }, @@ -2430,9 +2617,10 @@ static void parse_radio(struct ubus_request *req, int type, [7] = { .name = "channel", .type = BLOBMSG_TYPE_INT32 }, [8] = { .name = "regdomain", .type = BLOBMSG_TYPE_STRING }, [9] = { .name = "txpower", .type = BLOBMSG_TYPE_INT32 }, + [10] = { .name = "macaddr", .type = BLOBMSG_TYPE_STRING }, }; - blobmsg_parse(radio_attr, 10, tb, blob_data(msg), blob_len(msg)); + blobmsg_parse(radio_attr, 11, tb, blob_data(msg), blob_len(msg)); if (tb[0]) re->enabled = blobmsg_get_bool(tb[0]); @@ -2515,6 +2703,7 @@ static void parse_radio(struct ubus_request *req, int type, re->supp_opclass[i].num_exclude_channels * sizeof(uint8_t)); } } + i++; } } @@ -2530,6 +2719,16 @@ static void parse_radio(struct ubus_request *req, int type, if (tb[9]) re->current_txpower_percent = (uint8_t) blobmsg_get_u32(tb[9]); + + if (tb[10]) { + // TODO: uncomment when radio mac is fixed in wifimngr + //char macaddr[18] = {0}; + + re->macaddr[5] = atoi(re->name+2); + //strncpy(macaddr, blobmsg_data(tb[10]), 17); + //if (!hwaddr_aton(macaddr, re->macaddr)) + // return; + } } static void _enumerate_wifi_objects(struct ubus_request *req, int type, @@ -2699,47 +2898,6 @@ static void netif_free_all(struct agent *a) netif_free(p); } -const char *wifi_ifname_to_radio(struct agent *a, char *ifname) -{ - int i, j; - const char *ret; - - for (i = 0; i < WIFI_DEVICE_MAX_NUM; i++) { - for (j = 0; j < WIFI_IFACE_MAX_NUM; j++) { - if (a->ifs[i].iface[j].name && - a->ifs[i].iface[j].name[0] != '\0' && - !strncmp(a->ifs[i].iface[j].name, ifname, 15)) { - - ret = a->ifs[i].radio; - return ret; - } - } - } - return NULL; -} - -struct wifi_radio_element *wifi_ifname_to_radio_element(struct agent *a, - char *ifname) -{ - int i; - const char *radio; - - radio = wifi_ifname_to_radio(a, ifname); - if (!radio) - return NULL; - - for (i = 0; i < WIFI_DEVICE_MAX_NUM; i++) { - if (a->radios[i].name && - a->radios[i].name[0] != '\0' && - !strncmp(a->radios[i].name, radio, 15)) { - - return &a->radios[i]; - } - } - - return NULL; -} - /* get first ap on the radio */ // TODO: fixme: get base interface based on macaddr instead? struct netif_fh *wifi_radio_to_ap(struct agent *a, const char *radio) @@ -2830,7 +2988,6 @@ static void parse_bk(struct ubus_request *req, int type, static void parse_ap(struct ubus_request *req, int type, struct blob_attr *msg) { - struct wifi_radio_element *radio; struct netif_fh *fh = (struct netif_fh *)req->priv; char bssid[18] = { 0 }, ifname[16] = { 0 }; struct blob_attr *tb[4]; @@ -2850,7 +3007,8 @@ static void parse_ap(struct ubus_request *req, int type, strncpy(fh->name, blobmsg_data(tb[0]), 15); strncpy(bssid, blobmsg_data(tb[1]), 17); - hwaddr_aton(bssid, fh->bssid); + if (!hwaddr_aton(bssid, fh->bssid)) + return; fh->channel = blobmsg_get_u8(tb[2]); @@ -2870,14 +3028,7 @@ static void parse_ap(struct ubus_request *req, int type, parse_dot11ac(fh, data[1]); } - if (!hwaddr_aton(bssid, fh->bssid)) - return; - - radio = wifi_ifname_to_radio_element(fh->agent, ifname); - if (!radio) - return; - memcpy(radio->macaddr, fh->bssid, 6); } /* Initialize netif_fh/bk structs from ubus wifi objects */ @@ -2891,7 +3042,7 @@ static int agent_init_interfaces(struct agent *a) ieee1905_obj = ubus_get_object(a->ubus_ctx, "ieee1905"); if (ieee1905_obj != WIFI_OBJECT_INVALID) { - ubus_call_object(a, ieee1905_obj, "info", parse_al_mac, a); + ubus_call_object(a, ieee1905_obj, "info", parse_almac, a); } else { warn("Object '%s' not present!\n"); return -1; @@ -2991,6 +3142,18 @@ static int agent_init_interfaces(struct agent *a) ubus_call_object(a, wobj, "status", parse_bk, bn); } + + if (b->onboarded) { + struct wifi_radio_element *re; + + re = wifi_ifname_to_radio_element(a, b->name); + if (!re) + continue; + + re->onboarded = 1; + trace("radio (%s) has been onboarded\n", re->name); + } + } return 0; @@ -3034,6 +3197,54 @@ static void agent_steering_opp_timeout(struct uloop_timeout *t) send_sta_steer_complete((void *)a, origin, ifname); } +/* TODO: is it possible to pass private 'reason'? i.e. switch case (reason) */ +static void agent_dispatch_autoconfig(struct uloop_timeout *t) +{ + struct agent *a = container_of(t, struct agent, autocfg_dispatcher); + int diff; + time_t now; + struct netif_bk *bk; + int i; + + time(&now); + + trace("|%s:%d| Attempting to trigger AP-Autoconfig\n", __func__, __LINE__); + + diff = difftime(now, a->autocfg); + dbg("|%s:%d| Time since AP-Auotconfig was triggered %d(s)\n", __func__, __LINE__, diff); + /* if more than 2 minutes has passed since triggered, stop */ + if (a->configured && diff > 2 * 60) { + dbg("|%s:%d| Diff exceeds 2 minutes and agent is configured, "\ + "will not retrigger\n", __func__, __LINE__); + return; + } + + /* Only applicable for bSTA interfaces */ + list_for_each_entry(bk, &a->bklist, list) { + if (!bk->connected) + continue; + + agent_add_to_bridge(a, bk->name); + } + + for (i = 0; i < a->num_radios; i++) { + struct cmdu_cstruct *cmdu; + struct wifi_radio_element *radio = &a->radios[i]; + + cmdu = agent_gen_ap_autoconfig_search(a, radio, NULL, 0x02); + if (!cmdu) + continue; + + trace("|%s:%d| Sending Autoconfig Search for radio %s(%s)\n", + __func__, __LINE__, radio->name, + (radio->band == BAND_2 ? "2.4GHz" : "5GHz")); + agent_send_cmdu(a, cmdu); + map_free_cmdu(cmdu); + } + + uloop_timeout_set(&a->autocfg_dispatcher, 15 * 1000); +} + static struct msg *agent_msg_enqueue(struct agent *a, int id, char *data, int len) { @@ -3103,8 +3314,11 @@ void clear_fhlist(struct agent *a) int start_agent(void) { + struct cmdu_cstruct *autoconfig_cmdu; struct agent *w; struct ubus_context *ctx; + pthread_t tid[1]; + struct netif_fhcfg *f; signal_pending = 0; set_sighandler(SIGINT, agent_sighandler); @@ -3146,6 +3360,20 @@ int start_agent(void) ubus_add_uloop(ctx); agent_config_init(&w->cfg); + + memcpy(w->cntlr_almac, w->cfg.cntlr_almac, 6); + if (w->cfg.brcm_setup) { + int ret; + + /* TODO: memory management of thread on cleaup */ + ret = pthread_create(&(tid[0]), NULL, (void *)&brcm_nl_loop, + NULL); + if (ret) { + fprintf(stderr, "Failed to create thread\n"); + return -1; + } + } + //agent_config_reload(&w->cfg); //agent_config_defaults(w, &w->cfg); #if 0 @@ -3155,12 +3383,26 @@ int start_agent(void) #endif get_registered_steer_rules(); /* TODO: return rule list and improve */ + list_for_each_entry(f, &w->cfg.fhlist, list) { + for (;;) { + uint32_t flags; + + if_getflags(f->name, &flags); + if (flags & IFF_UP) + break; + + sleep(2); + } + } + agent_init_interfaces(w); ubus_register_event_handler(ctx, &w->wifi_evh, "wifi.*"); ubus_register_event_handler(ctx, &w->wifi_evh, "wps_credentials"); ubus_register_event_handler(ctx, &w->ieee1905_evh, "ieee1905.*"); + w->autocfg_dispatcher.cb = agent_dispatch_autoconfig; + w->heartbeat.cb = agent_periodic_run; uloop_timeout_set(&w->heartbeat, 1 * 1000); @@ -3177,6 +3419,12 @@ int start_agent(void) w->sta_steerlist_count = 0; w->sta_steer_req_timer.cb = agent_steering_opp_timeout; + autoconfig_cmdu = agent_gen_ap_autoconfig_search(w, + MULTICAST_ADDR_HEX, NULL, 0x02); + agent_add_cmdu(w, autoconfig_cmdu); + time(&w->autocfg); + uloop_timeout_set(&w->autocfg_dispatcher, 2 * 1000); // 2 seconds + uloop_run(); /* out_and_exit: */ @@ -3194,6 +3442,18 @@ int start_agent(void) return 0; } +struct wsc_data *agent_free_wsc_data(struct wsc_data *wsc) +{ + if (wsc->m1_frame) + free(wsc->m1_frame); + if (wsc->key) { + free(wsc->key->key); + free(wsc->key); + } + + return NULL; +} + void agent_free_radios(struct agent *a) { int i; @@ -3210,14 +3470,10 @@ void agent_free_radios(struct agent *a) } free(re->supp_opclass); + agent_free_wsc_data(&re->autconfig); + re->autconfig.key = NULL; + re->autconfig.m1_frame = NULL; - // theoretically should be allocated or NULL - if (re->autconfig.m1_frame) - free(re->autconfig.m1_frame); - if (re->autconfig.key) { - free(re->autconfig.key->key); - free(re->autconfig.key); - } } } diff --git a/src/core/agent.h b/src/core/agent.h index 8c10a5ac4f5e3dafa6e0b494fa7c80f15c22a22e..fc81cdd4552868066e20422c16c0aeeaf7897d5b 100644 --- a/src/core/agent.h +++ b/src/core/agent.h @@ -19,11 +19,6 @@ #define MAX_STA 20 typedef char timestamp_t[32]; -typedef struct ipaddress { - uint8_t ver; - uint8_t addr[16]; -} ipaddr_t; - /* defined in agent/main.c */ extern const char *ubus_socket; extern const char *pidfile; @@ -193,6 +188,7 @@ struct netif_bk { int channel; unsigned char bssid[6]; char ssid[33]; + bool connected; struct netif_bkcfg *cfg; /* enum netif_type iftype; */ struct list_head list; @@ -261,7 +257,7 @@ struct wifi_sta_element { uint32_t tx_errors; uint32_t rx_errors; uint32_t rtx_pkts; /* total retransmitted packets */ - ipaddr_t ipaddr; + struct ip_address ipaddr; char hostname[128]; uint8_t num_bcn_reports; uint8_t *bcn_reportlist; /* list of beacon reports */ @@ -330,10 +326,17 @@ struct wifi_unassoc_sta_element { uint8_t rssi; }; +struct wsc_data { + uint8_t *m1_frame; + uint16_t m1_size; + struct wsc_key *key; +}; + struct wifi_radio_element { char name[16]; uint8_t macaddr[6]; uint8_t country_code[2]; + bool onboarded; enum wifi_band band; bool enabled; int anpi; @@ -365,11 +368,7 @@ struct wifi_radio_element { struct wifi_scanres_element *scanlist; struct wifi_unassoc_sta_element *unassoc_stalist; - struct { - uint8_t *m1_frame; - uint16_t m1_size; - struct wsc_key *key; - } autconfig; + struct wsc_data autconfig; }; struct wifi_netdev { @@ -385,11 +384,18 @@ struct wifi_sta_steer_list { uint8_t complete; }; +#define CMDU_QUEUE_MAX 8 + /** struct agent - wifi agent */ struct agent { int debug; - uint8_t al_mac[6]; + uint8_t almac[6]; + uint8_t cntlr_almac[6]; struct uloop_timeout heartbeat; + bool configured; + time_t autocfg; + struct uloop_timeout autocfg_dispatcher; + struct cmdu_cstruct *cmdu_queue[CMDU_QUEUE_MAX]; struct list_head fhlist; struct list_head bklist; struct list_head framelist; @@ -418,6 +424,7 @@ struct agent { }; struct netif_bk *find_bkhaul_by_bssid(struct agent *a, uint8_t *bssid); +struct wsc_data *agent_free_wsc_data(struct wsc_data *wsc); extern int start_agent(void); extern void stop_agent(struct agent *a); diff --git a/src/core/agent_cmdu_generator.c b/src/core/agent_cmdu_generator.c new file mode 100644 index 0000000000000000000000000000000000000000..faa258700acf8be93ad11d17fd8dbba8b7eed91a --- /dev/null +++ b/src/core/agent_cmdu_generator.c @@ -0,0 +1,162 @@ +/* + * agent_tlv_generator.c - tlv building function + * + * Copyright (C) 2020 IOPSYS Software Solutions AB. All rights reserved. + * + * Author: jakob.olsson@iopsys.eu + * + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <signal.h> +#include <arpa/inet.h> +#include <sys/ioctl.h> +#include <net/if_arp.h> +#include <pthread.h> + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include <json-c/json.h> +#include <libubox/blobmsg.h> +#include <libubox/blobmsg_json.h> +#include <libubox/uloop.h> +#include <libubox/ustream.h> +#include <libubox/utils.h> +#include <libubus.h> + +#include <map1905/map2.h> +#include <map1905/maputils.h> +#include <wsc.h> + +#include <uci.h> + +#include "map_module.h" +#include "utils.h" +#include "debug.h" +#include "liblist.h" +#include "steer_rules.h" +#include "config.h" +#include "comm.h" +#include "msgqueue.h" +#include "worker.h" +#include "agent.h" +//#include "platform_interfaces.h" +#include "agent_tlv_generator.h" +#include "agent_cmdu_generator.h" + +struct cmdu_cstruct *agent_gen_ap_autoconfig_search(struct agent *a, + struct wifi_radio_element *radio, char *intf_name, + uint8_t profile) +{ + struct cmdu_cstruct *cmdu; + struct tlv_supp_service *p = NULL; + struct tlv_searched_service *p1; + struct tlv_map_profile *p2; + struct tlv_al_mac *p3; + struct tlv_autoconf_freq_band *p4; + struct tlv_searched_role *p5; + int i, tlv_index = 0; + uint8_t band = 0; + + cmdu = (struct cmdu_cstruct *)calloc(1, sizeof(struct cmdu_cstruct)); + if (!cmdu) { + fprintf(stderr, "failed to malloc cmdu\n"); + return NULL; + } + + memcpy(cmdu->origin, "\x01\x80\xc2\x00\x00\x13", 6); + if (intf_name) + strncpy(cmdu->intf_name, intf_name, + sizeof(cmdu->intf_name) - 1); + else + strncpy(cmdu->intf_name, "br-lan", sizeof(cmdu->intf_name) - 1); + + cmdu->message_type = CMDU_TYPE_AP_AUTOCONFIGURATION_SEARCH; + + p = calloc(1, sizeof(struct tlv_supp_service)); + if (!p) + goto fail_cmdu; + + cmdu->num_tlvs++; + p->tlv_type = MAP_TLV_SUPPORTED_SERVICE; + p->supported_services_list = 1; + p->supported_services = calloc(p->supported_services_list, + sizeof(*p->supported_services)); + if (!p->supported_services) + goto fail_p; + + for (i = 0; i < p->supported_services_list; i++) + p->supported_services[i].service = + SUPPORTED_SERVICE_MULTIAP_AGENT; + + p1 = calloc(1, sizeof(struct tlv_searched_service)); + if (!p1) + goto fail_p; + + cmdu->num_tlvs++; + p1->tlv_type = MAP_TLV_SEARCHED_SERVICE; + p1->searched_services_list = 1; + p1->service = calloc(p1->searched_services_list, sizeof(*p1->service)); + if (!p1->service) + goto fail_p1; + + for (i = 0; i < p->supported_services_list; i++) + p->supported_services[i].service = + SEARCHED_SERVICE_MULTIAP_CONTROLLER; + + p2 = calloc(1, sizeof(struct tlv_map_profile)); + if (!p2) + goto fail_p1; + + cmdu->num_tlvs++; + p2->tlv_type = MAP_TLV_MULTIAP_PROFILE; + p2->profile = profile; + + p3 = agent_gen_al_mac(a, a->almac); + if (!p3) + goto fail_p2; + cmdu->num_tlvs++; + + band = wifi_band_to_ieee1905band(radio->band); + + p4 = agent_gen_autoconf_freq_band(a, band); + if (!p4) + goto fail_p3; + cmdu->num_tlvs++; + + p5 = agent_gen_searched_role(a, 0x00); /* registrar */ + if (!p5) + goto fail_p4; + cmdu->num_tlvs++; + + cmdu->tlvs = (uint8_t **)calloc(cmdu->num_tlvs, + sizeof(uint8_t *)); + if (!cmdu->tlvs) + goto fail_p5; + + cmdu->tlvs[tlv_index++] = (uint8_t *)p; + cmdu->tlvs[tlv_index++] = (uint8_t *)p1; + cmdu->tlvs[tlv_index++] = (uint8_t *)p2; + cmdu->tlvs[tlv_index++] = (uint8_t *)p3; + cmdu->tlvs[tlv_index++] = (uint8_t *)p4; + cmdu->tlvs[tlv_index++] = (uint8_t *)p5; + + return cmdu; +fail_p5: + map_free_tlv_cstruct((uint8_t *) p5); +fail_p4: + map_free_tlv_cstruct((uint8_t *) p4); +fail_p3: + map_free_tlv_cstruct((uint8_t *) p3); +fail_p2: + map_free_tlv_cstruct((uint8_t *) p2); +fail_p1: + map_free_tlv_cstruct((uint8_t *) p1); +fail_p: + map_free_tlv_cstruct((uint8_t *) p); +fail_cmdu: + free(cmdu); + return NULL; +} diff --git a/src/core/agent_cmdu_generator.h b/src/core/agent_cmdu_generator.h new file mode 100644 index 0000000000000000000000000000000000000000..acf40545f190fba54a8390ce3c5c208c556b3a31 --- /dev/null +++ b/src/core/agent_cmdu_generator.h @@ -0,0 +1,16 @@ +/* + * agent_tlv_generator.h - tlv building function declarations + * + * Copyright (C) 2020 IOPSYS Software Solutions AB. All rights reserved. + * + * Author: jakob.olsson@iopsys.eu + * + */ + +#ifndef AGENT_CMDU_GEN_H +#define AGENT_CMDU_GEN_H + +struct cmdu_cstruct *agent_gen_ap_autoconfig_search(struct agent *a, + struct wifi_radio_element *radio, char *intf_name, + uint8_t profile); +#endif diff --git a/src/core/agent_map.c b/src/core/agent_map.c index f409ef2eb0c4b83bbb3eb6274548a01cce28c612..691e3273ee4de3fe70c10516165fcf41ba4e3af9 100644 --- a/src/core/agent_map.c +++ b/src/core/agent_map.c @@ -126,7 +126,10 @@ int build_ap_autoconfig_wsc(void *agent, struct cmdu_cstruct *rec_cmdu, struct tlv_ap_radio_adv_cap *p2; struct tlv_wsc *p3; int tlv_index = 0; - uint16_t len = 0; + + /* don't trigger autoconfig for bSTA radios */ + if (radio->onboarded) + return -1; cmdu = (struct cmdu_cstruct *)calloc(1, sizeof(struct cmdu_cstruct)); if (!cmdu) { @@ -525,12 +528,53 @@ int handle_ap_autoconfig_response(void *agent, struct cmdu_cstruct *cmdu) trace("agent: %s: --->\n", __func__); struct agent *a = (struct agent *) agent; struct wifi_radio_element *radio; + struct tlv_supp_service *supp_serv; + struct tlv_supported_freq_band *supp_freq; + char mac_str[18] = {0}; + bool cntlr = false; int i; + supp_serv = (struct tlv_supp_service *) extract_tlv_by_type(cmdu, + MAP_TLV_SUPPORTED_SERVICE); + if (!supp_serv) + return -1; + + for (i = 0; i < supp_serv->supported_services_list; i++) { + if (supp_serv->supported_services[i].service == SUPPORTED_SERVICE_MULTIAP_CONTROLLER) { + cntlr = true; + break; + } + } + + if (!cntlr) { + trace("agent: Autoconfig response was not from controller\n"); + return -1; + } + + memcpy(a->cntlr_almac, cmdu->origin, 6); + if (!hwaddr_ntoa(a->cntlr_almac, mac_str)) + return -1; + + set_value_by_string("mapagent", "agent", "controller_mac", mac_str, + UCI_TYPE_STRING); + uloop_timeout_cancel(&a->autocfg_dispatcher); + + supp_freq = (struct tlv_supported_freq_band *) extract_tlv_by_type(cmdu, + TLV_TYPE_SUPPORTED_FREQ_BAND); + if (!supp_freq) + return -1; + for (i = 0; i < a->num_radios; i++) { + uint8_t band; + radio = a->radios + i; + band = wifi_band_to_ieee1905band(radio->band); + if (band != supp_freq->freq_band) + continue; + build_ap_autoconfig_wsc(a, cmdu, radio, i); } + return 0; } @@ -555,12 +599,38 @@ static struct wifi_radio_element *wifi_get_radio_by_mac(struct agent *a, int wifi_teardown_iface(const char *ifname) { config_del_iface("wireless", "wifi-iface", ifname); - config_del_iface("ieee1905", "wifi-iface", ifname); - config_del_iface("agent", "fh-iface", ifname); + //config_del_iface("ieee1905", "wifi-iface", ifname); + config_del_iface("mapagent", "fh-iface", ifname); + config_del_iface("mapagent", "bk-iface", ifname); return 0; } +int wifi_teardown_map_ifaces_by_radio(struct agent *a, char *device) +{ + struct netif_fhcfg *fh, *fh_tmp; + struct netif_bkcfg *bk, *bk_tmp; + + list_for_each_entry_safe(fh, fh_tmp, &a->cfg.fhlist, list) { + if (strncmp(fh->device, device, sizeof(fh->device) - 1)) + continue; + + wifi_teardown_iface(fh->name); + clean_fh(fh); + } + + list_for_each_entry_safe(bk, bk_tmp, &a->cfg.bklist, list) { + if (strncmp(bk->device, device, sizeof(bk->device) - 1)) + continue; + + wifi_teardown_iface(bk->name); + clean_bk(bk); + } + + agent_config_reload(&a->cfg); + return 0; +} + int wifi_teardown_map_ifaces_by_band(struct agent *a, enum wifi_band band) { struct netif_fhcfg *fh, *fh_tmp; @@ -658,6 +728,8 @@ char *wifi_gen_first_ifname(struct agent *a, char *device, char *ifname) { int i; + strncpy(ifname, device, IFNAMSIZ); + /* maximum number of interface per BSSID is currently 4 * setting a higher number may cause segfault within libwsc.so, * caused by DH_free() from platform_cyrpto.c in @@ -665,9 +737,14 @@ char *wifi_gen_first_ifname(struct agent *a, char *device, char *ifname) */ /* TODO: should work with 16 instead of 4 */ for (i = 1; i <= TMP_WIFI_IFACE_MAX_NUM; i++) { - snprintf(ifname, IFNAMSIZ, "%s_%d", device, i); + if (!check_wireless_ifname(a, device, ifname)) return ifname; + + snprintf(ifname, IFNAMSIZ, "%s%s%d", + device, + (a->cfg.brcm_setup ? "." : "_"), + i); } return NULL; @@ -695,9 +772,10 @@ int handle_ap_autoconfig_wsc(void *agent, struct cmdu_cstruct *cmdu) if (!radio) return -1; - wifi_teardown_map_ifaces_by_band(a, radio->band); + dbg("|%s:%d| found radio = %s\n", __func__, __LINE__, radio->name); - // need iterate every TLV_TYPE_WSC, may be multiple + wifi_teardown_map_ifaces_by_radio(a, radio->name); + /* iterate every TLV_TYPE_WSC, may be multiple */ for (i = 0; i < cmdu->num_tlvs; i++) { tlv = cmdu->tlvs[i]; switch (*tlv) { @@ -723,11 +801,14 @@ int handle_ap_autoconfig_wsc(void *agent, struct cmdu_cstruct *cmdu) m2->wsc_frame, m2->wsc_frame_size, &out, ifname); if (!rv) { - err("Failed to process M2 target for interface"\ + err("Failed to process M2 target for interface "\ MACFMT "!\n", MAC2STR(bssid)); - //wifi_teardown_iface(ifname); - wifi_teardown_map_ifaces_by_band(a, radio->band); - // Return rather than freeing because it may belong to an updated frame + + wifi_teardown_map_ifaces_by_radio(a, + radio->name); + /* Return rather than freeing because it may + * belong to an updated frame + */ return -1; } @@ -736,16 +817,16 @@ int handle_ap_autoconfig_wsc(void *agent, struct cmdu_cstruct *cmdu) "tearing down all MAP interfaces"\ " for bssid" MACFMT "\n", MAC2STR(bssid)); - wifi_teardown_map_ifaces_by_band(a, radio->band); + wifi_teardown_map_ifaces_by_radio(a, + radio->name); goto teardown; } - uci_apply_m2(ifname, out.output.ssid, out.output.bssid, + uci_apply_m2(ifname, radio->name, out.output.ssid, out.output.auth_types, out.output.encryption_types, out.output.network_key, out.output.mapie, radio->band); - break; } default: @@ -754,16 +835,32 @@ int handle_ap_autoconfig_wsc(void *agent, struct cmdu_cstruct *cmdu) } } + a->configured = true; + agent_config_reload(&a->cfg); + uci_apply_wps_credentials(&a->cfg, radio->band); teardown: // TODO: freeing from here risks freeing an updated frame - free(radio->autconfig.m1_frame); - free(radio->autconfig.key->key); - free(radio->autconfig.key); + agent_free_wsc_data(&radio->autconfig); radio->autconfig.key = NULL; radio->autconfig.m1_frame = NULL; + uci_reload_services(); return 0; } +int handle_ap_autoconfig_renew(void *agent, struct cmdu_cstruct *cmdu) +{ + trace("agent: %s: --->\n", __func__); + struct agent *a = (struct agent *) agent; + struct wifi_radio_element *radio; + int i; + + for (i = 0; i < a->num_radios; i++) { + radio = a->radios + i; + build_ap_autoconfig_wsc(a, cmdu, radio, i); + } + + return 0; +} int handle_1905_ack(void *agent, struct cmdu_cstruct *cmdu) { @@ -776,7 +873,7 @@ int handle_ap_caps_query(void *agent, struct cmdu_cstruct *rec_cmdu) trace("agent: %s: --->\n", __func__); struct agent *a = (struct agent *) agent; uint16_t tlv_index = 0; - uint32_t j; + uint32_t i; struct cmdu_cstruct *cmdu; struct tlv_ap_cap *p2; struct tlv_ch_scan_cap *p5; @@ -795,6 +892,7 @@ int handle_ap_caps_query(void *agent, struct cmdu_cstruct *rec_cmdu) cmdu->message_type = CMDU_AP_CAPABILITY_REPORT; memcpy(cmdu->origin, rec_cmdu->origin, 6); cmdu->message_id = rec_cmdu->message_id; + strcpy(cmdu->intf_name, rec_cmdu->intf_name); cmdu->num_tlvs = 3 * a->num_radios + 1; /* (Radio basic, HT, VHT capability per radio) */ @@ -809,10 +907,10 @@ int handle_ap_caps_query(void *agent, struct cmdu_cstruct *rec_cmdu) } /* AP basic Radio Capability TLV*/ - for (j = 0; j < a->num_radios; j++) { + for (i = 0; i < a->num_radios; i++) { struct tlv_ap_radio_basic_cap *p; - p = agent_gen_ap_radio_basic_cap(a, cmdu, j); + p = agent_gen_ap_radio_basic_cap(a, cmdu, i); if (!p) continue; //cmdu->num_tlvs++; @@ -828,10 +926,10 @@ int handle_ap_caps_query(void *agent, struct cmdu_cstruct *rec_cmdu) cmdu->tlvs[tlv_index++] = (uint8_t *)p2; /* HT Capability */ - for (j = 0; j < a->num_radios; j++) { + for (i = 0; i < a->num_radios; i++) { struct tlv_ap_ht_cap *p3; - p3 = agent_gen_ap_ht_caps(a, cmdu, j); + p3 = agent_gen_ap_ht_caps(a, cmdu, i); if (!p3) continue; //cmdu->num_tlvs++; @@ -841,10 +939,10 @@ int handle_ap_caps_query(void *agent, struct cmdu_cstruct *rec_cmdu) } /* VHT Capability */ - for (j = 0; j < a->num_radios; j++) { + for (i = 0; i < a->num_radios; i++) { struct tlv_ap_vht_cap *p4; - p4 = agent_gen_ap_vht_caps(a, cmdu, j); + p4 = agent_gen_ap_vht_caps(a, cmdu, i); if (!p4) continue; @@ -1037,77 +1135,87 @@ int handle_channel_pref_query(void *agent, struct cmdu_cstruct *rec_cmdu) return ret; } -int handle_channel_sel_request(void *agent, struct cmdu_cstruct *cmdu) +int send_channel_sel_response(void *agent, struct cmdu_cstruct *rec_cmdu, + struct channel_response *channel_resp, + uint32_t channel_response_nr) { trace("agent: %s: --->\n", __func__); struct agent *a = (struct agent *) agent; - int ret = 0; - struct channel_response channel_resp[MAX_RADIO]; - uint32_t channel_resp_nr = 0, match = 0, found = 0; - int i, j, k, l, m; - uint8_t *tlv = NULL; - struct wifi_radio_element *radio; - uint32_t pref_tlv_present = 0; + uint16_t tlv_index = 0; + uint32_t j, ret = 0; + struct cmdu_cstruct *cmdu_data; - //Here we first need to update the channel preference values - //from the channel selection request - //then send the CMDU for channel selection response + cmdu_data = (struct cmdu_cstruct *)calloc(1, + sizeof(struct cmdu_cstruct)); - if (cmdu->num_tlvs != 0) { - for (i = 0; i < cmdu->num_tlvs; i++) { - tlv = (uint8_t *) cmdu->tlvs[i]; - switch (*tlv) { - case MAP_TLV_CHANNEL_PREFERENCE: - { - struct tlv_channel_pref *p = - (struct tlv_channel_pref *)tlv; - pref_tlv_present = 1; + if (!cmdu_data) { + fprintf(stderr, "Out of memory!\n"); + return -1; + } - ret = agent_process_channel_pref_tlv - (agent, p, channel_resp, - &channel_resp_nr); - } - case MAP_TLV_TRANSMIT_POWER_LIMIT: - { - struct tlv_tx_power_limit *p = - (struct tlv_tx_power_limit *)tlv; + cmdu_data->message_type = CMDU_CHANNEL_SELECTION_RESPONSE; + memcpy(cmdu_data->origin, rec_cmdu->origin, 6); + cmdu_data->message_id = rec_cmdu->message_id; + strcpy(cmdu_data->intf_name, rec_cmdu->intf_name); - trace("tlv radio_id: " MACFMT "\n", - MAC2STR(p->radio_id)); - for (l = 0; l < a->num_radios; l++) { - radio = a->radios + l; - match = memcmp(radio->macaddr, p->radio_id, 6); - if (match == 0) { - //Here we set the - //transmit_power_limit of the radio - radio->transmit_power_limit = - p->tx_power_limit; - trace("transmit power %d\n", - p->tx_power_limit); - break; - } - } - } - default: - break; - } - } - } + cmdu_data->num_tlvs = 1 * channel_response_nr; /* (channel selection response) */ + cmdu_data->tlvs = (uint8_t **)calloc(cmdu_data->num_tlvs, + sizeof(uint8_t *)); - if (cmdu->num_tlvs == 0 || pref_tlv_present == 0) { - //Here the condition is that the - //channel selection request have no tlvs or only transmit power tlv - //so we need to set all the prefernce in all radios to max 15 - agent_fill_radio_max_preference(agent, - channel_resp, &channel_resp_nr); + if (!cmdu_data->tlvs) { + map_free_cmdu(cmdu_data); + return -1; } - ret = send_channel_sel_response(agent, cmdu, - channel_resp, channel_resp_nr); + /* Operating Channel Response TLV 17.2.16 */ + for (j = 0; j < channel_response_nr; j++) { + struct tlv_ch_selection_resp *p = NULL; + /* Here we need to check that the radio + *response is for the radio for which we get request + */ + p = agent_gen_operate_channel_response(a, rec_cmdu, + channel_resp[j].radio_id, channel_resp[j].response); + if (!p) + continue; + cmdu_data->tlvs[tlv_index++] = (uint8_t *)p; + } + ret = agent_send_cmdu(a, cmdu_data); + map_free_cmdu(cmdu_data); + /* TODO send a report message for each radio. This will be + * sent not here but on receiving of the event when the + * actually radio channel poreference have been changed + */ + send_oper_channel_report(agent, rec_cmdu); return ret; } +int agent_fill_radio_max_preference(void *agent, + struct channel_response *channel_resp, + uint32_t *channel_response_nr) +{ + trace("agent: %s: --->\n", __func__); + struct agent *a = (struct agent *) agent; + uint32_t j = 0, k = 0, l = 0; + struct wifi_radio_element *radio = NULL; + + *channel_response_nr = a->num_radios; + + for (j = 0; j < a->num_radios; j++) { + radio = a->radios + j; + memcpy(channel_resp[j].radio_id, radio->macaddr, 6); + + for (k = 0; k < radio->num_supp_opclass; k++) { + for (l = 0; l < radio->supp_opclass[k]. + num_supported_channels; l++) + radio->supp_opclass[k].supp_chanlist[l].pref = + 0xff; + } + channel_resp[j].response = 0x00; + } + return 0; +} + int agent_process_channel_pref_tlv(void *agent, struct tlv_channel_pref *p, struct channel_response *channel_resp, uint32_t *channel_resp_nr) @@ -1116,44 +1224,46 @@ int agent_process_channel_pref_tlv(void *agent, struct tlv_channel_pref *p, struct agent *a = (struct agent *) agent; int ret = 0; uint32_t match = 0, found = 0; - int i, j, k, l, m; + int j, l; struct wifi_radio_element *radio; - uint32_t pref_tlv_present = 0; - trace("\tradio_id: " MACFMT "\n", - MAC2STR(p->radio_id)); + trace("\tradio_id: " MACFMT "\n", MAC2STR(p->radio_id)); for (l = 0; l < a->num_radios; l++) { radio = a->radios + l; match = memcmp(radio->macaddr, p->radio_id, 6); if (match == 0) { found = 1; memcpy(channel_resp[*channel_resp_nr].radio_id, - radio->macaddr, 6); + radio->macaddr, 6); channel_resp[*channel_resp_nr].response = 0x00; break; } } if (found == 0) { memcpy(channel_resp[*channel_resp_nr].radio_id, - p->radio_id, 6); - //Here response code is a Reserved code - //to decline the request + p->radio_id, 6); + /* Here response code is a Reserved code + * to decline the request + */ channel_resp[*channel_resp_nr].response = 0x04; *channel_resp_nr = *channel_resp_nr + 1; return ret; } - trace("ch_preference_op_class_nr: %d\n", - p->ch_preference_op_class_nr); + trace("ch_preference_op_class_nr: %d\n", p->ch_preference_op_class_nr); for (j = 0; j < p->ch_preference_op_class_nr; j++) { - //Here we need to search the operating class in the radio + /* Here we need to search the operating class in the radio */ for (l = 0; l < radio->num_supp_opclass; l++) { if (radio->supp_opclass[l].id == p->op_class[j].op_class) { - //Here we reset all the channels preferences in the - //operating class as 15 highest prefernce + int k; + + /* Here we reset all the channels preferences + * in the operating class as 15 highest + * preference + */ trace("op_class : %d channel_nr %d\n", - p->op_class[j].op_class, - p->op_class[j].channel_nr); + p->op_class[j].op_class, + p->op_class[j].channel_nr); for (k = 0; k < radio->supp_opclass[l].num_supported_channels; @@ -1162,11 +1272,13 @@ int agent_process_channel_pref_tlv(void *agent, struct tlv_channel_pref *p, supp_chanlist[k].pref = 0xff; for (k = 0; k < p->op_class[j].channel_nr; k++) { + int m; + for (m = 0; m < radio->supp_opclass[l]. num_supported_channels ; m++) { trace("channel %d\n", - p->op_class[j].channel_list[k]); + p->op_class[j].channel_list[k]); if (p->op_class[j].channel_list[k] == radio->supp_opclass[l]. supp_chanlist[m].channel) { @@ -1175,7 +1287,7 @@ int agent_process_channel_pref_tlv(void *agent, struct tlv_channel_pref *p, p->op_class[j].preference; trace("channel pref is %d\n", - p->op_class[j].preference); + p->op_class[j].preference); } } } @@ -1187,82 +1299,78 @@ int agent_process_channel_pref_tlv(void *agent, struct tlv_channel_pref *p, return ret; } -int agent_fill_radio_max_preference(void *agent, - struct channel_response *channel_resp, - uint32_t *channel_response_nr) +int handle_channel_sel_request(void *agent, struct cmdu_cstruct *cmdu) { trace("agent: %s: --->\n", __func__); struct agent *a = (struct agent *) agent; - uint32_t j = 0, k = 0, l = 0; - struct wifi_radio_element *radio = NULL; + int ret = 0; + struct channel_response channel_resp[MAX_RADIO]; + uint32_t channel_resp_nr = 0, match = 0; + int i; + uint8_t *tlv = NULL; + struct wifi_radio_element *radio; + uint32_t pref_tlv_present = 0; - *channel_response_nr = a->num_radios; + /* Here we first need to update the channel preference values + * from the channel selection request + * then send the CMDU for channel selection response + */ + if (cmdu->num_tlvs != 0) { + for (i = 0; i < cmdu->num_tlvs; i++) { + tlv = (uint8_t *) cmdu->tlvs[i]; + switch (*tlv) { + case MAP_TLV_CHANNEL_PREFERENCE: + { + struct tlv_channel_pref *p = + (struct tlv_channel_pref *)tlv; + pref_tlv_present = 1; - for (j = 0; j < a->num_radios; j++) { - radio = a->radios + j; - memcpy(channel_resp[j].radio_id, radio->macaddr, 6); + ret = agent_process_channel_pref_tlv + (agent, p, channel_resp, + &channel_resp_nr); + } + case MAP_TLV_TRANSMIT_POWER_LIMIT: + { + struct tlv_tx_power_limit *p = + (struct tlv_tx_power_limit *)tlv; + int l; - for (k = 0; k < radio->num_supp_opclass; k++) { - for (l = 0; l < radio->supp_opclass[k]. - num_supported_channels; l++) - radio->supp_opclass[k].supp_chanlist[l].pref = - 0xff; + trace("tlv radio_id: " MACFMT "\n", + MAC2STR(p->radio_id)); + for (l = 0; l < a->num_radios; l++) { + radio = a->radios + l; + match = memcmp(radio->macaddr, p->radio_id, 6); + if (match == 0) { + /* Here we set the + * transmit_power_limit + * of the radio + */ + radio->transmit_power_limit = + p->tx_power_limit; + trace("transmit power %d\n", + p->tx_power_limit); + break; + } + } + } + default: + break; + } } - channel_resp[j].response = 0x00; - } - return 0; -} - -int send_channel_sel_response(void *agent, struct cmdu_cstruct *rec_cmdu, - struct channel_response *channel_resp, - uint32_t channel_response_nr) -{ - trace("agent: %s: --->\n", __func__); - struct agent *a = (struct agent *) agent; - uint16_t tlv_index = 0; - uint32_t j, ret = 0; - struct cmdu_cstruct *cmdu_data; - - cmdu_data = (struct cmdu_cstruct *)calloc(1, - sizeof(struct cmdu_cstruct)); - - if (!cmdu_data) { - fprintf(stderr, "Out of memory!\n"); - return -1; } - cmdu_data->message_type = CMDU_CHANNEL_SELECTION_RESPONSE; - memcpy(cmdu_data->origin, rec_cmdu->origin, 6); - cmdu_data->message_id = rec_cmdu->message_id; - strcpy(cmdu_data->intf_name, rec_cmdu->intf_name); - - cmdu_data->num_tlvs = 1 * channel_response_nr; /* (channel selection response) */ - cmdu_data->tlvs = (uint8_t **)calloc(cmdu_data->num_tlvs, - sizeof(uint8_t *)); - - if (!cmdu_data->tlvs) { - map_free_cmdu(cmdu_data); - return -1; + if (cmdu->num_tlvs == 0 || pref_tlv_present == 0) { + /* Here the condition is that the + * channel selection request have no tlvs or only transmit power tlv + * so we need to set all the prefernce in all radios to max 15 + */ + agent_fill_radio_max_preference(agent, + channel_resp, &channel_resp_nr); } - /* Operating Channel Response TLV 17.2.16 */ - for (j = 0; j < channel_response_nr; j++) { - struct tlv_ch_selection_resp *p = NULL; - //Here we need to check that the radio - //response is for the radio for which we get request - p = agent_gen_operate_channel_response(a, rec_cmdu, - channel_resp[j].radio_id, channel_resp[j].response); - if (!p) - continue; - cmdu_data->tlvs[tlv_index++] = (uint8_t *)p; - } - ret = agent_send_cmdu(a, cmdu_data); - map_free_cmdu(cmdu_data); + ret = send_channel_sel_response(agent, cmdu, + channel_resp, channel_resp_nr); - //TODO send a report message for each radio. This will be - //sent not here but on receiving of the event when the - //actually radio channel poreference have been changed - send_oper_channel_report(agent, rec_cmdu); return ret; } @@ -1346,12 +1454,14 @@ int handle_sta_caps_query(void *agent, struct cmdu_cstruct *rec_cmdu) goto send_cmdu; } - // if bit is set, HT Control section is included and should be skipped + /* if bit is set, HT Control section is included and + * should be skipped + */ if (!(s->assoc_frame->frame[0] & 0x80)) offset += 4; body = s->assoc_frame->frame + offset; - // subtract 4 from remaining len to not include FCS section + /* subtract 4 from remaining len to not include FCS section */ len = s->assoc_frame->len - offset - 4; cmdu->num_tlvs--; @@ -1360,7 +1470,7 @@ int handle_sta_caps_query(void *agent, struct cmdu_cstruct *rec_cmdu) if (!p1->frame_body) goto fail_cmdu; - // first byte annotates length of frame + /* first byte annotates length of frame */ *(p1->frame_body) = (1 + len); memcpy(p1->frame_body + 1, body, len); @@ -1934,7 +2044,6 @@ int handle_backhaul_sta_steer_request(void *agent, struct tlv_backhaul_steer_req *req; struct cmdu_cstruct *cmdu; struct netif_bk *bk; - int ret; req = (struct tlv_backhaul_steer_req *) extract_tlv_by_type(rec_cmdu, MAP_TLV_BACKHAUL_STEERING_REQUEST); @@ -2033,6 +2142,7 @@ static const map_cmdu_handler_t i1905ftable[] = { /* [0x07] = handle_ap_autoconfig_search, */ [0x08] = handle_ap_autoconfig_response, [0x09] = handle_ap_autoconfig_wsc, + [0x0a] = handle_ap_autoconfig_renew, }; @@ -2157,15 +2267,15 @@ const char *tlv_friendlyname[] = { bool is_cmdu_for_us(struct agent *a, uint16_t type) { // TODO: handle only cmdu types relevant for module's role/profile. - // - // Since map-plugin now sends cmdu events, agent must filter out cmdus - // that it is not supposed to handle. - // When map-plugin directly call's map-module's 'cmd', then the - // additonal cmdu type validation/filtering it does becomes useful. In - // the latter case, agent doesn't need to do additonal checks for valid - // cmdu types. + /* Since map-plugin now sends cmdu events, agent must filter out cmdus + * that it is not supposed to handle. + * When map-plugin directly call's map-module's 'cmd', then the + * additonal cmdu type validation/filtering it does becomes useful. In + * the latter case, agent doesn't need to do additonal checks for valid + * cmdu types. + */ - // until then, the following should be okay.. + /* until then, the following should be okay.. */ if (type >= CMDU_TYPE_1905_START && type <= CMDU_TYPE_1905_END) { if (i1905ftable[type]) @@ -2250,7 +2360,8 @@ int agent_send_cmdu(struct agent *a, struct cmdu_cstruct *cmdu) blobmsg_add_u32(&b, "type", cmdu->message_type); blobmsg_add_string(&b, "egress", cmdu->intf_name); - blobmsg_add_u32(&b, "mid", cmdu->message_id); + if (cmdu->message_id) + blobmsg_add_u32(&b, "mid", cmdu->message_id); hwaddr_ntoa(cmdu->origin, dst_addr); blobmsg_add_string(&b, "dst_macaddr", dst_addr); diff --git a/src/core/agent_map.h b/src/core/agent_map.h index af1033a8126c5b6623478119e5eeaac4e23f88b8..da3d23a6eead46ecc95f4a7dcffc3618287d9d4d 100644 --- a/src/core/agent_map.h +++ b/src/core/agent_map.h @@ -2,6 +2,7 @@ #ifndef AGENT_MAP_H #define AGENT_MAP_H +struct channel_response; uint8_t *extract_tlv_by_type(struct cmdu_cstruct *cmdu, uint8_t tlv_type); diff --git a/src/core/agent_tlv_generator.c b/src/core/agent_tlv_generator.c index 0d83c425beb38e333d2a04666078fc12f298468e..67d271fe67c2d8a26290d936bf36e7c413893192 100644 --- a/src/core/agent_tlv_generator.c +++ b/src/core/agent_tlv_generator.c @@ -111,7 +111,7 @@ struct tlv_ap_radio_basic_cap *agent_gen_ap_radio_basic_cap(struct agent *a, p->tlv_type = MAP_TLV_AP_RADIO_BASIC_CAPABILITIES; memcpy(p->radio_id, radio->macaddr, 6); - p->max_bss_nr = 4; // Max BSS per Radio + p->max_bss_nr = 4; /* Max BSS per Radio */ p->operating_classes_nr = radio->num_supp_opclass; if (p->operating_classes_nr > 0) @@ -222,16 +222,15 @@ struct tlv_wsc *agent_gen_wsc(struct agent *a, struct cmdu_cstruct *cmdu, p->tlv_type = TLV_TYPE_WSC; // TODO: auth_type uses dummy value (WPA2PSK) - // TODO: remove iface name from wscbuildm1 lib func - rv = wscBuildM1(radio->name, &p->wsc_frame, &len, &key, a->al_mac, - radio->band, 0x0020, 0); + rv = wscBuildM1(radio->name, &p->wsc_frame, &len, (void **)&key, + a->almac, radio->band, 0x0020, 0); if (!rv) goto fail_p; p->wsc_frame_size = len; radio->autconfig.m1_size = len; - // discard previous frame if it has not been used + /* discard previous frame if it has not been used */ if (radio->autconfig.m1_frame) free(radio->autconfig.m1_frame); radio->autconfig.m1_frame = calloc(1, len); @@ -239,7 +238,8 @@ struct tlv_wsc *agent_gen_wsc(struct agent *a, struct cmdu_cstruct *cmdu, goto fail_key; memcpy(radio->autconfig.m1_frame, p->wsc_frame, len); - // discard previous key if it has not been used + + /* discard previous key if it has not been used */ if (radio->autconfig.key) { free(radio->autconfig.key->key); free(radio->autconfig.key); @@ -323,8 +323,6 @@ fail_p: struct tlv_cac_cap *agent_gen_cac_cap(struct agent *a) { struct tlv_cac_cap *p; - struct wifi_radio_element *radio = NULL; - struct wifi_opclass_supported_element *opclass = NULL; int i; p = (struct tlv_cac_cap *) calloc(1, sizeof(*p)); @@ -361,7 +359,7 @@ struct tlv_cac_cap *agent_gen_cac_cap(struct agent *a) int k; p->radio_data[i].cac_data[j].cac_method_supported = CAC_CAP_METHOD_CONTI_CAC; - p->radio_data[i].cac_data[j].duration = 60; //Default duration is 60, 600 for channels (120, 124 & 128) + p->radio_data[i].cac_data[j].duration = 60; /* Default duration is 60, 600 for channels (120, 124 & 128) */ // TODO: Assumption, All the supporting op_class supported continuous CAC method, // Currently no parmaeter/method to classify the same. p->radio_data[i].cac_data[j].nbr_op_classes = radio->num_supp_opclass; @@ -449,7 +447,7 @@ struct tlv_oper_ch_report *agent_gen_operate_channel_report(struct agent *a, if (!p->op_ch_op_class) { fprintf(stderr, "|%s:%d| out of memory!\n", __func__, __LINE__); p->op_ch_op_class_nr = 0; - return; + return NULL; } for (j = 0; j < p->op_ch_op_class_nr; j++) { @@ -457,8 +455,9 @@ struct tlv_oper_ch_report *agent_gen_operate_channel_report(struct agent *a, p->op_ch_op_class[j].channel = radio->current_channel; } - //current transmit power is the (operating class tx power) * - // (current_tx_power_percent)/100 + /* current transmit power is the (operating class tx power) * + * (current_tx_power_percent)/100 + */ for (j = 0; j < radio->num_supp_opclass; j++) { if (radio->supp_opclass[j].id == radio->current_opclass) p->curr_tx_power = @@ -512,7 +511,7 @@ void agent_gen_radio_channel_preference(struct agent *a, p->op_class[j].op_class = radio->supp_opclass[j].id; count = 0; - //Here we fill all the channels that are not having max preference 15 + /* Here we fill all the channels that are not having max preference 15 */ for (k = 0; k < radio->supp_opclass[j].num_supported_channels; k++) { if (radio->supp_opclass[j].supp_chanlist[k].pref != 0xff) count++; @@ -649,6 +648,20 @@ struct tlv_error_code *agent_gen_tlv_error_code(struct agent *a, return p; } +struct tlv_al_mac *agent_gen_al_mac(struct agent *a, uint8_t *hwaddr) +{ + struct tlv_al_mac *p; + + p = calloc(1, sizeof(struct tlv_al_mac)); + if (!p) + return NULL; + + p->tlv_type = TLV_TYPE_AL_MAC_ADDRESS_TYPE; + memcpy(p->al_mac_address, hwaddr, 6); + + return p; +} + struct tlv_steer_btm_report *agent_gen_steer_btm_report(struct agent *a, uint8_t *target_bssid, uint8_t *src_bssid, uint8_t *sta, uint8_t status_code) @@ -672,3 +685,43 @@ struct tlv_steer_btm_report *agent_gen_steer_btm_report(struct agent *a, return p; } + +/** + * band - + * 0x00 2.4GHz + * 0x01 5GHz + * 0x02 60GHz + */ +struct tlv_autoconf_freq_band *agent_gen_autoconf_freq_band(struct agent *a, + uint8_t band) +{ + struct tlv_autoconf_freq_band *p; + + p = calloc(1, sizeof(struct tlv_autoconf_freq_band)); + if (!p) + return NULL; + + p->tlv_type = TLV_TYPE_AUTOCONFIG_FREQ_BAND; + p->freq_band = band; + + return p; +} + +/** + * role - + * 0x00 registrar + */ +struct tlv_searched_role *agent_gen_searched_role(struct agent *a, + uint8_t role) +{ + struct tlv_searched_role *p; + + p = calloc(1, sizeof(struct tlv_searched_role)); + if (!p) + return NULL; + + p->tlv_type = TLV_TYPE_SEARCHED_ROLE; + p->role = role; + + return p; +} diff --git a/src/core/agent_tlv_generator.h b/src/core/agent_tlv_generator.h index c5ef25efc3817cdb31da7419826c8726cee73f65..68112982ff333f8c2d8598b37b7f5d38cd3d3dc4 100644 --- a/src/core/agent_tlv_generator.h +++ b/src/core/agent_tlv_generator.h @@ -43,4 +43,9 @@ struct tlv_error_code *agent_gen_tlv_error_code(struct agent *a, struct tlv_steer_btm_report *agent_gen_steer_btm_report(struct agent *a, uint8_t *target_bssid, uint8_t *src_bssid, uint8_t *sta, uint8_t status_code); +struct tlv_al_mac *agent_gen_al_mac(struct agent *a, uint8_t *hwaddr); +struct tlv_autoconf_freq_band *agent_gen_autoconf_freq_band(struct agent *a, + uint8_t band); +struct tlv_searched_role *agent_gen_searched_role(struct agent *a, + uint8_t role); #endif diff --git a/src/core/agent_ubus.c b/src/core/agent_ubus.c index c1e9c75ee5b095dbc123c0fe5636c69a28ffa789..fe16d6eb53d68d072c7f74060affffb5f082e5d2 100644 --- a/src/core/agent_ubus.c +++ b/src/core/agent_ubus.c @@ -106,14 +106,12 @@ static const struct blobmsg_policy config_policy_params[__CFG_POLICY_MAX] = { }; enum { - SEARCH_POLICY_AGENT, - SEARCH_POLICY_EGRESS, + SEARCH_POLICY_BAND, __SEARCH_POLICY_MAX, }; static const struct blobmsg_policy search_policy_params[__SEARCH_POLICY_MAX] = { - [SEARCH_POLICY_AGENT] = { .name = "agent", .type = BLOBMSG_TYPE_STRING }, - [SEARCH_POLICY_EGRESS] = { .name = "egress", .type = BLOBMSG_TYPE_STRING } + [SEARCH_POLICY_BAND] = { .name = "band", .type = BLOBMSG_TYPE_INT32 }, }; static int steer_policy(struct ubus_context *ctx, struct ubus_object *obj, @@ -290,7 +288,7 @@ static int steer(struct ubus_context *ctx, struct ubus_object *obj, } #endif - if (wifiagent_steer_sta(ctx, ifname, sta_macaddr, i, bsslist, optime) != 0) + if (wifiagent_steer_sta(ctx, ifname, sta_macaddr, i, bsslist, optime)) return UBUS_STATUS_UNKNOWN_ERROR; return UBUS_STATUS_OK; @@ -412,106 +410,51 @@ static int agent_config_ap(struct ubus_context *ctx, struct ubus_object *obj, return 0; } - static int agent_ap_search(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { struct agent *a = container_of(obj, struct agent, obj); struct blob_attr *tb[__SEARCH_POLICY_MAX]; - struct cmdu_cstruct *cmdu; - struct tlv_supp_service *p = NULL; - struct tlv_searched_service *p1; - struct tlv_map_profile *p2; - int i, tlv_index = 0; + int i, tlv_index = 0, band, ieee1905band; - blobmsg_parse(config_policy_params, __SEARCH_POLICY_MAX, tb, + blobmsg_parse(search_policy_params, __SEARCH_POLICY_MAX, tb, blob_data(msg), blob_len(msg)); - // TODO: ff:ff:ff:ff:ff:ff = send to all agents - cmdu = (struct cmdu_cstruct *)calloc(1, sizeof(struct cmdu_cstruct)); - if (!cmdu) { - fprintf(stderr, "failed to malloc cmdu\n"); - return UBUS_STATUS_UNKNOWN_ERROR; - } - - if (tb[SEARCH_POLICY_AGENT]) { - char agent[18] = {0}; + if (tb[SEARCH_POLICY_BAND]) { + band = blobmsg_get_u32(tb[SEARCH_POLICY_BAND]); - strncpy(agent, blobmsg_data(tb[SEARCH_POLICY_AGENT]), - sizeof(agent) - 1); - if (!hwaddr_aton(agent, cmdu->origin)) + if (band == 2) + band = BAND_2; + else if (band == 5) + band = BAND_5; + else { + trace("|%s:%d| Please provide band as '2', '5' or N/A\n", + __func__, __LINE__); return UBUS_STATUS_UNKNOWN_ERROR; + } } - if (tb[SEARCH_POLICY_EGRESS]) - strncpy(cmdu->intf_name, blobmsg_data(tb[SEARCH_POLICY_EGRESS]), - sizeof(cmdu->intf_name) - 1); - else - strncpy(cmdu->intf_name, "br-lan", sizeof(cmdu->intf_name) - 1); - - cmdu->message_type = CMDU_TYPE_AP_AUTOCONFIGURATION_SEARCH; - - p = calloc(1, sizeof(struct tlv_supp_service)); - if (!p) - goto fail_cmdu; - - cmdu->num_tlvs++; - p->tlv_type = MAP_TLV_SUPPORTED_SERVICE; - p->supported_services_list = 1; - p->supported_services = calloc(p->supported_services_list, - sizeof(*p->supported_services)); - if (!p->supported_services) - goto fail_p; - - for (i = 0; i < p->supported_services_list; i++) - p->supported_services[i].service = SUPPORTED_SERVICE_MULTIAP_AGENT; - - p1 = calloc(1, sizeof(struct tlv_searched_service)); - if (!p1) - goto fail_p; - - cmdu->num_tlvs++; - p1->tlv_type = MAP_TLV_SEARCHED_SERVICE; - p1->searched_services_list = 1; - p1->service = calloc(p1->searched_services_list, sizeof(*p1->service)); - if (!p1->service) - goto fail_p1; - - for (i = 0; i < p->supported_services_list; i++) - p->supported_services[i].service = SEARCHED_SERVICE_MULTIAP_CONTROLLER; - - p2 = calloc(1, sizeof(struct tlv_map_profile)); - if (!p2) - goto fail_p1; - - cmdu->num_tlvs++; - p2->tlv_type = MAP_TLV_MULTIAP_PROFILE; - p2->profile = 0x02; + for (i = 0; i < a->num_radios; i++) { + struct cmdu_cstruct *cmdu; + struct wifi_radio_element *radio = &a->radios[i]; - cmdu->tlvs = (uint8_t **)calloc(cmdu->num_tlvs, - sizeof(uint8_t *)); + if (tb[SEARCH_POLICY_BAND]) + if (band != radio->band) + continue; - if (!cmdu->tlvs) - goto fail_p2; + cmdu = agent_gen_ap_autoconfig_search(a, radio, NULL, 0x02); + if (!cmdu) + continue; - cmdu->tlvs[tlv_index++] = (uint8_t *)p; - cmdu->tlvs[tlv_index++] = (uint8_t *)p1; - cmdu->tlvs[tlv_index++] = (uint8_t *)p2; + trace("|%s:%d| Sending Autoconfig Search for radio %s(%s)\n", + __func__, __LINE__, radio->name, + (radio->band == BAND_2 ? "2.4GHz" : "5GHz")); + agent_send_cmdu(a, cmdu); + map_free_cmdu(cmdu); + } - agent_send_cmdu(a, cmdu); - map_free_cmdu(cmdu); return 0; - -fail_p2: - map_free_tlv_cstruct((uint8_t *) p2); -fail_p1: - map_free_tlv_cstruct((uint8_t *) p1); -fail_p: - map_free_tlv_cstruct((uint8_t *) p); -fail_cmdu: - free(cmdu); - return UBUS_STATUS_UNKNOWN_ERROR; } int agent_publish_object(struct agent *a, const char *objname) @@ -519,9 +462,9 @@ int agent_publish_object(struct agent *a, const char *objname) struct ubus_object *obj; struct ubus_object_type *obj_type; struct ubus_method *obj_methods; - struct ubus_method m[8] = { - UBUS_METHOD("ap_search", agent_ap_search, search_policy_params), - UBUS_METHOD("config_ap", agent_config_ap, config_policy_params), + struct ubus_method m[7] = { + UBUS_METHOD("apconfig", agent_ap_search, search_policy_params), + //UBUS_METHOD("config_ap", agent_config_ap, config_policy_params), UBUS_METHOD("steer_policy", steer_policy, steer_policy_params), UBUS_METHOD("steer", steer, steer_params), UBUS_METHOD("assoc_control", assoc_control, @@ -616,27 +559,6 @@ void agent_remove_object(struct agent *a) } } -/* -struct ubus_method wifiagent_methods[] = { - UBUS_METHOD("config_ap", agent_config_ap, config_ap_params), - UBUS_METHOD("steer_policy", steer_policy, steer_policy_params), - UBUS_METHOD("steer", steer, steer_params), - UBUS_METHOD("assoc_control", assoc_control, assoc_control_params), - UBUS_METHOD("cmd", cmd, cmd_params), - UBUS_METHOD("cmd_async", cmd_async, cmd_params), - UBUS_METHOD_NOARG("status", agent_status), -}; - -struct ubus_object_type wifiagent_type = - UBUS_OBJECT_TYPE("map.agent", wifiagent_methods); - -struct ubus_object wifiagent_object = { - .name = "map.agent", - .type = &wifiagent_type, - .methods = wifiagent_methods, - .n_methods = ARRAY_SIZE(wifiagent_methods), -}; -*/ #ifdef NOTIFY_EVENTS void wifiagent_notify_event(struct agent *a, void *ev_type, void *ev_data) { diff --git a/src/core/config.c b/src/core/config.c index 5661d95c074f0ac7f2e14dde0fee889ef2f0d2eb..5db119a0dafd3f39902f58a1dd5d41000a57b48c 100644 --- a/src/core/config.c +++ b/src/core/config.c @@ -49,7 +49,7 @@ #define UCI_WLAN_IFACE "wifi-iface" #define UCI_WIRELESS "wireless" #define UCI_IEEE1905 "ieee1905" -#define UCI_AGENT "agent" +#define UCI_AGENT "mapagent" int verbose; @@ -73,6 +73,34 @@ int set_value(struct uci_context *ctx, struct uci_package *pkg, return -1; } +int set_value_by_string(const char *package, const char *section, + const char *key, const char *value, enum uci_option_type type) +{ + struct uci_ptr ptr = {0}; + struct uci_context *ctx; + int rv; + + ctx = uci_alloc_context(); + if (!ctx) + return -1; + + ptr.package = package; + ptr.section = section; + ptr.option = key; + ptr.value = value; + + if (type == UCI_TYPE_STRING) + rv = uci_set(ctx, &ptr); + + if (type == UCI_TYPE_LIST) + rv = uci_add_list(ctx, &ptr); + + uci_commit(ctx, &ptr.p, false); + + uci_free_context(ctx); + return -1; +} + struct uci_section *config_get_iface_section(struct uci_context *ctx, struct uci_package *pkg, const char *type, const char *ifname) { @@ -104,6 +132,7 @@ struct uci_package *uci_load_pkg(struct uci_context **ctx, const char *config) if (!*ctx) return NULL; } + if (uci_load(*ctx, config, &pkg) != UCI_OK) { free(*ctx); return NULL; @@ -112,6 +141,48 @@ struct uci_package *uci_load_pkg(struct uci_context **ctx, const char *config) return pkg; } +/* TODO: causes segfault in disc? */ +char *uci_get_bridge(char *ifname, char *bridge) +{ + struct uci_context *ctx; + struct uci_package *pkg; + struct uci_element *e; + + strncpy(bridge, "lan", 15); + return bridge; + + pkg = uci_load_pkg(&ctx, UCI_WIRELESS); + if (!pkg) + return NULL; + + uci_foreach_element(&pkg->sections, e) { + struct uci_section *s = uci_to_section(e); + struct uci_option *opt; + + if (strcmp(s->type, UCI_WLAN_IFACE)) + continue; + + opt = uci_lookup_option(ctx, s, "ifname"); + if (!opt || opt->type != UCI_TYPE_STRING) + continue; + + if (!strncmp(opt->v.string, ifname, 16)) + continue; + + opt = uci_lookup_option(ctx, s, "network"); + if (!opt || opt->type != UCI_TYPE_STRING) + continue; + + strncpy(bridge, opt->v.string, 16); + break; + } + + uci_unload(ctx, pkg); + uci_free_context(ctx); + return bridge; +} + + /* TODO: can it be generalized? */ int wifi_set_iface_bssid(const char *ifname, uint8_t *bssid) { @@ -201,9 +272,9 @@ int wifi_apply_iface_cfg(const char *ifname, const char *encryption, set_value(ctx, pkg, section, "encryption", encryption, UCI_TYPE_STRING); set_value(ctx, pkg, section, "ssid", ssid, UCI_TYPE_STRING); set_value(ctx, pkg, section, "key", key, UCI_TYPE_STRING); + set_value(ctx, pkg, section, "wds", "1", UCI_TYPE_STRING); uci_commit(ctx, &pkg, false); - out_pkg: uci_unload(ctx, pkg); out_uci: @@ -342,7 +413,7 @@ out: } /* below functions are mostly taken from ieee1905d */ -static bool uci_check_wifi_iface(char *package_name, char *ifname, +bool uci_check_wifi_iface(char *package_name, char *ifname, char *section) { bool ret; @@ -384,7 +455,7 @@ static bool uci_check_wifi_iface(char *package_name, char *ifname, return ret; } -static bool uci_set_wireless_interface_option(char *package_name, +bool uci_set_wireless_interface_option(char *package_name, char *section_type, char *ifname, char *option, char *value) { struct uci_context *ctx; @@ -468,7 +539,7 @@ static bool get_encryption_value(uint16_t auth_type, uint16_t encryption_type, return true; } -static bool uci_add_wireless_iface_sec(char *package_name, char *interface_name, +bool uci_add_wireless_iface_sec(char *package_name, char *interface_name, char *section_name) { struct uci_context *ctx; @@ -555,7 +626,50 @@ bool uci_reload_services(void) return false; } -int uci_apply_m2(char *interface_name, uint8_t *ssid, uint8_t *bssid, +/* TODO: introduce option and vendor extension to make this logic redundant */ +int uci_apply_wps_credentials(struct agent_config *cfg, enum wifi_band band) +{ + struct netif_bkcfg *bk; + struct netif_fhcfg *fh; + + list_for_each_entry(bk, &cfg->bklist, list) { + if (bk->band != band) + continue; + + list_for_each_entry(fh, &cfg->fhlist, list) { + if (fh->band != band) + continue; + + dbg("Applying bBSS credentials to %s:\n", fh->name); + dbg(" - SSID : %s\n", bk->ssid); + dbg(" - NETWORK_KEY : %s\n", bk->key); + + uci_set_wireless_interface_option(UCI_WIRELESS, + UCI_WLAN_IFACE, + fh->name, + "multi_ap_backhaul_ssid", + bk->ssid); + uci_set_wireless_interface_option(UCI_WIRELESS, + UCI_WLAN_IFACE, + fh->name, + "multi_ap_backhaul_key", + bk->key); + uci_set_wireless_interface_option(UCI_WIRELESS, + UCI_WLAN_IFACE, fh->name, "wps", "1"); + uci_set_wireless_interface_option(UCI_WIRELESS, + UCI_WLAN_IFACE, fh->name, + "wps_pushbutton", "1"); + } + + break; + } + + return 0; +} + + +/* TODO: batch the changes arther than commit oneby one */ +int uci_apply_m2(char *interface_name, char *device, uint8_t *ssid, uint16_t auth_type, uint16_t encryption_type, uint8_t *network_key, uint8_t mapie, uint8_t band) { @@ -563,13 +677,12 @@ int uci_apply_m2(char *interface_name, uint8_t *ssid, uint8_t *bssid, char auth_type_str[20] = {0}; char multiap_str[2] = {0}; uint8_t multi_ap = 0; - bool sta_mode; + bool bk_mode; char band_str[2] = {0}; + char agent_section[16] = {0}; dbg("Applying WSC configuration (%s):\n", interface_name); dbg(" - SSID : %s\n", ssid); - dbg(" - BSSID : %02x:%02x:%02x:%02x:%02x:%02x\n", - bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); dbg(" - AUTH_TYPE : 0x%04x\n", auth_type); dbg(" - ENCRYPTION_TYPE : 0x%04x\n", encryption_type); dbg(" - NETWORK_KEY : %s\n", network_key); @@ -581,7 +694,7 @@ int uci_apply_m2(char *interface_name, uint8_t *ssid, uint8_t *bssid, multi_ap |= (BIT(5, mapie) << 1); multi_ap |= BIT(6, mapie); - sta_mode = BIT(7, mapie); + bk_mode = BIT(6, mapie); snprintf(multiap_str, sizeof(multiap_str), "%d", multi_ap); @@ -591,18 +704,19 @@ int uci_apply_m2(char *interface_name, uint8_t *ssid, uint8_t *bssid, return M2_PROCESS_ERROR; } + strncpy(agent_section, (bk_mode ? UCI_BK_AGENT : UCI_FH_AGENT), + sizeof(agent_section)); + // Set uci in agent ret = uci_check_wifi_iface(UCI_AGENT, interface_name, - (sta_mode ? UCI_BK_AGENT : UCI_FH_AGENT)); + agent_section); if (!ret) { ret = uci_add_wireless_iface_sec(UCI_AGENT, interface_name, - (sta_mode ? UCI_BK_AGENT : UCI_FH_AGENT)); + agent_section); if (!ret) return M2_PROCESS_ERROR; } - printf("%s band = %d\n", __func__, band); - if (band == BAND_5) strncpy(band_str, "5", 1); else if (band == BAND_2) @@ -610,42 +724,29 @@ int uci_apply_m2(char *interface_name, uint8_t *ssid, uint8_t *bssid, else /* TODO: 60 */ return M2_PROCESS_ERROR; - uci_set_wireless_interface_option(UCI_AGENT, - (sta_mode ? UCI_BK_AGENT : UCI_FH_AGENT), - interface_name, "band", - band_str); - if (sta_mode) { + uci_set_wireless_interface_option(UCI_AGENT, agent_section, + interface_name, "band", band_str); + uci_set_wireless_interface_option(UCI_AGENT, agent_section, + interface_name, "band", band_str); + uci_set_wireless_interface_option(UCI_AGENT, agent_section, + interface_name, "device", device); + uci_set_wireless_interface_option(UCI_AGENT, agent_section, + interface_name, "ssid", ssid); + uci_set_wireless_interface_option(UCI_AGENT, agent_section, + interface_name, "key", network_key); + uci_set_wireless_interface_option(UCI_AGENT, agent_section, + interface_name, "encryption", auth_type_str); + if (bk_mode) { char disallow_str[2] = {0}; snprintf(disallow_str, sizeof(disallow_str), "%d", ((mapie >> 2) & 0x03)); uci_set_wireless_interface_option(UCI_AGENT, - (sta_mode ? UCI_BK_AGENT : UCI_FH_AGENT), + UCI_BK_AGENT, interface_name, "disallow_bsta", disallow_str); } - // Set uci in ieee1905 - ret = uci_check_wifi_iface(UCI_IEEE1905, interface_name, - UCI_WLAN_IFACE); - if (!ret) { - ret = uci_add_wireless_iface_sec(UCI_IEEE1905, interface_name, - UCI_WLAN_IFACE); - if (!ret) - return M2_PROCESS_ERROR; - } - - uci_set_wireless_interface_option(UCI_IEEE1905, UCI_WLAN_IFACE, - interface_name, "ssid", (char *) ssid); - uci_set_wireless_interface_option(UCI_IEEE1905, UCI_WLAN_IFACE, - interface_name, "key", (char *) network_key); - uci_set_wireless_interface_option(UCI_IEEE1905, UCI_WLAN_IFACE, - interface_name, "encryption", auth_type_str); - uci_set_wireless_interface_option(UCI_IEEE1905, UCI_WLAN_IFACE, - interface_name, "multi_ap", multiap_str); - uci_set_wireless_interface_option(UCI_IEEE1905, UCI_WLAN_IFACE, - interface_name, "mode", (sta_mode ? "sta" : "ap")); - // Set uci in wireless ret = uci_check_wifi_iface(UCI_WIRELESS, interface_name, UCI_WLAN_IFACE); @@ -656,6 +757,8 @@ int uci_apply_m2(char *interface_name, uint8_t *ssid, uint8_t *bssid, return M2_PROCESS_ERROR; } + uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, + interface_name, "network", "lan"); uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, interface_name, "ssid", (char *) ssid); uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, @@ -663,11 +766,15 @@ int uci_apply_m2(char *interface_name, uint8_t *ssid, uint8_t *bssid, uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, interface_name, "encryption", auth_type_str); uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, - interface_name, "multi_ap", multiap_str); + interface_name, "mode", "ap"); uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, - interface_name, "mode", (sta_mode ? "sta" : "ap")); - - uci_reload_services(); + interface_name, "device", device); + uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, + interface_name, "multi_ap", multiap_str); + if (bk_mode) { + uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, + interface_name, "hidden", "1"); + } return M2_PROCESS_OK; } /* end of functions taken from ieee1905d */ @@ -802,77 +909,6 @@ void agent_config_dump(struct agent_config *cfg) } } -int agent_config_defaults(struct agent *a, struct agent_config *cfg) -{ - struct list_head *p, *tmp; - struct netif_fh *ifptr; - struct netif_fhcfg *new; - - if (!cfg) - return -1; - - cfg->enabled = false; - cfg->runfreq = AGENT_RUN_AUTO; - - INIT_LIST_HEAD(&cfg->fhlist); - INIT_LIST_HEAD(&cfg->bklist); - list_for_each_entry(ifptr, &a->fhlist, list) { - /* struct list_head pollist; */ - struct steer_rule *r; - - new = calloc(1, sizeof(struct netif_fhcfg)); - if (!new) { - warn("OOM! config\n"); - goto err_alloc; - } - - snprintf(new->name, 16, "%s", ifptr->name); - new->enabled = false; - new->steer_btm_retry = STEER_BTM_RETRY; - new->steer_btm_retry_secs = STEER_BTM_RETRY_INT; - new->fallback_legacy = STEER_LEGACY_FALLBACK_INT; - new->steer_legacy_reassoc_secs = STEER_LEGACY_REASSOC_INT; - new->steer_legacy_retry_secs = STEER_LEGACY_RETRY_INT; - new->assoc_control_time = ASSOC_CONTROL_INT; - INIT_LIST_HEAD(&new->steer_policylist); - /* nrules = get_registered_steer_rules(&pollist); */ /* TODO */ - list_for_each_entry(r, ®d_steer_rules, list) { - struct steer_policy *pol; - - pol = calloc(1, sizeof(struct steer_policy)); - if (!pol) - goto err_alloc_policy; - - snprintf(pol->name, 16, "%s", r->name); - pol->enabled = false; - if (r->init_config) - r->init_config(r, &pol->policy); - list_add(&pol->list, &new->steer_policylist); - } - - INIT_LIST_HEAD(&new->steer_excludelist); - INIT_LIST_HEAD(&new->steer_btm_excludelist); - INIT_LIST_HEAD(&new->assoc_ctrllist); - - ifptr->cfg = new; - dbg("%s: %s netif_fh->cfg = %p\n", __func__, ifptr->name, - ifptr->cfg); - list_add(&new->list, &cfg->fhlist); - } - - return 0; - -err_alloc_policy: - /* TODO */ -err_alloc: - list_for_each_safe(p, tmp, &cfg->fhlist) { - list_del(p); - free(p); - } - - return -1; -} - /* create fh-iface config and initialize with default values */ struct netif_fhcfg *create_fronthaul_iface_config(struct agent_config *cfg, const char *ifname) @@ -1174,18 +1210,24 @@ void register_config(struct config *c) #endif static int agent_config_get_wifi_agent(struct agent_config *a, - struct uci_section *s) + struct uci_section *s) { enum { A_ENABLED, A_DEBUG, A_PROFILE, + A_BRCM_SETUP, + /*A_CONFIGURED,*/ + A_CNTLR_MAC, NUM_POLICIES }; const struct uci_parse_option opts[] = { { .name = "enabled", .type = UCI_TYPE_STRING }, { .name = "debug", .type = UCI_TYPE_STRING }, { .name = "profile", .type = UCI_TYPE_STRING }, + { .name = "brcm_setup", .type = UCI_TYPE_STRING }, + /*{ .name = "configured", .type = UCI_TYPE_STRING },*/ + { .name = "controller_macaddr", .type = UCI_TYPE_STRING }, }; struct uci_option *tb[NUM_POLICIES]; @@ -1203,24 +1245,41 @@ static int agent_config_get_wifi_agent(struct agent_config *a, if (tb[A_PROFILE]) a->profile = atoi(tb[A_PROFILE]->v.string); + if (tb[A_BRCM_SETUP]) + a->brcm_setup = atoi(tb[A_BRCM_SETUP]->v.string); + + /*if (tb[A_CONFIGURED]) + a->configured = atoi(tb[A_CONFIGURED]->v.string);*/ + + if (tb[A_CNTLR_MAC]) + hwaddr_aton(tb[A_CNTLR_MAC]->v.string, a->cntlr_almac); + return 0; } static int agent_config_get_bk_iface(struct agent_config *a, - struct uci_section *s) + struct uci_section *s) { enum { BK_IFNAME, + BK_DEVICE, BK_BAND, BK_ENABLED, BK_ONBOARDED, + BK_SSID, + BK_KEY, + BK_ENCRYPTION, NUM_POLICIES }; const struct uci_parse_option opts[] = { { .name = "ifname", .type = UCI_TYPE_STRING }, + { .name = "device", .type = UCI_TYPE_STRING }, { .name = "band", .type = UCI_TYPE_STRING }, { .name = "enabled", .type = UCI_TYPE_STRING }, - { .name = "onboarded", .type = UCI_TYPE_STRING } + { .name = "onboarded", .type = UCI_TYPE_STRING }, + { .name = "ssid", .type = UCI_TYPE_STRING }, + { .name = "key", .type = UCI_TYPE_STRING }, + { .name = "encryption", .type = UCI_TYPE_STRING } }; struct uci_option *tb[NUM_POLICIES]; struct netif_bkcfg *bk; @@ -1246,6 +1305,13 @@ static int agent_config_get_bk_iface(struct agent_config *a, return -1; } + if (tb[BK_DEVICE]) { + const char *device; + + device = tb[BK_DEVICE]->v.string; + strncpy(bk->device, device, sizeof(bk->device) - 1); + } + if (tb[BK_ENABLED]) bk->enabled = atoi(tb[BK_ENABLED]->v.string); @@ -1261,6 +1327,27 @@ static int agent_config_get_bk_iface(struct agent_config *a, bk->band = BAND_5; } + if (tb[BK_SSID]) { + const char *ssid; + + ssid = tb[BK_SSID]->v.string; + strncpy(bk->ssid, ssid, sizeof(bk->ssid) - 1); + } + + if (tb[BK_KEY]) { + const char *key; + + key = tb[BK_KEY]->v.string; + strncpy(bk->key, key, sizeof(bk->key) - 1); + } + + if (tb[BK_ENCRYPTION]) { + const char *encryption; + + encryption = tb[BK_ENCRYPTION]->v.string; + strncpy(bk->encryption, encryption, sizeof(bk->encryption) - 1); + } + return 0; } @@ -1271,6 +1358,7 @@ static int agent_config_get_fh_iface(struct agent_config *a, FH_IFNAME, FH_BAND, FH_STEER, + FH_DEVICE, FH_EXCLUDE, FH_EXCLUDE_BTM, FH_ASSOC_CTRL, @@ -1280,12 +1368,16 @@ static int agent_config_get_fh_iface(struct agent_config *a, FH_STEER_LEGACY_RASSOC_SECS, FH_STEER_LEGACY_RETRY_SECS, FH_ASSOC_CTRL_SECS, + FH_SSID, + FH_KEY, + FH_ENCRYPTION, NUM_POLICIES, }; const struct uci_parse_option opts[] = { { .name = "ifname", .type = UCI_TYPE_STRING }, { .name = "band", .type = UCI_TYPE_STRING }, { .name = "steer", .type = UCI_TYPE_LIST }, + { .name = "device", .type = UCI_TYPE_STRING }, { .name = "exclude", .type = UCI_TYPE_LIST }, { .name = "exclude_btm", .type = UCI_TYPE_LIST }, { .name = "assoc_ctrl", .type = UCI_TYPE_LIST }, @@ -1294,7 +1386,10 @@ static int agent_config_get_fh_iface(struct agent_config *a, { .name = "fallback_legacy", .type = UCI_TYPE_STRING }, { .name = "steer_legacy_reassoc_secs", .type = UCI_TYPE_STRING }, { .name = "steer_legacy_retry_secs", .type = UCI_TYPE_STRING }, - { .name = "assoc_ctrl_secs", .type = UCI_TYPE_STRING } + { .name = "assoc_ctrl_secs", .type = UCI_TYPE_STRING }, + { .name = "ssid", .type = UCI_TYPE_STRING }, + { .name = "key", .type = UCI_TYPE_STRING }, + { .name = "encryption", .type = UCI_TYPE_STRING } }; struct uci_option *tb[NUM_POLICIES]; struct netif_fhcfg *fh; @@ -1356,6 +1451,14 @@ static int agent_config_get_fh_iface(struct agent_config *a, dbg("\n"); } + if (tb[FH_DEVICE]) { + const char *device; + + device = tb[FH_DEVICE]->v.string; + + strncpy(fh->device, device, sizeof(fh->device) - 1); + } + if (tb[FH_EXCLUDE]) { struct uci_element *xi; @@ -1399,6 +1502,27 @@ static int agent_config_get_fh_iface(struct agent_config *a, fh->assoc_control_time = atoi(tb[FH_ASSOC_CTRL_SECS]->v.string); + if (tb[FH_SSID]) { + const char *ssid; + + ssid = tb[FH_SSID]->v.string; + strncpy(fh->ssid, ssid, sizeof(fh->ssid) - 1); + } + + if (tb[FH_KEY]) { + const char *key; + + key = tb[FH_KEY]->v.string; + strncpy(fh->key, key, sizeof(fh->key) - 1); + } + + if (tb[FH_ENCRYPTION]) { + const char *encryption; + + encryption = tb[FH_ENCRYPTION]->v.string; + strncpy(fh->encryption, encryption, sizeof(fh->encryption) - 1); + } + return 0; } @@ -1431,7 +1555,7 @@ int agent_config_reload(struct agent_config *cfg) if (!ctx) return -1; - if (uci_load(ctx, "agent", &pkg)) { + if (uci_load(ctx, "mapagent", &pkg)) { uci_free_context(ctx); return -1; } @@ -1439,7 +1563,7 @@ int agent_config_reload(struct agent_config *cfg) uci_foreach_element(&pkg->sections, e) { struct uci_section *s = uci_to_section(e); - if (!strcmp(s->type, "wifiagent")) + if (!strcmp(s->type, "agent")) agent_config_get_wifi_agent(cfg, s); else if (!strcmp(s->type, "fh-iface")) agent_config_get_fh_iface(cfg, s); diff --git a/src/core/config.h b/src/core/config.h index f676ac23ad75091e5f73f9869fdb98d1a4a456d9..f10840a1e72155cfd0531af5b9f98492b0368b3d 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -55,6 +55,10 @@ void stax_del_entry(struct list_head *h, char *sta_macstr); */ struct netif_fhcfg { char name[16]; + char device[16]; + char ssid[33]; + char key[65]; + char encryption[32]; enum wifi_band band; bool enabled; bool sta_steer_enabled; @@ -92,6 +96,10 @@ struct netif_fhcfg { struct netif_bkcfg { char name[16]; enum wifi_band band; + char device[16]; + char ssid[33]; + char key[65]; + char encryption[32]; bool enabled; bool onboarded; /* TODO: others as needed */ @@ -116,6 +124,9 @@ struct agent_config { unsigned char oui0[32]; int ouis; uint8_t profile; + bool brcm_setup; + bool configured; + uint8_t cntlr_almac[6]; }; #if 0 @@ -137,11 +148,14 @@ enum m2_process_status { int set_value(struct uci_context *ctx, struct uci_package *pkg, struct uci_section *section, const char *key, const char *value, enum uci_option_type type); +int set_value_by_string(const char *package, const char *section, + const char *key, const char *value, enum uci_option_type type); struct uci_section *config_get_iface_section(struct uci_context *ctx, struct uci_package *pkg, const char *type, const char *ifname); bool uci_reload_services(void); struct uci_package *uci_load_pkg(struct uci_context **ctx, const char *config); int wifi_set_iface_bssid(const char *ifname, uint8_t *bssid); +char *uci_get_bridge(char *ifname, char *bridge); /* END TODO */ @@ -170,12 +184,20 @@ int config_add_default_wifi_iface(const char *config, const char *type, const char *ifname, const char *device, const char *network, const char *mode); +bool uci_check_wifi_iface(char *package_name, char *ifname, + char *section); +bool uci_set_wireless_interface_option(char *package_name, + char *section_type, char *ifname, char *option, char *value); +bool uci_add_wireless_iface_sec(char *package_name, char *interface_name, + char *section_name); + void clean_bk(struct netif_bkcfg *p); int clean_all_bk(struct agent_config *cfg); void clean_fh(struct netif_fhcfg *p); int clean_all_fh(struct agent_config *cfg); -int uci_apply_m2(char *interface_name, uint8_t *ssid, uint8_t *bssid, +int uci_apply_m2(char *interface_name, char *device, uint8_t *ssid, uint16_t auth_type, uint16_t encryption_type, uint8_t *network_key, uint8_t mapie, uint8_t band); +int uci_apply_wps_credentials(struct agent_config *cfg, enum wifi_band band); #endif diff --git a/src/utils/brcm_nl.c b/src/utils/brcm_nl.c new file mode 100644 index 0000000000000000000000000000000000000000..25cd402e7b1e47243d033866d471d856f1e6657c --- /dev/null +++ b/src/utils/brcm_nl.c @@ -0,0 +1,109 @@ + +/* + * compile: + * gcc -I/usr/include/libnl3 -o nl_rtlink nl_rtlink.c -lnl-3 -lnl-route-3 + */ +#include <stdio.h> +#include <stdlib.h> +#include <sys/socket.h> +#include <net/if.h> +#include <uci.h> +#include <string.h> + +#include <netlink/netlink.h> +#include <netlink/socket.h> +#include <netlink/msg.h> + +#include <sys/ioctl.h> +#include <net/if.h> + +#include <libubox/blobmsg.h> +#include <libubox/blobmsg_json.h> +#include <libubox/uloop.h> +#include <libubox/ustream.h> +#include <libubox/utils.h> +#include <libubus.h> + +#include <easy/easy.h> + +#define UCI_WIRELESS "wireless" +#define UCI_WLAN_IFACE "wifi-iface" + +static bool get_bridge(char *ifname, char *bridge) +{ + strncpy(bridge, "br-lan", 15); + return true; +} + +static int func(struct nl_msg *msg, void *arg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + + switch (nlh->nlmsg_type) { + case RTM_NEWLINK: + case RTM_DELLINK: + { + struct ifinfomsg *ifi; + char ifname[16] = {0}; + char bridge[16] = {0}; + int ret; + + ifi = NLMSG_DATA(nlh); + + if_indextoname(ifi->ifi_index, ifname); + + //printf("ifname = %s ifindex = %d status = %s\n", + // ifname, + // ifi->ifi_index, + // !!(ifi->ifi_flags & IFF_UP) ? "up" : "down"); + + //if (!(ifi->ifi_flags & IFF_UP)) + // break; + + if (!strstr(ifname, "wds")) + break; + + if (!get_bridge(ifname, bridge)) + break; + + /* add wds iface to bridge */ + ret = br_addif(bridge, ifname); + if (!ret) + printf("Successfully added interface %s to " \ + "bridge %s\n", ifname, bridge); + + /* bring up wds interface */ + ret = if_setflags(ifname, IFF_UP); + if (!ret) + printf("Successfully brought up interface %s", + ifname); + break; + } + default: + break; + + } + + return 0; +} + +int brcm_nl_loop(void) +{ + struct nl_sock *sk; + + sk = nl_socket_alloc(); + if (!sk) + return 1; + + nl_socket_disable_seq_check(sk); + + nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, func, NULL); + + nl_connect(sk, NETLINK_ROUTE); + nl_socket_add_memberships(sk, RTNLGRP_LINK, 0); + + for (;;) + nl_recvmsgs_default(sk); + + return 0; +} diff --git a/src/utils/brcm_nl.h b/src/utils/brcm_nl.h new file mode 100644 index 0000000000000000000000000000000000000000..d87d288bc879b35119f29a587efbf435397cac91 --- /dev/null +++ b/src/utils/brcm_nl.h @@ -0,0 +1,6 @@ +#ifndef BRCM_NL_H +#define BRCM_NL + +int brcm_nl_loop(void); + +#endif diff --git a/src/utils/debug.c b/src/utils/debug.c index 77291aee5d0b61b67cb0a4a55f011e4fb1737569..411077e287639a7289e88a4814844880288e225f 100644 --- a/src/utils/debug.c +++ b/src/utils/debug.c @@ -200,7 +200,6 @@ void log_test(int level, void *var, int len) fprintf(testfile, "%s\n", bstr); fflush(testfile); -out: free(bstr); } diff --git a/src/utils/utils.c b/src/utils/utils.c index 62872845b3cde10d781029505b498b28114107d7..7d44bb921308d7ab2b8ae1cfbffdc26bff407123 100644 --- a/src/utils/utils.c +++ b/src/utils/utils.c @@ -21,6 +21,9 @@ #include <libubox/list.h> #include <json-c/json.h> +#include <easy/easy.h> +#include <wifi.h> + #include "debug.h" bool match_oui0(unsigned char *oui, unsigned char *hwaddr, int ouis) @@ -444,3 +447,24 @@ bool json_get_bool(struct json_object *object, const char *key) return json_object_get_boolean(value) ? 1 : 0; } + +uint8_t wifi_band_to_ieee1905band(uint8_t band) +{ + uint8_t ieee1905band = -1; + + switch (band) { + case BAND_2: + ieee1905band = 0x00; + break; + case BAND_5: + ieee1905band = 0x01; + break; + case BAND_60: + ieee1905band = 0x02; + break; + default: + break; + } + + return ieee1905band; +} diff --git a/src/utils/utils.h b/src/utils/utils.h index bdde468c60083796cb1c2353f404080f3b441fa1..3dabc4c8169711c1f40227d882e74adeaee319b5 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h @@ -155,5 +155,6 @@ int list_dup(struct list_head *h, struct list_head *new, int set_sighandler(int sig, void (*handler)(int)); int unset_sighandler(int sig); void do_daemonize(const char *pidfile); +uint8_t wifi_band_to_ieee1905band(uint8_t band); #endif /* UTILS_H */