From 7a86382fb13a87c7afcb4401b2325bfbe03713a4 Mon Sep 17 00:00:00 2001 From: Jakob Olsson <jakob.olsson@iopsys.eu> Date: Fri, 29 Jan 2021 13:24:43 +0100 Subject: [PATCH] map-agent: autoconfig: parse IOPSYS vendor extensions in m2 --- src/core/agent.c | 22 +++++-- src/core/agent.h | 1 + src/core/agent_map.c | 13 ++-- src/core/config.c | 141 +++++++++++++++++++++++++++++++++++-------- src/core/config.h | 8 ++- 5 files changed, 150 insertions(+), 35 deletions(-) diff --git a/src/core/agent.c b/src/core/agent.c index b5bf5841e..68ebaeb55 100644 --- a/src/core/agent.c +++ b/src/core/agent.c @@ -2033,8 +2033,6 @@ static void wifi_wps_creds_event_handler(void *c, struct blob_attr *msg) if (!ret) return; } - uci_set_wireless_interface_option("mapagent", "bk-iface", ifname, - "onboarded", "1"); uci_reload_services(); @@ -2043,6 +2041,8 @@ static void wifi_wps_creds_event_handler(void *c, struct blob_attr *msg) return; radio->onboarded = 1; + uci_set_wireless_interface_option("mapagent", "wifi-radio", "device", + radio->name, "onboarded", "1"); } static void ubus_wifi_event_handler(struct ubus_context *ctx, @@ -2761,13 +2761,27 @@ static void _enumerate_wifi_objects(struct ubus_request *req, int type, char r_objname[32] = {0}; const char *r_fmt = "wifi.radio.%s"; wifi_object_t r_wobj = WIFI_OBJECT_INVALID; - + struct agent_config_radio *r_cfg; radio_obj = json_object_array_get_idx(radio_array, i); json_object_object_get_ex(radio_obj, "name", &radio_obj_name); radio_name = json_object_get_string(radio_obj_name); strncpy(a->ifs[i].radio, radio_name, 15); strncpy(a->radios[i].name, radio_name, 15); + list_for_each_entry(r_cfg, &a->cfg.radiolist, list) { + if (strncmp(r_cfg->name, a->radios[i].name, 15)) + continue; + + a->radios[i].onboarded = r_cfg->onboarded; + a->radios[i].configured = r_cfg->configured; + break; + } + + // parse channel range + // if channel range is stricly beneath <= 64, assign low + // else if channel rangei stricly above 100, >= 100, assign high + // else if both ranges, no assignation + json_object_object_get_ex(radio_obj, "accesspoints", &fh_array); fh_len = json_object_array_length(fh_array); for (j = 0; j < fh_len; j++) { @@ -3366,7 +3380,7 @@ static void agent_dispatch_autoconfig(struct uloop_timeout *t) struct cmdu_cstruct *cmdu; struct wifi_radio_element *radio = &a->radios[i]; - if (radio->onboarded) { + if (radio->onboarded || radio->configured) { dbg("radio %s has been onboarded, don't trigger search\n", radio->name); continue; diff --git a/src/core/agent.h b/src/core/agent.h index ab9c2e13b..599608b9f 100644 --- a/src/core/agent.h +++ b/src/core/agent.h @@ -338,6 +338,7 @@ struct wifi_radio_element { uint8_t macaddr[6]; uint8_t country_code[2]; bool onboarded; + bool configured; enum wifi_band band; bool enabled; int anpi; diff --git a/src/core/agent_map.c b/src/core/agent_map.c index a3c90ac4f..1ea5925e7 100644 --- a/src/core/agent_map.c +++ b/src/core/agent_map.c @@ -826,7 +826,10 @@ int handle_ap_autoconfig_wsc(void *agent, struct cmdu_cstruct *cmdu) out.output.auth_types, out.output.encryption_types, out.output.network_key, - out.output.mapie, radio->band); + out.output.mapie, radio->band, + out.output.bridge, out.output.proto, + out.output.vid, out.output.br_ip, + out.output.bk_ssid, out.output.bk_key); break; } default: @@ -834,11 +837,13 @@ int handle_ap_autoconfig_wsc(void *agent, struct cmdu_cstruct *cmdu) } } - - a->configured = true; + uci_set_wireless_interface_option("mapagent", "wifi-radio", "device", + radio->name, "configured", "1"); + radio->configured = 1; + //a->configured = true; wifi_reorder_interfaces(&a->cfg); agent_config_reload(&a->cfg); - uci_apply_wps_credentials(&a->cfg, radio->band); + //uci_apply_wps_credentials(&a->cfg, radio->band); teardown: // TODO: freeing from here risks freeing an updated frame agent_free_wsc_data(&radio->autconfig); diff --git a/src/core/config.c b/src/core/config.c index 66916719c..14508cdba 100644 --- a/src/core/config.c +++ b/src/core/config.c @@ -437,13 +437,14 @@ bool uci_check_wifi_iface(char *package_name, char *ifname, } bool uci_set_wireless_interface_option(char *package_name, - char *section_type, char *ifname, char *option, char *value) + char *section_type, char *search_key, char *search_val, + char *option, char *value) { struct uci_context *ctx; struct uci_package *pkg; struct uci_element *e; - if (!package_name || !ifname || !option || !value) + if (!package_name || !search_val || !option || !value) return false; ctx = uci_alloc_context(); @@ -460,11 +461,11 @@ bool uci_set_wireless_interface_option(char *package_name, if (!strcmp(s->type, section_type)) { struct uci_option *opt = uci_lookup_option(ctx, s, - "ifname"); + search_key); if (!opt || opt->type != UCI_TYPE_STRING) continue; - if (strcmp(opt->v.string, ifname) == 0) { + if (strcmp(opt->v.string, search_val) == 0) { struct uci_ptr ptr = {0}; ptr.value = value; @@ -611,6 +612,7 @@ bool uci_reload_services(void) return false; } +#if 0 /* Deprecated for 6.1 - Possibly bring back in 6.2 with modifications */ /* TODO: introduce option and vendor extension to make this logic redundant */ int uci_apply_wps_credentials(struct agent_config *cfg, enum wifi_band band) { @@ -631,18 +633,20 @@ int uci_apply_wps_credentials(struct agent_config *cfg, enum wifi_band band) uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, + "ifname", fh->name, "multi_ap_backhaul_ssid", bk->ssid); uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, + "ifname", fh->name, "multi_ap_backhaul_key", bk->key); uci_set_wireless_interface_option(UCI_WIRELESS, - UCI_WLAN_IFACE, fh->name, "wps", "1"); + UCI_WLAN_IFACE, "ifname", fh->name, "wps", "1"); uci_set_wireless_interface_option(UCI_WIRELESS, - UCI_WLAN_IFACE, fh->name, + UCI_WLAN_IFACE, "ifname", fh->name, "wps_pushbutton", "1"); } @@ -651,12 +655,15 @@ int uci_apply_wps_credentials(struct agent_config *cfg, enum wifi_band band) return 0; } +#endif /* 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) + uint8_t *network_key, uint8_t mapie, uint8_t band, + uint8_t *bridge, uint8_t *proto, uint8_t vid, uint32_t br_ip, + uint8_t *bk_ssid, uint8_t *bk_key) { bool ret; char auth_type_str[20] = {0}; @@ -665,6 +672,10 @@ int uci_apply_m2(char *interface_name, char *device, uint8_t *ssid, bool bk_mode; char band_str[2] = {0}; char agent_section[16] = {0}; + char ipaddr_str[INET_ADDRSTRLEN] = {0}; + + inet_ntop(AF_INET, &br_ip, ipaddr_str, INET_ADDRSTRLEN); + dbg("Applying WSC configuration (%s):\n", interface_name); dbg(" - SSID : %s\n", ssid); @@ -672,7 +683,12 @@ int uci_apply_m2(char *interface_name, char *device, uint8_t *ssid, dbg(" - ENCRYPTION_TYPE : 0x%04x\n", encryption_type); dbg(" - NETWORK_KEY : %s\n", network_key); dbg(" - MAPIE_EXTENSION : 0x%02x\n", mapie); - + dbg(" - BRIDGE : %s\n", bridge); + dbg(" - PROTO : %s\n", proto); + dbg(" - VID : 0x%02x\n", vid); + dbg(" - BR_IP : %s\n", ipaddr_str); + dbg(" - BK_SSID : %s\n", bk_ssid); + dbg(" - BK_KEY : %s\n", bk_key); // if teardown bit is set, return if (BIT(3, mapie)) return M2_PROCESS_TEARDOWN; @@ -683,12 +699,22 @@ int uci_apply_m2(char *interface_name, char *device, uint8_t *ssid, snprintf(multiap_str, sizeof(multiap_str), "%d", multi_ap); + //snprintf(ipaddr_str, sizeof(ipaddr_str), "%d.%d.%d.%d", br_ip[0], + // br_ip[1], br_ip[2], br_ip[3]); + if (!get_encryption_value(auth_type, encryption_type, auth_type_str, 20)) { info("Unsupported encryption or cipher received!!\n"); return M2_PROCESS_ERROR; } + ret = uci_set_bridge("network", bridge, proto, ipaddr_str); + if (ret) { + info("Error seting up bridge from M2!\n"); + return M2_PROCESS_ERROR; + } + + strncpy(agent_section, (bk_mode ? UCI_BK_AGENT : UCI_FH_AGENT), sizeof(agent_section)); @@ -709,17 +735,17 @@ int uci_apply_m2(char *interface_name, char *device, uint8_t *ssid, else /* TODO: 60 */ return M2_PROCESS_ERROR; - uci_set_wireless_interface_option(UCI_AGENT, agent_section, + uci_set_wireless_interface_option(UCI_AGENT, agent_section, "ifname", interface_name, "band", band_str); - uci_set_wireless_interface_option(UCI_AGENT, agent_section, + uci_set_wireless_interface_option(UCI_AGENT, agent_section, "ifname", interface_name, "band", band_str); - uci_set_wireless_interface_option(UCI_AGENT, agent_section, + uci_set_wireless_interface_option(UCI_AGENT, agent_section, "ifname", interface_name, "device", device); - uci_set_wireless_interface_option(UCI_AGENT, agent_section, + uci_set_wireless_interface_option(UCI_AGENT, agent_section, "ifname", interface_name, "ssid", ssid); - uci_set_wireless_interface_option(UCI_AGENT, agent_section, + uci_set_wireless_interface_option(UCI_AGENT, agent_section, "ifname", interface_name, "key", network_key); - uci_set_wireless_interface_option(UCI_AGENT, agent_section, + uci_set_wireless_interface_option(UCI_AGENT, agent_section, "ifname", interface_name, "encryption", auth_type_str); if (bk_mode) { char disallow_str[2] = {0}; @@ -727,7 +753,7 @@ int uci_apply_m2(char *interface_name, char *device, uint8_t *ssid, snprintf(disallow_str, sizeof(disallow_str), "%d", ((mapie >> 2) & 0x03)); uci_set_wireless_interface_option(UCI_AGENT, - UCI_BK_AGENT, + UCI_BK_AGENT, "ifname", interface_name, "disallow_bsta", disallow_str); } @@ -742,23 +768,34 @@ int uci_apply_m2(char *interface_name, char *device, uint8_t *ssid, 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, + uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, "ifname", + interface_name, "network", bridge); + uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, "ifname", interface_name, "ssid", (char *) ssid); - uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, + uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, "ifname", interface_name, "key", (char *) network_key); - uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, + uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, "ifname", interface_name, "encryption", auth_type_str); - uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, + uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, "ifname", interface_name, "mode", "ap"); - uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, + uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, "ifname", interface_name, "device", device); - uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, + uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, "ifname", interface_name, "multi_ap", multiap_str); + uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, "ifname", + interface_name, "multi_ap_backhaul_key", bk_key); + uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, "ifname", + interface_name, "multi_ap_backhaul_ssid", bk_ssid); + if (bk_mode) { uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, - interface_name, "hidden", "1"); + "ifname", interface_name, "hidden", "1"); + } else { + uci_set_wireless_interface_option(UCI_WIRELESS, + UCI_WLAN_IFACE, "ifname", interface_name, "wps", "1"); + uci_set_wireless_interface_option(UCI_WIRELESS, + UCI_WLAN_IFACE, "ifname", interface_name, + "wps_pushbutton", "1"); } return M2_PROCESS_OK; } @@ -1983,4 +2020,58 @@ int wifi_reorder_interfaces(struct agent_config *a) uci_commit(ctx, &pkg, false); uci_free_context(ctx); return 0; -} \ No newline at end of file +} + +int uci_set_bridge(char *config, char *bridge, char *proto, char *ipaddress) +{ + struct uci_context *ctx = NULL; + struct uci_package *pkg; + struct uci_element *e; + struct uci_section *section = NULL; + + /** if bridge starts with br prefix, step past */ + if (!strncmp(bridge, "br-", 3)) + bridge += 3; + + pkg = uci_load_pkg(&ctx, "network"); + if (!pkg) + return -1; + + uci_foreach_element(&pkg->sections, e) { + struct uci_section *s = uci_to_section(e); + + if (strncmp(s->e.name, bridge, 16)) + continue; + + section = s; + break; + } + + if (!section) { + struct uci_ptr ptr = {0}; + + ptr.p = pkg; + ptr.section = bridge; + ptr.value = "interface"; + ptr.option = NULL; + uci_set(ctx, &ptr); + section = ptr.s; + } + + set_value(ctx, pkg, section, "type", "bridge", UCI_TYPE_STRING); + set_value(ctx, pkg, section, "is_lan", "1", UCI_TYPE_STRING); + if (strlen(proto)) + set_value(ctx, pkg, section, "proto", proto, UCI_TYPE_STRING); + if (!strcmp(proto, "static")) { + set_value(ctx, pkg, section, "ipaddr", ipaddress, + UCI_TYPE_STRING); + set_value(ctx, pkg, section, "netmask", "255.255.255.0", + UCI_TYPE_STRING); + } + + uci_commit(ctx, &pkg, false); +out: + uci_unload(ctx, pkg); + uci_free_context(ctx); + return false; +} diff --git a/src/core/config.h b/src/core/config.h index 283725d7a..c13ddbadb 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -198,7 +198,8 @@ int config_add_default_wifi_iface(const char *config, const char *type, 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); + char *section_type, char *search_key, char *search_val, + char *option, char *value); bool uci_add_wireless_iface_sec(char *package_name, char *interface_name, char *section_name); @@ -209,9 +210,12 @@ int clean_all_fh(struct agent_config *cfg); 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); + uint8_t *network_key, uint8_t mapie, uint8_t band, + uint8_t *bridge, uint8_t *proto, uint8_t vid, uint32_t br_ip, + uint8_t *bk_ssid, uint8_t *bk_key); int uci_apply_wps_credentials(struct agent_config *cfg, enum wifi_band band); int wifi_reorder_interfaces_by_device(struct agent_config *a, struct uci_context *ctx, struct uci_package *pkg, char *device); int wifi_reorder_interfaces(struct agent_config *a); +int uci_set_bridge(char *config, char *bridge, char *proto, char *ipaddress); #endif -- GitLab