From: Guus Sliepen Date: Fri, 12 Nov 2010 15:15:29 +0000 (+0100) Subject: Merge branch 'master' into 1.1 X-Git-Tag: release-1.1pre1~69 X-Git-Url: https://www.tinc-vpn.org/git/browse?p=tinc;a=commitdiff_plain;h=a22041922f160667573e9a5ae3f4195e1668906a;hp=8b70c5be9bc762d81354f9cd77c3748a44a4956d Merge branch 'master' into 1.1 Conflicts: doc/tincd.8.in lib/pidfile.c src/graph.c src/net.c src/net.h src/net_packet.c src/net_setup.c src/net_socket.c src/netutl.c src/node.c src/node.h src/protocol_auth.c src/protocol_key.c src/tincd.c --- diff --git a/AUTHORS b/AUTHORS index 7c20a8df..3f1ebacf 100644 --- a/AUTHORS +++ b/AUTHORS @@ -8,6 +8,8 @@ Significant contributions from: - Grzegorz Dymarek - Max Rijevski - Scott Lamb +- Julien Muchembled +- Timothy Redaelli These files are from other sources: * lib/pidfile.h and lib/pidfile.c are by Martin Schulze, taken from diff --git a/THANKS b/THANKS index 08f17d58..601116ef 100644 --- a/THANKS +++ b/THANKS @@ -17,6 +17,7 @@ We would like to thank the following people for their contributions to tinc: * Jason Harper * Jeroen Ubbink * Jerome Etienne +* Julien Muchembled * Lubomír Bulej * Mads Kiilerich * Marc A. Lehmann diff --git a/doc/tinc.conf.5.in b/doc/tinc.conf.5.in index bc82b176..2bfd5fef 100644 --- a/doc/tinc.conf.5.in +++ b/doc/tinc.conf.5.in @@ -110,6 +110,13 @@ Note: it is not required that you put in the sign, but doing so improves readability. If you leave it out, remember to replace it with at least one space character. +.Pp +The server configuration is complemented with host specific configuration (see the next section). +Although all configuration options for the local host listed in this document can also be put in +.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf , +it is recommended to put host specific configuration options in the host configuration file, +as this makes it easy to exchange with other nodes. + .Pp Here are all valid variables, listed in alphabetical order. The default value is given between parentheses. diff --git a/doc/tinc.texi b/doc/tinc.texi index a5ef8e6c..3dc9eca4 100644 --- a/doc/tinc.texi +++ b/doc/tinc.texi @@ -749,6 +749,13 @@ and carriage returns are ignored. Note: it is not required that you put in the `=' sign, but doing so improves readability. If you leave it out, remember to replace it with at least one space character. +The server configuration is complemented with host specific configuration (see +the next section). Although all host configuration options for the local node +listed in this document can also be put in +@file{@value{sysconfdir}/tinc/@var{netname}/tinc.conf}, it is recommended to +put host specific configuration options in the host configuration file, as this +makes it easy to exchange with other nodes. + In this section all valid variables are listed in alphabetical order. The default value is given between parentheses, other comments are between square brackets. diff --git a/doc/tincd.8.in b/doc/tincd.8.in index 9995b4c7..df6af144 100644 --- a/doc/tincd.8.in +++ b/doc/tincd.8.in @@ -72,11 +72,11 @@ is omitted, the default is .It Fl -bypass-security Disables encryption and authentication of the meta protocol. Only useful for debugging. -.It Fl -chroot +.It Fl R, -chroot With this option tinc chroots into the directory where network config is located (@sysconfdir@/tinc/NETNAME if -n option is used, or to the directory specified with -c option) after initialization. -.It Fl -user Ns = Ns Ar USER +.It Fl U, -user Ns = Ns Ar USER setuid to the specified .Ar USER after initialization. diff --git a/have.h b/have.h index 89454feb..21c16efa 100644 --- a/have.h +++ b/have.h @@ -21,6 +21,15 @@ #ifndef __TINC_HAVE_H__ #define __TINC_HAVE_H__ +#ifdef HAVE_MINGW +#ifdef WITH_WINDOWS2000 +#define WINVER Windows2000 +#else +#define WINVER WindowsXP +#endif +#define WIN32_LEAN_AND_MEAN +#endif + #include #include #include @@ -32,12 +41,6 @@ #include #ifdef HAVE_MINGW -#ifdef WITH_WINDOWS2000 -#define WINVER Windows2000 -#else -#define WINVER WindowsXP -#endif -#define WIN32_LEAN_AND_MEAN #include #include #include diff --git a/m4/openssl.m4 b/m4/openssl.m4 index a5cd0394..f0913001 100644 --- a/m4/openssl.m4 +++ b/m4/openssl.m4 @@ -29,7 +29,7 @@ AC_DEFUN([tinc_OPENSSL], case $host_os in *mingw*) AC_CHECK_LIB(crypto, SHA1_version, - [LIBS="$LIBS -lcrypto -lgdi32"], + [LIBS="$LIBS -lcrypto -lgdi32 -lcrypt32"], [AC_MSG_ERROR([OpenSSL libraries not found.])] ) ;; diff --git a/src/bsd/device.c b/src/bsd/device.c index a9e39d4a..993b9825 100644 --- a/src/bsd/device.c +++ b/src/bsd/device.c @@ -47,8 +47,8 @@ int device_fd = -1; char *device = NULL; char *iface = NULL; static char *device_info = NULL; -static int device_total_in = 0; -static int device_total_out = 0; +static uint64_t device_total_in = 0; +static uint64_t device_total_out = 0; #if defined(TUNEMU) static device_type_t device_type = DEVICE_TYPE_TUNEMU; #elif defined(HAVE_OPENBSD) || defined(HAVE_FREEBSD) @@ -64,7 +64,7 @@ bool setup_device(void) { device = xstrdup(DEFAULT_DEVICE); if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) - iface = xstrdup(rindex(device, '/') ? rindex(device, '/') + 1 : device); + iface = xstrdup(strrchr(device, '/') ? strrchr(device, '/') + 1 : device); if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) { if(!strcasecmp(type, "tun")) @@ -353,6 +353,6 @@ bool write_packet(vpn_packet_t *packet) { void dump_device_stats(void) { logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); - logger(LOG_DEBUG, " total bytes in: %10d", device_total_in); - logger(LOG_DEBUG, " total bytes out: %10d", device_total_out); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); } diff --git a/src/conf.c b/src/conf.c index d5bc9165..faff003b 100644 --- a/src/conf.c +++ b/src/conf.c @@ -2,7 +2,8 @@ conf.c -- configuration code Copyright (C) 1998 Robert van der Meulen 1998-2005 Ivo Timmermans - 2000-2009 Guus Sliepen + 2000-2010 Guus Sliepen + 2010 Julien Muchembled 2000 Cris van Pelt This program is free software; you can redistribute it and/or modify @@ -23,6 +24,7 @@ #include "system.h" #include "splay_tree.h" +#include "connection.h" #include "conf.h" #include "logger.h" #include "netutl.h" /* for str2address */ @@ -36,6 +38,8 @@ int pinginterval = 0; /* seconds between pings */ int pingtimeout = 0; /* seconds to wait for response */ char *confbase = NULL; /* directory in which all config files are */ char *netname = NULL; /* name of the vpn network */ +list_t *cmdline_conf = NULL; /* global/host configuration values given at the command line */ + static int config_compare(const config_t *a, const config_t *b) { int result; @@ -45,12 +49,17 @@ static int config_compare(const config_t *a, const config_t *b) { if(result) return result; + /* give priority to command line options */ + result = !b->file - !a->file; + if (result) + return result; + result = a->line - b->line; if(result) return result; else - return strcmp(a->file, b->file); + return a->file ? strcmp(a->file, b->file) : 0; } void init_configuration(splay_tree_t ** config_tree) { @@ -87,7 +96,7 @@ config_t *lookup_config(splay_tree_t *config_tree, char *variable) { config_t cfg, *found; cfg.variable = variable; - cfg.file = ""; + cfg.file = NULL; cfg.line = 0; found = splay_search_closest_greater(config_tree, &cfg); @@ -233,17 +242,54 @@ static char *readline(FILE * fp, char *buf, size_t buflen) { return buf; } +config_t *parse_config_line(char *line, const char *fname, int lineno) { + config_t *cfg; + int len; + char *variable, *value, *eol; + variable = value = line; + + eol = line + strlen(line); + while(strchr("\t ", *--eol)) + *eol = '\0'; + + len = strcspn(value, "\t ="); + value += len; + value += strspn(value, "\t "); + if(*value == '=') { + value++; + value += strspn(value, "\t "); + } + variable[len] = '\0'; + + if(!*value) { + const char err[] = "No value for variable"; + if (fname) + logger(LOG_ERR, "%s `%s' on line %d while reading config file %s", + err, variable, lineno, fname); + else + logger(LOG_ERR, "%s `%s' in command line option %d", + err, variable, lineno); + return NULL; + } + + cfg = new_config(); + cfg->variable = xstrdup(variable); + cfg->value = xstrdup(value); + cfg->file = fname ? xstrdup(fname) : NULL; + cfg->line = lineno; + + return cfg; +} + /* Parse a configuration file and put the results in the configuration tree starting at *base. */ -int read_config_file(splay_tree_t *config_tree, const char *fname) { +bool read_config_file(splay_tree_t *config_tree, const char *fname) { FILE *fp; char buffer[MAX_STRING_SIZE]; char *line; - char *variable, *value, *eol; int lineno = 0; - int len; bool ignore = false; config_t *cfg; bool result = false; @@ -280,34 +326,9 @@ int read_config_file(splay_tree_t *config_tree, const char *fname) { continue; } - variable = value = line; - - eol = line + strlen(line); - while(strchr("\t ", *--eol)) - *eol = '\0'; - - len = strcspn(value, "\t ="); - value += len; - value += strspn(value, "\t "); - if(*value == '=') { - value++; - value += strspn(value, "\t "); - } - variable[len] = '\0'; - - - if(!*value) { - logger(LOG_ERR, "No value for variable `%s' on line %d while reading config file %s", - variable, lineno, fname); + cfg = parse_config_line(line, fname, lineno); + if (!cfg) break; - } - - cfg = new_config(); - cfg->variable = xstrdup(variable); - cfg->value = xstrdup(value); - cfg->file = xstrdup(fname); - cfg->line = lineno; - config_add(config_tree, cfg); } @@ -316,10 +337,32 @@ int read_config_file(splay_tree_t *config_tree, const char *fname) { return result; } +void read_config_options(splay_tree_t *config_tree, const char *prefix) { + list_node_t *node, *next; + size_t prefix_len = prefix ? strlen(prefix) : 0; + + for(node = cmdline_conf->tail; node; node = next) { + config_t *cfg = (config_t *)node->data; + next = node->prev; + + if(!prefix && strchr(cfg->variable, '.')) + continue; + + if(prefix && (strncmp(prefix, cfg->variable, prefix_len) || cfg->variable[prefix_len] != '.')) + continue; + + config_add(config_tree, cfg); + node->data = NULL; + list_unlink_node(cmdline_conf, node); + } +} + bool read_server_config() { char *fname; bool x; + read_config_options(config_tree, NULL); + xasprintf(&fname, "%s/tinc.conf", confbase); x = read_config_file(config_tree, fname); @@ -332,6 +375,19 @@ bool read_server_config() { return x; } +bool read_connection_config(connection_t *c) { + char *fname; + bool x; + + read_config_options(c->config_tree, c->name); + + xasprintf(&fname, "%s/hosts/%s", confbase, c->name); + x = read_config_file(c->config_tree, fname); + free(fname); + + return x; +} + bool disable_old_keys(FILE *f) { char buf[100]; long pos; @@ -340,24 +396,33 @@ bool disable_old_keys(FILE *f) { rewind(f); pos = ftell(f); + if(pos < 0) + return false; + while(fgets(buf, sizeof buf, f)) { if(!strncmp(buf, "-----BEGIN RSA", 14)) { buf[11] = 'O'; buf[12] = 'L'; buf[13] = 'D'; - fseek(f, pos, SEEK_SET); - fputs(buf, f); + if(fseek(f, pos, SEEK_SET)) + break; + if(fputs(buf, f) <= 0) + break; disabled = true; } else if(!strncmp(buf, "-----END RSA", 12)) { buf[ 9] = 'O'; buf[10] = 'L'; buf[11] = 'D'; - fseek(f, pos, SEEK_SET); - fputs(buf, f); + if(fseek(f, pos, SEEK_SET)) + break; + if(fputs(buf, f) <= 0) + break; disabled = true; } pos = ftell(f); + if(pos < 0) + break; } return disabled; diff --git a/src/conf.h b/src/conf.h index be70c24c..cc57e82b 100644 --- a/src/conf.h +++ b/src/conf.h @@ -22,6 +22,7 @@ #define __TINC_CONF_H__ #include "splay_tree.h" +#include "list.h" typedef struct config_t { char *variable; @@ -40,6 +41,7 @@ extern int maxtimeout; extern bool bypass_security; extern char *confbase; extern char *netname; +extern list_t *cmdline_conf; extern void init_configuration(splay_tree_t **); extern void exit_configuration(splay_tree_t **); @@ -54,8 +56,11 @@ extern bool get_config_string(const config_t *, char **); extern bool get_config_address(const config_t *, struct addrinfo **); extern bool get_config_subnet(const config_t *, struct subnet_t **); -extern int read_config_file(splay_tree_t *, const char *); +extern config_t *parse_config_line(char *, const char *, int); +extern bool read_config_file(splay_tree_t *, const char *); +extern void read_config_options(splay_tree_t *, const char *); extern bool read_server_config(void); +extern bool read_connection_config(struct connection_t *); extern FILE *ask_and_open(const char *, const char *, const char *); extern bool is_safe_path(const char *); extern bool disable_old_keys(FILE *); diff --git a/src/connection.c b/src/connection.c index 18c03c7e..fecb48d4 100644 --- a/src/connection.c +++ b/src/connection.c @@ -106,14 +106,3 @@ bool dump_connections(connection_t *cdump) { return send_request(cdump, "%d %d", CONTROL, REQ_DUMP_CONNECTIONS); } - -bool read_connection_config(connection_t *c) { - char *fname; - bool x; - - xasprintf(&fname, "%s/hosts/%s", confbase, c->name); - x = read_config_file(c->config_tree, fname); - free(fname); - - return x; -} diff --git a/src/connection.h b/src/connection.h index 0f2b1d6a..0fc49ef3 100644 --- a/src/connection.h +++ b/src/connection.h @@ -100,6 +100,5 @@ extern void free_connection(connection_t *); extern void connection_add(connection_t *); extern void connection_del(connection_t *); extern bool dump_connections(struct connection_t *); -extern bool read_connection_config(connection_t *); #endif /* __TINC_CONNECTION_H__ */ diff --git a/src/cygwin/device.c b/src/cygwin/device.c index 00580764..5c227fd7 100644 --- a/src/cygwin/device.c +++ b/src/cygwin/device.c @@ -38,8 +38,8 @@ char *device = NULL; char *iface = NULL; static char *device_info = NULL; -static int device_total_in = 0; -static int device_total_out = 0; +static uint64_t device_total_in = 0; +static uint64_t device_total_out = 0; static pid_t reader_pid; static int sp[2]; @@ -261,6 +261,6 @@ bool write_packet(vpn_packet_t *packet) { void dump_device_stats(void) { logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); - logger(LOG_DEBUG, " total bytes in: %10d", device_total_in); - logger(LOG_DEBUG, " total bytes out: %10d", device_total_out); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); } diff --git a/src/dummy/device.c b/src/dummy/device.c index a9600b28..c84e899b 100644 --- a/src/dummy/device.c +++ b/src/dummy/device.c @@ -27,8 +27,8 @@ char *device = "dummy"; char *iface = "dummy"; static char *device_info = "dummy device"; -static int device_total_in = 0; -static int device_total_out = 0; +static uint64_t device_total_in = 0; +static uint64_t device_total_out = 0; bool setup_device(void) { logger(LOG_INFO, "%s (%s) is a %s", device, iface, device_info); @@ -49,6 +49,6 @@ bool write_packet(vpn_packet_t *packet) { void dump_device_stats(void) { logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); - logger(LOG_DEBUG, " total bytes in: %10d", device_total_in); - logger(LOG_DEBUG, " total bytes out: %10d", device_total_out); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); } diff --git a/src/getopt.c b/src/getopt.c index b2f88b42..a6782ed6 100644 --- a/src/getopt.c +++ b/src/getopt.c @@ -44,6 +44,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include +#ifdef HAVE_STRING_H +#include +#endif + /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling @@ -688,16 +692,18 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) else { if (opterr) - if (argv[optind - 1][1] == '-') - /* --option */ - fprintf (stderr, - "%s: option `--%s' doesn't allow an argument\n", - argv[0], pfound->name); - else - /* +option or -option */ - fprintf (stderr, - "%s: option `%c%s' doesn't allow an argument\n", - argv[0], argv[optind - 1][0], pfound->name); + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + "%s: option `--%s' doesn't allow an argument\n", + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + "%s: option `%c%s' doesn't allow an argument\n", + argv[0], argv[optind - 1][0], pfound->name); + } nextchar += strlen (nextchar); diff --git a/src/linux/device.c b/src/linux/device.c index 72becd77..4dbe38d5 100644 --- a/src/linux/device.c +++ b/src/linux/device.c @@ -47,8 +47,8 @@ char *iface = NULL; static char ifrname[IFNAMSIZ]; static char *device_info; -static int device_total_in = 0; -static int device_total_out = 0; +static uint64_t device_total_in = 0; +static uint64_t device_total_out = 0; bool setup_device(void) { struct ifreq ifr; @@ -61,7 +61,7 @@ bool setup_device(void) { if (netname != NULL) iface = xstrdup(netname); #else - iface = xstrdup(rindex(device, '/') ? rindex(device, '/') + 1 : device); + iface = xstrdup(strrchr(device, '/') ? strrchr(device, '/') + 1 : device); #endif device_fd = open(device, O_RDWR | O_NONBLOCK); @@ -105,7 +105,7 @@ bool setup_device(void) { device_type = DEVICE_TYPE_ETHERTAP; if(iface) free(iface); - iface = xstrdup(rindex(device, '/') ? rindex(device, '/') + 1 : device); + iface = xstrdup(strrchr(device, '/') ? strrchr(device, '/') + 1 : device); } logger(LOG_INFO, "%s is a %s", device, device_info); @@ -205,6 +205,6 @@ bool write_packet(vpn_packet_t *packet) { void dump_device_stats(void) { logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); - logger(LOG_DEBUG, " total bytes in: %10d", device_total_in); - logger(LOG_DEBUG, " total bytes out: %10d", device_total_out); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); } diff --git a/src/logger.c b/src/logger.c index 35a6a38a..4c0d2312 100644 --- a/src/logger.c +++ b/src/logger.c @@ -85,7 +85,7 @@ void logger(int priority, const char *format, ...) { #ifdef HAVE_MINGW { char message[4096]; - char *messages[] = {message}; + const char *messages[] = {message}; vsnprintf(message, sizeof message, format, ap); ReportEvent(loghandle, priority, 0, 0, NULL, 1, 0, messages, NULL); } diff --git a/src/memcmp.c b/src/memcmp.c index 9d808338..8103e1a7 100644 --- a/src/memcmp.c +++ b/src/memcmp.c @@ -107,8 +107,8 @@ static int memcmp_bytes (a, b) op_t a, b; { - long int srcp1 = (long int) &a; - long int srcp2 = (long int) &b; + intptr_t srcp1 = (intptr_t) &a; + intptr_t srcp2 = (intptr_t) &b; op_t a0, b0; do @@ -123,7 +123,7 @@ memcmp_bytes (a, b) } #endif -static int memcmp_common_alignment __P((long, long, size_t)); +static int memcmp_common_alignment __P((intptr_t, intptr_t, size_t)); /* memcmp_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN `op_t' objects (not LEN bytes!). Both SRCP1 and SRCP2 should be aligned for @@ -133,8 +133,8 @@ __inline #endif static int memcmp_common_alignment (srcp1, srcp2, len) - long int srcp1; - long int srcp2; + intptr_t srcp1; + intptr_t srcp2; size_t len; { op_t a0, a1; @@ -213,7 +213,7 @@ memcmp_common_alignment (srcp1, srcp2, len) return 0; } -static int memcmp_not_common_alignment __P((long, long, size_t)); +static int memcmp_not_common_alignment __P((intptr_t, intptr_t, size_t)); /* memcmp_not_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN `op_t' objects (not LEN bytes!). SRCP2 should be aligned for memory @@ -223,8 +223,8 @@ __inline #endif static int memcmp_not_common_alignment (srcp1, srcp2, len) - long int srcp1; - long int srcp2; + intptr_t srcp1; + intptr_t srcp2; size_t len; { op_t a0, a1, a2, a3; @@ -332,8 +332,8 @@ rpl_memcmp (s1, s2, len) { op_t a0; op_t b0; - long int srcp1 = (long int) s1; - long int srcp2 = (long int) s2; + intptr_t srcp1 = (intptr_t) s1; + intptr_t srcp2 = (intptr_t) s2; op_t res; if (len >= OP_T_THRES) diff --git a/src/mingw/device.c b/src/mingw/device.c index b67d0d34..c6eb908b 100644 --- a/src/mingw/device.c +++ b/src/mingw/device.c @@ -38,8 +38,8 @@ char *device = NULL; char *iface = NULL; static char *device_info = NULL; -static int device_total_in = 0; -static int device_total_out = 0; +static uint64_t device_total_in = 0; +static uint64_t device_total_out = 0; extern char *myport; @@ -247,6 +247,6 @@ bool write_packet(vpn_packet_t *packet) { void dump_device_stats(void) { logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); - logger(LOG_DEBUG, " total bytes in: %10d", device_total_in); - logger(LOG_DEBUG, " total bytes out: %10d", device_total_out); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); } diff --git a/src/net.c b/src/net.c index 0e582364..7d44d17c 100644 --- a/src/net.c +++ b/src/net.c @@ -36,6 +36,9 @@ #include "subnet.h" #include "xalloc.h" +int contradicting_add_edge = 0; +int contradicting_del_edge = 0; + /* Purge edges and subnets of unreachable nodes. Use carefully. */ void purge(void) { @@ -189,6 +192,19 @@ static void timeout_handler(int fd, short events, void *event) { } } + if(contradicting_del_edge && contradicting_add_edge) { + logger(LOG_WARNING, "Possible node with same Name as us!"); + + if(rand() % 3 == 0) { + logger(LOG_ERR, "Shutting down, check configuration of all nodes for duplicate Names!"); + event_loopexit(NULL); + return; + } + + contradicting_add_edge = 0; + contradicting_del_edge = 0; + } + event_add(event, &(struct timeval){pingtimeout, 0}); } @@ -275,6 +291,7 @@ int reload_configuration(void) { if(strictsubnets) { subnet_t *subnet; + for(node = subnet_tree->head; node; node = node->next) { subnet = node->data; subnet->expires = 1; diff --git a/src/net.h b/src/net.h index cd97e301..f53c27a4 100644 --- a/src/net.h +++ b/src/net.h @@ -114,6 +114,8 @@ extern int listen_sockets; extern int keylifetime; extern bool do_prune; extern char *myport; +extern int contradicting_add_edge; +extern int contradicting_del_edge; /* Yes, very strange placement indeed, but otherwise the typedefs get all tangled up */ #include "connection.h" diff --git a/src/net_packet.c b/src/net_packet.c index 46d4e1a0..b444bc93 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -2,6 +2,7 @@ net_packet.c -- Handles in- and outgoing VPN packets Copyright (C) 1998-2005 Ivo Timmermans, 2000-2010 Guus Sliepen + 2010 Timothy Redaelli This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -356,7 +357,9 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { vpn_packet_t *outpkt; int origlen; size_t outlen; +#if defined(SOL_IP) && defined(IP_TOS) static int priority = 0; +#endif int origpriority; int sock; diff --git a/src/net_setup.c b/src/net_setup.c index 198da3df..9c188957 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -89,7 +89,7 @@ bool read_rsa_private_key() { /* First, check for simple PrivateKey statement */ if(get_config_string(lookup_config(config_tree, "PrivateKey"), &d)) { - if(!get_config_string(lookup_config(myself->connection->config_tree, "PublicKey"), &n)) { + if(!get_config_string(lookup_config(config_tree, "PublicKey"), &n)) { logger(LOG_ERR, "PrivateKey used but no PublicKey found!"); free(d); return false; @@ -223,6 +223,7 @@ bool setup_myself(void) { config_t *cfg; subnet_t *subnet; char *name, *hostname, *mode, *afname, *cipher, *digest; + char *fname = NULL; char *address = NULL; char *envp[5]; struct addrinfo *ai, *aip, hint = {0}; @@ -231,7 +232,6 @@ bool setup_myself(void) { myself = new_node(); myself->connection = new_connection(); - init_configuration(&myself->connection->config_tree); myself->hostname = xstrdup("MYSELF"); myself->connection->hostname = xstrdup("MYSELF"); @@ -252,17 +252,15 @@ bool setup_myself(void) { myself->name = name; myself->connection->name = xstrdup(name); - - if(!read_connection_config(myself->connection)) { - logger(LOG_ERR, "Cannot open host configuration file for myself!"); - return false; - } + xasprintf(&fname, "%s/hosts/%s", confbase, name); + read_config_options(config_tree, name); + read_config_file(config_tree, fname); + free(fname); if(!read_rsa_private_key()) return false; - if(!get_config_string(lookup_config(config_tree, "Port"), &myport) - && !get_config_string(lookup_config(myself->connection->config_tree, "Port"), &myport)) + if(!get_config_string(lookup_config(config_tree, "Port"), &myport)) myport = xstrdup("655"); if(!atoi(myport)) { @@ -277,7 +275,7 @@ bool setup_myself(void) { /* Read in all the subnets specified in the host configuration file */ - cfg = lookup_config(myself->connection->config_tree, "Subnet"); + cfg = lookup_config(config_tree, "Subnet"); while(cfg) { if(!get_config_subnet(cfg, &subnet)) @@ -285,7 +283,7 @@ bool setup_myself(void) { subnet_add(myself, subnet); - cfg = lookup_config_next(myself->connection->config_tree, cfg); + cfg = lookup_config_next(config_tree, cfg); } /* Check some options */ @@ -296,12 +294,6 @@ bool setup_myself(void) { if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice) && choice) myself->options |= OPTION_TCPONLY; - if(get_config_bool(lookup_config(myself->connection->config_tree, "IndirectData"), &choice) && choice) - myself->options |= OPTION_INDIRECT; - - if(get_config_bool(lookup_config(myself->connection->config_tree, "TCPOnly"), &choice) && choice) - myself->options |= OPTION_TCPONLY; - if(myself->options & OPTION_TCPONLY) myself->options |= OPTION_INDIRECT; @@ -339,14 +331,12 @@ bool setup_myself(void) { } choice = true; - get_config_bool(lookup_config(myself->connection->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(myself->connection->config_tree, "ClampMSS"), &choice); if(choice) myself->options |= OPTION_CLAMP_MSS; @@ -386,7 +376,7 @@ bool setup_myself(void) { /* Generate packet encryption key */ - if(!get_config_string(lookup_config(myself->connection->config_tree, "Cipher"), &cipher)) + if(!get_config_string(lookup_config(config_tree, "Cipher"), &cipher)) cipher = xstrdup("blowfish"); if(!cipher_open_by_name(&myself->incipher, cipher)) { @@ -405,7 +395,7 @@ bool setup_myself(void) { digest = xstrdup("sha1"); int maclength = 4; - get_config_int(lookup_config(myself->connection->config_tree, "MACLength"), &maclength); + get_config_int(lookup_config(config_tree, "MACLength"), &maclength); if(maclength < 0) { logger(LOG_ERR, "Bogus MAC length!"); @@ -419,7 +409,7 @@ bool setup_myself(void) { /* Compression */ - if(get_config_int(lookup_config(myself->connection->config_tree, "Compression"), &myself->incompression)) { + if(get_config_int(lookup_config(config_tree, "Compression"), &myself->incompression)) { if(myself->incompression < 0 || myself->incompression > 11) { logger(LOG_ERR, "Bogus compression level!"); return false; diff --git a/src/net_socket.c b/src/net_socket.c index 4fe65161..44d7f771 100644 --- a/src/net_socket.c +++ b/src/net_socket.c @@ -69,12 +69,12 @@ static void configure_tcp(connection_t *c) { #if defined(SOL_TCP) && defined(TCP_NODELAY) option = 1; - setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof option); + setsockopt(c->socket, SOL_TCP, TCP_NODELAY, (void *)&option, sizeof option); #endif #if defined(SOL_IP) && defined(IP_TOS) && defined(IPTOS_LOWDELAY) option = IPTOS_LOWDELAY; - setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof option); + setsockopt(c->socket, SOL_IP, IP_TOS, (void *)&option, sizeof option); #endif } @@ -94,7 +94,7 @@ static bool bind_to_interface(int sd) { strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ); ifr.ifr_ifrn.ifrn_name[IFNAMSIZ - 1] = 0; - status = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)); + status = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)); if(status) { logger(LOG_ERR, "Can't bind to interface %s: %s", iface, strerror(errno)); @@ -180,11 +180,11 @@ int setup_listen_socket(const sockaddr_t *sa) { /* Optimize TCP settings */ option = 1; - setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof option); + setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof option); #if defined(SOL_IPV6) && defined(IPV6_V6ONLY) if(sa->sa.sa_family == AF_INET6) - setsockopt(nfd, SOL_IPV6, IPV6_V6ONLY, &option, sizeof option); + setsockopt(nfd, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option); #endif if(get_config_string @@ -195,7 +195,7 @@ int setup_listen_socket(const sockaddr_t *sa) { memset(&ifr, 0, sizeof ifr); strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ); - if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof ifr)) { + if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof ifr)) { closesocket(nfd); logger(LOG_ERR, "Can't bind to interface %s: %s", iface, strerror(sockerrno)); @@ -258,11 +258,11 @@ int setup_vpn_in_socket(const sockaddr_t *sa) { #endif option = 1; - setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof option); + setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof option); #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) if(sa->sa.sa_family == AF_INET6) - setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, &option, sizeof option); + setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option); #endif #if defined(IP_DONTFRAG) && !defined(IP_DONTFRAGMENT) @@ -272,12 +272,12 @@ int setup_vpn_in_socket(const sockaddr_t *sa) { #if defined(SOL_IP) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) if(myself->options & OPTION_PMTU_DISCOVERY) { option = IP_PMTUDISC_DO; - setsockopt(nfd, SOL_IP, IP_MTU_DISCOVER, &option, sizeof(option)); + setsockopt(nfd, SOL_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option)); } #elif defined(IPPROTO_IP) && defined(IP_DONTFRAGMENT) if(myself->options & OPTION_PMTU_DISCOVERY) { option = 1; - setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, &option, sizeof(option)); + setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, (void *)&option, sizeof(option)); } #else #warning No way to disable IPv4 fragmentation @@ -286,12 +286,12 @@ int setup_vpn_in_socket(const sockaddr_t *sa) { #if defined(SOL_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) if(myself->options & OPTION_PMTU_DISCOVERY) { option = IPV6_PMTUDISC_DO; - setsockopt(nfd, SOL_IPV6, IPV6_MTU_DISCOVER, &option, sizeof(option)); + setsockopt(nfd, SOL_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option)); } #elif defined(IPPROTO_IPV6) && defined(IPV6_DONTFRAG) if(myself->options & OPTION_PMTU_DISCOVERY) { option = 1; - setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, &option, sizeof(option)); + setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, (void *)&option, sizeof(option)); } #else #warning No way to disable IPv6 fragmentation @@ -409,7 +409,7 @@ begin: #if defined(SOL_IPV6) && defined(IPV6_V6ONLY) int option = 1; if(c->address.sa.sa_family == AF_INET6) - setsockopt(c->socket, SOL_IPV6, IPV6_V6ONLY, &option, sizeof option); + setsockopt(c->socket, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option); #endif bind_to_interface(c->socket); diff --git a/src/process.c b/src/process.c index 09fd63e1..77454f75 100644 --- a/src/process.c +++ b/src/process.c @@ -40,7 +40,9 @@ extern char *identname; extern char **g_argv; extern bool use_logfile; +#ifndef HAVE_MINGW sigset_t emptysigset; +#endif static void memory_full(int size) { logger(LOG_ERR, "Memory exhausted (couldn't allocate %d bytes), exitting.", size); diff --git a/src/process.h b/src/process.h index 740f7c7c..ea7815eb 100644 --- a/src/process.h +++ b/src/process.h @@ -29,4 +29,8 @@ extern bool execute_script(const char *, char **); extern bool detach(void); extern bool kill_other(int); +#ifdef HAVE_MINGW +extern bool init_service(void); +#endif + #endif /* __TINC_PROCESS_H__ */ diff --git a/src/protocol_auth.c b/src/protocol_auth.c index ca9e86b8..60590961 100644 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@ -452,7 +452,7 @@ bool ack_h(connection_t *c, char *request) { if(get_config_int(lookup_config(c->config_tree, "PMTU"), &mtu) && mtu < n->mtu) n->mtu = mtu; - if(get_config_int(lookup_config(myself->connection->config_tree, "PMTU"), &mtu) && mtu < n->mtu) + if(get_config_int(lookup_config(config_tree, "PMTU"), &mtu) && mtu < n->mtu) n->mtu = mtu; if(get_config_bool(lookup_config(c->config_tree, "ClampMSS"), &choice)) { diff --git a/src/protocol_edge.c b/src/protocol_edge.c index 4aad53f0..1dd68d5e 100644 --- a/src/protocol_edge.c +++ b/src/protocol_edge.c @@ -133,6 +133,7 @@ bool add_edge_h(connection_t *c, char *request) { } else if(from == myself) { ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for ourself which does not exist", "ADD_EDGE", c->name, c->hostname); + contradicting_add_edge++; e = new_edge(); e->from = from; e->to = to; @@ -229,6 +230,7 @@ bool del_edge_h(connection_t *c, char *request) { if(e->from == myself) { ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for ourself", "DEL_EDGE", c->name, c->hostname); + contradicting_del_edge++; send_add_edge(c, e); /* Send back a correction */ return true; } diff --git a/src/protocol_key.c b/src/protocol_key.c index 4187538b..f57dc2ea 100644 --- a/src/protocol_key.c +++ b/src/protocol_key.c @@ -216,7 +216,7 @@ bool ans_key_h(connection_t *c, char *request) { return true; } - if(!*address) { + if(!*address && from->address.sa.sa_family != AF_UNSPEC) { char *address, *port; ifdebug(PROTOCOL) logger(LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name); sockaddr2str(&from->address, &address, &port); diff --git a/src/raw_socket/device.c b/src/raw_socket/device.c index 0ee7cc20..66d63487 100644 --- a/src/raw_socket/device.c +++ b/src/raw_socket/device.c @@ -35,8 +35,8 @@ char *iface = NULL; static char ifrname[IFNAMSIZ]; static char *device_info; -static int device_total_in = 0; -static int device_total_out = 0; +static uint64_t device_total_in = 0; +static uint64_t device_total_out = 0; bool setup_device(void) { struct ifreq ifr; @@ -123,6 +123,6 @@ bool write_packet(vpn_packet_t *packet) { void dump_device_stats(void) { logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); - logger(LOG_DEBUG, " total bytes in: %10d", device_total_in); - logger(LOG_DEBUG, " total bytes out: %10d", device_total_out); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); } diff --git a/src/solaris/device.c b/src/solaris/device.c index 8221b9fd..d257ffdd 100644 --- a/src/solaris/device.c +++ b/src/solaris/device.c @@ -38,8 +38,8 @@ char *device = NULL; char *iface = NULL; static char *device_info = NULL; -static int device_total_in = 0; -static int device_total_out = 0; +static uint64_t device_total_in = 0; +static uint64_t device_total_out = 0; bool setup_device(void) { int ip_fd = -1, if_fd = -1; @@ -163,6 +163,6 @@ bool write_packet(vpn_packet_t *packet) { void dump_device_stats(void) { logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); - logger(LOG_DEBUG, " total bytes in: %10d", device_total_in); - logger(LOG_DEBUG, " total bytes out: %10d", device_total_out); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); } diff --git a/src/tincd.c b/src/tincd.c index 21623647..c4750da2 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -4,6 +4,8 @@ 2000-2010 Guus Sliepen 2008 Max Rijevski 2009 Michael Tokarev + 2010 Julien Muchembled + 2010 Timothy Redaelli This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -111,6 +113,7 @@ static struct option const long_options[] = { #ifdef HAVE_MINGW static struct WSAData wsa_state; CRITICAL_SECTION mutex; +int main2(int argc, char **argv); #endif static void usage(bool status) { @@ -127,6 +130,7 @@ static void usage(bool status) { " --logfile[=FILENAME] Write log entries to a logfile.\n" " --controlcookie=FILENAME Write control socket cookie to FILENAME.\n" " --bypass-security Disables meta protocol security, for debugging.\n" + " -o [HOST.]KEY=VALUE Set global/host configuration value.\n" " -R, --chroot chroot to NET dir at startup.\n" " -U, --user=USER setuid to given USER at startup.\n" " --help Display this help and exit.\n" " --version Output version information and exit.\n\n"); @@ -135,10 +139,14 @@ static void usage(bool status) { } static bool parse_options(int argc, char **argv) { + config_t *cfg; int r; int option_index = 0; + int lineno = 0; - while((r = getopt_long(argc, argv, "c:DLd::n:RU:", long_options, &option_index)) != EOF) { + cmdline_conf = list_alloc((list_action_t)free_config); + + while((r = getopt_long(argc, argv, "c:DLd::n:o:RU:", long_options, &option_index)) != EOF) { switch (r) { case 0: /* long option */ break; @@ -168,7 +176,16 @@ static bool parse_options(int argc, char **argv) { break; case 'n': /* net name given */ - netname = xstrdup(optarg); + /* netname "." is special: a "top-level name" */ + netname = strcmp(optarg, ".") != 0 ? + xstrdup(optarg) : NULL; + break; + + case 'o': /* option */ + cfg = parse_config_line(optarg, NULL, ++lineno); + if (!cfg) + return false; + list_insert_tail(cmdline_conf, cfg); break; case 'R': /* chroot to NETNAME dir */ @@ -431,13 +448,25 @@ int main2(int argc, char **argv) { char *priority = 0; if(get_config_string(lookup_config(config_tree, "ProcessPriority"), &priority)) { - if(!strcasecmp(priority, "Normal")) - setpriority(NORMAL_PRIORITY_CLASS); - else if(!strcasecmp(priority, "Low")) - setpriority(BELOW_NORMAL_PRIORITY_CLASS); - else if(!strcasecmp(priority, "High")) - setpriority(HIGH_PRIORITY_CLASS); - else { + if(!strcasecmp(priority, "Normal")) { + if (setpriority(NORMAL_PRIORITY_CLASS) != 0) { + logger(LOG_ERR, "System call `%s' failed: %s", + "setpriority", strerror(errno)); + goto end; + } + } else if(!strcasecmp(priority, "Low")) { + if (setpriority(BELOW_NORMAL_PRIORITY_CLASS) != 0) { + logger(LOG_ERR, "System call `%s' failed: %s", + "setpriority", strerror(errno)); + goto end; + } + } else if(!strcasecmp(priority, "High")) { + if (setpriority(HIGH_PRIORITY_CLASS) != 0) { + logger(LOG_ERR, "System call `%s' failed: %s", + "setpriority", strerror(errno)); + goto end; + } + } else { logger(LOG_ERR, "Invalid priority `%s`!", priority); goto end; } diff --git a/src/uml_socket/device.c b/src/uml_socket/device.c index ddb4563b..e9b07663 100644 --- a/src/uml_socket/device.c +++ b/src/uml_socket/device.c @@ -41,8 +41,8 @@ static char *device_info; extern char *identname; extern bool running; -static int device_total_in = 0; -static int device_total_out = 0; +static uint64_t device_total_in = 0; +static uint64_t device_total_out = 0; enum request_type { REQ_NEW_CONTROL }; @@ -272,6 +272,6 @@ bool write_packet(vpn_packet_t *packet) { void dump_device_stats(void) { logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); - logger(LOG_DEBUG, " total bytes in: %10d", device_total_in); - logger(LOG_DEBUG, " total bytes out: %10d", device_total_out); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); }