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,
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) {
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
523
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,
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
594
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;
}
#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(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 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};
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);
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);
Jakob Olsson
committed
bk_mode = 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;
}
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;
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, "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 (bk_mode) {
char disallow_str[2] = {0};
snprintf(disallow_str, sizeof(disallow_str), "%d",
((mapie >> 2) & 0x03));
uci_set_wireless_interface_option(UCI_AGENT,
UCI_BK_AGENT, "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);
Jakob Olsson
committed
if (bk_mode) {
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
}
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 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");
915
916
917
918
919
920
921
922
923
924
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(" 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));
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
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));