Commit 451e65a4 authored by Jakob Olsson's avatar Jakob Olsson
Browse files

implement ap_autoconfig cmdus

Includes some memory management fixes, some TLV building
refactoring and misc cleanup.

The controller side does currently not implement any function
to trigger a credential exchange, but must in the currentl
implementation be triggered from the agent side. Such feature
is still to be implemented.
parent 713f5945
Pipeline #6703 failed with stages
in 50 seconds
......@@ -160,5 +160,104 @@ config rule-custom
echo "
config wificntlr
option enabled '1'
option registrar '5 2' #bands on which wps registrar supported
option debug '6'
config fh-credentials 'map-net55'
option band '5'
option encryption 'psk2'
option key '1234567890'
option ssid 'map-net5'
option vlan '101'
option multi_ap '128' # TODO: should mode 1/2/3 be added?
config fh-credentials 'map-net55'
option band '5'
option encryption 'psk2'
option key '1234567890'
option ssid 'map-net55'
option vlan '0' # 0 - 2 rsvd, 3 - 4094 => vlan id
config bk-credentials
option band '5'
option encryption 'psk2'
option key '5555555555'
option ssid 'map-bkhaul-5'
config bk-credentials
option band '2'
option encryption 'psk2'
option key '2222222222'
option ssid 'map-bkhaul-2'
config agent-policy
option agent_id '00:22:07:7E:9C:D6' # 1905al macaddress of agent
list steer_exclude '00:11:22:33:44:55'
list steer_exclude_btm '00:aa:bb:cc:dd:ee'
option steer_policy '2' # 0, 1, 2 - see MultiAP spec
option util_threshold '200' # channel-util as in BSS load
option rcpi_threshold '30' # 0 - 220 valid range
option report_scan '0' # 0 or 1 for independent sc include_sta_metric '0' # sta metric in AP metric resp
option pvid '100' # primary vlan id
option pcp_default '5' # default vlan pcp
option disallow_bsta_p1 '0' # 0 or 1 profile20 valid range
option report_scan '0' # 0 or 1 for independent scans
option report_sta_assocfails '1' # 0 or 1 - stas assoc failure
option report_metric_periodic '0' # 0, or 1 - 255 in secs
option report_rcpi_threshold '30' # 0 - 220 valid range
option report_scan '0' # 0 or 1 for independent scans
option report_sta_assocfails '1' # 0 or 1 - stas assoc failure
option report_metric_periodic '0' # 0, or 1 - 255 in secs
option report_rcpi_threshold '0' # 0, or 1 - 220
option report_util_threshold '0' # 0, or channel-util value
option include_sta_stats '0' # sta stats in AP metric resp
option include_sta_metric '0' # sta metric in AP metric resp
option pvid '100' # primary vlan id
option pcp_default '5' # default vlan pcp
option disallow_bsta_p1 '0' # 0 or 1 profile-1 bSTA
option disallow_bsta_p2 '0' # 0 or 1 profile-2 bSTA
config agent-policy
option agent_id '00:00:00:00:00:00'
list steer_exclude '00:11:22:33:44:55'
list steer_exclude_btm '00:aa:bb:cc:dd:ee'
option steer_policy '2' # 0, 1, 2 - see MultiAP spec
option util_threshold '200' # channel-util as in BSS load
option rcpi_threshold '30' # 0 - 220 valid range
option report_scan '0' # 0 or 1 for independent sc include_sta_metric '0' # sta metric in AP metric resp
option pvid '100' # primary vlan id
option pcp_default '5' # default vlan pcp
option disallow_bsta_p1 '0' # 0 or 1 profile20 valid range
option report_scan '0' # 0 or 1 for independent scans
option report_sta_assocfails '1' # 0 or 1 - stas assoc failure
option report_metric_periodic '0' # 0, or 1 - 255 in secs
option report_rcpi_threshold '30' # 0 - 220 valid range
option report_scan '0' # 0 or 1 for independent scans
option report_sta_assocfails '1' # 0 or 1 - stas assoc failure
option report_metric_periodic '0' # 0, or 1 - 255 in secs
option report_rcpi_threshold '0' # 0, or 1 - 220
option report_util_threshold '0' # 0, or channel-util value
option include_sta_stats '0' # sta stats in AP metric resp
option include_sta_metric '0' # sta metric in AP metric resp
option pvid '100' # primary vlan id
option pcp_default '5' # default vlan pcp
option disallow_bsta_p1 '0' # 0 or 1 profile-1 bSTA
option disallow_bsta_p2 '0' # 0 or 1 profile-2 bSTA
config agent-policy
option agent_id '00:22:07:6A:1C:3A' # 1905al macaddress of agent
list steer_exclude '00:11:22:33:44:55'
list steer_exclude_btm '00:aa:bb:cc:dd:ee'
option steer_policy '2' # 0, 1, 2 - see MultiAP spec
option util_threshold '200' # channel-util as in BSS load
option report_metric_periodic '0' # 0, or 1 - 255 in secs
option report_rcpi_threshold '0' # 0, or 1 - 220
option report_util_threshold '0' # 0, or channel-util value
option include_sta_stats '0' # sta stats in 3:4d:35:d2'
option bss '00:22:07:11:22:33'
config rule-custom
option action restrict
option sta 'd8:32:e3:4d:35:d2'
option bss '00:22:07:11:22:33'
" > /etc/config/controller
......@@ -20,6 +20,7 @@ CNTLR_OBJS = \
core/cntlr_ubus.o \
core/cntlr.o \
core/cntlr_map.o \
core/cntlr_tlv_generator.o \
core/cntlr_map_debug.o \
core/config.o \
core/main.o
......@@ -27,6 +28,7 @@ CNTLR_OBJS = \
LIBS = -lubus -lubox -ljson-c -lblobmsg_json -luci -pthread
LIBS += -rdynamic -ldl
LIBS += -lmaputils
LIBS += -lwsc
plugin_subdirs ?= $(wildcard plugins/*)
plugin_sofile = $(wildcard $(d)/*.so)
......
......@@ -22,12 +22,22 @@ config bk-credentials
option encryption 'psk2'
option key '5555555555'
option ssid 'map-bkhaul-5'
option multi_ap '2'
# option multi_ap_backhaul_sta '1' # possible future TODO
# option multi_ap_backhaul_key 'multiap_key123' # possible future TODO
# option multi_ap_backhaul_ssid 'MultiAP-0022077E9CD6' # possible future TODO
option disallow_bsta '1' # bitmap, 1 for disallow p1, 2 to disallow p2, 3 to disallow both (probably never applicable)
config bk-credentials
option band '2'
option encryption 'psk2'
option key '2222222222'
option ssid 'map-bkhaul-2'
option multi_ap '2'
# option multi_ap_backhaul_sta '1' # possible future TODO
# option multi_ap_backhaul_key 'multiap_key123' # possible future TODO
# option multi_ap_backhaul_ssid 'MultiAP-0022077E9CD6' # possible future TODO
option disallow_bsta '0' # 0 or 1 profile-1 bSTA
config agent-policy
option agent_id '02:20:40:55:66:77' # 1905al macaddress of agent
......@@ -48,7 +58,6 @@ config agent-policy
option disallow_bsta_p1 '0' # 0 or 1 profile-1 bSTA
option disallow_bsta_p2 '0' # 0 or 1 profile-2 bSTA
config agent-policy
option agent_id '02:20:40:aa:bb:cc' # 1905al macaddress of agent
list steer_exclude '00:11:22:33:44:55'
......@@ -68,7 +77,6 @@ config agent-policy
option disallow_bsta_p1 '0' # 0 or 1 profile-1 bSTA
option disallow_bsta_p2 '0' # 0 or 1 profile-2 bSTA
### do not parse following now ###
config steer-param 'rssi'
option rssi_threshold '-68'
......
......@@ -29,6 +29,9 @@
#include <easy/easy.h>
#include <wifi.h> // FIXME: should not be included
#include <map1905/map2.h>
#include <map1905/maputils.h>
#include "debug.h"
#include "utils.h"
#include "config.h"
......@@ -44,6 +47,36 @@ static int update_fronthaul_bsslist(struct node *n, struct netif_fhbss *fh);
static void node_getbssinfo(void *cntlr, void *resp, int len, void *cookie);
static int enumerate_topology_indirect(struct controller *c);
void stop_cntlr(struct controller *c)
{
if (!c) {
warn("%s: (cntlr = NULL)\n", __func__);
exit(0);
}
stop_test_logging();
ubus_unregister_event_handler(c->ubus_ctx, &c->ieee1905_evh);
ubus_unregister_event_handler(c->ubus_ctx, &c->ubusx_ev);
cntlr_remove_object(c);
uloop_done();
cntlr_config_clean(&c->cfg);
comm_destroy(c->comm);
ubus_free(c->ubus_ctx);
free(c);
}
static void cntlr_terminate(struct controller *c)
{
dbg("%s: called.\n", __func__);
stop_cntlr(c);
exit_alloctrace();
stop_logging();
//unlink(pidfile);
exit(0);
}
/* find node by macaddress */
static struct node *find_node_by_mac(struct controller *c,
const unsigned char *mac)
......@@ -1977,6 +2010,7 @@ int start_controller(void)
as_init_table(&c->as_table);
ubus_add_uloop(ctx);
cntlr_config_defaults(c, &c->cfg);
cntlr_config_reload(&c->cfg);
c->topology = ubus_get_topology_object(c->ubus_ctx);
......@@ -2008,13 +2042,11 @@ int start_controller(void)
cntlr_register_module(c);
uloop_run();
out_exit:
/* ubus_unregister_event_handler(ctx, ev); */
/* cntlr_remove_object(ctx); */
ubus_free(ctx);
uloop_done();
free(c);
cntlr_terminate(c);
return 0;
}
......@@ -49,6 +49,14 @@ struct netif_link {
struct list_head list;
};
/* TODO - fill this structure */
struct netif_radio {
char name[16];
unsigned char hwaddr[6];
bool isup;
struct list_head list;
};
enum nodetype {
NODE_WIFI_EXTENDER,
NODE_WIFI_REPEATER,
......@@ -121,6 +129,7 @@ struct controller {
object_t topology;
int num_nodes;
struct list_head nodelist;
struct list_head radiolist; /** TODOTODO -- list of radios */
struct list_head watchlist;
struct uloop_timeout radar_timer;
struct hlist_head *as_table; /** active sta hash table */
......
......@@ -30,6 +30,10 @@
#include <easy/easy.h>
#include <wifi.h> // TODO: remove wifi.h
#include <map1905/map2.h>
#include <map1905/maputils.h>
#include <ieee1905/1905_tlvs.h>
#include "map_module.h"
#include "utils.h"
#include "debug.h"
......@@ -39,12 +43,10 @@
#include "msgqueue.h"
#include "worker.h"
#include "cntlr.h"
#include <map1905/map2.h>
#include <map1905/maputils.h>
#include "cntlr_ubus.h"
#include "cntlr_map_debug.h"
#include "cntlr_tlv_generator.h"
#define for_each_tlv(e, _buf, _len) \
for ((e) = (struct tlv *)(_buf); \
......@@ -77,10 +79,58 @@ int handle_topology_response(void *cntlr, struct cmdu_cstruct *cmdu)
return 0;
}
int handle_ap_autoconfig_search(void *cntlr, struct cmdu_cstruct *cmdu)
/* TODO: error handling */
int handle_ap_autoconfig_search(void *cntlr, struct cmdu_cstruct *rec_cmdu)
{
trace("%s: --->\n", __func__);
return 0;
struct controller *c = (struct controller *) cntlr;
uint16_t tlv_index = 0;
struct cmdu_cstruct *cmdu;
struct tlv_map_profile *p;
struct tlv_supp_service *p1;
int ret;
cmdu = (struct cmdu_cstruct *)calloc(1,
sizeof(struct cmdu_cstruct));
if (!cmdu) {
fprintf(stderr, "Out of memory!\n");
return -1;
}
cmdu->message_type = CMDU_TYPE_AP_AUTOCONFIGURATION_RESPONSE;
memcpy(cmdu->origin, rec_cmdu->origin, 6);
cmdu->message_id = cmdu->message_id;
strncpy(cmdu->intf_name, rec_cmdu->intf_name,
sizeof(cmdu->intf_name) - 1);
p = cntlr_gen_map_profile(c, cmdu);
if (!p)
goto fail_cmdu;
cmdu->num_tlvs++;
p1 = cntlr_gen_supp_service(c, cmdu);
if (!p1)
goto fail_p;
cmdu->num_tlvs++;
cmdu->tlvs = (uint8_t **)calloc(cmdu->num_tlvs, sizeof(uint8_t *));
if (!cmdu->tlvs)
goto fail_p1;
cmdu->tlvs[tlv_index++] = (uint8_t *)p;
cmdu->tlvs[tlv_index++] = (uint8_t *)p1;
ret = send_cmdu(c, cmdu);
map_free_cmdu(cmdu);
return ret;
fail_p1:
map_free_tlv_cstruct((uint8_t *) p1);
fail_p:
map_free_tlv_cstruct((uint8_t *) p);
fail_cmdu:
free(cmdu);
return -1;
}
int handle_ap_autoconfig_response(void *cntlr, struct cmdu_cstruct *cmdu)
......@@ -89,10 +139,108 @@ int handle_ap_autoconfig_response(void *cntlr, struct cmdu_cstruct *cmdu)
return 0;
}
int handle_ap_autoconfig_wsc(void *cntlr, struct cmdu_cstruct *cmdu)
int handle_ap_autoconfig_wsc(void *cntlr, struct cmdu_cstruct *rec_cmdu)
{
trace("%s: --->\n", __func__);
return 0;
struct controller *c = (struct controller *) cntlr;
struct tlv_default_8021q_settings *p;
struct tlv_traffic_sep_policy *p1;
struct tlv_ap_radio_identifier *p2;
struct tlv_wsc *p3;
struct cmdu_cstruct *cmdu;
int tlv_index = 0, ret, i;
uint8_t **tlvs;
cmdu = (struct cmdu_cstruct *)calloc(1, sizeof(struct cmdu_cstruct));
if (!cmdu) {
fprintf(stderr, "failed to malloc cmdu\n");
return UBUS_STATUS_UNKNOWN_ERROR;
}
memcpy(cmdu->origin, rec_cmdu->origin, 6);
cmdu->message_type = CMDU_TYPE_AP_AUTOCONFIGURATION_WSC;
cmdu->message_id = rec_cmdu->message_id;
strncpy(cmdu->intf_name, rec_cmdu->intf_name,
sizeof(cmdu->intf_name) - 1);
p = cntlr_gen_8021q_settings(c, cmdu, rec_cmdu);
if (!p)
goto fail_cmdu;
cmdu->num_tlvs++;
p1 = cntlr_gen_traffic_sep_policy(c, cmdu);
if (!p1)
goto fail_p;
cmdu->num_tlvs++;
p2 = cntlr_gen_radio_identifier(c, cmdu, rec_cmdu);
if (!p2)
goto fail_p1;
cmdu->num_tlvs++;
cmdu->tlvs = (uint8_t **)calloc(cmdu->num_tlvs, sizeof(uint8_t *));
if (!cmdu->tlvs)
goto fail_p2;
cmdu->tlvs[tlv_index++] = (uint8_t *)p;
cmdu->tlvs[tlv_index++] = (uint8_t *)p1;
cmdu->tlvs[tlv_index++] = (uint8_t *)p2;
/* Generate all fBSS wsc tlvs for this BSS */
for (i = 0; i < c->cfg.num_fh; i++) {
/* Will return null if band did not match OR on failure*/
p3 = cntlr_gen_wsc(c, cmdu, rec_cmdu, &c->cfg.fh[i]);
if (!p3)
continue;
cmdu->num_tlvs++;
tlvs = (uint8_t **)realloc(cmdu->tlvs, cmdu->num_tlvs * sizeof(uint8_t *));
if (!tlvs) {
cmdu->num_tlvs--;
map_free_tlv_cstruct((uint8_t *) p3);
continue;
}
cmdu->tlvs = tlvs;
cmdu->tlvs[tlv_index++] = (uint8_t *)p3;
}
/* Generate all bBSS wsc tlvs for this BSS */
for (i = 0; i < c->cfg.num_bk; i++) {
/* Will return null if band did not match OR on failure*/
p3 = cntlr_gen_wsc(c, cmdu, rec_cmdu, &c->cfg.bk[i]);
if (!p3)
continue;
cmdu->num_tlvs++;
tlvs = (uint8_t **)realloc(cmdu->tlvs, cmdu->num_tlvs * sizeof(uint8_t *));
if (!tlvs) {
cmdu->num_tlvs--;
map_free_tlv_cstruct((uint8_t *) p3);
continue;
}
cmdu->tlvs = tlvs;
cmdu->tlvs[tlv_index++] = (uint8_t *)p3;
}
if (cmdu->num_tlvs < 4)
goto fail_tlvs;
ret = send_cmdu(c, cmdu);
map_free_cmdu(cmdu);
return ret;
fail_tlvs:
free(cmdu->tlvs);
fail_p2:
map_free_tlv_cstruct((uint8_t *) p2);
fail_p1:
map_free_tlv_cstruct((uint8_t *) p1);
fail_p:
map_free_tlv_cstruct((uint8_t *) p);
fail_cmdu:
free(cmdu);
return -1;
}
......@@ -347,7 +495,7 @@ bool is_cmdu_for_us(void *module, uint16_t type)
}
int cntlr_handle_map_event(void *module, uint16_t cmdutype, uint16_t mid,
char *rxif, uint8_t *src, uint8_t *tlvs, int len)
char *rxif, uint8_t *src, uint8_t *tlvs, int len)
{
struct controller *c = (struct controller *)module;
const struct map_cmdu_calltable_t *f;
......@@ -379,7 +527,6 @@ int cntlr_handle_map_event(void *module, uint16_t cmdutype, uint16_t mid,
if (verbose >= 4 && f[idx].debug)
f[idx].debug(c, cmdu);
map_free_cmdu(cmdu);
//TODO: check ret
......
......@@ -356,15 +356,22 @@ int debug_sta_caps_report(void *cntlr, struct cmdu_cstruct *cmdu)
char *frame;
int offset = 1 + 2 + 1;
trace("\tresult_code: 0x%02x\n", p->result_code);
/* if tlv is shorter or equal to the offset len,
* then no frame is passed
*/
if (p->tlv_len <= offset)
break;
frame = calloc(1,
(2 * (p->tlv_len - offset)) + 1);
if (!frame)
continue;
break;
btostr(p->frame_body + offset,
p->tlv_len - offset, frame);
trace("\tresult_code: 0x%02x\n", p->result_code);
trace("\tframe: 0x%s\n", frame);
break;
}
......
/*
* cntlr_tlv_generator.c - tlv building function
*
* Copyright (C) 2020 IOPSYS Software Solutions AB. All rights reserved.
*
* Author: jakob.olsson@iopsys.eu
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if_arp.h>
#include <pthread.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 <easy/easy.h>
#include <wifi.h> // TODO: remove wifi.h
#include <map1905/map2.h>
#include <map1905/maputils.h>
#include <wsc.h>
#include "map_module.h"
#include "utils.h"
#include "debug.h"
#include "config.h"
#include "cntlr.h"
#include "cntlr_ubus.h"
#include "cntlr_map_debug.h"
#include "cntlr_tlv_generator.h"
uint8_t *extract_tlv_by_type(struct cmdu_cstruct *cmdu, uint8_t tlv_type)
{
uint8_t *tlv;
int i;
for (i = 0; i < cmdu->num_tlvs; i++) {
tlv = cmdu->tlvs[i];
if (*tlv == tlv_type)
return tlv;
}
return NULL;
}
struct tlv_default_8021q_settings *cntlr_gen_8021q_settings(struct controller *c,
struct cmdu_cstruct *cmdu, struct cmdu_cstruct *rec_cmdu)
{
struct tlv_default_8021q_settings *p;
struct agent_policy *a, *found = NULL;
list_for_each_entry(a, &c->cfg.policylist, list) {
if (!memcmp(rec_cmdu->origin, a->agent_id, 6)) {
found = a;
break;
}
}
if (!found)
return NULL;
p = (struct tlv_default_8021q_settings *) calloc(1, sizeof(*p));
if (!p)
return NULL;
p->tlv_type = MAP_TLV_DEFAULT_8021Q_SETTINGS;
p->primary_vid = a->pvid;
p->pcp = a->pcp_default;
return p;
}
struct tlv_traffic_sep_policy *cntlr_gen_traffic_sep_policy(struct controller *c,
struct cmdu_cstruct *cmdu)
{
struct tlv_traffic_sep_policy *p;
int i;
p = (struct tlv_traffic_sep_policy *) calloc(1, sizeof(*p));
if (!p)
return NULL;
p->tlv_type = MAP_TLV_TRAFFIC_SEPARATION_POLICY;
p->nbr_ssid = c->cfg.num_fh;
p->data = calloc(p->nbr_ssid, sizeof(*(p->data)));
if (!p->data) {
map_free_tlv_cstruct((uint8_t *) p);
return NULL;
}
for (i = 0; i < p->nbr_ssid; i++) {
int len;
len = strlen((char *)c->cfg.fh[i].ssid);
p->data[i].ssid_len = len;
p->data[i].vid = c->cfg.fh[i].vlanid;
p->data[i].ssid = calloc(1, len + 1);
if (!p->data[i].ssid)
continue;
strncpy(p->data[i].ssid, (char *)c->cfg.fh[i].ssid, len);
}
return p;
}
struct tlv_wsc *cntlr_gen_wsc(struct controller *c,
struct cmdu_cstruct *cmdu, struct cmdu_cstruct *rec_cmdu,
struct iface_credential *creds)
{
struct tlv_ap_radio_basic_cap *ap_caps = NULL;
struct tlv_wsc *m2, *m1;
enum wifi_band band = BAND_UNKNOWN;
struct mdata cfg = {0};