-/*
- These are all the possible configurable values
-*/
-static internal_config_t hazahaza[] = {
-/* Main configuration file keywords */
- { "Name", config_name, TYPE_NAME },
- { "ConnectTo", config_connectto, TYPE_NAME },
- { "PingTimeout", config_pingtimeout, TYPE_INT },
- { "TapDevice", config_tapdevice, TYPE_NAME },
- { "PrivateKey", config_privatekey, TYPE_NAME },
- { "KeyExpire", config_keyexpire, TYPE_INT },
- { "Hostnames", config_hostnames, TYPE_BOOL },
- { "Interface", config_interface, TYPE_NAME },
- { "InterfaceIP", config_interfaceip, TYPE_IP },
-/* Host configuration file keywords */
- { "Address", config_address, TYPE_NAME },
- { "Port", config_port, TYPE_INT },
- { "PublicKey", config_publickey, TYPE_NAME },
- { "Subnet", config_subnet, TYPE_IP }, /* Use IPv4 subnets only for now */
- { "RestrictHosts", config_restricthosts, TYPE_BOOL },
- { "RestrictSubnets", config_restrictsubnets, TYPE_BOOL },
- { "RestrictAddress", config_restrictaddress, TYPE_BOOL },
- { "RestrictPort", config_restrictport, TYPE_BOOL },
- { "IndirectData", config_indirectdata, TYPE_BOOL },
- { "TCPonly", config_tcponly, TYPE_BOOL },
- { NULL, 0, 0 }
-};
+ result = strcasecmp(a->variable, b->variable);
+
+ if(result)
+ return result;
+
+ result = a->line - b->line;
+
+ if(result)
+ return result;
+ else
+ return strcmp(a->file, b->file);
+}
+
+void init_configuration(avl_tree_t ** config_tree)
+{
+ cp();
+
+ *config_tree = avl_alloc_tree((avl_compare_t) config_compare, (avl_action_t) free_config);
+}
+
+void exit_configuration(avl_tree_t ** config_tree)
+{
+ cp();
+
+ avl_delete_tree(*config_tree);
+ *config_tree = NULL;
+}
+
+config_t *new_config(void)
+{
+ cp();
+
+ return (config_t *) xmalloc_and_zero(sizeof(config_t));
+}
+
+void free_config(config_t *cfg)
+{
+ cp();
+
+ if(cfg->variable)
+ free(cfg->variable);
+
+ if(cfg->value)
+ free(cfg->value);
+
+ if(cfg->file)
+ free(cfg->file);
+
+ free(cfg);
+}
+
+void config_add(avl_tree_t *config_tree, config_t *cfg)
+{
+ cp();
+
+ avl_insert(config_tree, cfg);
+}
+
+config_t *lookup_config(avl_tree_t *config_tree, char *variable)
+{
+ config_t cfg, *found;
+
+ cp();
+
+ cfg.variable = variable;
+ cfg.file = "";
+ cfg.line = 0;
+
+ found = avl_search_closest_greater(config_tree, &cfg);
+
+ if(!found)
+ return NULL;
+
+ if(strcasecmp(found->variable, variable))
+ return NULL;
+
+ return found;
+}
+
+config_t *lookup_config_next(avl_tree_t *config_tree, config_t *cfg)
+{
+ avl_node_t *node;
+ config_t *found;
+
+ cp();
+
+ node = avl_search_node(config_tree, cfg);
+
+ if(node) {
+ if(node->next) {
+ found = (config_t *) node->next->data;
+
+ if(!strcasecmp(found->variable, cfg->variable))
+ return found;
+ }
+ }
+
+ return NULL;
+}
+
+int get_config_bool(config_t *cfg, int *result)
+{
+ cp();
+
+ if(!cfg)
+ return 0;
+
+ if(!strcasecmp(cfg->value, "yes")) {
+ *result = 1;
+ return 1;
+ } else if(!strcasecmp(cfg->value, "no")) {
+ *result = 0;
+ return 1;
+ }
+
+ syslog(LOG_ERR, _("\"yes\" or \"no\" expected for configuration variable %s in %s line %d"),
+ cfg->variable, cfg->file, cfg->line);
+
+ return 0;
+}
+
+int get_config_int(config_t *cfg, int *result)
+{
+ cp();
+
+ if(!cfg)
+ return 0;
+
+ if(sscanf(cfg->value, "%d", result) == 1)
+ return 1;
+
+ syslog(LOG_ERR, _("Integer expected for configuration variable %s in %s line %d"),
+ cfg->variable, cfg->file, cfg->line);
+
+ return 0;
+}
+
+int get_config_string(config_t *cfg, char **result)
+{
+ cp();
+
+ if(!cfg)
+ return 0;
+
+ *result = xstrdup(cfg->value);
+
+ return 1;
+}
+
+int get_config_address(config_t *cfg, struct addrinfo **result)
+{
+ struct addrinfo *ai;
+
+ cp();
+
+ if(!cfg)
+ return 0;
+
+ ai = str2addrinfo(cfg->value, NULL, 0);
+
+ if(ai) {
+ *result = ai;
+ return 1;
+ }
+
+ syslog(LOG_ERR, _("Hostname or IP address expected for configuration variable %s in %s line %d"),
+ cfg->variable, cfg->file, cfg->line);
+
+ return 0;
+}
+
+int get_config_subnet(config_t *cfg, subnet_t ** result)
+{
+ subnet_t *subnet;
+
+ cp();
+
+ if(!cfg)
+ return 0;
+
+ subnet = str2net(cfg->value);
+
+ if(!subnet) {
+ syslog(LOG_ERR, _("Subnet expected for configuration variable %s in %s line %d"),
+ cfg->variable, cfg->file, cfg->line);
+ return 0;
+ }
+
+ /* Teach newbies what subnets are... */
+
+ if(((subnet->type == SUBNET_IPV4)
+ && maskcheck(&subnet->net.ipv4.address, subnet->net.ipv4.prefixlength, sizeof(ipv4_t)))
+ || ((subnet->type == SUBNET_IPV6)
+ && maskcheck(&subnet->net.ipv6.address, subnet->net.ipv6.prefixlength, sizeof(ipv6_t)))) {
+ syslog(LOG_ERR, _ ("Network address and prefix length do not match for configuration variable %s in %s line %d"),
+ cfg->variable, cfg->file, cfg->line);
+ free(subnet);
+ return 0;
+ }
+
+ *result = subnet;
+
+ return 1;
+}