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 IFNAMSIZ
#define IFNAMSIZ 16
#endif
//Security and encryption
#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 ATTR_ENCR_TYPE_FLAGS (0x1010)
#define WPS_ENCR_NONE (0x0001)
#define WPS_ENCR_WEP (0x0002) /* deprecated */
#define WPS_ENCR_TKIP (0x0004)
#define WPS_ENCR_AES (0x0008)
#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 <1905_tlvs.h>
#include <map22.h>
#include <easy/easy.h>
#include <map_module22.h>
#include <bufutil.h>
#include "debug.h"
#include "utils.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"
char *replace_char(char *str, char find, char replace)
{
char *current_pos = strchr(str, find);
while (current_pos) {
*current_pos = replace;
current_pos = strchr(current_pos, find);
}
return str;
}
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
/* 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;
}
#if 0
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
int wifi_get_iface_bssid(char *ifname, uint8_t *bssid)
{
struct uci_context *ctx = NULL;
struct uci_package *pkg;
struct uci_section *section;
struct uci_ptr ptr = {0};
int ret = -1;
if (!bssid)
return ret;
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;
ptr.p = pkg;
ptr.s = section;
ptr.option = "bssid";
ptr.target = UCI_TYPE_OPTION;
ret = uci_lookup_ptr(ctx, &ptr, NULL, false);
if (!ret && ptr.o)
hwaddr_aton(ptr.o->v.string, bssid);
else
memset(bssid, 0, 6);
out_pkg:
uci_unload(ctx, pkg);
uci_free_context(ctx);
return ret;
}
#endif
int wifi_get_iface_bssid(char *ifname, uint8_t *bssid)
{
struct uci_context *ctx = NULL;
struct uci_package *pkg;
struct uci_section *section;
struct uci_ptr ptr = {0};
int ret = -1;
if (!bssid)
return ret;
pkg = uci_load_pkg(&ctx, "mapagent");
if (!pkg)
return ret;
section = config_get_section(ctx, pkg, "bk-iface", "ifname", ifname);
if (!section)
goto out_pkg;
ptr.p = pkg;
ptr.s = section;
ptr.option = "bssid";
ptr.target = UCI_TYPE_OPTION;
ret = uci_lookup_ptr(ctx, &ptr, NULL, false);
if (!ret && ptr.o)
hwaddr_aton(ptr.o->v.string, bssid);
else
memset(bssid, 0, 6);
out_pkg:
uci_unload(ctx, pkg);
uci_free_context(ctx);
return ret;
}
Jakob Olsson
committed
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
int wifi_set_iface_bssid(struct netif_bk *bk, uint8_t *bssid)
{
struct uci_context *ctx = NULL;
struct uci_package *pkg;
struct uci_section *section;
struct uci_ptr ptr = {0};
char bssid_str[18] = {0};
int ret = -1;
pkg = uci_load_pkg(&ctx, "mapagent");
if (!pkg)
return ret;
section = config_get_section(ctx, pkg, "bk-iface", "ifname", bk->name);
if (!section)
goto out_pkg;
if (bssid && !hwaddr_is_zero(bssid))
hwaddr_ntoa(bssid, bssid_str);
dbg("|%s:%d| setting bssid to %s\n", bssid_str);
ret = set_value(ctx, pkg, section, "bssid", bssid_str, UCI_TYPE_STRING);
uci_commit(ctx, &pkg, false);
out_pkg:
uci_unload(ctx, pkg);
uci_free_context(ctx);
return ret;
}
#if 0 /* strive to not touch /etc/config/wireless */
/* TODO: can it be generalized? */
int wifi_set_iface_bssid(struct netif_bk *bk, uint8_t *bssid)
{
struct uci_context *ctx = NULL;
struct uci_package *pkg;
struct uci_section *section;
struct uci_ptr ptr = {0};
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", bk->name);
if (!section)
goto out_pkg;
if (bssid && !hwaddr_is_zero(bssid))
hwaddr_ntoa(bssid, bssid_str);
dbg("|%s:%d| setting bssid to %s\n", bssid_str);
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;
}
#endif
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);
set_value(ctx, pkg, section, "default_disabled", "0", UCI_TYPE_STRING);
uci_commit(ctx, &pkg, false);
out_pkg:
uci_unload(ctx, pkg);
out_uci:
uci_free_context(ctx);
out:
return rv;
}
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
char *agent_config_get_ethwan(char *ifname)
{
struct uci_context *ctx;
struct uci_ptr ptr = {0};
ctx = uci_alloc_context();
if (!ctx)
return NULL;
//ptr.value = value;
ptr.package = "ports";
ptr.section = "WAN";
ptr.option = "ifname";
ptr.target = UCI_TYPE_OPTION;
if (uci_lookup_ptr(ctx, &ptr, NULL, false)) {
uci_free_context(ctx);
return NULL;
}
strncpy(ifname, ptr.o->v.string, 15);
uci_free_context(ctx);
return ifname;
}
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,
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
595
596
597
598
599
600
601
602
603
604
605
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) {
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, int *mfp)
{
if (!encrypt_val)
return false;
*mfp = 0;
if ((auth_type & WPS_AUTH_WPA2PSK) && (auth_type & WPS_AUTH_SAE)) {
strncat(encrypt_val, "sae-mixed", elen);
*mfp = 1;
} else if (auth_type & WPS_AUTH_SAE) {
strncat(encrypt_val, "sae", elen);
*mfp = 2;
} else 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,
char *section_type, char *section_name)
{
struct uci_context *ctx;
struct uci_package *pkg;
struct uci_section *s;
struct uci_ptr ptr = {0};
bool ret = false;
if (!interface_name || !package_name)
return false;
ctx = uci_alloc_context();
if (!ctx)
return false;
if (uci_load(ctx, package_name, &pkg))
goto out_ctx;
ptr.p = pkg;
if (section_name) {
ptr.section = section_name;
ptr.value = section_type;
ptr.option = NULL;
uci_set(ctx, &ptr);
if (uci_save(ctx, ptr.p) != UCI_OK)
goto out_unload;
} else {
if (uci_add_section(ctx, pkg, section_type, &s) != UCI_OK)
goto out_unload;
ptr.value = interface_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);
ret = true;
out_unload:
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
}
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
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
/*
* Will only be successful if uci_apply_m2 is done prior, or interfaces already
* exist and are configured through other means
*/
void uci_apply_traffic_sep(struct tlv_traffic_sep_policy *tlv)
{
int i;
uint8_t *ptr;
ptr = tlv;
ptr++;
for (i = 0; i < tlv->num_ssid; i++) {
char ssid[33] = {0};
char vid[8] = {0};
uint8_t len = 0;
len = *ptr;
ptr++;
memcpy(ssid, ptr, len);
ptr += len;
snprintf(vid, sizeof(vid), "%u", buf_get_be16(ptr));
ptr += 2;
uci_set_wireless_interface_option(UCI_AGENT, UCI_FH_AGENT,
"ssid", ssid, "vid", vid);
}
}
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,
struct wps_credential *out, bool onboarded, struct iop_ext *exts)
{
bool ret;
char auth_type_str[20] = {0};
char multiap_str[2] = {0};
uint8_t multi_ap = 0;
char band_str[2] = {0};
char ipaddr_str[INET_ADDRSTRLEN] = {0};
char ssid[33] = {0}, network_key[65] = {0}, bridge_buf[16] = {0}, *bridge;
int mfp = 0;
/* step past br- prefix if present*/
if (!strncmp("br-", bridge, 3))
bridge += 3;
dbg("%s %d band = %d\n", __func__, __LINE__, out->band);
if (out->band == BAND_5)
strncpy(band_str, "5", 1);
else if (out->band == BAND_2)
strncpy(band_str, "2", 1);
else /* TODO: 60 */
return M2_PROCESS_ERROR;
memcpy(ssid, out->ssid, out->ssidlen);
memcpy(network_key, out->key, out->keylen);
memcpy(bridge, exts->bridge, 15);
inet_ntop(AF_INET, &exts->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", out->auth_type);
dbg(" - ENCRYPTION_TYPE : 0x%04x\n", out->enc_type);
dbg(" - MAPIE_EXTENSION : 0x%02x\n", out->mapie);
dbg(" - BRIDGE : %s\n", bridge);
dbg(" - PROTO : %s\n", exts->proto);
dbg(" - VID : 0x%02x\n", exts->vid);
dbg(" - BR_IP : %s\n", ipaddr_str);
dbg(" - BAND : %s\n", band_str);
dbg(" - ENABLED : %d\n", exts->enabled);
multi_ap |= (BIT(5, out->mapie) << 1);
multi_ap |= BIT(6, out->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(out->auth_type, out->enc_type,
auth_type_str, 20, &mfp)) {
info("Unsupported encryption or cipher received!!\n");
return M2_PROCESS_ERROR;
}
ret = uci_set_bridge("network", bridge, exts->proto, ipaddr_str);
if (ret) {
info("Error seting up bridge from M2!\n");
return M2_PROCESS_ERROR;
}
// Set uci in agent
ret = uci_check_wifi_iface(UCI_AGENT, interface_name,
if (!ret) {
ret = uci_add_wireless_iface_sec(UCI_AGENT, interface_name,
if (!ret)
return M2_PROCESS_ERROR;
}
uci_set_wireless_interface_option(UCI_AGENT, UCI_FH_AGENT, "ifname",
Jakob Olsson
committed
interface_name, "band", band_str);
uci_set_wireless_interface_option(UCI_AGENT, UCI_FH_AGENT, "ifname",
Jakob Olsson
committed
interface_name, "device", device);
uci_set_wireless_interface_option(UCI_AGENT, UCI_FH_AGENT, "ifname",
Jakob Olsson
committed
interface_name, "ssid", ssid);
uci_set_wireless_interface_option(UCI_AGENT, UCI_FH_AGENT, "ifname",
Jakob Olsson
committed
interface_name, "key", network_key);
uci_set_wireless_interface_option(UCI_AGENT, UCI_FH_AGENT, "ifname",
Jakob Olsson
committed
interface_name, "encryption", auth_type_str);
uci_set_wireless_interface_option(UCI_AGENT, UCI_FH_AGENT, "ifname",
interface_name, "multi_ap", multiap_str);
uci_set_wireless_interface_option(UCI_AGENT, UCI_FH_AGENT, "ifname",
interface_name, "enabled", (exts->enabled ? "1" : "0"));
if (multi_ap & 0x01) {
char disallow_str[2] = {0};
snprintf(disallow_str, sizeof(disallow_str), "%d",
uci_set_wireless_interface_option(UCI_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) {
char name[32] = {0};
snprintf(name, sizeof(name), "%s_ap", interface_name);
replace_char(name, '.', '_');
ret = uci_add_wireless_iface_sec(UCI_WIRELESS, interface_name,
if (!ret)
return M2_PROCESS_ERROR;
}
uci_set_wireless_interface_option(UCI_WIRELESS, UCI_WLAN_IFACE, "ifname",
interface_name, "network", bridge);