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"
#define WPS_AUTH_OPEN (0x0001)
#define WPS_AUTH_WPAPSK (0x0002)
#define WPS_AUTH_SHARED (0x0004) /* deprecated */
#define WPS_AUTH_WPA (0x0008)
#define WPS_AUTH_WPA2 (0x0010)
#define WPS_AUTH_WPA2PSK (0x0020)
#define WPS_ENCR_NONE (0x0001)
#define WPS_ENCR_WEP (0x0002) /* deprecated */
#define WPS_ENCR_TKIP (0x0004)
#define WPS_ENCR_AES (0x0008)
// 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 -1;
}
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
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
179
180
181
182
183
184
185
186
187
/* 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();
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,
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
430
431
432
433
434
435
436
437
438
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,
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
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
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
char *section_type, char *ifname, char *option, char *value)
{
struct uci_context *ctx;
struct uci_package *pkg;
struct uci_element *e;
if (!package_name || !ifname || !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,
"ifname");
if (!opt || opt->type != UCI_TYPE_STRING)
continue;
if (strcmp(opt->v.string, ifname) == 0) {
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
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,
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
588
589
590
591
592
593
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(void)
memset(&bb, 0, sizeof(struct blob_buf));
blob_buf_init(&bb, 0);
blobmsg_add_string(&bb, "config", "wireless");
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;
blob_buf_free(&bb);
return false;
}
Jakob Olsson
committed
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
/* 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)
{
bool ret;
char auth_type_str[20] = {0};
char multiap_str[2] = {0};
uint8_t multi_ap = 0;
Jakob Olsson
committed
bool bk_mode;
Jakob Olsson
committed
char agent_section[16] = {0};
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);
// 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);
Jakob Olsson
committed
bk_mode = BIT(6, mapie);
snprintf(multiap_str, sizeof(multiap_str), "%d", multi_ap);
if (!get_encryption_value(auth_type, encryption_type,
auth_type_str, 20)) {
info("Unsupported encryption or cipher received!!\n");
return M2_PROCESS_ERROR;
}
Jakob Olsson
committed
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,
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;
Jakob Olsson
committed
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,
Jakob Olsson
committed
UCI_BK_AGENT,
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;
}
Jakob Olsson
committed
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,
interface_name, "key", (char *) network_key);
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,
Jakob Olsson
committed
interface_name, "mode", "ap");
uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE,
Jakob Olsson
committed
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 */
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;
}
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
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 netif_fhcfg *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 netif_fhcfg *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;
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");
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
}
dbg(" Steer Exclude Lists -------\n");
list_for_each_entry(x, &n->steer_excludelist, list) {
dbg(" mac: %s\n", x->macstring);
}
dbg(" Steer BTM Exclude Lists -------\n");
list_for_each_entry(x, &n->steer_btm_excludelist, list) {
dbg(" mac: %s\n", x->macstring);
}
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));
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
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->steer_excludelist);
INIT_LIST_HEAD(&new->steer_btm_excludelist);
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");
return NULL;
}
snprintf(new->name, 16, "%s", ifname);
new->enabled = true;
new->onboarded = false;
/* f->cfg = new; */
dbg("%s: %s netif_fh->cfg = %p\n", __func__, new->name, new);
}
static void config_update_entry(struct uci_context *ctx, struct uci_package *p,
struct uci_section *s, const char *optname,
int add, void *val, int len)
{
struct uci_ptr ptr;
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = s;
ptr.package = p->e.name;
ptr.section = s->e.name;
ptr.option = optname;
ptr.target = UCI_TYPE_OPTION;
ptr.flags |= UCI_LOOKUP_EXTENDED;
ptr.value = (char *)val;
if (add) {
dbg("config: add list option: %s\n", (char *)val);
uci_add_list(ctx, &ptr);