Import Upstream version 1.1~pre4

This commit is contained in:
Guus Sliepen 2019-08-26 13:44:50 +02:00
parent 34d5939212
commit ff64081061
48 changed files with 1739 additions and 1176 deletions

264
ChangeLog
View file

@ -1,3 +1,267 @@
commit 5b7f42bca4dbfee7a5fa2bc119f4739baaeb2f55
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Wed Dec 5 22:32:10 2012 +0100
Releasing 1.1pre4.
commit 4c16094e949e1f17461ac744118076a3cec437e8
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Wed Dec 5 21:42:43 2012 +0100
Fix whitespace.
commit 4f8abf1b29b117c5d593bfa7703966fd88e9eace
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Wed Dec 5 21:40:49 2012 +0100
Scale packet counters similar to byte counters.
commit d5f0ff5df86d06825110527ddc252b1268e31479
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Wed Dec 5 21:33:01 2012 +0100
Don't use nested functions.
This allows tinc to be compiled with Clang.
commit eb80105ea855f2c7ee0ea467574acf86cf455a77
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Wed Dec 5 14:42:21 2012 +0100
Fix compiler warnings on OpenBSD.
commit 5e3607b616538eac7bb70d78d4f20d847a1c3064
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Mon Dec 3 13:09:40 2012 +0100
Remove GraphDumpFile from the manual and manpages.
This option is not supported in tinc 1.1, "tincctl dump graph" can be used
instead.
commit a717b9bcfbe811787fd6718fb3f8fb3f272bcfb9
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Mon Dec 3 13:08:03 2012 +0100
Add option to dump only a list of reachable nodes.
commit 75c619e372f02f8225d158fd514f01bd04857d3b
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Mon Dec 3 10:41:28 2012 +0100
More fixes for Windows.
In particular, Windows does support many of the timer* macros, except timeradd
and timersub.
commit d53384c2de6d2824b9adcec111301d86e6b25f8e
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Mon Dec 3 09:08:21 2012 +0100
Fix compiler error on Windows.
commit 76816e119b7d38a14823d430aafeff362dfbfd41
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Mon Dec 3 09:07:23 2012 +0100
Fix crash in timeout handling.
commit d19b00606576d19ef206e363ac709daf3bd00f25
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Mon Dec 3 09:02:08 2012 +0100
Set a node's pointers to zero before trying to insert it into a tree.
commit d2b19be1a0dd3c4987aa926117f5bf281892c78b
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Thu Nov 29 14:35:08 2012 +0100
Fix use of unitialised values in hash tables.
Not only was Valgrind unhappy about it, it could also result in cache misses.
commit d9c70767aa6da8b62b4a1034d5f07892603beddd
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Thu Nov 29 14:32:12 2012 +0100
Fix check for expired events.
This would trigger a infinite loop if a timeout expired and the next timeout
was not expired yet, but less than 1 second from being expired.
commit 8825cddd0d8ed6dad00924ef382139da51ca3fc4
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Thu Nov 29 12:37:04 2012 +0100
Allow multiple timeouts to expire at the exact same time.
commit 6bc5d626a8726fc23365ee705761a3c666a08ad4
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Thu Nov 29 12:28:23 2012 +0100
Drop libevent and use our own event handling again.
There are several reasons for this:
- MacOS/X doesn't support polling the tap device using kqueue, requiring a
workaround to fall back to select().
- On Windows only sockets are properly handled, therefore tinc uses a second
thread that does a blocking ReadFile() on the TAP-Win32/64 device. However,
this does not mix well with libevent.
- Libevent, event just the core, is quite large, and although it is easy to get
and install on many platforms, it can be a burden.
- Libev is more lightweight and seems technically superior, but it doesn't
abstract away all the platform differences (for example, async events are not
supported on Windows).
commit d30b9e1272fef18070d37d10b2b3e4bb2fc07f59
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Mon Nov 19 14:20:50 2012 +0100
Ensure MTU probe replies are sent back the same way they came in.
Also sprinkle some comments over mtu_probe_h().
commit 3c1b7047332f4b5e9d5ae7109e696b33712a5fb2
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Mon Nov 19 13:50:17 2012 +0100
Improve UDP address selection.
We don't need to search the whole edge tree, we can use the node's own edge
tree since each edge has a pointer to its reverse. Also, we do need to make
sure we try the reflexive address often.
commit f57129ce3439f3826c12f15feb5df05e5ad8cab9
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Sat Nov 17 22:48:06 2012 +0100
Try all known addresses of node during PMTU discovery, now also for SPTPS.
commit 30404650b28bf72d0b05b55393f2dd492434f9f3
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Sat Nov 17 22:14:52 2012 +0100
Choose a suitable socket when updating a node's UDP address.
commit 8f9ee895224b39347783f3119343efc3bdaa3511
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Thu Nov 15 11:24:18 2012 +0100
Also don't use poll() on MacOS/X.
commit 8a77df9e28114cbfd83351070fdb266cf31fc310
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Thu Nov 15 11:13:40 2012 +0100
Disable support for kqueue on MacOS/X.
Apparently MacOS/X doesn't support kqueue events on character devices.
commit 818c92e6583006bf2e38f1027044925df6cf0ca0
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Wed Nov 14 10:44:35 2012 +0100
Remove text saying you must have one of PrivateKey or PrivateKeyFile in tinc.conf.
commit e8bf81794f412b27261be0f2aa4eb287352041af
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Tue Nov 13 15:05:41 2012 +0100
Send broadcast packets using a random socket, and properly support IPv6.
Before it would always use the first socket, and always send an IPv4 broadcast packet. That
works fine in a lot of situations, but it is better to try all sockets, and to send IPv6 packets
on IPv6 sockets. This is especially important for users that are on IPv6-only networks or that
have multiple physical network interfaces, although in the latter case it probably requires
them to use the ListenAddress variable to create a separate socket for each interface.
commit 0870c7c32cf8a24f234fc066df867747ddb1ddc7
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Tue Nov 13 15:01:43 2012 +0100
Don't take the address of a variable whose scope is about to disappear.
commit bb3d7f3b31d4a429d1c31c6621d82f34dd552482
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Sun Nov 11 19:01:28 2012 +0100
Fix configure script help text for --enable options.
commit 5bfbb8f6c58307a8109f556caa30be122cc4d39f
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Sun Nov 11 19:01:02 2012 +0100
Fix index entry for section about readline library.
commit 5766518589a5e6cc43ba77a4049059ead05fb300
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Sun Nov 11 18:53:23 2012 +0100
Mention in the manual that support for LZO and zlib can be disabled.
commit 6ec4596557d658f6c15c2cb9a96152c8c476118a
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Sun Nov 11 18:45:40 2012 +0100
Mention libcurses and libreadline in the manual.
commit 0ee139e91431527015b7132e4c36f8d4ec09f66b
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Sat Nov 10 23:45:22 2012 +0100
Make sure PMTU discovery works in switch mode with VLAN tags.
Before, when tinc saw a packet larger than the PMTU with a VLAN tag, it would
not know what to do with it, and would just forward it via TCP. Now, tinc
handles 802.1q packets correctly, as long as there is only one tag.
commit ade4fccad6857f3d6d548e52bc94ab23751e4fef
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Sat Nov 10 23:13:05 2012 +0100
Using alloca() for a constant sized buffer is very silly.
Cppcheck said using alloca() in the 21st century is silly anyway.
commit b355476e917f377abb6434657933fcf4ffe6870a
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Sat Nov 10 23:09:31 2012 +0100
Fix potential buffer overflow reading the PID file.
Found by cppcheck.
commit edc08b73a9e353bde6db4c73866a6a730a1a7cb4
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Sun Oct 21 17:45:16 2012 +0200
Slightly randomize all timeouts.
commit 717ea66d7ba0c23f27d86b3d5c6992b751135455
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Sun Oct 21 17:35:13 2012 +0200
Add the AutoConnect option.
When set to a non-zero value, tinc will try to maintain exactly that number of
meta connections to other nodes. If there are not enough connections, it will
periodically try to set up an outgoing connection to a random node. If there
are too many connections, it will periodically try to remove an outgoing
connection.
commit 1f8b70efa0dedbd3642e0ee82a640d125664af34
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Sun Oct 21 17:34:53 2012 +0200
Keep track of the number of nodes in a tree.
commit 0006c754f2e61e108aa2dd5a6ddd2e9b50d51bd6
Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Wed Oct 17 13:51:02 2012 +0200
Fix warnings from groff.
commit 0db9e471ea53b48687ea247c855cd95ec453530c commit 0db9e471ea53b48687ea247c855cd95ec453530c
Author: Guus Sliepen <guus@tinc-vpn.org> Author: Guus Sliepen <guus@tinc-vpn.org>
Date: Sun Oct 14 19:22:30 2012 +0200 Date: Sun Oct 14 19:22:30 2012 +0200

View file

@ -57,10 +57,9 @@ DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
THANKS config.guess config.sub depcomp install-sh missing THANKS config.guess config.sub depcomp install-sh missing
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/libevent.m4 \ $(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \
$(top_srcdir)/m4/lzo.m4 $(top_srcdir)/m4/openssl.m4 \ $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \
$(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/zlib.m4 \ $(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.in
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4) $(ACLOCAL_M4)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \

483
NEWS
View file

@ -1,3 +1,17 @@
Version 1.1pre4 December 5 2012
* Added the "AutoConnect" option which will let tinc automatically select
which nodes to connect to.
* Improved performance of VLAN-tagged IP traffic inside the VPN.
* Ensured LocalDiscovery works with multiple BindToAddress statements and/or
IPv6-only LANs.
* Dropped dependency on libevent.
* Fixed Windows version not reading packets from the TAP adapter.
Version 1.1pre3 October 14 2012 Version 1.1pre3 October 14 2012
* New experimental protocol: * New experimental protocol:
@ -41,7 +55,7 @@ Version 1.1pre1 June 25 2011
* tincctl, a commandline utility * tincctl, a commandline utility
* tinc-gui, a preliminary GUI implemented in Python/wxWidgets * tinc-gui, a preliminary GUI implemented in Python/wxWidgets
* Code cleanups and reorganization. * Code cleanups and reorganization.
* Repleacable cryptography backend, currently supports OpenSSL and libgcrypt. * Repleacable cryptography backend, currently supports OpenSSL and libgcrypt.
@ -247,13 +261,13 @@ Version 1.0.6 Dec 18 2006
* Fixed a bug where broadcasts in switch and hub modes sometimes would not * Fixed a bug where broadcasts in switch and hub modes sometimes would not
work anymore when part of the VPN had become disconnected from the rest. work anymore when part of the VPN had become disconnected from the rest.
version 1.0.5 Nov 14 2006 Version 1.0.5 Nov 14 2006
* Lots of small fixes. * Lots of small fixes.
* Broadcast packets no longer grow in size with each hop. This should * Broadcast packets no longer grow in size with each hop. This should
fix switch mode (again). fix switch mode (again).
* Generic host-up and host-down scripts. * Generic host-up and host-down scripts.
* Optionally dump graph in graphviz format to a file or a script. * Optionally dump graph in graphviz format to a file or a script.
@ -262,347 +276,354 @@ version 1.0.5 Nov 14 2006
Thanks to Scott Lamb for his contributions to this version of tinc. Thanks to Scott Lamb for his contributions to this version of tinc.
version 1.0.4 May 4 2005 Version 1.0.4 May 4 2005
* Fix switch and hub modes. * Fix switch and hub modes.
* Optionally start scripts when a Subnet becomes (un)reachable. * Optionally start scripts when a Subnet becomes (un)reachable.
version 1.0.3 Nov 11 2004 Version 1.0.3 Nov 11 2004
* Show error message when failing to write a PID file. * Show error message when failing to write a PID file.
* Ignore spaces at end of lines in config files. * Ignore spaces at end of lines in config files.
* Fix handling of late packets. * Fix handling of late packets.
* Unify BSD tun/tap device handling. This allows IPv6 on tun devices and * Unify BSD tun/tap device handling. This allows IPv6 on tun devices and
anything on tap devices as long as the underlying OS supports it. anything on tap devices as long as the underlying OS supports it.
* Handle IPv6 on Solaris tun devices. * Handle IPv6 on Solaris tun devices.
* Allow tinc to work properly under Windows XP SP2. * Allow tinc to work properly under Windows XP SP2.
* Allow VLAN tagged Ethernet frames in switch and hub mode. * Allow VLAN tagged Ethernet frames in switch and hub mode.
* Experimental PMTUDiscovery, TunnelServer and BlockingTCP options. * Experimental PMTUDiscovery, TunnelServer and BlockingTCP options.
version 1.0.2 Nov 8 2003 Version 1.0.2 Nov 8 2003
* Fix address and hostname resolving under Windows. * Fix address and hostname resolving under Windows.
* Remove warnings about non-existing scripts and unsupported address families. * Remove warnings about non-existing scripts and unsupported address families.
* Use the event logger under Windows. * Use the event logger under Windows.
* Fix quoting of filenames and command line arguments under Windows. * Fix quoting of filenames and command line arguments under Windows.
* Strict checks for length incoming network packets and return values of * Strict checks for length incoming network packets and return values of
cryptographic functions, cryptographic functions,
* Fix a bug in metadata handling that made the tinc daemon abort. * Fix a bug in metadata handling that made the tinc daemon abort.
version 1.0.1 Aug 14 2003 Version 1.0.1 Aug 14 2003
* Allow empty lines in config files. * Allow empty lines in config files.
* Fix handling of spaces and backslashes in filenames under native Windows. * Fix handling of spaces and backslashes in filenames under native Windows.
* Allow scripts to be executed under native Windows. * Allow scripts to be executed under native Windows.
* Update documentation, make it less Linux specific. * Update documentation, make it less Linux specific.
version 1.0 Aug 4 2003 Version 1.0 Aug 4 2003
* Lots of small bugfixes and code cleanups. * Lots of small bugfixes and code cleanups.
* Throughput doubled and latency reduced. * Throughput doubled and latency reduced.
* Added support for LZO compression. * Added support for LZO compression.
* No need to set MAC address or disable ARP anymore. * No need to set MAC address or disable ARP anymore.
* Added support for Windows 2000 and XP, both natively and in a Cygwin * Added support for Windows 2000 and XP, both natively and in a Cygwin
environment. environment.
version 1.0pre8 Sep 16 2002 Version 1.0pre8 Sep 16 2002
* More fixes for subnets with prefixlength undivisible by 8. * More fixes for subnets with prefixlength undivisible by 8.
* Added support for NetBSD and MacOS/X. * Added support for NetBSD and MacOS/X.
* Switched from undirected graphs to directed graphs to avoid certain race * Switched from undirected graphs to directed graphs to avoid certain race
conditions and improve scalability. conditions and improve scalability.
* Generalized broadcasting and forwarding of protocol messages. * Generalized broadcasting and forwarding of protocol messages.
* Cleanup of source code. * Cleanup of source code.
Version 1.0pre7 Apr 7 2002
version 1.0pre7 Apr 7 2002 * Don't do blocking read()s when getting a signal.
* Don't do blocking read()s when getting a signal. * Remove RSA key checking code, since it sometimes thinks perfectly good RSA
keys are bad.
* Remove RSA key checking code, since it sometimes thinks perfectly good RSA * Fix handling of subnets when prefixlength isn't divisible by 8.
keys are bad.
* Fix handling of subnets when prefixlength isn't divisible by 8. Version 1.0pre6 Mar 27 2002
* Improvement of redundant links:
* Non-blocking connects.
* Protocol broadcast messages can no longer go into an infinite loop.
* Graph algorithm updated to look harder for direct connections.
version 1.0pre6 Mar 27 2002 * Good support for routing IPv6 packets over the VPN. Works on Linux,
FreeBSD, possibly OpenBSD but not on Solaris.
* Improvement of redundant links: * Support for tunnels over IPv6 networks. Works on all supported
operating systems.
* Non-blocking connects. * Optional compression of UDP connections using zlib.
* Protocol broadcast messages can no longer go into an infinite loop.
* Graph algorithm updated to look harder for direct connections.
* Good support for routing IPv6 packets over the VPN. Works on Linux, * Optionally let UDP connections inherit TOS field of tunneled packets.
FreeBSD, possibly OpenBSD but not on Solaris.
* Support for tunnels over IPv6 networks. Works on all supported * Optionally start scripts when certain hosts become (un)reachable.
operating systems.
* Optional compression of UDP connections using zlib. Version 1.0pre5 Feb 9 2002
* Optionally let UDP connections inherit TOS field of tunneled packets. * Security enhancements:
* Added sequence number and optional message authentication code to
the packets.
* Configurable encryption cipher and digest algorithms.
* Optionally start scripts when certain hosts become (un)reachable. * More robust handling of dis- and reconnects.
* Added a "switch" and a "hub" mode to allow bridging setups.
version 1.0pre5 Feb 9 2002 * Preliminary support for routing of IPv6 packets.
* Security enhancements: * Supports Linux, FreeBSD, OpenBSD and Solaris.
* Added sequence number and optional message authentication code to Version 1.0pre4 Jan 17 2001
the packets.
* Configurable encryption cipher and digest algorithms. * Updated documentation; the documentation now reflects the
configuration as it is.
* More robust handling of dis- and reconnects. * Some internal changes to make tinc scale better for large
networks, such as using AVL trees instead of linked lists for the
connection list.
* Added a "switch" and a "hub" mode to allow bridging setups. * RSA keys can be stored in separate files if needed. See the
documentation for more information.
* Preliminary support for routing of IPv6 packets. * Tinc has now been reported to run on Linux PowerPC and FreeBSD x86.
* Supports Linux, FreeBSD, OpenBSD and Solaris. Version 1.0pre3 Oct 31 2000
* The protocol has been redesigned, and although some details are
still under discussion, this is secure. Care has been taken to
resist most, if not all, attacks.
It looks like this might be the last release before 1.0. * Unfortunately this protocol is not compatible with earlier versions,
nor are earlier versions compatible with this version. Because the
older protocol has huge security flaws, we feel that not
implementing backwards compatibility is justified.
* Some data about the protocol:
* It uses public/private RSA keys for authentication (this is the
actual fix for the security hole).
* All cryptographic functions have been taken out of tinc, instead
it uses the OpenSSL library functions.
* Offers support for multiple subnets per tinc daemon.
version 1.0pre4 Jan 17 2001 * New is also the support for the universal tun/tap device. This
means better portability to FreeBSD and Solaris.
* Updated documentation; the documentation now reflects the * Tinc is tested to compile on Solaris, Linux x86, Linux alpha.
configuration as it is.
* Some internal changes to make tinc scale better for large * Tinc now uses the OpenSSL library for cryptographic operations.
networks, such as using AVL trees instead of linked lists for the More information on getting and installing OpenSSL is in the manual.
connection list. This also means that the GMP library is no longer required.
* RSA keys can be stored in separate files if needed. See the * Further, thanks to Enrique Zanardi, we have Spanish messages; Matias
documentation for more information. Carrasco provided us with a Spanish translation of the manual.
* tinc has now been reported to run on Linux PowerPC and FreeBSD x86. Version 1.0pre2 May 31 2000
* This version has been internationalized; and a Dutch translation has
been included.
* Two configuration variables have been added:
* VpnMask - the IP network mask for the entire VPN, not just our
subnet (as given by MyVirtualIP). The Redhat and Debian packages
use this variable in their system startup scripts, but it is
ignored by tinc.
* Hostnames - if set to `yes', look up the names of IP addresses
trying to connect to us. Default set to `no', to prevent lockups
during lookups.
version 1.0pre3 Oct 31 2000 * The system startup scripts for Debian and Redhat use
/etc/tinc/nets.boot to find out which networks need to be started
during system boot.
* The protocol has been redesigned, and although some details are * Fixes to prevent denial of service attacks by sending random data
still under discussion, this is secure. Care has been taken to after connecting (and even when the connection has been established),
resist most, if not all, attacks. either random garbage or just nonsensical protocol fields.
* Unfortunately this protocol is not compatible with earlier versions,
nor are earlier versions compatible with this version. Because the
older protocol has huge security flaws, we feel that not
implementing backwards compatibility is justified.
* Some data about the protocol: * Tinc will retry to connect upon startup, does not quit if it doesn't
work the first time.
* It uses public/private RSA keys for authentication (this is the * Hosts that are disconnected implicitly if we lose a connection get
actual fix for the security hole). deleted from the internal list, to prevent hogging eachother with
add and delete requests when the connection is restored.
* All cryptographic functions have been taken out of tinc, instead Version 1.0pre1 May 12 2000
it uses the OpenSSL library functions.
* Offers support for multiple subnets per tinc daemon.
* New is also the support for the universal tun/tap device. This
means better portability to FreeBSD and Solaris.
* tinc is tested to compile on Solaris, Linux x86, Linux alpha.
* tinc now uses the OpenSSL library for cryptographic operations.
More information on getting and installing OpenSSL is in the manual.
This also means that the GMP library is no longer required.
* Further, thanks to Enrique Zanardi, we have Spanish messages; Matias
Carrasco provided us with a Spanish translation of the manual.
What still needs to be done before 1.0:
* Documentation. Especially since the protocol has changed, and a lot
of configuration directives have been added.
version 1.0pre2 May 31 2000
* This version has been internationalized; and a Dutch translation has
been included.
* Two configuration variables have been added:
* VpnMask - the IP network mask for the entire VPN, not just our
subnet (as given by MyVirtualIP). The Redhat and Debian packages
use this variable in their system startup scripts, but it is
ignored by tinc.
* Hostnames - if set to `yes', look up the names of IP addresses
trying to connect to us. Default set to `no', to prevent lockups
during lookups.
* The system startup scripts for Debian and Redhat use
/etc/tinc/nets.boot to find out which networks need to be started
during system boot.
* Fixes to prevent denial of service attacks by sending random data
after connecting (and even when the connection has been established),
either random garbage or just nonsensical protocol fields.
* tinc will retry to connect upon startup, does not quit if it doesn't
work the first time.
* Hosts that are disconnected implicitly if we lose a connection get
deleted from the internal list, to prevent hogging eachother with
add and delete requests when the connection is restored.
What still needs to be done before 1.0:
* Documentation.
* Failover ConnectTo lines, try another one if the first doesn't work.
version 1.0pre1 May 12 2000
* New meta-protocol * New meta-protocol
* Various other bugfixes * Various other bugfixes
* Documentation updates * Documentation updates
version 0.3.3 Feb 9 2000 Version 0.3.3 Feb 9 2000
* Fixed bug that made tinc stop working with latest kernels (Guus
Sliepen) * Fixed bug that made tinc stop working with latest kernels
* Updated the manual * Updated the manual
version 0.3.2 Nov 12 1999 Version 0.3.2 Nov 12 1999
* no more `Invalid filedescriptor' when working with multiple
connections
* forward unknown packets to uplink
version 0.3.1 Oct 20 1999 * No more `Invalid filedescriptor' when working with multiple
* fixed a bug where tinc would exit without a trace connections.
version 0.3 Aug 20 1999 * Forward unknown packets to uplink.
* pings now work immediately
* all packet sizes get transmitted correctly
version 0.2.26 Aug 15 1999 Version 0.3.1 Oct 20 1999
* fixed some remaining bugs
* --sysconfdir works with configure
* last version before 0.3
version 0.2.25 Aug 8 1999 * Fixed a bug where tinc would exit without a trace.
* improved stability, going towards 0.3 now.
version 0.2.24 Aug 7 1999 Version 0.3 Aug 20 1999
* added key aging, there's a new config variable, KeyExpire.
* updated man and info pages
version 0.2.23 Aug 5 1999 * Pings now work immediately.
* all known bugs fixed, this is a candidate for 0.3
version 0.2.22 Apr 11 1999 * All packet sizes get transmitted correctly.
* multiconnection thing is now working nearly perfect :)
Version 0.2.26 Aug 15 1999
* Fixed some remaining bugs.
* --sysconfdir works with configure.
* Last version before 0.3.
Version 0.2.25 Aug 8 1999
* Improved stability, going towards 0.3 now.
Version 0.2.24 Aug 7 1999
* Added key aging, there's a new config variable, KeyExpire.
* Updated man and info pages.
Version 0.2.23 Aug 5 1999
* All known bugs fixed, this is a candidate for 0.3.
Version 0.2.22 Apr 11 1999
* Multiconnection thing is now working nearly perfect :)
Version 0.2.21 Apr 10 1999
version 0.2.21 Apr 10 1999
* You shouldn't notice a thing, but a lot has changed wrt key * You shouldn't notice a thing, but a lot has changed wrt key
management - except that it refuses to talk to versions < 0.2.20 management - except that it refuses to talk to versions < 0.2.20
version 0.2.20 Version 0.2.19 Apr 3 1999
version 0.2.19 Apr 3 1999 * Don't install a libcipher.so.
* don't install a libcipher.so
version 0.2.18 Apr 3 1999 Version 0.2.18 Apr 3 1999
* blowfish library dynamically loaded upon execution
* included Eric Young's IDEA library
version 0.2.17 Apr 1 1999 * Blowfish library dynamically loaded upon execution.
* tincd now re-executes itself in case of a segmentation fault.
version 0.2.16 Apr 1 1999 * Included Eric Young's IDEA library.
* wrote tincd.conf(5) man page, which still needs a lot of work.
* config file now accepts and tolerates spaces, and any integer base
for integer variables, and better error reporting. See
doc/tincd.conf.sample for an example.
version 0.2.15 Mar 29 1999 Version 0.2.17 Apr 1 1999
* fixed bugs
version 0.2.14 Feb 10 1999 * Tincd now re-executes itself in case of a segmentation fault.
* added --timeout flag and PingTimeout configuration
* did some first syslog cleanup work
version 0.2.13 Jan 23 1999 Version 0.2.16 Apr 1 1999
* bugfixes
version 0.2.12 Jan 23 1999 * Wrote tincd.conf(5) man page, which still needs a lot of work.
* fixed nauseating bug so that it would crash whenever a connection
got lost
version 0.2.11 Jan 22 1999 * Config file now accepts and tolerates spaces, and any integer base
* framework for multiple connections has been done for integer variables, and better error reporting. See
* simple manpage for tincd doc/tincd.conf.sample for an example.
version 0.2.10 Jan 18 1999 Version 0.2.15 Mar 29 1999
* passphrase support added
version 0.2.9 Jan 13 1999 * Fixed bugs.
* bugs fixed.
version 0.2.8 Jan 11 1999 Version 0.2.14 Feb 10 1999
* a reworked protocol version
* a ping/pong system
* more reliable networking code
* automatic reconnection
* still does not work with more than one connection :)
* strips MAC addresses before sending, so there's less overhead, and
less redundancy
version 0.2.7 Jan 3 1999 * Added --timeout flag and PingTimeout configuration.
* several updates to make extending more easy. * Did some first syslog cleanup work.
Version 0.2.13 Jan 23 1999
* Bugfixes.
Version 0.2.12 Jan 23 1999
* Fixed nauseating bug so that it would crash whenever a connection
got lost.
Version 0.2.11 Jan 22 1999
* Framework for multiple connections has been done.
* Simple manpage for tincd.
Version 0.2.10 Jan 18 1999
* Passphrase support added.
Version 0.2.9 Jan 13 1999
* Bugs fixed.
Version 0.2.8 Jan 11 1999
* A reworked protocol version.
* A ping/pong system.
* More reliable networking code.
* Automatic reconnection.
* Still does not work with more than one connection :)
* Strips MAC addresses before sending, so there's less overhead, and
less redundancy.
Version 0.2.7 Jan 3 1999
* Several updates to make extending more easy.
Version 0.2.6 Dec 20 1998
version 0.2.6 Dec 20 1998
* Point-to-Point connections have been established, including * Point-to-Point connections have been established, including
blowfish encryption and a secret key-exchange. Blowfish encryption and a secret key-exchange.
Version 0.2.5 Dec 16 1998
version 0.2.5 Dec 16 1998
* Project renamed to tinc, in honour of TINC. * Project renamed to tinc, in honour of TINC.
version 0.2.4 Dec 16 1998 Version 0.2.4 Dec 16 1998
* now it really does ;)
version 0.2.3 Nov 24 1998 * Now it really does ;)
* it sort of works now
version 0.2.2 Nov 20 1998 Version 0.2.3 Nov 24 1998
* uses GNU gmp.
version 0.2.1 Nov 14 1998 * It sort of works now.
Version 0.2.2 Nov 20 1998
* Uses GNU gmp.
Version 0.2.1 Nov 14 1998
* Bare version. * Bare version.

