// Otherwise, check if there are any known Address statements
if(!cache->config_tree) {
- init_configuration(&cache->config_tree);
+ cache->config_tree = create_configuration();
read_host_config(cache->config_tree, cache->node->name, false);
cache->cfg = lookup_config(cache->config_tree, "Address");
}
/* Select a random node we haven't connected to yet. */
int count = 0;
- for splay_each(node_t, n, node_tree) {
+ for splay_each(node_t, n, &node_tree) {
if(n == myself || n->connection || !(n->status.has_address || n->status.reachable)) {
continue;
}
int r = rand() % count;
- for splay_each(node_t, n, node_tree) {
+ for splay_each(node_t, n, &node_tree) {
if(n == myself || n->connection || !(n->status.has_address || n->status.reachable)) {
continue;
}
* are only a few reachable nodes, and many unreachable ones, we're
* going to try harder to connect to them. */
- unsigned int r = rand() % node_tree->count;
+ unsigned int r = rand() % node_tree.count;
- for splay_each(node_t, n, node_tree) {
+ for splay_each(node_t, n, &node_tree) {
if(r--) {
continue;
}
#endif
static bool setup_device(void) {
- get_config_string(lookup_config(config_tree, "Device"), &device);
+ get_config_string(lookup_config(&config_tree, "Device"), &device);
// Find out if it's supposed to be a tun or a tap device
char *type;
- if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
+ if(get_config_string(lookup_config(&config_tree, "DeviceType"), &type)) {
if(!strcasecmp(type, "tun"))
/* use default */;
realname = device;
}
- if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) {
+ if(!get_config_string(lookup_config(&config_tree, "Interface"), &iface)) {
iface = xstrdup(strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname);
} else if(strcmp(iface, strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname)) {
logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: Interface does not match Device. $INTERFACE might be set incorrectly.");
#include "protocol.h"
#include "xalloc.h"
-splay_tree_t *config_tree = NULL;
-
int pinginterval = 0; /* seconds between pings */
int pingtimeout = 0; /* seconds to wait for response */
}
}
-void init_configuration(splay_tree_t **config_tree) {
- *config_tree = splay_alloc_tree((splay_compare_t) config_compare, (splay_action_t) free_config);
+splay_tree_t config_tree = {
+ .compare = (splay_compare_t) config_compare,
+ .delete = (splay_action_t) free_config,
+};
+
+splay_tree_t *create_configuration() {
+ splay_tree_t *tree = splay_alloc_tree(NULL, NULL);
+ init_configuration(tree);
+ return tree;
+}
+
+void init_configuration(splay_tree_t *tree) {
+ memset(tree, 0, sizeof(*tree));
+ tree->compare = (splay_compare_t) config_compare;
+ tree->delete = (splay_action_t) free_config;
}
void exit_configuration(splay_tree_t **config_tree) {
int line;
} config_t;
-
-extern splay_tree_t *config_tree;
+extern splay_tree_t config_tree;
extern int pinginterval;
extern int pingtimeout;
extern bool bypass_security;
extern list_t cmdline_conf;
-extern void init_configuration(splay_tree_t **config_tree);
+extern splay_tree_t *create_configuration();
+extern void init_configuration(splay_tree_t *);
extern void exit_configuration(splay_tree_t **config_tree);
extern config_t *new_config(void) __attribute__((__malloc__));
extern void free_config(config_t *config);
#include "node.h"
#include "xalloc.h"
-splay_tree_t *edge_weight_tree;
-
-static int edge_compare(const edge_t *a, const edge_t *b) {
- return strcmp(a->to->name, b->to->name);
-}
-
static int edge_weight_compare(const edge_t *a, const edge_t *b) {
int result;
return strcmp(a->to->name, b->to->name);
}
-void init_edges(void) {
- edge_weight_tree = splay_alloc_tree((splay_compare_t) edge_weight_compare, NULL);
+splay_tree_t edge_weight_tree = {
+ .compare = (splay_compare_t) edge_weight_compare,
+};
+
+static int edge_compare(const edge_t *a, const edge_t *b) {
+ return strcmp(a->to->name, b->to->name);
}
splay_tree_t *new_edge_tree(void) {
}
void exit_edges(void) {
- splay_delete_tree(edge_weight_tree);
+ splay_empty_tree(&edge_weight_tree);
}
/* Creation and deletion of connection elements */
e->reverse->reverse = e;
}
- node = splay_insert(edge_weight_tree, e);
+ node = splay_insert(&edge_weight_tree, e);
if(!node) {
logger(DEBUG_ALWAYS, LOG_ERR, "Edge from %s to %s already exists in edge_weight_tree\n", e->from->name, e->to->name);
e->reverse->reverse = NULL;
}
- splay_delete(edge_weight_tree, e);
+ splay_delete(&edge_weight_tree, e);
splay_delete(e->from->edge_tree, e);
}
}
bool dump_edges(connection_t *c) {
- for splay_each(node_t, n, node_tree) {
+ for splay_each(node_t, n, &node_tree) {
for splay_each(edge_t, e, n->edge_tree) {
char *address = sockaddr2hostname(&e->address);
char *local_address = sockaddr2hostname(&e->local_address);
struct edge_t *reverse; /* edge in the opposite direction, if available */
} edge_t;
-extern splay_tree_t *edge_weight_tree; /* Tree with all known edges sorted on weight */
+extern splay_tree_t edge_weight_tree; /* Tree with all known edges sorted on weight */
-extern void init_edges(void);
extern void exit_edges(void);
extern edge_t *new_edge(void) __attribute__((__malloc__));
extern void free_edge(edge_t *e);
return false;
}
- if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
+ if(!get_config_string(lookup_config(&config_tree, "Device"), &device)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not read device from configuration!");
return false;
}
}
static void check_conffile(const char *nodename, bool server) {
- splay_tree_t *config = NULL;
+ splay_tree_t config;
init_configuration(&config);
bool read;
if(server) {
- read = read_server_config(config);
+ read = read_server_config(&config);
} else {
- read = read_host_config(config, nodename, true);
+ read = read_host_config(&config, nodename, true);
}
if(!read) {
- exit_configuration(&config);
+ splay_empty_tree(&config);
return;
}
int count[total_vars];
memset(count, 0, sizeof(count));
- for splay_each(config_t, conf, config) {
+ for splay_each(config_t, conf, &config) {
int var_type = 0;
for(size_t i = 0; variables[i].name; ++i) {
}
}
- exit_configuration(&config);
+ splay_empty_tree(&config);
}
#ifdef HAVE_MINGW
// Avoid touching global configuration here. Read the config files into
// a temporary configuration tree, then throw it away after fsck is done.
- splay_tree_t *config = NULL;
+ splay_tree_t config;
init_configuration(&config);
// Read the server configuration file and append host configuration for our node.
- bool success = read_server_config(config) &&
- read_host_config(config, name, true);
+ bool success = read_server_config(&config) &&
+ read_host_config(&config, name, true);
// Check both RSA and EC key pairs.
// We need working configuration to run this check.
if(success) {
- success = check_keypairs(config, name);
+ success = check_keypairs(&config, name);
}
// Check that scripts are executable and check the config for invalid variables.
// This way, we can diagnose more issues on the first run.
success = success & check_scripts_and_configs();
- exit_configuration(&config);
+ splay_empty_tree(&config);
free(name);
exe_name = NULL;
/* Clear visited status on nodes */
- for splay_each(node_t, n, node_tree) {
+ for splay_each(node_t, n, &node_tree) {
n->status.visited = false;
}
/* Starting point */
- for splay_each(edge_t, e, edge_weight_tree) {
+ for splay_each(edge_t, e, &edge_weight_tree) {
if(e->from->status.reachable) {
e->from->status.visited = true;
break;
bool skipped = false;
- for splay_each(edge_t, e, edge_weight_tree) {
+ for splay_each(edge_t, e, &edge_weight_tree) {
if(!e->reverse || (e->from->status.visited == e->to->status.visited)) {
skipped = true;
continue;
if(skipped) {
skipped = false;
- next = edge_weight_tree->head;
+ next = edge_weight_tree.head;
}
}
}
/* Clear visited status on nodes */
- for splay_each(node_t, n, node_tree) {
+ for splay_each(node_t, n, &node_tree) {
n->status.visited = false;
n->status.indirect = true;
n->distance = -1;
int became_reachable_count = 0;
int became_unreachable_count = 0;
- for splay_each(node_t, n, node_tree) {
+ for splay_each(node_t, n, &node_tree) {
if(n->status.visited != n->status.reachable) {
n->status.reachable = !n->status.reachable;
n->last_state_change = now.tv_sec;
char *p;
if(!*config_tree) {
- init_configuration(config_tree);
+ *config_tree = create_configuration();
if(!read_host_config(*config_tree, name, true)) {
return false;
static const char *device_info;
static bool setup_device(void) {
- if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
+ if(!get_config_string(lookup_config(&config_tree, "Device"), &device)) {
device = xstrdup(DEFAULT_DEVICE);
}
- if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
+ if(!get_config_string(lookup_config(&config_tree, "Interface"), &iface))
if(netname) {
iface = xstrdup(netname);
}
struct ifreq ifr = {0};
- get_config_string(lookup_config(config_tree, "DeviceType"), &type);
+ get_config_string(lookup_config(&config_tree, "DeviceType"), &type);
if(type && strcasecmp(type, "tun") && strcasecmp(type, "tap")) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unknown device type %s!", type);
bool t1q = false;
- if(get_config_bool(lookup_config(config_tree, "IffOneQueue"), &t1q) && t1q) {
+ if(get_config_bool(lookup_config(&config_tree, "IffOneQueue"), &t1q) && t1q) {
ifr.ifr_flags |= IFF_ONE_QUEUE;
}
int err;
- get_config_string(lookup_config(config_tree, "Device"), &device);
- get_config_string(lookup_config(config_tree, "Interface"), &iface);
+ get_config_string(lookup_config(&config_tree, "Device"), &device);
+ get_config_string(lookup_config(&config_tree, "Interface"), &iface);
if(device && iface) {
logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: both Device and Interface specified, results may not be as expected");
char *space;
int ttl = 1;
- get_config_string(lookup_config(config_tree, "Interface"), &iface);
+ get_config_string(lookup_config(&config_tree, "Interface"), &iface);
- if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
+ if(!get_config_string(lookup_config(&config_tree, "Device"), &device)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Device variable required for %s", device_info);
goto error;
}
/* Remove all edges and subnets owned by unreachable nodes. */
- for splay_each(node_t, n, node_tree) {
+ for splay_each(node_t, n, &node_tree) {
if(!n->status.reachable) {
logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Purging node %s (%s)", n->name, n->hostname);
/* Check if anyone else claims to have an edge to an unreachable node. If not, delete node. */
- for splay_each(node_t, n, node_tree) {
+ for splay_each(node_t, n, &node_tree) {
if(!n->status.reachable) {
- for splay_each(edge_t, e, edge_weight_tree)
+ for splay_each(edge_t, e, &edge_weight_tree)
if(e->to == n) {
return;
}
/* If AutoConnect is set, check if we need to make or break connections. */
- if(autoconnect && node_tree->count > 1) {
+ if(autoconnect && node_tree.count > 1) {
do_autoconnect();
}
/* Reread our own configuration file */
- exit_configuration(&config_tree);
- init_configuration(&config_tree);
+ splay_empty_tree(&config_tree);
- if(!read_server_config(config_tree)) {
+ if(!read_server_config(&config_tree)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to reread configuration file.");
return EINVAL;
}
- read_config_options(config_tree, NULL);
+ read_config_options(&config_tree, NULL);
snprintf(fname, sizeof(fname), "%s" SLASH "hosts" SLASH "%s", confbase, myself->name);
- read_config_file(config_tree, fname, true);
+ read_config_file(&config_tree, fname, true);
/* Parse some options that are allowed to be changed while tinc is running */
/* If StrictSubnet is set, expire deleted Subnets and read new ones in */
if(strictsubnets) {
- for splay_each(subnet_t, subnet, subnet_tree)
+ for splay_each(subnet_t, subnet, &subnet_tree)
if(subnet->owner) {
subnet->expires = 1;
}
}
- for splay_each(node_t, n, node_tree) {
+ for splay_each(node_t, n, &node_tree) {
n->status.has_address = false;
}
load_all_nodes();
if(strictsubnets) {
- for splay_each(subnet_t, subnet, subnet_tree) {
+ for splay_each(subnet_t, subnet, &subnet_tree) {
if(!subnet->owner) {
continue;
}
subnet->expires = 1;
}
- config_t *cfg = lookup_config(config_tree, "Subnet");
+ config_t *cfg = lookup_config(&config_tree, "Subnet");
while(cfg) {
subnet_t *subnet, *s2;
}
}
- cfg = lookup_config_next(config_tree, cfg);
+ cfg = lookup_config_next(&config_tree, cfg);
}
for splay_each(subnet_t, subnet, myself->subnet_tree) {
break;
}
- for splay_each(node_t, n, node_tree)
+ for splay_each(node_t, n, &node_tree)
if(n->status.reachable && n != myself && ((n->via == myself && n->nexthop == n) || n->via == n)) {
send_packet(n, packet);
}
bool hard = false;
static time_t last_hard_try = 0;
- for splay_each(node_t, n, node_tree) {
+ for splay_each(node_t, n, &node_tree) {
if(!n->status.reachable || n == myself) {
continue;
}
return true;
}
- splay_tree_t *config_tree;
FILE *fp;
char *pubname = NULL;
char *p;
- init_configuration(&config_tree);
+ splay_tree_t config;
+ init_configuration(&config);
- if(!read_host_config(config_tree, n->name, true)) {
+ if(!read_host_config(&config, n->name, true)) {
goto exit;
}
/* First, check for simple Ed25519PublicKey statement */
- if(get_config_string(lookup_config(config_tree, "Ed25519PublicKey"), &p)) {
+ if(get_config_string(lookup_config(&config, "Ed25519PublicKey"), &p)) {
n->ecdsa = ecdsa_set_base64_public_key(p);
free(p);
goto exit;
/* Else, check for Ed25519PublicKeyFile statement and read it */
- if(!get_config_string(lookup_config(config_tree, "Ed25519PublicKeyFile"), &pubname)) {
+ if(!get_config_string(lookup_config(&config, "Ed25519PublicKeyFile"), &pubname)) {
xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, n->name);
}
fclose(fp);
exit:
- exit_configuration(&config_tree);
+ splay_empty_tree(&config);
free(pubname);
return n->ecdsa;
}
logger(DEBUG_STATUS, LOG_INFO, "Expiring symmetric keys");
send_key_changed();
- for splay_each(node_t, n, node_tree) {
+ for splay_each(node_t, n, &node_tree) {
n->status.validkey_in = false;
}
}
node_t *n = lookup_node(ent->d_name);
- splay_tree_t *config_tree;
- init_configuration(&config_tree);
- read_config_options(config_tree, ent->d_name);
- read_host_config(config_tree, ent->d_name, true);
+ splay_tree_t config;
+ init_configuration(&config);
+ read_config_options(&config, ent->d_name);
+ read_host_config(&config, ent->d_name, true);
if(!n) {
n = new_node();
}
if(strictsubnets) {
- for(config_t *cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
+ for(config_t *cfg = lookup_config(&config, "Subnet"); cfg; cfg = lookup_config_next(&config, cfg)) {
subnet_t *s, *s2;
if(!get_config_subnet(cfg, &s)) {
}
}
- if(lookup_config(config_tree, "Address")) {
+ if(lookup_config(&config, "Address")) {
n->status.has_address = true;
}
- exit_configuration(&config_tree);
+ splay_empty_tree(&config);
}
closedir(dir);
char *name = NULL;
char *returned_name;
- get_config_string(lookup_config(config_tree, "Name"), &name);
+ get_config_string(lookup_config(&config_tree, "Name"), &name);
if(!name) {
return NULL;
free(scriptinterpreter);
scriptinterpreter = NULL;
- get_config_string(lookup_config(config_tree, "ScriptsInterpreter"), &scriptinterpreter);
+ get_config_string(lookup_config(&config_tree, "ScriptsInterpreter"), &scriptinterpreter);
free(scriptextension);
- if(!get_config_string(lookup_config(config_tree, "ScriptsExtension"), &scriptextension)) {
+ if(!get_config_string(lookup_config(&config_tree, "ScriptsExtension"), &scriptextension)) {
scriptextension = xstrdup("");
}
char *proxy = NULL;
- get_config_string(lookup_config(config_tree, "Proxy"), &proxy);
+ get_config_string(lookup_config(&config_tree, "Proxy"), &proxy);
if(proxy) {
char *space;
bool choice;
- if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice) && choice) {
+ if(get_config_bool(lookup_config(&config_tree, "IndirectData"), &choice) && choice) {
myself->options |= OPTION_INDIRECT;
}
- if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice) && choice) {
+ if(get_config_bool(lookup_config(&config_tree, "TCPOnly"), &choice) && choice) {
myself->options |= OPTION_TCPONLY;
}
myself->options |= OPTION_INDIRECT;
}
- get_config_bool(lookup_config(config_tree, "UDPDiscovery"), &udp_discovery);
- get_config_int(lookup_config(config_tree, "UDPDiscoveryKeepaliveInterval"), &udp_discovery_keepalive_interval);
- get_config_int(lookup_config(config_tree, "UDPDiscoveryInterval"), &udp_discovery_interval);
- get_config_int(lookup_config(config_tree, "UDPDiscoveryTimeout"), &udp_discovery_timeout);
+ get_config_bool(lookup_config(&config_tree, "UDPDiscovery"), &udp_discovery);
+ get_config_int(lookup_config(&config_tree, "UDPDiscoveryKeepaliveInterval"), &udp_discovery_keepalive_interval);
+ get_config_int(lookup_config(&config_tree, "UDPDiscoveryInterval"), &udp_discovery_interval);
+ get_config_int(lookup_config(&config_tree, "UDPDiscoveryTimeout"), &udp_discovery_timeout);
- get_config_int(lookup_config(config_tree, "MTUInfoInterval"), &mtu_info_interval);
- get_config_int(lookup_config(config_tree, "UDPInfoInterval"), &udp_info_interval);
+ get_config_int(lookup_config(&config_tree, "MTUInfoInterval"), &mtu_info_interval);
+ get_config_int(lookup_config(&config_tree, "UDPInfoInterval"), &udp_info_interval);
- get_config_bool(lookup_config(config_tree, "DirectOnly"), &directonly);
- get_config_bool(lookup_config(config_tree, "LocalDiscovery"), &localdiscovery);
+ get_config_bool(lookup_config(&config_tree, "DirectOnly"), &directonly);
+ get_config_bool(lookup_config(&config_tree, "LocalDiscovery"), &localdiscovery);
char *rmode = NULL;
- if(get_config_string(lookup_config(config_tree, "Mode"), &rmode)) {
+ if(get_config_string(lookup_config(&config_tree, "Mode"), &rmode)) {
if(!strcasecmp(rmode, "router")) {
routing_mode = RMODE_ROUTER;
} else if(!strcasecmp(rmode, "switch")) {
char *fmode = NULL;
- if(get_config_string(lookup_config(config_tree, "Forwarding"), &fmode)) {
+ if(get_config_string(lookup_config(&config_tree, "Forwarding"), &fmode)) {
if(!strcasecmp(fmode, "off")) {
forwarding_mode = FMODE_OFF;
} else if(!strcasecmp(fmode, "internal")) {
}
choice = !(myself->options & OPTION_TCPONLY);
- get_config_bool(lookup_config(config_tree, "PMTUDiscovery"), &choice);
+ get_config_bool(lookup_config(&config_tree, "PMTUDiscovery"), &choice);
if(choice) {
myself->options |= OPTION_PMTU_DISCOVERY;
}
choice = true;
- get_config_bool(lookup_config(config_tree, "ClampMSS"), &choice);
+ get_config_bool(lookup_config(&config_tree, "ClampMSS"), &choice);
if(choice) {
myself->options |= OPTION_CLAMP_MSS;
}
- get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance);
- get_config_bool(lookup_config(config_tree, "DecrementTTL"), &decrement_ttl);
+ get_config_bool(lookup_config(&config_tree, "PriorityInheritance"), &priorityinheritance);
+ get_config_bool(lookup_config(&config_tree, "DecrementTTL"), &decrement_ttl);
char *bmode = NULL;
- if(get_config_string(lookup_config(config_tree, "Broadcast"), &bmode)) {
+ if(get_config_string(lookup_config(&config_tree, "Broadcast"), &bmode)) {
if(!strcasecmp(bmode, "no")) {
broadcast_mode = BMODE_NONE;
} else if(!strcasecmp(bmode, "yes") || !strcasecmp(bmode, "mst")) {
/* Delete all broadcast subnets before re-adding them */
- for splay_each(subnet_t, s, subnet_tree) {
+ for splay_each(subnet_t, s, &subnet_tree) {
if(!s->owner) {
- splay_delete_node(subnet_tree, node);
+ splay_delete_node(&subnet_tree, node);
}
}
subnet_add(NULL, s);
}
- for(config_t *cfg = lookup_config(config_tree, "BroadcastSubnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
+ for(config_t *cfg = lookup_config(&config_tree, "BroadcastSubnet"); cfg; cfg = lookup_config_next(&config_tree, cfg)) {
subnet_t *s;
if(!get_config_subnet(cfg, &s)) {
#endif
- if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire)) {
+ if(!get_config_int(lookup_config(&config_tree, "MACExpire"), &macexpire)) {
macexpire = 600;
}
- if(get_config_int(lookup_config(config_tree, "MaxTimeout"), &maxtimeout)) {
+ if(get_config_int(lookup_config(&config_tree, "MaxTimeout"), &maxtimeout)) {
if(maxtimeout <= 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Bogus maximum timeout!");
return false;
char *afname = NULL;
- if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname)) {
+ if(get_config_string(lookup_config(&config_tree, "AddressFamily"), &afname)) {
if(!strcasecmp(afname, "IPv4")) {
addressfamily = AF_INET;
} else if(!strcasecmp(afname, "IPv6")) {
free(afname);
}
- get_config_bool(lookup_config(config_tree, "Hostnames"), &hostnames);
+ get_config_bool(lookup_config(&config_tree, "Hostnames"), &hostnames);
- if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime)) {
+ if(!get_config_int(lookup_config(&config_tree, "KeyExpire"), &keylifetime)) {
keylifetime = 3600;
}
- if(!get_config_bool(lookup_config(config_tree, "AutoConnect"), &autoconnect)) {
+ if(!get_config_bool(lookup_config(&config_tree, "AutoConnect"), &autoconnect)) {
autoconnect = true;
}
- get_config_bool(lookup_config(config_tree, "DisableBuggyPeers"), &disablebuggypeers);
+ get_config_bool(lookup_config(&config_tree, "DisableBuggyPeers"), &disablebuggypeers);
- if(!get_config_int(lookup_config(config_tree, "InvitationExpire"), &invitation_lifetime)) {
+ if(!get_config_int(lookup_config(&config_tree, "InvitationExpire"), &invitation_lifetime)) {
invitation_lifetime = 604800; // 1 week
}
myself->connection = new_connection();
myself->name = name;
myself->connection->name = xstrdup(name);
- read_host_config(config_tree, name, true);
+ read_host_config(&config_tree, name, true);
- if(!get_config_string(lookup_config(config_tree, "Port"), &myport)) {
+ if(!get_config_string(lookup_config(&config_tree, "Port"), &myport)) {
myport = xstrdup("655");
} else {
port_specified = true;
myself->options |= PROT_MINOR << 24;
#ifdef DISABLE_LEGACY
- myself->connection->ecdsa = read_ecdsa_private_key(config_tree, NULL);
+ myself->connection->ecdsa = read_ecdsa_private_key(&config_tree, NULL);
experimental = myself->connection->ecdsa != NULL;
if(!experimental) {
#else
- if(!get_config_bool(lookup_config(config_tree, "ExperimentalProtocol"), &experimental)) {
- myself->connection->ecdsa = read_ecdsa_private_key(config_tree, NULL);
+ if(!get_config_bool(lookup_config(&config_tree, "ExperimentalProtocol"), &experimental)) {
+ myself->connection->ecdsa = read_ecdsa_private_key(&config_tree, NULL);
experimental = myself->connection->ecdsa != NULL;
if(!experimental) {
}
} else {
if(experimental) {
- myself->connection->ecdsa = read_ecdsa_private_key(config_tree, NULL);
+ myself->connection->ecdsa = read_ecdsa_private_key(&config_tree, NULL);
if(!myself->connection->ecdsa) {
return false;
}
}
- myself->connection->rsa = read_rsa_private_key(config_tree, NULL);
+ myself->connection->rsa = read_rsa_private_key(&config_tree, NULL);
if(!myself->connection->rsa) {
if(experimental) {
/* Read in all the subnets specified in the host configuration file */
- for(config_t *cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
+ for(config_t *cfg = lookup_config(&config_tree, "Subnet"); cfg; cfg = lookup_config_next(&config_tree, cfg)) {
subnet_t *subnet;
if(!get_config_subnet(cfg, &subnet)) {
return false;
}
- get_config_bool(lookup_config(config_tree, "StrictSubnets"), &strictsubnets);
- get_config_bool(lookup_config(config_tree, "TunnelServer"), &tunnelserver);
+ get_config_bool(lookup_config(&config_tree, "StrictSubnets"), &strictsubnets);
+ get_config_bool(lookup_config(&config_tree, "TunnelServer"), &tunnelserver);
strictsubnets |= tunnelserver;
- if(get_config_int(lookup_config(config_tree, "MaxConnectionBurst"), &max_connection_burst)) {
+ if(get_config_int(lookup_config(&config_tree, "MaxConnectionBurst"), &max_connection_burst)) {
if(max_connection_burst <= 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "MaxConnectionBurst cannot be negative!");
return false;
}
}
- if(get_config_int(lookup_config(config_tree, "UDPRcvBuf"), &udp_rcvbuf)) {
+ if(get_config_int(lookup_config(&config_tree, "UDPRcvBuf"), &udp_rcvbuf)) {
if(udp_rcvbuf < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "UDPRcvBuf cannot be negative!");
return false;
udp_rcvbuf_warnings = true;
}
- if(get_config_int(lookup_config(config_tree, "UDPSndBuf"), &udp_sndbuf)) {
+ if(get_config_int(lookup_config(&config_tree, "UDPSndBuf"), &udp_sndbuf)) {
if(udp_sndbuf < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "UDPSndBuf cannot be negative!");
return false;
udp_sndbuf_warnings = true;
}
- get_config_int(lookup_config(config_tree, "FWMark"), &fwmark);
+ get_config_int(lookup_config(&config_tree, "FWMark"), &fwmark);
#ifndef SO_MARK
if(fwmark) {
int replaywin_int;
- if(get_config_int(lookup_config(config_tree, "ReplayWindow"), &replaywin_int)) {
+ if(get_config_int(lookup_config(&config_tree, "ReplayWindow"), &replaywin_int)) {
if(replaywin_int < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "ReplayWindow cannot be negative!");
return false;
char *cipher;
- if(!get_config_string(lookup_config(config_tree, "Cipher"), &cipher)) {
+ if(!get_config_string(lookup_config(&config_tree, "Cipher"), &cipher)) {
cipher = xstrdup("aes-256-cbc");
}
/* Check if we want to use message authentication codes... */
int maclength = 4;
- get_config_int(lookup_config(config_tree, "MACLength"), &maclength);
+ get_config_int(lookup_config(&config_tree, "MACLength"), &maclength);
if(maclength < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Bogus MAC length!");
char *digest;
- if(!get_config_string(lookup_config(config_tree, "Digest"), &digest)) {
+ if(!get_config_string(lookup_config(&config_tree, "Digest"), &digest)) {
digest = xstrdup("sha256");
}
#endif
/* Compression */
- if(get_config_int(lookup_config(config_tree, "Compression"), &myself->incompression)) {
+ if(get_config_int(lookup_config(&config_tree, "Compression"), &myself->incompression)) {
switch(myself->incompression) {
case COMPRESS_LZ4:
#ifdef HAVE_LZ4
devops = os_devops;
- if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
+ if(get_config_string(lookup_config(&config_tree, "DeviceType"), &type)) {
if(!strcasecmp(type, "dummy")) {
devops = dummy_devops;
} else if(!strcasecmp(type, "raw_socket")) {
free(type);
}
- get_config_bool(lookup_config(config_tree, "DeviceStandby"), &device_standby);
+ get_config_bool(lookup_config(&config_tree, "DeviceStandby"), &device_standby);
if(!devops.setup()) {
return false;
listen_sockets = 0;
int cfgs = 0;
- for(config_t *cfg = lookup_config(config_tree, "BindToAddress"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
+ for(config_t *cfg = lookup_config(&config_tree, "BindToAddress"); cfg; cfg = lookup_config_next(&config_tree, cfg)) {
cfgs++;
get_config_string(cfg, &address);
}
}
- for(config_t *cfg = lookup_config(config_tree, "ListenAddress"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
+ for(config_t *cfg = lookup_config(&config_tree, "ListenAddress"); cfg; cfg = lookup_config_next(&config_tree, cfg)) {
cfgs++;
get_config_string(cfg, &address);
myself->connection->hostname = xstrdup(myself->hostname);
char *upnp = NULL;
- get_config_string(lookup_config(config_tree, "UPnP"), &upnp);
+ get_config_string(lookup_config(&config_tree, "UPnP"), &upnp);
bool upnp_tcp = false;
bool upnp_udp = false;
bool setup_network(void) {
init_connections();
init_subnets();
- init_nodes();
- init_edges();
- init_requests();
- if(get_config_int(lookup_config(config_tree, "PingInterval"), &pinginterval)) {
+ if(get_config_int(lookup_config(&config_tree, "PingInterval"), &pinginterval)) {
if(pinginterval < 1) {
pinginterval = 86400;
}
pinginterval = 60;
}
- if(!get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout)) {
+ if(!get_config_int(lookup_config(&config_tree, "PingTimeout"), &pingtimeout)) {
pingtimeout = 5;
}
pingtimeout = pinginterval;
}
- if(!get_config_int(lookup_config(config_tree, "MaxOutputBufferSize"), &maxoutbufsize)) {
+ if(!get_config_int(lookup_config(&config_tree, "MaxOutputBufferSize"), &maxoutbufsize)) {
maxoutbufsize = 10 * MTU;
}
int status;
#endif /* defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) */
- if(!get_config_string(lookup_config(config_tree, "BindToInterface"), &iface)) {
+ if(!get_config_string(lookup_config(&config_tree, "BindToInterface"), &iface)) {
return true;
}
#endif
if(get_config_string
- (lookup_config(config_tree, "BindToInterface"), &iface)) {
+ (lookup_config(&config_tree, "BindToInterface"), &iface)) {
#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
struct ifreq ifr;
/* Make sure there is one outgoing_t in the list for each ConnectTo. */
- for(config_t *cfg = lookup_config(config_tree, "ConnectTo"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
+ for(config_t *cfg = lookup_config(&config_tree, "ConnectTo"); cfg; cfg = lookup_config_next(&config_tree, cfg)) {
char *name;
get_config_string(cfg, &name);
#include "ed25519/sha512.h"
-splay_tree_t *node_tree;
-static splay_tree_t *node_id_tree;
-static splay_tree_t *node_udp_tree;
-
node_t *myself;
static int node_compare(const node_t *a, const node_t *b) {
return (a->name && b->name) ? strcmp(a->name, b->name) : 0;
}
-void init_nodes(void) {
- node_tree = splay_alloc_tree((splay_compare_t) node_compare, (splay_action_t) free_node);
- node_id_tree = splay_alloc_tree((splay_compare_t) node_id_compare, NULL);
- node_udp_tree = splay_alloc_tree((splay_compare_t) node_udp_compare, NULL);
-}
+splay_tree_t node_tree = {
+ .compare = (splay_compare_t) node_compare,
+ .delete = (splay_action_t) free_node,
+};
+
+static splay_tree_t node_id_tree = {
+ .compare = (splay_compare_t) node_id_compare,
+};
+
+static splay_tree_t node_udp_tree = {
+ .compare = (splay_compare_t) node_udp_compare,
+};
void exit_nodes(void) {
- splay_delete_tree(node_udp_tree);
- splay_delete_tree(node_id_tree);
- splay_delete_tree(node_tree);
+ splay_empty_tree(&node_udp_tree);
+ splay_empty_tree(&node_id_tree);
+ splay_empty_tree(&node_tree);
}
node_t *new_node(void) {
sha512(n->name, strlen(n->name), buf);
memcpy(&n->id, buf, sizeof(n->id));
- splay_insert(node_tree, n);
- splay_insert(node_id_tree, n);
+ splay_insert(&node_tree, n);
+ splay_insert(&node_id_tree, n);
}
void node_del(node_t *n) {
- splay_delete(node_udp_tree, n);
+ splay_delete(&node_udp_tree, n);
for splay_each(subnet_t, s, n->subnet_tree) {
subnet_del(n, s);
edge_del(e);
}
- splay_delete(node_id_tree, n);
- splay_delete(node_tree, n);
+ splay_delete(&node_id_tree, n);
+ splay_delete(&node_tree, n);
}
node_t *lookup_node(char *name) {
n.name = name;
- return splay_search(node_tree, &n);
+ return splay_search(&node_tree, &n);
}
node_t *lookup_node_id(const node_id_t *id) {
node_t n = {.id = *id};
- return splay_search(node_id_tree, &n);
+ return splay_search(&node_id_tree, &n);
}
node_t *lookup_node_udp(const sockaddr_t *sa) {
node_t tmp = {.address = *sa};
- return splay_search(node_udp_tree, &tmp);
+ return splay_search(&node_udp_tree, &tmp);
}
void update_node_udp(node_t *n, const sockaddr_t *sa) {
return;
}
- splay_delete(node_udp_tree, n);
+ splay_delete(&node_udp_tree, n);
if(sa) {
n->address = *sa;
}
}
- splay_insert(node_udp_tree, n);
+ splay_insert(&node_udp_tree, n);
free(n->hostname);
n->hostname = sockaddr2hostname(&n->address);
logger(DEBUG_PROTOCOL, LOG_DEBUG, "UDP address of %s set to %s", n->name, n->hostname);
}
bool dump_nodes(connection_t *c) {
- for splay_each(node_t, n, node_tree) {
+ for splay_each(node_t, n, &node_tree) {
char id[2 * sizeof(n->id) + 1];
for(size_t c = 0; c < sizeof(n->id); ++c) {
}
bool dump_traffic(connection_t *c) {
- for splay_each(node_t, n, node_tree)
+ for splay_each(node_t, n, &node_tree)
send_request(c, "%d %d %s %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64, CONTROL, REQ_DUMP_TRAFFIC,
n->name, n->in_packets, n->in_bytes, n->out_packets, n->out_bytes);
} node_t;
extern struct node_t *myself;
-extern splay_tree_t *node_tree;
+extern splay_tree_t node_tree;
-extern void init_nodes(void);
extern void exit_nodes(void);
extern node_t *new_node(void) __attribute__((__malloc__));
extern void free_node(node_t *n);
"REQ_PUBKEY", "ANS_PUBKEY", "SPTPS_PACKET", "UDP_INFO", "MTU_INFO",
};
-static splay_tree_t *past_request_tree;
+static int past_request_compare(const past_request_t *a, const past_request_t *b) {
+ return strcmp(a->request, b->request);
+}
+
+static void free_past_request(past_request_t *r) {
+ free((char *)r->request);
+ free(r);
+}
+
+static splay_tree_t past_request_tree = {
+ .compare = (splay_compare_t) past_request_compare,
+ .delete = (splay_action_t) free_past_request,
+};
/* Generic request routines - takes care of logging and error
detection as well */
return true;
}
-static int past_request_compare(const past_request_t *a, const past_request_t *b) {
- return strcmp(a->request, b->request);
-}
-
-static void free_past_request(past_request_t *r) {
- free((char *)r->request);
- free(r);
-}
-
static timeout_t past_request_timeout;
static void age_past_requests(void *data) {
(void)data;
int left = 0, deleted = 0;
- for splay_each(past_request_t, p, past_request_tree) {
+ for splay_each(past_request_t, p, &past_request_tree) {
if(p->firstseen + pinginterval <= now.tv_sec) {
- splay_delete_node(past_request_tree, node), deleted++;
+ splay_delete_node(&past_request_tree, node), deleted++;
} else {
left++;
}
p.request = request;
- if(splay_search(past_request_tree, &p)) {
+ if(splay_search(&past_request_tree, &p)) {
logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Already seen request");
return true;
} else {
new = xmalloc(sizeof(*new));
new->request = xstrdup(request);
new->firstseen = now.tv_sec;
- splay_insert(past_request_tree, new);
+ splay_insert(&past_request_tree, new);
timeout_add(&past_request_timeout, age_past_requests, NULL, &(struct timeval) {
10, rand() % 100000
});
}
}
-void init_requests(void) {
- past_request_tree = splay_alloc_tree((splay_compare_t) past_request_compare, (splay_action_t) free_past_request);
-}
-
void exit_requests(void) {
- splay_delete_tree(past_request_tree);
+ splay_empty_tree(&past_request_tree);
timeout_del(&past_request_timeout);
}
extern void forward_request(struct connection_t *c, const char *request);
extern bool receive_request(struct connection_t *c, const char *request);
-extern void init_requests(void);
extern void exit_requests(void);
extern bool seen_request(const char *request);
if(bypass_security) {
if(!c->config_tree) {
- init_configuration(&c->config_tree);
+ c->config_tree = create_configuration();
}
c->allow_request = ACK;
}
if(!c->config_tree) {
- init_configuration(&c->config_tree);
+ c->config_tree = create_configuration();
if(!read_host_config(c->config_tree, c->name, false)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Peer %s had unknown identity (%s)", c->hostname, c->name);
}
if(!get_config_int(lookup_config(c->config_tree, "Weight"), &c->estimated_weight)) {
- get_config_int(lookup_config(config_tree, "Weight"), &c->estimated_weight);
+ get_config_int(lookup_config(&config_tree, "Weight"), &c->estimated_weight);
}
return send_request(c, "%d %s %d %x", ACK, myport, c->estimated_weight, (c->options & 0xffffff) | (experimental ? (PROT_MINOR << 24) : 0));
return;
}
- for splay_each(node_t, n, node_tree) {
+ for splay_each(node_t, n, &node_tree) {
for splay_each(subnet_t, s, n->subnet_tree) {
send_add_subnet(c, s);
}
n->mtu = mtu;
}
- if(get_config_int(lookup_config(config_tree, "PMTU"), &mtu) && mtu < n->mtu) {
+ if(get_config_int(lookup_config(&config_tree, "PMTU"), &mtu) && mtu < n->mtu) {
n->mtu = mtu;
}
}
if(e->weight != weight) {
- splay_node_t *node = splay_unlink(edge_weight_tree, e);
+ splay_node_t *node = splay_unlink(&edge_weight_tree, e);
e->weight = weight;
- splay_insert_node(edge_weight_tree, node);
+ splay_insert_node(&edge_weight_tree, node);
}
} else if(from == myself) {
logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself which does not exist",
/* Force key exchange for connections using SPTPS */
if(experimental) {
- for splay_each(node_t, n, node_tree) {
+ for splay_each(node_t, n, &node_tree) {
if(n->status.reachable && n->status.validkey && n->status.sptps) {
sptps_force_kex(&n->sptps);
}
struct ifreq ifr;
struct sockaddr_ll sa;
- if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) {
+ if(!get_config_string(lookup_config(&config_tree, "Interface"), &iface)) {
iface = xstrdup("eth0");
}
- if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
+ if(!get_config_string(lookup_config(&config_tree, "Device"), &device)) {
device = xstrdup(iface);
}
static bool setup_device(void) {
char *type;
- if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
+ if(!get_config_string(lookup_config(&config_tree, "Device"), &device)) {
if(routing_mode == RMODE_ROUTER) {
device = xstrdup(DEFAULT_TUN_DEVICE);
} else {
}
}
- if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
+ if(get_config_string(lookup_config(&config_tree, "DeviceType"), &type)) {
if(!strcasecmp(type, "tun"))
/* use default */;
else if(!strcasecmp(type, "tap")) {
/* Get unit number. */
char *ptr = device;
- get_config_string(lookup_config(config_tree, "Interface"), &ptr);
+ get_config_string(lookup_config(&config_tree, "Interface"), &ptr);
while(*ptr && !isdigit((uint8_t) *ptr)) {
ptr++;
/* Fast tree cleanup */
-void splay_delete_tree(splay_tree_t *tree) {
+void splay_empty_tree(splay_tree_t *tree) {
for(splay_node_t *node = tree->head, *next; node; node = next) {
next = node->next;
splay_free_node(tree, node);
}
+ tree->head = NULL;
+ tree->tail = NULL;
+ tree->root = NULL;
+ tree->count = 0;
+ tree->generation++;
+}
+
+void splay_delete_tree(splay_tree_t *tree) {
+ splay_empty_tree(tree);
splay_free_tree(tree);
}
/* Fast tree cleanup */
+extern void splay_empty_tree(splay_tree_t *tree);
extern void splay_delete_tree(splay_tree_t *tree);
/* Searching */
/* lists type of subnet */
-splay_tree_t *subnet_tree;
+splay_tree_t subnet_tree = {
+ .compare = (splay_compare_t) subnet_compare,
+ .delete = (splay_action_t) free_subnet,
+};
/* Subnet lookup cache */
/* Initialising trees */
void init_subnets(void) {
- subnet_tree = splay_alloc_tree((splay_compare_t) subnet_compare, (splay_action_t) free_subnet);
-
ipv4_cache = hash_alloc(0x100, sizeof(ipv4_t));
ipv6_cache = hash_alloc(0x100, sizeof(ipv6_t));
mac_cache = hash_alloc(0x100, sizeof(mac_t));
}
void exit_subnets(void) {
- splay_delete_tree(subnet_tree);
+ splay_empty_tree(&subnet_tree);
hash_free(ipv4_cache);
hash_free(ipv6_cache);
void subnet_add(node_t *n, subnet_t *subnet) {
subnet->owner = n;
- splay_insert(subnet_tree, subnet);
+ splay_insert(&subnet_tree, subnet);
if(n) {
splay_insert(n->subnet_tree, subnet);
splay_delete(n->subnet_tree, subnet);
}
- splay_delete(subnet_tree, subnet);
+ splay_delete(&subnet_tree, subnet);
subnet_cache_flush();
}
// Search all subnets for a matching one
- for splay_each(subnet_t, p, owner ? owner->subnet_tree : subnet_tree) {
+ for splay_each(subnet_t, p, owner ? owner->subnet_tree : &subnet_tree) {
if(!p || p->type != SUBNET_MAC) {
continue;
}
// Search all subnets for a matching one
- for splay_each(subnet_t, p, subnet_tree) {
+ for splay_each(subnet_t, p, &subnet_tree) {
if(!p || p->type != SUBNET_IPV4) {
continue;
}
// Search all subnets for a matching one
- for splay_each(subnet_t, p, subnet_tree) {
+ for splay_each(subnet_t, p, &subnet_tree) {
if(!p || p->type != SUBNET_IPV6) {
continue;
}
}
bool dump_subnets(connection_t *c) {
- for splay_each(subnet_t, subnet, subnet_tree) {
+ for splay_each(subnet_t, subnet, &subnet_tree) {
char netstr[MAXNETSTR];
if(!net2str(netstr, sizeof(netstr), subnet)) {
#define MAXNETSTR 64
-extern splay_tree_t *subnet_tree;
+extern splay_tree_t subnet_tree;
extern int subnet_compare(const struct subnet_t *a, const struct subnet_t *b);
extern subnet_t *new_subnet(void) __attribute__((__malloc__));
#endif
static void cleanup() {
- if(config_tree) {
- exit_configuration(&config_tree);
- }
-
+ splay_empty_tree(&config_tree);
list_empty_list(&cmdline_conf);
free_names();
}
unsetenv("LISTEN_PID");
#endif
- init_configuration(&config_tree);
-
/* Slllluuuuuuurrrrp! */
gettimeofday(&now, NULL);
srand(now.tv_sec + now.tv_usec);
crypto_init();
- if(!read_server_config(config_tree)) {
+ if(!read_server_config(&config_tree)) {
return 1;
}
if(debug_level == DEBUG_NOTHING) {
int level = 0;
- if(get_config_int(lookup_config(config_tree, "LogLevel"), &level)) {
+ if(get_config_int(lookup_config(&config_tree, "LogLevel"), &level)) {
debug_level = level;
}
}
/* Change process priority */
- if(get_config_string(lookup_config(config_tree, "ProcessPriority"), &priority)) {
+ if(get_config_string(lookup_config(&config_tree, "ProcessPriority"), &priority)) {
if(!strcasecmp(priority, "Normal")) {
if(setpriority(NORMAL_PRIORITY_CLASS) != 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setpriority", strerror(errno));
} name;
struct timeval tv;
- if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
+ if(!get_config_string(lookup_config(&config_tree, "Device"), &device)) {
xasprintf(&device, RUNSTATEDIR "/%s.umlsocket", identname);
}
- get_config_string(lookup_config(config_tree, "Interface"), &iface);
+ get_config_string(lookup_config(&config_tree, "Interface"), &iface);
if((write_fd = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not open write %s: %s", device_info, strerror(errno));
upnp_tcp = tcp;
upnp_udp = udp;
- get_config_int(lookup_config(config_tree, "UPnPDiscoverWait"), &upnp_discover_wait);
- get_config_int(lookup_config(config_tree, "UPnPRefreshPeriod"), &upnp_refresh_period);
+ get_config_int(lookup_config(&config_tree, "UPnPDiscoverWait"), &upnp_discover_wait);
+ get_config_int(lookup_config(&config_tree, "UPnPRefreshPeriod"), &upnp_refresh_period);
#ifdef HAVE_MINGW
HANDLE handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)upnp_thread, NULL, 0, NULL);
static const char *device_info = "VDE socket";
static bool setup_device(void) {
- if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
+ if(!get_config_string(lookup_config(&config_tree, "Device"), &device)) {
xasprintf(&device, RUNSTATEDIR "/vde.ctl");
}
- get_config_string(lookup_config(config_tree, "Interface"), &iface);
+ get_config_string(lookup_config(&config_tree, "Interface"), &iface);
- get_config_int(lookup_config(config_tree, "VDEPort"), &port);
+ get_config_int(lookup_config(&config_tree, "VDEPort"), &port);
- get_config_string(lookup_config(config_tree, "VDEGroup"), &group);
+ get_config_string(lookup_config(&config_tree, "VDEGroup"), &group);
struct vde_open_args args = {
.port = port,