Compare commits

...

9 Commits

Author SHA1 Message Date
8aa11dccba Moved from ktv to cfg 2022-08-08 23:14:11 +02:00
7d28858a70 New cmp funtion to get sorted integer arrays 2022-08-08 23:11:27 +02:00
8db182a303 Removed ktv stuff and switched to cfg 2022-08-08 23:10:31 +02:00
9452589625 ipv4 and ipv6 configurable 2022-08-08 23:09:28 +02:00
be3adf279d ipv4 and ipv6 are configurable 2022-08-08 23:09:10 +02:00
1544c6aa1b More example cfg 2022-08-08 23:08:38 +02:00
a3bc9dd09c Removed libconfuse-stuff, change to config.ckv 2022-08-08 23:07:58 +02:00
fb280d1c1c Removed libconfuse dependency 2022-08-08 23:06:56 +02:00
5240553144 Creates man pages 2022-08-08 08:40:14 +02:00
10 changed files with 533 additions and 438 deletions

View File

@ -17,7 +17,6 @@ LIBS+=-lmavl
LIBS+=-lcw LIBS+=-lcw
LIBS+=-lrt LIBS+=-lrt
LIBS+=-lpthread LIBS+=-lpthread
LIBS+=-lconfuse
LIBS+=-lc LIBS+=-lc
LIBS+=-lnettle LIBS+=-lnettle
LIBS+=-lssl LIBS+=-lssl

View File

