--- gvpe/src/conf.C 2005/04/26 00:55:55 1.41 +++ gvpe/src/conf.C 2012/12/04 10:29:43 1.59 @@ -1,22 +1,32 @@ /* - conf.c -- configuration code - Copyright (C) 2003-2005 Marc Lehmann + conf.C -- configuration code + Copyright (C) 2003-2008,2011 Marc Lehmann This file is part of GVPE. - GVPE 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 2 of the License, or - (at your option) any later version. - - This program 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 gvpe; if not, write to the Free Software - Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + GVPE 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. + + This program 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 this program; if not, see . + + Additional permission under GNU GPL version 3 section 7 + + If you modify this Program, or any covered work, by linking or + combining it with the OpenSSL project's OpenSSL library (or a modified + version of that library), containing parts covered by the terms of the + OpenSSL or SSLeay licenses, the licensors of this Program grant you + additional permission to convey the resulting work. Corresponding + Source for a non-source form of such a combination shall include the + source code for the parts of OpenSSL used as well as that of the + covered work. */ #include "config.h" @@ -30,6 +40,7 @@ #include #include #include +#include #include "netcompat.h" @@ -49,7 +60,8 @@ struct configuration conf; -u8 best_protocol (u8 protset) +u8 +best_protocol (u8 protset) { if (protset & PROT_IPv4 ) return PROT_IPv4; if (protset & PROT_ICMPv4) return PROT_ICMPv4; @@ -60,7 +72,8 @@ return 0; } -const char *strprotocol (u8 protocol) +const char * +strprotocol (u8 protocol) { if (protocol & PROT_IPv4 ) return "rawip"; if (protocol & PROT_ICMPv4) return "icmp"; @@ -71,21 +84,28 @@ return ""; } -void -conf_node::print () +static bool +match_list (const vector &list, const char *str) { - printf ("%4d fe:fd:80:00:0%1x:%02x %c %-8.8s %-10.10s %s%s%d\n", - id, - id >> 8, id & 0xff, - compress ? 'Y' : 'N', - connectmode == C_ONDEMAND ? "ondemand" : - connectmode == C_NEVER ? "never" : - connectmode == C_ALWAYS ? "always" : "", - nodename, - hostname ? hostname : "", - hostname ? ":" : "", - hostname ? udp_port : 0 - ); + for (vector::const_iterator i = list.end (); i-- > list.begin (); ) + if ((*i)[0] == '*' && !(*i)[1]) + return true; + else if (!strcmp (*i, str)) + return true; + + return false; +} + +bool +conf_node::may_direct (struct conf_node *other) +{ + if (match_list (allow_direct, other->nodename)) + return true; + + if (match_list (deny_direct, other->nodename)) + return false; + + return true; } conf_node::~conf_node () @@ -106,11 +126,13 @@ #endif } -void configuration::init () +void +configuration::init () { memset (this, 0, sizeof (*this)); mtu = DEFAULT_MTU; + nfmark = 0; rekey = DEFAULT_REKEY; keepalive = DEFAULT_KEEPALIVE; llevel = L_INFO; @@ -125,11 +147,14 @@ default_node.compress = true; default_node.protocols = 0; default_node.max_retry = DEFAULT_MAX_RETRY; + default_node.max_ttl = DEFAULT_MAX_TTL; + default_node.max_queue = DEFAULT_MAX_QUEUE; default_node.if_up_data = strdup (""); #if ENABLE_DNS default_node.dns_port = 0; // default is 0 == client + dns_case_preserving = true; dns_forw_host = strdup ("127.0.0.1"); dns_forw_port = 53; dns_timeout_factor = DEFAULT_DNS_TIMEOUT_FACTOR; @@ -141,22 +166,28 @@ conf.pidfilename = strdup (LOCALSTATEDIR "/run/gvpe.pid"); } -void configuration::cleanup() +void +configuration::cleanup () { if (rsa_key) RSA_free (rsa_key); rsa_key = 0; - free (pidfilename); pidfilename = 0; - free (ifname); ifname = 0; + free (pidfilename); pidfilename = 0; + free (ifname); ifname = 0; #if ENABLE_HTTP_PROXY - free (proxy_host); proxy_host = 0; - free (proxy_auth); proxy_auth = 0; + free (proxy_host); proxy_host = 0; + free (proxy_auth); proxy_auth = 0; #endif #if ENABLE_DNS - free (dns_forw_host); dns_forw_host = 0; + free (dns_forw_host); dns_forw_host = 0; #endif + free (change_root); change_root = 0; + free (script_if_up); script_if_up = 0; + free (script_node_up); script_node_up = 0; + free (script_node_change); script_node_change = 0; + free (script_node_down); script_node_down = 0; } void @@ -171,6 +202,12 @@ init (); } +//static bool +//is_true (const char *name) +//{ + //re +//} + #define parse_bool(target,name,trueval,falseval) do { \ if (!strcmp (val, "yes")) target = trueval; \ else if (!strcmp (val, "no")) target = falseval; \ @@ -179,7 +216,7 @@ else if (!strcmp (val, "on")) target = trueval; \ else if (!strcmp (val, "off")) target = falseval; \ else \ - return _("illegal boolean value, only 'yes|true|on' or 'no|false|off' allowed. (ignored)"); \ + return _("illegal boolean value, only 'yes|true|on' or 'no|false|off' allowed, ignored"); \ } while (0) const char * @@ -207,25 +244,30 @@ char *val = strtok (NULL, "\t\n\r ="); if (!val || val[0] == '#') - return _("no value given for variable. (ignored)"); + return _("no value given for variable, ignored"); - if (!strcmp (var, "on")) + else if (!strcmp (var, "on")) { - if (!::thisnode - || (val[0] == '!' && strcmp (val + 1, ::thisnode)) - || !strcmp (val, ::thisnode)) + if (::thisnode + && ((val[0] == '!' && strcmp (val + 1, ::thisnode)) + || !strcmp (val, ::thisnode))) return parse_line (strtok (NULL, "\n\r")); - else - return 0; + } + + else if (!strcmp (var, "include")) + { + char *fname = conf.config_filename (val); + parse_file (fname); + free (fname); } // truly global - if (!strcmp (var, "loglevel")) + else if (!strcmp (var, "loglevel")) { loglevel l = string_to_loglevel (val); if (l == L_NONE) - return _("unknown loglevel. (skipping)"); + return _("unknown loglevel, ignored"); } else if (!strcmp (var, "ip-proto")) conf.ip_proto = atoi (val); @@ -235,8 +277,23 @@ conf.icmp_type = atoi (val); #endif } + else if (!strcmp (var, "chuser")) + { + struct passwd *pw = getpwnam (val); + if (!pw) + return _("user specified for chuser not found"); + + conf.change_uid = pw->pw_uid; + conf.change_gid = pw->pw_gid; + } + else if (!strcmp (var, "chuid")) + conf.change_uid = atoi (val); + else if (!strcmp (var, "chgid")) + conf.change_gid = atoi (val); + else if (!strcmp (var, "chroot")) + free (conf.change_root), conf.change_root = strdup (val); - // per config + // per node else if (!strcmp (var, "node")) { parse_argv (); @@ -294,10 +351,14 @@ conf.keepalive = atoi (val); else if (!strcmp (var, "mtu")) conf.mtu = atoi (val); + else if (!strcmp (var, "nfmark")) + conf.nfmark = atoi (val); else if (!strcmp (var, "if-up")) free (conf.script_if_up), conf.script_if_up = strdup (val); else if (!strcmp (var, "node-up")) free (conf.script_node_up), conf.script_node_up = strdup (val); + else if (!strcmp (var, "node-change")) + free (conf.script_node_change), conf.script_node_change = strdup (val); else if (!strcmp (var, "node-down")) free (conf.script_node_down), conf.script_node_down = strdup (val); else if (!strcmp (var, "pid-file")) @@ -338,6 +399,12 @@ conf.dns_max_outstanding = atoi (val); #endif } + else if (!strcmp (var, "dns-case-preserving")) + { +#if ENABLE_DNS + parse_bool (conf.dns_case_preserving, "dns-case-preserving", true, false); +#endif + } else if (!strcmp (var, "http-proxy-host")) { #if ENABLE_HTTP_PROXY @@ -401,7 +468,7 @@ else if (!strcmp (val, "disabled")) node->connectmode = conf_node::C_DISABLED; else - return _("illegal value for 'connectmode', use one of 'ondemand', 'never', 'always' or 'disabled'. (ignored)"); + return _("illegal value for 'connectmode', use one of 'ondemand', 'never', 'always' or 'disabled', ignored"); } else if (!strcmp (var, "inherit-tos")) parse_bool (node->inherit_tos, "inherit-tos", true, false); @@ -434,15 +501,40 @@ { u8 v; parse_bool (v, "enable-rawip", PROT_IPv4, 0); node->protocols = (node->protocols & ~PROT_IPv4 ) | v; } + else if (!strcmp (var, "allow-direct")) + node->allow_direct.push_back (strdup (val)); + else if (!strcmp (var, "deny-direct")) + node->deny_direct.push_back (strdup (val)); + else if (!strcmp (var, "max-ttl")) + node->max_ttl = atof (val); + else if (!strcmp (var, "max-queue")) + node->max_queue = atoi (val); // unknown or misplaced else - return _("unknown configuration directive. (ignored)"); + return _("unknown configuration directive - ignored"); return 0; } -void configuration_parser::parse_argv () +void +conf_node::finalise () +{ + if (max_queue < 1) + { + slog (L_WARN, _("%s: max-queue value invalid, setting it to 1."), nodename); + max_queue = 1; + } + + if (routerprio > 1 && (connectmode != C_ALWAYS && connectmode != C_DISABLED)) + { + //slog (L_WARN, _("%s: has non-zero router-priority but either 'never' or 'ondemand' as connectmode, setting it to 'always'."), nodename); + connectmode = C_ALWAYS; + } +} + +void +configuration_parser::parse_argv () { for (int i = 0; i < argc; ++i) { @@ -476,25 +568,13 @@ } } -configuration_parser::configuration_parser (configuration &conf, - bool need_keys, - int argc, - char **argv) -: conf (conf),need_keys (need_keys), argc (argc), argv (argv) +void +configuration_parser::parse_file (const char *fname) { - char *fname; - FILE *f; - - conf.clear (); - - asprintf (&fname, "%s/gvpe.conf", confbase); - f = fopen (fname, "r"); - - if (f) + if (FILE *f = fopen (fname, "r")) { - char line[16384]; + char line [2048]; int lineno = 0; - node = &conf.default_node; while (fgets (line, sizeof (line), f)) { @@ -515,13 +595,26 @@ slog (L_ERR, _("unable to read config file '%s': %s"), fname, strerror (errno)); exit (EXIT_FAILURE); } +} + +configuration_parser::configuration_parser (configuration &conf, + bool need_keys, + int argc, + char **argv) +: conf (conf),need_keys (need_keys), argc (argc), argv (argv) +{ + char *fname; + conf.clear (); + node = &conf.default_node; + + asprintf (&fname, "%s/gvpe.conf", confbase); + parse_file (fname); free (fname); fname = conf.config_filename (conf.prikeyfile, "hostkey"); - f = fopen (fname, "r"); - if (f) + if (FILE *f = fopen (fname, "r")) { conf.rsa_key = RSA_new (); @@ -544,6 +637,8 @@ exit (EXIT_FAILURE); } + free (fname); + if (need_keys && ::thisnode && conf.rsa_key && conf.thisnode && conf.thisnode->rsa_key) if (BN_cmp (conf.rsa_key->n, conf.thisnode->rsa_key->n) != 0 @@ -553,10 +648,12 @@ exit (EXIT_FAILURE); } - free (fname); + for (configuration::node_vector::iterator i = conf.nodes.begin(); i != conf.nodes.end(); ++i) + (*i)->finalise (); } -char *configuration::config_filename (const char *name, const char *dflt) +char * +configuration::config_filename (const char *name, const char *dflt) { char *fname; @@ -573,6 +670,26 @@ } void +conf_node::print () +{ + printf ("%4d fe:fd:80:00:0%1x:%02x %c %-8.8s %-10.10s %02x %s%s%d\n", + id, + id >> 8, id & 0xff, + compress ? 'Y' : 'N', + connectmode == C_ONDEMAND ? "ondemand" + : connectmode == C_NEVER ? "never" + : connectmode == C_ALWAYS ? "always" + : connectmode == C_DISABLED ? "disabled" + : "", + nodename, + protocols, + hostname ? hostname : "", + hostname ? ":" : "", + hostname ? udp_port : 0 + ); +} + +void configuration::print () { printf (_("\nConfiguration\n\n")); @@ -586,8 +703,8 @@ printf (_("rsa key size: %d\n"), rsa_key ? RSA_size (rsa_key) * 8 : -1); printf ("\n"); - printf ("%4s %-17s %s %-8.8s %-10.10s %s\n", - _("ID#"), _("MAC"), _("Com"), _("Conmode"), _("Node"), _("Host:Port")); + printf ("%4s %-17s %s %-8.8s %-10.10s %04s %s\n", + _("ID#"), _("MAC"), _("Com"), _("Conmode"), _("Node"), _("Prot"), _("Host:Port")); for (node_vector::iterator i = nodes.begin (); i != nodes.end (); ++i) (*i)->print (); @@ -607,4 +724,3 @@ cleanup (); } -