Newer
Older
/*
* config.c - controller configuration handling
*
* Copyright (C) 2020 IOPSYS Software Solutions AB. All rights reserved.
*
* Author: anjan.chanda@iopsys.eu
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.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 <uci.h>
#include <easy/easy.h> // TODO: remove wifi.h
#include <wifi.h> // TODO: remove wifi.h
#include "debug.h"
#include "utils.h"
#include "config.h"
#include "comm.h"
#include "msgqueue.h"
#include "worker.h"
#include "cntlr.h"
void cntlr_config_dump(struct controller_config *c)
int i;
dbg("Controller config ---------\n");
dbg("Enabled: %d\n", c->enabled);
dbg("Registrar @5Ghz: %d\n", c->has_registrar_5g);
dbg("Registrar @2Ghz: %d\n", c->has_registrar_2g);
dbg("Credentials: Fronthaul\n");
for (i = 0; i < c->num_fh; i++) {
dbg(" Band : %d\n", c->fh[i].band);
dbg(" Security: 0x%x\n", c->fh[i].sec);
dbg(" ssid : %s\n", c->fh[i].ssid);
dbg(" vlan : %d\n\n", c->fh[i].vlanid);
dbg("Credentials: Backhaul\n");
for (i = 0; i < c->num_bk; i++) {
dbg(" Band : %d\n", c->bk[i].band);
dbg(" Security: 0x%x\n", c->bk[i].sec);
dbg(" ssid : %s\n", c->bk[i].ssid);
dbg(" vlan : %d\n\n", c->bk[i].vlanid);
dbg(" Id : " MACFMT "\n", MAC2STR(c->apolicy.agent_id));
dbg(" Steer-policy : %d\n", c->apolicy.policy);
dbg(" Util-threshold : %d\n", c->apolicy.util_threshold);
dbg(" RCPI-threshold : %d\n", c->apolicy.rcpi_threshold);
dbg(" Report scan : %d\n", c->apolicy.report_scan);
dbg(" Report assocfails : %d\n", c->apolicy.report_sta_assocfails);
dbg(" Report metric : %d\n", c->apolicy.report_metric_periodic);
dbg(" Report RCPI-thresh : %d\n", c->apolicy.report_rcpi_threshold);
dbg(" Report Util-thresh : %d\n", c->apolicy.report_util_threshold);
dbg(" Include STA stats : %d\n", c->apolicy.include_sta_stats);
dbg(" Include STA metric : %d\n", c->apolicy.include_sta_metric);
dbg(" Primary VLAN ID : %d\n", c->apolicy.pvid);
dbg(" PCP Default : %d\n", c->apolicy.pcp_default);
dbg(" Disallow bSTA P1 : %d\n", c->apolicy.disallow_bsta_p1);
dbg(" Disallow bSTA P2 : %d\n", c->apolicy.disallow_bsta_p2);
dbg("---------------------------\n");
int cntlr_config_defaults(struct controller *cntlr, struct controller_config *c)
memset(c, 0, sizeof(*c));
INIT_LIST_HEAD(&c->policylist);
static int cntlr_config_get_base(struct controller_config *c,
struct uci_section *s)
enum {
CNTLR_ENABLED,
CNTLR_REGISTRAR,
NUM_CNTLR_ATTRS,
};
const struct uci_parse_option opts[] = {
{ .name = "enabled", .type = UCI_TYPE_STRING },
{ .name = "registrar", .type = UCI_TYPE_STRING },
{ .name = "debug", .type = UCI_TYPE_STRING },
{ .name = "debug", .type = UCI_TYPE_STRING }
};
struct uci_option *tb[NUM_CNTLR_ATTRS];
uci_parse_section(s, opts, NUM_CNTLR_ATTRS, tb);
if (tb[CNTLR_ENABLED]) {
const char *val = tb[CNTLR_ENABLED]->v.string;
if (tb[CNTLR_REGISTRAR]) {
const char *val = tb[CNTLR_REGISTRAR]->v.string;
c->has_registrar_5g = !strstr(val, "5") ? false : true;
c->has_registrar_2g = !strstr(val, "2") ? false : true;
const char *debug = tb[CNTLR_DEBUG]->v.string;
c->debug_level = atoi(debug);
if (c->debug_level > verbose)
verbose = c->debug_level;
static int cntlr_config_get_credentials(struct controller_config *c,
struct uci_section *s)
enum {
CRED_BAND,
CRED_SSID,
CRED_SEC,
CRED_KEY,
CRED_VLAN,
NUM_CREDS,
};
const struct uci_parse_option opts[] = {
[CRED_BAND] = { .name = "band", .type = UCI_TYPE_STRING },
[CRED_SSID] = { .name = "ssid", .type = UCI_TYPE_STRING },
[CRED_SEC] = { .name = "encryption", .type = UCI_TYPE_STRING },
[CRED_KEY] = { .name = "key", .type = UCI_TYPE_STRING },
[CRED_VLAN] = { .name = "vlan", .type = UCI_TYPE_STRING },
[CRED_MAP] = { .name = "multi_ap", .type = UCI_TYPE_STRING },
[CRED_D_BSTA] = { .name = "disallow_bsta", .type = UCI_TYPE_STRING },
};
struct uci_option *tb[NUM_CREDS];
struct iface_credential *cred;
if (!strcmp(s->type, "fh-credentials")) {
if (c->num_fh >= 2)
return -1;
cred = &c->fh[c->num_fh++];
} else {
if (c->num_bk >= 2)
return -1;
if (tb[CRED_BAND]) {
if (atoi(tb[CRED_BAND]->v.string) == 5)
cred->band = BAND_5;
cred->band = BAND_2;
strncpy((char *) cred->ssid, tb[CRED_SSID]->v.string, 32);
if (tb[CRED_SEC]) {
const char *sec = tb[CRED_SEC]->v.string;
if (!strncmp(sec, "psk3", 4))
cred->sec = WIFI_SECURITY_WPA3PSK;
else if (!strncmp(sec, "psk2", 4))
cred->sec = WIFI_SECURITY_WPA2PSK;
else if (!strncmp(sec, "psk", 3))
cred->sec = WIFI_SECURITY_WPAPSK;
//TODO: ciphers (if any)
}
strncpy((char *) cred->key, tb[CRED_KEY]->v.string, 63);
if (tb[CRED_VLAN])
cred->vlanid = atoi(tb[CRED_VLAN]->v.string);
if (tb[CRED_MAP])
cred->multi_ap = atoi(tb[CRED_MAP]->v.string);
if (tb[CRED_D_BSTA])
cred->disallow_bsta = atoi(tb[CRED_D_BSTA]->v.string);
static int cntlr_config_get_agent_policy(struct controller_config *c,
struct uci_section *s)
POL_STEER,
POL_UTIL_TH,
POL_RCPI_TH,
POL_RPT_SCAN,
POL_RPT_ASSOC_FAILS,
POL_RPT_METRIC_PERIODIC,
POL_RPT_RCPI_TH,
POL_RPT_UTIL_TH,
POL_INC_STA_STATS,
POL_INC_STA_METRIC,
POL_PVID,
POL_PCP_DEFAULT,
POL_DISALLOW_BSTA_P1,
POL_DISALLOW_BSTA_P2,
NUM_POLICIES,
};
const struct uci_parse_option opts[] = {
{ .name = "agent_id", .type = UCI_TYPE_STRING },
{ .name = "steer_policy", .type = UCI_TYPE_STRING },
{ .name = "util_threshold", .type = UCI_TYPE_STRING },
{ .name = "rcpi_threshold", .type = UCI_TYPE_STRING },
{ .name = "report_scan", .type = UCI_TYPE_STRING },
{ .name = "report_sta_assocfails", .type = UCI_TYPE_STRING },
{ .name = "report_metric_periodic", .type = UCI_TYPE_STRING },
{ .name = "report_rcpi_threshold", .type = UCI_TYPE_STRING },
{ .name = "report_util_threshold", .type = UCI_TYPE_STRING },
{ .name = "include_sta_stats", .type = UCI_TYPE_STRING },
{ .name = "include_sta_metric", .type = UCI_TYPE_STRING },
{ .name = "pvid", .type = UCI_TYPE_STRING },
{ .name = "pcp_default", .type = UCI_TYPE_STRING },
{ .name = "disallow_bsta_p1", .type = UCI_TYPE_STRING },
{ .name = "disallow_bsta_p2", .type = UCI_TYPE_STRING },
};
struct uci_option *tb[NUM_POLICIES];
struct agent_policy *a;
a = calloc(1, sizeof(*a));
if (!a)
return -1;
uci_parse_section(s, opts, NUM_POLICIES, tb);
if (tb[POL_AGENT_ID]) {
const char *val = tb[POL_AGENT_ID]->v.string;
a->util_threshold = atoi(tb[POL_UTIL_TH]->v.string);
a->rcpi_threshold = atoi(tb[POL_RCPI_TH]->v.string);
atoi(tb[POL_RPT_SCAN]->v.string) == 1 ? true : false;
atoi(tb[POL_RPT_ASSOC_FAILS]->v.string) == 1 ?
a->pcp_default = atoi(tb[POL_PCP_DEFAULT]->v.string);
atoi(tb[POL_DISALLOW_BSTA_P1]->v.string) == 1 ?
atoi(tb[POL_DISALLOW_BSTA_P2]->v.string) == 1 ?
int cntlr_config_reload(struct controller_config *cfg)
struct uci_context *ctx;
struct uci_package *pkg;
struct uci_element *e;
ctx = uci_alloc_context();
if (uci_load(ctx, "controller", &pkg)) {
uci_free_context(ctx);
return -1;
}
uci_foreach_element(&pkg->sections, e) {
struct uci_section *s = uci_to_section(e);
if (!strcmp(s->type, "wificntlr")) {
cntlr_config_get_base(cfg, s);
} else if (!strcmp(s->type, "fh-credentials") ||
!strcmp(s->type, "bk-credentials")) {
cntlr_config_get_credentials(cfg, s);
} else if (!strcmp(s->type, "agent-policy")) {
cntlr_config_get_agent_policy(cfg, s);
}
int clean_agent_policies(struct controller_config *cfg)
{
struct agent_policy *p, *tmp;
list_for_each_entry_safe(p, tmp, &cfg->policylist, list) {
list_del(&p->list);
free(p);
}
return 0;
}
int cntlr_config_clean(struct controller_config *cfg)
{
clean_agent_policies(cfg);
return 0;
}