2014-07-11 22:12:11 +02:00
|
|
|
/*
|
|
|
|
This file is part of actube.
|
|
|
|
|
|
|
|
libcapwap is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
libcapwap is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/utsname.h>
|
|
|
|
|
|
|
|
#include <confuse.h>
|
|
|
|
|
2016-03-03 20:46:20 +01:00
|
|
|
#include "cw/capwap.h"
|
|
|
|
#include "cw/sock.h"
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2016-03-03 20:46:20 +01:00
|
|
|
#include "cw/log.h"
|
|
|
|
#include "cw/dbg.h"
|
|
|
|
#include "cw/cw_util.h"
|
2018-04-04 10:59:07 +02:00
|
|
|
#include "cw/dtls.h"
|
2018-03-17 18:01:17 +01:00
|
|
|
|
2020-03-09 13:08:58 +01:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <net/if.h>
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2018-02-18 21:48:42 +01:00
|
|
|
#include "conf.h"
|
2016-02-17 16:17:06 +01:00
|
|
|
#include "ac.h"
|
|
|
|
|
2022-07-28 01:36:16 +02:00
|
|
|
#include "cw/mavltypes.h"
|
|
|
|
|
2014-07-14 22:43:17 +02:00
|
|
|
uint8_t conf_macaddress[12];
|
2016-02-17 16:17:06 +01:00
|
|
|
uint8_t conf_macaddress_len = 0;
|
2014-07-14 22:43:17 +02:00
|
|
|
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
long conf_strict_capwap = 1;
|
|
|
|
long conf_strict_headers = 0;
|
2018-03-17 18:01:17 +01:00
|
|
|
/*int conf_capwap_mode = CW_MODE_CAPWAP;*/
|
2015-04-26 14:46:28 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
const char *conf_acname = NULL;
|
2014-07-11 22:12:11 +02:00
|
|
|
int conf_acname_len = 0;
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
char *conf_acid = NULL;
|
2014-07-14 22:43:17 +02:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
char *conf_primary_if = NULL;
|
2014-07-14 22:43:17 +02:00
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
long conf_max_wtps = CONF_DEFAULT_MAXWTPS;
|
2016-02-17 16:17:06 +01:00
|
|
|
char *conf_logfilename = CONF_DEFAULT_LOGFILENAME;
|
|
|
|
struct sockaddr_storage *conf_salist = NULL;
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
char **conf_listen_addrs;
|
|
|
|
int conf_listen_addrs_len = 0;
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
char **conf_mcast_groups = 0;
|
|
|
|
int conf_mcast_groups_len = 0;
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
char **conf_bcast_addrs = 0;
|
2014-07-11 22:12:11 +02:00
|
|
|
int conf_bcast_addrs_len;
|
|
|
|
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
struct sockaddr_storage *conf_bsalist = NULL;
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
int conf_salist_len = 0;
|
|
|
|
int conf_bsalist_len = 0;
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
struct sockaddr *conf_ac_ips;
|
2014-07-11 22:12:11 +02:00
|
|
|
int conf_ac_ips_len;
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
char *conf_sslcertfilename = NULL;
|
|
|
|
char *conf_sslkeyfilename = NULL;
|
|
|
|
char *conf_sslkeypass = NULL;
|
|
|
|
char *conf_sslcipher = NULL;
|
|
|
|
char *conf_dtls_psk = NULL;
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
int conf_security = 0;
|
|
|
|
long conf_vendor_id = CONF_DEFAULT_VENDOR_ID;
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2014-08-23 22:15:50 +02:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
bstr_t conf_hardware_version = NULL;
|
|
|
|
bstr_t conf_software_version = NULL;
|
2015-03-15 20:53:21 +01:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
bstr_t conf_cisco_hardware_version = NULL;
|
|
|
|
bstr_t conf_cisco_software_version = NULL;
|
2015-03-15 20:53:21 +01:00
|
|
|
|
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
int conf_use_loopback = 0;
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
long conf_debug_level = -1;
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
char *conf_db_file = 0;
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
int conf_ipv4 = 1;
|
2014-07-11 22:12:11 +02:00
|
|
|
#ifdef WITH_IPV6
|
2016-02-17 16:17:06 +01:00
|
|
|
int conf_ipv6 = 1;
|
2014-07-11 22:12:11 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2014-07-25 08:43:45 +02:00
|
|
|
#ifdef WITH_LWAPP
|
2016-02-17 16:17:06 +01:00
|
|
|
int conf_lwapp = 1;
|
|
|
|
char *conf_lw_control_port = 0;
|
|
|
|
#endif
|
2014-07-25 08:24:38 +02:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
char *conf_image_dir = 0;
|
2015-03-17 01:10:08 +01:00
|
|
|
|
2014-07-25 08:24:38 +02:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
char *conf_control_port = 0;
|
2014-07-25 08:24:38 +02:00
|
|
|
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
int conf_dtls_verify_peer = 1;
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
static int init_acname()
|
|
|
|
{
|
2016-02-17 16:17:06 +01:00
|
|
|
if (conf_acname == NULL) {
|
|
|
|
char *s = malloc(strlen(CONF_DEFAULT_ACNAME) + strlen(conf_acid) + 1);
|
|
|
|
sprintf(s, "%s%s", CONF_DEFAULT_ACNAME, conf_acid);
|
|
|
|
conf_acname = s;
|
2014-07-11 22:12:11 +02:00
|
|
|
}
|
2016-02-17 16:17:06 +01:00
|
|
|
conf_acname_len = strlen(conf_acname);
|
2014-07-11 22:12:11 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-02-26 23:33:30 +01:00
|
|
|
#include "../mod/modload.h"
|
2016-02-22 18:33:47 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-07-14 22:43:17 +02:00
|
|
|
static int init_acid()
|
|
|
|
{
|
2018-03-11 00:56:41 +01:00
|
|
|
int i;
|
|
|
|
char *s;
|
|
|
|
|
2014-07-14 22:43:17 +02:00
|
|
|
if (conf_acid != NULL)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_IPV6
|
2016-02-17 16:17:06 +01:00
|
|
|
conf_primary_if = sock_get_primary_if(AF_INET6);
|
2014-07-14 22:43:17 +02:00
|
|
|
if (!conf_primary_if)
|
|
|
|
conf_primary_if = sock_get_primary_if(AF_INET);
|
2016-02-17 16:17:06 +01:00
|
|
|
#else
|
2014-07-14 22:43:17 +02:00
|
|
|
conf_primary_if = get_primary_if(AF_INET);
|
|
|
|
#endif
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
if (!conf_primary_if) {
|
|
|
|
cw_log(LOG_ERR,
|
|
|
|
"Fatal: Unable to detect primary interface, needed to set ac_id. Pleas use confiPleas u to set ac_id");
|
2014-07-14 22:43:17 +02:00
|
|
|
return 0;
|
2016-02-17 16:17:06 +01:00
|
|
|
}
|
2014-07-14 22:43:17 +02:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
if (!sock_getifhwaddr(conf_primary_if, conf_macaddress, &conf_macaddress_len)) {
|
|
|
|
cw_log(LOG_ERR, "Fatal: Unable to detect link layer address for %s\n",
|
|
|
|
conf_primary_if);
|
2014-07-14 22:43:17 +02:00
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2014-07-14 22:43:17 +02:00
|
|
|
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
conf_acid = malloc(2 * conf_macaddress_len + 1);
|
2018-03-11 00:56:41 +01:00
|
|
|
s = conf_acid;
|
2014-07-14 22:43:17 +02:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
for (i = 0; i < conf_macaddress_len; i++) {
|
|
|
|
s += sprintf(s, "%02X", conf_macaddress[i]);
|
2014-07-14 22:43:17 +02:00
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
static int init_dtls()
|
|
|
|
{
|
2016-02-17 16:17:06 +01:00
|
|
|
if (conf_dtls_psk != NULL) {
|
2018-03-11 00:56:41 +01:00
|
|
|
/*
|
|
|
|
// conf_security=CW_SECURITY_FLAGS_S;
|
|
|
|
*/
|
2014-07-11 22:12:11 +02:00
|
|
|
}
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
return 1;
|
|
|
|
}
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
|
|
|
|
static int init_vendor_id()
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int init_control_port()
|
|
|
|
{
|
|
|
|
char str[30];
|
2016-02-17 16:17:06 +01:00
|
|
|
sprintf(str, "%d", CONF_DEFAULT_CONTROL_PORT);
|
|
|
|
conf_control_port =
|
|
|
|
(char *) cw_setstr((uint8_t **) & conf_control_port, (uint8_t *) str,
|
|
|
|
strlen(str));
|
2014-07-25 08:43:45 +02:00
|
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_LWAPP
|
2016-02-17 16:17:06 +01:00
|
|
|
sprintf(str, "%d", CONF_DEFAULT_LW_CONTROL_PORT);
|
2014-07-25 08:43:45 +02:00
|
|
|
conf_lw_control_port = strdup(str);
|
2016-02-17 16:17:06 +01:00
|
|
|
#endif
|
2014-07-25 08:43:45 +02:00
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include <ifaddrs.h>
|
|
|
|
|
|
|
|
static int init_listen_addrs()
|
|
|
|
{
|
2018-03-11 00:56:41 +01:00
|
|
|
struct ifaddrs *ifap, *ifa;
|
|
|
|
int rc;
|
|
|
|
int ctr;
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
if (conf_listen_addrs != 0)
|
2014-07-11 22:12:11 +02:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
rc = getifaddrs(&ifap);
|
2016-02-17 16:17:06 +01:00
|
|
|
if (rc == -1)
|
2014-07-11 22:12:11 +02:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* count the addresses */
|
2018-03-11 00:56:41 +01:00
|
|
|
ctr = 0;
|
2016-02-17 16:17:06 +01:00
|
|
|
for (ifa = ifap; ifa != 0; ifa = ifa->ifa_next) {
|
2016-03-25 19:31:43 +01:00
|
|
|
if (!ifa->ifa_addr)
|
|
|
|
continue;
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
if (ifa->ifa_addr->sa_family == AF_INET && conf_ipv4)
|
2014-07-11 22:12:11 +02:00
|
|
|
ctr++;
|
2016-02-17 16:17:06 +01:00
|
|
|
if (ifa->ifa_addr->sa_family == AF_INET6 && conf_ipv6)
|
2014-07-11 22:12:11 +02:00
|
|
|
ctr++;
|
|
|
|
}
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
conf_listen_addrs = malloc(sizeof(char *) * ctr);
|
|
|
|
if (!conf_listen_addrs) {
|
|
|
|
rc = 0;
|
2014-07-11 22:12:11 +02:00
|
|
|
goto errX;
|
|
|
|
}
|
2016-02-17 16:17:06 +01:00
|
|
|
memset(conf_listen_addrs, 0, sizeof(char *) * ctr);
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
ctr = 0;
|
2014-07-11 22:12:11 +02:00
|
|
|
/* get the addresses */
|
2016-02-17 16:17:06 +01:00
|
|
|
for (ifa = ifap; ifa != 0; ifa = ifa->ifa_next) {
|
2014-07-11 22:12:11 +02:00
|
|
|
char str[100];
|
|
|
|
|
2016-02-16 08:13:34 +01:00
|
|
|
/** ignore loopback interfaces if configured*/
|
2016-02-17 16:17:06 +01:00
|
|
|
if (!conf_use_loopback) {
|
|
|
|
if ((ifa->ifa_flags & IFF_LOOPBACK)) {
|
2014-07-11 22:12:11 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2016-03-25 19:31:43 +01:00
|
|
|
if (!ifa->ifa_addr)
|
|
|
|
continue;
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
if (ifa->ifa_addr->sa_family == AF_INET && conf_ipv4) {
|
2016-03-06 12:44:48 +01:00
|
|
|
sock_addrtostr(ifa->ifa_addr, str, 100,0);
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
conf_listen_addrs[ctr] =
|
|
|
|
(char *) cw_setstr((uint8_t **) & conf_listen_addrs[ctr],
|
|
|
|
(uint8_t *) str, strlen(str));
|
2014-07-11 22:12:11 +02:00
|
|
|
if (conf_listen_addrs[ctr])
|
|
|
|
ctr++;
|
|
|
|
|
|
|
|
}
|
2016-02-17 16:17:06 +01:00
|
|
|
if (ifa->ifa_addr->sa_family == AF_INET6 && conf_ipv6) {
|
2016-03-06 12:44:48 +01:00
|
|
|
sock_addrtostr(ifa->ifa_addr, str, 100,0);
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
if (strncmp(str, "fe80:", 5) == 0) {
|
|
|
|
strcat(str, "%");
|
|
|
|
strcat(str, ifa->ifa_name);
|
2014-07-11 22:12:11 +02:00
|
|
|
}
|
2016-02-17 16:17:06 +01:00
|
|
|
conf_listen_addrs[ctr] =
|
|
|
|
(char *) cw_setstr((uint8_t **) & conf_listen_addrs[ctr],
|
|
|
|
(uint8_t *) str, strlen(str));
|
2014-07-11 22:12:11 +02:00
|
|
|
if (conf_listen_addrs[ctr])
|
|
|
|
ctr++;
|
|
|
|
}
|
|
|
|
}
|
2016-02-17 16:17:06 +01:00
|
|
|
conf_listen_addrs_len = ctr;
|
|
|
|
rc = 1;
|
|
|
|
errX:
|
2014-07-11 22:12:11 +02:00
|
|
|
freeifaddrs(ifap);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
static char *conf_default_mcast_groups_ipv4[] = {
|
2014-07-11 22:12:11 +02:00
|
|
|
"224.0.1.140",
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_IPV6
|
2016-02-17 16:17:06 +01:00
|
|
|
static char *conf_default_mcast_groups_ipv6[] = {
|
2018-03-11 00:56:41 +01:00
|
|
|
"ff01:0:0:0:0:0:0:18c",
|
2014-07-11 22:12:11 +02:00
|
|
|
/* "ff01:0:0:0:0:0:0:18c",
|
|
|
|
"ff02:0:0:0:0:0:0:18c%em0",
|
|
|
|
"ff03:0:0:0:0:0:0:18c",
|
|
|
|
"ff04:0:0:0:0:0:0:18c",
|
|
|
|
"ff05:0:0:0:0:0:0:18c",
|
|
|
|
"ff06:0:0:0:0:0:0:18c"
|
2016-02-17 16:17:06 +01:00
|
|
|
*/
|
2014-07-11 22:12:11 +02:00
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2018-03-11 00:56:41 +01:00
|
|
|
/*
|
2016-02-17 16:17:06 +01:00
|
|
|
static int add_bcast_addr(void *priv, void *addr)
|
2014-07-11 22:12:11 +02:00
|
|
|
{
|
2018-03-04 16:59:20 +01:00
|
|
|
printf("Callback Called\n");
|
|
|
|
union mavldata *ud;
|
|
|
|
ud = addr;
|
|
|
|
printf("Callback Called %s\n", ud->str);
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
char *s = (char *) addr;
|
|
|
|
conf_bcast_addrs[conf_bcast_addrs_len] = strdup(s);
|
|
|
|
if (conf_bcast_addrs[conf_bcast_addrs_len] != 0)
|
2014-07-11 22:12:11 +02:00
|
|
|
conf_bcast_addrs_len++;
|
|
|
|
return 1;
|
|
|
|
}
|
2018-03-11 00:56:41 +01:00
|
|
|
*/
|
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize broadcast addresses (ipv4 only)
|
|
|
|
*/
|
|
|
|
int init_bcast_addrs()
|
|
|
|
{
|
2018-03-11 00:56:41 +01:00
|
|
|
int rc;
|
|
|
|
char str[100];
|
|
|
|
struct ifaddrs *ifa0, *ifa;
|
2018-03-04 16:59:20 +01:00
|
|
|
mavl_t t;
|
|
|
|
mavliter_t it;
|
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
if (conf_bcast_addrs)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (!conf_ipv4)
|
|
|
|
return 1;
|
|
|
|
|
2022-07-28 01:36:16 +02:00
|
|
|
/*t = mavl_create_ptr(); */
|
|
|
|
t = mavl_create_ptr(mavl_cmpstr,mavl_freeptr);
|
2018-03-11 00:56:41 +01:00
|
|
|
if (t==NULL)
|
2014-07-11 22:12:11 +02:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* add the default broadast address */
|
2018-03-11 00:56:41 +01:00
|
|
|
mavl_add_str(t, cw_strdup("255.255.255.255"));
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
|
|
|
|
/* add all other local broadcast addresses */
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
rc = getifaddrs(&ifa0);
|
2016-02-17 16:17:06 +01:00
|
|
|
if (rc == -1)
|
2014-07-11 22:12:11 +02:00
|
|
|
return 0;
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
for (ifa = ifa0; ifa != 0; ifa = ifa->ifa_next) {
|
|
|
|
struct sockaddr *sa;
|
2014-07-11 22:12:11 +02:00
|
|
|
if (!(ifa->ifa_flags & IFF_BROADCAST))
|
|
|
|
continue;
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
|
|
|
|
if (!conf_use_loopback) {
|
2014-07-11 22:12:11 +02:00
|
|
|
if ((ifa->ifa_flags & IFF_LOOPBACK))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sa = ifa->ifa_addr;
|
2016-03-25 19:31:43 +01:00
|
|
|
if (!sa)
|
|
|
|
continue;
|
2016-02-17 16:17:06 +01:00
|
|
|
if (sa->sa_family != AF_INET)
|
2014-07-11 22:12:11 +02:00
|
|
|
continue;
|
|
|
|
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
if (ifa->ifa_broadaddr) {
|
2016-03-06 11:23:34 +01:00
|
|
|
sock_addrtostr(ifa->ifa_broadaddr, str, 100,1);
|
2016-02-17 16:17:06 +01:00
|
|
|
*strchr(str, ':') = 0;
|
2018-03-11 00:56:41 +01:00
|
|
|
mavl_add_str(t, cw_strdup(str));
|
2014-07-11 22:12:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
conf_bcast_addrs = malloc(t->count * sizeof(char *));
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2018-03-04 16:59:20 +01:00
|
|
|
mavliter_init(&it,t);
|
|
|
|
mavliter_foreach(&it){
|
2018-03-11 00:56:41 +01:00
|
|
|
char * d;
|
|
|
|
d = mavliter_get_str(&it);
|
|
|
|
conf_bcast_addrs[conf_bcast_addrs_len] = cw_strdup(d);
|
2018-03-04 16:59:20 +01:00
|
|
|
if (conf_bcast_addrs[conf_bcast_addrs_len] != 0)
|
|
|
|
conf_bcast_addrs_len++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
mavl_destroy(t);
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
freeifaddrs(ifa0);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int init_mcast_groups()
|
|
|
|
{
|
2018-03-11 00:56:41 +01:00
|
|
|
int ctr;
|
|
|
|
int i;
|
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
int n = 0;
|
2016-02-17 16:17:06 +01:00
|
|
|
int n4 = 0, n6 = 0;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
if (conf_mcast_groups)
|
|
|
|
return 1;
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
if (conf_ipv4) {
|
|
|
|
n4 = sizeof(conf_default_mcast_groups_ipv4) / sizeof(char *);
|
2014-07-11 22:12:11 +02:00
|
|
|
}
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
if (conf_ipv6) {
|
|
|
|
n6 = sizeof(conf_default_mcast_groups_ipv6) / sizeof(char *);
|
2014-07-11 22:12:11 +02:00
|
|
|
}
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
n = n4 + n6;
|
|
|
|
if (n == 0)
|
2014-07-11 22:12:11 +02:00
|
|
|
return 1;
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
conf_mcast_groups = malloc(sizeof(char *) * n);
|
2014-07-11 22:12:11 +02:00
|
|
|
if (!conf_mcast_groups)
|
|
|
|
return 0;
|
2016-02-17 16:17:06 +01:00
|
|
|
memset(conf_mcast_groups, 0, n * sizeof(char *));
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2018-03-11 00:56:41 +01:00
|
|
|
ctr = 0;
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
for (i = 0; i < n4; i++) {
|
|
|
|
uint8_t *g = (uint8_t *) conf_default_mcast_groups_ipv4[i];
|
|
|
|
conf_mcast_groups[ctr] =
|
|
|
|
(char *) cw_setstr((uint8_t **) & conf_mcast_groups[ctr], g,
|
|
|
|
strlen((char *) g));
|
2014-07-11 22:12:11 +02:00
|
|
|
if (conf_mcast_groups[ctr])
|
|
|
|
ctr++;
|
|
|
|
}
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
for (i = 0; i < n6; i++) {
|
|
|
|
uint8_t *g = (uint8_t *) conf_default_mcast_groups_ipv6[i];
|
|
|
|
conf_mcast_groups[ctr] =
|
|
|
|
(char *) cw_setstr((uint8_t **) & conf_mcast_groups[ctr], g,
|
|
|
|
strlen((char *) g));
|
2014-07-11 22:12:11 +02:00
|
|
|
if (conf_mcast_groups[ctr])
|
|
|
|
ctr++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
conf_mcast_groups_len = n;
|
2014-07-11 22:12:11 +02:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
static int conf_read_strings(cfg_t * cfg, char *name, char ***dst, int *len)
|
2014-07-11 22:12:11 +02:00
|
|
|
{
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
int n, i;
|
2014-07-11 22:12:11 +02:00
|
|
|
n = cfg_size(cfg, name);
|
2016-02-17 16:17:06 +01:00
|
|
|
*len = n;
|
|
|
|
if (n == 0)
|
2014-07-11 22:12:11 +02:00
|
|
|
return 1;
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
*dst = malloc(sizeof(char *) * n);
|
2014-07-11 22:12:11 +02:00
|
|
|
if (!*dst)
|
|
|
|
return 0;
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
char *str = cfg_getnstr(cfg, name, i);
|
|
|
|
if (!((*dst)[i] = malloc(strlen(str) + 1))) {
|
|
|
|
*len = 0;
|
2014-07-11 22:12:11 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
strcpy((*dst)[i], str);
|
2014-07-11 22:12:11 +02:00
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-23 22:15:50 +02:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
static int conf_read_dbg_level(cfg_t * cfg)
|
2014-08-23 22:15:50 +02:00
|
|
|
{
|
2016-02-17 16:17:06 +01:00
|
|
|
const char *name = "dbg";
|
|
|
|
int n, i;
|
2014-08-23 22:15:50 +02:00
|
|
|
n = cfg_size(cfg, name);
|
|
|
|
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
char *str = cfg_getnstr(cfg, name, i);
|
2018-03-11 00:56:41 +01:00
|
|
|
int b = cw_strlist_get_id(cw_dbg_strings, str);
|
|
|
|
|
2015-04-12 10:19:02 +02:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
cw_dbg_set_level(b, 1);
|
2014-08-23 22:15:50 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-03-11 00:56:41 +01:00
|
|
|
struct cw_Mod ** conf_mods;
|
2018-03-26 20:18:46 +02:00
|
|
|
char *conf_mods_dir = NULL;
|
2018-02-18 21:48:42 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Read the module names from config file
|
|
|
|
*/
|
|
|
|
static int conf_read_mods(cfg_t *cfg){
|
2022-07-30 23:27:42 +02:00
|
|
|
|
2018-02-18 21:48:42 +01:00
|
|
|
int n, i;
|
|
|
|
n = cfg_size(cfg,CFG_ENTRY_MODS);
|
|
|
|
|
2018-02-25 19:12:28 +01:00
|
|
|
conf_mods = malloc(sizeof(struct cw_Mod *)*(n+1));
|
2018-02-26 09:04:53 +01:00
|
|
|
|
|
|
|
cw_dbg(DBG_INFO,"Mods directory: %s",conf_mods_dir);
|
2018-03-12 11:22:06 +01:00
|
|
|
cw_mod_set_path(conf_mods_dir);
|
2018-02-26 09:04:53 +01:00
|
|
|
|
2018-02-18 21:48:42 +01:00
|
|
|
for (i=0; i < n; i++){
|
|
|
|
char *modname = cfg_getnstr(cfg, CFG_ENTRY_MODS, i);
|
2018-03-17 12:32:40 +01:00
|
|
|
struct cw_Mod * mod = cw_mod_load(modname, actube_global_cfg, CW_ROLE_AC);
|
|
|
|
|
2018-02-26 09:04:53 +01:00
|
|
|
if (!mod)
|
|
|
|
return 0;
|
2018-02-26 14:44:27 +01:00
|
|
|
cw_mod_add_to_list(mod);
|
2018-02-18 21:48:42 +01:00
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
|
|
|
|
int conf_parse_listen_addr(const char *addrstr, char *saddr, char *port, int *proto)
|
|
|
|
{
|
2018-03-11 00:56:41 +01:00
|
|
|
char *b;
|
|
|
|
int c;
|
|
|
|
int i, l;
|
|
|
|
char *ctrlport;
|
2016-02-17 16:17:06 +01:00
|
|
|
char *p = strchr(addrstr, '/');
|
|
|
|
if (!p)
|
|
|
|
*proto = AC_PROTO_CAPWAP;
|
|
|
|
else {
|
|
|
|
if (strcmp("capwap", p + 1) == 0)
|
|
|
|
*proto = AC_PROTO_CAPWAP;
|
|
|
|
else if (strcmp("lwapp", p + 1) == 0)
|
|
|
|
*proto = AC_PROTO_LWAPP;
|
|
|
|
else
|
|
|
|
*proto = AC_PROTO_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
switch (*proto) {
|
|
|
|
case AC_PROTO_CAPWAP:
|
2018-02-23 09:17:26 +01:00
|
|
|
ctrlport = CAPWAP_CONTROL_PORT_STR;
|
2016-02-17 16:17:06 +01:00
|
|
|
break;
|
|
|
|
case AC_PROTO_LWAPP:
|
|
|
|
ctrlport = LWAPP_CONTROL_PORT_STR;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ctrlport = "0";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
c = 0;
|
2016-02-17 16:17:06 +01:00
|
|
|
|
|
|
|
if (p)
|
|
|
|
l = p - addrstr;
|
|
|
|
else
|
|
|
|
l = strlen(addrstr);
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
if (addrstr[i] == ':')
|
|
|
|
c++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* no colon found, asume its ipv4 w/o port */
|
|
|
|
if (c == 0) {
|
|
|
|
strncpy(saddr, addrstr, l);
|
|
|
|
saddr[l] = 0;
|
|
|
|
strcpy(port, ctrlport);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* one colon found, so we assume, its an ipv4
|
|
|
|
* address with port */
|
|
|
|
if (c == 1) {
|
|
|
|
char *c = strchr(addrstr, ':');
|
|
|
|
strncpy(saddr, addrstr, c - addrstr);
|
|
|
|
saddr[c - addrstr] = 0;
|
|
|
|
strncpy(port, c + 1, l - (c - addrstr));
|
|
|
|
port[l - (c - addrstr) - 1] = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* we assume now, its ipv6 */
|
2018-03-11 00:56:41 +01:00
|
|
|
b = strstr(addrstr, "]:");
|
2016-02-17 16:17:06 +01:00
|
|
|
if (!b) {
|
|
|
|
/* ippv6 w/o port */
|
|
|
|
strncpy(saddr, addrstr, l);
|
|
|
|
saddr[l] = 0;
|
|
|
|
strcpy(port, ctrlport);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
strncpy(saddr, addrstr + 1, b - addrstr);
|
|
|
|
saddr[b - addrstr - 1] = 0;
|
|
|
|
strncpy(port, b + 2, l - (b - addrstr) - 2);
|
|
|
|
port[l - (b - addrstr) - 2] = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-02-18 21:48:42 +01:00
|
|
|
static void errfunc(cfg_t *cfg, const char *fmt, va_list ap){
|
2016-02-17 16:17:06 +01:00
|
|
|
|
2018-02-18 21:48:42 +01:00
|
|
|
if (cfg && cfg->filename && cfg->line)
|
|
|
|
fprintf(stderr, "ERROR in %s:%d: ",
|
|
|
|
cfg->filename, cfg->line);
|
|
|
|
else if (cfg && cfg->filename)
|
|
|
|
fprintf(stderr, "ERROR in %s:", cfg->filename);
|
|
|
|
vfprintf(stderr, fmt, ap);
|
|
|
|
fprintf(stderr,"\n");
|
|
|
|
}
|
2016-02-17 16:17:06 +01:00
|
|
|
|
|
|
|
|
|
|
|
int read_config(const char *filename)
|
|
|
|
{
|
|
|
|
int i, n;
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
cfg_opt_t opts[] = {
|
2018-02-18 21:48:42 +01:00
|
|
|
CFG_STR_LIST("mods", "{}", CFGF_NONE),
|
2018-02-26 09:04:53 +01:00
|
|
|
CFG_SIMPLE_STR("mods_dir", &conf_mods_dir),
|
|
|
|
|
2014-08-23 22:15:50 +02:00
|
|
|
CFG_STR_LIST("dbg", "{}", CFGF_NONE),
|
2014-07-11 22:12:11 +02:00
|
|
|
CFG_STR_LIST("listen", "{}", CFGF_NONE),
|
|
|
|
CFG_STR_LIST("mcast_groups", "{}", CFGF_NONE),
|
2016-02-17 20:26:19 +01:00
|
|
|
CFG_STR_LIST("broadcast_listen", "{}", CFGF_NONE),
|
2016-02-17 16:17:06 +01:00
|
|
|
CFG_STR_LIST("ac_ips", "{}", CFGF_NONE),
|
|
|
|
CFG_SIMPLE_STR("control_port", &conf_control_port),
|
|
|
|
|
|
|
|
CFG_SIMPLE_BOOL("strict_capwap", &conf_strict_capwap),
|
|
|
|
CFG_SIMPLE_BOOL("strict_headers", &conf_strict_headers),
|
2016-03-07 11:16:48 +01:00
|
|
|
CFG_SIMPLE_BOOL("use_loopback", &conf_use_loopback),
|
2018-03-11 00:56:41 +01:00
|
|
|
/*// CFG_SIMPLE_STR("capwap_mode", &conf_capwap_mode_str),*/
|
2015-04-26 14:46:28 +02:00
|
|
|
|
|
|
|
|
2014-07-25 08:24:38 +02:00
|
|
|
#ifdef WITH_LWAPP
|
2016-02-17 16:17:06 +01:00
|
|
|
CFG_SIMPLE_STR("lw_control_port", &conf_lw_control_port),
|
|
|
|
CFG_SIMPLE_BOOL("lwapp", &conf_lwapp),
|
2014-07-25 08:24:38 +02:00
|
|
|
#endif
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
CFG_SIMPLE_INT("max_wtps", &conf_max_wtps),
|
|
|
|
CFG_SIMPLE_INT("debug_level", &conf_debug_level),
|
2014-08-23 22:15:50 +02:00
|
|
|
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
CFG_SIMPLE_INT("vendor_id", &conf_vendor_id),
|
|
|
|
CFG_SIMPLE_STR("ac_id", &conf_acid),
|
|
|
|
CFG_SIMPLE_STR("ac_name", &conf_acname),
|
|
|
|
CFG_SIMPLE_STR("hardware_version", &conf_hardware_version),
|
|
|
|
CFG_SIMPLE_STR("software_version", &conf_software_version),
|
2015-03-19 21:51:28 +01:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
CFG_SIMPLE_STR("cisco_hardware_version", &conf_cisco_hardware_version),
|
|
|
|
CFG_SIMPLE_STR("cisco_software_version", &conf_cisco_software_version),
|
2015-03-19 21:51:28 +01:00
|
|
|
|
2014-08-02 07:50:40 +02:00
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
|
|
|
|
CFG_SIMPLE_STR("ssl_cert", &conf_sslcertfilename),
|
|
|
|
CFG_SIMPLE_STR("ssl_key", &conf_sslkeyfilename),
|
|
|
|
CFG_SIMPLE_STR("ssl_key_pass", &conf_sslkeypass),
|
|
|
|
CFG_SIMPLE_STR("ssl_cipher", &conf_sslcipher),
|
|
|
|
CFG_SIMPLE_STR("dtls_psk", &conf_dtls_psk),
|
|
|
|
|
|
|
|
CFG_SIMPLE_BOOL("dtls_verify_peer", &conf_dtls_verify_peer),
|
|
|
|
CFG_SIMPLE_BOOL("ipv4", &conf_ipv4),
|
|
|
|
CFG_SIMPLE_BOOL("ipv6", &conf_ipv6),
|
2018-03-11 00:56:41 +01:00
|
|
|
CFG_SIMPLE_STR("db_file", &conf_db_file),
|
2016-02-17 16:17:06 +01:00
|
|
|
CFG_SIMPLE_STR("image_dir", &conf_image_dir),
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
CFG_END()
|
|
|
|
};
|
|
|
|
cfg_t *cfg;
|
2018-03-26 20:18:46 +02:00
|
|
|
|
|
|
|
conf_mods_dir=cw_strdup("");
|
2022-07-30 23:27:42 +02:00
|
|
|
|
2018-03-11 00:56:41 +01:00
|
|
|
if (!init_control_port())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
2018-02-18 21:48:42 +01:00
|
|
|
cfg = cfg_init(opts, CFGF_NONE);
|
|
|
|
cfg_set_error_function(cfg, errfunc);
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2018-02-18 21:48:42 +01:00
|
|
|
if (cfg_parse(cfg, filename))
|
|
|
|
return 0;
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
|
2014-08-23 22:15:50 +02:00
|
|
|
/* read debug options */
|
|
|
|
conf_read_dbg_level(cfg);
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
/* read the listen addresses */
|
2016-02-17 16:17:06 +01:00
|
|
|
conf_read_strings(cfg, "listen", &conf_listen_addrs, &conf_listen_addrs_len);
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
/* read multi cast groups */
|
2016-02-17 16:17:06 +01:00
|
|
|
conf_read_strings(cfg, "mcast_groups", &conf_mcast_groups,
|
|
|
|
&conf_mcast_groups_len);
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
/* read ipv4 broadcast addresses */
|
2016-02-17 20:26:19 +01:00
|
|
|
conf_read_strings(cfg, "broadcast_listen", &conf_bcast_addrs, &conf_bcast_addrs_len);
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
|
|
|
|
/* read ac_ips */
|
|
|
|
n = cfg_size(cfg, "ac_ips");
|
2016-02-17 16:17:06 +01:00
|
|
|
if (!(conf_ac_ips = malloc(sizeof(struct sockaddr) * n)))
|
2014-07-11 22:12:11 +02:00
|
|
|
return 0;
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
conf_ac_ips_len = n;
|
|
|
|
for (i = 0; i < n; i++) {
|
2014-07-11 22:12:11 +02:00
|
|
|
struct sockaddr sa;
|
2016-02-17 16:17:06 +01:00
|
|
|
char *str = cfg_getnstr(cfg, "ac_ips", i);
|
|
|
|
if (sock_strtoaddr(cfg_getnstr(cfg, "ac_ips", i), &sa))
|
|
|
|
conf_ac_ips[i] = sa;
|
|
|
|
else {
|
2014-07-11 22:12:11 +02:00
|
|
|
perror(str);
|
|
|
|
}
|
|
|
|
}
|
2022-07-30 23:27:42 +02:00
|
|
|
|
|
|
|
|
2018-02-18 21:48:42 +01:00
|
|
|
if (!conf_read_mods(cfg)){
|
|
|
|
cfg_free(cfg);
|
|
|
|
return 0;
|
|
|
|
}
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
|
|
|
|
cfg_free(cfg);
|
|
|
|
|
2014-07-14 22:43:17 +02:00
|
|
|
if (!init_acid())
|
|
|
|
return 0;
|
|
|
|
|
2016-02-17 16:17:06 +01:00
|
|
|
if (!init_acname())
|
2014-07-11 22:12:11 +02:00
|
|
|
return 0;
|
|
|
|
|
2018-03-25 19:13:58 +02:00
|
|
|
/* if (!init_version())
|
2014-07-11 22:12:11 +02:00
|
|
|
return 0;
|
2018-03-25 19:13:58 +02:00
|
|
|
*/
|
2014-08-23 22:15:50 +02:00
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
if (!init_vendor_id())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!init_dtls())
|
|
|
|
return 0;
|
|
|
|
|
2015-02-07 02:01:03 +01:00
|
|
|
if (!conf_sslcipher)
|
2016-02-17 16:17:06 +01:00
|
|
|
conf_sslcipher = CAPWAP_CIPHER;
|
2014-07-11 22:12:11 +02:00
|
|
|
|
2015-03-17 01:10:08 +01:00
|
|
|
if (!conf_image_dir)
|
2016-02-17 16:17:06 +01:00
|
|
|
conf_image_dir = CONF_DEFAULT_IMAGE_DIR;
|
2015-03-17 01:10:08 +01:00
|
|
|
|
2015-04-26 15:12:44 +02:00
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
|
|
|
|
init_listen_addrs();
|
|
|
|
init_mcast_groups();
|
|
|
|
init_bcast_addrs();
|
|
|
|
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2014-07-11 22:12:11 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void free_config()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|