7
README
View file

@ -1,4 +1,4 @@
This is the README file for tinc version 1.1pre3. Installation This is the README file for tinc version 1.1pre4. Installation
instructions may be found in the INSTALL file. instructions may be found in the INSTALL file.
tinc is Copyright (C) 1998-2012 by: tinc is Copyright (C) 1998-2012 by:
@ -36,11 +36,11 @@ at your own risk.
Compatibility Compatibility
------------- -------------
Version 1.1pre3 is compatible with 1.0pre8, 1.0 and later, but not with older Version 1.1pre4 is compatible with 1.0pre8, 1.0 and later, but not with older
versions of tinc. versions of tinc.
When the ExperimentalProtocol option is used, tinc is still compatible with When the ExperimentalProtocol option is used, tinc is still compatible with
1.0.X and 1.1pre3 itself, but not with any other 1.1preX version. 1.0.X and 1.1pre4 itself, but not with any other 1.1preX version.
Requirements Requirements
@ -50,7 +50,6 @@ In order to compile tinc, you will need a GNU C compiler environment. Please
ensure you have the latest stable versions of all the required libraries: ensure you have the latest stable versions of all the required libraries:
- OpenSSL (http://www.openssl.org/) version 1.0.0 or later. - OpenSSL (http://www.openssl.org/) version 1.0.0 or later.
- Libevent (http://monkey.org/~provos/libevent/)
The following libraries are used by default, but can be disabled if necessary: The following libraries are used by default, but can be disabled if necessary:

1
aclocal.m4 vendored
View file

@ -1135,7 +1135,6 @@ AC_SUBST([am__untar])
m4_include([m4/attribute.m4]) m4_include([m4/attribute.m4])
m4_include([m4/curses.m4]) m4_include([m4/curses.m4])
m4_include([m4/libevent.m4])
m4_include([m4/lzo.m4]) m4_include([m4/lzo.m4])
m4_include([m4/openssl.m4]) m4_include([m4/openssl.m4])
m4_include([m4/readline.m4]) m4_include([m4/readline.m4])

View file

@ -64,9 +64,6 @@
/* Define to 1 if you have the `ECDSA_verify' function. */ /* Define to 1 if you have the `ECDSA_verify' function. */
#undef HAVE_ECDSA_VERIFY #undef HAVE_ECDSA_VERIFY
/* Define to 1 if you have the <event.h> header file. */
#undef HAVE_EVENT_H
/* Define to 1 if you have the `EVP_EncryptInit_ex' function. */ /* Define to 1 if you have the `EVP_EncryptInit_ex' function. */
#undef HAVE_EVP_ENCRYPTINIT_EX #undef HAVE_EVP_ENCRYPTINIT_EX

112
configure vendored
View file

@ -738,7 +738,6 @@ enable_uml
enable_vde enable_vde
enable_tunemu enable_tunemu
with_windows2000 with_windows2000
with_libgcrypt
enable_curses enable_curses
with_curses with_curses
with_curses_include with_curses_include
@ -747,9 +746,6 @@ enable_readline
with_readline with_readline
with_readline_include with_readline_include
with_readline_lib with_readline_lib
with_libevent
with_libevent_include
with_libevent_lib
enable_zlib enable_zlib
with_zlib with_zlib
with_zlib_include with_zlib_include
@ -1393,9 +1389,9 @@ Optional Features:
--enable-dependency-tracking do not reject slow dependency extractors --enable-dependency-tracking do not reject slow dependency extractors
--enable-maintainer-mode enable make rules and dependencies not useful --enable-maintainer-mode enable make rules and dependencies not useful
(and sometimes confusing) to the casual installer (and sometimes confusing) to the casual installer
--disable-uml enable support for User Mode Linux --enable-uml enable support for User Mode Linux
--disable-vde enable support for Virtual Distributed Ethernet --enable-vde enable support for Virtual Distributed Ethernet
--disable-tunemu enable support for the tunemu driver --enable-tunemu enable support for the tunemu driver
--disable-curses disable curses support --disable-curses disable curses support
--disable-readline disable readline support --disable-readline disable readline support
--disable-zlib disable zlib compression support --disable-zlib disable zlib compression support
@ -1408,7 +1404,6 @@ Optional Packages:
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--without-windows2000 compile with support for Windows 2000. This disables --without-windows2000 compile with support for Windows 2000. This disables
support for tunneling over existing IPv6 networks. support for tunneling over existing IPv6 networks.
--with-libgcrypt enable use of libgcrypt instead of OpenSSL]
--with-curses=DIR curses base directory, or: --with-curses=DIR curses base directory, or:
--with-curses-include=DIR --with-curses-include=DIR
curses headers directory curses headers directory
@ -1417,10 +1412,6 @@ Optional Packages:
--with-readline-include=DIR --with-readline-include=DIR
readline headers directory readline headers directory
--with-readline-lib=DIR readline library directory --with-readline-lib=DIR readline library directory
--with-libevent=DIR libevent base directory, or:
--with-libevent-include=DIR
libevent headers directory
--with-libevent-lib=DIR libevent library directory
--with-zlib=DIR zlib base directory, or: --with-zlib=DIR zlib base directory, or:
--with-zlib-include=DIR zlib headers directory --with-zlib-include=DIR zlib headers directory
--with-zlib-lib=DIR zlib library directory --with-zlib-lib=DIR zlib library directory
@ -4104,7 +4095,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE=tinc PACKAGE=tinc
VERSION=1.1pre3 VERSION=1.1pre4
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
@ -5929,12 +5920,6 @@ rm -f confcache
# Check whether --with-libgcrypt was given.
if test "${with_libgcrypt+set}" = set; then :
withval=$with_libgcrypt;
fi
# Check whether --enable-curses was given. # Check whether --enable-curses was given.
if test "${enable_curses+set}" = set; then : if test "${enable_curses+set}" = set; then :
@ -6145,95 +6130,6 @@ fi
# Check whether --with-libevent was given.
if test "${with_libevent+set}" = set; then :
withval=$with_libevent; libevent="$withval"
CPPFLAGS="$CPPFLAGS -I$withval/include"
LDFLAGS="$LDFLAGS -L$withval/lib"
fi
# Check whether --with-libevent-include was given.
if test "${with_libevent_include+set}" = set; then :
withval=$with_libevent_include; libevent_include="$withval"
CPPFLAGS="$CPPFLAGS -I$withval"
fi
# Check whether --with-libevent-lib was given.
if test "${with_libevent_lib+set}" = set; then :
withval=$with_libevent_lib; libevent_lib="$withval"
LDFLAGS="$LDFLAGS -L$withval"
fi
for ac_header in event.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "event.h" "ac_cv_header_event_h" "$ac_includes_default"
if test "x$ac_cv_header_event_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_EVENT_H 1
_ACEOF
else
as_fn_error $? "\"libevent header files not found.\"" "$LINENO" 5; break
fi
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for event_init in -levent" >&5
$as_echo_n "checking for event_init in -levent... " >&6; }
if ${ac_cv_lib_event_event_init+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-levent $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char event_init ();
int
main ()
{
return event_init ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_event_event_init=yes
else
ac_cv_lib_event_event_init=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_event_event_init" >&5
$as_echo "$ac_cv_lib_event_event_init" >&6; }
if test "x$ac_cv_lib_event_event_init" = xyes; then :
LIBS="-levent $LIBS"
else
as_fn_error $? "\"libevent libraries not found.\"" "$LINENO" 5
fi
# Check whether --enable-zlib was given. # Check whether --enable-zlib was given.
if test "${enable_zlib+set}" = set; then : if test "${enable_zlib+set}" = set; then :
enableval=$enable_zlib; enableval=$enable_zlib;

View file

@ -4,7 +4,7 @@ AC_PREREQ(2.61)
AC_INIT AC_INIT
AC_CONFIG_SRCDIR([src/tincd.c]) AC_CONFIG_SRCDIR([src/tincd.c])
AC_GNU_SOURCE AC_GNU_SOURCE
AM_INIT_AUTOMAKE(tinc, 1.1pre3) AM_INIT_AUTOMAKE(tinc, 1.1pre4)
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
AM_MAINTAINER_MODE AM_MAINTAINER_MODE
@ -74,7 +74,7 @@ case $host_os in
esac esac
AC_ARG_ENABLE(uml, AC_ARG_ENABLE(uml,
AS_HELP_STRING([--disable-uml], [enable support for User Mode Linux]), AS_HELP_STRING([--enable-uml], [enable support for User Mode Linux]),
[ AS_IF([test "x$enable_uml" = "xyes"], [ AS_IF([test "x$enable_uml" = "xyes"],
[ AC_DEFINE(ENABLE_UML, 1, [Support for UML]) [ AC_DEFINE(ENABLE_UML, 1, [Support for UML])
uml=true uml=true
@ -85,7 +85,7 @@ AC_ARG_ENABLE(uml,
) )
AC_ARG_ENABLE(vde, AC_ARG_ENABLE(vde,
AS_HELP_STRING([--disable-vde], [enable support for Virtual Distributed Ethernet]), AS_HELP_STRING([--enable-vde], [enable support for Virtual Distributed Ethernet]),
[ AS_IF([test "x$enable_vde" = "xyes"], [ AS_IF([test "x$enable_vde" = "xyes"],
[ AC_CHECK_HEADERS(libvdeplug_dyn.h, [], [AC_MSG_ERROR([VDE plug header files not found.]); break]) [ AC_CHECK_HEADERS(libvdeplug_dyn.h, [], [AC_MSG_ERROR([VDE plug header files not found.]); break])
AC_DEFINE(ENABLE_VDE, 1, [Support for VDE]) AC_DEFINE(ENABLE_VDE, 1, [Support for VDE])
@ -97,7 +97,7 @@ AC_ARG_ENABLE(vde,
) )
AC_ARG_ENABLE(tunemu, AC_ARG_ENABLE(tunemu,
AS_HELP_STRING([--disable-tunemu], [enable support for the tunemu driver]), AS_HELP_STRING([--enable-tunemu], [enable support for the tunemu driver]),
[ AS_IF([test "x$enable_tunemu" = "xyes"], [ AS_IF([test "x$enable_tunemu" = "xyes"],
[ AC_DEFINE(ENABLE_TUNEMU, 1, [Support for tunemu]) [ AC_DEFINE(ENABLE_TUNEMU, 1, [Support for tunemu])
tunemu=true tunemu=true
@ -179,11 +179,10 @@ AC_CACHE_SAVE
dnl These are defined in files in m4/ dnl These are defined in files in m4/
AC_ARG_WITH(libgcrypt, AC_HELP_STRING([--with-libgcrypt], [enable use of libgcrypt instead of OpenSSL])], []) dnl AC_ARG_WITH(libgcrypt, AC_HELP_STRING([--with-libgcrypt], [enable use of libgcrypt instead of OpenSSL])], [])
tinc_CURSES tinc_CURSES
tinc_READLINE tinc_READLINE
tinc_LIBEVENT
tinc_ZLIB tinc_ZLIB
tinc_LZO tinc_LZO

View file

@ -53,10 +53,9 @@ subdir = doc
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in texinfo.tex DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in texinfo.tex
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/libevent.m4 \ $(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \
$(top_srcdir)/m4/lzo.m4 $(top_srcdir)/m4/openssl.m4 \ $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \
$(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/zlib.m4 \ $(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.in
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4) $(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d mkinstalldirs = $(install_sh) -d

Binary file not shown.

View file

@ -3,16 +3,13 @@
.\" Manual page created by: .\" Manual page created by:
.\" Ivo Timmermans .\" Ivo Timmermans
.\" Guus Sliepen <guus@tinc-vpn.org> .\" Guus Sliepen <guus@tinc-vpn.org>
.Sh NAME .Sh NAME
.Nm tinc.conf .Nm tinc.conf
.Nd tinc daemon configuration .Nd tinc daemon configuration
.Sh DESCRIPTION .Sh DESCRIPTION
The files in the The files in the
.Pa @sysconfdir@/tinc/ .Pa @sysconfdir@/tinc/
directory contain runtime and security information for the tinc daemon. directory contain runtime and security information for the tinc daemon.
.Sh NETWORKS .Sh NETWORKS
To distinguish multiple instances of tinc running on one computer, To distinguish multiple instances of tinc running on one computer,
you can use the you can use the
@ -44,31 +41,26 @@ the configuration file should be
.Pa @sysconfdir@/tinc/tinc.conf , .Pa @sysconfdir@/tinc/tinc.conf ,
and the host configuration files are now expected to be in and the host configuration files are now expected to be in
.Pa @sysconfdir@/tinc/hosts/ . .Pa @sysconfdir@/tinc/hosts/ .
.Sh NAMES .Sh NAMES
Each tinc daemon should have a name that is unique in the network which it will be part of. Each tinc daemon should have a name that is unique in the network which it will be part of.
The name will be used by other tinc daemons for identification. The name will be used by other tinc daemons for identification.
The name has to be declared in the The name has to be declared in the
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf .Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf
file. file.
.Pp .Pp
To make things easy, To make things easy,
choose something that will give unique and easy to remember names to your tinc daemon(s). choose something that will give unique and easy to remember names to your tinc daemon(s).
You could try things like hostnames, owner surnames or location names. You could try things like hostnames, owner surnames or location names.
However, you are only allowed to use alphanumerical characters (a-z, A-Z, and 0-9) and underscores (_) in the name. However, you are only allowed to use alphanumerical characters (a-z, A-Z, and 0-9) and underscores (_) in the name.
.Sh INITIAL CONFIGURATION .Sh INITIAL CONFIGURATION
If you have not configured tinc yet, you can easily create a basic configuration using the following command: If you have not configured tinc yet, you can easily create a basic configuration using the following command:
.Bd -literal -offset indent .Bd -literal -offset indent
.Nm tincctl Fl n Ar NETNAME Li init Ar NAME .Nm tincctl Fl n Ar NETNAME Li init Ar NAME
.Ed .Ed
.Pp .Pp
You can further change the configuration as needed either by manually editing the configuration files, You can further change the configuration as needed either by manually editing the configuration files,
or by using or by using
.Xr tincctl 8 . .Xr tincctl 8 .
.Sh PUBLIC/PRIVATE KEYS .Sh PUBLIC/PRIVATE KEYS
The The
.Nm tincctl Li init .Nm tincctl Li init
@ -81,24 +73,20 @@ in the directory
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa / .Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /
The public keys should be stored in the host configuration file The public keys should be stored in the host configuration file
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Va NAME . .Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Va NAME .
The RSA keys are used for backwards compatibility with tinc version 1.0. The RSA keys are used for backwards compatibility with tinc version 1.0.
If you are upgrading from version 1.0 to 1.1, you can keep the old configuration files, If you are upgrading from version 1.0 to 1.1, you can keep the old configuration files,
but you will need to create ECDSA keys using the following command: but you will need to create ECDSA keys using the following command:
.Bd -literal -offset indent .Bd -literal -offset indent
.Nm tincctl Fl n Ar NETNAME Li generate-ecdsa-keys .Nm tincctl Fl n Ar NETNAME Li generate-ecdsa-keys
.Ed .Ed
.Sh SERVER CONFIGURATION .Sh SERVER CONFIGURATION
The server configuration of the daemon is done in the file The server configuration of the daemon is done in the file
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf . .Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf .
This file consists of comments (lines started with a This file consists of comments (lines started with a
.Li # ) .Li # )
or assignments in the form of: or assignments in the form of:
.Pp .Pp
.Va Variable Li = Ar Value . .Va Variable Li = Ar Value .
.Pp .Pp
The variable names are case insensitive, and any spaces, tabs, The variable names are case insensitive, and any spaces, tabs,
newlines and carriage returns are ignored. newlines and carriage returns are ignored.
@ -106,31 +94,35 @@ Note: it is not required that you put in the
.Li = .Li =
sign, but doing so improves readability. sign, but doing so improves readability.
If you leave it out, remember to replace it with at least one space character. If you leave it out, remember to replace it with at least one space character.
.Pp .Pp
The server configuration is complemented with host specific configuration (see the next section). 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 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 , .Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf ,
it is recommended to put host specific configuration options in the host configuration file, it is recommended to put host specific configuration options in the host configuration file,
as this makes it easy to exchange with other nodes. as this makes it easy to exchange with other nodes.
.Pp .Pp
You can edit the config file manually, but it is recommended that you use You can edit the config file manually, but it is recommended that you use
.Xr tincctl 8 .Xr tincctl 8
to change configuration variables for you. to change configuration variables for you.
.Pp .Pp
Here are all valid variables, listed in alphabetical order. Here are all valid variables, listed in alphabetical order.
The default value is given between parentheses. The default value is given between parentheses.
.Bl -tag -width indent .Bl -tag -width indent
.It Va AddressFamily Li = ipv4 | ipv6 | any Pq any .It Va AddressFamily Li = ipv4 | ipv6 | any Pq any
This option affects the address family of listening and outgoing sockets. This option affects the address family of listening and outgoing sockets.
If If
.Qq any .Qq any
is selected, then depending on the operating system both IPv4 and IPv6 or just is selected, then depending on the operating system both IPv4 and IPv6 or just
IPv6 listening sockets will be created. IPv6 listening sockets will be created.
.It Va AutoConnect Li = Ar count Po 0 Pc Bq experimental
If set to a non-zero value,
.Nm
will try to only have
.Ar count
meta connections to other nodes,
by automatically making or breaking connections to known nodes.
Higher values increase redundancy but also increase meta data overhead.
When using this option, a good value is 3.
.It Va BindToAddress Li = Ar address Op Ar port .It Va BindToAddress Li = Ar address Op Ar port
If your computer has more than one IPv4 or IPv6 address, If your computer has more than one IPv4 or IPv6 address,
.Nm tinc .Nm tinc
@ -149,38 +141,31 @@ To only bind to a specific port but not to a specific address, use
.Li * .Li *
for the for the
.Ar address . .Ar address .
.It Va BindToInterface Li = Ar interface Bq experimental .It Va BindToInterface Li = Ar interface Bq experimental
If your computer has more than one network interface, If your computer has more than one network interface,
.Nm tinc .Nm tinc
will by default listen on all of them for incoming connections. will by default listen on all of them for incoming connections.
It is possible to bind only to a single interface with this variable. It is possible to bind only to a single interface with this variable.
.Pp .Pp
This option may not work on all platforms. This option may not work on all platforms.
Also, on some platforms it will not actually bind to an interface, Also, on some platforms it will not actually bind to an interface,
but rather to the address that the interface has at the moment a socket is created. but rather to the address that the interface has at the moment a socket is created.
.It Va Broadcast Li = no | mst | direct Po mst Pc Bq experimental .It Va Broadcast Li = no | mst | direct Po mst Pc Bq experimental
This option selects the way broadcast packets are sent to other daemons. This option selects the way broadcast packets are sent to other daemons.
NOTE: all nodes in a VPN must use the same NOTE: all nodes in a VPN must use the same
.Va Broadcast .Va Broadcast
mode, otherwise routing loops can form. mode, otherwise routing loops can form.
.Bl -tag -width indent .Bl -tag -width indent
.It no .It no
Broadcast packets are never sent to other nodes. Broadcast packets are never sent to other nodes.
.It mst .It mst
Broadcast packets are sent and forwarded via the VPN's Minimum Spanning Tree. Broadcast packets are sent and forwarded via the VPN's Minimum Spanning Tree.
This ensures broadcast packets reach all nodes. This ensures broadcast packets reach all nodes.
.It direct .It direct
Broadcast packets are sent directly to all nodes that can be reached directly. Broadcast packets are sent directly to all nodes that can be reached directly.
Broadcast packets received from other nodes are never forwarded. Broadcast packets received from other nodes are never forwarded.
If the IndirectData option is also set, broadcast packets will only be sent to nodes which we have a meta connection to. If the IndirectData option is also set, broadcast packets will only be sent to nodes which we have a meta connection to.
.El .El
.It Va ConnectTo Li = Ar name .It Va ConnectTo Li = Ar name
Specifies which other tinc daemon to connect to on startup. Specifies which other tinc daemon to connect to on startup.
Multiple Multiple
@ -191,14 +176,12 @@ The names should be known to this tinc daemon
(i.e., there should be a host configuration file for the name on the (i.e., there should be a host configuration file for the name on the
.Va ConnectTo .Va ConnectTo
line). line).
.Pp .Pp
If you don't specify a host with If you don't specify a host with
.Va ConnectTo , .Va ConnectTo ,
.Nm tinc .Nm tinc
won't try to connect to other daemons at all, won't try to connect to other daemons at all,
and will instead just listen for incoming connections. and will instead just listen for incoming connections.
.It Va DecrementTTL Li = yes | no Po no Pc Bq experimental .It Va DecrementTTL Li = yes | no Po no Pc Bq experimental
When enabled, When enabled,
.Nm tinc .Nm tinc
@ -208,7 +191,6 @@ and will drop packets that have a TTL value of zero,
in which case it will send an ICMP Time Exceeded packet back. in which case it will send an ICMP Time Exceeded packet back.
.Pp .Pp
Do not use this option if you use switch mode and want to use IPv6. Do not use this option if you use switch mode and want to use IPv6.
.It Va Device Li = Ar device Po Pa /dev/tap0 , Pa /dev/net/tun No or other depending on platform Pc .It Va Device Li = Ar device Po Pa /dev/tap0 , Pa /dev/net/tun No or other depending on platform Pc
The virtual network device to use. The virtual network device to use.
.Nm tinc .Nm tinc
@ -220,18 +202,15 @@ instead of
.Va Device . .Va Device .
The info pages of the tinc package contain more information The info pages of the tinc package contain more information
about configuring the virtual network device. about configuring the virtual network device.
.It Va DeviceType Li = Ar type Pq platform dependent .It Va DeviceType Li = Ar type Pq platform dependent
The type of the virtual network device. The type of the virtual network device.
Tinc will normally automatically select the right type of tun/tap interface, and this option should not be used. Tinc will normally automatically select the right type of tun/tap interface, and this option should not be used.
However, this option can be used to select one of the special interface types, if support for them is compiled in. However, this option can be used to select one of the special interface types, if support for them is compiled in.
.Bl -tag -width indent .Bl -tag -width indent
.It dummy .It dummy
Use a dummy interface. Use a dummy interface.
No packets are ever read or written to a virtual network device. No packets are ever read or written to a virtual network device.
Useful for testing, or when setting up a node that only forwards packets for other nodes. Useful for testing, or when setting up a node that only forwards packets for other nodes.
.It raw_socket .It raw_socket
Open a raw socket, and bind it to a pre-existing Open a raw socket, and bind it to a pre-existing
.Va Interface .Va Interface
@ -239,7 +218,6 @@ Open a raw socket, and bind it to a pre-existing
All packets are read from this interface. All packets are read from this interface.
Packets received for the local node are written to the raw socket. Packets received for the local node are written to the raw socket.
However, at least on Linux, the operating system does not process IP packets destined for the local host. However, at least on Linux, the operating system does not process IP packets destined for the local host.
.It multicast .It multicast
Open a multicast UDP socket and bind it to the address and port (separated by spaces) and optionally a TTL value specified using Open a multicast UDP socket and bind it to the address and port (separated by spaces) and optionally a TTL value specified using
.Va Device . .Va Device .
@ -249,7 +227,6 @@ Do NOT connect multiple
.Nm tinc .Nm tinc
daemons to the same multicast address, this will very likely cause routing loops. daemons to the same multicast address, this will very likely cause routing loops.
Also note that this can cause decrypted VPN packets to be sent out on a real network if misconfigured. Also note that this can cause decrypted VPN packets to be sent out on a real network if misconfigured.
.It uml Pq not compiled in by default .It uml Pq not compiled in by default
Create a UNIX socket with the filename specified by Create a UNIX socket with the filename specified by
.Va Device , .Va Device ,
@ -258,7 +235,6 @@ or
if not specified. if not specified.
.Nm tinc .Nm tinc
will wait for a User Mode Linux instance to connect to this socket. will wait for a User Mode Linux instance to connect to this socket.
.It vde Pq not compiled in by default .It vde Pq not compiled in by default
Uses the libvdeplug library to connect to a Virtual Distributed Ethernet switch, Uses the libvdeplug library to connect to a Virtual Distributed Ethernet switch,
using the UNIX socket specified by using the UNIX socket specified by
@ -267,46 +243,37 @@ or
.Pa @localstatedir@/run/vde.ctl .Pa @localstatedir@/run/vde.ctl
if not specified. if not specified.
.El .El
Also, in case tinc does not seem to correctly interpret packets received from the virtual network device, Also, in case tinc does not seem to correctly interpret packets received from the virtual network device,
it can be used to change the way packets are interpreted: it can be used to change the way packets are interpreted:
.Bl -tag -width indent .Bl -tag -width indent
.It tun Pq BSD and Linux .It tun Pq BSD and Linux
Set type to tun. Set type to tun.
Depending on the platform, this can either be with or without an address family header (see below). Depending on the platform, this can either be with or without an address family header (see below).
.It tunnohead Pq BSD .It tunnohead Pq BSD
Set type to tun without an address family header. Set type to tun without an address family header.
Tinc will expect packets read from the virtual network device to start with an IP header. Tinc will expect packets read from the virtual network device to start with an IP header.
On some platforms IPv6 packets cannot be read from or written to the device in this mode. On some platforms IPv6 packets cannot be read from or written to the device in this mode.
.It tunifhead Pq BSD .It tunifhead Pq BSD
Set type to tun with an address family header. Set type to tun with an address family header.
Tinc will expect packets read from the virtual network device Tinc will expect packets read from the virtual network device
to start with a four byte header containing the address family, to start with a four byte header containing the address family,
followed by an IP header. followed by an IP header.
This mode should support both IPv4 and IPv6 packets. This mode should support both IPv4 and IPv6 packets.
.It tap Pq BSD and Linux .It tap Pq BSD and Linux
Set type to tap. Set type to tap.
Tinc will expect packets read from the virtual network device Tinc will expect packets read from the virtual network device
to start with an Ethernet header. to start with an Ethernet header.
.El .El
.It Va DirectOnly Li = yes | no Po no Pc Bq experimental .It Va DirectOnly Li = yes | no Po no Pc Bq experimental
When this option is enabled, packets that cannot be sent directly to the destination node, When this option is enabled, packets that cannot be sent directly to the destination node,
but which would have to be forwarded by an intermediate node, are dropped instead. but which would have to be forwarded by an intermediate node, are dropped instead.
When combined with the IndirectData option, When combined with the IndirectData option,
packets for nodes for which we do not have a meta connection with are also dropped. packets for nodes for which we do not have a meta connection with are also dropped.
.It Va ECDSAPrivateKeyFile Li = Ar filename Po Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /ecdsa_key.priv Pc .It Va ECDSAPrivateKeyFile Li = Ar filename Po Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /ecdsa_key.priv Pc
The file in which the private ECDSA key of this tinc daemon resides. The file in which the private ECDSA key of this tinc daemon resides.
This is only used if This is only used if
.Va ExperimentalProtocol .Va ExperimentalProtocol
is enabled. is enabled.
.It Va ExperimentalProtocol Li = yes | no Po no Pc Bq experimental .It Va ExperimentalProtocol Li = yes | no Po no Pc Bq experimental
When this option is enabled, experimental protocol enhancements will be used. When this option is enabled, experimental protocol enhancements will be used.
Ephemeral ECDH will be used for key exchanges, Ephemeral ECDH will be used for key exchanges,
@ -315,53 +282,31 @@ When enabled, an ECDSA key must have been generated before with
.Nm tincctl generate-ecdsa-keys . .Nm tincctl generate-ecdsa-keys .
The experimental protocol may change at any time, The experimental protocol may change at any time,
and there is no guarantee that tinc will run stable when it is used. and there is no guarantee that tinc will run stable when it is used.
.It Va Forwarding Li = off | internal | kernel Po internal Pc Bq experimental .It Va Forwarding Li = off | internal | kernel Po internal Pc Bq experimental
This option selects the way indirect packets are forwarded. This option selects the way indirect packets are forwarded.
.Bl -tag -width indent .Bl -tag -width indent
.It off .It off
Incoming packets that are not meant for the local node, Incoming packets that are not meant for the local node,
but which should be forwarded to another node, are dropped. but which should be forwarded to another node, are dropped.
.It internal .It internal
Incoming packets that are meant for another node are forwarded by tinc internally. Incoming packets that are meant for another node are forwarded by tinc internally.
.Pp .Pp
This is the default mode, and unless you really know you need another forwarding mode, don't change it. This is the default mode, and unless you really know you need another forwarding mode, don't change it.
.It kernel .It kernel
Incoming packets are always sent to the TUN/TAP device, even if the packets are not for the local node. Incoming packets are always sent to the TUN/TAP device, even if the packets are not for the local node.
This is less efficient, but allows the kernel to apply its routing and firewall rules on them, This is less efficient, but allows the kernel to apply its routing and firewall rules on them,
and can also help debugging. and can also help debugging.
.El .El
.It Va GraphDumpFile Li = Ar filename
If this option is present,
.Nm tinc
will dump the current network graph to the file
.Ar filename
every minute, unless there were no changes to the graph.
The file is in a format that can be read by graphviz tools.
If
.Ar filename
starts with a pipe symbol |,
then the rest of the filename is interpreted as a shell command
that is executed, the graph is then sent to stdin.
.It Va Hostnames Li = yes | no Pq no .It Va Hostnames Li = yes | no Pq no
This option selects whether IP addresses (both real and on the VPN) should This option selects whether IP addresses (both real and on the VPN) should
be resolved. Since DNS lookups are blocking, it might affect tinc's be resolved. Since DNS lookups are blocking, it might affect tinc's
efficiency, even stopping the daemon for a few seconds every time it does efficiency, even stopping the daemon for a few seconds every time it does
a lookup if your DNS server is not responding. a lookup if your DNS server is not responding.
.Pp .Pp
This does not affect resolving hostnames to IP addresses from the This does not affect resolving hostnames to IP addresses from the
host configuration files, but whether hostnames should be resolved while logging. host configuration files, but whether hostnames should be resolved while logging.
.It Va IffOneQueue Li = yes | no Po no Pc Bq experimental .It Va IffOneQueue Li = yes | no Po no Pc Bq experimental
(Linux only) Set IFF_ONE_QUEUE flag on TUN/TAP devices. (Linux only) Set IFF_ONE_QUEUE flag on TUN/TAP devices.
.It Va Interface Li = Ar interface .It Va Interface Li = Ar interface
Defines the name of the interface corresponding to the virtual network device. Defines the name of the interface corresponding to the virtual network device.
Depending on the operating system and the type of device this may or may not actually set the name of the interface. Depending on the operating system and the type of device this may or may not actually set the name of the interface.
@ -369,12 +314,10 @@ Under Windows, this variable is used to select which network interface will be u
If you specified a If you specified a
.Va Device , .Va Device ,
this variable is almost always already correctly set. this variable is almost always already correctly set.
.It Va KeyExpire Li = Ar seconds Pq 3600 .It Va KeyExpire Li = Ar seconds Pq 3600
This option controls the period the encryption keys used to encrypt the data are valid. This option controls the period the encryption keys used to encrypt the data are valid.
It is common practice to change keys at regular intervals to make it even harder for crackers, It is common practice to change keys at regular intervals to make it even harder for crackers,
even though it is thought to be nearly impossible to crack a single key. even though it is thought to be nearly impossible to crack a single key.
.It Va LocalDiscovery Li = yes | no Pq no .It Va LocalDiscovery Li = yes | no Pq no
When enabled, When enabled,
.Nm tinc .Nm tinc
@ -382,54 +325,43 @@ will try to detect peers that are on the same local network.
This will allow direct communication using LAN addresses, even if both peers are behind a NAT This will allow direct communication using LAN addresses, even if both peers are behind a NAT
and they only ConnectTo a third node outside the NAT, and they only ConnectTo a third node outside the NAT,
which normally would prevent the peers from learning each other's LAN address. which normally would prevent the peers from learning each other's LAN address.
.Pp .Pp
Currently, local discovery is implemented by sending broadcast packets to the LAN during path MTU discovery. Currently, local discovery is implemented by sending broadcast packets to the LAN during path MTU discovery.
This feature may not work in all possible situations. This feature may not work in all possible situations.
.It Va MACExpire Li = Ar seconds Pq 600 .It Va MACExpire Li = Ar seconds Pq 600
This option controls the amount of time MAC addresses are kept before they are removed. This option controls the amount of time MAC addresses are kept before they are removed.
This only has effect when This only has effect when
.Va Mode .Va Mode
is set to is set to
.Qq switch . .Qq switch .
.It Va MaxTimeout Li = Ar seconds Pq 900 .It Va MaxTimeout Li = Ar seconds Pq 900
This is the maximum delay before trying to reconnect to other tinc daemons. This is the maximum delay before trying to reconnect to other tinc daemons.
.It Va Mode Li = router | switch | hub Pq router .It Va Mode Li = router | switch | hub Pq router
This option selects the way packets are routed to other daemons. This option selects the way packets are routed to other daemons.
.Bl -tag -width indent .Bl -tag -width indent
.It router .It router
In this mode In this mode
.Va Subnet .Va Subnet
variables in the host configuration files will be used to form a routing table. variables in the host configuration files will be used to form a routing table.
Only unicast packets of routable protocols (IPv4 and IPv6) are supported in this mode. Only unicast packets of routable protocols (IPv4 and IPv6) are supported in this mode.
.Pp .Pp
This is the default mode, and unless you really know you need another mode, don't change it. This is the default mode, and unless you really know you need another mode, don't change it.
.It switch .It switch
In this mode the MAC addresses of the packets on the VPN will be used to In this mode the MAC addresses of the packets on the VPN will be used to
dynamically create a routing table just like an Ethernet switch does. dynamically create a routing table just like an Ethernet switch does.
Unicast, multicast and broadcast packets of every protocol that runs over Ethernet are supported in this mode Unicast, multicast and broadcast packets of every protocol that runs over Ethernet are supported in this mode
at the cost of frequent broadcast ARP requests and routing table updates. at the cost of frequent broadcast ARP requests and routing table updates.
.Pp .Pp
This mode is primarily useful if you want to bridge Ethernet segments. This mode is primarily useful if you want to bridge Ethernet segments.
.It hub .It hub
This mode is almost the same as the switch mode, but instead This mode is almost the same as the switch mode, but instead
every packet will be broadcast to the other daemons every packet will be broadcast to the other daemons
while no routing table is managed. while no routing table is managed.
.El .El
.It Va Name Li = Ar name Bq required .It Va Name Li = Ar name Bq required
This is the name which identifies this tinc daemon. This is the name which identifies this tinc daemon.
It must be unique for the virtual private network this daemon will connect to. It must be unique for the virtual private network this daemon will connect to.
The Name may only consist of alphanumeric and underscore characters. The Name may only consist of alphanumeric and underscore characters.
If If
.Va Name .Va Name
starts with a starts with a
@ -441,40 +373,28 @@ If
is is
.Li $HOST , .Li $HOST ,
but no such environment variable exist, the hostname will be read using the gethostnname() system call. but no such environment variable exist, the hostname will be read using the gethostnname() system call.
.It Va PingInterval Li = Ar seconds Pq 60 .It Va PingInterval Li = Ar seconds Pq 60
The number of seconds of inactivity that The number of seconds of inactivity that
.Nm tinc .Nm tinc
will wait before sending a probe to the other end. will wait before sending a probe to the other end.
.It Va PingTimeout Li = Ar seconds Pq 5 .It Va PingTimeout Li = Ar seconds Pq 5
The number of seconds to wait for a response to pings or to allow meta The number of seconds to wait for a response to pings or to allow meta
connections to block. If the other end doesn't respond within this time, connections to block. If the other end doesn't respond within this time,
the connection is terminated, the connection is terminated,
and the others will be notified of this. and the others will be notified of this.
.It Va PriorityInheritance Li = yes | no Po no Pc Bq experimental .It Va PriorityInheritance Li = yes | no Po no Pc Bq experimental
When this option is enabled the value of the TOS field of tunneled IPv4 packets When this option is enabled the value of the TOS field of tunneled IPv4 packets
will be inherited by the UDP packets that are sent out. will be inherited by the UDP packets that are sent out.
.It Va PrivateKey Li = Ar key Bq obsolete .It Va PrivateKey Li = Ar key Bq obsolete
The private RSA key of this tinc daemon. The private RSA key of this tinc daemon.
It will allow this tinc daemon to authenticate itself to other daemons. It will allow this tinc daemon to authenticate itself to other daemons.
.It Va PrivateKeyFile Li = Ar filename Po Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /rsa_key.priv Pc .It Va PrivateKeyFile Li = Ar filename Po Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /rsa_key.priv Pc
The file in which the private RSA key of this tinc daemon resides. The file in which the private RSA key of this tinc daemon resides.
Note that there must be exactly one of
.Va PrivateKey
or
.Va PrivateKeyFile
specified in the configuration file.
.It Va ProcessPriority Li = low | normal | high .It Va ProcessPriority Li = low | normal | high
When this option is used the priority of the When this option is used the priority of the
.Nm tincd .Nm tincd
process will be adjusted. process will be adjusted.
Increasing the priority may help to reduce latency and packet loss on the VPN. Increasing the priority may help to reduce latency and packet loss on the VPN.
.It Va Proxy Li = socks4 | socks5 | http | exec Ar ... Bq experimental .It Va Proxy Li = socks4 | socks5 | http | exec Ar ... Bq experimental
Use a proxy when making outgoing connections. Use a proxy when making outgoing connections.
The following proxy types are currently supported: The following proxy types are currently supported:
@ -507,7 +427,6 @@ and
.Ev REMOTEPORT .Ev REMOTEPORT
are available. are available.
.El .El
.It Va ReplayWindow Li = Ar bytes Pq 16 .It Va ReplayWindow Li = Ar bytes Pq 16
vhis is the size of the replay tracking window for each remote node, in bytes. vhis is the size of the replay tracking window for each remote node, in bytes.
The window is a bitfield which tracks 1 packet per bit, so for example The window is a bitfield which tracks 1 packet per bit, so for example
@ -517,35 +436,29 @@ the interaction of replay tracking with underlying real packet loss and/or
reordering. Setting this to zero will disable replay tracking completely and reordering. Setting this to zero will disable replay tracking completely and
pass all traffic, but leaves tinc vulnerable to replay-based attacks on your pass all traffic, but leaves tinc vulnerable to replay-based attacks on your
traffic. traffic.
.It Va StrictSubnets Li = yes | no Po no Pc Bq experimental .It Va StrictSubnets Li = yes | no Po no Pc Bq experimental
When this option is enabled tinc will only use Subnet statements which are When this option is enabled tinc will only use Subnet statements which are
present in the host config files in the local present in the host config files in the local
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ .Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/
directory. directory.
.It Va TunnelServer Li = yes | no Po no Pc Bq experimental .It Va TunnelServer Li = yes | no Po no Pc Bq experimental
When this option is enabled tinc will no longer forward information between other tinc daemons, When this option is enabled tinc will no longer forward information between other tinc daemons,
and will only allow connections with nodes for which host config files are present in the local and will only allow connections with nodes for which host config files are present in the local
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ .Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/
directory. directory.
Setting this options also implicitly sets StrictSubnets. Setting this options also implicitly sets StrictSubnets.
.It Va UDPRcvBuf Li = Ar bytes Pq OS default .It Va UDPRcvBuf Li = Ar bytes Pq OS default
Sets the socket receive buffer size for the UDP socket, in bytes. Sets the socket receive buffer size for the UDP socket, in bytes.
If unset, the default buffer size will be used by the operating system. If unset, the default buffer size will be used by the operating system.
.It Va UDPSndBuf Li = Ar bytes Pq OS default .It Va UDPSndBuf Li = Ar bytes Pq OS default
Sets the socket send buffer size for the UDP socket, in bytes. Sets the socket send buffer size for the UDP socket, in bytes.
If unset, the default buffer size will be used by the operating system. If unset, the default buffer size will be used by the operating system.
.El .El
.Sh HOST CONFIGURATION FILES .Sh HOST CONFIGURATION FILES
The host configuration files contain all information needed The host configuration files contain all information needed
to establish a connection to those hosts. to establish a connection to those hosts.
A host configuration file is also required for the local tinc daemon, A host configuration file is also required for the local tinc daemon,
it will use it to read in it's listen port, public key and subnets. it will use it to read in it's listen port, public key and subnets.
.Pp .Pp
The idea is that these files are portable. The idea is that these files are portable.
You can safely mail your own host configuration file to someone else. You can safely mail your own host configuration file to someone else.
@ -554,7 +467,6 @@ and now his tinc daemon will be able to connect to your tinc daemon.
Since host configuration files only contain public keys, Since host configuration files only contain public keys,
no secrets are revealed by sending out this information. no secrets are revealed by sending out this information.
.Bl -tag -width indent .Bl -tag -width indent
.It Va Address Li = Ar address Oo Ar port Oc Bq recommended .It Va Address Li = Ar address Oo Ar port Oc Bq recommended
The IP address or hostname of this tinc daemon on the real network. The IP address or hostname of this tinc daemon on the real network.
This will only be used when trying to make an outgoing connection to this tinc daemon. This will only be used when trying to make an outgoing connection to this tinc daemon.
@ -563,7 +475,6 @@ Multiple
.Va Address .Va Address
variables can be specified, in which case each address will be tried until a working variables can be specified, in which case each address will be tried until a working
connection has been established. connection has been established.
.It Va Cipher Li = Ar cipher Pq blowfish .It Va Cipher Li = Ar cipher Pq blowfish
The symmetric cipher algorithm used to encrypt UDP packets. The symmetric cipher algorithm used to encrypt UDP packets.
Any cipher supported by OpenSSL is recognised. Any cipher supported by OpenSSL is recognised.
@ -571,24 +482,20 @@ Furthermore, specifying
.Qq none .Qq none
will turn off packet encryption. will turn off packet encryption.
It is best to use only those ciphers which support CBC mode. It is best to use only those ciphers which support CBC mode.
.It Va ClampMSS Li = yes | no Pq yes .It Va ClampMSS Li = yes | no Pq yes
This option specifies whether tinc should clamp the maximum segment size (MSS) This option specifies whether tinc should clamp the maximum segment size (MSS)
of TCP packets to the path MTU. This helps in situations where ICMP of TCP packets to the path MTU. This helps in situations where ICMP
Fragmentation Needed or Packet too Big messages are dropped by firewalls. Fragmentation Needed or Packet too Big messages are dropped by firewalls.
.It Va Compression Li = Ar level Pq 0 .It Va Compression Li = Ar level Pq 0
This option sets the level of compression used for UDP packets. This option sets the level of compression used for UDP packets.
Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib), Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib),
10 (fast lzo) and 11 (best lzo). 10 (fast lzo) and 11 (best lzo).
.It Va Digest Li = Ar digest Pq sha1 .It Va Digest Li = Ar digest Pq sha1
The digest algorithm used to authenticate UDP packets. The digest algorithm used to authenticate UDP packets.
Any digest supported by OpenSSL is recognised. Any digest supported by OpenSSL is recognised.
Furthermore, specifying Furthermore, specifying
.Qq none .Qq none
will turn off packet authentication. will turn off packet authentication.
.It Va IndirectData Li = yes | no Pq no .It Va IndirectData Li = yes | no Pq no
This option specifies whether other tinc daemons besides the one you specified with This option specifies whether other tinc daemons besides the one you specified with
.Va ConnectTo .Va ConnectTo
@ -596,33 +503,26 @@ can make a direct connection to you.
This is especially useful if you are behind a firewall This is especially useful if you are behind a firewall
and it is impossible to make a connection from the outside to your tinc daemon. and it is impossible to make a connection from the outside to your tinc daemon.
Otherwise, it is best to leave this option out or set it to no. Otherwise, it is best to leave this option out or set it to no.
.It Va MACLength Li = Ar length Pq 4 .It Va MACLength Li = Ar length Pq 4
The length of the message authentication code used to authenticate UDP packets. The length of the message authentication code used to authenticate UDP packets.
Can be anything from Can be anything from
.Qq 0 .Qq 0
up to the length of the digest produced by the digest algorithm. up to the length of the digest produced by the digest algorithm.
.It Va PMTU Li = Ar mtu Po 1514 Pc .It Va PMTU Li = Ar mtu Po 1514 Pc
This option controls the initial path MTU to this node. This option controls the initial path MTU to this node.
.It Va PMTUDiscovery Li = yes | no Po yes Pc .It Va PMTUDiscovery Li = yes | no Po yes Pc
When this option is enabled, tinc will try to discover the path MTU to this node. When this option is enabled, tinc will try to discover the path MTU to this node.
After the path MTU has been discovered, it will be enforced on the VPN. After the path MTU has been discovered, it will be enforced on the VPN.
.It Va Port Li = Ar port Pq 655 .It Va Port Li = Ar port Pq 655
The port number on which this tinc daemon is listening for incoming connections, The port number on which this tinc daemon is listening for incoming connections,
which is used if no port number is specified in an which is used if no port number is specified in an
.Va Address .Va Address
statement. statement.
.It Va PublicKey Li = Ar key Bq obsolete .It Va PublicKey Li = Ar key Bq obsolete
The public RSA key of this tinc daemon. The public RSA key of this tinc daemon.
It will be used to cryptographically verify it's identity and to set up a secure connection. It will be used to cryptographically verify it's identity and to set up a secure connection.
.It Va PublicKeyFile Li = Ar filename Bq obsolete .It Va PublicKeyFile Li = Ar filename Bq obsolete
The file in which the public RSA key of this tinc daemon resides. The file in which the public RSA key of this tinc daemon resides.
.Pp .Pp
From version 1.0pre4 on From version 1.0pre4 on
.Nm tinc .Nm tinc
@ -631,7 +531,6 @@ the above two options then are not necessary.
Either the PEM format is used, or exactly one of the above two options must be specified Either the PEM format is used, or exactly one of the above two options must be specified
in each host configuration file, in each host configuration file,
if you want to be able to establish a connection with that host. if you want to be able to establish a connection with that host.
.It Va Subnet Li = Ar address Ns Op Li / Ns Ar prefixlength Ns Op Li # Ns Ar weight .It Va Subnet Li = Ar address Ns Op Li / Ns Ar prefixlength Ns Op Li # Ns Ar weight
The subnet which this tinc daemon will serve. The subnet which this tinc daemon will serve.
.Nm tinc .Nm tinc
@ -641,7 +540,6 @@ it will be sent to the daemon who has this subnet in his host configuration file
Multiple Multiple
.Va Subnet .Va Subnet
variables can be specified. variables can be specified.
.Pp .Pp
Subnets can either be single MAC, IPv4 or IPv6 addresses, Subnets can either be single MAC, IPv4 or IPv6 addresses,
in which case a subnet consisting of only that single address is assumed, in which case a subnet consisting of only that single address is assumed,
@ -652,14 +550,12 @@ Note that subnets like 192.168.1.1/24 are invalid!
Read a networking HOWTO/FAQ/guide if you don't understand this. Read a networking HOWTO/FAQ/guide if you don't understand this.
IPv6 subnets are notated like fec0:0:0:1::/64. IPv6 subnets are notated like fec0:0:0:1::/64.
MAC addresses are notated like 0:1a:2b:3c:4d:5e. MAC addresses are notated like 0:1a:2b:3c:4d:5e.
.Pp .Pp
A Subnet can be given a weight to indicate its priority over identical Subnets A Subnet can be given a weight to indicate its priority over identical Subnets
owned by different nodes. The default weight is 10. Lower values indicate owned by different nodes. The default weight is 10. Lower values indicate
higher priority. Packets will be sent to the node with the highest priority, higher priority. Packets will be sent to the node with the highest priority,
unless that node is not reachable, in which case the node with the next highest unless that node is not reachable, in which case the node with the next highest
priority will be tried, and so on. priority will be tried, and so on.
.It Va TCPOnly Li = yes | no Pq no Bq obsolete .It Va TCPOnly Li = yes | no Pq no Bq obsolete
If this variable is set to yes, If this variable is set to yes,
then the packets are tunnelled over the TCP connection instead of a UDP connection. then the packets are tunnelled over the TCP connection instead of a UDP connection.
@ -667,53 +563,42 @@ This is especially useful for those who want to run a tinc daemon
from behind a masquerading firewall, from behind a masquerading firewall,
or if UDP packet routing is disabled somehow. or if UDP packet routing is disabled somehow.
Setting this options also implicitly sets IndirectData. Setting this options also implicitly sets IndirectData.
.Pp .Pp
Since version 1.0.10, tinc will automatically detect whether communication via Since version 1.0.10, tinc will automatically detect whether communication via
UDP is possible or not. UDP is possible or not.
.El .El
.Sh SCRIPTS .Sh SCRIPTS
Apart from reading the server and host configuration files, Apart from reading the server and host configuration files,
tinc can also run scripts at certain moments. tinc can also run scripts at certain moments.
Under Windows (not Cygwin), the scripts should have the extension Under Windows (not Cygwin), the scripts should have the extension
.Pa .bat . .Pa .bat .
.Bl -tag -width indent .Bl -tag -width indent
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up
This is the most important script. This is the most important script.
If it is present it will be executed right after the tinc daemon has been started and has connected to the virtual network device. If it is present it will be executed right after the tinc daemon has been started and has connected to the virtual network device.
It should be used to set up the corresponding network interface, It should be used to set up the corresponding network interface,
but can also be used to start other things. but can also be used to start other things.
Under Windows you can use the Network Connections control panel instead of creating this script. Under Windows you can use the Network Connections control panel instead of creating this script.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-down .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-down
This script is started right before the tinc daemon quits. This script is started right before the tinc daemon quits.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Ar HOST Ns Pa -up .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Ar HOST Ns Pa -up
This script is started when the tinc daemon with name This script is started when the tinc daemon with name
.Ar HOST .Ar HOST
becomes reachable. becomes reachable.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Ar HOST Ns Pa -down .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Ar HOST Ns Pa -down
This script is started when the tinc daemon with name This script is started when the tinc daemon with name
.Ar HOST .Ar HOST
becomes unreachable. becomes unreachable.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /host-up .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /host-up
This script is started when any host becomes reachable. This script is started when any host becomes reachable.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /host-down .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /host-down
This script is started when any host becomes unreachable. This script is started when any host becomes unreachable.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /subnet-up .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /subnet-up
This script is started when a Subnet becomes reachable. This script is started when a Subnet becomes reachable.
The Subnet and the node it belongs to are passed in environment variables. The Subnet and the node it belongs to are passed in environment variables.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /subnet-down .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /subnet-down
This script is started when a Subnet becomes unreachable. This script is started when a Subnet becomes unreachable.
.El .El
.Pp .Pp
The scripts are started without command line arguments, but can make use of certain environment variables. The scripts are started without command line arguments, but can make use of certain environment variables.
Under UNIX like operating systems the names of environment variables must be preceded by a Under UNIX like operating systems the names of environment variables must be preceded by a
@ -725,73 +610,55 @@ files, they have to be put between
.Li % .Li %
signs. signs.
.Bl -tag -width indent .Bl -tag -width indent
.It Ev NETNAME .It Ev NETNAME
If a netname was specified, this environment variable contains it. If a netname was specified, this environment variable contains it.
.It Ev NAME .It Ev NAME
Contains the name of this tinc daemon. Contains the name of this tinc daemon.
.It Ev DEVICE .It Ev DEVICE
Contains the name of the virtual network device that tinc uses. Contains the name of the virtual network device that tinc uses.
.It Ev INTERFACE .It Ev INTERFACE
Contains the name of the virtual network interface that tinc uses. Contains the name of the virtual network interface that tinc uses.
This should be used for commands like This should be used for commands like
.Pa ifconfig . .Pa ifconfig .
.It Ev NODE .It Ev NODE
When a host becomes (un)reachable, this is set to its name. When a host becomes (un)reachable, this is set to its name.
If a subnet becomes (un)reachable, this is set to the owner of that subnet. If a subnet becomes (un)reachable, this is set to the owner of that subnet.
.It Ev REMOTEADDRESS .It Ev REMOTEADDRESS
When a host becomes (un)reachable, this is set to its real address. When a host becomes (un)reachable, this is set to its real address.
.It Ev REMOTEPORT .It Ev REMOTEPORT
When a host becomes (un)reachable, this is set to the port number it uses for communication with other tinc daemons. When a host becomes (un)reachable, this is set to the port number it uses for communication with other tinc daemons.
.It Ev SUBNET .It Ev SUBNET
When a subnet becomes (un)reachable, this is set to the subnet. When a subnet becomes (un)reachable, this is set to the subnet.
.It Ev WEIGHT .It Ev WEIGHT
When a subnet becomes (un)reachable, this is set to the subnet weight. When a subnet becomes (un)reachable, this is set to the subnet weight.
.El .El
.Pp .Pp
Do not forget that under UNIX operating systems, you have to make the scripts executable, using the command Do not forget that under UNIX operating systems, you have to make the scripts executable, using the command
.Nm chmod Li a+x Pa script . .Nm chmod Li a+x Pa script .
.Sh FILES .Sh FILES
The most important files are: The most important files are:
.Bl -tag -width indent .Bl -tag -width indent
.It Pa @sysconfdir@/tinc/ .It Pa @sysconfdir@/tinc/
The top directory for configuration files. The top directory for configuration files.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf
The default name of the server configuration file for net The default name of the server configuration file for net
.Ar NETNAME . .Ar NETNAME .
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/
Host configuration files are kept in this directory. Host configuration files are kept in this directory.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up
If an executable file with this name exists, If an executable file with this name exists,
it will be executed right after the tinc daemon has connected to the virtual network device. it will be executed right after the tinc daemon has connected to the virtual network device.
It can be used to set up the corresponding network interface. It can be used to set up the corresponding network interface.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-down .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-down
If an executable file with this name exists, If an executable file with this name exists,
it will be executed right before the tinc daemon is going to close it will be executed right before the tinc daemon is going to close
its connection to the virtual network device. its connection to the virtual network device.
.El .El
.Sh SEE ALSO .Sh SEE ALSO
.Xr tincd 8 , .Xr tincd 8 ,
.Xr tincctl 8 , .Xr tincctl 8 ,
.Pa http://www.tinc-vpn.org/ , .Pa http://www.tinc-vpn.org/ ,
.Pa http://www.tldp.org/LDP/nag2/ . .Pa http://www.tldp.org/LDP/nag2/ .
.Pp .Pp
The full documentation for The full documentation for
.Nm tinc .Nm tinc
@ -799,7 +666,6 @@ is maintained as a Texinfo manual.
If the info and tinc programs are properly installed at your site, the command If the info and tinc programs are properly installed at your site, the command
.Ic info tinc .Ic info tinc
should give you access to the complete manual. should give you access to the complete manual.
.Pp .Pp
.Nm tinc .Nm tinc
comes with ABSOLUTELY NO WARRANTY. comes with ABSOLUTELY NO WARRANTY.

View file

@ -5,7 +5,7 @@ START-INFO-DIR-ENTRY
* tinc: (tinc). The tinc Manual. * tinc: (tinc). The tinc Manual.
END-INFO-DIR-ENTRY END-INFO-DIR-ENTRY
This is the info manual for tinc version 1.1pre2, a Virtual Private This is the info manual for tinc version 1.1pre4, a Virtual Private
Network daemon. Network daemon.
Copyright (C) 1998-2012 Ivo Timmermans, Guus Sliepen Copyright (C) 1998-2012 Ivo Timmermans, Guus Sliepen
@ -295,7 +295,8 @@ an error message, and stop.
* OpenSSL:: * OpenSSL::
* zlib:: * zlib::
* lzo:: * lzo::
* libevent:: * libcurses::
* libreadline::
 
File: tinc.info, Node: OpenSSL, Next: zlib, Up: Libraries File: tinc.info, Node: OpenSSL, Next: zlib, Up: Libraries
@ -307,8 +308,8 @@ For all cryptography-related functions, tinc uses the functions provided
by the OpenSSL library. by the OpenSSL library.
If this library is not installed, you wil get an error when If this library is not installed, you wil get an error when
configuring tinc for build. Support for running tinc without having configuring tinc for build. Support for running tinc with other
OpenSSL installed _may_ be added in the future. cryptographic libraries installed _may_ be added in the future.
You can use your operating system's package manager to install this You can use your operating system's package manager to install this
if available. Make sure you install the development AND runtime if available. Make sure you install the development AND runtime
@ -363,9 +364,12 @@ File: tinc.info, Node: zlib, Next: lzo, Prev: OpenSSL, Up: Libraries
For the optional compression of UDP packets, tinc uses the functions For the optional compression of UDP packets, tinc uses the functions
provided by the zlib library. provided by the zlib library.
If this library is not installed, you wil get an error when If this library is not installed, you wil get an error when running
configuring tinc for build. Support for running tinc without having the configure script. You can either install the zlib library, or
zlib installed _may_ be added in the future. disable support for zlib compression by using the "-disable-zlib"
option when running the configure script. Note that if you disable
support for zlib, the resulting binary will not work correctly on VPNs
where zlib compression is used.
You can use your operating system's package manager to install this You can use your operating system's package manager to install this
if available. Make sure you install the development AND runtime if available. Make sure you install the development AND runtime
@ -378,16 +382,19 @@ make sure you build development and runtime libraries (which is the
default). default).
 
File: tinc.info, Node: lzo, Next: libevent, Prev: zlib, Up: Libraries File: tinc.info, Node: lzo, Next: libcurses, Prev: zlib, Up: Libraries
2.2.3 lzo 2.2.3 lzo
--------- ---------
Another form of compression is offered using the lzo library. Another form of compression is offered using the LZO library.
If this library is not installed, you wil get an error when If this library is not installed, you wil get an error when running
configuring tinc for build. Support for running tinc without having lzo the configure script. You can either install the LZO library, or
installed _may_ be added in the future. disable support for LZO compression by using the "-disable-lzo" option
when running the configure script. Note that if you disable support for
LZO, the resulting binary will not work correctly on VPNs where LZO
compression is used.
You can use your operating system's package manager to install this You can use your operating system's package manager to install this
if available. Make sure you install the development AND runtime if available. Make sure you install the development AND runtime
@ -400,24 +407,52 @@ package. Please make sure you build development and runtime libraries
(which is the default). (which is the default).
 
File: tinc.info, Node: libevent, Prev: lzo, Up: Libraries File: tinc.info, Node: libcurses, Next: libreadline, Prev: lzo, Up: Libraries
2.2.4 libevent 2.2.4 libcurses
-------------- ---------------
For the main event loop, tinc uses the libevent library. For the "tincctl top" command, tinc requires a curses library.
If this library is not installed, you wil get an error when If this library is not installed, you wil get an error when running
configuring tinc for build. the configure script. You can either install a suitable curses
library, or disable all functionality that depends on a curses library
by using the "-disable-curses" option when running the configure script.
There are several curses libraries. It is recommended that you
install "ncurses" (`http://invisible-island.net/ncurses/'), however
other curses libraries should also work. In particular, "PDCurses"
(`http://pdcurses.sourceforge.net/') is recommended if you want to
compile tinc for Windows.
You can use your operating system's package manager to install this
if available. Make sure you install the development AND runtime versions
of this package.

File: tinc.info, Node: libreadline, Prev: libcurses, Up: Libraries
2.2.5 libreadline
-----------------
For the "tincctl" command's shell functionality, tinc uses the readline
library.
If this library is not installed, you wil get an error when running
the configure script. You can either install a suitable readline
library, or disable all functionality that depends on a readline
library by using the "-disable-readline" option when running the
configure script.
You can use your operating system's package manager to install this You can use your operating system's package manager to install this
if available. Make sure you install the development AND runtime if available. Make sure you install the development AND runtime
versions of this package. versions of this package.
If you have to install libevent manually, you can get the source code If you have to install libreadline manually, you can get the source
from `http://libevent.org/'. Instructions on how to configure, build code from `http://www.gnu.org/software/readline/'. Instructions on how
and install this package are included within the package. Please make to configure, build and install this package are included within the
sure you build development and runtime libraries (which is the default). package. Please make sure you build development and runtime libraries
(which is the default).
 
File: tinc.info, Node: Installation, Next: Configuration, Prev: Preparations, Up: Top File: tinc.info, Node: Installation, Next: Configuration, Prev: Preparations, Up: Top
@ -738,6 +773,13 @@ AddressFamily = <ipv4|ipv6|any> (any)
system both IPv4 and IPv6 or just IPv6 listening sockets will be system both IPv4 and IPv6 or just IPv6 listening sockets will be
created. created.
AutoConnect = <count> (0) [experimental]
If set to a non-zero value, tinc will try to only have count meta
connections to other nodes, by automatically making or breaking
connections to known nodes. Higher values increase redundancy but
also increase meta data overhead. When using this option, a good
value is 3.
BindToAddress = <ADDRESS> [<PORT>] BindToAddress = <ADDRESS> [<PORT>]
If your computer has more than one IPv4 or IPv6 address, tinc will If your computer has more than one IPv4 or IPv6 address, tinc will
by default listen on all of them for incoming connections. by default listen on all of them for incoming connections.
@ -912,14 +954,6 @@ Forwarding = <off|internal|kernel> (internal) [experimental]
efficient, but allows the kernel to apply its routing and efficient, but allows the kernel to apply its routing and
firewall rules on them, and can also help debugging. firewall rules on them, and can also help debugging.
GraphDumpFile = <FILENAME>
If this option is present, tinc will dump the current network
graph to the file FILENAME every minute, unless there were no
changes to the graph. The file is in a format that can be read by
graphviz tools. If FILENAME starts with a pipe symbol |, then the
rest of the filename is interpreted as a shell command that is
executed, the graph is then sent to stdin.
Hostnames = <yes|no> (no) Hostnames = <yes|no> (no)
This option selects whether IP addresses (both real and on the VPN) This option selects whether IP addresses (both real and on the VPN)
should be resolved. Since DNS lookups are blocking, it might should be resolved. Since DNS lookups are blocking, it might
@ -1026,9 +1060,6 @@ PrivateKeyFile = <PATH> (`/etc/tinc/NETNAME/rsa_key.priv')
generated by `tincctl generate-keys'. It must be a full path, not generated by `tincctl generate-keys'. It must be a full path, not
a relative directory. a relative directory.
Note that there must be exactly one of PrivateKey or PrivateKeyFile
specified in the configuration file.
ProcessPriority = <low|normal|high> ProcessPriority = <low|normal|high>
When this option is used the priority of the tincd process will be When this option is used the priority of the tincd process will be
adjusted. Increasing the priority may help to reduce latency and adjusted. Increasing the priority may help to reduce latency and
@ -2073,8 +2104,9 @@ File: tinc.info, Node: tincctl commands, Next: tincctl examples, Prev: tincct
store the files, but will default to the configuration directory store the files, but will default to the configuration directory
(you can use the -c or -n option). (you can use the -c or -n option).
`dump nodes' `dump [reachable] nodes'
Dump a list of all known nodes in the VPN. Dump a list of all known nodes in the VPN. If the reachable
keyword is used, only lists reachable nodes.
`dump edges' `dump edges'
Dump a list of all known connections in the VPN. Dump a list of all known connections in the VPN.
@ -2792,14 +2824,16 @@ Concept Index
* ANS_KEY: The meta-protocol. (line 64) * ANS_KEY: The meta-protocol. (line 64)
* authentication: Authentication protocol. * authentication: Authentication protocol.
(line 6) (line 6)
* AutoConnect: Main configuration variables.
(line 12)
* binary package: Building and installing tinc. * binary package: Building and installing tinc.
(line 9) (line 9)
* BindToAddress: Main configuration variables. * BindToAddress: Main configuration variables.
(line 12) (line 19)
* BindToInterface: Main configuration variables. * BindToInterface: Main configuration variables.
(line 23) (line 30)
* Broadcast: Main configuration variables. * Broadcast: Main configuration variables.
(line 34) (line 41)
* Cabal: Security. (line 6) * Cabal: Security. (line 6)
* CHAL_REPLY: Authentication protocol. * CHAL_REPLY: Authentication protocol.
(line 10) (line 10)
@ -2818,29 +2852,29 @@ Concept Index
(line 24) (line 24)
* connection: The connection. (line 6) * connection: The connection. (line 6)
* ConnectTo: Main configuration variables. * ConnectTo: Main configuration variables.
(line 54) (line 61)
* daemon: Running tinc. (line 11) * daemon: Running tinc. (line 11)
* data-protocol: The meta-connection. (line 18) * data-protocol: The meta-connection. (line 18)
* debug level: Runtime options. (line 17) * debug level: Runtime options. (line 17)
* debug levels: Debug levels. (line 6) * debug levels: Debug levels. (line 6)
* DecrementTTL: Main configuration variables. * DecrementTTL: Main configuration variables.
(line 65) (line 72)
* DEL_EDGE: The meta-protocol. (line 47) * DEL_EDGE: The meta-protocol. (line 47)
* DEL_SUBNET: The meta-protocol. (line 47) * DEL_SUBNET: The meta-protocol. (line 47)
* DEVICE: Scripts. (line 55) * DEVICE: Scripts. (line 55)
* Device: Main configuration variables. * Device: Main configuration variables.
(line 74) (line 81)
* device files: Device files. (line 6) * device files: Device files. (line 6)
* DeviceType: Main configuration variables. * DeviceType: Main configuration variables.
(line 81) (line 88)
* Digest: Host configuration variables. * Digest: Host configuration variables.
(line 29) (line 29)
* DirectOnly: Main configuration variables. * DirectOnly: Main configuration variables.
(line 146)
* dummy: Main configuration variables.
(line 88)
* ECDSAPrivateKeyFile: Main configuration variables.
(line 153) (line 153)
* dummy: Main configuration variables.
(line 95)
* ECDSAPrivateKeyFile: Main configuration variables.
(line 160)
* encapsulating: The UDP tunnel. (line 30) * encapsulating: The UDP tunnel. (line 30)
* encryption: Encryption of network packets. * encryption: Encryption of network packets.
(line 6) (line 6)
@ -2848,52 +2882,51 @@ Concept Index
* example: Example configuration. * example: Example configuration.
(line 6) (line 6)
* exec: Main configuration variables. * exec: Main configuration variables.
(line 326) (line 322)
* ExperimentalProtocol: Main configuration variables. * ExperimentalProtocol: Main configuration variables.
(line 157) (line 164)
* Forwarding: Main configuration variables. * Forwarding: Main configuration variables.
(line 166) (line 173)
* frame type: The UDP tunnel. (line 6) * frame type: The UDP tunnel. (line 6)
* GraphDumpFile: Main configuration variables.
(line 186)
* Hostnames: Main configuration variables. * Hostnames: Main configuration variables.
(line 194) (line 193)
* http: Main configuration variables. * http: Main configuration variables.
(line 323) (line 319)
* hub: Main configuration variables. * hub: Main configuration variables.
(line 247) (line 246)
* ID: Authentication protocol. * ID: Authentication protocol.
(line 10) (line 10)
* IndirectData: Host configuration variables. * IndirectData: Host configuration variables.
(line 34) (line 34)
* INTERFACE: Scripts. (line 58) * INTERFACE: Scripts. (line 58)
* Interface: Main configuration variables. * Interface: Main configuration variables.
(line 205) (line 204)
* IRC: Contact information. (line 9) * IRC: Contact information. (line 9)
* KEY_CHANGED: The meta-protocol. (line 64) * KEY_CHANGED: The meta-protocol. (line 64)
* KeyExpire: Main configuration variables. * KeyExpire: Main configuration variables.
(line 252) (line 251)
* libevent: libevent. (line 6) * libcurses: libcurses. (line 6)
* libraries: Libraries. (line 6) * libraries: Libraries. (line 6)
* libreadline: libreadline. (line 6)
* license: OpenSSL. (line 36) * license: OpenSSL. (line 36)
* LocalDiscovery: Main configuration variables. * LocalDiscovery: Main configuration variables.
(line 213) (line 212)
* lzo: lzo. (line 6) * lzo: lzo. (line 6)
* MACExpire: Main configuration variables. * MACExpire: Main configuration variables.
(line 258) (line 257)
* MACLength: Host configuration variables. * MACLength: Host configuration variables.
(line 42) (line 42)
* meta-protocol: The meta-connection. (line 18) * meta-protocol: The meta-connection. (line 18)
* META_KEY: Authentication protocol. * META_KEY: Authentication protocol.
(line 10) (line 10)
* Mode: Main configuration variables. * Mode: Main configuration variables.
(line 224) (line 223)
* multicast: Main configuration variables. * multicast: Main configuration variables.
(line 100) (line 107)
* multiple networks: Multiple networks. (line 6) * multiple networks: Multiple networks. (line 6)
* NAME: Scripts. (line 52) * NAME: Scripts. (line 52)
* Name: Main configuration variables. * Name: Main configuration variables.
(line 263) (line 262)
* netmask: Network interfaces. (line 39) * netmask: Network interfaces. (line 39)
* NETNAME <1>: tincctl environment variables. * NETNAME <1>: tincctl environment variables.
(line 6) (line 6)
@ -2908,9 +2941,9 @@ Concept Index
(line 67) (line 67)
* PING: The meta-protocol. (line 89) * PING: The meta-protocol. (line 89)
* PingInterval: Main configuration variables. * PingInterval: Main configuration variables.
(line 274) (line 273)
* PingTimeout: Main configuration variables. * PingTimeout: Main configuration variables.
(line 278) (line 277)
* platforms: Supported platforms. (line 6) * platforms: Supported platforms. (line 6)
* PMTU: Host configuration variables. * PMTU: Host configuration variables.
(line 47) (line 47)
@ -2921,32 +2954,32 @@ Concept Index
(line 55) (line 55)
* port numbers: Other files. (line 17) * port numbers: Other files. (line 17)
* PriorityInheritance: Main configuration variables. * PriorityInheritance: Main configuration variables.
(line 284) (line 283)
* private: Virtual Private Networks. * private: Virtual Private Networks.
(line 10) (line 10)
* PrivateKey: Main configuration variables. * PrivateKey: Main configuration variables.
(line 289) (line 288)
* PrivateKeyFile: Main configuration variables. * PrivateKeyFile: Main configuration variables.
(line 295) (line 294)
* ProcessPriority: Main configuration variables. * ProcessPriority: Main configuration variables.
(line 303) (line 299)
* Proxy: Main configuration variables. * Proxy: Main configuration variables.
(line 308) (line 304)
* PublicKey: Host configuration variables. * PublicKey: Host configuration variables.
(line 59) (line 59)
* PublicKeyFile: Host configuration variables. * PublicKeyFile: Host configuration variables.
(line 62) (line 62)
* raw_socket: Main configuration variables. * raw_socket: Main configuration variables.
(line 93) (line 100)
* release: Supported platforms. (line 14) * release: Supported platforms. (line 14)
* REMOTEADDRESS: Scripts. (line 67) * REMOTEADDRESS: Scripts. (line 67)
* REMOTEPORT: Scripts. (line 70) * REMOTEPORT: Scripts. (line 70)
* ReplayWindow: Main configuration variables. * ReplayWindow: Main configuration variables.
(line 331) (line 327)
* REQ_KEY: The meta-protocol. (line 64) * REQ_KEY: The meta-protocol. (line 64)
* requirements: Libraries. (line 6) * requirements: Libraries. (line 6)
* router: Main configuration variables. * router: Main configuration variables.
(line 227) (line 226)
* runtime options: Runtime options. (line 9) * runtime options: Runtime options. (line 9)
* scalability: tinc. (line 19) * scalability: tinc. (line 19)
* scripts: Scripts. (line 6) * scripts: Scripts. (line 6)
@ -2954,17 +2987,17 @@ Concept Index
(line 18) (line 18)
* signals: Signals. (line 6) * signals: Signals. (line 6)
* socks4: Main configuration variables. * socks4: Main configuration variables.
(line 312) (line 308)
* socks5: Main configuration variables. * socks5: Main configuration variables.
(line 317) (line 313)
* StrictSubnets: Main configuration variables. * StrictSubnets: Main configuration variables.
(line 342) (line 338)
* SUBNET: Scripts. (line 74) * SUBNET: Scripts. (line 74)
* Subnet: Host configuration variables. * Subnet: Host configuration variables.
(line 74) (line 74)
* SVPN: Security. (line 11) * SVPN: Security. (line 11)
* switch: Main configuration variables. * switch: Main configuration variables.
(line 236) (line 235)
* TCP: The meta-connection. (line 10) * TCP: The meta-connection. (line 10)
* TCPonly: Host configuration variables. * TCPonly: Host configuration variables.
(line 103) (line 103)
@ -2976,24 +3009,24 @@ Concept Index
* tincd: tinc. (line 14) * tincd: tinc. (line 14)
* traditional VPNs: tinc. (line 19) * traditional VPNs: tinc. (line 19)
* tunifhead: Main configuration variables. * tunifhead: Main configuration variables.
(line 135) (line 142)
* TunnelServer: Main configuration variables. * TunnelServer: Main configuration variables.
(line 347) (line 343)
* tunnohead: Main configuration variables. * tunnohead: Main configuration variables.
(line 129) (line 136)
* UDP <1>: Encryption of network packets. * UDP <1>: Encryption of network packets.
(line 12) (line 12)
* UDP: The UDP tunnel. (line 30) * UDP: The UDP tunnel. (line 30)
* UDPRcvBuf: Main configuration variables. * UDPRcvBuf: Main configuration variables.
(line 354) (line 350)
* UDPSndBuf: Main configuration variables. * UDPSndBuf: Main configuration variables.
(line 359) (line 355)
* UML: Main configuration variables. * UML: Main configuration variables.
(line 111) (line 118)
* Universal tun/tap: Configuration of Linux kernels. * Universal tun/tap: Configuration of Linux kernels.
(line 6) (line 6)
* VDE: Main configuration variables. * VDE: Main configuration variables.
(line 116) (line 123)
* virtual: Virtual Private Networks. * virtual: Virtual Private Networks.
(line 18) (line 18)
* virtual network device: The UDP tunnel. (line 6) * virtual network device: The UDP tunnel. (line 6)
@ -3021,57 +3054,58 @@ Node: Configuration of Solaris kernels8891
Node: Configuration of Darwin (MacOS/X) kernels9552 Node: Configuration of Darwin (MacOS/X) kernels9552
Node: Configuration of Windows10241 Node: Configuration of Windows10241
Node: Libraries10755 Node: Libraries10755
Node: OpenSSL11156 Node: OpenSSL11173
Node: zlib13432 Node: zlib13461
Node: lzo14261 Node: lzo14487
Node: libevent15065 Node: libcurses15485
Node: Installation15760 Node: libreadline16405
Node: Building and installing tinc16776 Node: Installation17353
Node: Darwin (MacOS/X) build environment17435 Node: Building and installing tinc18369
Node: Cygwin (Windows) build environment18002 Node: Darwin (MacOS/X) build environment19028
Node: MinGW (Windows) build environment18590 Node: Cygwin (Windows) build environment19595
Node: System files19114 Node: MinGW (Windows) build environment20183
Node: Device files19379 Node: System files20707
Node: Other files19795 Node: Device files20972
Node: Configuration20408 Node: Other files21388
Node: Configuration introduction20695 Node: Configuration22001
Node: Multiple networks22242 Node: Configuration introduction22288
Node: How connections work23622 Node: Multiple networks23835
Node: Configuration files26195 Node: How connections work25215
Node: Main configuration variables27728 Node: Configuration files27788
Node: Host configuration variables44334 Node: Main configuration variables29321
Node: Scripts49564 Node: Host configuration variables45731
Node: How to configure52243 Node: Scripts50961
Node: Network interfaces56861 Node: How to configure53640
Node: Example configuration59262 Node: Network interfaces58258
Node: Running tinc64414 Node: Example configuration60659
Node: Runtime options65007 Node: Running tinc65811
Node: Signals67711 Node: Runtime options66404
Node: Debug levels68561 Node: Signals69108
Node: Solving problems69497 Node: Debug levels69958
Node: Error messages70927 Node: Solving problems70894
Node: Sending bug reports75249 Node: Error messages72324
Node: Controlling tinc76201 Node: Sending bug reports76646
Node: tincctl runtime options76598 Node: Controlling tinc77598
Node: tincctl environment variables77297 Node: tincctl runtime options77995
Node: tincctl commands77641 Node: tincctl environment variables78694
Node: tincctl examples81866 Node: tincctl commands79038
Node: tincctl top82471 Node: tincctl examples83343
Node: Technical information84069 Node: tincctl top83948
Node: The connection84304 Node: Technical information85546
Node: The UDP tunnel84616 Node: The connection85781
Node: The meta-connection87677 Node: The UDP tunnel86093
Node: The meta-protocol89146 Node: The meta-connection89154
Node: Security94155 Node: The meta-protocol90623
Node: Authentication protocol95285 Node: Security95632
Node: Encryption of network packets100289 Node: Authentication protocol96762
Node: Security issues101662 Node: Encryption of network packets101766
Node: Platform specific information103279 Node: Security issues103139
Node: Interface configuration103507 Node: Platform specific information104756
Node: Routes105960 Node: Interface configuration104984
Node: About us107876 Node: Routes107437
Node: Contact information108051 Node: About us109353
Node: Authors108455 Node: Contact information109528
Node: Concept Index108860 Node: Authors109932
Node: Concept Index110337
 
End Tag Table End Tag Table

View file

@ -339,7 +339,8 @@ having them installed, configure will give you an error message, and stop.
* OpenSSL:: * OpenSSL::
* zlib:: * zlib::
* lzo:: * lzo::
* libevent:: * libcurses::
* libreadline::
@end menu @end menu
@ -352,7 +353,7 @@ For all cryptography-related functions, tinc uses the functions provided
by the OpenSSL library. by the OpenSSL library.
If this library is not installed, you wil get an error when configuring If this library is not installed, you wil get an error when configuring
tinc for build. Support for running tinc without having OpenSSL tinc for build. Support for running tinc with other cryptographic libraries
installed @emph{may} be added in the future. installed @emph{may} be added in the future.
You can use your operating system's package manager to install this if You can use your operating system's package manager to install this if
@ -415,9 +416,11 @@ Markus F.X.J. Oberhumer
For the optional compression of UDP packets, tinc uses the functions provided For the optional compression of UDP packets, tinc uses the functions provided
by the zlib library. by the zlib library.
If this library is not installed, you wil get an error when configuring If this library is not installed, you wil get an error when running the
tinc for build. Support for running tinc without having zlib configure script. You can either install the zlib library, or disable support
installed @emph{may} be added in the future. for zlib compression by using the "--disable-zlib" option when running the
configure script. Note that if you disable support for zlib, the resulting
binary will not work correctly on VPNs where zlib compression is used.
You can use your operating system's package manager to install this if You can use your operating system's package manager to install this if
available. Make sure you install the development AND runtime versions available. Make sure you install the development AND runtime versions
@ -435,11 +438,13 @@ default).
@subsection lzo @subsection lzo
@cindex lzo @cindex lzo
Another form of compression is offered using the lzo library. Another form of compression is offered using the LZO library.
If this library is not installed, you wil get an error when configuring If this library is not installed, you wil get an error when running the
tinc for build. Support for running tinc without having lzo configure script. You can either install the LZO library, or disable support
installed @emph{may} be added in the future. for LZO compression by using the "--disable-lzo" option when running the
configure script. Note that if you disable support for LZO, the resulting
binary will not work correctly on VPNs where LZO compression is used.
You can use your operating system's package manager to install this if You can use your operating system's package manager to install this if
available. Make sure you install the development AND runtime versions available. Make sure you install the development AND runtime versions
@ -453,24 +458,48 @@ default).
@c ================================================================== @c ==================================================================
@node libevent @node libcurses
@subsection libevent @subsection libcurses
@cindex libevent @cindex libcurses
For the main event loop, tinc uses the libevent library. For the "tincctl top" command, tinc requires a curses library.
If this library is not installed, you wil get an error when configuring If this library is not installed, you wil get an error when running the
tinc for build. configure script. You can either install a suitable curses library, or disable
all functionality that depends on a curses library by using the
"--disable-curses" option when running the configure script.
There are several curses libraries. It is recommended that you install
"ncurses" (@url{http://invisible-island.net/ncurses/}),
however other curses libraries should also work.
In particular, "PDCurses" (@url{http://pdcurses.sourceforge.net/})
is recommended if you want to compile tinc for Windows.
You can use your operating system's package manager to install this if
available. Make sure you install the development AND runtime versions
of this package.
@c ==================================================================
@node libreadline
@subsection libreadline
@cindex libreadline
For the "tincctl" command's shell functionality, tinc uses the readline library.
If this library is not installed, you wil get an error when running the
configure script. You can either install a suitable readline library, or
disable all functionality that depends on a readline library by using the
"--disable-readline" option when running the configure script.
You can use your operating system's package manager to install this if You can use your operating system's package manager to install this if
available. Make sure you install the development AND runtime versions available. Make sure you install the development AND runtime versions
of this package. of this package.
If you have to install libevent manually, you can get the source code If you have to install libreadline manually, you can get the source code from
from @url{http://libevent.org/}. Instructions on how to configure, @url{http://www.gnu.org/software/readline/}. Instructions on how to configure,
build and install this package are included within the package. Please build and install this package are included within the package. Please make
make sure you build development and runtime libraries (which is the sure you build development and runtime libraries (which is the default).
default).
@c @c
@ -805,6 +834,14 @@ This option affects the address family of listening and outgoing sockets.
If any is selected, then depending on the operating system If any is selected, then depending on the operating system
both IPv4 and IPv6 or just IPv6 listening sockets will be created. both IPv4 and IPv6 or just IPv6 listening sockets will be created.
@cindex AutoConnect
@item AutoConnect = <count> (0) [experimental]
If set to a non-zero value,
tinc will try to only have count meta connections to other nodes,
by automatically making or breaking connections to known nodes.
Higher values increase redundancy but also increase meta data overhead.
When using this option, a good value is 3.
@cindex BindToAddress @cindex BindToAddress
@item BindToAddress = <@var{address}> [<@var{port}>] @item BindToAddress = <@var{address}> [<@var{port}>]
If your computer has more than one IPv4 or IPv6 address, tinc If your computer has more than one IPv4 or IPv6 address, tinc
@ -990,16 +1027,6 @@ This is less efficient, but allows the kernel to apply its routing and firewall
and can also help debugging. and can also help debugging.
@end table @end table
@cindex GraphDumpFile
@item GraphDumpFile = <@var{filename}>
If this option is present,
tinc will dump the current network graph to the file @var{filename}
every minute, unless there were no changes to the graph.
The file is in a format that can be read by graphviz tools.
If @var{filename} starts with a pipe symbol |,
then the rest of the filename is interpreted as a shell command
that is executed, the graph is then sent to stdin.
@cindex Hostnames @cindex Hostnames
@item Hostnames = <yes|no> (no) @item Hostnames = <yes|no> (no)
This option selects whether IP addresses (both real and on the VPN) This option selects whether IP addresses (both real and on the VPN)
@ -1106,10 +1133,6 @@ This is the full path name of the RSA private key file that was
generated by @samp{tincctl generate-keys}. It must be a full path, not a generated by @samp{tincctl generate-keys}. It must be a full path, not a
relative directory. relative directory.
Note that there must be exactly one of PrivateKey
or PrivateKeyFile
specified in the configuration file.
@cindex ProcessPriority @cindex ProcessPriority
@item ProcessPriority = <low|normal|high> @item ProcessPriority = <low|normal|high>
When this option is used the priority of the tincd process will be adjusted. When this option is used the priority of the tincd process will be adjusted.
@ -2199,8 +2222,9 @@ Generate public/private keypair of @var{bits} length. If @var{bits} is not speci
but will default to the configuration directory (you can use the -c or -n but will default to the configuration directory (you can use the -c or -n
option). option).
@item dump nodes @item dump [reachable] nodes
Dump a list of all known nodes in the VPN. Dump a list of all known nodes in the VPN.
If the reachable keyword is used, only lists reachable nodes.
@item dump edges @item dump edges
Dump a list of all known connections in the VPN. Dump a list of all known connections in the VPN.

View file

@ -45,7 +45,6 @@ If no netname is specified on the command line with the
option, the value of this environment variable is used. option, the value of this environment variable is used.
.El .El
.Sh COMMANDS .Sh COMMANDS
.zZ
.Bl -tag -width indent .Bl -tag -width indent
.It init Op Ar name .It init Op Ar name
Create initial configuration files and RSA and ECDSA keypairs with default length. Create initial configuration files and RSA and ECDSA keypairs with default length.
@ -115,9 +114,9 @@ If
is omitted, the default length will be 2048 bits. is omitted, the default length will be 2048 bits.
When saving keys to existing files, tinc will not delete the old keys; When saving keys to existing files, tinc will not delete the old keys;
you have to remove them manually. you have to remove them manually.
.It dump [reachable] nodes
.It dump nodes
Dump a list of all known nodes in the VPN. Dump a list of all known nodes in the VPN.
If the keyword reachable is used, only lists reachable nodes.
.It dump edges .It dump edges
Dump a list of all known connections in the VPN. Dump a list of all known connections in the VPN.
.It dump subnets .It dump subnets
@ -190,6 +189,7 @@ tincctl -n vpn config Subnet 192.168.1.0/24
tincctl -n vpn config bar.Address bar.example.com tincctl -n vpn config bar.Address bar.example.com
tincctl -n vpn config ConnectTo bar tincctl -n vpn config ConnectTo bar
tincctl -n vpn export | gpg --clearsign | mail -s "My config" vpnmaster@example.com tincctl -n vpn export | gpg --clearsign | mail -s "My config" vpnmaster@example.com
.Ed
.Sh TOP .Sh TOP
The top command connects to a running tinc daemon and repeatedly queries its per-node traffic counters. The top command connects to a running tinc daemon and repeatedly queries its per-node traffic counters.
It displays a list of all the known nodes in the left-most column, It displays a list of all the known nodes in the left-most column,

View file

@ -56,10 +56,9 @@ DIST_COMMON = $(dist_bin_SCRIPTS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/libevent.m4 \ $(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \
$(top_srcdir)/m4/lzo.m4 $(top_srcdir)/m4/openssl.m4 \ $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \
$(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/zlib.m4 \ $(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.in
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4) $(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d mkinstalldirs = $(install_sh) -d

4
have.h
View file

@ -196,10 +196,6 @@
#include <netinet/if_ether.h> #include <netinet/if_ether.h>
#endif #endif
#ifdef HAVE_EVENT_H
#include <event.h>
#endif
#ifdef HAVE_MINGW #ifdef HAVE_MINGW
#define SLASH "\\" #define SLASH "\\"
#else #else

View file

@ -54,10 +54,9 @@ subdir = m4
DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/libevent.m4 \ $(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \
$(top_srcdir)/m4/lzo.m4 $(top_srcdir)/m4/openssl.m4 \ $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \
$(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/zlib.m4 \ $(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.in
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4) $(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d mkinstalldirs = $(install_sh) -d

View file

@ -1,33 +0,0 @@
dnl Check to find the libevent headers/libraries
AC_DEFUN([tinc_LIBEVENT],
[
AC_ARG_WITH(libevent,
AS_HELP_STRING([--with-libevent=DIR], [libevent base directory, or:]),
[libevent="$withval"
CPPFLAGS="$CPPFLAGS -I$withval/include"
LDFLAGS="$LDFLAGS -L$withval/lib"]
)
AC_ARG_WITH(libevent-include,
AS_HELP_STRING([--with-libevent-include=DIR], [libevent headers directory]),
[libevent_include="$withval"
CPPFLAGS="$CPPFLAGS -I$withval"]
)
AC_ARG_WITH(libevent-lib,
AS_HELP_STRING([--with-libevent-lib=DIR], [libevent library directory]),
[libevent_lib="$withval"
LDFLAGS="$LDFLAGS -L$withval"]
)
AC_CHECK_HEADERS(event.h,
[],
[AC_MSG_ERROR("libevent header files not found."); break]
)
AC_CHECK_LIB(event, event_init,
[LIBS="-levent $LIBS"],
[AC_MSG_ERROR("libevent libraries not found.")]
)
])

View file

@ -8,7 +8,7 @@ tincd_SOURCES = \
utils.c getopt.c getopt1.c list.c splay_tree.c dropin.c fake-getaddrinfo.c fake-getnameinfo.c hash.c \ utils.c getopt.c getopt1.c list.c splay_tree.c dropin.c fake-getaddrinfo.c fake-getnameinfo.c hash.c \
buffer.c conf.c connection.c control.c edge.c graph.c logger.c meta.c net.c net_packet.c net_setup.c \ buffer.c conf.c connection.c control.c edge.c graph.c logger.c meta.c net.c net_packet.c net_setup.c \
net_socket.c netutl.c node.c process.c protocol.c protocol_auth.c protocol_edge.c protocol_misc.c \ net_socket.c netutl.c node.c process.c protocol.c protocol_auth.c protocol_edge.c protocol_misc.c \
protocol_key.c protocol_subnet.c route.c sptps.c subnet.c subnet_parse.c tincd.c \ protocol_key.c protocol_subnet.c route.c sptps.c subnet.c subnet_parse.c event.c tincd.c \
dummy_device.c raw_socket_device.c multicast_device.c dummy_device.c raw_socket_device.c multicast_device.c
if UML if UML
@ -46,7 +46,7 @@ INCLUDES = @INCLUDES@ -I$(top_builddir)
noinst_HEADERS = \ noinst_HEADERS = \
xalloc.h utils.h getopt.h list.h splay_tree.h dropin.h fake-getaddrinfo.h fake-getnameinfo.h fake-gai-errnos.h ipv6.h ipv4.h ethernet.h \ xalloc.h utils.h getopt.h list.h splay_tree.h dropin.h fake-getaddrinfo.h fake-getnameinfo.h fake-gai-errnos.h ipv6.h ipv4.h ethernet.h \
buffer.h conf.h connection.h control.h control_common.h device.h edge.h graph.h info.h logger.h meta.h net.h netutl.h node.h process.h \ buffer.h conf.h connection.h control.h control_common.h device.h edge.h graph.h info.h logger.h meta.h net.h netutl.h node.h process.h \
protocol.h route.h subnet.h sptps.h tincctl.h top.h bsd/tunemu.h hash.h protocol.h route.h subnet.h sptps.h tincctl.h top.h bsd/tunemu.h hash.h event.h
nodist_noinst_HEADERS = \ nodist_noinst_HEADERS = \
cipher.h crypto.h ecdh.h ecdsa.h digest.h prf.h rsa.h ecdsagen.h rsagen.h cipher.h crypto.h ecdh.h ecdsa.h digest.h prf.h rsa.h ecdsagen.h rsagen.h

View file

@ -62,10 +62,9 @@ DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/libevent.m4 \ $(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \
$(top_srcdir)/m4/lzo.m4 $(top_srcdir)/m4/openssl.m4 \ $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \
$(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/zlib.m4 \ $(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.in
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4) $(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d mkinstalldirs = $(install_sh) -d
@ -95,8 +94,8 @@ am__tincd_SOURCES_DIST = utils.c getopt.c getopt1.c list.c \
netutl.c node.c process.c protocol.c protocol_auth.c \ netutl.c node.c process.c protocol.c protocol_auth.c \
protocol_edge.c protocol_misc.c protocol_key.c \ protocol_edge.c protocol_misc.c protocol_key.c \
protocol_subnet.c route.c sptps.c subnet.c subnet_parse.c \ protocol_subnet.c route.c sptps.c subnet.c subnet_parse.c \
tincd.c dummy_device.c raw_socket_device.c multicast_device.c \ event.c tincd.c dummy_device.c raw_socket_device.c \
uml_device.c vde_device.c bsd/tunemu.c multicast_device.c uml_device.c vde_device.c bsd/tunemu.c
@UML_TRUE@am__objects_1 = uml_device.$(OBJEXT) @UML_TRUE@am__objects_1 = uml_device.$(OBJEXT)
@VDE_TRUE@am__objects_2 = vde_device.$(OBJEXT) @VDE_TRUE@am__objects_2 = vde_device.$(OBJEXT)
@TUNEMU_TRUE@am__objects_3 = tunemu.$(OBJEXT) @TUNEMU_TRUE@am__objects_3 = tunemu.$(OBJEXT)
@ -112,9 +111,10 @@ am_tincd_OBJECTS = utils.$(OBJEXT) getopt.$(OBJEXT) getopt1.$(OBJEXT) \
protocol_edge.$(OBJEXT) protocol_misc.$(OBJEXT) \ protocol_edge.$(OBJEXT) protocol_misc.$(OBJEXT) \
protocol_key.$(OBJEXT) protocol_subnet.$(OBJEXT) \ protocol_key.$(OBJEXT) protocol_subnet.$(OBJEXT) \
route.$(OBJEXT) sptps.$(OBJEXT) subnet.$(OBJEXT) \ route.$(OBJEXT) sptps.$(OBJEXT) subnet.$(OBJEXT) \
subnet_parse.$(OBJEXT) tincd.$(OBJEXT) dummy_device.$(OBJEXT) \ subnet_parse.$(OBJEXT) event.$(OBJEXT) tincd.$(OBJEXT) \
raw_socket_device.$(OBJEXT) multicast_device.$(OBJEXT) \ dummy_device.$(OBJEXT) raw_socket_device.$(OBJEXT) \
$(am__objects_1) $(am__objects_2) $(am__objects_3) multicast_device.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
$(am__objects_3)
nodist_tincd_OBJECTS = device.$(OBJEXT) cipher.$(OBJEXT) \ nodist_tincd_OBJECTS = device.$(OBJEXT) cipher.$(OBJEXT) \
crypto.$(OBJEXT) ecdh.$(OBJEXT) ecdsa.$(OBJEXT) \ crypto.$(OBJEXT) ecdh.$(OBJEXT) ecdsa.$(OBJEXT) \
digest.$(OBJEXT) prf.$(OBJEXT) rsa.$(OBJEXT) digest.$(OBJEXT) prf.$(OBJEXT) rsa.$(OBJEXT)
@ -251,7 +251,7 @@ tincd_SOURCES = utils.c getopt.c getopt1.c list.c splay_tree.c \
net.c net_packet.c net_setup.c net_socket.c netutl.c node.c \ net.c net_packet.c net_setup.c net_socket.c netutl.c node.c \
process.c protocol.c protocol_auth.c protocol_edge.c \ process.c protocol.c protocol_auth.c protocol_edge.c \
protocol_misc.c protocol_key.c protocol_subnet.c route.c \ protocol_misc.c protocol_key.c protocol_subnet.c route.c \
sptps.c subnet.c subnet_parse.c tincd.c dummy_device.c \ sptps.c subnet.c subnet_parse.c event.c tincd.c dummy_device.c \
raw_socket_device.c multicast_device.c $(am__append_1) \ raw_socket_device.c multicast_device.c $(am__append_1) \
$(am__append_2) $(am__append_3) $(am__append_2) $(am__append_3)
nodist_tincd_SOURCES = \ nodist_tincd_SOURCES = \
@ -273,7 +273,7 @@ DEFAULT_INCLUDES =
noinst_HEADERS = \ noinst_HEADERS = \
xalloc.h utils.h getopt.h list.h splay_tree.h dropin.h fake-getaddrinfo.h fake-getnameinfo.h fake-gai-errnos.h ipv6.h ipv4.h ethernet.h \ xalloc.h utils.h getopt.h list.h splay_tree.h dropin.h fake-getaddrinfo.h fake-getnameinfo.h fake-gai-errnos.h ipv6.h ipv4.h ethernet.h \
buffer.h conf.h connection.h control.h control_common.h device.h edge.h graph.h info.h logger.h meta.h net.h netutl.h node.h process.h \ buffer.h conf.h connection.h control.h control_common.h device.h edge.h graph.h info.h logger.h meta.h net.h netutl.h node.h process.h \
protocol.h route.h subnet.h sptps.h tincctl.h top.h bsd/tunemu.h hash.h protocol.h route.h subnet.h sptps.h tincctl.h top.h bsd/tunemu.h hash.h event.h
nodist_noinst_HEADERS = \ nodist_noinst_HEADERS = \
cipher.h crypto.h ecdh.h ecdsa.h digest.h prf.h rsa.h ecdsagen.h rsagen.h cipher.h crypto.h ecdh.h ecdsa.h digest.h prf.h rsa.h ecdsagen.h rsagen.h
@ -383,6 +383,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecdsa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecdsa.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecdsagen.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecdsagen.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edge.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edge.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fake-getaddrinfo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fake-getaddrinfo.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fake-getnameinfo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fake-getnameinfo.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@

View file

@ -68,11 +68,7 @@ void free_connection(connection_t *c) {
buffer_clear(&c->inbuf); buffer_clear(&c->inbuf);
buffer_clear(&c->outbuf); buffer_clear(&c->outbuf);
if(event_initialized(&c->inevent)) io_del(&c->io);
event_del(&c->inevent);
if(event_initialized(&c->outevent))
event_del(&c->outevent);
if(c->socket > 0) if(c->socket > 0)
closesocket(c->socket); closesocket(c->socket);

View file

@ -90,8 +90,7 @@ typedef struct connection_t {
struct buffer_t inbuf; struct buffer_t inbuf;
struct buffer_t outbuf; struct buffer_t outbuf;
struct event inevent; /* input event on this metadata connection */ io_t io; /* input/output event on this metadata connection */
struct event outevent; /* output event on this metadata connection */
int tcplen; /* length of incoming TCPpacket */ int tcplen; /* length of incoming TCPpacket */
int allow_request; /* defined if there's only one request possible */ int allow_request; /* defined if there's only one request possible */

View file

@ -58,7 +58,7 @@ bool control_h(connection_t *c, const char *request) {
switch (type) { switch (type) {
case REQ_STOP: case REQ_STOP:
event_loopexit(NULL); event_exit();
return control_ok(c, REQ_STOP); return control_ok(c, REQ_STOP);
case REQ_DUMP_NODES: case REQ_DUMP_NODES:
@ -156,7 +156,7 @@ bool init_control(void) {
// Make sure we have a valid address, and map 0.0.0.0 and :: to 127.0.0.1 and ::1. // Make sure we have a valid address, and map 0.0.0.0 and :: to 127.0.0.1 and ::1.
if(getsockname(listen_socket[0].tcp, (struct sockaddr *)&sa, &len)) { if(getsockname(listen_socket[0].tcp.fd, (struct sockaddr *)&sa, &len)) {
xasprintf(&localhost, "127.0.0.1 port %d", myport); xasprintf(&localhost, "127.0.0.1 port %d", myport);
} else { } else {
if(sa.sa.sa_family == AF_INET) { if(sa.sa.sa_family == AF_INET) {

View file

@ -45,4 +45,22 @@ extern int gettimeofday(struct timeval *, void *);
extern int usleep(long long usec); extern int usleep(long long usec);
#endif #endif
#ifndef timeradd
#define timeradd(a, b, r) do {\
(r)->tv_sec = (a)->tv_sec + (b)->tv_sec;\
(r)->tv_usec = (a)->tv_usec + (b)->tv_usec;\
if((r)->tv_usec >= 1000000)\
(r)->tv_sec++, (r)->tv_usec -= 1000000;\
} while (0)
#endif
#ifndef timersub
#define timersub(a, b, r) do {\
(r)->tv_sec = (a)->tv_sec - (b)->tv_sec;\
(r)->tv_usec = (a)->tv_usec - (b)->tv_usec;\
if((r)->tv_usec < 1000000)\
(r)->tv_sec--, (r)->tv_usec += 1000000;\
} while (0)
#endif
#endif /* __DROPIN_H__ */ #endif /* __DROPIN_H__ */

View file

@ -41,6 +41,10 @@
#define ETH_P_IPV6 0x86DD #define ETH_P_IPV6 0x86DD
#endif #endif
#ifndef ETH_P_8021Q
#define ETH_P_8021Q 0x8100
#endif
#ifndef HAVE_STRUCT_ETHER_HEADER #ifndef HAVE_STRUCT_ETHER_HEADER
struct ether_header { struct ether_header {
uint8_t ether_dhost[ETH_ALEN]; uint8_t ether_dhost[ETH_ALEN];

250
src/event.c Normal file
View file

@ -0,0 +1,250 @@
/*
event.c -- I/O, timeout and signal event handling
Copyright (C) 2012 Guus Sliepen <guus@tinc-vpn.org>
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "system.h"
#include "dropin.h"
#include "event.h"
#include "net.h"
#include "utils.h"
struct timeval now;
static fd_set readfds;
static fd_set writefds;
static volatile bool running;
static int io_compare(const io_t *a, const io_t *b) {
return a->fd - b->fd;
}
static int timeout_compare(const timeout_t *a, const timeout_t *b) {
struct timeval diff;
timersub(&a->tv, &b->tv, &diff);
if(diff.tv_sec < 0)
return -1;
if(diff.tv_sec > 0)
return 1;
if(diff.tv_usec < 0)
return -1;
if(diff.tv_usec > 0)
return 1;
if(a < b)
return -1;
if(a > b)
return 1;
return 0;
}
static int signal_compare(const signal_t *a, const signal_t *b) {
return a->signum - b->signum;
}
static splay_tree_t io_tree = {.compare = (splay_compare_t)io_compare};
static splay_tree_t timeout_tree = {.compare = (splay_compare_t)timeout_compare};
static splay_tree_t signal_tree = {.compare = (splay_compare_t)signal_compare};
void io_add(io_t *io, io_cb_t cb, void *data, int fd, int flags) {
if(io->cb)
return;
io->fd = fd;
io->cb = cb;
io->data = data;
io->node.data = io;
io_set(io, flags);
if(!splay_insert_node(&io_tree, &io->node))
abort();
}
void io_set(io_t *io, int flags) {
io->flags = flags;
if(flags & IO_READ)
FD_SET(io->fd, &readfds);
else
FD_CLR(io->fd, &readfds);
if(flags & IO_WRITE)
FD_SET(io->fd, &writefds);
else
FD_CLR(io->fd, &writefds);
}
void io_del(io_t *io) {
if(!io->cb)
return;
io_set(io, 0);
splay_unlink_node(&io_tree, &io->node);
io->cb = NULL;
}
void timeout_add(timeout_t *timeout, timeout_cb_t cb, void *data, struct timeval *tv) {
timeout->cb = cb;
timeout->data = data;
timeout->node.data = timeout;
timeout_set(timeout, tv);
}
void timeout_set(timeout_t *timeout, struct timeval *tv) {
if(timerisset(&timeout->tv))
splay_unlink_node(&timeout_tree, &timeout->node);
if(!now.tv_sec)
gettimeofday(&now, NULL);
timeradd(&now, tv, &timeout->tv);
if(!splay_insert_node(&timeout_tree, &timeout->node))
abort();
}
void timeout_del(timeout_t *timeout) {
if(!timeout->cb)
return;
splay_unlink_node(&timeout_tree, &timeout->node);
timeout->cb = 0;
timeout->tv = (struct timeval){0, 0};
}
#ifndef HAVE_MINGW
static io_t signalio;
static int pipefd[2] = {-1, -1};
static void signal_handler(int signum) {
unsigned char num = signum;
write(pipefd[1], &num, 1);
}
static void signalio_handler(void *data, int flags) {
unsigned char signum;
if(read(pipefd[0], &signum, 1) != 1)
return;
signal_t *sig = splay_search(&signal_tree, &((signal_t){.signum = signum}));
if(sig)
sig->cb(sig->data);
}
static void pipe_init(void) {
if(!pipe(pipefd))
io_add(&signalio, signalio_handler, NULL, pipefd[0], IO_READ);
}
void signal_add(signal_t *sig, signal_cb_t cb, void *data, int signum) {
if(sig->cb)
return;
sig->cb = cb;
sig->data = data;
sig->signum = signum;
sig->node.data = sig;
if(pipefd[0] == -1)
pipe_init();
signal(sig->signum, signal_handler);
if(!splay_insert_node(&signal_tree, &sig->node))
abort();
}
void signal_del(signal_t *sig) {
if(!sig->cb)
return;
signal(sig->signum, SIG_DFL);
splay_unlink_node(&signal_tree, &sig->node);
sig->cb = NULL;
}
#endif
bool event_loop(void) {
running = true;
fd_set readable;
fd_set writable;
while(running) {
gettimeofday(&now, NULL);
struct timeval diff, *tv = NULL;
while(timeout_tree.head) {
timeout_t *timeout = timeout_tree.head->data;
timersub(&timeout->tv, &now, &diff);
if(diff.tv_sec < 0) {
timeout->cb(timeout->data);
if(timercmp(&timeout->tv, &now, <))
timeout_del(timeout);
} else {
tv = &diff;
break;
}
}
memcpy(&readable, &readfds, sizeof readable);
memcpy(&writable, &writefds, sizeof writable);
int fds = 0;
if(io_tree.tail) {
io_t *last = io_tree.tail->data;
fds = last->fd + 1;
}
#ifdef HAVE_MINGW
LeaveCriticalSection(&mutex);
#endif
int n = select(fds, &readable, &writable, NULL, tv);
#ifdef HAVE_MINGW
EnterCriticalSection(&mutex);
#endif
if(n < 0) {
if(sockwouldblock(errno))
continue;
else
return false;
}
if(!n)
continue;
for splay_each(io_t, io, &io_tree) {
if(FD_ISSET(io->fd, &writable))
io->cb(io->data, IO_WRITE);
else if(FD_ISSET(io->fd, &readable))
io->cb(io->data, IO_READ);
}
}
return true;
}
void event_exit(void) {
running = false;
}

70
src/event.h Normal file
View file

@ -0,0 +1,70 @@
/*
event.h -- I/O, timeout and signal event handling
Copyright (C) 2012 Guus Sliepen <guus@tinc-vpn.org>
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_EVENT_H__
#define __TINC_EVENT_H__
#include "splay_tree.h"
#define IO_READ 1
#define IO_WRITE 2
typedef void (*io_cb_t)(void *data, int flags);
typedef void (*timeout_cb_t)(void *data);
typedef void (*signal_cb_t)(void *data);
typedef struct io_t {
int fd;
int flags;
io_cb_t cb;
void *data;
splay_node_t node;
} io_t;
typedef struct timeout_t {
struct timeval tv;
timeout_cb_t cb;
void *data;
splay_node_t node;
} timeout_t;
typedef struct signal_t {
int signum;
signal_cb_t cb;
void *data;
splay_node_t node;
} signal_t;
extern struct timeval now;
extern void io_add(io_t *io, io_cb_t cb, void *data, int fd, int flags);
extern void io_del(io_t *io);
extern void io_set(io_t *io, int flags);
extern void timeout_add(timeout_t *timeout, timeout_cb_t cb, void *data, struct timeval *tv);
extern void timeout_del(timeout_t *timeout);
extern void timeout_set(timeout_t *timeout, struct timeval *tv);
extern void signal_add(signal_t *sig, signal_cb_t cb, void *data, int signum);
extern void signal_del(signal_t *sig);
extern bool event_loop(void);
extern void event_exit(void);
#endif

View file

@ -213,8 +213,7 @@ static void check_reachability(void) {
n->minmtu = 0; n->minmtu = 0;
n->mtuprobes = 0; n->mtuprobes = 0;
if(timeout_initialized(&n->mtuevent)) timeout_del(&n->mtutimeout);
event_del(&n->mtuevent);
char *name; char *name;
char *address; char *address;

View file

@ -55,7 +55,7 @@ hash_t *hash_alloc(size_t n, size_t size) {
hash_t *hash = xmalloc_and_zero(sizeof *hash); hash_t *hash = xmalloc_and_zero(sizeof *hash);
hash->n = n; hash->n = n;
hash->size = size; hash->size = size;
hash->keys = xmalloc(hash->n * hash->size); hash->keys = xmalloc_and_zero(hash->n * hash->size);
hash->values = xmalloc_and_zero(hash->n * sizeof *hash->values); hash->values = xmalloc_and_zero(hash->n * sizeof *hash->values);
return hash; return hash;
} }
@ -100,6 +100,8 @@ void hash_clear(hash_t *hash) {
void hash_resize(hash_t *hash, size_t n) { void hash_resize(hash_t *hash, size_t n) {
hash->keys = xrealloc(hash->keys, n * hash->size); hash->keys = xrealloc(hash->keys, n * hash->size);
hash->values = xrealloc(hash->values, n * sizeof *hash->values); hash->values = xrealloc(hash->values, n * sizeof *hash->values);
if(n > hash->n) if(n > hash->n) {
memset(hash->keys + hash->n * hash->size, 0, (n - hash->n) * hash->size);
memset(hash->values + hash->n, 0, (n - hash->n) * sizeof *hash->values); memset(hash->values + hash->n, 0, (n - hash->n) * sizeof *hash->values);
}
} }

View file

@ -41,7 +41,6 @@ bool logcontrol = false;
static void real_logger(int level, int priority, const char *message) { static void real_logger(int level, int priority, const char *message) {
char timestr[32] = ""; char timestr[32] = "";
time_t now;
static bool suppress = false; static bool suppress = false;
// Bail out early if there is nothing to do. // Bail out early if there is nothing to do.
@ -58,8 +57,10 @@ static void real_logger(int level, int priority, const char *message) {
fflush(stderr); fflush(stderr);
break; break;
case LOGMODE_FILE: case LOGMODE_FILE:
now = time(NULL); if(!now.tv_sec)
strftime(timestr, sizeof timestr, "%Y-%m-%d %H:%M:%S", localtime(&now)); gettimeofday(&now, NULL);
time_t now_sec = now.tv_sec;
strftime(timestr, sizeof timestr, "%Y-%m-%d %H:%M:%S", localtime(&now_sec));
fprintf(logfile, "%s %s[%ld]: %s\n", timestr, logident, (long)logpid, message); fprintf(logfile, "%s %s[%ld]: %s\n", timestr, logident, (long)logpid, message);
fflush(logfile); fflush(logfile);
break; break;

View file

@ -39,7 +39,7 @@ bool send_meta_sptps(void *handle, uint8_t type, const char *buffer, size_t leng
} }
buffer_add(&c->outbuf, buffer, length); buffer_add(&c->outbuf, buffer, length);
event_add(&c->outevent, NULL); io_set(&c->io, IO_READ | IO_WRITE);
return true; return true;
} }
@ -65,12 +65,11 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
c->name, c->hostname); c->name, c->hostname);
return false; return false;
} }
} else { } else {
buffer_add(&c->outbuf, buffer, length); buffer_add(&c->outbuf, buffer, length);
} }
event_add(&c->outevent, NULL); io_set(&c->io, IO_READ | IO_WRITE);
return true; return true;
} }

175
src/net.c
View file

@ -74,7 +74,7 @@ void purge(void) {
if(e->to == n) if(e->to == n)
return; return;
if(!strictsubnets || !n->subnet_tree->head) if(!autoconnect && (!strictsubnets || !n->subnet_tree->head))
/* in strictsubnets mode do not delete nodes with subnets */ /* in strictsubnets mode do not delete nodes with subnets */
node_del(n); node_del(n);
} }
@ -137,18 +137,16 @@ void terminate_connection(connection_t *c, bool report) {
end does not reply in time, we consider them dead end does not reply in time, we consider them dead
and close the connection. and close the connection.
*/ */
static void timeout_handler(int fd, short events, void *event) { static void timeout_handler(void *data) {
time_t now = time(NULL);
for list_each(connection_t, c, connection_list) { for list_each(connection_t, c, connection_list) {
if(c->status.control) if(c->status.control)
continue; continue;
if(c->last_ping_time + pingtimeout <= now) { if(c->last_ping_time + pingtimeout <= now.tv_sec) {
if(c->status.active) { if(c->status.active) {
if(c->status.pinged) { if(c->status.pinged) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds", c->name, c->hostname, (long)now - c->last_ping_time); logger(DEBUG_CONNECTIONS, LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds", c->name, c->hostname, (long)now.tv_sec - c->last_ping_time);
} else if(c->last_ping_time + pinginterval <= now) { } else if(c->last_ping_time + pinginterval <= now.tv_sec) {
send_ping(c); send_ping(c);
continue; continue;
} else { } else {
@ -164,6 +162,15 @@ static void timeout_handler(int fd, short events, void *event) {
} }
} }
timeout_set(data, &(struct timeval){pingtimeout, rand() % 100000});
}
static void periodic_handler(void *data) {
/* Check if there are too many contradicting ADD_EDGE and DEL_EDGE messages.
This usually only happens when another node has the same Name as this node.
If so, sleep for a short while to prevent a storm of contradicting messages.
*/
if(contradicting_del_edge > 100 && contradicting_add_edge > 100) { if(contradicting_del_edge > 100 && contradicting_add_edge > 100) {
logger(DEBUG_ALWAYS, LOG_WARNING, "Possible node with same Name as us! Sleeping %d seconds.", sleeptime); logger(DEBUG_ALWAYS, LOG_WARNING, "Possible node with same Name as us! Sleeping %d seconds.", sleeptime);
usleep(sleeptime * 1000000LL); usleep(sleeptime * 1000000LL);
@ -179,11 +186,100 @@ static void timeout_handler(int fd, short events, void *event) {
contradicting_add_edge = 0; contradicting_add_edge = 0;
contradicting_del_edge = 0; contradicting_del_edge = 0;
event_add(event, &(struct timeval){pingtimeout, 0}); /* If AutoConnect is set, check if we need to make or break connections. */
if(autoconnect && node_tree->count > 1) {
/* Count number of active connections */
int nc = 0;
for list_each(connection_t, c, connection_list) {
if(c->status.active && !c->status.control)
nc++;
}
if(nc < autoconnect) {
/* Not enough active connections, try to add one.
Choose a random node, if we don't have a connection to it,
and we are not already trying to make one, create an
outgoing connection to this node.
*/
int r = rand() % node_tree->count;
int i = 0;
for splay_each(node_t, n, node_tree) {
if(i++ != r)
continue;
if(n->connection)
break;
bool found = false;
for list_each(outgoing_t, outgoing, outgoing_list) {
if(!strcmp(outgoing->name, n->name)) {
found = true;
break;
}
}
if(!found) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "Autoconnecting to %s", n->name);
outgoing_t *outgoing = xmalloc_and_zero(sizeof *outgoing);
outgoing->name = xstrdup(n->name);
list_insert_tail(outgoing_list, outgoing);
setup_outgoing_connection(outgoing);
}
break;
}
} else if(nc > autoconnect) {
/* Too many active connections, try to remove one.
Choose a random outgoing connection to a node
that has at least one other connection.
*/
int r = rand() % nc;
int i = 0;
for list_each(connection_t, c, connection_list) {
if(!c->status.active || c->status.control)
continue;
if(i++ != r)
continue;
if(!c->outgoing || !c->node || c->node->edge_tree->count < 2)
break;
logger(DEBUG_CONNECTIONS, LOG_INFO, "Autodisconnecting from %s", c->name);
list_delete(outgoing_list, c->outgoing);
c->outgoing = NULL;
terminate_connection(c, c->status.active);
break;
}
}
if(nc >= autoconnect) {
/* If we have enough active connections,
remove any pending outgoing connections.
*/
for list_each(outgoing_t, o, outgoing_list) {
bool found = false;
for list_each(connection_t, c, connection_list) {
if(c->outgoing == o) {
found = true;
break;
}
}
if(!found) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "Cancelled outgoing connection to %s", o->name);
list_delete_node(outgoing_list, node);
}
}
}
}
timeout_set(data, &(struct timeval){5, rand() % 100000});
} }
void handle_meta_connection_data(int fd, short events, void *data) { void handle_meta_connection_data(connection_t *c) {
connection_t *c = data;
int result; int result;
socklen_t len = sizeof result; socklen_t len = sizeof result;
@ -207,19 +303,19 @@ void handle_meta_connection_data(int fd, short events, void *data) {
} }
} }
static void sigterm_handler(int signal, short events, void *data) { static void sigterm_handler(void *data) {
logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(signal)); logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum));
event_loopexit(NULL); event_exit();
} }
static void sighup_handler(int signal, short events, void *data) { static void sighup_handler(void *data) {
logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(signal)); logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum));
reopenlogger(); reopenlogger();
reload_configuration(); reload_configuration();
} }
static void sigalrm_handler(int signal, short events, void *data) { static void sigalrm_handler(void *data) {
logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(signal)); logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum));
retry(); retry();
} }
@ -233,7 +329,7 @@ int reload_configuration(void) {
if(!read_server_config()) { if(!read_server_config()) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to reread configuration file, exitting."); logger(DEBUG_ALWAYS, LOG_ERR, "Unable to reread configuration file, exitting.");
event_loopexit(NULL); event_exit();
return EINVAL; return EINVAL;
} }
@ -332,8 +428,7 @@ int reload_configuration(void) {
void retry(void) { void retry(void) {
for list_each(connection_t, c, connection_list) { for list_each(connection_t, c, connection_list) {
if(c->outgoing && !c->node) { if(c->outgoing && !c->node) {
if(timeout_initialized(&c->outgoing->ev)) timeout_del(&c->outgoing->ev);
event_del(&c->outgoing->ev);
if(c->status.connecting) if(c->status.connecting)
close(c->socket); close(c->socket);
c->outgoing->timeout = 0; c->outgoing->timeout = 0;
@ -346,40 +441,38 @@ void retry(void) {
this is where it all happens... this is where it all happens...
*/ */
int main_loop(void) { int main_loop(void) {
struct event timeout_event; timeout_t pingtimer = {{0}};
timeout_t periodictimer = {{0}};
timeout_set(&timeout_event, timeout_handler, &timeout_event); timeout_add(&pingtimer, timeout_handler, &pingtimer, &(struct timeval){pingtimeout, rand() % 100000});
event_add(&timeout_event, &(struct timeval){pingtimeout, 0}); timeout_add(&periodictimer, periodic_handler, &periodictimer, &(struct timeval){pingtimeout, rand() % 100000});
#ifndef HAVE_MINGW #ifndef HAVE_MINGW
struct event sighup_event; signal_t sighup = {0};
struct event sigterm_event; signal_t sigterm = {0};
struct event sigquit_event; signal_t sigquit = {0};
struct event sigalrm_event; signal_t sigalrm = {0};
signal_set(&sighup_event, SIGHUP, sighup_handler, NULL); signal_add(&sighup, sighup_handler, &sighup, SIGHUP);
signal_add(&sighup_event, NULL); signal_add(&sigterm, sigterm_handler, &sigterm, SIGTERM);
signal_set(&sigterm_event, SIGTERM, sigterm_handler, NULL); signal_add(&sigquit, sigterm_handler, &sigquit, SIGQUIT);
signal_add(&sigterm_event, NULL); signal_add(&sigalrm, sigalrm_handler, &sigalrm, SIGALRM);
signal_set(&sigquit_event, SIGQUIT, sigterm_handler, NULL);
signal_add(&sigquit_event, NULL);
signal_set(&sigalrm_event, SIGALRM, sigalrm_handler, NULL);
signal_add(&sigalrm_event, NULL);
#endif #endif
if(event_loop(0) < 0) { if(!event_loop()) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while waiting for input: %s", strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "Error while waiting for input: %s", strerror(errno));
return 1; return 1;
} }
#ifndef HAVE_MINGW #ifndef HAVE_MINGW
signal_del(&sighup_event); signal_del(&sighup);
signal_del(&sigterm_event); signal_del(&sigalrm);
signal_del(&sigquit_event); signal_del(&sigquit);
signal_del(&sigalrm_event); signal_del(&sigterm);
#endif #endif
event_del(&timeout_event); timeout_del(&periodictimer);
timeout_del(&pingtimer);
return 0; return 0;
} }

View file

@ -24,6 +24,7 @@
#include "ipv6.h" #include "ipv6.h"
#include "cipher.h" #include "cipher.h"
#include "digest.h" #include "digest.h"
#include "event.h"
#ifdef ENABLE_JUMBOGRAMS #ifdef ENABLE_JUMBOGRAMS
#define MTU 9018 /* 9000 bytes payload + 14 bytes ethernet header + 4 bytes VLAN tag */ #define MTU 9018 /* 9000 bytes payload + 14 bytes ethernet header + 4 bytes VLAN tag */
@ -99,10 +100,8 @@ typedef enum packet_type_t {
} packet_type_t; } packet_type_t;
typedef struct listen_socket_t { typedef struct listen_socket_t {
struct event ev_tcp; io_t tcp;
struct event ev_udp; io_t udp;
int tcp;
int udp;
sockaddr_t sa; sockaddr_t sa;
} listen_socket_t; } listen_socket_t;
@ -116,7 +115,7 @@ typedef struct outgoing_t {
struct config_t *cfg; struct config_t *cfg;
struct addrinfo *ai; struct addrinfo *ai;
struct addrinfo *aip; struct addrinfo *aip;
struct event ev; timeout_t ev;
} outgoing_t; } outgoing_t;
extern list_t *outgoing_list; extern list_t *outgoing_list;
@ -134,6 +133,7 @@ extern int udp_rcvbuf;
extern int udp_sndbuf; extern int udp_sndbuf;
extern bool do_prune; extern bool do_prune;
extern char *myport; extern char *myport;
extern int autoconnect;
extern int contradicting_add_edge; extern int contradicting_add_edge;
extern int contradicting_del_edge; extern int contradicting_del_edge;
extern time_t last_config_check; extern time_t last_config_check;
@ -160,10 +160,10 @@ extern char *scriptextension;
#include "node.h" #include "node.h"
extern void retry_outgoing(outgoing_t *); extern void retry_outgoing(outgoing_t *);
extern void handle_incoming_vpn_data(int, short, void *); extern void handle_incoming_vpn_data(void *, int);
extern void finish_connecting(struct connection_t *); extern void finish_connecting(struct connection_t *);
extern bool do_outgoing_connection(struct outgoing_t *); extern bool do_outgoing_connection(struct outgoing_t *);
extern void handle_new_meta_connection(int, short, void *); extern void handle_new_meta_connection(void *, int);
extern int setup_listen_socket(const sockaddr_t *); extern int setup_listen_socket(const sockaddr_t *);
extern int setup_vpn_in_socket(const sockaddr_t *); extern int setup_vpn_in_socket(const sockaddr_t *);
extern bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len); extern bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len);
@ -183,13 +183,14 @@ extern bool node_read_ecdsa_public_key(struct node_t *);
extern bool read_ecdsa_public_key(struct connection_t *); extern bool read_ecdsa_public_key(struct connection_t *);
extern bool read_rsa_public_key(struct connection_t *); extern bool read_rsa_public_key(struct connection_t *);
extern void send_mtu_probe(struct node_t *); extern void send_mtu_probe(struct node_t *);
extern void handle_device_data(int, short, void *); extern void handle_device_data(void *, int);
extern void handle_meta_connection_data(int, short, void *); extern void handle_meta_connection_data(struct connection_t *);
extern void regenerate_key(void); extern void regenerate_key(void);
extern void purge(void); extern void purge(void);
extern void retry(void); extern void retry(void);
extern int reload_configuration(void); extern int reload_configuration(void);
extern void load_all_subnets(void); extern void load_all_subnets(void);
extern void load_all_nodes(void);
#ifndef HAVE_MINGW #ifndef HAVE_MINGW
#define closesocket(s) close(s) #define closesocket(s) close(s)

View file

@ -77,7 +77,7 @@ bool localdiscovery = false;
which will be broadcast to the local network. which will be broadcast to the local network.
*/ */
static void send_mtu_probe_handler(int fd, short events, void *data) { static void send_mtu_probe_handler(void *data) {
node_t *n = data; node_t *n = data;
int timeout = 1; int timeout = 1;
@ -151,23 +151,37 @@ static void send_mtu_probe_handler(int fd, short events, void *data) {
} }
end: end:
event_add(&n->mtuevent, &(struct timeval){timeout, 0}); timeout_set(&n->mtutimeout, &(struct timeval){timeout, rand() % 100000});
} }
void send_mtu_probe(node_t *n) { void send_mtu_probe(node_t *n) {
if(!timeout_initialized(&n->mtuevent)) timeout_add(&n->mtutimeout, send_mtu_probe_handler, n, &(struct timeval){1, 0});
timeout_set(&n->mtuevent, send_mtu_probe_handler, n); send_mtu_probe_handler(n);
send_mtu_probe_handler(0, 0, n);
} }
static void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) { static void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) {
logger(DEBUG_TRAFFIC, LOG_INFO, "Got MTU probe length %d from %s (%s)", packet->len, n->name, n->hostname); logger(DEBUG_TRAFFIC, LOG_INFO, "Got MTU probe length %d from %s (%s)", packet->len, n->name, n->hostname);
if(!packet->data[0]) { if(!packet->data[0]) {
/* It's a probe request, send back a reply */
packet->data[0] = 1; packet->data[0] = 1;
send_udppacket(n, packet);
} else { /* Temporarily set udp_confirmed, so that the reply is sent
back exactly the way it came in. */
bool udp_confirmed = n->status.udp_confirmed;
n->status.udp_confirmed = true; n->status.udp_confirmed = true;
send_udppacket(n, packet);
n->status.udp_confirmed = udp_confirmed;
} else {
/* It's a valid reply: now we know bidirectional communication
is possible using the address and socket that the reply
packet used. */
n->status.udp_confirmed = true;
/* If we haven't established the PMTU yet, restart the discovery process. */
if(n->mtuprobes > 30) { if(n->mtuprobes > 30) {
if(n->minmtu) if(n->minmtu)
@ -176,6 +190,8 @@ static void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) {
n->mtuprobes = 1; n->mtuprobes = 1;
} }
/* If applicable, raise the minimum supported MTU */
if(len > n->maxmtu) if(len > n->maxmtu)
len = n->maxmtu; len = n->maxmtu;
if(n->minmtu < len) if(n->minmtu < len)
@ -438,6 +454,84 @@ static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) {
return; return;
} }
static void choose_udp_address(const node_t *n, const sockaddr_t **sa, int *sock) {
/* Latest guess */
*sa = &n->address;
*sock = n->sock;
/* If the UDP address is confirmed, use it. */
if(n->status.udp_confirmed)
return;
/* Send every third packet to n->address; that could be set
to the node's reflexive UDP address discovered during key
exchange. */
static int x = 0;
if(++x >= 3) {
x = 0;
return;
}
/* Otherwise, address are found in edges to this node.
So we pick a random edge and a random socket. */
int i = 0;
int j = rand() % n->edge_tree->count;
edge_t *candidate = NULL;
for splay_each(edge_t, e, n->edge_tree) {
if(i++ == j) {
candidate = e->reverse;
break;
}
}
if(candidate) {
*sa = &candidate->address;
*sock = rand() % listen_sockets;
}
/* Make sure we have a suitable socket for the chosen address */
if(listen_socket[*sock].sa.sa.sa_family != (*sa)->sa.sa_family) {
for(int i = 0; i < listen_sockets; i++) {
if(listen_socket[i].sa.sa.sa_family == (*sa)->sa.sa_family) {
*sock = i;
break;
}
}
}
}
static void choose_broadcast_address(const node_t *n, const sockaddr_t **sa, int *sock) {
static sockaddr_t broadcast_ipv4 = {
.in = {
.sin_family = AF_INET,
.sin_addr.s_addr = -1,
}
};
static sockaddr_t broadcast_ipv6 = {
.in6 = {
.sin6_family = AF_INET6,
.sin6_addr.s6_addr[0x0] = 0xff,
.sin6_addr.s6_addr[0x1] = 0x02,
.sin6_addr.s6_addr[0xf] = 0x01,
}
};
*sock = rand() % listen_sockets;
if(listen_socket[*sock].sa.sa.sa_family == AF_INET6) {
broadcast_ipv6.in6.sin6_port = n->prevedge->address.in.sin_port;
broadcast_ipv6.in6.sin6_scope_id = listen_socket[*sock].sa.in6.sin6_scope_id;
*sa = &broadcast_ipv6;
} else {
broadcast_ipv4.in.sin_port = n->prevedge->address.in.sin_port;
*sa = &broadcast_ipv4;
}
}
static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
vpn_packet_t pkt1, pkt2; vpn_packet_t pkt1, pkt2;
vpn_packet_t *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 }; vpn_packet_t *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 };
@ -462,15 +556,13 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
/* Make sure we have a valid key */ /* Make sure we have a valid key */
if(!n->status.validkey) { if(!n->status.validkey) {
time_t now = time(NULL);
logger(DEBUG_TRAFFIC, LOG_INFO, logger(DEBUG_TRAFFIC, LOG_INFO,
"No valid key known yet for %s (%s), forwarding via TCP", "No valid key known yet for %s (%s), forwarding via TCP",
n->name, n->hostname); n->name, n->hostname);
if(n->last_req_key + 10 <= now) { if(n->last_req_key + 10 <= now.tv_sec) {
send_req_key(n); send_req_key(n);
n->last_req_key = now; n->last_req_key = now.tv_sec;
} }
send_tcppacket(n->nexthop->connection, origpkt); send_tcppacket(n->nexthop->connection, origpkt);
@ -534,88 +626,27 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
/* Send the packet */ /* Send the packet */
sockaddr_t *sa; const sockaddr_t *sa;
int sock; int sock;
/* Overloaded use of priority field: -1 means local broadcast */ /* Overloaded use of priority field: -1 means local broadcast */
if(origpriority == -1 && n->prevedge) { if(origpriority == -1 && n->prevedge)
sockaddr_t broadcast; choose_broadcast_address(n, &sa, &sock);
broadcast.in.sin_family = AF_INET; else
broadcast.in.sin_addr.s_addr = -1; choose_udp_address(n, &sa, &sock);
broadcast.in.sin_port = n->prevedge->address.in.sin_port;
sa = &broadcast;
sock = 0;
} else {
if(origpriority == -1)
origpriority = 0;
if(n->status.udp_confirmed) {
/* Address of this node is confirmed, so use it. */
sa = &n->address;
sock = n->sock;
} else {
/* Otherwise, go through the list of known addresses of
this node. The first address we try is always the
one in n->address; that could be set to the node's
reflexive UDP address discovered during key
exchange. The other known addresses are those found
in edges to this node. */
static unsigned int i;
int j = 0;
edge_t *candidate = NULL;
if(i) {
for splay_each(edge_t, e, edge_weight_tree) {
if(e->to != n)
continue;
j++;
if(!candidate || j == i)
candidate = e;
}
}
if(!candidate) {
sa = &n->address;
sock = n->sock;
} else {
sa = &candidate->address;
sock = rand() % listen_sockets;
}
if(i++)
if(i > j)
i = 0;
}
}
/* Determine which socket we have to use */
if(sa->sa.sa_family != listen_socket[sock].sa.sa.sa_family)
for(sock = 0; sock < listen_sockets; sock++)
if(sa->sa.sa_family == listen_socket[sock].sa.sa.sa_family)
break;
if(sock >= listen_sockets)
sock = 0;
if(!n->status.udp_confirmed)
n->sock = sock;
#if defined(SOL_IP) && defined(IP_TOS) #if defined(SOL_IP) && defined(IP_TOS)
if(priorityinheritance && origpriority != priority if(priorityinheritance && origpriority != priority
&& listen_socket[n->sock].sa.sa.sa_family == AF_INET) { && listen_socket[n->sock].sa.sa.sa_family == AF_INET) {
priority = origpriority; priority = origpriority;
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Setting outgoing packet priority to %d", priority); logger(DEBUG_TRAFFIC, LOG_DEBUG, "Setting outgoing packet priority to %d", priority);
if(setsockopt(listen_socket[n->sock].udp, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */ if(setsockopt(listen_socket[n->sock].udp.fd, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */
logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno));
} }
#endif #endif
socklen_t sl = SALEN(n->address.sa); if(sendto(listen_socket[sock].udp.fd, (char *) &inpkt->seqno, inpkt->len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) {
if(sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, &sa->sa, sl) < 0 && !sockwouldblock(sockerrno)) {
if(sockmsgsize(sockerrno)) { if(sockmsgsize(sockerrno)) {
if(n->maxmtu >= origlen) if(n->maxmtu >= origlen)
n->maxmtu = origlen - 1; n->maxmtu = origlen - 1;
@ -647,15 +678,12 @@ bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len) {
/* Otherwise, send the packet via UDP */ /* Otherwise, send the packet via UDP */
struct sockaddr *sa; const sockaddr_t *sa;
socklen_t sl;
int sock; int sock;
sa = &(to->address.sa); choose_udp_address(to, &sa, &sock);
sl = SALEN(to->address.sa);
sock = to->sock;
if(sendto(listen_socket[sock].udp, data, len, 0, sa, sl) < 0 && !sockwouldblock(sockerrno)) { if(sendto(listen_socket[sock].udp.fd, data, len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) {
if(sockmsgsize(sockerrno)) { if(sockmsgsize(sockerrno)) {
if(to->maxmtu >= len) if(to->maxmtu >= len)
to->maxmtu = len - 1; to->maxmtu = len - 1;
@ -711,11 +739,11 @@ bool receive_sptps_record(void *handle, uint8_t type, const char *data, uint16_t
int offset = (type & PKT_MAC) ? 0 : 14; int offset = (type & PKT_MAC) ? 0 : 14;
if(type & PKT_COMPRESSED) { if(type & PKT_COMPRESSED) {
len = uncompress_packet(inpkt.data + offset, (const uint8_t *)data, len, from->incompression); length_t ulen = uncompress_packet(inpkt.data + offset, (const uint8_t *)data, len, from->incompression);
if(len < 0) { if(ulen < 0) {
return false; return false;
} else { } else {
inpkt.len = len + offset; inpkt.len = ulen + offset;
} }
if(inpkt.len > MAXSIZE) if(inpkt.len > MAXSIZE)
abort(); abort();
@ -838,14 +866,13 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) {
node_t *n = NULL; node_t *n = NULL;
bool hard = false; bool hard = false;
static time_t last_hard_try = 0; static time_t last_hard_try = 0;
time_t now = time(NULL);
for splay_each(edge_t, e, edge_weight_tree) { for splay_each(edge_t, e, edge_weight_tree) {
if(!e->to->status.reachable || e->to == myself) if(!e->to->status.reachable || e->to == myself)
continue; continue;
if(sockaddrcmp_noport(from, &e->address)) { if(sockaddrcmp_noport(from, &e->address)) {
if(last_hard_try == now) if(last_hard_try == now.tv_sec)
continue; continue;
hard = true; hard = true;
} }
@ -858,13 +885,14 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) {
} }
if(hard) if(hard)
last_hard_try = now; last_hard_try = now.tv_sec;
last_hard_try = now; last_hard_try = now.tv_sec;
return n; return n;
} }
void handle_incoming_vpn_data(int sock, short events, void *data) { void handle_incoming_vpn_data(void *data, int flags) {
listen_socket_t *ls = data;
vpn_packet_t pkt; vpn_packet_t pkt;
char *hostname; char *hostname;
sockaddr_t from = {{0}}; sockaddr_t from = {{0}};
@ -872,7 +900,7 @@ void handle_incoming_vpn_data(int sock, short events, void *data) {
node_t *n; node_t *n;
int len; int len;
len = recvfrom(sock, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen); len = recvfrom(ls->udp.fd, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen);
if(len <= 0 || len > MAXSIZE) { if(len <= 0 || len > MAXSIZE) {
if(!sockwouldblock(sockerrno)) if(!sockwouldblock(sockerrno))
@ -900,12 +928,12 @@ void handle_incoming_vpn_data(int sock, short events, void *data) {
return; return;
} }
n->sock = (intptr_t)data; n->sock = ls - listen_socket;
receive_udppacket(n, &pkt); receive_udppacket(n, &pkt);
} }
void handle_device_data(int sock, short events, void *data) { void handle_device_data(void *data, int flags) {
vpn_packet_t packet; vpn_packet_t packet;
packet.priority = 0; packet.priority = 0;

View file

@ -42,7 +42,7 @@
#include "xalloc.h" #include "xalloc.h"
char *myport; char *myport;
static struct event device_ev; static io_t device_io;
devops_t devops; devops_t devops;
char *proxyhost; char *proxyhost;
@ -50,6 +50,7 @@ char *proxyport;
char *proxyuser; char *proxyuser;
char *proxypass; char *proxypass;
proxytype_t proxytype; proxytype_t proxytype;
int autoconnect;
char *scriptinterpreter; char *scriptinterpreter;
char *scriptextension; char *scriptextension;
@ -269,22 +270,16 @@ static bool read_rsa_private_key(void) {
return result; return result;
} }
static struct event keyexpire_event; static timeout_t keyexpire_timeout;
static void keyexpire_handler(int fd, short events, void *data) { static void keyexpire_handler(void *data) {
regenerate_key(); regenerate_key();
timeout_set(data, &(struct timeval){keylifetime, rand() % 100000});
} }
void regenerate_key(void) { void regenerate_key(void) {
if(timeout_initialized(&keyexpire_event)) { logger(DEBUG_STATUS, LOG_INFO, "Expiring symmetric keys");
logger(DEBUG_STATUS, LOG_INFO, "Expiring symmetric keys"); send_key_changed();
event_del(&keyexpire_event);
send_key_changed();
} else {
timeout_set(&keyexpire_event, keyexpire_handler, NULL);
}
event_add(&keyexpire_event, &(struct timeval){keylifetime, 0});
} }
/* /*
@ -347,6 +342,36 @@ void load_all_subnets(void) {
closedir(dir); closedir(dir);
} }
void load_all_nodes(void) {
DIR *dir;
struct dirent *ent;
char *dname;
xasprintf(&dname, "%s" SLASH "hosts", confbase);
dir = opendir(dname);
if(!dir) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", dname, strerror(errno));
free(dname);
return;
}
while((ent = readdir(dir))) {
if(!check_id(ent->d_name))
continue;
node_t *n = lookup_node(ent->d_name);
if(n)
continue;
n = new_node();
n->name = xstrdup(ent->d_name);
node_add(n);
}
closedir(dir);
}
char *get_name(void) { char *get_name(void) {
char *name = NULL; char *name = NULL;
@ -362,7 +387,7 @@ char *get_name(void) {
logger(DEBUG_ALWAYS, LOG_ERR, "Invalid Name: environment variable %s does not exist\n", name + 1); logger(DEBUG_ALWAYS, LOG_ERR, "Invalid Name: environment variable %s does not exist\n", name + 1);
return false; return false;
} }
envname = alloca(32); char envname[32];
if(gethostname(envname, 32)) { if(gethostname(envname, 32)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not get hostname: %s\n", strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "Could not get hostname: %s\n", strerror(errno));
return false; return false;
@ -570,6 +595,8 @@ bool setup_myself_reloadable(void) {
if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime)) if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime))
keylifetime = 3600; keylifetime = 3600;
get_config_int(lookup_config(config_tree, "AutoConnect"), &autoconnect);
return true; return true;
} }
@ -683,7 +710,8 @@ static bool setup_myself(void) {
free(cipher); free(cipher);
regenerate_key(); send_key_changed();
timeout_add(&keyexpire_timeout, keyexpire_handler, &keyexpire_timeout, &(struct timeval){keylifetime, rand() % 100000});
/* Check if we want to use message authentication codes... */ /* Check if we want to use message authentication codes... */
@ -730,6 +758,8 @@ static bool setup_myself(void) {
if(strictsubnets) if(strictsubnets)
load_all_subnets(); load_all_subnets();
else if(autoconnect)
load_all_nodes();
/* Open device */ /* Open device */
@ -755,15 +785,8 @@ static bool setup_myself(void) {
if(!devops.setup()) if(!devops.setup())
return false; return false;
if(device_fd >= 0) { if(device_fd >= 0)
event_set(&device_ev, device_fd, EV_READ|EV_PERSIST, handle_device_data, NULL); io_add(&device_io, handle_device_data, NULL, device_fd, IO_READ);
if (event_add(&device_ev, NULL) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "event_add failed: %s", strerror(errno));
devops.close();
return false;
}
}
/* Run tinc-up script to further initialize the tap interface */ /* Run tinc-up script to further initialize the tap interface */
char *envp[5]; char *envp[5];
@ -805,27 +828,16 @@ static bool setup_myself(void) {
return false; return false;
} }
listen_socket[i].tcp = i + 3;
#ifdef FD_CLOEXEC #ifdef FD_CLOEXEC
fcntl(i + 3, F_SETFD, FD_CLOEXEC); fcntl(i + 3, F_SETFD, FD_CLOEXEC);
#endif #endif
listen_socket[i].udp = setup_vpn_in_socket(&sa); int udp_fd = setup_vpn_in_socket(&sa);
if(listen_socket[i].udp < 0) if(udp_fd < 0)
return false; return false;
event_set(&listen_socket[i].ev_tcp, listen_socket[i].tcp, EV_READ|EV_PERSIST, handle_new_meta_connection, NULL); io_add(&listen_socket[i].tcp, (io_cb_t)handle_new_meta_connection, &listen_socket[i], i + 3, IO_READ);
if(event_add(&listen_socket[i].ev_tcp, NULL) < 0) { io_add(&listen_socket[i].udp, (io_cb_t)handle_incoming_vpn_data, &listen_socket[i], udp_fd, IO_READ);
logger(DEBUG_ALWAYS, LOG_ERR, "event_add failed: %s", strerror(errno));
abort();
}
event_set(&listen_socket[i].ev_udp, listen_socket[i].udp, EV_READ|EV_PERSIST, handle_incoming_vpn_data, (void *)(intptr_t)listen_sockets);
if(event_add(&listen_socket[listen_sockets].ev_udp, NULL) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "event_add failed: %s", strerror(errno));
abort();
}
if(debug_level >= DEBUG_CONNECTIONS) { if(debug_level >= DEBUG_CONNECTIONS) {
hostname = sockaddr2hostname(&sa); hostname = sockaddr2hostname(&sa);
@ -878,37 +890,20 @@ static bool setup_myself(void) {
return false; return false;
} }
listen_socket[listen_sockets].tcp = int tcp_fd = setup_listen_socket((sockaddr_t *) aip->ai_addr);
setup_listen_socket((sockaddr_t *) aip->ai_addr);
if(listen_socket[listen_sockets].tcp < 0) if(tcp_fd < 0)
continue; continue;
listen_socket[listen_sockets].udp = int udp_fd = setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);
setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);
if(listen_socket[listen_sockets].udp < 0) { if(tcp_fd < 0) {
close(listen_socket[listen_sockets].tcp); close(tcp_fd);
continue; continue;
} }
event_set(&listen_socket[listen_sockets].ev_tcp, io_add(&listen_socket[listen_sockets].tcp, handle_new_meta_connection, &listen_socket[listen_sockets], tcp_fd, IO_READ);
listen_socket[listen_sockets].tcp, io_add(&listen_socket[listen_sockets].udp, handle_incoming_vpn_data, &listen_socket[listen_sockets], udp_fd, IO_READ);
EV_READ|EV_PERSIST,
handle_new_meta_connection, NULL);
if(event_add(&listen_socket[listen_sockets].ev_tcp, NULL) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "event_add failed: %s", strerror(errno));
abort();
}
event_set(&listen_socket[listen_sockets].ev_udp,
listen_socket[listen_sockets].udp,
EV_READ|EV_PERSIST,
handle_incoming_vpn_data, (void *)(intptr_t)listen_sockets);
if(event_add(&listen_socket[listen_sockets].ev_udp, NULL) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "event_add failed: %s", strerror(errno));
abort();
}
if(debug_level >= DEBUG_CONNECTIONS) { if(debug_level >= DEBUG_CONNECTIONS) {
hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr); hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr);
@ -990,10 +985,10 @@ void close_network_connections(void) {
} }
for(int i = 0; i < listen_sockets; i++) { for(int i = 0; i < listen_sockets; i++) {
event_del(&listen_socket[i].ev_tcp); io_del(&listen_socket[i].tcp);
event_del(&listen_socket[i].ev_udp); io_del(&listen_socket[i].udp);
close(listen_socket[i].tcp); close(listen_socket[i].tcp.fd);
close(listen_socket[i].udp); close(listen_socket[i].udp.fd);
} }
char *envp[5]; char *envp[5];

View file

@ -271,7 +271,7 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
return nfd; return nfd;
} /* int setup_vpn_in_socket */ } /* int setup_vpn_in_socket */
static void retry_outgoing_handler(int fd, short events, void *data) { static void retry_outgoing_handler(void *data) {
setup_outgoing_connection(data); setup_outgoing_connection(data);
} }
@ -281,12 +281,9 @@ void retry_outgoing(outgoing_t *outgoing) {
if(outgoing->timeout > maxtimeout) if(outgoing->timeout > maxtimeout)
outgoing->timeout = maxtimeout; outgoing->timeout = maxtimeout;
timeout_set(&outgoing->ev, retry_outgoing_handler, outgoing); timeout_add(&outgoing->ev, retry_outgoing_handler, outgoing, &(struct timeval){outgoing->timeout, rand() % 100000});
event_add(&outgoing->ev, &(struct timeval){outgoing->timeout, 0});
logger(DEBUG_CONNECTIONS, LOG_NOTICE, logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Trying to re-establish outgoing connection in %d seconds", outgoing->timeout);
"Trying to re-establish outgoing connection in %d seconds",
outgoing->timeout);
} }
void finish_connecting(connection_t *c) { void finish_connecting(connection_t *c) {
@ -349,9 +346,7 @@ static void do_outgoing_pipe(connection_t *c, char *command) {
#endif #endif
} }
static void handle_meta_write(int sock, short events, void *data) { static void handle_meta_write(connection_t *c) {
connection_t *c = data;
ssize_t outlen = send(c->socket, c->outbuf.data + c->outbuf.offset, c->outbuf.len - c->outbuf.offset, 0); ssize_t outlen = send(c->socket, c->outbuf.data + c->outbuf.offset, c->outbuf.len - c->outbuf.offset, 0);
if(outlen <= 0) { if(outlen <= 0) {
if(!errno || errno == EPIPE) { if(!errno || errno == EPIPE) {
@ -368,10 +363,16 @@ static void handle_meta_write(int sock, short events, void *data) {
} }
buffer_read(&c->outbuf, outlen); buffer_read(&c->outbuf, outlen);
if(!c->outbuf.len && event_initialized(&c->outevent)) if(!c->outbuf.len)
event_del(&c->outevent); io_set(&c->io, IO_READ);
} }
static void handle_meta_io(void *data, int flags) {
if(flags & IO_WRITE)
handle_meta_write(data);
else
handle_meta_connection_data(data);
}
bool do_outgoing_connection(outgoing_t *outgoing) { bool do_outgoing_connection(outgoing_t *outgoing) {
char *address, *port, *space; char *address, *port, *space;
@ -487,16 +488,13 @@ begin:
connection_add(c); connection_add(c);
event_set(&c->inevent, c->socket, EV_READ | EV_PERSIST, handle_meta_connection_data, c); io_add(&c->io, handle_meta_io, c, c->socket, IO_READ);
event_set(&c->outevent, c->socket, EV_WRITE | EV_PERSIST, handle_meta_write, c);
event_add(&c->inevent, NULL);
return true; return true;
} }
void setup_outgoing_connection(outgoing_t *outgoing) { void setup_outgoing_connection(outgoing_t *outgoing) {
if(event_initialized(&outgoing->ev)) timeout_del(&outgoing->ev);
event_del(&outgoing->ev);
node_t *n = lookup_node(outgoing->name); node_t *n = lookup_node(outgoing->name);
@ -523,13 +521,14 @@ void setup_outgoing_connection(outgoing_t *outgoing) {
accept a new tcp connect and create a accept a new tcp connect and create a
new connection new connection
*/ */
void handle_new_meta_connection(int sock, short events, void *data) { void handle_new_meta_connection(void *data, int flags) {
listen_socket_t *l = data;
connection_t *c; connection_t *c;
sockaddr_t sa; sockaddr_t sa;
int fd; int fd;
socklen_t len = sizeof sa; socklen_t len = sizeof sa;
fd = accept(sock, &sa.sa, &len); fd = accept(l->tcp.fd, &sa.sa, &len);
if(fd < 0) { if(fd < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Accepting a new connection failed: %s", sockstrerror(sockerrno)); logger(DEBUG_ALWAYS, LOG_ERR, "Accepting a new connection failed: %s", sockstrerror(sockerrno));
@ -552,9 +551,7 @@ void handle_new_meta_connection(int sock, short events, void *data) {
logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection from %s", c->hostname); logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection from %s", c->hostname);
event_set(&c->inevent, c->socket, EV_READ | EV_PERSIST, handle_meta_connection_data, c); io_add(&c->io, handle_meta_io, c, c->socket, IO_READ);
event_set(&c->outevent, c->socket, EV_WRITE | EV_PERSIST, handle_meta_write, c);
event_add(&c->inevent, NULL);
configure_tcp(c); configure_tcp(c);
@ -565,8 +562,7 @@ void handle_new_meta_connection(int sock, short events, void *data) {
} }
static void free_outgoing(outgoing_t *outgoing) { static void free_outgoing(outgoing_t *outgoing) {
if(event_initialized(&outgoing->ev)) timeout_del(&outgoing->ev);
event_del(&outgoing->ev);
if(outgoing->ai) if(outgoing->ai)
freeaddrinfo(outgoing->ai); freeaddrinfo(outgoing->ai);

View file

@ -52,7 +52,7 @@ struct addrinfo *str2addrinfo(const char *address, const char *service, int sock
sockaddr_t str2sockaddr(const char *address, const char *port) { sockaddr_t str2sockaddr(const char *address, const char *port) {
struct addrinfo *ai, hint = {0}; struct addrinfo *ai, hint = {0};
sockaddr_t result; sockaddr_t result = {{0}};
int err; int err;
hint.ai_family = AF_UNSPEC; hint.ai_family = AF_UNSPEC;

View file

@ -78,8 +78,7 @@ void free_node(node_t *n) {
ecdsa_free(&n->ecdsa); ecdsa_free(&n->ecdsa);
sptps_stop(&n->sptps); sptps_stop(&n->sptps);
if(timeout_initialized(&n->mtuevent)) timeout_del(&n->mtutimeout);
event_del(&n->mtuevent);
if(n->hostname) if(n->hostname)
free(n->hostname); free(n->hostname);
@ -129,6 +128,13 @@ void update_node_udp(node_t *n, const sockaddr_t *sa) {
if(sa) { if(sa) {
n->address = *sa; n->address = *sa;
n->sock = 0;
for(int i = 0; i < listen_sockets; i++) {
if(listen_socket[i].sa.sa.sa_family == sa->sa.sa_family) {
n->sock = i;
break;
}
}
hash_insert(node_udp_cache, sa, n); hash_insert(node_udp_cache, sa, n);
free(n->hostname); free(n->hostname);
n->hostname = sockaddr2hostname(&n->address); n->hostname = sockaddr2hostname(&n->address);

View file

@ -25,6 +25,7 @@
#include "cipher.h" #include "cipher.h"
#include "connection.h" #include "connection.h"
#include "digest.h" #include "digest.h"
#include "event.h"
#include "subnet.h" #include "subnet.h"
typedef struct node_status_t { typedef struct node_status_t {
@ -83,7 +84,7 @@ typedef struct node_t {
length_t minmtu; /* Probed minimum MTU */ length_t minmtu; /* Probed minimum MTU */
length_t maxmtu; /* Probed maximum MTU */ length_t maxmtu; /* Probed maximum MTU */
int mtuprobes; /* Number of probes */ int mtuprobes; /* Number of probes */
struct event mtuevent; /* Probe event */ timeout_t mtutimeout; /* Probe event */
uint64_t in_packets; uint64_t in_packets;
uint64_t in_bytes; uint64_t in_bytes;

View file

@ -25,6 +25,7 @@
#include "control.h" #include "control.h"
#include "device.h" #include "device.h"
#include "edge.h" #include "edge.h"
#include "event.h"
#include "logger.h" #include "logger.h"
#include "net.h" #include "net.h"
#include "node.h" #include "node.h"
@ -127,7 +128,7 @@ DWORD WINAPI controlhandler(DWORD request, DWORD type, LPVOID boe, LPVOID bah) {
return ERROR_CALL_NOT_IMPLEMENTED; return ERROR_CALL_NOT_IMPLEMENTED;
} }
event_loopexit(NULL); event_exit();
status.dwWaitHint = 30000; status.dwWaitHint = 30000;
status.dwCurrentState = SERVICE_STOP_PENDING; status.dwCurrentState = SERVICE_STOP_PENDING;
SetServiceStatus(statushandle, &status); SetServiceStatus(statushandle, &status);

View file

@ -165,7 +165,24 @@ static void free_past_request(past_request_t *r) {
free(r); free(r);
} }
static struct event past_request_event; static timeout_t past_request_timeout;
static void age_past_requests(void *data) {
int left = 0, deleted = 0;
for splay_each(past_request_t, p, past_request_tree) {
if(p->firstseen + pinginterval <= now.tv_sec)
splay_delete_node(past_request_tree, node), deleted++;
else
left++;
}
if(left || deleted)
logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Aging past requests: deleted %d, left %d", deleted, left);
if(left)
timeout_set(&past_request_timeout, &(struct timeval){10, rand() % 100000});
}
bool seen_request(const char *request) { bool seen_request(const char *request) {
past_request_t *new, p = {NULL}; past_request_t *new, p = {NULL};
@ -180,39 +197,17 @@ bool seen_request(const char *request) {
new->request = xstrdup(request); new->request = xstrdup(request);
new->firstseen = time(NULL); new->firstseen = time(NULL);
splay_insert(past_request_tree, new); splay_insert(past_request_tree, new);
event_add(&past_request_event, &(struct timeval){10, 0}); timeout_add(&past_request_timeout, age_past_requests, NULL, &(struct timeval){10, rand() % 100000});
return false; return false;
} }
} }
static void age_past_requests(int fd, short events, void *data) {
int left = 0, deleted = 0;
time_t now = time(NULL);
for splay_each(past_request_t, p, past_request_tree) {
if(p->firstseen + pinginterval <= now)
splay_delete_node(past_request_tree, node), deleted++;
else
left++;
}
if(left || deleted)
logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Aging past requests: deleted %d, left %d",
deleted, left);
if(left)
event_add(&past_request_event, &(struct timeval){10, 0});
}
void init_requests(void) { void init_requests(void) {
past_request_tree = splay_alloc_tree((splay_compare_t) past_request_compare, (splay_action_t) free_past_request); past_request_tree = splay_alloc_tree((splay_compare_t) past_request_compare, (splay_action_t) free_past_request);
timeout_set(&past_request_event, age_past_requests, NULL);
} }
void exit_requests(void) { void exit_requests(void) {
splay_delete_tree(past_request_tree); splay_delete_tree(past_request_tree);
if(timeout_initialized(&past_request_event)) timeout_del(&past_request_timeout);
event_del(&past_request_event);
} }

View file

@ -59,7 +59,7 @@ static const size_t opt_size = sizeof(struct nd_opt_hdr);
#define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif #endif
static struct event age_subnets_event; static timeout_t age_subnets_timeout;
/* RFC 1071 */ /* RFC 1071 */
@ -84,13 +84,12 @@ static uint16_t inet_checksum(void *data, int len, uint16_t prevsum) {
static bool ratelimit(int frequency) { static bool ratelimit(int frequency) {
static time_t lasttime = 0; static time_t lasttime = 0;
static int count = 0; static int count = 0;
time_t now = time(NULL);
if(lasttime == now) { if(lasttime == now.tv_sec) {
if(count >= frequency) if(count >= frequency)
return true; return true;
} else { } else {
lasttime = now; lasttime = now.tv_sec;
count = 0; count = 0;
} }
@ -115,15 +114,22 @@ static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *pac
mtu = via->mtu; mtu = via->mtu;
/* Find TCP header */ /* Find TCP header */
int start = 0; int start = ether_size;
uint16_t type = packet->data[12] << 8 | packet->data[13]; uint16_t type = packet->data[12] << 8 | packet->data[13];
if(type == ETH_P_IP && packet->data[23] == 6) if(type == ETH_P_8021Q) {
start = 14 + (packet->data[14] & 0xf) * 4; start += 4;
else if(type == ETH_P_IPV6 && packet->data[20] == 6) type = packet->data[16] << 8 | packet->data[17];
start = 14 + 40; }
if(!start || packet->len <= start + 20) if(type == ETH_P_IP && packet->data[start + 9] == 6)
start += (packet->data[start] & 0xf) * 4;
else if(type == ETH_P_IPV6 && packet->data[start + 6] == 6)
start += 40;
else
return;
if(packet->len <= start + 20)
return; return;
/* Use data offset field to calculate length of options field */ /* Use data offset field to calculate length of options field */
@ -185,12 +191,11 @@ static void swap_mac_addresses(vpn_packet_t *packet) {
memcpy(&packet->data[6], &tmp, sizeof tmp); memcpy(&packet->data[6], &tmp, sizeof tmp);
} }
static void age_subnets(int fd, short events, void *data) { static void age_subnets(void *data) {
bool left = false; bool left = false;
time_t now = time(NULL);
for splay_each(subnet_t, s, myself->subnet_tree) { for splay_each(subnet_t, s, myself->subnet_tree) {
if(s->expires && s->expires < now) { if(s->expires && s->expires < now.tv_sec) {
if(debug_level >= DEBUG_TRAFFIC) { if(debug_level >= DEBUG_TRAFFIC) {
char netstr[MAXNETSTR]; char netstr[MAXNETSTR];
if(net2str(netstr, sizeof netstr, s)) if(net2str(netstr, sizeof netstr, s))
@ -209,7 +214,7 @@ static void age_subnets(int fd, short events, void *data) {
} }
if(left) if(left)
event_add(&age_subnets_event, &(struct timeval){10, 0}); timeout_set(&age_subnets_timeout, &(struct timeval){10, rand() % 100000});
} }
static void learn_mac(mac_t *address) { static void learn_mac(mac_t *address) {
@ -236,9 +241,7 @@ static void learn_mac(mac_t *address) {
if(c->status.active) if(c->status.active)
send_add_subnet(c, subnet); send_add_subnet(c, subnet);
if(!timeout_initialized(&age_subnets_event)) timeout_add(&age_subnets_timeout, age_subnets, NULL, &(struct timeval){10, rand() % 100000});
timeout_set(&age_subnets_event, age_subnets, NULL);
event_add(&age_subnets_event, &(struct timeval){10, 0});
} else { } else {
if(subnet->expires) if(subnet->expires)
subnet->expires = time(NULL) + macexpire; subnet->expires = time(NULL) + macexpire;
@ -247,7 +250,7 @@ static void learn_mac(mac_t *address) {
/* RFC 792 */ /* RFC 792 */
static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, uint8_t type, uint8_t code) { static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, length_t ether_size, uint8_t type, uint8_t code) {
struct ip ip = {0}; struct ip ip = {0};
struct icmp icmp = {0}; struct icmp icmp = {0};
@ -320,7 +323,7 @@ static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, uint8_t
/* RFC 791 */ /* RFC 791 */
static void fragment_ipv4_packet(node_t *dest, vpn_packet_t *packet) { static void fragment_ipv4_packet(node_t *dest, vpn_packet_t *packet, length_t ether_size) {
struct ip ip; struct ip ip;
vpn_packet_t fragment; vpn_packet_t fragment;
int len, maxlen, todo; int len, maxlen, todo;
@ -384,7 +387,7 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) {
dest.x[2], dest.x[2],
dest.x[3]); dest.x[3]);
route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_UNKNOWN); route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_UNKNOWN);
return; return;
} }
@ -394,10 +397,10 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) {
} }
if(!subnet->owner->status.reachable) if(!subnet->owner->status.reachable)
return route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_UNREACH); return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_UNREACH);
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself) if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
return route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_ANO); return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_ANO);
if(priorityinheritance) if(priorityinheritance)
packet->priority = packet->data[15]; packet->priority = packet->data[15];
@ -410,15 +413,15 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) {
} }
if(directonly && subnet->owner != via) if(directonly && subnet->owner != via)
return route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_ANO); return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_ANO);
if(via && packet->len > MAX(via->mtu, 590) && via != myself) { if(via && packet->len > MAX(via->mtu, 590) && via != myself) {
logger(DEBUG_TRAFFIC, LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu); logger(DEBUG_TRAFFIC, LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
if(packet->data[20] & 0x40) { if(packet->data[20] & 0x40) {
packet->len = MAX(via->mtu, 590); packet->len = MAX(via->mtu, 590);
route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED); route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED);
} else { } else {
fragment_ipv4_packet(via, packet); fragment_ipv4_packet(via, packet, ether_size);
} }
return; return;
@ -445,7 +448,7 @@ static void route_ipv4(node_t *source, vpn_packet_t *packet) {
/* RFC 2463 */ /* RFC 2463 */
static void route_ipv6_unreachable(node_t *source, vpn_packet_t *packet, uint8_t type, uint8_t code) { static void route_ipv6_unreachable(node_t *source, vpn_packet_t *packet, length_t ether_size, uint8_t type, uint8_t code) {
struct ip6_hdr ip6; struct ip6_hdr ip6;
struct icmp6_hdr icmp6 = {0}; struct icmp6_hdr icmp6 = {0};
uint16_t checksum; uint16_t checksum;
@ -543,7 +546,7 @@ static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) {
ntohs(dest.x[6]), ntohs(dest.x[6]),
ntohs(dest.x[7])); ntohs(dest.x[7]));
route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR); route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR);
return; return;
} }
@ -553,10 +556,10 @@ static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) {
} }
if(!subnet->owner->status.reachable) if(!subnet->owner->status.reachable)
return route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE); return route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE);
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself) if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
return route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN); return route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN);
via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via; via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
@ -566,12 +569,12 @@ static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) {
} }
if(directonly && subnet->owner != via) if(directonly && subnet->owner != via)
return route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN); return route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN);
if(via && packet->len > MAX(via->mtu, 1294) && via != myself) { if(via && packet->len > MAX(via->mtu, 1294) && via != myself) {
logger(DEBUG_TRAFFIC, LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu); logger(DEBUG_TRAFFIC, LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
packet->len = MAX(via->mtu, 1294); packet->len = MAX(via->mtu, 1294);
route_ipv6_unreachable(source, packet, ICMP6_PACKET_TOO_BIG, 0); route_ipv6_unreachable(source, packet, ether_size, ICMP6_PACKET_TOO_BIG, 0);
return; return;
} }
@ -842,17 +845,24 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
if(via && packet->len > via->mtu && via != myself) { if(via && packet->len > via->mtu && via != myself) {
logger(DEBUG_TRAFFIC, LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu); logger(DEBUG_TRAFFIC, LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
uint16_t type = packet->data[12] << 8 | packet->data[13]; uint16_t type = packet->data[12] << 8 | packet->data[13];
if(type == ETH_P_IP && packet->len > 590) { length_t ethlen = 14;
if(packet->data[20] & 0x40) {
if(type == ETH_P_8021Q) {
type = packet->data[16] << 8 | packet->data[17];
ethlen += 4;
}
if(type == ETH_P_IP && packet->len > 576 + ethlen) {
if(packet->data[6 + ethlen] & 0x40) {
packet->len = via->mtu; packet->len = via->mtu;
route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED); route_ipv4_unreachable(source, packet, ethlen, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED);
} else { } else {
fragment_ipv4_packet(via, packet); fragment_ipv4_packet(via, packet, ethlen);
} }
return; return;
} else if(type == ETH_P_IPV6 && packet->len > 1294) { } else if(type == ETH_P_IPV6 && packet->len > 1280 + ethlen) {
packet->len = via->mtu; packet->len = via->mtu;
route_ipv6_unreachable(source, packet, ICMP6_PACKET_TOO_BIG, 0); route_ipv6_unreachable(source, packet, ethlen, ICMP6_PACKET_TOO_BIG, 0);
return; return;
} }
} }
@ -881,42 +891,48 @@ static void send_pcap(vpn_packet_t *packet) {
static bool do_decrement_ttl(node_t *source, vpn_packet_t *packet) { static bool do_decrement_ttl(node_t *source, vpn_packet_t *packet) {
uint16_t type = packet->data[12] << 8 | packet->data[13]; uint16_t type = packet->data[12] << 8 | packet->data[13];
length_t ethlen = ether_size;
if(type == ETH_P_8021Q) {
type = packet->data[16] << 8 | packet->data[17];
ethlen += 4;
}
switch (type) { switch (type) {
case ETH_P_IP: case ETH_P_IP:
if(!checklength(source, packet, 14 + 32)) if(!checklength(source, packet, ethlen + ip_size))
return false; return false;
if(packet->data[22] < 1) { if(packet->data[ethlen + 8] < 1) {
if(packet->data[25] != IPPROTO_ICMP || packet->data[46] != ICMP_TIME_EXCEEDED) if(packet->data[ethlen + 11] != IPPROTO_ICMP || packet->data[ethlen + 32] != ICMP_TIME_EXCEEDED)
route_ipv4_unreachable(source, packet, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL); route_ipv4_unreachable(source, packet, ethlen, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL);
return false; return false;
} }
uint16_t old = packet->data[22] << 8 | packet->data[23]; uint16_t old = packet->data[ethlen + 8] << 8 | packet->data[ethlen + 9];
packet->data[22]--; packet->data[ethlen + 8]--;
uint16_t new = packet->data[22] << 8 | packet->data[23]; uint16_t new = packet->data[ethlen + 8] << 8 | packet->data[ethlen + 9];
uint32_t checksum = packet->data[24] << 8 | packet->data[25]; uint32_t checksum = packet->data[ethlen + 10] << 8 | packet->data[ethlen + 11];
checksum += old + (~new & 0xFFFF); checksum += old + (~new & 0xFFFF);
while(checksum >> 16) while(checksum >> 16)
checksum = (checksum & 0xFFFF) + (checksum >> 16); checksum = (checksum & 0xFFFF) + (checksum >> 16);
packet->data[24] = checksum >> 8; packet->data[ethlen + 10] = checksum >> 8;
packet->data[25] = checksum & 0xff; packet->data[ethlen + 11] = checksum & 0xff;
return true; return true;
case ETH_P_IPV6: case ETH_P_IPV6:
if(!checklength(source, packet, 14 + 40)) if(!checklength(source, packet, ethlen + ip6_size))
return false; return false;
if(packet->data[21] < 1) { if(packet->data[ethlen + 7] < 1) {
if(packet->data[20] != IPPROTO_ICMPV6 || packet->data[54] != ICMP6_TIME_EXCEEDED) if(packet->data[ethlen + 6] != IPPROTO_ICMPV6 || packet->data[ethlen + 40] != ICMP6_TIME_EXCEEDED)
route_ipv6_unreachable(source, packet, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT); route_ipv6_unreachable(source, packet, ethlen, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT);
return false; return false;
} }
packet->data[21]--; packet->data[ethlen + 7]--;
return true; return true;

View file

@ -398,6 +398,8 @@ splay_node_t *splay_insert_node(splay_tree_t *tree, splay_node_t *node) {
splay_node_t *closest; splay_node_t *closest;
int result; int result;
node->left = node->right = node->parent = node->next = node->prev = NULL;
if(!tree->root) if(!tree->root)
splay_insert_top(tree, node); splay_insert_top(tree, node);
else { else {
@ -418,6 +420,7 @@ splay_node_t *splay_insert_node(splay_tree_t *tree, splay_node_t *node) {
void splay_insert_top(splay_tree_t *tree, splay_node_t *node) { void splay_insert_top(splay_tree_t *tree, splay_node_t *node) {
node->prev = node->next = node->left = node->right = node->parent = NULL; node->prev = node->next = node->left = node->right = node->parent = NULL;
tree->head = tree->tail = tree->root = node; tree->head = tree->tail = tree->root = node;
tree->count++;
} }
void splay_insert_before(splay_tree_t *tree, splay_node_t *before, splay_node_t *node) { void splay_insert_before(splay_tree_t *tree, splay_node_t *before, splay_node_t *node) {
@ -446,6 +449,7 @@ void splay_insert_before(splay_tree_t *tree, splay_node_t *before, splay_node_t
node->parent = NULL; node->parent = NULL;
tree->root = node; tree->root = node;
tree->count++;
} }
void splay_insert_after(splay_tree_t *tree, splay_node_t *after, splay_node_t *node) { void splay_insert_after(splay_tree_t *tree, splay_node_t *after, splay_node_t *node) {
@ -474,6 +478,7 @@ void splay_insert_after(splay_tree_t *tree, splay_node_t *after, splay_node_t *n
node->parent = NULL; node->parent = NULL;
tree->root = node; tree->root = node;
tree->count++;
} }
splay_node_t *splay_unlink(splay_tree_t *tree, void *data) { splay_node_t *splay_unlink(splay_tree_t *tree, void *data) {
@ -511,6 +516,8 @@ void splay_unlink_node(splay_tree_t *tree, splay_node_t *node) {
} else { } else {
tree->root = NULL; tree->root = NULL;
} }
tree->count--;
} }
void splay_delete_node(splay_tree_t *tree, splay_node_t *node) { void splay_delete_node(splay_tree_t *tree, splay_node_t *node) {

View file

@ -58,6 +58,8 @@ typedef struct splay_tree_t {
splay_compare_t compare; splay_compare_t compare;
splay_action_t delete; splay_action_t delete;
int count;
} splay_tree_t; } splay_tree_t;
/* (De)constructors */ /* (De)constructors */

View file

@ -29,6 +29,7 @@ bool send_request(void *c, const char *msg, ...) { return false; }
struct list_t *connection_list = NULL; struct list_t *connection_list = NULL;
bool send_meta(void *c, const char *msg , int len) { return false; } bool send_meta(void *c, const char *msg , int len) { return false; }
char *logfilename = NULL; char *logfilename = NULL;
struct timeval now;
ecdsa_t mykey, hiskey; ecdsa_t mykey, hiskey;

View file

@ -57,11 +57,12 @@ static char *name = NULL;
static char *identname = NULL; /* program name for syslog */ static char *identname = NULL; /* program name for syslog */
static char *pidfilename = NULL; /* pid file location */ static char *pidfilename = NULL; /* pid file location */
static char *confdir = NULL; static char *confdir = NULL;
static char controlcookie[1024]; static char controlcookie[1025];
char *netname = NULL; char *netname = NULL;
char *confbase = NULL; char *confbase = NULL;
static char *tinc_conf = NULL; static char *tinc_conf = NULL;
static char *hosts_dir = NULL; static char *hosts_dir = NULL;
struct timeval now;
// Horrible global variables... // Horrible global variables...
static int pid = 0; static int pid = 0;
@ -134,7 +135,7 @@ static void usage(bool status) {
" generate-rsa-keys [bits] Generate a new RSA public/private keypair.\n" " generate-rsa-keys [bits] Generate a new RSA public/private keypair.\n"
" generate-ecdsa-keys Generate a new ECDSA public/private keypair.\n" " generate-ecdsa-keys Generate a new ECDSA public/private keypair.\n"
" dump Dump a list of one of the following things:\n" " dump Dump a list of one of the following things:\n"
" nodes - all known nodes in the VPN\n" " [reachable] nodes - all known nodes in the VPN\n"
" edges - all known connections in the VPN\n" " edges - all known connections in the VPN\n"
" subnets - all known subnets in the VPN\n" " subnets - all known subnets in the VPN\n"
" connections - all meta connections with ourself\n" " connections - all meta connections with ourself\n"
@ -708,8 +709,8 @@ static bool connect_tincd(bool verbose) {
return false; return false;
} }
char host[128]; char host[129];
char port[128]; char port[129];
if(fscanf(f, "%20d %1024s %128s port %128s", &pid, controlcookie, host, port) != 4) { if(fscanf(f, "%20d %1024s %128s port %128s", &pid, controlcookie, host, port) != 4) {
if(verbose) if(verbose)
@ -911,6 +912,19 @@ static int cmd_reload(int argc, char *argv[]) {
} }
static int cmd_dump(int argc, char *argv[]) { static int cmd_dump(int argc, char *argv[]) {
bool only_reachable = false;
if(argc > 2 && !strcasecmp(argv[1], "reachable")) {
if(strcasecmp(argv[2], "nodes")) {
fprintf(stderr, "`reachable' only supported for nodes.\n");
usage(true);
return 1;
}
only_reachable = true;
argv++;
argc--;
}
if(argc != 2) { if(argc != 2) {
fprintf(stderr, "Invalid number of arguments.\n"); fprintf(stderr, "Invalid number of arguments.\n");
usage(true); usage(true);
@ -985,8 +999,10 @@ static int cmd_dump(int argc, char *argv[]) {
fprintf(stderr, "Unable to parse node dump from tincd: %s\n", line); fprintf(stderr, "Unable to parse node dump from tincd: %s\n", line);
return 1; return 1;
} }
memcpy(&status, &status_int, sizeof status);
if(do_graph) { if(do_graph) {
memcpy(&status, &status_int, sizeof status);
const char *color = "black"; const char *color = "black";
if(!strcmp(host, "MYSELF")) if(!strcmp(host, "MYSELF"))
color = "green"; color = "green";
@ -1000,6 +1016,8 @@ static int cmd_dump(int argc, char *argv[]) {
color = "green"; color = "green";
printf(" %s [label = \"%s\", color = \"%s\"%s];\n", node, node, color, strcmp(host, "MYSELF") ? "" : ", style = \"filled\""); printf(" %s [label = \"%s\", color = \"%s\"%s];\n", node, node, color, strcmp(host, "MYSELF") ? "" : ", style = \"filled\"");
} else { } else {
if(only_reachable && !status.reachable)
continue;
printf("%s at %s port %s cipher %d digest %d maclength %d compression %d options %x status %04x nexthop %s via %s distance %d pmtu %hd (min %hd max %hd)\n", printf("%s at %s port %s cipher %d digest %d maclength %d compression %d options %x status %04x nexthop %s via %s distance %d pmtu %hd (min %hd max %hd)\n",
node, host, port, cipher, digest, maclength, compression, options, status_int, nexthop, via, distance, pmtu, minmtu, maxmtu); node, host, port, cipher, digest, maclength, compression, options, status_int, nexthop, via, distance, pmtu, minmtu, maxmtu);
} }
@ -1233,6 +1251,7 @@ static struct {
} const variables[] = { } const variables[] = {
/* Server configuration */ /* Server configuration */
{"AddressFamily", VAR_SERVER}, {"AddressFamily", VAR_SERVER},
{"AutoConnect", VAR_SERVER},
{"BindToAddress", VAR_SERVER | VAR_MULTIPLE}, {"BindToAddress", VAR_SERVER | VAR_MULTIPLE},
{"BindToInterface", VAR_SERVER}, {"BindToInterface", VAR_SERVER},
{"Broadcast", VAR_SERVER}, {"Broadcast", VAR_SERVER},
@ -1945,7 +1964,7 @@ static char *complete_command(const char *text, int state) {
} }
static char *complete_dump(const char *text, int state) { static char *complete_dump(const char *text, int state) {
const char *matches[] = {"nodes", "edges", "subnets", "connections", "graph", NULL}; const char *matches[] = {"reachable", "nodes", "edges", "subnets", "connections", "graph", NULL};
static int i; static int i;
if(!state) if(!state)

View file

@ -450,11 +450,6 @@ int main2(int argc, char **argv) {
} }
#endif #endif
if(!event_init()) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error initializing libevent!");
return 1;
}
/* Setup sockets and open device. */ /* Setup sockets and open device. */
if(!setup_network()) if(!setup_network())

198
src/top.c
View file

@ -57,11 +57,13 @@ static int sortmode = 0;
static bool cumulative = false; static bool cumulative = false;
static list_t node_list; static list_t node_list;
static struct timeval now, prev, diff; static struct timeval cur, prev, diff;
static int delay = 1000; static int delay = 1000;
static bool changed = true; static bool changed = true;
static const char *unit = "bytes"; static const char *bunit = "bytes";
static float scale = 1; static float bscale = 1;
static const char *punit = "pkts";
static float pscale = 1;
#ifndef timersub #ifndef timersub
#define timersub(a, b, c) do {(c)->tv_sec = (a)->tv_sec - (b)->tv_sec; (c)->tv_usec = (a)->tv_usec = (b)->tv_usec;} while(0) #define timersub(a, b, c) do {(c)->tv_sec = (a)->tv_sec - (b)->tv_sec; (c)->tv_usec = (a)->tv_usec = (b)->tv_usec;} while(0)
@ -69,10 +71,10 @@ static float scale = 1;
static void update(int fd) { static void update(int fd) {
sendline(fd, "%d %d", CONTROL, REQ_DUMP_TRAFFIC); sendline(fd, "%d %d", CONTROL, REQ_DUMP_TRAFFIC);
gettimeofday(&now, NULL); gettimeofday(&cur, NULL);
timersub(&now, &prev, &diff); timersub(&cur, &prev, &diff);
prev = now; prev = cur;
float interval = diff.tv_sec + diff.tv_usec * 1e-6; float interval = diff.tv_sec + diff.tv_usec * 1e-6;
char line[4096]; char line[4096];
@ -136,12 +138,69 @@ static void update(int fd) {
} }
} }
static int cmpfloat(float a, float b) {
if(a < b)
return -1;
else if(a > b)
return 1;
else
return 0;
}
static int cmpu64(uint64_t a, uint64_t b) {
if(a < b)
return -1;
else if(a > b)
return 1;
else
return 0;
}
static int sortfunc(const void *a, const void *b) {
const nodestats_t *na = *(const nodestats_t **)a;
const nodestats_t *nb = *(const nodestats_t **)b;
switch(sortmode) {
case 1:
if(cumulative)
return -cmpu64(na->in_packets, nb->in_packets) ?: na->i - nb->i;
else
return -cmpfloat(na->in_packets_rate, nb->in_packets_rate) ?: na->i - nb->i;
case 2:
if(cumulative)
return -cmpu64(na->in_bytes, nb->in_bytes) ?: na->i - nb->i;
else
return -cmpfloat(na->in_bytes_rate, nb->in_bytes_rate) ?: na->i - nb->i;
case 3:
if(cumulative)
return -cmpu64(na->out_packets, nb->out_packets) ?: na->i - nb->i;
else
return -cmpfloat(na->out_packets_rate, nb->out_packets_rate) ?: na->i - nb->i;
case 4:
if(cumulative)
return -cmpu64(na->out_bytes, nb->out_bytes) ?: na->i - nb->i;
else
return -cmpfloat(na->out_bytes_rate, nb->out_bytes_rate) ?: na->i - nb->i;
case 5:
if(cumulative)
return -cmpu64(na->in_packets + na->out_packets, nb->in_packets + nb->out_packets) ?: na->i - nb->i;
else
return -cmpfloat(na->in_packets_rate + na->out_packets_rate, nb->in_packets_rate + nb->out_packets_rate) ?: na->i - nb->i;
case 6:
if(cumulative)
return -cmpu64(na->in_bytes + na->out_bytes, nb->in_bytes + nb->out_bytes) ?: na->i - nb->i;
else
return -cmpfloat(na->in_bytes_rate + na->out_bytes_rate, nb->in_bytes_rate + nb->out_bytes_rate) ?: na->i - nb->i;
default:
return strcmp(na->name, nb->name) ?: na->i - nb->i;
}
}
static void redraw(void) { static void redraw(void) {
erase(); erase();
mvprintw(0, 0, "Tinc %-16s Nodes: %4d Sort: %-10s %s", netname ?: "", node_list.count, sortname[sortmode], cumulative ? "Cumulative" : "Current"); mvprintw(0, 0, "Tinc %-16s Nodes: %4d Sort: %-10s %s", netname ?: "", node_list.count, sortname[sortmode], cumulative ? "Cumulative" : "Current");
attrset(A_REVERSE); attrset(A_REVERSE);
mvprintw(2, 0, "Node IN pkts IN %s OUT pkts OUT %s", unit, unit); mvprintw(2, 0, "Node IN %s IN %s OUT %s OUT %s", punit, bunit, punit, bunit);
chgat(-1, A_REVERSE, 0, NULL); chgat(-1, A_REVERSE, 0, NULL);
static nodestats_t **sorted = 0; static nodestats_t **sorted = 0;
@ -157,63 +216,6 @@ static void redraw(void) {
for(int i = 0; i < n; i++) for(int i = 0; i < n; i++)
sorted[i]->i = i; sorted[i]->i = i;
int cmpfloat(float a, float b) {
if(a < b)
return -1;
else if(a > b)
return 1;
else
return 0;
}
int cmpu64(uint64_t a, uint64_t b) {
if(a < b)
return -1;
else if(a > b)
return 1;
else
return 0;
}
int sortfunc(const void *a, const void *b) {
const nodestats_t *na = *(const nodestats_t **)a;
const nodestats_t *nb = *(const nodestats_t **)b;
switch(sortmode) {
case 1:
if(cumulative)
return -cmpu64(na->in_packets, nb->in_packets) ?: na->i - nb->i;
else
return -cmpfloat(na->in_packets_rate, nb->in_packets_rate) ?: na->i - nb->i;
case 2:
if(cumulative)
return -cmpu64(na->in_bytes, nb->in_bytes) ?: na->i - nb->i;
else
return -cmpfloat(na->in_bytes_rate, nb->in_bytes_rate) ?: na->i - nb->i;
case 3:
if(cumulative)
return -cmpu64(na->out_packets, nb->out_packets) ?: na->i - nb->i;
else
return -cmpfloat(na->out_packets_rate, nb->out_packets_rate) ?: na->i - nb->i;
case 4:
if(cumulative)
return -cmpu64(na->out_bytes, nb->out_bytes) ?: na->i - nb->i;
else
return -cmpfloat(na->out_bytes_rate, nb->out_bytes_rate) ?: na->i - nb->i;
case 5:
if(cumulative)
return -cmpu64(na->in_packets + na->out_packets, nb->in_packets + nb->out_packets) ?: na->i - nb->i;
else
return -cmpfloat(na->in_packets_rate + na->out_packets_rate, nb->in_packets_rate + nb->out_packets_rate) ?: na->i - nb->i;
case 6:
if(cumulative)
return -cmpu64(na->in_bytes + na->out_bytes, nb->in_bytes + nb->out_bytes) ?: na->i - nb->i;
else
return -cmpfloat(na->in_bytes_rate + na->out_bytes_rate, nb->in_bytes_rate + nb->out_bytes_rate) ?: na->i - nb->i;
default:
return strcmp(na->name, nb->name) ?: na->i - nb->i;
}
}
qsort(sorted, n, sizeof *sorted, sortfunc); qsort(sorted, n, sizeof *sorted, sortfunc);
for(int i = 0, row = 3; i < n; i++, row++) { for(int i = 0, row = 3; i < n; i++, row++) {
@ -228,10 +230,10 @@ static void redraw(void) {
if(cumulative) if(cumulative)
mvprintw(row, 0, "%-16s %10"PRIu64" %10.0f %10"PRIu64" %10.0f", mvprintw(row, 0, "%-16s %10"PRIu64" %10.0f %10"PRIu64" %10.0f",
node->name, node->in_packets, node->in_bytes * scale, node->out_packets, node->out_bytes * scale); node->name, node->in_packets * pscale, node->in_bytes * bscale, node->out_packets * pscale, node->out_bytes * bscale);
else else
mvprintw(row, 0, "%-16s %10.0f %10.0f %10.0f %10.0f", mvprintw(row, 0, "%-16s %10.0f %10.0f %10.0f %10.0f",
node->name, node->in_packets_rate, node->in_bytes_rate * scale, node->out_packets_rate, node->out_bytes_rate * scale); node->name, node->in_packets_rate * pscale, node->in_bytes_rate * bscale, node->out_packets_rate * pscale, node->out_bytes_rate * bscale);
} }
attrset(A_NORMAL); attrset(A_NORMAL);
@ -262,45 +264,53 @@ void top(int fd) {
break; break;
} }
case 'c': case 'c':
cumulative = !cumulative; cumulative = !cumulative;
break; break;
case 'n': case 'n':
sortmode = 0; sortmode = 0;
break; break;
case 'i': case 'i':
sortmode = 2; sortmode = 2;
break; break;
case 'I': case 'I':
sortmode = 1; sortmode = 1;
break; break;
case 'o': case 'o':
sortmode = 4; sortmode = 4;
break; break;
case 'O': case 'O':
sortmode = 3; sortmode = 3;
break; break;
case 't': case 't':
sortmode = 6; sortmode = 6;
break; break;
case 'T': case 'T':
sortmode = 5; sortmode = 5;
break; break;
case 'b': case 'b':
unit = "bytes"; bunit = "bytes";
scale = 1; bscale = 1;
break; punit = "pkts";
pscale = 1;
break;
case 'k': case 'k':
unit = "kbyte"; bunit = "kbyte";
scale = 1e-3; bscale = 1e-3;
break; punit = "pkts";
pscale = 1;
break;
case 'M': case 'M':
unit = "Mbyte"; bunit = "Mbyte";
scale = 1e-6; bscale = 1e-6;
break; punit = "kpkt";
pscale = 1e-3;
break;
case 'G': case 'G':
unit = "Gbyte"; bunit = "Gbyte";
scale = 1e-9; bscale = 1e-9;
break; punit = "Mpkt";
pscale = 1e-6;
break;
case 'q': case 'q':
case KEY_BREAK: case KEY_BREAK:
running = false; running = false;