Newer
Older
/*
* config.c - configurations handling
*
* Copyright (C) 2019 IOPSYS Software Solutions AB. All rights reserved.
*
* Author: anjan.chanda@iopsys.eu
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.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 "debug.h"
#include "utils.h"
#include "config.h"
#include "steer_rules.h"
#include "comm.h"
#include "msgqueue.h"
#include "worker.h"
// UCI sections
#define UCI_BK_AGENT "bk-iface"
#define UCI_FH_AGENT "fh-iface"
#define UCI_WLAN_IFACE "wifi-iface"
#define UCI_WL_DEVICE "wifi-device"
#define UCI_WIRELESS "wireless"
#define UCI_IEEE1905 "ieee1905"
Jakob Olsson
committed
#define UCI_AGENT "mapagent"
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;
}
Jakob Olsson
committed
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 rv;
Jakob Olsson
committed
}
struct uci_section *config_get_section(struct uci_context *ctx,
struct uci_package *pkg, const char *type, const char *key,
const char *value)
{
struct uci_element *e;
struct uci_section *section;
/* get the wet iface section */
uci_foreach_element(&pkg->sections, e) {
const char *c_value;
section = uci_to_section(e);
c_value = uci_lookup_option_string(ctx, section, key);
if (c_value && !strcmp(c_value, value))
return section;
}
return NULL;
}
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;
}
Jakob Olsson
committed
if (uci_load(*ctx, config, &pkg) != UCI_OK) {
free(*ctx);
return NULL;
}
return pkg;
}
Jakob Olsson
committed
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/* 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)
{
struct uci_context *ctx = NULL;
struct uci_package *pkg;
struct uci_section *section;
char bssid_str[18] = {0};
int ret = -1;
pkg = uci_load_pkg(&ctx, "wireless");
if (!pkg)
return ret;
section = config_get_section(ctx, pkg, "wifi-iface", "ifname", ifname);
if (!section)
goto out_pkg;
if (bssid && !hwaddr_ntoa(bssid, bssid_str))
goto out_pkg;
ret = set_value(ctx, pkg, section, "bssid", bssid_str, UCI_TYPE_STRING);
uci_commit(ctx, &pkg, false);
uci_reload_services("wireless");
out_pkg:
uci_unload(ctx, pkg);
uci_free_context(ctx);
return ret;
}
int config_del_iface(const char *config, const char *type, const char *ifname)
{
struct uci_context *ctx;
struct uci_package *pkg;
struct uci_section *section;
struct uci_ptr ptr = {0};
int rv = -1;
ctx = uci_alloc_context();
if (!ctx)
goto out;
if (uci_load(ctx, config, &pkg) != UCI_OK) {
dbg("config file 'wireless' not found!\n");
goto out_uci;
}
section = config_get_section(ctx, pkg, type, "ifname", ifname);
if (!section)
goto out_pkg;
ptr.p = pkg;
ptr.s = section;
uci_delete(ctx, &ptr);
uci_commit(ctx, &pkg, false);
out_pkg:
uci_unload(ctx, pkg);
out_uci:
uci_free_context(ctx);
out:
return rv;
}
int wifi_apply_iface_cfg(const char *ifname, const char *encryption,
const char *ssid, const char *key)
{
struct uci_context *ctx;
struct uci_package *pkg;
struct uci_section *section;
int rv = -1;
ctx = uci_alloc_context();
if (!ctx)
goto out;
if (uci_load(ctx, "wireless", &pkg) != UCI_OK) {
dbg("config file 'wireless' not found!\n");
goto out_uci;
}
section = config_get_section(ctx, pkg, "wifi-iface", "ifname", ifname);
if (!section)
goto out_pkg;
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);
Jakob Olsson
committed
set_value(ctx, pkg, section, "wds", "1", UCI_TYPE_STRING);
uci_commit(ctx, &pkg, false);
out_pkg:
uci_unload(ctx, pkg);
out_uci:
uci_free_context(ctx);
out:
return rv;
}
struct uci_section *config_add_section(struct uci_context *ctx,
struct uci_package *pkg, const char *config, const char *type,
const char *key, const char *value)
struct uci_section *section = NULL;
struct uci_ptr ptr = {0};
int rv = -1;
section = config_get_section(ctx, pkg, type, key, value);
if (!section) {
rv = uci_add_section(ctx, pkg, type, §ion);
if (rv)
goto out_pkg;
rv = uci_save(ctx, pkg);
if (rv)
goto out_pkg;
ptr.value = value;
ptr.package = config;
ptr.section = section->e.name;
ptr.option = key;
ptr.target = UCI_TYPE_OPTION;
uci_lookup_ptr(ctx, &ptr, NULL, false);
uci_set(ctx, &ptr);
uci_save(ctx, ptr.p);
return section;
}
int config_add_default_wifi_iface(const char *config, const char *type,
const char *ifname, const char *device, const char *network,
const char *mode)
{
struct uci_context *ctx;
struct uci_package *pkg;
struct uci_section *section;
int rv = -1;
ctx = uci_alloc_context();
if (!ctx)
goto out;
if (uci_load(ctx, config, &pkg) != UCI_OK) {
dbg("config file 'wireless' not found!\n");
goto out_uci;
}
section = config_add_section(ctx, pkg, config, type, "ifname", ifname);
set_value(ctx, pkg, section, "device", device, UCI_TYPE_STRING);
set_value(ctx, pkg, section, "network", network, UCI_TYPE_STRING);
//set_value(ctx, pkg, section, "mode", mode, UCI_TYPE_STRING);
uci_commit(ctx, &pkg, false);
out_pkg:
uci_unload(ctx, pkg);
out_uci:
uci_free_context(ctx);
out:
}
int config_add_default_agent_iface(const char *config, const char *type,
const char *ifname, enum wifi_band band)
{
struct uci_context *ctx;
struct uci_package *pkg;
struct uci_section *section;
int rv = -1;
ctx = uci_alloc_context();
if (!ctx)
goto out;
if (uci_load(ctx, config, &pkg) != UCI_OK) {
dbg("config file 'wireless' not found!\n");
goto out_uci;
}
section = config_add_section(ctx, pkg, config, type, "ifname", ifname);
trace("band = %d\n", band);
if (band == BAND_5)
set_value(ctx, pkg, section, "band", "5", UCI_TYPE_STRING);
if (band == BAND_2)
set_value(ctx, pkg, section, "band", "2", UCI_TYPE_STRING);
uci_commit(ctx, &pkg, false);
out_pkg:
uci_unload(ctx, pkg);
out_uci:
uci_free_context(ctx);
out:
}
/* below functions are mostly taken from ieee1905d */
Jakob Olsson
committed
bool uci_check_wifi_iface(char *package_name, char *ifname,
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
char *section)
{
bool ret;
struct uci_context *ctx;
struct uci_package *pkg;
struct uci_element *e;
if (!package_name || !ifname)
return false;
ctx = uci_alloc_context();
if (!ctx)
return false;
if (uci_load(ctx, package_name, &pkg)) {
uci_free_context(ctx);
return false;
}
ret = false;
uci_foreach_element(&pkg->sections, e) {
struct uci_section *s = uci_to_section(e);
if (!strcmp(s->type, section)) {
struct uci_option *opt = uci_lookup_option(ctx, s,
"ifname");
if (!opt || opt->type != UCI_TYPE_STRING)
continue;
if (strcmp(opt->v.string, ifname) == 0) {
ret = true;
break;
}
}
}
uci_unload(ctx, pkg);
uci_free_context(ctx);
return ret;
}
Jakob Olsson
committed
bool uci_set_wireless_interface_option(char *package_name,
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 || !search_val || !option || !value)
return false;
ctx = uci_alloc_context();
if (!ctx)
return false;
if (uci_load(ctx, package_name, &pkg)) {
uci_free_context(ctx);
return false;
}
uci_foreach_element(&pkg->sections, e) {
struct uci_section *s = uci_to_section(e);
if (!strcmp(s->type, section_type)) {
struct uci_option *opt = uci_lookup_option(ctx, s,
if (!opt || opt->type != UCI_TYPE_STRING)
continue;
if (strcmp(opt->v.string, search_val) == 0) {
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
struct uci_ptr ptr = {0};
ptr.value = value;
ptr.package = package_name;
ptr.section = s->e.name;
ptr.option = option;
ptr.target = UCI_TYPE_OPTION;
if (uci_lookup_ptr(ctx, &ptr, NULL, false) ||
!UCI_LOOKUP_COMPLETE)
break;
if (uci_set(ctx, &ptr) == UCI_OK)
uci_save(ctx, ptr.p);
break;
}
}
}
uci_commit(ctx, &pkg, false);
uci_unload(ctx, pkg);
uci_free_context(ctx);
return false;
}
static bool get_encryption_value(uint16_t auth_type, uint16_t encryption_type,
char *encrypt_val, size_t elen)
{
if (!encrypt_val)
return false;
if ((auth_type & WPS_AUTH_WPAPSK) && (auth_type & WPS_AUTH_WPA2PSK))
strncat(encrypt_val, "psk-mixed", elen);
else if ((auth_type & WPS_AUTH_WPA) && (auth_type & WPS_AUTH_WPA2))
strncat(encrypt_val, "wpa-mixed", elen);
else if (auth_type & WPS_AUTH_WPAPSK)
strncat(encrypt_val, "psk", elen);
else if (auth_type & WPS_AUTH_WPA2PSK)
strncat(encrypt_val, "psk2", elen);
else if (auth_type & WPS_AUTH_WPA)
strncat(encrypt_val, "wpa", elen);
else if (auth_type & WPS_AUTH_WPA2)
strncat(encrypt_val, "wpa2", elen);
else if (auth_type & WPS_AUTH_OPEN)
strncat(encrypt_val, "none", elen);
else
return false;
//Check for the encryption type
if ((encryption_type & WPS_ENCR_TKIP) &&
(encryption_type & WPS_ENCR_AES))
strncat(encrypt_val, "+tkip+aes", elen);
else if (encryption_type & WPS_ENCR_TKIP)
strncat(encrypt_val, "+tkip", elen);
else if (encryption_type & WPS_ENCR_AES)
strncat(encrypt_val, "+aes", elen);
return true;
}
Jakob Olsson
committed
bool uci_add_wireless_iface_sec(char *package_name, char *interface_name,
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
char *section_name)
{
struct uci_context *ctx;
struct uci_package *pkg;
struct uci_section *s;
if (!interface_name || !package_name)
return false;
ctx = uci_alloc_context();
if (!ctx)
return false;
if (uci_load(ctx, package_name, &pkg)) {
uci_free_context(ctx);
return false;
}
if (uci_add_section(ctx, pkg, section_name, &s) == UCI_OK) {
struct uci_ptr ptr = {0};
if (uci_save(ctx, pkg) != UCI_OK)
return false;
ptr.value = interface_name;
ptr.package = package_name;
ptr.section = s->e.name;
ptr.option = "ifname";
ptr.target = UCI_TYPE_OPTION;
uci_lookup_ptr(ctx, &ptr, NULL, false);
uci_set(ctx, &ptr);
uci_save(ctx, ptr.p);
uci_commit(ctx, &pkg, false);
}
uci_unload(ctx, pkg);
uci_free_context(ctx);
return true;
}
static int ubus_call(const char *object, const char *method,
struct blob_buf *data, void *callback, void *cb_arg)
{
uint32_t id;
struct ubus_context *ctx = ubus_connect(NULL);
if (!ctx) {
err("ubus_connect failed\n");
return UBUS_STATUS_UNKNOWN_ERROR;
}
if (ubus_lookup_id(ctx, object, &id)) {
err("(%s) not present\n", object);
ubus_free(ctx);
return UBUS_STATUS_UNKNOWN_ERROR;
}
// Invoke Ubus to get data from uspd
if (ubus_invoke(ctx, id, method, data->head, callback, cb_arg, 1000)) {
err("ubus call failed\n");
ubus_free(ctx);
return UBUS_STATUS_UNKNOWN_ERROR;
}
ubus_free(ctx);
return UBUS_STATUS_OK;
}
bool uci_reload_services(char *services)
int rv = 0;
memset(&bb, 0, sizeof(struct blob_buf));
blob_buf_init(&bb, 0);
blobmsg_add_string(&bb, "config", services);
rv = ubus_call("uci", "commit", &bb, NULL, NULL);
info("## Reloading uci config %d\n", rv);
//if (!ubus_call("uci", "reload_config", &bb, NULL, NULL))
// return true;
//ubus_call("uci", "reload_config", &bb, NULL, NULL);
blob_buf_free(&bb);
return false;
}
#if 0 /* Deprecated for 6.1 - Possibly bring back in 6.2 with modifications */
Jakob Olsson
committed
/* 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,
Jakob Olsson
committed
fh->name,
"multi_ap_backhaul_ssid",
bk->ssid);
uci_set_wireless_interface_option(UCI_WIRELESS,
UCI_WLAN_IFACE,
Jakob Olsson
committed
fh->name,
"multi_ap_backhaul_key",
bk->key);
uci_set_wireless_interface_option(UCI_WIRELESS,
UCI_WLAN_IFACE, "ifname", fh->name, "wps", "1");
Jakob Olsson
committed
uci_set_wireless_interface_option(UCI_WIRELESS,
UCI_WLAN_IFACE, "ifname", fh->name,
Jakob Olsson
committed
"wps_pushbutton", "1");
}
break;
}
return 0;
}
Jakob Olsson
committed
/* TODO: batch the changes arther than commit oneby one */
int uci_apply_m2(struct agent_config *cfg, 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 *bridge, uint8_t *proto, uint8_t vid, uint32_t br_ip,
uint8_t *bk_ssid, uint8_t *bk_key, bool onboarded)
{
bool ret;
char auth_type_str[20] = {0};
char multiap_str[2] = {0};
uint8_t multi_ap = 0;
char band_str[2] = {0};
Jakob Olsson
committed
char agent_section[16] = {0};
char ipaddr_str[INET_ADDRSTRLEN] = {0};
/* step past br- prefix if present*/
if (!strncmp("br-", bridge, 3))
bridge += 3;
inet_ntop(AF_INET, &br_ip, ipaddr_str, INET_ADDRSTRLEN);
dbg("Applying WSC configuration (%s):\n", interface_name);
dbg(" - SSID : %s\n", ssid);
dbg(" - AUTH_TYPE : 0x%04x\n", auth_type);
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;
multi_ap |= (BIT(5, mapie) << 1);
multi_ap |= BIT(6, mapie);
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, UCI_FH_AGENT, sizeof(agent_section));
Jakob Olsson
committed
// Set uci in agent
ret = uci_check_wifi_iface(UCI_AGENT, interface_name,
Jakob Olsson
committed
agent_section);
if (!ret) {
ret = uci_add_wireless_iface_sec(UCI_AGENT, interface_name,
Jakob Olsson
committed
agent_section);
if (!ret)
return M2_PROCESS_ERROR;
}
if (band == BAND_5)
strncpy(band_str, "5", 1);
else if (band == BAND_2)
strncpy(band_str, "2", 1);
else /* TODO: 60 */
return M2_PROCESS_ERROR;
uci_set_wireless_interface_option(UCI_AGENT, agent_section, "ifname",
Jakob Olsson
committed
interface_name, "band", band_str);
uci_set_wireless_interface_option(UCI_AGENT, agent_section, "ifname",
Jakob Olsson
committed
interface_name, "device", device);
uci_set_wireless_interface_option(UCI_AGENT, agent_section, "ifname",
Jakob Olsson
committed
interface_name, "ssid", ssid);
uci_set_wireless_interface_option(UCI_AGENT, agent_section, "ifname",
Jakob Olsson
committed
interface_name, "key", network_key);
uci_set_wireless_interface_option(UCI_AGENT, agent_section, "ifname",
Jakob Olsson
committed
interface_name, "encryption", auth_type_str);
if (multi_ap & 0x01) {
char disallow_str[2] = {0};
snprintf(disallow_str, sizeof(disallow_str), "%d",
((mapie >> 2) & 0x03));
uci_set_wireless_interface_option(UCI_AGENT,
agent_section, "ifname",
interface_name,
"disallow_bsta", disallow_str);
}
// Set uci in wireless
ret = uci_check_wifi_iface(UCI_WIRELESS, interface_name,
UCI_WLAN_IFACE);
if (!ret) {
ret = uci_add_wireless_iface_sec(UCI_WIRELESS, interface_name,
UCI_WLAN_IFACE);
if (!ret)
return M2_PROCESS_ERROR;
}
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",
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, "ifname",
interface_name, "encryption", auth_type_str);
uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, "ifname",
Jakob Olsson
committed
interface_name, "mode", "ap");
uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, "ifname",
Jakob Olsson
committed
interface_name, "device", device);
uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, "ifname",
Jakob Olsson
committed
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 (onboarded)
uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, "ifname",
interface_name, "disabled", "1");
if (multi_ap == 0x01) {
Jakob Olsson
committed
uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE,
"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");
Jakob Olsson
committed
}
/* TODO: don't support guest network for the moment */
//uci_add_dhcp(bridge);
//uci_add_fw(cfg, bridge);
return M2_PROCESS_OK;
}
/* end of functions taken from ieee1905d */
static struct netif_bkcfg *get_netif_bkcfg_by_name(struct agent_config *c,
{
struct netif_bkcfg *p;
list_for_each_entry(p, &c->bklist, list) {
if (!strcmp(name, p->name))
return p;
}
return NULL;
}
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
static struct netif_fhcfg *get_netif_fhcfg_by_name(struct agent_config *c,
const char *name)
{
struct netif_fhcfg *p;
list_for_each_entry(p, &c->fhlist, list) {
if (!strcmp(name, p->name))
return p;
}
return NULL;
}
static struct steer_policy *get_steer_policy_by_name(struct netif_fhcfg *c,
const char *name)
{
struct steer_policy *p;
if (!c)
return NULL;
list_for_each_entry(p, &c->steer_policylist, list) {
if (!strcmp(name, p->name))
return p;
}
return NULL;
}
void stax_add_entry(struct list_head *h, char *sta_macstr)
{
struct stax *n;
n = calloc(1, sizeof(struct stax));
if (n) {
snprintf(n->macstring, 18, "%s", sta_macstr);
list_add(&n->list, h);
}
}
void stax_del_entry(struct list_head *h, char *sta_macstr)
{
struct stax *s, *tmp;
list_for_each_entry_safe(s, tmp, h, list) {
if (!strncmp(s->macstring, sta_macstr, sizeof(s->macstring))) {
list_del(&s->list);
free(s);
return;
}
}
}
static int clean_steer_btm_excl(struct agent_config *p)
{
struct stax *n, *tmp;
list_for_each_entry_safe(n, tmp, &p->steer_btm_excludelist, list) {
list_del(&n->list);
free(n);
}
return 0;
}
static int clean_steer_excl(struct agent_config *p)
{
struct stax *n, *tmp;
list_for_each_entry_safe(n, tmp, &p->steer_excludelist, list) {
list_del(&n->list);
free(n);
}
return 0;
}
void agent_config_dump(struct agent_config *cfg)
{
struct netif_fhcfg *n;
struct steer_policy *pol;
struct stax *x;
if (!cfg)
return;
dbg(" Steer Exclude Lists -------\n");
list_for_each_entry(x, &cfg->steer_excludelist, list) {
dbg(" mac: %s\n", x->macstring);
}
dbg(" Steer BTM Exclude Lists -------\n");
list_for_each_entry(x, &cfg->steer_btm_excludelist, list) {
dbg(" mac: %s\n", x->macstring);
}
list_for_each_entry(n, &cfg->fhlist, list) {
dbg("name: %s\n", n->name);
dbg(" enabled : %s\n", n->enabled ? "true" : "false");
dbg(" assocctrl: %s\n", n->assoc_control ? "true" : "false");
dbg(" Policies -------\n");
list_for_each_entry(pol, &n->steer_policylist, list) {
dbg(" name: %s\n", pol->name);
dbg(" enabled : %s\n",
pol->enabled ? "true" : "false");
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
}
dbg(" Assoc Ctrl Lists -------\n");
list_for_each_entry(x, &n->assoc_ctrllist, list) {
dbg(" mac: %s\n", x->macstring);
}
}
}
/* create fh-iface config and initialize with default values */
struct netif_fhcfg *create_fronthaul_iface_config(struct agent_config *cfg,
const char *ifname)
{
struct netif_fhcfg *new;
struct steer_rule *r;
if (!cfg)
return NULL;
new = calloc(1, sizeof(struct netif_fhcfg));
if (!new) {
warn("OOM! config\n");
return NULL;
}
snprintf(new->name, 16, "%s", ifname);
new->enabled = true;
new->fallback_legacy = STEER_LEGACY_FALLBACK_INT;
new->steer_btm_retry_secs = STEER_BTM_RETRY_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));
goto err_oom;
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->assoc_ctrllist);
/* f->cfg = new; */
dbg("%s: %s netif_fh->cfg = %p\n", __func__, new->name, new);
list_add(&new->list, &cfg->fhlist);
return new;
err_oom:
list_flush(&new->steer_policylist, struct steer_policy, list);
free(new);
return NULL;
}
/* create fh-iface config and initialize with default values */
struct netif_bkcfg *create_backhaul_iface_config(struct agent_config *cfg,
const char *ifname)
struct netif_bkcfg *new;
if (!cfg)
return NULL;
new = calloc(1, sizeof(struct netif_bkcfg));
if (!new) {
warn("OOM! config\n");