@ -223,7 +223,7 @@ int main (int argc, char *argv[])
cw_cfg_dump(global_cfg); cw_cfg_dump(global_cfg);
cw_log (LOG_INFO, "Starting AC-Tube, Name=%s, ID=%s", conf_acname, conf_acid); cw_log (LOG_INFO, "Starting AC-Tube, Name=%s, ID=%s", cw_cfg_get(global_cfg,"capwap/ac-name",NULL), conf_acid);
rc = ac_run(global_cfg); rc = ac_run(global_cfg);
errX: errX:
@ -246,41 +246,51 @@ void process_ctrl_packet (int index, struct sockaddr *addr, uint8_t * buffer, in
void process_cw_data_packet (int index, struct sockaddr *addr, uint8_t * buffer, int len); void process_cw_data_packet (int index, struct sockaddr *addr, uint8_t * buffer, int len);
static void pcb(char *dst, struct mavlnode *node)
{
struct cw_Cfg_entry *e = mavlnode_dataptr(node);
sprintf(dst, "%s", e->key);
}
int ac_run(cw_Cfg_t * cfg) int ac_run(cw_Cfg_t * cfg)
{ {
struct cw_Cfg_iter cfi;
const char *s;
int i;
if (1 /*!conf_listen_addrs_len*/) {
cw_log (LOG_ERR, "Fatal error: No listen addresses found.");
// return 1;
}
extern void cw_cfg_iterate(cw_Cfg_t *);
cw_cfg_iterate(cfg);
return 1;
/* it is important to create the unicast sockets first, /* it is important to create the unicast sockets first,
* because when we create the mcast an bcast sockets next * because when we create the mcast an bcast sockets next
* we will look for already created sockets to find a * we will look for already created sockets to find a
* good unicast reply socket */ * good unicast reply socket */
int i; cw_cfg_iter_init(cfg, &cfi, "actube/listen");
for (i=0; (s = cw_cfg_iter_next(&cfi, NULL)) != NULL; i++) {
/* for (i = 0; i < conf_listen_addrs_len; i++) {
char addr[100]; char addr[100];
char port[50]; char port[50];
int proto; int proto;
conf_parse_listen_addr (conf_listen_addrs[i], addr, port, &proto); conf_parse_listen_addr (s, addr, port, &proto);
socklist_add_unicast (addr, port, proto,
socklist_add_unicast (addr, port, proto); cw_cfg_get_bool(cfg,"actube/ipv4","true"),
cw_cfg_get_bool(cfg,"actube/ipv6","true")
);
}
if (!i) {
cw_log (LOG_ERR, "Fatal error: No listen addresses found.");
return 1;
} }
*/
if (socklist_len == 0) { if (socklist_len == 0) {
cw_log (LOG_ERR, "Fatal error: Could not setup any listen socket"); cw_log (LOG_ERR, "Fatal error: Could not setup any listen socket");
return 1; return 1;
} }
/* create multicast sockets */ /* create multicast sockets */
for (i = 0; i < conf_mcast_groups_len; i++) { for (i = 0; i < conf_mcast_groups_len; i++) {
@ -298,13 +308,20 @@ int ac_run(cw_Cfg_t * cfg)
} }
/* broadcast socket ipv4 only */ /* broadcast socket ipv4 only */
for (i = 0; i < conf_bcast_addrs_len; i++) {
//mavl_print(cfg,pcb,180);
cw_cfg_iter_init(cfg, &cfi, "actube/bcast");
for (i=0; (s = cw_cfg_iter_next(&cfi, NULL)) != NULL; i++) {
// for (i = 0; i < conf_bcast_addrs_len; i++) {
char addr[50], port[50]; char addr[50], port[50];
int proto; int proto;
conf_parse_listen_addr (conf_bcast_addrs[i], addr, port, &proto); conf_parse_listen_addr (s, addr, port, &proto);
socklist_add_broadcast (addr, port, proto); socklist_add_broadcast (addr, port, proto);
#ifdef WITH_LWAPP #ifdef WITH_LWAPP
// printf("Adding %d\n",socklist_len); // printf("Adding %d\n",socklist_len);

View File

@ -19,7 +19,6 @@
#include <string.h> #include <string.h>
#include <sys/utsname.h> #include <sys/utsname.h>
#include <confuse.h>
#include "cw/capwap.h" #include "cw/capwap.h"
#include "cw/sock.h" #include "cw/sock.h"
@ -40,9 +39,9 @@
#include "cw/mavltypes.h" #include "cw/mavltypes.h"
uint8_t conf_macaddress[12]; /*uint8_t conf_macaddress[12];
uint8_t conf_macaddress_len = 0; uint8_t conf_macaddress_len = 0;
*/
long conf_strict_capwap = 1; long conf_strict_capwap = 1;
long conf_strict_headers = 0; long conf_strict_headers = 0;
@ -50,9 +49,6 @@ long conf_strict_headers = 0;
const char *conf_acname = NULL;
int conf_acname_len = 0;
char *conf_acid = NULL; char *conf_acid = NULL;
char *conf_primary_if = NULL; char *conf_primary_if = NULL;
@ -66,9 +62,6 @@ struct sockaddr_storage *conf_salist = NULL;
char **conf_mcast_groups = 0; char **conf_mcast_groups = 0;
int conf_mcast_groups_len = 0; int conf_mcast_groups_len = 0;
char **conf_bcast_addrs = 0;
int conf_bcast_addrs_len;
struct sockaddr_storage *conf_bsalist = NULL; struct sockaddr_storage *conf_bsalist = NULL;
@ -119,14 +112,44 @@ char *conf_control_port = 0;
int conf_dtls_verify_peer = 1; int conf_dtls_verify_peer = 1;
static int init_acname() static int init_ac_name(cw_Cfg_t * cfg)
{ {
if (conf_acname == NULL) { char *s;
char *s = malloc(strlen(CONF_DEFAULT_ACNAME) + strlen(conf_acid) + 1); char *primary_if=NULL;
sprintf(s, "%s%s", CONF_DEFAULT_ACNAME, conf_acid); char ac_name[CAPWAP_MAX_AC_NAME_LEN+1];
conf_acname = s; uint8_t macaddress[128];
uint8_t macaddress_len;
char acid[128];
int i;
s= cw_cfg_get(cfg,"capwap/ac-name",NULL);
if (s!=NULL)
return 1;
// primary_if = sock_get_primary_if(AF_INET6);
if (!primary_if)
primary_if = sock_get_primary_if(AF_INET);
acid[0]=0;
if (primary_if) {
macaddress_len=8;
if (!sock_getifhwaddr(primary_if, macaddress, &macaddress_len)) {
cw_dbg(DBG_INFO, "Fatal: Unable to detect link layer address for %s\n",
primary_if);
}
else{
s=acid;
for (i = 0; i < macaddress_len; i++) {
s += sprintf(s, "%02X", macaddress[i]);
}
}
} }
conf_acname_len = strlen(conf_acname);
sprintf(ac_name,"actube%s",acid);
cw_cfg_set(cfg,"capwap/ac-name",ac_name);
return 1; return 1;
} }
@ -135,49 +158,6 @@ static int init_acname()
static int init_acid()
{
int i;
char *s;
if (conf_acid != NULL)
return 1;
#ifdef WITH_IPV6
conf_primary_if = sock_get_primary_if(AF_INET6);
if (!conf_primary_if)
conf_primary_if = sock_get_primary_if(AF_INET);
#else
conf_primary_if = get_primary_if(AF_INET);
#endif
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");
return 0;
}
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);
return 0;
};
conf_acid = malloc(2 * conf_macaddress_len + 1);
s = conf_acid;
for (i = 0; i < conf_macaddress_len; i++) {
s += sprintf(s, "%02X", conf_macaddress[i]);
}
return 1;
}
static int init_dtls() static int init_dtls()
{ {
if (conf_dtls_psk != NULL) { if (conf_dtls_psk != NULL) {
@ -221,11 +201,13 @@ static int init_listen_addrs(cw_Cfg_t * cfg)
struct ifaddrs *ifap, *ifa; struct ifaddrs *ifap, *ifa;
int rc; int rc;
int ctr; int ctr;
const char * a0; struct cw_Cfg_iter cfi;
a0 = cw_cfg_get(cfg,"actube/listen.0",NULL);
if (a0)
return 1; cw_cfg_iter_init(cfg, &cfi, "actube/listen");
if (cw_cfg_iter_next(&cfi,NULL) != NULL)
return 0;
rc = getifaddrs(&ifap); rc = getifaddrs(&ifap);
if (rc == -1) if (rc == -1)
@ -310,18 +292,24 @@ static int add_bcast_addr(void *priv, void *addr)
/* /*
* Initialize broadcast addresses (ipv4 only) * Initialize broadcast addresses (ipv4 only)
*/ */
int init_bcast_addrs() int init_bcast_addrs(cw_Cfg_t *cfg)
{ {
int rc; int rc;
char str[100]; char str[100];
char key[100];
struct ifaddrs *ifa0, *ifa; struct ifaddrs *ifa0, *ifa;
mavl_t t; mavl_t t;
mavliter_t it; mavliter_t it;
struct cw_Cfg_iter cfi;
if (conf_bcast_addrs) int i;
return 1;
if (!conf_ipv4) //printf("BCAST INIT\n");
cw_cfg_iter_init(cfg, &cfi, "actube/bcast");
if (cw_cfg_iter_next(&cfi,NULL) != NULL)
return 0;
if (!cw_cfg_get_bool(cfg,"actube/ipv4", "true"))
return 1; return 1;
/*t = mavl_create_ptr(); */ /*t = mavl_create_ptr(); */
@ -359,22 +347,34 @@ int init_bcast_addrs()
if (ifa->ifa_broadaddr) { if (ifa->ifa_broadaddr) {
char *s,*sr;
sock_addrtostr(ifa->ifa_broadaddr, str, 100,1); sock_addrtostr(ifa->ifa_broadaddr, str, 100,1);
*strchr(str, ':') = 0; *strchr(str, ':') = 0;
mavl_add_str(t, cw_strdup(str));
s = cw_strdup(str);
sr = mavl_add_str(t, s);
printf("BCAST = %p --- %p: %s\n",str,s,str);
} }
} }
conf_bcast_addrs = malloc(t->count * sizeof(char *)); // conf_bcast_addrs = malloc(t->count * sizeof(char *));
i=0;
mavliter_init(&it,t); mavliter_init(&it,t);
mavliter_foreach(&it){ mavliter_foreach(&it){
char * d; char * d;
d = mavliter_get_str(&it); d = mavliter_get_str(&it);
conf_bcast_addrs[conf_bcast_addrs_len] = cw_strdup(d); // conf_bcast_addrs[conf_bcast_addrs_len] = cw_strdup(d);
if (conf_bcast_addrs[conf_bcast_addrs_len] != 0) // if (conf_bcast_addrs[conf_bcast_addrs_len] != 0)
conf_bcast_addrs_len++; // conf_bcast_addrs_len++;
sprintf(key,"actube/bcast.%d",i++);
cw_cfg_set(cfg,key,d);
} }
@ -386,7 +386,7 @@ int init_bcast_addrs()
return 1; return 1;
} }
int init_mcast_groups() int init_mcast_groups(cw_Cfg_t * cfg)
{ {
int ctr; int ctr;
int i; int i;
@ -440,6 +440,7 @@ int init_mcast_groups()
} }
/*
static int conf_read_strings(cfg_t * cfg, char *name, char ***dst, int *len) static int conf_read_strings(cfg_t * cfg, char *name, char ***dst, int *len)
{ {
@ -465,8 +466,9 @@ static int conf_read_strings(cfg_t * cfg, char *name, char ***dst, int *len)
return 1; return 1;
} }
*/
/*
static int conf_read_dbg_level(cfg_t * cfg) static int conf_read_dbg_level(cfg_t * cfg)
{ {
const char *name = "dbg"; const char *name = "dbg";
@ -484,6 +486,7 @@ static int conf_read_dbg_level(cfg_t * cfg)
} }
return 1; return 1;
} }
*/
struct cw_Mod ** conf_mods; struct cw_Mod ** conf_mods;
char *conf_mods_dir = NULL; char *conf_mods_dir = NULL;
@ -491,19 +494,28 @@ char *conf_mods_dir = NULL;
/* /*
* Read the module names from config file * Read the module names from config file
*/ */
static int conf_read_mods(cfg_t *cfg){ static int init_mods(cw_Cfg_t *cfg){
int n, i; int n, i;
n = cfg_size(cfg,CFG_ENTRY_MODS); const char * modname;
conf_mods = malloc(sizeof(struct cw_Mod *)*(n+1));
cw_dbg(DBG_INFO,"Mods directory: %s",conf_mods_dir); struct cw_Cfg_iter cfi;
cw_mod_set_path(conf_mods_dir); cw_cfg_iter_init(cfg, &cfi, "actube/mod");
if (cw_cfg_iter_next(&cfi,NULL) == NULL){
cw_cfg_set(cfg,"actube/mod.0","capwap");
cw_cfg_set(cfg,"actube/mod.1","capwap80211");
}
for (i=0; i < n; i++){ // cw_dbg(DBG_INFO,"Mods directory: %s",conf_mods_dir);
char *modname = cfg_getnstr(cfg, CFG_ENTRY_MODS, i); // cw_mod_set_path(conf_mods_dir);
struct cw_Mod * mod = cw_mod_load(modname, actube_global_cfg, CW_ROLE_AC);
cw_cfg_iter_init(cfg, &cfi, "actube/mod");
printf("iter mods\n");
for (i=0; (modname = cw_cfg_iter_next(&cfi, NULL)) != NULL; i++) {
printf("init mod name: %s\n",modname);
struct cw_Mod * mod = cw_mod_load(modname, cfg, CW_ROLE_AC);
if (!mod) if (!mod)
return 0; return 0;
@ -604,143 +616,6 @@ static void errfunc(cfg_t *cfg, const char *fmt, va_list ap){
fprintf(stderr,"\n"); fprintf(stderr,"\n");
} }
int read_config(const char *filename)
{
int i, n;
cfg_opt_t opts[] = {
CFG_STR_LIST("mods", "{}", CFGF_NONE),
CFG_SIMPLE_STR("mods_dir", &conf_mods_dir),
CFG_STR_LIST("dbg", "{}", CFGF_NONE),
CFG_STR_LIST("listen", "{}", CFGF_NONE),
CFG_STR_LIST("mcast_groups", "{}", CFGF_NONE),
CFG_STR_LIST("broadcast_listen", "{}", CFGF_NONE),
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),
CFG_SIMPLE_BOOL("use_loopback", &conf_use_loopback),
/*// CFG_SIMPLE_STR("capwap_mode", &conf_capwap_mode_str),*/
#ifdef WITH_LWAPP
CFG_SIMPLE_STR("lw_control_port", &conf_lw_control_port),
CFG_SIMPLE_BOOL("lwapp", &conf_lwapp),
#endif
CFG_SIMPLE_INT("max_wtps", &conf_max_wtps),
CFG_SIMPLE_INT("debug_level", &conf_debug_level),
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),
CFG_SIMPLE_STR("cisco_hardware_version", &conf_cisco_hardware_version),
CFG_SIMPLE_STR("cisco_software_version", &conf_cisco_software_version),
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("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),
CFG_SIMPLE_STR("db_file", &conf_db_file),
CFG_SIMPLE_STR("image_dir", &conf_image_dir),
CFG_END()
};
cfg_t *cfg;
conf_mods_dir=cw_strdup("");
if (!init_control_port())
return 0;
cfg = cfg_init(opts, CFGF_NONE);
cfg_set_error_function(cfg, errfunc);
if (cfg_parse(cfg, filename))
return 0;
/* read debug options */
conf_read_dbg_level(cfg);
/* read multi cast groups */
conf_read_strings(cfg, "mcast_groups", &conf_mcast_groups,
&conf_mcast_groups_len);
/* read ipv4 broadcast addresses */
conf_read_strings(cfg, "broadcast_listen", &conf_bcast_addrs, &conf_bcast_addrs_len);
/* read ac_ips */
n = cfg_size(cfg, "ac_ips");
if (!(conf_ac_ips = malloc(sizeof(struct sockaddr) * n)))
return 0;
conf_ac_ips_len = n;
for (i = 0; i < n; i++) {
struct sockaddr sa;
char *str = cfg_getnstr(cfg, "ac_ips", i);
if (sock_strtoaddr(cfg_getnstr(cfg, "ac_ips", i), &sa))
conf_ac_ips[i] = sa;
else {
perror(str);
}
}
if (!conf_read_mods(cfg)){
cfg_free(cfg);
return 0;
}
cfg_free(cfg);
if (!init_acid())
return 0;
if (!init_acname())
return 0;
/* if (!init_version())
return 0;
*/
if (!init_vendor_id())
return 0;
if (!init_dtls())
return 0;
/* if (!conf_sslcipher)
conf_sslcipher = CAPWAP_CIPHER;
*/ if (!conf_image_dir)
conf_image_dir = CONF_DEFAULT_IMAGE_DIR;
init_mcast_groups();
init_bcast_addrs();
return 1;
}
void free_config() void free_config()
{ {
@ -753,5 +628,7 @@ void ac_conf_init(cw_Cfg_t *cfg)
{ {
printf("ac conf\n"); printf("ac conf\n");
init_listen_addrs(cfg); init_listen_addrs(cfg);
init_bcast_addrs(cfg);
init_ac_name(cfg);
init_mods(cfg);
} }

View File

@ -1,4 +1,12 @@
#Cfg #Cfg
#
# AC Name
# Deafults to actube + mac address of primary interface
#
#capwap/ac-name
#
capwap/ssl-cipher: DHE-RSA:RSA:AES-256-CBC:AES-128-CBC:SHA1:PSK capwap/ssl-cipher: DHE-RSA:RSA:AES-256-CBC:AES-128-CBC:SHA1:PSK
capwap/ssl-psk-enable: false capwap/ssl-psk-enable: false
capwap/ssl-psk: 123456 capwap/ssl-psk: 123456
@ -9,6 +17,23 @@ cisco/ssl-certfile: "../../ssl/intermediate-ca/int-ca.crt"
cisco/ssl-cipher: DEFAULT cisco/ssl-cipher: DEFAULT
cisco/ssl-dhbits: 2048 cisco/ssl-dhbits: 2048
#actube/listen.hitler : 123456789
actube/listen.17 : 123456789 #
# Whether or not to use IPv4/IPv6
#
#actube/ipv4: true
#actube/ipv6: true
#
actube/ipv6: false
#
# List of Mods
#
#actube/mod.1: capwap
#actube/mod.2: capwap80211
#
actube/mod.0: cisco
actube/mod.1: capwap
actube/mod.2: capwap80211

View File

@ -335,7 +335,7 @@ static int socklist_check_size()
} }
int socklist_add_unicast(const char *addr, const char *port, int ac_proto) int socklist_add_unicast(const char *addr, const char *port, int ac_proto, int ipv4, int ipv6)
{ {
char sock_buf[SOCK_ADDR_BUFSIZE]; char sock_buf[SOCK_ADDR_BUFSIZE];
struct addrinfo hints; struct addrinfo hints;
@ -364,6 +364,14 @@ int socklist_add_unicast(const char *addr, const char *port, int ac_proto)
struct sockaddr broadcast; struct sockaddr broadcast;
struct sockaddr *sa; struct sockaddr *sa;
int sockfd; int sockfd;
if (res->ai_addr->sa_family == AF_INET && !ipv4){
continue;
}
if (res->ai_addr->sa_family == AF_INET6 && !ipv6){
continue;
}
ifname[0] = 0; ifname[0] = 0;
rc = sock_getifinfo(res->ai_addr, ifname, &broadcast, &netmask); rc = sock_getifinfo(res->ai_addr, ifname, &broadcast, &netmask);
@ -372,6 +380,7 @@ int socklist_add_unicast(const char *addr, const char *port, int ac_proto)
continue; continue;
} }
/* Bind the control port */ /* Bind the control port */
sa = res->ai_addr; sa = res->ai_addr;
sockfd = socket(res->ai_addr->sa_family, SOCK_DGRAM, 0); sockfd = socket(res->ai_addr->sa_family, SOCK_DGRAM, 0);

View File

@ -40,7 +40,7 @@ struct socklistelem{
extern int socklist_add_multicast(const char * addr, const char * port, int ac_proto); extern int socklist_add_multicast(const char * addr, const char * port, int ac_proto);
extern int socklist_add_unicast(const char *addr, const char * port, int ac_proto); extern int socklist_add_unicast(const char *addr, const char * port, int ac_proto, int ipv4, int ipv6);
extern int socklist_add_broadcast(const char *addr, const char * port,int ac_proto); extern int socklist_add_broadcast(const char *addr, const char * port,int ac_proto);
extern int socklist_init(); extern int socklist_init();
extern void socklist_destroy(); extern void socklist_destroy();

View File

@ -1743,7 +1743,7 @@ RTF_EXTENSIONS_FILE =
# classes and files. # classes and files.
# The default value is: NO. # The default value is: NO.
GENERATE_MAN = NO GENERATE_MAN = YES
# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a # The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of

View File

@ -7,28 +7,82 @@
#include "cfg.h" #include "cfg.h"
#include "val.h" #include "val.h"
static int cmp(const void *k1,const void*k2){ static const char *nextc(const char *s)
struct cw_Cfg_entry * e1,*e2; {
e1=(struct cw_Cfg_entry *)k1; while (isdigit(*s))
e2=(struct cw_Cfg_entry *)k2; s++;
return strcmp(e1->key,e2->key); return s;
}
static int cmp0(const char *s1, const char *s2)
{
const char *d1, *d2;
int i1, i2, i;
d1 = strchr(s1, '.');
if (d1 == NULL)
return strcmp(s1, s2);
d2 = strchr(s2, '.');
if (d2 == NULL)
return strcmp(s1, s2);
if ((d1 - s1) != (d2 - s2))
return strcmp(s1, s2);
if (strncmp(s1, s2, (d1 - s1)) != 0)
return strcmp(s1, s2);
if (isdigit(d1[1])) {
i1 = atoi(d1 + 1);
} else {
return cmp0(d1 + 1, d2 + 1);
}
if (isdigit(d2[1])) {
i2 = atoi(d2 + 1);
} else {
return cmp0(d1 + 1, d2 + 1);
}
i = i1 - i2;
if (i == 0) {
return cmp0(nextc(d1 + 1), nextc(d2 + 1));
}
return i;
}
static int cmp(const void *k1, const void *k2)
{
struct cw_Cfg_entry *e1, *e2;
e1 = (struct cw_Cfg_entry *) k1;
e2 = (struct cw_Cfg_entry *) k2;
return cmp0(e1->key, e2->key);
/* return strcmp(e1->key,e2->key);*/
} }
static void del(void *ptr) static void del(void *ptr)
{ {
struct cw_Cfg_entry * e; struct cw_Cfg_entry *e;
e=(struct cw_Cfg_entry *)ptr; e = (struct cw_Cfg_entry *) ptr;
free(e->key); free((void *) e->key);
free(e->val); free((void *) e->val);
} }
cw_Cfg_t * cw_cfg_create() cw_Cfg_t *cw_cfg_create()
{ {
return mavl_create(cmp, del, sizeof(struct cw_Cfg_entry)); return mavl_create(cmp, del, sizeof(struct cw_Cfg_entry));
} }
int cw_cfg_set(cw_Cfg_t * cfg,const char *key, const char *val) int cw_cfg_set(cw_Cfg_t * cfg, const char *key, const char *val)
{ {
struct cw_Cfg_entry e; struct cw_Cfg_entry e;
int replaced; int replaced;
@ -37,12 +91,12 @@ int cw_cfg_set(cw_Cfg_t * cfg,const char *key, const char *val)
if (!e.key) if (!e.key)
return 0; return 0;
e.val = cw_strdup(val); e.val = cw_strdup(val);
if (!e.val){ if (!e.val) {
free(e.key); free((void *) e.key);
return 0; return 0;
} }
void * rc = mavl_replace(cfg,&e,&replaced); void *rc = mavl_replace(cfg, &e, &replaced);
if (!rc){ if (!rc) {
del(&e); del(&e);
return 0; return 0;
} }
@ -52,32 +106,27 @@ int cw_cfg_set(cw_Cfg_t * cfg,const char *key, const char *val)
return -1; return -1;
} }
const char * cw_cfg_get(cw_Cfg_t * cfg, char *key, const char *def) const char *cw_cfg_get(cw_Cfg_t * cfg, const char *key, const char *def)
{ {
struct cw_Cfg_entry e,*r; struct cw_Cfg_entry e, *r;
e.key = key; e.key = key;
r = mavl_get(cfg,&e); r = mavl_get(cfg, &e);
if (!r) if (!r)
return def; return def;
return r->val; return r->val;
} }
uint16_t cw_cfg_get_word(cw_Cfg_t * cfg, char *key)
{
} void cw_cfg_dump(cw_Cfg_t * cfg)
void cw_cfg_dump(cw_Cfg_t *cfg)
{ {
mavliter_t it; mavliter_t it;
struct cw_Cfg_entry *e; struct cw_Cfg_entry *e;
mavliter_init(&it,cfg); mavliter_init(&it, cfg);
mavliter_foreach(&it){ mavliter_foreach(&it) {
e = mavliter_get(&it); e = mavliter_get(&it);
printf("%s: '%s'\n",e->key,e->val); printf("%s: '%s'\n", e->key, e->val);
//cw_dbg(dbglevel,"%s%s :%s: %s",prefix,data->key,type->get_type_name(data), value); //cw_dbg(dbglevel,"%s%s :%s: %s",prefix,data->key,type->get_type_name(data), value);
} }
} }
@ -97,23 +146,23 @@ struct parser {
static int get_char(struct parser *p) static int get_char(struct parser *p)
{ {
int c; int c;
c = fgetc (p->f); c = fgetc(p->f);
p->pos++; p->pos++;
if (c=='\n'){ if (c == '\n') {
p->prevpos=p->pos; p->prevpos = p->pos;
p->line ++; p->line++;
p->pos=0; p->pos = 0;
} }
return c; return c;
} }
static void unget_char(struct parser *p,int c){ static void unget_char(struct parser *p, int c)
ungetc(c,p->f); {
if (c=='\n'){ ungetc(c, p->f);
if (c == '\n') {
p->line--; p->line--;
p->pos=p->prevpos; p->pos = p->prevpos;
} } else
else
p->pos--; p->pos--;
} }
@ -123,67 +172,67 @@ static int get_char_q(struct parser *p)
{ {
int c; int c;
while(1) { while (1) {
c = get_char(p); c = get_char(p);
if (c==EOF || c=='\n') if (c == EOF || c == '\n')
return c; return c;
if(c=='"' && !p->quote){ if (c == '"' && !p->quote) {
p->quote=1; p->quote = 1;
continue; continue;
} }
if(c=='"' && p->quote){ if (c == '"' && p->quote) {
p->quote=0; p->quote = 0;
continue; continue;
} }
break; break;
} }
if (!p->quote) if (!p->quote)
return c; return c;
if (c!='\\') if (c != '\\')
return c; return c;
c = get_char(p); c = get_char(p);
switch(c){ switch (c) {
case EOF: case EOF:
return c; return c;
case 'n': case 'n':
return '\n'; return '\n';
case '\\': case '\\':
return '\\'; return '\\';
case '"': case '"':
return '"'; return '"';
default: default:
unget_char(p,c); unget_char(p, c);
return '\\'; return '\\';
} }
/* We will never reach here */ /* We will never reach here */
/* return c;*/ /* return c; */
} }
static int skip_chars (struct parser *p, const char * chars) static int skip_chars(struct parser *p, const char *chars)
{ {
int c; int c;
while ( (c = get_char (p)) != EOF) { while ((c = get_char(p)) != EOF) {
if (strchr (chars, c)) if (strchr(chars, c))
continue; continue;
return c; return c;
} }
return c; return c;
} }
static int skip_to_chars (struct parser *p, const char *chars) static int skip_to_chars(struct parser *p, const char *chars)
{ {
int c; int c;
while ( (c = get_char (p)) != EOF) { while ((c = get_char(p)) != EOF) {
if (strchr (chars, c)) if (strchr(chars, c))
return c; return c;
} }
return c; return c;
@ -191,52 +240,56 @@ static int skip_to_chars (struct parser *p, const char *chars)
static int read_key (struct parser *p, char *key, int max_len) static int read_key(struct parser *p, char *key, int max_len)
{ {
int c,n; int c, n;
do { do {
c = skip_chars (p, " \t\n\a\v"); c = skip_chars(p, " \t\n\a\v");
if (c == '#') { if (c == '#') {
c = skip_to_chars (p, "\n\a"); c = skip_to_chars(p, "\n\a");
} else { } else {
break; break;
} }
} while (c != EOF); } while (c != EOF);
unget_char(p,c);
c=get_char_q(p);
n=0; unget_char(p, c);
while(c!=EOF && n<max_len){ c = get_char_q(p);
if (!p->quote && !isalnum(c) && !strchr("._/-()@#|{}[]\\",c)/*strchr(": \t\n\a",c)*/){
unget_char(p,c); n = 0;
while (c != EOF && n < max_len) {
if (!p->quote && !isalnum(c)
&& !strchr("._/-()@#|{}[]\\", c) /*strchr(": \t\n\a",c) */ ) {
unget_char(p, c);
break; break;
} }
key[n]=c; key[n] = c;
c=get_char_q(p); c = get_char_q(p);
n++; n++;
} }
key[n]=0; key[n] = 0;
return n; return n;
} }
static int skip_to_colon(FILE *f,struct parser * p) static int skip_to_colon(FILE * f, struct parser *p)
{ {
int c; int c;
c = skip_chars (p, " \t"); c = skip_chars(p, " \t");
if (c!=':'){ if (c != ':') {
if (c=='\n'){ if (c == '\n') {
unget_char(p,c); unget_char(p, c);
sprintf(p->error,"Error at line %d, pos %d: Unexpected EOL, collon expected.", p->line, p->pos); sprintf(p->error,
"Error at line %d, pos %d: Unexpected EOL, collon expected.",
p->line, p->pos);
return 0; return 0;
} }
sprintf(p->error,"Error at line %d, pos %d: Collon expected.", p->line, p->pos); sprintf(p->error, "Error at line %d, pos %d: Collon expected.",
p->line, p->pos);
return 0; return 0;
} }
return 1; return 1;
@ -244,58 +297,58 @@ static int skip_to_colon(FILE *f,struct parser * p)
static int read_val(struct parser *p, char *val, int max_len){ static int read_val(struct parser *p, char *val, int max_len)
int c,n,quote; {
if (!skip_to_colon(p->f,p)) int c, n, quote;
if (!skip_to_colon(p->f, p))
return -1; return -1;
c = skip_chars (p, " \t"); c = skip_chars(p, " \t");
if (c=='"'){ if (c == '"') {
quote=1; quote = 1;
c=get_char(p); c = get_char(p);
} else {
quote = 0;
} }
else{ n = 0;
quote=0; while (c != EOF && n < max_len) {
} if (quote && c == '"') {
n=0;
while(c!=EOF && n<max_len){
if (quote && c=='"'){
break; break;
} }
if (c=='\n'){ if (c == '\n') {
break; break;
} }
if (quote){ if (quote) {
if (c=='\\'){ if (c == '\\') {
c = get_char(p); c = get_char(p);
switch(c){ switch (c) {
case 'n': case 'n':
c='\n'; c = '\n';
break; break;
case '\\': case '\\':
break; break;
case '"': case '"':
break; break;
default: default:
unget_char(p,c); unget_char(p, c);
c='\\'; c = '\\';
} }
} }
} }
val[n++]=c; val[n++] = c;
c=get_char(p); c = get_char(p);
} }
if(!quote && n>0){ if (!quote && n > 0) {
while(n>0){ while (n > 0) {
if (isspace(val[n-1])) if (isspace(val[n - 1]))
n--; n--;
else else
break; break;
} }
} }
val[n]=0; val[n] = 0;
return n; return n;
@ -303,20 +356,20 @@ static int read_val(struct parser *p, char *val, int max_len){
int cw_cfg_read_line (FILE *f, struct parser *p, char * key, char *val) int cw_cfg_read_line(FILE * f, struct parser *p, char *key, char *val)
{ {
int n; int n;
n = read_key (p,key,CW_CFG_MAX_KEY_LEN); n = read_key(p, key, CW_CFG_MAX_KEY_LEN);
if (n==0) if (n == 0)
return 1; return 1;
if (n==-1){ if (n == -1) {
return -1; return -1;
} }
n = read_val (p,val,CW_CFG_MAX_KEY_LEN); n = read_val(p, val, CW_CFG_MAX_KEY_LEN);
if (n==-1){ if (n == -1) {
return -1; return -1;
} }
return 0; return 0;
@ -328,45 +381,45 @@ int cw_cfg_read_from_file(FILE * f, cw_Cfg_t * cfg)
char val[2048]; char val[2048];
struct parser p; struct parser p;
p.line=1; p.line = 1;
p.pos=0; p.pos = 0;
p.prevpos=0; p.prevpos = 0;
p.quote=0; p.quote = 0;
p.f=f; p.f = f;
int rc; int rc;
int errs=0; int errs = 0;
do { do {
rc = cw_cfg_read_line(f,&p,key,val); rc = cw_cfg_read_line(f, &p, key, val);
if (rc==-1){ if (rc == -1) {
fprintf(stderr,"Error: %s\n",p.error); fprintf(stderr, "Error: %s\n", p.error);
errs++; errs++;
} }
if (rc != 0){ if (rc != 0) {
continue; continue;
} }
cw_cfg_set(cfg,key,val); cw_cfg_set(cfg, key, val);
} while (rc == 0);
}while(rc==0);
return errs; return errs;
} }
int cw_cfg_load(const char *filename,cw_Cfg_t * cfg) int cw_cfg_load(const char *filename, cw_Cfg_t * cfg)
{ {
int errs; int errs;
FILE *f = fopen(filename,"rb"); FILE *f = fopen(filename, "rb");
if (!f) if (!f)
return errno; return errno;
errs = cw_cfg_read_from_file(f,cfg); errs = cw_cfg_read_from_file(f, cfg);
fclose(f); fclose(f);
if (errs) if (errs)
@ -378,64 +431,148 @@ int cw_cfg_load(const char *filename,cw_Cfg_t * cfg)
static int cw_cfg_get_next_idx(cw_Cfg_t * cfg, const char *key, int n) static int cw_cfg_get_next_idx(cw_Cfg_t * cfg, const char *key, int n)
{ {
char ikey[CW_CFG_MAX_KEY_LEN]; char ikey[CW_CFG_MAX_KEY_LEN];
struct cw_Cfg_entry search, * result; struct cw_Cfg_entry search, *result;
char *d; const char *d;
int i; int i;
sprintf(ikey,"%s.%d",key,n);
search.key=ikey;
result = mavl_get_first(cfg,&search);
printf("KEY: %s\n",search.key); sprintf(ikey, "%s.%d", key, n);
printf("NNNNN: %s\n",result->key);
search.key = ikey;
if (result==NULL) result = mavl_get_first(cfg, &search);
printf("KEY: %s\n", search.key);
printf("NNNNN: %s\n", result->key);
if (result == NULL)
return -1; return -1;
d=NULL;
for (i = strlen(ikey); i>=0; i--){
if (ikey[i]=='.'){ d = NULL;
d = result->key+i; for (i = strlen(ikey); i >= 0; i--) {
if (ikey[i] == '.') {
d = result->key + i;
break; break;
} }
} }
if (d==NULL){ if (d == NULL) {
return -1; return -1;
} }
if(result->key[i]!='.'){ if (result->key[i] != '.') {
return -1; return -1;
} }
if (strncmp(result->key,ikey,i)!=0) if (strncmp(result->key, ikey, i) != 0)
return -1; return -1;
printf("TRANSFER %s\n",result->key+i+1); printf("TRANSFER %s\n", result->key + i + 1);
return atoi(result->key+i+1); return atoi(result->key + i + 1);
} }
void cw_cfg_iterate(cw_Cfg_t * cfg)
static void pcb(char *dst, struct mavlnode *node)
{
struct cw_Cfg_entry *e = mavlnode_dataptr(node);
sprintf(dst, "%s", e->key);
}
void cw_cfg_iter_init(cw_Cfg_t * cfg, struct cw_Cfg_iter *cfi, const char *base)
{
struct cw_Cfg_entry search;
search.key = base;
mavliter_init(&(cfi->it), cfg);
mavliter_seek(&(cfi->it), &search, 0);
cfi->base = base;
}
const char *cw_cfg_iter_next(struct cw_Cfg_iter *cfi, const char *key)
{
struct cw_Cfg_entry *e;
int bl, kl;
const char *d;
e = mavliter_get(&(cfi->it));
if (e == NULL)
return NULL;
bl = strlen(cfi->base);
kl = strlen(e->key);
if (bl > kl)
return NULL;
if (bl == kl) {
if (strcmp(cfi->base, e->key) != 0)
return NULL;
else {
mavliter_next(&(cfi->it));
return e->val;
}
}
d = strchr(e->key, '.');
if (d == NULL)
return NULL;
if (d - e->key != bl)
return NULL;
if (strncmp(cfi->base, e->key, bl) != 0)
return NULL;
mavliter_next(&(cfi->it));
return e->val;
}
void cw_cfg_iterate(cw_Cfg_t * cfg, const char *key)
{ {
printf("Iterate\n"); printf("Iterate\n");
struct cw_Cfg_entry *e; struct cw_Cfg_entry *e;
struct cw_Cfg_entry search; struct cw_Cfg_entry search;
search.key="actube/listen"; search.key = key;
struct mavliter it;
struct mavlnode *first;
int i=0; mavl_print(cfg,pcb,180);
i = cw_cfg_get_next_idx(cfg,"actube/listen",i);
printf("This i %d\n",i); printf("SEEK TO %s\n", search.key);
while ( (i = cw_cfg_get_next_idx(cfg,"actube/listen",i))!=-1) { struct cw_Cfg_iter cfi;
cw_cfg_iter_init(cfg, &cfi, key);
const char *kee;
printf("Here i %d\n",i); while ((kee = cw_cfg_iter_next(&cfi, NULL)) != NULL) {
printf("we have key: %s.%d\n","actube/listen",i); printf("KEY===%s\n", kee);
printf("Next=%d\n",i); }
return;
mavliter_init(&it, cfg);
mavliter_seek(&it, &search, 0);
struct cw_Cfg_entry *en;
return;
int i = 0;
i = cw_cfg_get_next_idx(cfg, "actube/listen", i);
printf("This i %d\n", i);
while ((i = cw_cfg_get_next_idx(cfg, "actube/listen", i)) != -1) {
printf("Here i %d\n", i);
printf("we have key: %s.%d\n", "actube/listen", i);
printf("Next=%d\n", i);
i++; i++;
}; };
@ -443,11 +580,30 @@ void cw_cfg_iterate(cw_Cfg_t * cfg)
e = mavl_get_first(cfg,&search); e = mavl_get_first(cfg, &search);
if (!e){ if (!e) {
printf("NULL\n"); printf("NULL\n");
return; return;
} }
printf("%s : %s\n",e->key,e->val); printf("%s : %s\n", e->key, e->val);
} }
int cw_cfg_get_bool(cw_Cfg_t * cfg, const char * key, const char *def)
{
struct cw_Val v;
const char *s = cw_cfg_get(cfg,key,def);
CW_TYPE_BOOL->from_str(&v,s);
return v.val.boolean;
}
uint16_t cw_cfg_get_word(cw_Cfg_t * cfg, char *key, const char * def)
{
struct cw_Val v;
const char *s = cw_cfg_get(cfg,key,def);
CW_TYPE_WORD->from_str(&v,s);
return v.val.word;
}

View File

@ -14,11 +14,23 @@ int cw_cfg_read_from_file(FILE * file, cw_Cfg_t * cfg);
int cw_cfg_load(const char *filename,cw_Cfg_t * cfg); int cw_cfg_load(const char *filename,cw_Cfg_t * cfg);
struct cw_Cfg_entry{ struct cw_Cfg_entry{
char *key; const char *key;
char *val; const char *val;
}; };
const char * cw_cfg_get(cw_Cfg_t * cfg, char *key, const char *def);
struct cw_Cfg_iter{
struct mavliter it;
const char *base;
};
const char * cw_cfg_get(cw_Cfg_t * cfg, const char *key, const char *def);
const char *cw_cfg_iter_next(struct cw_Cfg_iter *cfi, const char *key);
void cw_cfg_iter_init(cw_Cfg_t * cfg, struct cw_Cfg_iter *cfi, const char *base);
int cw_cfg_get_bool(cw_Cfg_t * cfg, const char * key, const char *def);
uint16_t cw_cfg_get_word(cw_Cfg_t * cfg, char *key, const char * def);
#endif #endif

View File

@ -5,6 +5,7 @@
#include "cw/val.h" #include "cw/val.h"
#include "cw/keys.h" #include "cw/keys.h"
#include "cw/dtls.h" #include "cw/dtls.h"
#include "cw/cfg.h"
#include "mod_capwap.h" #include "mod_capwap.h"
@ -15,16 +16,15 @@ static int init(struct cw_Mod * mod, mavl_t global_cfg, int role)
switch (role){ switch (role){
case CW_ROLE_AC:{ case CW_ROLE_AC:{
cw_dbg(DBG_MOD, "CAPWAP: Initialiazing mod_capwap in AC mode"); cw_dbg(DBG_MOD, "CAPWAP: Initialiazing mod_capwap in AC mode");
cw_ktv_add_from_str(global_cfg, cw_cfg_set(global_cfg,
"capwap/ac-descriptor/hardware/version", "capwap/ac-descriptor/hardware/version",
CW_TYPE_BSTR16,NULL,"0.0.0.1"); "0.0.0.1");
cw_ktv_add_from_str(global_cfg, cw_cfg_set(global_cfg,
"capwap/ac-descriptor/hardware/vendor",CW_TYPE_DWORD,NULL,"0"); "capwap/ac-descriptor/hardware/vendor","0");
cw_ktv_add_from_str(global_cfg, cw_cfg_set(global_cfg,
"capwap/ac-descriptor/software/version", "capwap/ac-descriptor/software/version","0.0.0.1");
CW_TYPE_BSTR16, NULL, "0.0.0.1"); cw_cfg_set(global_cfg,
cw_ktv_add_from_str(global_cfg, "capwap/ac-descriptor/software/vendor", "0");
"capwap/ac-descriptor/software/vendor",CW_TYPE_DWORD, NULL, "0");
} }
break; break;
} }