diff --git a/src/Makefile b/src/Makefile index 9daac83e83af9a1b91c817a547b32eeebbd4bfb5..f7288672c04ace4413b750cb0c58c132a38971f0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -21,6 +21,7 @@ CNTLR_OBJS = \ core/cntlr.o \ core/cntlr_map.o \ core/cntlr_tlv_generator.o \ + core/cntlr_cmdu_generator.o \ core/cntlr_map_debug.o \ core/config.o \ core/main.o diff --git a/src/controller.conf b/src/controller.conf index 155015341ad4ec0d74afbb3a170e99d1c59f5d41..69ec214de9cdfbf8260a1cd0272a9631c8a03aca 100644 --- a/src/controller.conf +++ b/src/controller.conf @@ -1,4 +1,4 @@ -config wificntlr +config controller controller option enabled '1' option registrar '5 2' #bands on which wps registrar supported option debug '6' @@ -10,12 +10,24 @@ config fh-credentials option ssid 'map-net5' option vlan '101' +config vlan 'lan' + option network 'lan' + option id '1' + option proto 'dhcp' + +config vlan 'guest' + option network 'guest' + option id '2' + option proto 'static' + option ip_address '10.0.1.1' + config fh-credentials option band '2' option encryption 'psk2' option key '1234567890' option ssid 'map-net2' - option vlan '0' # 0 - 2 rsvd, 3 - 4094 => vlan id + option vlan_id '2' # 0 - 2 rsvd, 3 - 4094 => vlan id + #option vlan 'lan' config bk-credentials option band '5' diff --git a/src/core/cntlr.h b/src/core/cntlr.h index a66bd2f97bf8f7962ab0ee79b1082784f8acbbdb..65ba7f17c4627767c2c91e88e318461282a1e7ee 100644 --- a/src/core/cntlr.h +++ b/src/core/cntlr.h @@ -63,6 +63,7 @@ enum nodetype { NODE_ETH_EXTENDER, }; + enum uplink_type { UL_UNSPEC, UL_ETH, diff --git a/src/core/cntlr_cmdu_generator.c b/src/core/cntlr_cmdu_generator.c new file mode 100644 index 0000000000000000000000000000000000000000..6750ce8f8cfecd1bc3bfd9df5c5cf3fa11f2c16e --- /dev/null +++ b/src/core/cntlr_cmdu_generator.c @@ -0,0 +1,204 @@ +/* + * 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 <easy/easy.h> +#include <wifi.h> + +#include "map_module.h" +#include "utils.h" +#include "debug.h" +#include "liblist.h" +#include "config.h" +#include "comm.h" +#include "msgqueue.h" +#include "worker.h" +#include "cntlr.h" +#include "cntlr_tlv_generator.h" +#include "cntlr_cmdu_generator.h" + +static void cmdu_defaults(struct cmdu_cstruct *cmdu, uint8_t *origin, + char *intf_name, uint16_t type) +{ + memcpy(cmdu->origin, origin, 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 = type; +} + +struct cmdu_cstruct *cntlr_gen_ap_autoconfig_renew(struct controller *c, + uint8_t *origin, char *intf_name, uint8_t *almac) +{ + struct cmdu_cstruct *cmdu; + struct tlv_al_mac *p; + struct tlv_supported_freq_band *p1; + struct tlv_supported_role *p2; + int tlv_index = 0; + + cmdu = (struct cmdu_cstruct *)calloc(1, sizeof(struct cmdu_cstruct)); + if (!cmdu) { + fprintf(stderr, "failed to malloc cmdu\n"); + return NULL; + } + + cmdu_defaults(cmdu, origin, intf_name, + CMDU_TYPE_AP_AUTOCONFIGURATION_RENEW); + + p = cntlr_gen_al_mac(c, almac); + if (!p) + goto fail_cmdu; + cmdu->num_tlvs++; + + /* Hard-code dummy 5GHz, ignored by agent according to spec */ + p1 = cntlr_gen_supported_freq_band(c, 0x01); + if (!p1) + goto fail_p; + cmdu->num_tlvs++; + + /* Hard-code dummy registrar role, only valid value */ + p2 = cntlr_gen_supported_role(c, 0x00); + if (!p2) + goto fail_p1; + cmdu->num_tlvs++; + + cmdu->tlvs = (uint8_t **)calloc(cmdu->num_tlvs, sizeof(uint8_t *)); + if (!cmdu->tlvs) + goto fail_p2; + cmdu->tlvs[tlv_index++] = (uint8_t *)p; + cmdu->tlvs[tlv_index++] = (uint8_t *)p1; + cmdu->tlvs[tlv_index++] = (uint8_t *)p2; + + return cmdu; +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: + map_free_cmdu(cmdu); + return NULL; +} + +struct cmdu_cstruct *cntlr_gen_ap_capability_query(struct controller *c, + uint8_t *origin, char *intf_name) +{ + struct cmdu_cstruct *cmdu; + + cmdu = (struct cmdu_cstruct *)calloc(1, sizeof(struct cmdu_cstruct)); + if (!cmdu) { + fprintf(stderr, "failed to malloc cmdu\n"); + return NULL; + } + + cmdu_defaults(cmdu, origin, intf_name, CMDU_AP_CAPABILITY_QUERY); + + return cmdu; +} + +struct cmdu_cstruct *cntlr_gen_client_capability_query(struct controller *c, + uint8_t *origin, char *intf_name, uint8_t *sta, uint8_t *bssid) +{ + struct tlv_client_info *p; + struct cmdu_cstruct *cmdu; + + cmdu = (struct cmdu_cstruct *)calloc(1, + sizeof(struct cmdu_cstruct)); + if (!cmdu) { + fprintf(stderr, "failed to malloc cmdu\n"); + return NULL; + } + + cmdu_defaults(cmdu, origin, intf_name, CMDU_CLIENT_CAPABILITY_QUERY); + + p = cntlr_gen_client_info(c, sta, bssid); + if (!p) + goto fail_cmdu; + + cmdu->num_tlvs = 1; + cmdu->tlvs = (uint8_t **)calloc(cmdu->num_tlvs, + sizeof(uint8_t *)); + + if (!cmdu->tlvs) + goto fail_p; + + cmdu->tlvs[0] = (uint8_t *)p; + + return cmdu; +fail_p: + map_free_tlv_cstruct((uint8_t *) p); +fail_cmdu: + map_free_cmdu(cmdu); + return NULL; +} + +struct cmdu_cstruct *cntlr_gen_backhaul_steer_request(struct controller *c, + uint8_t *origin, char *intf_name, uint8_t *bssid, + uint8_t *bkhaul, uint8_t op_class, uint8_t channel) +{ + struct tlv_backhaul_steer_req *p; + struct cmdu_cstruct *cmdu; + + cmdu = (struct cmdu_cstruct *)calloc(1, + sizeof(struct cmdu_cstruct)); + if (!cmdu) { + fprintf(stderr, "failed to malloc cmdu\n"); + return NULL; + } + + cmdu_defaults(cmdu, origin, intf_name, CMDU_BACKHAUL_STEER_REQUEST); + + p = cntlr_gen_backhaul_steer_req(c, bkhaul, bssid, op_class, channel); + if (!p) + goto fail_cmdu; + + cmdu->num_tlvs = 1; + cmdu->tlvs = (uint8_t **)calloc(cmdu->num_tlvs, + sizeof(uint8_t *)); + + if (!cmdu->tlvs) + goto fail_p; + + cmdu->tlvs[0] = (uint8_t *)p; + + return cmdu; +fail_p: + map_free_tlv_cstruct((uint8_t *) p); +fail_cmdu: + map_free_cmdu(cmdu); + return NULL; +} diff --git a/src/core/cntlr_cmdu_generator.h b/src/core/cntlr_cmdu_generator.h new file mode 100644 index 0000000000000000000000000000000000000000..9b478b9942f6c9d779944d26d45dba959d9e1220 --- /dev/null +++ b/src/core/cntlr_cmdu_generator.h @@ -0,0 +1,22 @@ +/* + * agent_tlv_generator.h - tlv building function declarations + * + * Copyright (C) 2020 IOPSYS Software Solutions AB. All rights reserved. + * + * Author: jakob.olsson@iopsys.eu + * + */ + +#ifndef CNTLR_CMDU_GEN_H +#define CNTLR_CMDU_GEN_H + +struct cmdu_cstruct *cntlr_gen_ap_autoconfig_renew(struct controller *c, + uint8_t *origin, char *intf_name, uint8_t *almac); +struct cmdu_cstruct *cntlr_gen_ap_capability_query(struct controller *c, + uint8_t *origin, char *intf_name); +struct cmdu_cstruct *cntlr_gen_client_capability_query(struct controller *c, + uint8_t *origin, char *intf_name, uint8_t *sta, uint8_t *bssid); +struct cmdu_cstruct *cntlr_gen_backhaul_steer_request(struct controller *c, + uint8_t *origin, char *intf_name, uint8_t *bssid, + uint8_t *bkhaul, uint8_t op_class, uint8_t channel); +#endif diff --git a/src/core/cntlr_map.c b/src/core/cntlr_map.c index 9feb715e583dd5259f6b21ac42b4ccd260d56d56..d8f850d0d42c448eafec625e13fe6bd96180f787 100644 --- a/src/core/cntlr_map.c +++ b/src/core/cntlr_map.c @@ -79,7 +79,6 @@ int handle_topology_response(void *cntlr, struct cmdu_cstruct *cmdu) return 0; } -/* TODO: error handling */ int handle_ap_autoconfig_search(void *cntlr, struct cmdu_cstruct *rec_cmdu) { trace("%s: --->\n", __func__); @@ -88,8 +87,36 @@ int handle_ap_autoconfig_search(void *cntlr, struct cmdu_cstruct *rec_cmdu) struct cmdu_cstruct *cmdu; struct tlv_map_profile *p; struct tlv_supp_service *p1; + struct tlv_supported_freq_band *p2; + struct tlv_al_mac *almac_tlv; + struct tlv_autoconf_freq_band *freq_tlv; + char mac_str[18] = {0}; int ret; + almac_tlv = extract_tlv_by_type(rec_cmdu, TLV_TYPE_AL_MAC_ADDRESS_TYPE); + if (!almac_tlv) + return -1; + + freq_tlv = extract_tlv_by_type(rec_cmdu, TLV_TYPE_AUTOCONFIG_FREQ_BAND); + if (!freq_tlv) + return -1; + + if (freq_tlv->freq_band == 0x00) { + if (!c->cfg.has_registrar_2g) + return -1; + } else if (freq_tlv->freq_band == 0x01) { + if (!c->cfg.has_registrar_5g) + return -1; + } else + return -1; + + if (!hwaddr_ntoa(almac_tlv->al_mac_address, mac_str)) + return -1; + + ret = cntlr_config_add_agent(&c->cfg, mac_str); + if (!ret) + cntlr_config_reload(&c->cfg); + cmdu = (struct cmdu_cstruct *)calloc(1, sizeof(struct cmdu_cstruct)); if (!cmdu) { @@ -99,7 +126,7 @@ int handle_ap_autoconfig_search(void *cntlr, struct cmdu_cstruct *rec_cmdu) cmdu->message_type = CMDU_TYPE_AP_AUTOCONFIGURATION_RESPONSE; memcpy(cmdu->origin, rec_cmdu->origin, 6); - cmdu->message_id = cmdu->message_id; + cmdu->message_id = rec_cmdu->message_id; strncpy(cmdu->intf_name, rec_cmdu->intf_name, sizeof(cmdu->intf_name) - 1); @@ -113,17 +140,25 @@ int handle_ap_autoconfig_search(void *cntlr, struct cmdu_cstruct *rec_cmdu) goto fail_p; cmdu->num_tlvs++; + p2 = cntlr_gen_supported_freq_band(c, freq_tlv->freq_band); + if (!p2) + goto fail_p1; + cmdu->num_tlvs++; + cmdu->tlvs = (uint8_t **)calloc(cmdu->num_tlvs, sizeof(uint8_t *)); if (!cmdu->tlvs) - goto fail_p1; + goto fail_p2; cmdu->tlvs[tlv_index++] = (uint8_t *)p; cmdu->tlvs[tlv_index++] = (uint8_t *)p1; + cmdu->tlvs[tlv_index++] = (uint8_t *)p2; ret = send_cmdu(c, cmdu); map_free_cmdu(cmdu); return ret; +fail_p2: + map_free_tlv_cstruct((uint8_t *) p2); fail_p1: map_free_tlv_cstruct((uint8_t *) p1); fail_p: @@ -147,6 +182,7 @@ int handle_ap_autoconfig_wsc(void *cntlr, struct cmdu_cstruct *rec_cmdu) struct tlv_default_8021q_settings *p; struct tlv_traffic_sep_policy *p1; struct tlv_ap_radio_identifier *p2; + struct tlv_ap_radio_basic_cap *rec_basic_cap; struct tlv_wsc *p3; struct cmdu_cstruct *cmdu; int tlv_index = 0, ret, i; @@ -184,7 +220,12 @@ int handle_ap_autoconfig_wsc(void *cntlr, struct cmdu_cstruct *rec_cmdu) goto fail_p; cmdu->num_tlvs++; - p2 = cntlr_gen_radio_identifier(c, cmdu, rec_cmdu); + rec_basic_cap = extract_tlv_by_type(rec_cmdu, + MAP_TLV_AP_RADIO_BASIC_CAPABILITIES); + if (!rec_basic_cap) + goto fail_p1; + + p2 = cntlr_gen_ap_radio_identifier(c, cmdu, rec_basic_cap->radio_id); if (!p2) goto fail_p1; cmdu->num_tlvs++; diff --git a/src/core/cntlr_tlv_generator.c b/src/core/cntlr_tlv_generator.c index 558492cb22693b4682a4bd3dfd6c6ab9d393a786..72df47432ec3b8a17520079176ef1468a0ac1cd2 100644 --- a/src/core/cntlr_tlv_generator.c +++ b/src/core/cntlr_tlv_generator.c @@ -158,12 +158,15 @@ struct tlv_wsc *cntlr_gen_wsc(struct controller *c, else /* default to WPA */ cfg.input.auth_types = 0x0008; - /* backhaul STA */ - cfg.input.mapie |= (creds->mode == WIFI_MODE_STA ? 1 << 7 : 0); + /* backhaul STA - DEPRECATED + * cfg.input.mapie |= (creds->mode == WIFI_MODE_STA ? 1 << 7 : 0); + */ /* backhaul BSS */ cfg.input.mapie |= (creds->multi_ap & 0x01) << 6; + cfg.input.mapie |= (creds->mode == AP_WIFI_BBSS ? (1 << 6) : 0); /* fronthaul BSS */ cfg.input.mapie |= (creds->multi_ap & 0x02) << 4; + cfg.input.mapie |= (creds->mode == AP_WIFI_FBSS ? (1 << 5) : 0); /* backhaul STA */ cfg.input.mapie |= (creds->disallow_bsta << 2); /* teardown bit */ @@ -181,33 +184,22 @@ struct tlv_wsc *cntlr_gen_wsc(struct controller *c, return m2; } -struct tlv_ap_radio_identifier *cntlr_gen_radio_identifier(struct controller *c, - struct cmdu_cstruct *cmdu, struct cmdu_cstruct *rec_cmdu) + +struct tlv_ap_radio_identifier *cntlr_gen_ap_radio_identifier(struct controller *c, + struct cmdu_cstruct *cmdu, uint8_t *hwaddr) { struct tlv_ap_radio_identifier *p; - uint8_t *tlv; - int i; - p = (struct tlv_ap_radio_identifier *) calloc(1, + p = (struct tlv_ap_radio_identifier *)calloc(1, sizeof(struct tlv_ap_radio_identifier)); - if (!p) + if (!p) { + fprintf(stderr, "failed to malloc tlv\n"); return NULL; - - for (i = 0; i < rec_cmdu->num_tlvs; i++) { - tlv = (uint8_t *) rec_cmdu->tlvs[i]; - switch (*tlv) { - case MAP_TLV_AP_RADIO_BASIC_CAPABILITIES: { - struct tlv_ap_radio_basic_cap *rec_p = (struct tlv_ap_radio_basic_cap *)tlv; - - p->tlv_type = MAP_TLV_AP_RADIO_IDENTIFIER; - memcpy(p->radio_id, rec_p->radio_id, 6); - break; - } - default: - break; - } } + p->tlv_type = MAP_TLV_AP_RADIO_IDENTIFIER; + memcpy(p->radio_id, hwaddr, 6); + return p; } @@ -267,6 +259,20 @@ struct tlv_ch_scan_rep_policy *cntlr_gen_ch_scan_rep_policy( return p; } +struct tlv_al_mac *cntlr_gen_al_mac(struct controller *c, 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_unsuccess_assoc_policy *cntlr_gen_unsuccess_assoc_policy( struct controller *c, struct agent_policy *a, struct cmdu_cstruct *cmdu) @@ -284,6 +290,21 @@ struct tlv_unsuccess_assoc_policy *cntlr_gen_unsuccess_assoc_policy( return p; } +struct tlv_supported_freq_band *cntlr_gen_supported_freq_band(struct controller *c, + uint8_t freq_band) +{ + struct tlv_supported_freq_band *p; + + p = calloc(1, sizeof(struct tlv_supported_freq_band)); + if (!p) + return NULL; + + p->tlv_type = TLV_TYPE_SUPPORTED_FREQ_BAND; + p->freq_band = freq_band; + + return p; +} + struct tlv_backhaul_bss_config *cntlr_gen_backhaul_bss_config( struct controller *c, struct agent_policy *a, struct cmdu_cstruct *cmdu, const uint8_t *bssid) @@ -409,3 +430,53 @@ struct tlv_metric_report_policy *cntlr_gen_metric_report_policy( return p; } + +struct tlv_supported_role *cntlr_gen_supported_role(struct controller *c, + uint8_t role) +{ + struct tlv_supported_role *p; + + p = calloc(1, sizeof(struct tlv_supported_role)); + if (!p) + return NULL; + + p->tlv_type = TLV_TYPE_SUPPORTED_ROLE; + p->role = role; + + return p; +} + +struct tlv_client_info *cntlr_gen_client_info(struct controller *c, + uint8_t *sta, uint8_t *bssid) +{ + struct tlv_client_info *p; + + p = calloc(1, sizeof(struct tlv_client_info)); + if (!p) + return NULL; + + p->tlv_type = MAP_TLV_CLIENT_INFO; + memcpy(p->bssid, bssid, 6); + memcpy(p->client_addr, sta, 6); + + return p; +} + +struct tlv_backhaul_steer_req *cntlr_gen_backhaul_steer_req(struct controller *c, + uint8_t *bssid, uint8_t *bkhaul, uint8_t op_class, + uint8_t channel) +{ + struct tlv_backhaul_steer_req *p; + + p = calloc(1, sizeof(struct tlv_backhaul_steer_req)); + if (!p) + return NULL; + + p->tlv_type = MAP_TLV_BACKHAUL_STEERING_REQUEST; + memcpy(p->bssid, bssid, 6); + memcpy(p->addr, bkhaul, 6); + + p->channel = channel; + p->op_class = op_class; + return p; +} diff --git a/src/core/cntlr_tlv_generator.h b/src/core/cntlr_tlv_generator.h index d409c49100525f51d4ded99e75125654dd011ab0..74adb4f98a713331f0cf2db65dd27d67d43c6dad 100644 --- a/src/core/cntlr_tlv_generator.h +++ b/src/core/cntlr_tlv_generator.h @@ -10,6 +10,7 @@ #ifndef CNTLR_TLV_GEN_H #define CNTLR_TLV_GEN_H +uint8_t *extract_tlv_by_type(struct cmdu_cstruct *cmdu, uint8_t tlv_type); struct tlv_default_8021q_settings *cntlr_gen_8021q_settings(struct controller *c, struct agent_policy *a); struct tlv_traffic_sep_policy *cntlr_gen_traffic_sep_policy(struct controller *c, @@ -17,8 +18,8 @@ struct tlv_traffic_sep_policy *cntlr_gen_traffic_sep_policy(struct controller *c struct tlv_wsc *cntlr_gen_wsc(struct controller *c, struct cmdu_cstruct *cmdu, struct cmdu_cstruct *rec_cmdu, struct iface_credential *fh); -struct tlv_ap_radio_identifier *cntlr_gen_radio_identifier(struct controller *c, - struct cmdu_cstruct *cmdu, struct cmdu_cstruct *rec_cmdu); +struct tlv_ap_radio_identifier *cntlr_gen_ap_radio_identifier(struct controller *c, + struct cmdu_cstruct *cmdu, uint8_t *hwaddr); struct tlv_supp_service *cntlr_gen_supp_service(struct controller *c, struct cmdu_cstruct *cmdu); struct tlv_map_profile *cntlr_gen_map_profile(struct controller *c, @@ -37,4 +38,14 @@ struct tlv_unsuccess_assoc_policy *cntlr_gen_unsuccess_assoc_policy( struct tlv_backhaul_bss_config *cntlr_gen_backhaul_bss_config( struct controller *c, struct agent_policy *a, struct cmdu_cstruct *cmdu, const uint8_t *bssid); +struct tlv_al_mac *cntlr_gen_al_mac(struct controller *c, uint8_t *hwaddr); +struct tlv_supported_freq_band *cntlr_gen_supported_freq_band(struct controller *c, + uint8_t freq_band); +struct tlv_supported_role *cntlr_gen_supported_role(struct controller *c, + uint8_t role); +struct tlv_client_info *cntlr_gen_client_info(struct controller *c, + uint8_t *sta, uint8_t *bssid); +struct tlv_backhaul_steer_req *cntlr_gen_backhaul_steer_req(struct controller *c, + uint8_t *bssid, uint8_t *bkhaul, uint8_t op_class, + uint8_t channel); #endif diff --git a/src/core/cntlr_ubus.c b/src/core/cntlr_ubus.c index ed10aaa93f767e47c8bb1af954b44bd277407ce4..bc383006588ca63e19c75edcf08d08fe2b85dc69 100644 --- a/src/core/cntlr_ubus.c +++ b/src/core/cntlr_ubus.c @@ -34,6 +34,9 @@ #include "cntlr_tlv_generator.h" #include "map_module.h" +#include "cntlr_tlv_generator.h" +#include "cntlr_cmdu_generator.h" + enum { AP_POLICY_AGENT, @@ -105,11 +108,15 @@ static const struct blobmsg_policy config_policy_params[__CFG_POLICY_MAX] = { enum { RECFG_POLICY_AGENT, + RECFG_POLICY_ALMAC, + RECFG_POLICY_EGRESS, __RECFG_POLICY_MAX, }; static const struct blobmsg_policy reconfig_policy_params[__RECFG_POLICY_MAX] = { [RECFG_POLICY_AGENT] = { .name = "agent", .type = BLOBMSG_TYPE_STRING }, + [RECFG_POLICY_ALMAC] = { .name = "almac", .type = BLOBMSG_TYPE_STRING }, + [RECFG_POLICY_EGRESS] = { .name = "egress", .type = BLOBMSG_TYPE_STRING } }; enum { @@ -198,14 +205,16 @@ int send_cmdu(struct controller *c, blobmsg_add_u32(&b, "type", cmdu_data->message_type); blobmsg_add_string(&b, "egress", cmdu_data->intf_name); - blobmsg_add_u32(&b, "mid", cmdu_data->message_id); + if (cmdu_data->message_id) + blobmsg_add_u32(&b, "mid", cmdu_data->message_id); hwaddr_ntoa(cmdu_data->origin, dst_addr); blobmsg_add_string(&b, "dst_macaddr", dst_addr); - fprintf(stdout, "|%s:%d|cmdu:%s|dst:%s|num_tlvs:%d|\n", __func__, __LINE__, + fprintf(stdout, "|%s:%d|cmdu:%s|dst:%s|num_tlvs:%d|egress:%s|\n", + __func__, __LINE__, map_stringify_cmdu_type(cmdu_data->message_type), - dst_addr, cmdu_data->num_tlvs); + dst_addr, cmdu_data->num_tlvs, cmdu_data->intf_name); if (cmdu_data->num_tlvs > 0) { for (i = 0; i < cmdu_data->num_tlvs; i++) { @@ -356,37 +365,28 @@ int cntlr_ap_caps(struct ubus_context *ctx, struct ubus_object *obj, { struct blob_attr *tb[__AP_POLICY_MAX]; struct controller *c = container_of(obj, struct controller, obj); - char agent[18] = {0}; - struct cmdu_cstruct *cmdu_data; - - cmdu_data = (struct cmdu_cstruct *)calloc(1, - sizeof(struct cmdu_cstruct)); - if (!cmdu_data) { - fprintf(stderr, "failed to malloc cmdu\n"); - return UBUS_STATUS_UNKNOWN_ERROR; - } + uint8_t hwaddr[6] = {0}; + struct cmdu_cstruct *cmdu; blobmsg_parse(ap_caps_policy_params, __AP_POLICY_MAX, tb, blob_data(msg), blob_len(msg)); - if (tb[AP_POLICY_AGENT]) { + char agent[18] = {0}; + strncpy(agent, blobmsg_data(tb[AP_POLICY_AGENT]), sizeof(agent) - 1); - if (!hwaddr_aton(agent, cmdu_data->origin)) + if (!hwaddr_aton(agent, hwaddr)) return UBUS_STATUS_UNKNOWN_ERROR; } - // TODO: ff:ff:ff:ff:ff:ff = send to all agents - - cmdu_data->message_type = CMDU_AP_CAPABILITY_QUERY; - cmdu_data->message_id = 1; - - cmdu_data->num_tlvs = 0; - send_cmdu(c, cmdu_data); + cmdu = cntlr_gen_ap_capability_query(c, hwaddr, NULL); + if (!cmdu) + return UBUS_STATUS_UNKNOWN_ERROR; - map_free_cmdu(cmdu_data); + send_cmdu(c, cmdu); + map_free_cmdu(cmdu); return 0; } @@ -577,15 +577,14 @@ fail_cmdu: } static int cntlr_sta_caps(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) { struct blob_attr *tb[__STA_POLICY_MAX]; - uint8_t hw_bssid[6] = {0}, hw_sta[6] = {0}; - struct tlv_client_info *p; + uint8_t hw_bssid[6] = {0}, hw_sta[6] = {0}, hw_agent[6] = {0}; struct controller *c = container_of(obj, struct controller, obj); - char sta[18] = {0}, agent[18] = {0}, bssid[18] = {0}; - struct cmdu_cstruct *cmdu_data; + char sta[18] = {0}, bssid[18] = {0}; + struct cmdu_cstruct *cmdu; blobmsg_parse(sta_caps_policy_params, __STA_POLICY_MAX, tb, blob_data(msg), blob_len(msg)); @@ -599,62 +598,29 @@ static int cntlr_sta_caps(struct ubus_context *ctx, struct ubus_object *obj, strncpy(sta, blobmsg_data(tb[STA_POLICY_STA]), sizeof(sta) - 1); strncpy(bssid, blobmsg_data(tb[STA_POLICY_BSSID]), sizeof(bssid) - 1); - cmdu_data = (struct cmdu_cstruct *)calloc(1, - sizeof(struct cmdu_cstruct)); - if (!cmdu_data) { - fprintf(stderr, "failed to malloc cmdu\n"); - return UBUS_STATUS_UNKNOWN_ERROR; - } - if (tb[AP_POLICY_AGENT]) { + char agent[18] = {0}; + strncpy(agent, blobmsg_data(tb[AP_POLICY_AGENT]), sizeof(agent) - 1); - if (!hwaddr_aton(agent, cmdu_data->origin)) - goto fail_cmdu; - } - - // TODO: ff:ff:ff:ff:ff:ff = send to all agents - - cmdu_data->message_type = CMDU_CLIENT_CAPABILITY_QUERY; - cmdu_data->message_id = 1; - - p = calloc(1, sizeof(struct tlv_client_info)); - if (!p) { - fprintf(stderr, "failed to malloc cmdu\n"); - goto fail_cmdu; - } - - if (!hwaddr_aton(sta, hw_sta)) { - fprintf(stderr, "STA Capability Query: provide STA " \ - "address in format 11:22:33...\n"); - goto fail_p; - } - - if (!hwaddr_aton(bssid, hw_bssid)) { - fprintf(stderr, "STA Capability Query: provide BSSID " \ - "address in format 11:22:33...\n"); - goto fail_p; + if (!hwaddr_aton(agent, hw_agent)) + return UBUS_STATUS_UNKNOWN_ERROR; } - p->tlv_type = MAP_TLV_CLIENT_INFO; - memcpy(p->bssid, hw_bssid, 6); - memcpy(p->client_addr, hw_sta, 6); + if (!hwaddr_aton(sta, hw_sta)) + return UBUS_STATUS_UNKNOWN_ERROR; - cmdu_data->num_tlvs = 1; - cmdu_data->tlvs = (uint8_t **)calloc(cmdu_data->num_tlvs, - sizeof(uint8_t *)); + if (!hwaddr_aton(sta, hw_bssid)) + return UBUS_STATUS_UNKNOWN_ERROR; - if (cmdu_data->tlvs) - cmdu_data->tlvs[0] = (uint8_t *)p; + cmdu = cntlr_gen_client_capability_query(c, hw_agent, NULL, hw_sta, + hw_bssid); + if (!cmdu) + return UBUS_STATUS_UNKNOWN_ERROR; - send_cmdu(c, cmdu_data); - map_free_cmdu(cmdu_data); + send_cmdu(c, cmdu); + map_free_cmdu(cmdu); return 0; -fail_p: - map_free_tlv_cstruct((uint8_t *) p); -fail_cmdu: - map_free_cmdu(cmdu_data); - return UBUS_STATUS_UNKNOWN_ERROR; } static int cntlr_teardown_ap(struct ubus_context *ctx, struct ubus_object *obj, @@ -668,33 +634,49 @@ static int cntlr_reconfig_ap(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { - return 0; -} + struct controller *c = container_of(obj, struct controller, obj); + struct blob_attr *tb[__RECFG_POLICY_MAX]; + char almac[18] = {0}, egress[16] = {0}; + uint8_t hwaddr[6] = {0}, alhwaddr[6] = {0}; + struct cmdu_cstruct *cmdu; + int i, tlv_index = 0; + + blobmsg_parse(reconfig_policy_params, __RECFG_POLICY_MAX, tb, + blob_data(msg), blob_len(msg)); -/* - * - One AP Radio Identifier TLV (see section 17.2.3). - * - One or more WSC TLV (containing M2). - * - Zero or one Default 802.1Q Settings TLV (see section 17.2.49). [Profile-2] - * - Zero or one Traffic Separation Policy TLV (see section 17.2.50). [Profile-2] -*/ - -struct tlv_ap_radio_identifier *cntlr_gen_config_ap_tlv(struct controller *c, - struct cmdu_cstruct *cmdu, uint8_t *hwaddr) -{ - struct tlv_ap_radio_identifier *p; + if (!tb[RECFG_POLICY_ALMAC]) { + fprintf(stderr, "Provide ALMAC address in format 11:22:33...\n"); + return UBUS_STATUS_INVALID_ARGUMENT; + } - p = (struct tlv_ap_radio_identifier *)calloc(1, - sizeof(struct tlv_ap_radio_identifier)); - if (!p) { - fprintf(stderr, "failed to malloc tlv\n"); - return NULL; + if (tb[RECFG_POLICY_AGENT]) { + char agent[18] = {0}; + + strncpy(agent, blobmsg_data(tb[RECFG_POLICY_AGENT]), + sizeof(agent) - 1); + if (!hwaddr_aton(agent, hwaddr)) + return UBUS_STATUS_UNKNOWN_ERROR; } - p->tlv_type = MAP_TLV_AP_RADIO_IDENTIFIER; - memcpy(p->radio_id, hwaddr, 6); + if (tb[RECFG_POLICY_EGRESS]) + strncpy(egress, blobmsg_data(tb[RECFG_POLICY_EGRESS]), + sizeof(egress) - 1); + else + strncpy(egress, "br-lan", sizeof(egress) - 1); + + strncpy(almac, blobmsg_data(tb[RECFG_POLICY_ALMAC]), + sizeof(almac) - 1); + if (!hwaddr_aton(almac, alhwaddr)) + return UBUS_STATUS_UNKNOWN_ERROR; + + cmdu = cntlr_gen_ap_autoconfig_renew(c, alhwaddr, egress, alhwaddr); + if (!cmdu) + return UBUS_STATUS_UNKNOWN_ERROR; - return p; + send_cmdu(c, cmdu); + map_free_cmdu(cmdu); + return UBUS_STATUS_OK; } static struct netif_radio *cntlr_radio_to_bssid(struct controller *c, const char *radio) @@ -768,7 +750,7 @@ static int cntlr_config_ap(struct ubus_context *ctx, struct ubus_object *obj, free(cmdu); return UBUS_STATUS_UNKNOWN_ERROR; } - p = cntlr_gen_config_ap_tlv(c, cmdu, hwaddr); + p = cntlr_gen_ap_radio_identifier(c, cmdu, hwaddr); } else if (tb[CFG_POLICY_RADIO]) { char radio[18] = {0}; struct netif_radio *r; @@ -781,7 +763,7 @@ static int cntlr_config_ap(struct ubus_context *ctx, struct ubus_object *obj, return UBUS_STATUS_UNKNOWN_ERROR; } - p = cntlr_gen_config_ap_tlv(c, cmdu, r->hwaddr); + p = cntlr_gen_ap_radio_identifier(c, cmdu, r->hwaddr); } /* else { // TODO: all radios @@ -870,10 +852,11 @@ static int cntlr_bk_steer(struct ubus_context *ctx, struct ubus_object *obj, struct blob_attr *msg) { struct blob_attr *tb[__BK_STEER_POLICY_MAX]; - struct tlv_backhaul_steer_req *p; struct controller *c = container_of(obj, struct controller, obj); - char agent[18] = {0}, bssid[18] = {0}, bkhaul[18] = {0}; + char agent_str[18] = {0}, bssid_str[18] = {0}, bkhaul_str[18] = {0}; + uint8_t agent[6] = {0}, bssid[6] = {0}, bkhaul[6] = {0}; struct cmdu_cstruct *cmdu; + uint8_t op_class, channel; blobmsg_parse(bk_steer_policy_params, __BK_STEER_POLICY_MAX, tb, blob_data(msg), blob_len(msg)); @@ -885,64 +868,40 @@ static int cntlr_bk_steer(struct ubus_context *ctx, struct ubus_object *obj, return UBUS_STATUS_INVALID_ARGUMENT; } - strncpy(bssid, blobmsg_data(tb[BK_STEER_POLICY_BSSID]), - sizeof(bssid) - 1); - strncpy(bkhaul, blobmsg_data(tb[BK_STEER_POLICY_STA_MAC]), - sizeof(bkhaul) - 1); + strncpy(bssid_str, blobmsg_data(tb[BK_STEER_POLICY_BSSID]), + sizeof(bssid_str) - 1); + strncpy(bkhaul_str, blobmsg_data(tb[BK_STEER_POLICY_STA_MAC]), + sizeof(bkhaul_str) - 1); - 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[AP_POLICY_AGENT]) { - strncpy(agent, blobmsg_data(tb[AP_POLICY_AGENT]), - sizeof(agent) - 1); - if (!hwaddr_aton(agent, cmdu->origin)) - goto fail_cmdu; - } - - cmdu->message_type = CMDU_BACKHAUL_STEER_REQUEST; - - p = calloc(1, sizeof(struct tlv_client_info)); - if (!p) { - fprintf(stderr, "failed to malloc cmdu\n"); - goto fail_cmdu; - } - - cmdu->num_tlvs++; - - if (!hwaddr_aton(bssid, p->bssid)) { + if (!hwaddr_aton(bssid_str, bssid)) { fprintf(stderr, "BSSID must be in format 11:22:33...\n"); - goto fail_p; + return UBUS_STATUS_INVALID_ARGUMENT; } - if (!hwaddr_aton(bkhaul, p->addr)) { + if (!hwaddr_aton(bkhaul_str, bkhaul)) { fprintf(stderr, "Backhaul must be in format 11:22:33...\n"); - goto fail_p; + return UBUS_STATUS_INVALID_ARGUMENT; } - p->channel = blobmsg_get_u8(tb[BK_STEER_POLICY_CHANNEL]); - p->op_class = blobmsg_get_u8(tb[BK_STEER_POLICY_OP_CLASS]); - p->tlv_type = MAP_TLV_BACKHAUL_STEERING_REQUEST; + if (tb[AP_POLICY_AGENT]) { + strncpy(agent_str, blobmsg_data(tb[AP_POLICY_AGENT]), + sizeof(agent_str) - 1); + if (!hwaddr_aton(agent_str, agent)) + return UBUS_STATUS_INVALID_ARGUMENT; + } - cmdu->tlvs = (uint8_t **)calloc(cmdu->num_tlvs, - sizeof(uint8_t *)); + channel = blobmsg_get_u8(tb[BK_STEER_POLICY_CHANNEL]); + op_class = blobmsg_get_u8(tb[BK_STEER_POLICY_OP_CLASS]); - if (cmdu->tlvs) - cmdu->tlvs[0] = (uint8_t *)p; + cmdu = cntlr_gen_backhaul_steer_request(c, agent, NULL, bssid, bkhaul, + op_class, channel); + if (!cmdu) + return UBUS_STATUS_UNKNOWN_ERROR; send_cmdu(c, cmdu); map_free_cmdu(cmdu); return 0; -fail_p: - map_free_tlv_cstruct((uint8_t *) p); -fail_cmdu: - free(cmdu); - return UBUS_STATUS_UNKNOWN_ERROR; } static int cntlr_ap_policy_config(struct ubus_context *ctx, struct ubus_object *obj, @@ -1147,20 +1106,24 @@ int cntlr_publish_object(struct controller *c, const char *objname) struct ubus_object *obj; struct ubus_object_type *obj_type; struct ubus_method *obj_methods; - struct ubus_method m[7] = { + struct ubus_method m[8] = { UBUS_METHOD_NOARG("status", cntlr_status), - UBUS_METHOD("ap_caps", cntlr_ap_caps, ap_caps_policy_params), - UBUS_METHOD("sta_caps", cntlr_sta_caps, sta_caps_policy_params), + UBUS_METHOD("ap_caps", cntlr_ap_caps, + ap_caps_policy_params), + UBUS_METHOD("sta_caps", cntlr_sta_caps, + sta_caps_policy_params), UBUS_METHOD("channels", cntlr_channel_pref, channel_pref_policy_params), UBUS_METHOD("bk_steer", cntlr_bk_steer, bk_steer_policy_params), - UBUS_METHOD("agent_policy", cntlr_ap_policy_config, ap_policy_config_params), - UBUS_METHOD("channel", cntlr_channel_select, channel_select_policy_params) + UBUS_METHOD("agent_policy", cntlr_ap_policy_config, + ap_policy_config_params), + UBUS_METHOD("channel", cntlr_channel_select, + channel_select_policy_params), + UBUS_METHOD("reconfig_ap", cntlr_reconfig_ap, + reconfig_policy_params), /* UBUS_METHOD("teardown_ap", cntlr_teardown_ap, config_policy_params), - UBUS_METHOD("reconfig_ap", cntlr_reconfig_ap, - reconfig_policy_params), UBUS_METHOD("config_ap", cntlr_config_ap, config_policy_params), */ diff --git a/src/core/config.c b/src/core/config.c index 08db6bd444fa3cc5ed94910688aedd04dc976129..95446f9ad886f4470ecdad21fb6902b9b09b1210 100644 --- a/src/core/config.c +++ b/src/core/config.c @@ -52,6 +52,97 @@ static void stax_add_entry(struct list_head *h, char *sta_macstr) } } +struct uci_package *uci_load_pkg(struct uci_context **ctx, const char *config) +{ + struct uci_package *pkg; + + if (!*ctx) { + *ctx = uci_alloc_context(); + if (!*ctx) + return NULL; + } + if (uci_load(*ctx, config, &pkg) != UCI_OK) { + free(*ctx); + return NULL; + } + + return pkg; +} + +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) +{ + struct uci_ptr ptr = {0}; + + ptr.p = pkg; + ptr.s = section; + ptr.option = key; + ptr.value = value; + + if (type == UCI_TYPE_STRING) + return uci_set(ctx, &ptr); + + if (type == UCI_TYPE_LIST) + return uci_add_list(ctx, &ptr); + + return -1; +} + +struct uci_section *config_get_agent_section(struct uci_context *ctx, + struct uci_package *pkg, const char *type, const char *al_mac) +{ + struct uci_element *e; + struct uci_section *section; + + uci_foreach_element(&pkg->sections, e) { + const char *agent_id; + + section = uci_to_section(e); + if (strcmp(section->type, type)) + continue; + + agent_id = uci_lookup_option_string(ctx, section, "agent_id"); + if (agent_id && !strcmp(agent_id, al_mac)) + return section; + } + + return NULL; +} + +int cntlr_config_add_agent(struct controller_config *c, char *al_mac) +{ + struct uci_context *ctx = NULL; + struct uci_package *pkg; + struct uci_section *section; + int ret = -1; + + pkg = uci_load_pkg(&ctx, "mapcontroller"); + if (!pkg) + return ret; + + section = config_get_agent_section(ctx, pkg, "agent-policy", al_mac); + if (section) + goto out_pkg; + + ret = uci_add_section(ctx, pkg, "agent-policy", §ion); + if (ret) + goto out_pkg; + + ret = uci_save(ctx, pkg); + if (ret) + goto out_pkg; + + ret = set_value(ctx, pkg, section, "agent_id", al_mac, UCI_TYPE_STRING); + + uci_commit(ctx, &pkg, false); + +out_pkg: + uci_unload(ctx, pkg); + uci_free_context(ctx); + return ret; +} + void cntlr_config_dump(struct controller_config *c) { int i; @@ -195,13 +286,13 @@ static int cntlr_config_get_credentials(struct controller_config *c, return -1; cred = &c->fh[c->num_fh++]; - cred->mode = WIFI_MODE_AP; + cred->mode = AP_WIFI_FBSS; } else { if (c->num_bk >= 2) return -1; cred = &c->bk[c->num_bk++]; - cred->mode = WIFI_MODE_STA; + cred->mode = AP_WIFI_BBSS; } uci_parse_section(s, opts, NUM_CREDS, tb); @@ -411,7 +502,7 @@ int cntlr_config_reload(struct controller_config *cfg) if (!ctx) return -1; - if (uci_load(ctx, "controller", &pkg)) { + if (uci_load(ctx, "mapcontroller", &pkg)) { uci_free_context(ctx); return -1; } @@ -419,7 +510,7 @@ int cntlr_config_reload(struct controller_config *cfg) uci_foreach_element(&pkg->sections, e) { struct uci_section *s = uci_to_section(e); - if (!strcmp(s->type, "wificntlr")) { + if (!strcmp(s->type, "controller")) { cntlr_config_get_base(cfg, s); } else if (!strcmp(s->type, "fh-credentials") || !strcmp(s->type, "bk-credentials")) { diff --git a/src/core/config.h b/src/core/config.h index b4aa7029df296c613821ebc07aeb7f3bc3328cc6..fea14869367217218facabfbaaab494a9bbb5efe 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -37,6 +37,11 @@ enum wifi_security { }; */ +enum aptype { + AP_WIFI_FBSS, + AP_WIFI_BBSS, +}; + struct stax { char macstring[32]; /* ':' separated mac address string */ struct list_head list; @@ -51,7 +56,7 @@ struct iface_credential { uint16_t vlanid; uint8_t multi_ap; struct list_head *list; - enum wifi_mode mode; + enum aptype mode; uint8_t disallow_bsta; }; @@ -103,6 +108,8 @@ struct controller_config { struct controller; +int cntlr_config_add_agent(struct controller_config *c, char *al_mac); + int cntlr_config_reload(struct controller_config *cfg); int cntlr_config_defaults(struct controller *c, struct controller_config *cfg); void cntlr_config_dump(struct controller_config *cfg);