From c94ede3b8708cdf105a3fecfc119a558e1583f27 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sat, 1 May 2010 15:37:11 +0200 Subject: [PATCH 01/23] Define WINVER before including any other header file on Windows. --- have.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/have.h b/have.h index cf5c173a..923e76ab 100644 --- a/have.h +++ b/have.h @@ -21,6 +21,14 @@ #ifndef __TINC_HAVE_H__ #define __TINC_HAVE_H__ +#ifdef HAVE_MINGW +#ifdef WITH_WINDOWS2000 +#define WINVER Windows2000 +#else +#define WINVER WindowsXP +#endif +#endif + #include #include #include @@ -32,11 +40,6 @@ #include #ifdef HAVE_MINGW -#ifdef WITH_WINDOWS2000 -#define WINVER Windows2000 -#else -#define WINVER WindowsXP -#endif #include #include #include From 0fdd7da52077d77a11a3646eb3e7d5b6ffa178e8 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sat, 1 May 2010 15:38:04 +0200 Subject: [PATCH 02/23] Use intptr_t instead of long to store a pointer. --- lib/memcmp.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/memcmp.c b/lib/memcmp.c index 9d808338..8103e1a7 100644 --- a/lib/memcmp.c +++ b/lib/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) From ef92a5725c47c6e8e801e07190dd7dd3f9cb3a17 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sat, 1 May 2010 15:39:03 +0200 Subject: [PATCH 03/23] OpenSSL 1.0.0 compiled for 64 bit Windows requires linking with -lcrypt32. --- m4/openssl.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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.])] ) ;; From f5122ccecee095b9185b2324dea7bcd9655462ee Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sat, 1 May 2010 15:39:59 +0200 Subject: [PATCH 04/23] Fix all warnings when compiling with mingw64. --- src/logger.c | 2 +- src/net.c | 2 +- src/net_socket.c | 26 +++++++++++++------------- src/process.c | 2 ++ src/process.h | 4 ++++ src/tincd.c | 1 + 6 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/logger.c b/src/logger.c index a1cc2073..bc20438c 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/net.c b/src/net.c index a04ba005..64bca947 100644 --- a/src/net.c +++ b/src/net.c @@ -297,7 +297,7 @@ static void check_network_activity(fd_set * readset, fd_set * writeset) { if(FD_ISSET(c->socket, readset)) { if(c->status.connecting) { c->status.connecting = false; - getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &result, &len); + getsockopt(c->socket, SOL_SOCKET, SO_ERROR, (void *)&result, &len); if(!result) finish_connecting(c); diff --git a/src/net_socket.c b/src/net_socket.c index 96e268fa..762c0a22 100644 --- a/src/net_socket.c +++ b/src/net_socket.c @@ -70,12 +70,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 } @@ -95,7 +95,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)); @@ -181,11 +181,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 @@ -196,7 +196,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)); @@ -259,11 +259,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) @@ -273,12 +273,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 @@ -287,12 +287,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 @@ -410,7 +410,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 6d0e499a..f2fff1dc 100644 --- a/src/process.c +++ b/src/process.c @@ -43,7 +43,9 @@ extern char **g_argv; extern bool use_logfile; extern volatile bool running; +#ifndef HAVE_MINGW sigset_t emptysigset; +#endif static int saved_debug_level = -1; diff --git a/src/process.h b/src/process.h index bb42cd0f..8d2d5621 100644 --- a/src/process.h +++ b/src/process.h @@ -30,4 +30,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/tincd.c b/src/tincd.c index 3debb3e4..e1eb3b3d 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -118,6 +118,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) { From df985256a766ee90f2fa4269b95fa0565c969dda Mon Sep 17 00:00:00 2001 From: Timothy Redaelli Date: Tue, 4 May 2010 00:27:44 +0200 Subject: [PATCH 05/23] Fix warnings showed using -D_FORTIFY_SOURCE=2 --- src/tincd.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/tincd.c b/src/tincd.c index e1eb3b3d..70aa6ba3 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -595,13 +595,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; } From eda71798749e8b0abf5e8b3cbc11da82aa607f00 Mon Sep 17 00:00:00 2001 From: Timothy Redaelli Date: Tue, 4 May 2010 15:43:48 +0200 Subject: [PATCH 06/23] Fix warnings under BSD --- lib/getopt.c | 26 ++++++++++++++++---------- src/net_packet.c | 2 ++ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/lib/getopt.c b/lib/getopt.c index b2f88b42..a6782ed6 100644 --- a/lib/getopt.c +++ b/lib/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/net_packet.c b/src/net_packet.c index a438d3e9..cf5fb939 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -365,7 +365,9 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { vpn_packet_t *outpkt; int origlen; int outlen, outpad; +#if defined(SOL_IP) && defined(IP_TOS) static int priority = 0; +#endif int origpriority; int sock; From dbf3d168b720045328d476f3b9e5f5e45b4ab6de Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Fri, 7 May 2010 12:24:49 +0200 Subject: [PATCH 07/23] Use strrchr() insteaad of rindex(). The latter function is deprecated, some build environments do not support. --- src/bsd/device.c | 2 +- src/linux/device.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bsd/device.c b/src/bsd/device.c index c2cd34cb..6674abd2 100644 --- a/src/bsd/device.c +++ b/src/bsd/device.c @@ -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")) diff --git a/src/linux/device.c b/src/linux/device.c index 35c66d55..6363b126 100644 --- a/src/linux/device.c +++ b/src/linux/device.c @@ -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); From 4a21aabada23d1d2c8a10f54dd7248171c4ec82f Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Fri, 4 Jun 2010 14:53:52 +0200 Subject: [PATCH 08/23] Detect and prevent two nodes with the same Name being on the VPN simultaneously. In this situation, the two nodes will start fighting over the edges they announced. When we have to contradict both ADD_EDGE and DEL_EDGE messages, we log a warning, and with 25% chance per PingTimeout we quit. --- src/net.c | 15 +++++++++++++++ src/net.h | 2 ++ src/protocol_edge.c | 2 ++ 3 files changed, 19 insertions(+) diff --git a/src/net.c b/src/net.c index 64bca947..ee58ac0a 100644 --- a/src/net.c +++ b/src/net.c @@ -44,6 +44,8 @@ bool do_purge = false; volatile bool running = false; time_t now = 0; +int contradicting_add_edge = 0; +int contradicting_del_edge = 0; /* Purge edges and subnets of unreachable nodes. Use carefully. */ @@ -415,6 +417,19 @@ int main_loop(void) { send_key_changed(broadcast, myself); keyexpires = now + keylifetime; } + + 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!"); + running = false; + break; + } + + contradicting_add_edge = 0; + contradicting_del_edge = 0; + } } if(sigalrm) { diff --git a/src/net.h b/src/net.h index a97759fc..eae979cd 100644 --- a/src/net.h +++ b/src/net.h @@ -115,6 +115,8 @@ extern bool do_prune; extern bool do_purge; extern char *myport; extern time_t now; +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/protocol_edge.c b/src/protocol_edge.c index 300333b6..32102d27 100644 --- a/src/protocol_edge.c +++ b/src/protocol_edge.c @@ -133,6 +133,7 @@ bool add_edge_h(connection_t *c) { } 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) { 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; } From 798fa2f04c52b0639713f74b1195847bec40c16a Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Fri, 4 Jun 2010 15:04:08 +0200 Subject: [PATCH 09/23] Use 64 bit counters to keep track of bytes sent/received from the virtual network interface. --- src/bsd/device.c | 8 ++++---- src/cygwin/device.c | 8 ++++---- src/dummy/device.c | 8 ++++---- src/linux/device.c | 8 ++++---- src/mingw/device.c | 8 ++++---- src/raw_socket/device.c | 8 ++++---- src/solaris/device.c | 8 ++++---- src/uml_socket/device.c | 8 ++++---- 8 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/bsd/device.c b/src/bsd/device.c index 6674abd2..e8fdc1bc 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) @@ -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/cygwin/device.c b/src/cygwin/device.c index 958184bd..90966cd2 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/linux/device.c b/src/linux/device.c index 6363b126..6c828c01 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; @@ -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/mingw/device.c b/src/mingw/device.c index c0f5d296..cbaa19e5 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/raw_socket/device.c b/src/raw_socket/device.c index 30bb1845..f68e4619 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 e26dc06c..9018c31a 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/uml_socket/device.c b/src/uml_socket/device.c index 3523f647..59551b4f 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); } From 4b6a9f1c1f645ce5989692655337d9e23ca28648 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Fri, 4 Jun 2010 16:03:19 +0200 Subject: [PATCH 10/23] Do not append an address to ANS_KEY messages if we don't know any address. This would let tinc raise an exception when an ANS_KEY request crossed a DEL_EDGE request for the node sending the key. --- src/protocol_key.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocol_key.c b/src/protocol_key.c index 67f40af4..22692bb6 100644 --- a/src/protocol_key.c +++ b/src/protocol_key.c @@ -229,7 +229,7 @@ bool ans_key_h(connection_t *c) { 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); From 8c3105283ac53f8cc9cc4dde25957ec1cf6b53a0 Mon Sep 17 00:00:00 2001 From: Julien Muchembled Date: Fri, 3 Sep 2010 13:34:22 +0200 Subject: [PATCH 11/23] New '-o' option to configure server or hosts from command line Options given on the command line have precedence over configuration from files. This can be useful, for example, for a roaming node, for which 'ConnectTo' and .Address depends on its location. --- src/conf.c | 92 ++++++++++++++++++++++++++++++++---------------- src/conf.h | 3 ++ src/connection.c | 15 ++++++++ src/tincd.c | 14 +++++++- 4 files changed, 92 insertions(+), 32 deletions(-) diff --git a/src/conf.c b/src/conf.c index ea33e9c3..dc5d2dc2 100644 --- a/src/conf.c +++ b/src/conf.c @@ -36,6 +36,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 +47,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(avl_tree_t ** config_tree) { @@ -87,7 +94,7 @@ config_t *lookup_config(avl_tree_t *config_tree, char *variable) { config_t cfg, *found; cfg.variable = variable; - cfg.file = ""; + cfg.file = NULL; cfg.line = 0; found = avl_search_closest_greater(config_tree, &cfg); @@ -233,6 +240,45 @@ 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. @@ -241,9 +287,7 @@ bool read_config_file(avl_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 +324,9 @@ bool read_config_file(avl_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); } @@ -317,9 +336,20 @@ bool read_config_file(avl_tree_t *config_tree, const char *fname) { } bool read_server_config() { + list_node_t *node, *next; char *fname; bool x; + for(node = cmdline_conf->tail; node; node = next) { + config_t *cfg = (config_t *)node->data; + next = node->prev; + if (!strchr(cfg->variable, '.')) { + config_add(config_tree, cfg); + node->data = NULL; + list_unlink_node(cmdline_conf, node); + } + } + xasprintf(&fname, "%s/tinc.conf", confbase); x = read_config_file(config_tree, fname); diff --git a/src/conf.h b/src/conf.h index dae4eab8..a7e42d3c 100644 --- a/src/conf.h +++ b/src/conf.h @@ -22,6 +22,7 @@ #define __TINC_CONF_H__ #include "avl_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(avl_tree_t **); extern void exit_configuration(avl_tree_t **); @@ -54,6 +56,7 @@ 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 config_t *parse_config_line(char *, const char *, int); extern bool read_config_file(avl_tree_t *, const char *); extern bool read_server_config(void); extern FILE *ask_and_open(const char *, const char *); diff --git a/src/connection.c b/src/connection.c index 6229e79d..36c0fdbc 100644 --- a/src/connection.c +++ b/src/connection.c @@ -129,9 +129,24 @@ void dump_connections(void) { } bool read_connection_config(connection_t *c) { + list_node_t *node, *next; + size_t name_len = strlen(c->name); char *fname; bool x; + for(node = cmdline_conf->tail; node; node = next) { + config_t *cfg = (config_t *)node->data; + next = node->prev; + if (!strncmp(c->name, cfg->variable, name_len) && cfg->variable[name_len] == '.') { + config_t *new_cfg = new_config(); + new_cfg->variable = xstrdup(cfg->variable + name_len + 1); + new_cfg->value = xstrdup(cfg->value); + new_cfg->file = NULL; + new_cfg->line = cfg->line; + config_add(c->config_tree, new_cfg); + } + } + xasprintf(&fname, "%s/hosts/%s", confbase, c->name); x = read_config_file(c->config_tree, fname); free(fname); diff --git a/src/tincd.c b/src/tincd.c index 70aa6ba3..dc9bf469 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -136,6 +136,7 @@ static void usage(bool status) { " -L, --mlock Lock tinc into main memory.\n" " --logfile[=FILENAME] Write log entries to a logfile.\n" " --pidfile=FILENAME Write PID to FILENAME.\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" @@ -145,10 +146,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::k::n:K::RU:", long_options, &option_index)) != EOF) { + cmdline_conf = list_alloc((list_action_t)free_config); + + while((r = getopt_long(argc, argv, "c:DLd::k::n:o:K::RU:", long_options, &option_index)) != EOF) { switch (r) { case 0: /* long option */ break; @@ -217,6 +222,13 @@ static bool parse_options(int argc, char **argv) { netname = xstrdup(optarg); break; + case 'o': /* option */ + cfg = parse_config_line(optarg, NULL, ++lineno); + if (!cfg) + return false; + list_insert_tail(cmdline_conf, cfg); + break; + case 'K': /* generate public/private keypair */ if(optarg) { generate_keys = atoi(optarg); From ff71f289022ccb91abc2726f16522d55b5ccf0f6 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Fri, 22 Oct 2010 12:47:12 +0200 Subject: [PATCH 12/23] Merge local host configuration with server configuration. With some exceptions, tinc only accepted host configuration options for the local node from the corresponding host configuration file. Although this is documented, many people expect that they can also put those options in tinc.conf. Tinc now internally merges the contents of both tinc.conf and the local host configuration file. --- doc/tinc.conf.5.in | 7 +++++++ doc/tinc.texi | 7 +++++++ src/net_setup.c | 35 ++++++++++++----------------------- src/protocol_auth.c | 2 +- 4 files changed, 27 insertions(+), 24 deletions(-) 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 dd7bc625..9e0f978d 100644 --- a/doc/tinc.texi +++ b/doc/tinc.texi @@ -725,6 +725,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/src/net_setup.c b/src/net_setup.c index cb70926a..9f0fd888 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -149,7 +149,7 @@ bool read_rsa_private_key(void) { struct stat s; if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key)) { - if(!get_config_string(lookup_config(myself->connection->config_tree, "PublicKey"), &pubkey)) { + if(!get_config_string(lookup_config(config_tree, "PublicKey"), &pubkey)) { logger(LOG_ERR, "PrivateKey used but no PublicKey found!"); return false; } @@ -270,6 +270,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}; @@ -278,7 +279,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"); @@ -299,17 +299,14 @@ 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_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)) { @@ -324,7 +321,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)) @@ -332,7 +329,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 */ @@ -343,12 +340,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; @@ -386,14 +377,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; @@ -434,7 +423,7 @@ bool setup_myself(void) { /* Generate packet encryption key */ if(get_config_string - (lookup_config(myself->connection->config_tree, "Cipher"), &cipher)) { + (lookup_config(config_tree, "Cipher"), &cipher)) { if(!strcasecmp(cipher, "none")) { myself->incipher = NULL; } else { @@ -462,7 +451,7 @@ bool setup_myself(void) { /* Check if we want to use message authentication codes... */ - if(get_config_string(lookup_config(myself->connection->config_tree, "Digest"), &digest)) { + if(get_config_string(lookup_config(config_tree, "Digest"), &digest)) { if(!strcasecmp(digest, "none")) { myself->indigest = NULL; } else { @@ -478,7 +467,7 @@ bool setup_myself(void) { myself->connection->outdigest = EVP_sha1(); - if(get_config_int(lookup_config(myself->connection->config_tree, "MACLength"), &myself->inmaclength)) { + if(get_config_int(lookup_config(config_tree, "MACLength"), &myself->inmaclength)) { if(myself->indigest) { if(myself->inmaclength > myself->indigest->md_size) { logger(LOG_ERR, "MAC length exceeds size of digest!"); @@ -495,7 +484,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/protocol_auth.c b/src/protocol_auth.c index 98d5b61d..3f4fa010 100644 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@ -539,7 +539,7 @@ bool ack_h(connection_t *c) { 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)) { From 667b1bac77b134cf32c98d5dc25619e8c3303f52 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Fri, 22 Oct 2010 13:06:06 +0200 Subject: [PATCH 13/23] Remove duplicate command-line option parsing. Also fix parsing of command-line host configuration options for the local node. --- src/conf.c | 46 +++++++++++++++++++++++++++++++++++++--------- src/conf.h | 2 ++ src/connection.c | 26 -------------------------- src/connection.h | 1 - src/net_setup.c | 1 + 5 files changed, 40 insertions(+), 36 deletions(-) diff --git a/src/conf.c b/src/conf.c index dc5d2dc2..da58a455 100644 --- a/src/conf.c +++ b/src/conf.c @@ -23,6 +23,7 @@ #include "system.h" #include "avl_tree.h" +#include "connection.h" #include "conf.h" #include "logger.h" #include "netutl.h" /* for str2address */ @@ -335,20 +336,32 @@ bool read_config_file(avl_tree_t *config_tree, const char *fname) { return result; } +void read_config_options(avl_tree_t *config_tree, const char *prefix) { + list_node_t *node, *next; + size_t prefix_len = strlen(prefix); + + 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() { list_node_t *node, *next; char *fname; bool x; - for(node = cmdline_conf->tail; node; node = next) { - config_t *cfg = (config_t *)node->data; - next = node->prev; - if (!strchr(cfg->variable, '.')) { - config_add(config_tree, cfg); - node->data = NULL; - list_unlink_node(cmdline_conf, node); - } - } + read_config_options(config_tree, NULL); xasprintf(&fname, "%s/tinc.conf", confbase); x = read_config_file(config_tree, fname); @@ -362,6 +375,21 @@ bool read_server_config() { return x; } +bool read_connection_config(connection_t *c) { + list_node_t *node, *next; + size_t name_len = strlen(c->name); + 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; +} + FILE *ask_and_open(const char *filename, const char *what) { FILE *r; char *directory; diff --git a/src/conf.h b/src/conf.h index a7e42d3c..3eae4ad7 100644 --- a/src/conf.h +++ b/src/conf.h @@ -58,7 +58,9 @@ extern bool get_config_subnet(const config_t *, struct subnet_t **); extern config_t *parse_config_line(char *, const char *, int); extern bool read_config_file(avl_tree_t *, const char *); +extern void read_config_options(avl_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 *); extern bool is_safe_path(const char *); extern bool disable_old_keys(FILE *); diff --git a/src/connection.c b/src/connection.c index 36c0fdbc..ac946abe 100644 --- a/src/connection.c +++ b/src/connection.c @@ -127,29 +127,3 @@ void dump_connections(void) { logger(LOG_DEBUG, "End of connections."); } - -bool read_connection_config(connection_t *c) { - list_node_t *node, *next; - size_t name_len = strlen(c->name); - char *fname; - bool x; - - for(node = cmdline_conf->tail; node; node = next) { - config_t *cfg = (config_t *)node->data; - next = node->prev; - if (!strncmp(c->name, cfg->variable, name_len) && cfg->variable[name_len] == '.') { - config_t *new_cfg = new_config(); - new_cfg->variable = xstrdup(cfg->variable + name_len + 1); - new_cfg->value = xstrdup(cfg->value); - new_cfg->file = NULL; - new_cfg->line = cfg->line; - config_add(c->config_tree, new_cfg); - } - } - - 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 5aac4a66..05e8b4ba 100644 --- a/src/connection.h +++ b/src/connection.h @@ -111,6 +111,5 @@ extern void free_connection(connection_t *); extern void connection_add(connection_t *); extern void connection_del(connection_t *); extern void dump_connections(void); -extern bool read_connection_config(connection_t *); #endif /* __TINC_CONNECTION_H__ */ diff --git a/src/net_setup.c b/src/net_setup.c index 9f0fd888..f4e56378 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -300,6 +300,7 @@ bool setup_myself(void) { myself->name = name; myself->connection->name = xstrdup(name); xasprintf(&fname, "%s/hosts/%s", confbase, name); + read_config_options(config_tree, name); read_config_file(config_tree, fname); free(fname); From 1c2cd7ed273ee1538ff8a13d036c68aa9992c4aa Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Fri, 22 Oct 2010 13:17:42 +0200 Subject: [PATCH 14/23] Attribution for Julien Muchembled. --- AUTHORS | 1 + THANKS | 1 + src/conf.c | 3 ++- src/tincd.c | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 7c20a8df..cd409485 100644 --- a/AUTHORS +++ b/AUTHORS @@ -8,6 +8,7 @@ Significant contributions from: - Grzegorz Dymarek - Max Rijevski - Scott Lamb +- Julien Muchembled 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/src/conf.c b/src/conf.c index da58a455..f5f6c3a4 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 diff --git a/src/tincd.c b/src/tincd.c index dc9bf469..89e0c934 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -4,6 +4,7 @@ 2000-2010 Guus Sliepen 2008 Max Rijevski 2009 Michael Tokarev + 2010 Julien Muchembled 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 From c6ccbadfcf93a7bd4a88dee8ff146b4db7f85e71 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Fri, 22 Oct 2010 13:40:04 +0200 Subject: [PATCH 15/23] Attribution for Timothy Redaelli. --- AUTHORS | 1 + src/net_packet.c | 1 + src/tincd.c | 1 + 3 files changed, 3 insertions(+) diff --git a/AUTHORS b/AUTHORS index cd409485..3f1ebacf 100644 --- a/AUTHORS +++ b/AUTHORS @@ -9,6 +9,7 @@ Significant contributions from: - 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/src/net_packet.c b/src/net_packet.c index cf5fb939..44ab55d4 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 diff --git a/src/tincd.c b/src/tincd.c index 89e0c934..a8e55596 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -5,6 +5,7 @@ 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 From a08462bf845973016e061b8ca1233142d80416f6 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Fri, 22 Oct 2010 22:42:21 +0200 Subject: [PATCH 16/23] Ensure there is a newline character before a PEM key is written. --- src/tincd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tincd.c b/src/tincd.c index a8e55596..a618e63f 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -365,6 +365,7 @@ static bool keygen(int bits) { fchmod(fileno(f), 0600); #endif + fputc('\n', f); PEM_write_RSAPrivateKey(f, rsa_key, NULL, NULL, 0, NULL, NULL); fclose(f); free(filename); @@ -382,6 +383,7 @@ static bool keygen(int bits) { if(disable_old_keys(f)) fprintf(stderr, "Warning: old key(s) found and disabled.\n"); + fputc('\n', f); PEM_write_RSAPublicKey(f, rsa_key); fclose(f); free(filename); From 20ae7dd8c12390f7360eb28cc17e1b8a8a706b06 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Fri, 22 Oct 2010 22:43:50 +0200 Subject: [PATCH 17/23] Abort disabling old PEM keys on I/O errors. --- src/conf.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/conf.c b/src/conf.c index f5f6c3a4..c5467d20 100644 --- a/src/conf.c +++ b/src/conf.c @@ -459,24 +459,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; From 5f729f76f5a63114df582fc29f4189140c1e5ead Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Fri, 22 Oct 2010 22:46:44 +0200 Subject: [PATCH 18/23] Remove unused variables. These were caused by commit 667b1bac77b134cf32c98d5dc25619e8c3303f52. --- src/conf.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/conf.c b/src/conf.c index c5467d20..1b8213c4 100644 --- a/src/conf.c +++ b/src/conf.c @@ -358,7 +358,6 @@ void read_config_options(avl_tree_t *config_tree, const char *prefix) { } bool read_server_config() { - list_node_t *node, *next; char *fname; bool x; @@ -377,8 +376,6 @@ bool read_server_config() { } bool read_connection_config(connection_t *c) { - list_node_t *node, *next; - size_t name_len = strlen(c->name); char *fname; bool x; From aca70cd3c3fe787e62c618849e43f67b3870ac20 Mon Sep 17 00:00:00 2001 From: Michael Tokarev Date: Sun, 24 Oct 2010 15:23:10 +0400 Subject: [PATCH 19/23] Treat netname="." in a special way. Treat netname "." in a special way as if there was no netname specified. Before, f.e. tincd -n. -k didn't work as it tried to open /var/run/tinc-.pid. Now -n. works as if there was no -n option is specified. Signed-Off-By: Michael Tokarev --- src/tincd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tincd.c b/src/tincd.c index a618e63f..3dab9a01 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -221,7 +221,9 @@ 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 */ From a91bf2dfcd0f5857905e59da7d944654e0875503 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 2 Nov 2010 14:18:35 +0100 Subject: [PATCH 20/23] Quit when there are too many consecutive errors on the tun/tap device. Although transient errors sometimes happen on the tun/tap device (for example, if the kernel is temporarily out of buffer space), there are situations where the tun/tap device becomes permanently broken. Instead of endlessly spamming the syslog, we now sleep an increasing amount of time between consecutive read errors, and if reads still fail after 10 attempts (approximately 3 seconds), tinc will quit. --- src/net.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/net.c b/src/net.c index ee58ac0a..bed779a5 100644 --- a/src/net.c +++ b/src/net.c @@ -280,12 +280,21 @@ static void check_network_activity(fd_set * readset, fd_set * writeset) { int result, i; socklen_t len = sizeof(result); vpn_packet_t packet; + int errors = 0; /* check input from kernel */ if(device_fd >= 0 && FD_ISSET(device_fd, readset)) { if(read_packet(&packet)) { + errors = 0; packet.priority = 0; route(myself, &packet); + } else { + usleep(errors * 50000); + errors++; + if(errors > 10) { + logger(LOG_ERR, "Too many errors from %s, exiting!", device); + running = false; + } } } From 66b7aea294896a99df289231143a506b422b994c Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 2 Nov 2010 14:23:43 +0100 Subject: [PATCH 21/23] Read error counter must be static. --- src/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net.c b/src/net.c index bed779a5..08e3cad3 100644 --- a/src/net.c +++ b/src/net.c @@ -280,7 +280,7 @@ static void check_network_activity(fd_set * readset, fd_set * writeset) { int result, i; socklen_t len = sizeof(result); vpn_packet_t packet; - int errors = 0; + static int errors = 0; /* check input from kernel */ if(device_fd >= 0 && FD_ISSET(device_fd, readset)) { From a07aa92176571eb7f063708640d0d486280808ef Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Fri, 12 Nov 2010 11:33:01 +0100 Subject: [PATCH 22/23] Add short options -R and -U to the tincd(8) manpage. --- doc/tincd.8.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/tincd.8.in b/doc/tincd.8.in index b8520521..05586302 100644 --- a/doc/tincd.8.in +++ b/doc/tincd.8.in @@ -89,11 +89,11 @@ Under Windows this option will be ignored. .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. From 930bf74fbe5ce8363b6cc2ae3a3e960e910e0996 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Fri, 12 Nov 2010 11:38:05 +0100 Subject: [PATCH 23/23] Don't use strlen() on a NULL pointer. A bug introduced in commit 667b1bac77b134cf32c98d5dc25619e8c3303f52 caused tinc to crash on startup. --- src/conf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conf.c b/src/conf.c index 1b8213c4..07279531 100644 --- a/src/conf.c +++ b/src/conf.c @@ -339,7 +339,7 @@ bool read_config_file(avl_tree_t *config_tree, const char *fname) { void read_config_options(avl_tree_t *config_tree, const char *prefix) { list_node_t *node, *next; - size_t prefix_len = strlen(prefix); + size_t prefix_len = prefix ? strlen(prefix) : 0; for(node = cmdline_conf->tail; node; node = next) { config_t *cfg = (config_t *)node->data;