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
Author: Guus Sliepen <guus@tinc-vpn.org>
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
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/libevent.m4 \
$(top_srcdir)/m4/lzo.m4 $(top_srcdir)/m4/openssl.m4 \
$(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/zlib.m4 \
$(top_srcdir)/configure.in
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \
$(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \

387
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
* New experimental protocol:
@ -247,7 +261,7 @@ Version 1.0.6 Dec 18 2006
* 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.
version 1.0.5 Nov 14 2006
Version 1.0.5 Nov 14 2006
* Lots of small fixes.
@ -262,201 +276,175 @@ version 1.0.5 Nov 14 2006
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.
* 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.
* 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,
* 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.
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.
* 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
* Remove RSA key checking code, since it sometimes thinks perfectly good RSA
keys are bad.
* Fix handling of subnets when prefixlength isn't divisible by 8.
* Fix handling of subnets when prefixlength isn't divisible by 8.
Version 1.0pre6 Mar 27 2002
version 1.0pre6 Mar 27 2002
* Improvement of redundant links:
* 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.
* Good support for routing IPv6 packets over the VPN. Works on Linux,
* Good support for routing IPv6 packets over the VPN. Works on Linux,
FreeBSD, possibly OpenBSD but not on Solaris.
* Support for tunnels over IPv6 networks. Works on all supported
* Support for tunnels over IPv6 networks. Works on all supported
operating systems.
* Optional compression of UDP connections using zlib.
* Optional compression of UDP connections using zlib.
* Optionally let UDP connections inherit TOS field of tunneled packets.
* Optionally let UDP connections inherit TOS field of tunneled packets.
* Optionally start scripts when certain hosts become (un)reachable.
* Optionally start scripts when certain hosts become (un)reachable.
Version 1.0pre5 Feb 9 2002
version 1.0pre5 Feb 9 2002
* Security enhancements:
* Security enhancements:
* Added sequence number and optional message authentication code to
the packets.
* Configurable encryption cipher and digest algorithms.
* More robust handling of dis- and reconnects.
* More robust handling of dis- and reconnects.
* Added a "switch" and a "hub" mode to allow bridging setups.
* Added a "switch" and a "hub" mode to allow bridging setups.
* Preliminary support for routing of IPv6 packets.
* Preliminary support for routing of IPv6 packets.
* Supports Linux, FreeBSD, OpenBSD and Solaris.
* Supports Linux, FreeBSD, OpenBSD and Solaris.
Version 1.0pre4 Jan 17 2001
It looks like this might be the last release before 1.0.
version 1.0pre4 Jan 17 2001
* Updated documentation; the documentation now reflects the
* Updated documentation; the documentation now reflects the
configuration as it is.
* Some internal changes to make tinc scale better for large
* Some internal changes to make tinc scale better for large
networks, such as using AVL trees instead of linked lists for the
connection list.
* RSA keys can be stored in separate files if needed. See the
* RSA keys can be stored in separate files if needed. See the
documentation for more information.
* tinc has now been reported to run on Linux PowerPC and FreeBSD x86.
* Tinc has now been reported to run on Linux PowerPC and FreeBSD x86.
Version 1.0pre3 Oct 31 2000
version 1.0pre3 Oct 31 2000
* The protocol has been redesigned, and although some details are
* 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.
* Unfortunately this protocol is not compatible with earlier versions,
* 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:
* 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.
* New is also the support for the universal tun/tap device. This
* 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 is tested to compile on Solaris, Linux x86, Linux alpha.
* tinc now uses the OpenSSL library for cryptographic operations.
* 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
* Further, thanks to Enrique Zanardi, we have Spanish messages; Matias
Carrasco provided us with a Spanish translation of the manual.
Version 1.0pre2 May 31 2000
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
* This version has been internationalized; and a Dutch translation has
been included.
* Two configuration variables have been added:
* 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
@ -465,144 +453,177 @@ version 1.0pre2 May 31 2000
trying to connect to us. Default set to `no', to prevent lockups
during lookups.
* The system startup scripts for Debian and Redhat use
* 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
* 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
* 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
* 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.
Version 1.0pre1 May 12 2000
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
* Various other bugfixes
* Documentation updates
version 0.3.3 Feb 9 2000
* Fixed bug that made tinc stop working with latest kernels (Guus
Sliepen)
Version 0.3.3 Feb 9 2000
* Fixed bug that made tinc stop working with latest kernels
* Updated the manual
version 0.3.2 Nov 12 1999
* no more `Invalid filedescriptor' when working with multiple
connections
* forward unknown packets to uplink
Version 0.3.2 Nov 12 1999
version 0.3.1 Oct 20 1999
* fixed a bug where tinc would exit without a trace
* No more `Invalid filedescriptor' when working with multiple
connections.
version 0.3 Aug 20 1999
* pings now work immediately
* all packet sizes get transmitted correctly
* Forward unknown packets to uplink.
version 0.2.26 Aug 15 1999
* fixed some remaining bugs
* --sysconfdir works with configure
* last version before 0.3
Version 0.3.1 Oct 20 1999
version 0.2.25 Aug 8 1999
* improved stability, going towards 0.3 now.
* Fixed a bug where tinc would exit without a trace.
version 0.2.24 Aug 7 1999
* added key aging, there's a new config variable, KeyExpire.
* updated man and info pages
Version 0.3 Aug 20 1999
version 0.2.23 Aug 5 1999
* all known bugs fixed, this is a candidate for 0.3
* Pings now work immediately.
version 0.2.22 Apr 11 1999
* multiconnection thing is now working nearly perfect :)
* All packet sizes get transmitted correctly.
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
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
* blowfish library dynamically loaded upon execution
* included Eric Young's IDEA library
Version 0.2.18 Apr 3 1999
version 0.2.17 Apr 1 1999
* tincd now re-executes itself in case of a segmentation fault.
* Blowfish library dynamically loaded upon execution.
version 0.2.16 Apr 1 1999
* 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.
* Included Eric Young's IDEA library.
version 0.2.15 Mar 29 1999
* fixed bugs
Version 0.2.17 Apr 1 1999
version 0.2.14 Feb 10 1999
* added --timeout flag and PingTimeout configuration
* did some first syslog cleanup work
* Tincd now re-executes itself in case of a segmentation fault.
version 0.2.13 Jan 23 1999
* bugfixes
Version 0.2.16 Apr 1 1999
version 0.2.12 Jan 23 1999
* fixed nauseating bug so that it would crash whenever a connection
got lost
* Wrote tincd.conf(5) man page, which still needs a lot of work.
version 0.2.11 Jan 22 1999
* framework for multiple connections has been done
* simple manpage for tincd
* 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.10 Jan 18 1999
* passphrase support added
Version 0.2.15 Mar 29 1999
version 0.2.9 Jan 13 1999
* bugs fixed.
* Fixed bugs.
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.14 Feb 10 1999
version 0.2.7 Jan 3 1999
* several updates to make extending more easy.
* Added --timeout flag and PingTimeout configuration.
* 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
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.
version 0.2.4 Dec 16 1998
* now it really does ;)
Version 0.2.4 Dec 16 1998
version 0.2.3 Nov 24 1998
* it sort of works now
* Now it really does ;)
version 0.2.2 Nov 20 1998
* uses GNU gmp.
Version 0.2.3 Nov 24 1998
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.

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.
tinc is Copyright (C) 1998-2012 by:
@ -36,11 +36,11 @@ at your own risk.
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.
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
@ -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:
- 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:

1
aclocal.m4 vendored
View file

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

View file

@ -64,9 +64,6 @@
/* Define to 1 if you have the `ECDSA_verify' function. */
#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. */
#undef HAVE_EVP_ENCRYPTINIT_EX

112
configure vendored
View file

@ -738,7 +738,6 @@ enable_uml
enable_vde
enable_tunemu
with_windows2000
with_libgcrypt
enable_curses
with_curses
with_curses_include
@ -747,9 +746,6 @@ enable_readline
with_readline
with_readline_include
with_readline_lib
with_libevent
with_libevent_include
with_libevent_lib
enable_zlib
with_zlib
with_zlib_include
@ -1393,9 +1389,9 @@ Optional Features:
--enable-dependency-tracking do not reject slow dependency extractors
--enable-maintainer-mode enable make rules and dependencies not useful
(and sometimes confusing) to the casual installer
--disable-uml enable support for User Mode Linux
--disable-vde enable support for Virtual Distributed Ethernet
--disable-tunemu enable support for the tunemu driver
--enable-uml enable support for User Mode Linux
--enable-vde enable support for Virtual Distributed Ethernet
--enable-tunemu enable support for the tunemu driver
--disable-curses disable curses support
--disable-readline disable readline 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-windows2000 compile with support for Windows 2000. This disables
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-include=DIR
curses headers directory
@ -1417,10 +1412,6 @@ Optional Packages:
--with-readline-include=DIR
readline headers 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-include=DIR zlib headers directory
--with-zlib-lib=DIR zlib library directory
@ -4104,7 +4095,7 @@ fi
# Define the identity of the package.
PACKAGE=tinc
VERSION=1.1pre3
VERSION=1.1pre4
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.
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.
if test "${enable_zlib+set}" = set; then :
enableval=$enable_zlib;

View file

@ -4,7 +4,7 @@ AC_PREREQ(2.61)
AC_INIT
AC_CONFIG_SRCDIR([src/tincd.c])
AC_GNU_SOURCE
AM_INIT_AUTOMAKE(tinc, 1.1pre3)
AM_INIT_AUTOMAKE(tinc, 1.1pre4)
AC_CONFIG_HEADERS([config.h])
AM_MAINTAINER_MODE
@ -74,7 +74,7 @@ case $host_os in
esac
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"],
[ AC_DEFINE(ENABLE_UML, 1, [Support for UML])
uml=true
@ -85,7 +85,7 @@ AC_ARG_ENABLE(uml,
)
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"],
[ AC_CHECK_HEADERS(libvdeplug_dyn.h, [], [AC_MSG_ERROR([VDE plug header files not found.]); break])
AC_DEFINE(ENABLE_VDE, 1, [Support for VDE])
@ -97,7 +97,7 @@ AC_ARG_ENABLE(vde,
)
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"],
[ AC_DEFINE(ENABLE_TUNEMU, 1, [Support for tunemu])
tunemu=true
@ -179,11 +179,10 @@ AC_CACHE_SAVE
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_READLINE
tinc_LIBEVENT
tinc_ZLIB
tinc_LZO

View file

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

Binary file not shown.

View file

@ -3,16 +3,13 @@
.\" Manual page created by:
.\" Ivo Timmermans
.\" Guus Sliepen <guus@tinc-vpn.org>
.Sh NAME
.Nm tinc.conf
.Nd tinc daemon configuration
.Sh DESCRIPTION
The files in the
.Pa @sysconfdir@/tinc/
directory contain runtime and security information for the tinc daemon.
.Sh NETWORKS
To distinguish multiple instances of tinc running on one computer,
you can use the
@ -44,31 +41,26 @@ the configuration file should be
.Pa @sysconfdir@/tinc/tinc.conf ,
and the host configuration files are now expected to be in
.Pa @sysconfdir@/tinc/hosts/ .
.Sh NAMES
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 has to be declared in the
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf
file.
.Pp
To make things easy,
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.
However, you are only allowed to use alphanumerical characters (a-z, A-Z, and 0-9) and underscores (_) in the name.
.Sh INITIAL CONFIGURATION
If you have not configured tinc yet, you can easily create a basic configuration using the following command:
.Bd -literal -offset indent
.Nm tincctl Fl n Ar NETNAME Li init Ar NAME
.Ed
.Pp
You can further change the configuration as needed either by manually editing the configuration files,
or by using
.Xr tincctl 8 .
.Sh PUBLIC/PRIVATE KEYS
The
.Nm tincctl Li init
@ -81,24 +73,20 @@ in the directory
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /
The public keys should be stored in the host configuration file
.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.
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:
.Bd -literal -offset indent
.Nm tincctl Fl n Ar NETNAME Li generate-ecdsa-keys
.Ed
.Sh SERVER CONFIGURATION
The server configuration of the daemon is done in the file
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf .
This file consists of comments (lines started with a
.Li # )
or assignments in the form of:
.Pp
.Va Variable Li = Ar Value .
.Pp
The variable names are case insensitive, and any spaces, tabs,
newlines and carriage returns are ignored.
@ -106,31 +94,35 @@ Note: it is not required that you put in the
.Li =
sign, but doing so improves readability.
If you leave it out, remember to replace it with at least one space character.
.Pp
The server configuration is complemented with host specific configuration (see the next section).
Although all configuration options for the local host listed in this document can also be put in
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf ,
it is recommended to put host specific configuration options in the host configuration file,
as this makes it easy to exchange with other nodes.
.Pp
You can edit the config file manually, but it is recommended that you use
.Xr tincctl 8
to change configuration variables for you.
.Pp
Here are all valid variables, listed in alphabetical order.
The default value is given between parentheses.
.Bl -tag -width indent
.It Va AddressFamily Li = ipv4 | ipv6 | any Pq any
This option affects the address family of listening and outgoing sockets.
If
.Qq any
is selected, then depending on the operating system both IPv4 and IPv6 or just
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
If your computer has more than one IPv4 or IPv6 address,
.Nm tinc
@ -149,38 +141,31 @@ To only bind to a specific port but not to a specific address, use
.Li *
for the
.Ar address .
.It Va BindToInterface Li = Ar interface Bq experimental
If your computer has more than one network interface,
.Nm tinc
will by default listen on all of them for incoming connections.
It is possible to bind only to a single interface with this variable.
.Pp
This option may not work on all platforms.
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.
.It Va Broadcast Li = no | mst | direct Po mst Pc Bq experimental
This option selects the way broadcast packets are sent to other daemons.
NOTE: all nodes in a VPN must use the same
.Va Broadcast
mode, otherwise routing loops can form.
.Bl -tag -width indent
.It no
Broadcast packets are never sent to other nodes.
.It mst
Broadcast packets are sent and forwarded via the VPN's Minimum Spanning Tree.
This ensures broadcast packets reach all nodes.
.It direct
Broadcast packets are sent directly to all nodes that can be reached directly.
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.
.El
.It Va ConnectTo Li = Ar name
Specifies which other tinc daemon to connect to on startup.
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
.Va ConnectTo
line).
.Pp
If you don't specify a host with
.Va ConnectTo ,
.Nm tinc
won't try to connect to other daemons at all,
and will instead just listen for incoming connections.
.It Va DecrementTTL Li = yes | no Po no Pc Bq experimental
When enabled,
.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.
.Pp
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
The virtual network device to use.
.Nm tinc
@ -220,18 +202,15 @@ instead of
.Va Device .
The info pages of the tinc package contain more information
about configuring the virtual network device.
.It Va DeviceType Li = Ar type Pq platform dependent
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.
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
.It dummy
Use a dummy interface.
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.
.It raw_socket
Open a raw socket, and bind it to a pre-existing
.Va Interface
@ -239,7 +218,6 @@ Open a raw socket, and bind it to a pre-existing
All packets are read from this interface.
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.
.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
.Va Device .
@ -249,7 +227,6 @@ Do NOT connect multiple
.Nm tinc
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.
.It uml Pq not compiled in by default
Create a UNIX socket with the filename specified by
.Va Device ,
@ -258,7 +235,6 @@ or
if not specified.
.Nm tinc
will wait for a User Mode Linux instance to connect to this socket.
.It vde Pq not compiled in by default
Uses the libvdeplug library to connect to a Virtual Distributed Ethernet switch,
using the UNIX socket specified by
@ -267,46 +243,37 @@ or
.Pa @localstatedir@/run/vde.ctl
if not specified.
.El
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:
.Bl -tag -width indent
.It tun Pq BSD and Linux
Set type to tun.
Depending on the platform, this can either be with or without an address family header (see below).
.It tunnohead Pq BSD
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.
On some platforms IPv6 packets cannot be read from or written to the device in this mode.
.It tunifhead Pq BSD
Set type to tun with an address family header.
Tinc will expect packets read from the virtual network device
to start with a four byte header containing the address family,
followed by an IP header.
This mode should support both IPv4 and IPv6 packets.
.It tap Pq BSD and Linux
Set type to tap.
Tinc will expect packets read from the virtual network device
to start with an Ethernet header.
.El
.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,
but which would have to be forwarded by an intermediate node, are dropped instead.
When combined with the IndirectData option,
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
The file in which the private ECDSA key of this tinc daemon resides.
This is only used if
.Va ExperimentalProtocol
is enabled.
.It Va ExperimentalProtocol Li = yes | no Po no Pc Bq experimental
When this option is enabled, experimental protocol enhancements will be used.
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 .
The experimental protocol may change at any time,
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
This option selects the way indirect packets are forwarded.
.Bl -tag -width indent
.It off
Incoming packets that are not meant for the local node,
but which should be forwarded to another node, are dropped.
.It internal
Incoming packets that are meant for another node are forwarded by tinc internally.
.Pp
This is the default mode, and unless you really know you need another forwarding mode, don't change it.
.It kernel
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,
and can also help debugging.
.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
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
efficiency, even stopping the daemon for a few seconds every time it does
a lookup if your DNS server is not responding.
.Pp
This does not affect resolving hostnames to IP addresses from the
host configuration files, but whether hostnames should be resolved while logging.
.It Va IffOneQueue Li = yes | no Po no Pc Bq experimental
(Linux only) Set IFF_ONE_QUEUE flag on TUN/TAP devices.
.It Va Interface Li = Ar interface
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.
@ -369,12 +314,10 @@ Under Windows, this variable is used to select which network interface will be u
If you specified a
.Va Device ,
this variable is almost always already correctly set.
.It Va KeyExpire Li = Ar seconds Pq 3600
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,
even though it is thought to be nearly impossible to crack a single key.
.It Va LocalDiscovery Li = yes | no Pq no
When enabled,
.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
and they only ConnectTo a third node outside the NAT,
which normally would prevent the peers from learning each other's LAN address.
.Pp
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.
.It Va MACExpire Li = Ar seconds Pq 600
This option controls the amount of time MAC addresses are kept before they are removed.
This only has effect when
.Va Mode
is set to
.Qq switch .
.It Va MaxTimeout Li = Ar seconds Pq 900
This is the maximum delay before trying to reconnect to other tinc daemons.
.It Va Mode Li = router | switch | hub Pq router
This option selects the way packets are routed to other daemons.
.Bl -tag -width indent
.It router
In this mode
.Va Subnet
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.
.Pp
This is the default mode, and unless you really know you need another mode, don't change it.
.It switch
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.
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.
.Pp
This mode is primarily useful if you want to bridge Ethernet segments.
.It hub
This mode is almost the same as the switch mode, but instead
every packet will be broadcast to the other daemons
while no routing table is managed.
.El
.It Va Name Li = Ar name Bq required
This is the name which identifies this tinc daemon.
It must be unique for the virtual private network this daemon will connect to.
The Name may only consist of alphanumeric and underscore characters.
If
.Va Name
starts with a
@ -441,40 +373,28 @@ If
is
.Li $HOST ,
but no such environment variable exist, the hostname will be read using the gethostnname() system call.
.It Va PingInterval Li = Ar seconds Pq 60
The number of seconds of inactivity that
.Nm tinc
will wait before sending a probe to the other end.
.It Va PingTimeout Li = Ar seconds Pq 5
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,
the connection is terminated,
and the others will be notified of this.
.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
will be inherited by the UDP packets that are sent out.
.It Va PrivateKey Li = Ar key Bq obsolete
The private RSA key of this tinc daemon.
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
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
When this option is used the priority of the
.Nm tincd
process will be adjusted.
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
Use a proxy when making outgoing connections.
The following proxy types are currently supported:
@ -507,7 +427,6 @@ and
.Ev REMOTEPORT
are available.
.El
.It Va ReplayWindow Li = Ar bytes Pq 16
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
@ -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
pass all traffic, but leaves tinc vulnerable to replay-based attacks on your
traffic.
.It Va StrictSubnets Li = yes | no Po no Pc Bq experimental
When this option is enabled tinc will only use Subnet statements which are
present in the host config files in the local
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/
directory.
.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,
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/
directory.
Setting this options also implicitly sets StrictSubnets.
.It Va UDPRcvBuf Li = Ar bytes Pq OS default
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.
.It Va UDPSndBuf Li = Ar bytes Pq OS default
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.
.El
.Sh HOST CONFIGURATION FILES
The host configuration files contain all information needed
to establish a connection to those hosts.
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.
.Pp
The idea is that these files are portable.
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,
no secrets are revealed by sending out this information.
.Bl -tag -width indent
.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.
This will only be used when trying to make an outgoing connection to this tinc daemon.
@ -563,7 +475,6 @@ Multiple
.Va Address
variables can be specified, in which case each address will be tried until a working
connection has been established.
.It Va Cipher Li = Ar cipher Pq blowfish
The symmetric cipher algorithm used to encrypt UDP packets.
Any cipher supported by OpenSSL is recognised.
@ -571,24 +482,20 @@ Furthermore, specifying
.Qq none
will turn off packet encryption.
It is best to use only those ciphers which support CBC mode.
.It Va ClampMSS Li = yes | no Pq yes
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
Fragmentation Needed or Packet too Big messages are dropped by firewalls.
.It Va Compression Li = Ar level Pq 0
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),
10 (fast lzo) and 11 (best lzo).
.It Va Digest Li = Ar digest Pq sha1
The digest algorithm used to authenticate UDP packets.
Any digest supported by OpenSSL is recognised.
Furthermore, specifying
.Qq none
will turn off packet authentication.
.It Va IndirectData Li = yes | no Pq no
This option specifies whether other tinc daemons besides the one you specified with
.Va ConnectTo
@ -596,33 +503,26 @@ can make a direct connection to you.
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.
Otherwise, it is best to leave this option out or set it to no.
.It Va MACLength Li = Ar length Pq 4
The length of the message authentication code used to authenticate UDP packets.
Can be anything from
.Qq 0
up to the length of the digest produced by the digest algorithm.
.It Va PMTU Li = Ar mtu Po 1514 Pc
This option controls the initial path MTU to this node.
.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.
After the path MTU has been discovered, it will be enforced on the VPN.
.It Va Port Li = Ar port Pq 655
The port number on which this tinc daemon is listening for incoming connections,
which is used if no port number is specified in an
.Va Address
statement.
.It Va PublicKey Li = Ar key Bq obsolete
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 Va PublicKeyFile Li = Ar filename Bq obsolete
The file in which the public RSA key of this tinc daemon resides.
.Pp
From version 1.0pre4 on
.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
in each host configuration file,
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
The subnet which this tinc daemon will serve.
.Nm tinc
@ -641,7 +540,6 @@ it will be sent to the daemon who has this subnet in his host configuration file
Multiple
.Va Subnet
variables can be specified.
.Pp
Subnets can either be single MAC, IPv4 or IPv6 addresses,
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.
IPv6 subnets are notated like fec0:0:0:1::/64.
MAC addresses are notated like 0:1a:2b:3c:4d:5e.
.Pp
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
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
priority will be tried, and so on.
.It Va TCPOnly Li = yes | no Pq no Bq obsolete
If this variable is set to yes,
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,
or if UDP packet routing is disabled somehow.
Setting this options also implicitly sets IndirectData.
.Pp
Since version 1.0.10, tinc will automatically detect whether communication via
UDP is possible or not.
.El
.Sh SCRIPTS
Apart from reading the server and host configuration files,
tinc can also run scripts at certain moments.
Under Windows (not Cygwin), the scripts should have the extension
.Pa .bat .
.Bl -tag -width indent
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up
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.
It should be used to set up the corresponding network interface,
but can also be used to start other things.
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
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
This script is started when the tinc daemon with name
.Ar HOST
becomes reachable.
.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
.Ar HOST
becomes unreachable.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /host-up
This script is started when any host becomes reachable.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /host-down
This script is started when any host becomes unreachable.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /subnet-up
This script is started when a Subnet becomes reachable.
The Subnet and the node it belongs to are passed in environment variables.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /subnet-down
This script is started when a Subnet becomes unreachable.
.El
.Pp
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
@ -725,73 +610,55 @@ files, they have to be put between
.Li %
signs.
.Bl -tag -width indent
.It Ev NETNAME
If a netname was specified, this environment variable contains it.
.It Ev NAME
Contains the name of this tinc daemon.
.It Ev DEVICE
Contains the name of the virtual network device that tinc uses.
.It Ev INTERFACE
Contains the name of the virtual network interface that tinc uses.
This should be used for commands like
.Pa ifconfig .
.It Ev NODE
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.
.It Ev REMOTEADDRESS
When a host becomes (un)reachable, this is set to its real address.
.It Ev REMOTEPORT
When a host becomes (un)reachable, this is set to the port number it uses for communication with other tinc daemons.
.It Ev SUBNET
When a subnet becomes (un)reachable, this is set to the subnet.
.It Ev WEIGHT
When a subnet becomes (un)reachable, this is set to the subnet weight.
.El
.Pp
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 .
.Sh FILES
The most important files are:
.Bl -tag -width indent
.It Pa @sysconfdir@/tinc/
The top directory for configuration files.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf
The default name of the server configuration file for net
.Ar NETNAME .
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/
Host configuration files are kept in this directory.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up
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 can be used to set up the corresponding network interface.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-down
If an executable file with this name exists,
it will be executed right before the tinc daemon is going to close
its connection to the virtual network device.
.El
.Sh SEE ALSO
.Xr tincd 8 ,
.Xr tincctl 8 ,
.Pa http://www.tinc-vpn.org/ ,
.Pa http://www.tldp.org/LDP/nag2/ .
.Pp
The full documentation for
.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
.Ic info tinc
should give you access to the complete manual.
.Pp
.Nm tinc
comes with ABSOLUTELY NO WARRANTY.

View file

@ -5,7 +5,7 @@ START-INFO-DIR-ENTRY
* tinc: (tinc). The tinc Manual.
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.
Copyright (C) 1998-2012 Ivo Timmermans, Guus Sliepen
@ -295,7 +295,8 @@ an error message, and stop.
* OpenSSL::
* zlib::
* lzo::
* libevent::
* libcurses::
* libreadline::

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.
If this library is not installed, you wil get an error when
configuring tinc for build. Support for running tinc without having
OpenSSL installed _may_ be added in the future.
configuring tinc for build. Support for running tinc with other
cryptographic libraries installed _may_ be added in the future.
You can use your operating system's package manager to install this
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
provided by the zlib library.
If this library is not installed, you wil get an error when
configuring tinc for build. Support for running tinc without having
zlib installed _may_ be added in the future.
If this library is not installed, you wil get an error when running
the configure script. You can either install the zlib library, or
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
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).

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
---------
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 tinc for build. Support for running tinc without having lzo
installed _may_ be added in the future.
If this library is not installed, you wil get an error when running
the configure script. You can either install the LZO library, or
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
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).

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
configuring tinc for build.
If this library is not installed, you wil get an error when running
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
if available. Make sure you install the development AND runtime
versions of this package.
If you have to install libevent manually, you can get the source code
from `http://libevent.org/'. Instructions on how to configure, build
and install this package are included within the package. Please make
sure you build development and runtime libraries (which is the default).
If you have to install libreadline manually, you can get the source
code from `http://www.gnu.org/software/readline/'. Instructions on how
to configure, build and install this package are included within the
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
@ -738,6 +773,13 @@ AddressFamily = <ipv4|ipv6|any> (any)
system both IPv4 and IPv6 or just IPv6 listening sockets will be
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>]
If your computer has more than one IPv4 or IPv6 address, tinc will
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
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)
This option selects whether IP addresses (both real and on the VPN)
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
a relative directory.
Note that there must be exactly one of PrivateKey or PrivateKeyFile
specified in the configuration file.
ProcessPriority = <low|normal|high>
When this option is used the priority of the tincd process will be
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
(you can use the -c or -n option).
`dump nodes'
Dump a list of all known nodes in the VPN.
`dump [reachable] nodes'
Dump a list of all known nodes in the VPN. If the reachable
keyword is used, only lists reachable nodes.
`dump edges'
Dump a list of all known connections in the VPN.
@ -2792,14 +2824,16 @@ Concept Index
* ANS_KEY: The meta-protocol. (line 64)
* authentication: Authentication protocol.
(line 6)
* AutoConnect: Main configuration variables.
(line 12)
* binary package: Building and installing tinc.
(line 9)
* BindToAddress: Main configuration variables.
(line 12)
(line 19)
* BindToInterface: Main configuration variables.
(line 23)
(line 30)
* Broadcast: Main configuration variables.
(line 34)
(line 41)
* Cabal: Security. (line 6)
* CHAL_REPLY: Authentication protocol.
(line 10)
@ -2818,29 +2852,29 @@ Concept Index
(line 24)
* connection: The connection. (line 6)
* ConnectTo: Main configuration variables.
(line 54)
(line 61)
* daemon: Running tinc. (line 11)
* data-protocol: The meta-connection. (line 18)
* debug level: Runtime options. (line 17)
* debug levels: Debug levels. (line 6)
* DecrementTTL: Main configuration variables.
(line 65)
(line 72)
* DEL_EDGE: The meta-protocol. (line 47)
* DEL_SUBNET: The meta-protocol. (line 47)
* DEVICE: Scripts. (line 55)
* Device: Main configuration variables.
(line 74)
(line 81)
* device files: Device files. (line 6)
* DeviceType: Main configuration variables.
(line 81)
(line 88)
* Digest: Host configuration variables.
(line 29)
* DirectOnly: Main configuration variables.
(line 146)
* dummy: Main configuration variables.
(line 88)
* ECDSAPrivateKeyFile: Main configuration variables.
(line 153)
* dummy: Main configuration variables.
(line 95)
* ECDSAPrivateKeyFile: Main configuration variables.
(line 160)
* encapsulating: The UDP tunnel. (line 30)
* encryption: Encryption of network packets.
(line 6)
@ -2848,52 +2882,51 @@ Concept Index
* example: Example configuration.
(line 6)
* exec: Main configuration variables.
(line 326)
(line 322)
* ExperimentalProtocol: Main configuration variables.
(line 157)
(line 164)
* Forwarding: Main configuration variables.
(line 166)
(line 173)
* frame type: The UDP tunnel. (line 6)
* GraphDumpFile: Main configuration variables.
(line 186)
* Hostnames: Main configuration variables.
(line 194)
(line 193)
* http: Main configuration variables.
(line 323)
(line 319)
* hub: Main configuration variables.
(line 247)
(line 246)
* ID: Authentication protocol.
(line 10)
* IndirectData: Host configuration variables.
(line 34)
* INTERFACE: Scripts. (line 58)
* Interface: Main configuration variables.
(line 205)
(line 204)
* IRC: Contact information. (line 9)
* KEY_CHANGED: The meta-protocol. (line 64)
* KeyExpire: Main configuration variables.
(line 252)
* libevent: libevent. (line 6)
(line 251)
* libcurses: libcurses. (line 6)
* libraries: Libraries. (line 6)
* libreadline: libreadline. (line 6)
* license: OpenSSL. (line 36)
* LocalDiscovery: Main configuration variables.
(line 213)
(line 212)
* lzo: lzo. (line 6)
* MACExpire: Main configuration variables.
(line 258)
(line 257)
* MACLength: Host configuration variables.
(line 42)
* meta-protocol: The meta-connection. (line 18)
* META_KEY: Authentication protocol.
(line 10)
* Mode: Main configuration variables.
(line 224)
(line 223)
* multicast: Main configuration variables.
(line 100)
(line 107)
* multiple networks: Multiple networks. (line 6)
* NAME: Scripts. (line 52)
* Name: Main configuration variables.
(line 263)
(line 262)
* netmask: Network interfaces. (line 39)
* NETNAME <1>: tincctl environment variables.
(line 6)
@ -2908,9 +2941,9 @@ Concept Index
(line 67)
* PING: The meta-protocol. (line 89)
* PingInterval: Main configuration variables.
(line 274)
(line 273)
* PingTimeout: Main configuration variables.
(line 278)
(line 277)
* platforms: Supported platforms. (line 6)
* PMTU: Host configuration variables.
(line 47)
@ -2921,32 +2954,32 @@ Concept Index
(line 55)
* port numbers: Other files. (line 17)
* PriorityInheritance: Main configuration variables.
(line 284)
(line 283)
* private: Virtual Private Networks.
(line 10)
* PrivateKey: Main configuration variables.
(line 289)
(line 288)
* PrivateKeyFile: Main configuration variables.
(line 295)
(line 294)
* ProcessPriority: Main configuration variables.
(line 303)
(line 299)
* Proxy: Main configuration variables.
(line 308)
(line 304)
* PublicKey: Host configuration variables.
(line 59)
* PublicKeyFile: Host configuration variables.
(line 62)
* raw_socket: Main configuration variables.
(line 93)
(line 100)
* release: Supported platforms. (line 14)
* REMOTEADDRESS: Scripts. (line 67)
* REMOTEPORT: Scripts. (line 70)
* ReplayWindow: Main configuration variables.
(line 331)
(line 327)
* REQ_KEY: The meta-protocol. (line 64)
* requirements: Libraries. (line 6)
* router: Main configuration variables.
(line 227)
(line 226)
* runtime options: Runtime options. (line 9)
* scalability: tinc. (line 19)
* scripts: Scripts. (line 6)
@ -2954,17 +2987,17 @@ Concept Index
(line 18)
* signals: Signals. (line 6)
* socks4: Main configuration variables.
(line 312)
(line 308)
* socks5: Main configuration variables.
(line 317)
(line 313)
* StrictSubnets: Main configuration variables.
(line 342)
(line 338)
* SUBNET: Scripts. (line 74)
* Subnet: Host configuration variables.
(line 74)
* SVPN: Security. (line 11)
* switch: Main configuration variables.
(line 236)
(line 235)
* TCP: The meta-connection. (line 10)
* TCPonly: Host configuration variables.
(line 103)
@ -2976,24 +3009,24 @@ Concept Index
* tincd: tinc. (line 14)
* traditional VPNs: tinc. (line 19)
* tunifhead: Main configuration variables.
(line 135)
(line 142)
* TunnelServer: Main configuration variables.
(line 347)
(line 343)
* tunnohead: Main configuration variables.
(line 129)
(line 136)
* UDP <1>: Encryption of network packets.
(line 12)
* UDP: The UDP tunnel. (line 30)
* UDPRcvBuf: Main configuration variables.
(line 354)
(line 350)
* UDPSndBuf: Main configuration variables.
(line 359)
(line 355)
* UML: Main configuration variables.
(line 111)
(line 118)
* Universal tun/tap: Configuration of Linux kernels.
(line 6)
* VDE: Main configuration variables.
(line 116)
(line 123)
* virtual: Virtual Private Networks.
(line 18)
* 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 Windows10241
Node: Libraries10755
Node: OpenSSL11156
Node: zlib13432
Node: lzo14261
Node: libevent15065
Node: Installation15760
Node: Building and installing tinc16776
Node: Darwin (MacOS/X) build environment17435
Node: Cygwin (Windows) build environment18002
Node: MinGW (Windows) build environment18590
Node: System files19114
Node: Device files19379
Node: Other files19795
Node: Configuration20408
Node: Configuration introduction20695
Node: Multiple networks22242
Node: How connections work23622
Node: Configuration files26195
Node: Main configuration variables27728
Node: Host configuration variables44334
Node: Scripts49564
Node: How to configure52243
Node: Network interfaces56861
Node: Example configuration59262
Node: Running tinc64414
Node: Runtime options65007
Node: Signals67711
Node: Debug levels68561
Node: Solving problems69497
Node: Error messages70927
Node: Sending bug reports75249
Node: Controlling tinc76201
Node: tincctl runtime options76598
Node: tincctl environment variables77297
Node: tincctl commands77641
Node: tincctl examples81866
Node: tincctl top82471
Node: Technical information84069
Node: The connection84304
Node: The UDP tunnel84616
Node: The meta-connection87677
Node: The meta-protocol89146
Node: Security94155
Node: Authentication protocol95285
Node: Encryption of network packets100289
Node: Security issues101662
Node: Platform specific information103279
Node: Interface configuration103507
Node: Routes105960
Node: About us107876
Node: Contact information108051
Node: Authors108455
Node: Concept Index108860
Node: OpenSSL11173
Node: zlib13461
Node: lzo14487
Node: libcurses15485
Node: libreadline16405
Node: Installation17353
Node: Building and installing tinc18369
Node: Darwin (MacOS/X) build environment19028
Node: Cygwin (Windows) build environment19595
Node: MinGW (Windows) build environment20183
Node: System files20707
Node: Device files20972
Node: Other files21388
Node: Configuration22001
Node: Configuration introduction22288
Node: Multiple networks23835
Node: How connections work25215
Node: Configuration files27788
Node: Main configuration variables29321
Node: Host configuration variables45731
Node: Scripts50961
Node: How to configure53640
Node: Network interfaces58258
Node: Example configuration60659
Node: Running tinc65811
Node: Runtime options66404
Node: Signals69108
Node: Debug levels69958
Node: Solving problems70894
Node: Error messages72324
Node: Sending bug reports76646
Node: Controlling tinc77598
Node: tincctl runtime options77995
Node: tincctl environment variables78694
Node: tincctl commands79038
Node: tincctl examples83343
Node: tincctl top83948
Node: Technical information85546
Node: The connection85781
Node: The UDP tunnel86093
Node: The meta-connection89154
Node: The meta-protocol90623
Node: Security95632
Node: Authentication protocol96762
Node: Encryption of network packets101766
Node: Security issues103139
Node: Platform specific information104756
Node: Interface configuration104984
Node: Routes107437
Node: About us109353
Node: Contact information109528
Node: Authors109932
Node: Concept Index110337

End Tag Table

View file

@ -339,7 +339,8 @@ having them installed, configure will give you an error message, and stop.
* OpenSSL::
* zlib::
* lzo::
* libevent::
* libcurses::
* libreadline::
@end menu
@ -352,7 +353,7 @@ For all cryptography-related functions, tinc uses the functions provided
by the OpenSSL library.
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.
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
by the zlib library.
If this library is not installed, you wil get an error when configuring
tinc for build. Support for running tinc without having zlib
installed @emph{may} be added in the future.
If this library is not installed, you wil get an error when running the
configure script. You can either install the zlib library, or 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 if
available. Make sure you install the development AND runtime versions
@ -435,11 +438,13 @@ default).
@subsection 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
tinc for build. Support for running tinc without having lzo
installed @emph{may} be added in the future.
If this library is not installed, you wil get an error when running the
configure script. You can either install the LZO library, or 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 if
available. Make sure you install the development AND runtime versions
@ -453,24 +458,48 @@ default).
@c ==================================================================
@node libevent
@subsection libevent
@node libcurses
@subsection libcurses
@cindex libevent
For the main event loop, tinc uses the libevent library.
@cindex libcurses
For the "tincctl top" command, tinc requires a curses library.
If this library is not installed, you wil get an error when configuring
tinc for build.
If this library is not installed, you wil get an error when running 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" (@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.
If you have to install libevent manually, you can get the source code
from @url{http://libevent.org/}. Instructions on how to configure,
build and install this package are included within the package. Please
make sure you build development and runtime libraries (which is the
default).
@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
available. Make sure you install the development AND runtime versions
of this package.
If you have to install libreadline manually, you can get the source code from
@url{http://www.gnu.org/software/readline/}. Instructions on how to configure,
build and install this package are included within the package. Please make
sure you build development and runtime libraries (which is the default).
@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
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
@item BindToAddress = <@var{address}> [<@var{port}>]
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.
@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
@item Hostnames = <yes|no> (no)
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
relative directory.
Note that there must be exactly one of PrivateKey
or PrivateKeyFile
specified in the configuration file.
@cindex ProcessPriority
@item ProcessPriority = <low|normal|high>
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
option).
@item dump nodes
@item dump [reachable] nodes
Dump a list of all known nodes in the VPN.
If the reachable keyword is used, only lists reachable nodes.
@item dump edges
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.
.El
.Sh COMMANDS
.zZ
.Bl -tag -width indent
.It init Op Ar name
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.
When saving keys to existing files, tinc will not delete the old keys;
you have to remove them manually.
.It dump nodes
.It dump [reachable] nodes
Dump a list of all known nodes in the VPN.
If the keyword reachable is used, only lists reachable nodes.
.It dump edges
Dump a list of all known connections in the VPN.
.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 ConnectTo bar
tincctl -n vpn export | gpg --clearsign | mail -s "My config" vpnmaster@example.com
.Ed
.Sh TOP
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,

View file

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

4
have.h
View file

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

View file

@ -54,10 +54,9 @@ subdir = m4
DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/libevent.m4 \
$(top_srcdir)/m4/lzo.m4 $(top_srcdir)/m4/openssl.m4 \
$(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/zlib.m4 \
$(top_srcdir)/configure.in
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \
$(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
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 \
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 \
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
if UML
@ -46,7 +46,7 @@ INCLUDES = @INCLUDES@ -I$(top_builddir)
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 \
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 = \
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
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/libevent.m4 \
$(top_srcdir)/m4/lzo.m4 $(top_srcdir)/m4/openssl.m4 \
$(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/zlib.m4 \
$(top_srcdir)/configure.in
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \
$(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
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 \
protocol_edge.c protocol_misc.c protocol_key.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 \
uml_device.c vde_device.c bsd/tunemu.c
event.c tincd.c dummy_device.c raw_socket_device.c \
multicast_device.c uml_device.c vde_device.c bsd/tunemu.c
@UML_TRUE@am__objects_1 = uml_device.$(OBJEXT)
@VDE_TRUE@am__objects_2 = vde_device.$(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_key.$(OBJEXT) protocol_subnet.$(OBJEXT) \
route.$(OBJEXT) sptps.$(OBJEXT) subnet.$(OBJEXT) \
subnet_parse.$(OBJEXT) tincd.$(OBJEXT) dummy_device.$(OBJEXT) \
raw_socket_device.$(OBJEXT) multicast_device.$(OBJEXT) \
$(am__objects_1) $(am__objects_2) $(am__objects_3)
subnet_parse.$(OBJEXT) event.$(OBJEXT) tincd.$(OBJEXT) \
dummy_device.$(OBJEXT) raw_socket_device.$(OBJEXT) \
multicast_device.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
$(am__objects_3)
nodist_tincd_OBJECTS = device.$(OBJEXT) cipher.$(OBJEXT) \
crypto.$(OBJEXT) ecdh.$(OBJEXT) ecdsa.$(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 \
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 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) \
$(am__append_2) $(am__append_3)
nodist_tincd_SOURCES = \
@ -273,7 +273,7 @@ DEFAULT_INCLUDES =
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 \
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 = \
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)/ecdsagen.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-getnameinfo.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->outbuf);
if(event_initialized(&c->inevent))
event_del(&c->inevent);
if(event_initialized(&c->outevent))
event_del(&c->outevent);
io_del(&c->io);
if(c->socket > 0)
closesocket(c->socket);

View file

@ -90,8 +90,7 @@ typedef struct connection_t {
struct buffer_t inbuf;
struct buffer_t outbuf;
struct event inevent; /* input event on this metadata connection */
struct event outevent; /* output event on this metadata connection */
io_t io; /* input/output event on this metadata connection */
int tcplen; /* length of incoming TCPpacket */
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) {
case REQ_STOP:
event_loopexit(NULL);
event_exit();
return control_ok(c, REQ_STOP);
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.
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);
} else {
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);
#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__ */

View file

@ -41,6 +41,10 @@
#define ETH_P_IPV6 0x86DD
#endif
#ifndef ETH_P_8021Q
#define ETH_P_8021Q 0x8100
#endif
#ifndef HAVE_STRUCT_ETHER_HEADER
struct ether_header {
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->mtuprobes = 0;
if(timeout_initialized(&n->mtuevent))
event_del(&n->mtuevent);
timeout_del(&n->mtutimeout);
char *name;
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->n = n;
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);
return hash;
}
@ -100,6 +100,8 @@ void hash_clear(hash_t *hash) {
void hash_resize(hash_t *hash, size_t n) {
hash->keys = xrealloc(hash->keys, n * hash->size);
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);
}
}

View file

@ -41,7 +41,6 @@ bool logcontrol = false;
static void real_logger(int level, int priority, const char *message) {
char timestr[32] = "";
time_t now;
static bool suppress = false;
// 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);
break;
case LOGMODE_FILE:
now = time(NULL);
strftime(timestr, sizeof timestr, "%Y-%m-%d %H:%M:%S", localtime(&now));
if(!now.tv_sec)
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);
fflush(logfile);
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);
event_add(&c->outevent, NULL);
io_set(&c->io, IO_READ | IO_WRITE);
return true;
}
@ -65,12 +65,11 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
c->name, c->hostname);
return false;
}
} else {
buffer_add(&c->outbuf, buffer, length);
}
event_add(&c->outevent, NULL);
io_set(&c->io, IO_READ | IO_WRITE);
return true;
}

175
src/net.c
View file

@ -74,7 +74,7 @@ void purge(void) {
if(e->to == n)
return;
if(!strictsubnets || !n->subnet_tree->head)
if(!autoconnect && (!strictsubnets || !n->subnet_tree->head))
/* in strictsubnets mode do not delete nodes with subnets */
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
and close the connection.
*/
static void timeout_handler(int fd, short events, void *event) {
time_t now = time(NULL);
static void timeout_handler(void *data) {
for list_each(connection_t, c, connection_list) {
if(c->status.control)
continue;
if(c->last_ping_time + pingtimeout <= now) {
if(c->last_ping_time + pingtimeout <= now.tv_sec) {
if(c->status.active) {
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);
} else if(c->last_ping_time + pinginterval <= now) {
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.tv_sec) {
send_ping(c);
continue;
} 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) {
logger(DEBUG_ALWAYS, LOG_WARNING, "Possible node with same Name as us! Sleeping %d seconds.", sleeptime);
usleep(sleeptime * 1000000LL);
@ -179,11 +186,100 @@ static void timeout_handler(int fd, short events, void *event) {
contradicting_add_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) {
connection_t *c = data;
void handle_meta_connection_data(connection_t *c) {
int 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) {
logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(signal));
event_loopexit(NULL);
static void sigterm_handler(void *data) {
logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum));
event_exit();
}
static void sighup_handler(int signal, short events, void *data) {
logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(signal));
static void sighup_handler(void *data) {
logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum));
reopenlogger();
reload_configuration();
}
static void sigalrm_handler(int signal, short events, void *data) {
logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(signal));
static void sigalrm_handler(void *data) {
logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum));
retry();
}
@ -233,7 +329,7 @@ int reload_configuration(void) {
if(!read_server_config()) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to reread configuration file, exitting.");
event_loopexit(NULL);
event_exit();
return EINVAL;
}
@ -332,8 +428,7 @@ int reload_configuration(void) {
void retry(void) {
for list_each(connection_t, c, connection_list) {
if(c->outgoing && !c->node) {
if(timeout_initialized(&c->outgoing->ev))
event_del(&c->outgoing->ev);
timeout_del(&c->outgoing->ev);
if(c->status.connecting)
close(c->socket);
c->outgoing->timeout = 0;
@ -346,40 +441,38 @@ void retry(void) {
this is where it all happens...
*/
int main_loop(void) {
struct event timeout_event;
timeout_t pingtimer = {{0}};
timeout_t periodictimer = {{0}};
timeout_set(&timeout_event, timeout_handler, &timeout_event);
event_add(&timeout_event, &(struct timeval){pingtimeout, 0});
timeout_add(&pingtimer, timeout_handler, &pingtimer, &(struct timeval){pingtimeout, rand() % 100000});
timeout_add(&periodictimer, periodic_handler, &periodictimer, &(struct timeval){pingtimeout, rand() % 100000});
#ifndef HAVE_MINGW
struct event sighup_event;
struct event sigterm_event;
struct event sigquit_event;
struct event sigalrm_event;
signal_t sighup = {0};
signal_t sigterm = {0};
signal_t sigquit = {0};
signal_t sigalrm = {0};
signal_set(&sighup_event, SIGHUP, sighup_handler, NULL);
signal_add(&sighup_event, NULL);
signal_set(&sigterm_event, SIGTERM, sigterm_handler, NULL);
signal_add(&sigterm_event, NULL);
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);
signal_add(&sighup, sighup_handler, &sighup, SIGHUP);
signal_add(&sigterm, sigterm_handler, &sigterm, SIGTERM);
signal_add(&sigquit, sigterm_handler, &sigquit, SIGQUIT);
signal_add(&sigalrm, sigalrm_handler, &sigalrm, SIGALRM);
#endif
if(event_loop(0) < 0) {
if(!event_loop()) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while waiting for input: %s", strerror(errno));
return 1;
}
#ifndef HAVE_MINGW
signal_del(&sighup_event);
signal_del(&sigterm_event);
signal_del(&sigquit_event);
signal_del(&sigalrm_event);
signal_del(&sighup);
signal_del(&sigalrm);
signal_del(&sigquit);
signal_del(&sigterm);
#endif
event_del(&timeout_event);
timeout_del(&periodictimer);
timeout_del(&pingtimer);
return 0;
}

View file

@ -24,6 +24,7 @@
#include "ipv6.h"
#include "cipher.h"
#include "digest.h"
#include "event.h"
#ifdef ENABLE_JUMBOGRAMS
#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;
typedef struct listen_socket_t {
struct event ev_tcp;
struct event ev_udp;
int tcp;
int udp;
io_t tcp;
io_t udp;
sockaddr_t sa;
} listen_socket_t;
@ -116,7 +115,7 @@ typedef struct outgoing_t {
struct config_t *cfg;
struct addrinfo *ai;
struct addrinfo *aip;
struct event ev;
timeout_t ev;
} outgoing_t;
extern list_t *outgoing_list;
@ -134,6 +133,7 @@ extern int udp_rcvbuf;
extern int udp_sndbuf;
extern bool do_prune;
extern char *myport;
extern int autoconnect;
extern int contradicting_add_edge;
extern int contradicting_del_edge;
extern time_t last_config_check;
@ -160,10 +160,10 @@ extern char *scriptextension;
#include "node.h"
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 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_vpn_in_socket(const sockaddr_t *);
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_rsa_public_key(struct connection_t *);
extern void send_mtu_probe(struct node_t *);
extern void handle_device_data(int, short, void *);
extern void handle_meta_connection_data(int, short, void *);
extern void handle_device_data(void *, int);
extern void handle_meta_connection_data(struct connection_t *);
extern void regenerate_key(void);
extern void purge(void);
extern void retry(void);
extern int reload_configuration(void);
extern void load_all_subnets(void);
extern void load_all_nodes(void);
#ifndef HAVE_MINGW
#define closesocket(s) close(s)

View file

@ -77,7 +77,7 @@ bool localdiscovery = false;
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;
int timeout = 1;
@ -151,23 +151,37 @@ static void send_mtu_probe_handler(int fd, short events, void *data) {
}
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) {
if(!timeout_initialized(&n->mtuevent))
timeout_set(&n->mtuevent, send_mtu_probe_handler, n);
send_mtu_probe_handler(0, 0, n);
timeout_add(&n->mtutimeout, send_mtu_probe_handler, n, &(struct timeval){1, 0});
send_mtu_probe_handler(n);
}
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);
if(!packet->data[0]) {
/* It's a probe request, send back a reply */
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;
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->minmtu)
@ -176,6 +190,8 @@ static void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) {
n->mtuprobes = 1;
}
/* If applicable, raise the minimum supported MTU */
if(len > n->maxmtu)
len = n->maxmtu;
if(n->minmtu < len)
@ -438,6 +454,84 @@ static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) {
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) {
vpn_packet_t 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 */
if(!n->status.validkey) {
time_t now = time(NULL);
logger(DEBUG_TRAFFIC, LOG_INFO,
"No valid key known yet for %s (%s), forwarding via TCP",
n->name, n->hostname);
if(n->last_req_key + 10 <= now) {
if(n->last_req_key + 10 <= now.tv_sec) {
send_req_key(n);
n->last_req_key = now;
n->last_req_key = now.tv_sec;
}
send_tcppacket(n->nexthop->connection, origpkt);
@ -534,88 +626,27 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
/* Send the packet */
sockaddr_t *sa;
const sockaddr_t *sa;
int sock;
/* Overloaded use of priority field: -1 means local broadcast */
if(origpriority == -1 && n->prevedge) {
sockaddr_t broadcast;
broadcast.in.sin_family = AF_INET;
broadcast.in.sin_addr.s_addr = -1;
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(origpriority == -1 && n->prevedge)
choose_broadcast_address(n, &sa, &sock);
else
choose_udp_address(n, &sa, &sock);
#if defined(SOL_IP) && defined(IP_TOS)
if(priorityinheritance && origpriority != priority
&& listen_socket[n->sock].sa.sa.sa_family == AF_INET) {
priority = origpriority;
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));
}
#endif
socklen_t sl = SALEN(n->address.sa);
if(sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, &sa->sa, sl) < 0 && !sockwouldblock(sockerrno)) {
if(sendto(listen_socket[sock].udp.fd, (char *) &inpkt->seqno, inpkt->len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) {
if(sockmsgsize(sockerrno)) {
if(n->maxmtu >= origlen)
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 */
struct sockaddr *sa;
socklen_t sl;
const sockaddr_t *sa;
int sock;
sa = &(to->address.sa);
sl = SALEN(to->address.sa);
sock = to->sock;
choose_udp_address(to, &sa, &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(to->maxmtu >= len)
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;
if(type & PKT_COMPRESSED) {
len = uncompress_packet(inpkt.data + offset, (const uint8_t *)data, len, from->incompression);
if(len < 0) {
length_t ulen = uncompress_packet(inpkt.data + offset, (const uint8_t *)data, len, from->incompression);
if(ulen < 0) {
return false;
} else {
inpkt.len = len + offset;
inpkt.len = ulen + offset;
}
if(inpkt.len > MAXSIZE)
abort();
@ -838,14 +866,13 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) {
node_t *n = NULL;
bool hard = false;
static time_t last_hard_try = 0;
time_t now = time(NULL);
for splay_each(edge_t, e, edge_weight_tree) {
if(!e->to->status.reachable || e->to == myself)
continue;
if(sockaddrcmp_noport(from, &e->address)) {
if(last_hard_try == now)
if(last_hard_try == now.tv_sec)
continue;
hard = true;
}
@ -858,13 +885,14 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) {
}
if(hard)
last_hard_try = now;
last_hard_try = now.tv_sec;
last_hard_try = now;
last_hard_try = now.tv_sec;
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;
char *hostname;
sockaddr_t from = {{0}};
@ -872,7 +900,7 @@ void handle_incoming_vpn_data(int sock, short events, void *data) {
node_t *n;
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(!sockwouldblock(sockerrno))
@ -900,12 +928,12 @@ void handle_incoming_vpn_data(int sock, short events, void *data) {
return;
}
n->sock = (intptr_t)data;
n->sock = ls - listen_socket;
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;
packet.priority = 0;

View file

@ -42,7 +42,7 @@
#include "xalloc.h"
char *myport;
static struct event device_ev;
static io_t device_io;
devops_t devops;
char *proxyhost;
@ -50,6 +50,7 @@ char *proxyport;
char *proxyuser;
char *proxypass;
proxytype_t proxytype;
int autoconnect;
char *scriptinterpreter;
char *scriptextension;
@ -269,22 +270,16 @@ static bool read_rsa_private_key(void) {
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();
timeout_set(data, &(struct timeval){keylifetime, rand() % 100000});
}
void regenerate_key(void) {
if(timeout_initialized(&keyexpire_event)) {
logger(DEBUG_STATUS, LOG_INFO, "Expiring symmetric keys");
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);
}
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 *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);
return false;
}
envname = alloca(32);
char envname[32];
if(gethostname(envname, 32)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not get hostname: %s\n", strerror(errno));
return false;
@ -570,6 +595,8 @@ bool setup_myself_reloadable(void) {
if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime))
keylifetime = 3600;
get_config_int(lookup_config(config_tree, "AutoConnect"), &autoconnect);
return true;
}
@ -683,7 +710,8 @@ static bool setup_myself(void) {
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... */
@ -730,6 +758,8 @@ static bool setup_myself(void) {
if(strictsubnets)
load_all_subnets();
else if(autoconnect)
load_all_nodes();
/* Open device */
@ -755,15 +785,8 @@ static bool setup_myself(void) {
if(!devops.setup())
return false;
if(device_fd >= 0) {
event_set(&device_ev, device_fd, EV_READ|EV_PERSIST, handle_device_data, NULL);
if (event_add(&device_ev, NULL) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "event_add failed: %s", strerror(errno));
devops.close();
return false;
}
}
if(device_fd >= 0)
io_add(&device_io, handle_device_data, NULL, device_fd, IO_READ);
/* Run tinc-up script to further initialize the tap interface */
char *envp[5];
@ -805,27 +828,16 @@ static bool setup_myself(void) {
return false;
}
listen_socket[i].tcp = i + 3;
#ifdef FD_CLOEXEC
fcntl(i + 3, F_SETFD, FD_CLOEXEC);
#endif
listen_socket[i].udp = setup_vpn_in_socket(&sa);
if(listen_socket[i].udp < 0)
int udp_fd = setup_vpn_in_socket(&sa);
if(udp_fd < 0)
return false;
event_set(&listen_socket[i].ev_tcp, listen_socket[i].tcp, EV_READ|EV_PERSIST, handle_new_meta_connection, NULL);
if(event_add(&listen_socket[i].ev_tcp, NULL) < 0) {
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();
}
io_add(&listen_socket[i].tcp, (io_cb_t)handle_new_meta_connection, &listen_socket[i], i + 3, IO_READ);
io_add(&listen_socket[i].udp, (io_cb_t)handle_incoming_vpn_data, &listen_socket[i], udp_fd, IO_READ);
if(debug_level >= DEBUG_CONNECTIONS) {
hostname = sockaddr2hostname(&sa);
@ -878,37 +890,20 @@ static bool setup_myself(void) {
return false;
}
listen_socket[listen_sockets].tcp =
setup_listen_socket((sockaddr_t *) aip->ai_addr);
int tcp_fd = setup_listen_socket((sockaddr_t *) aip->ai_addr);
if(listen_socket[listen_sockets].tcp < 0)
if(tcp_fd < 0)
continue;
listen_socket[listen_sockets].udp =
setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);
int udp_fd = setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);
if(listen_socket[listen_sockets].udp < 0) {
close(listen_socket[listen_sockets].tcp);
if(tcp_fd < 0) {
close(tcp_fd);
continue;
}
event_set(&listen_socket[listen_sockets].ev_tcp,
listen_socket[listen_sockets].tcp,
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();
}
io_add(&listen_socket[listen_sockets].tcp, handle_new_meta_connection, &listen_socket[listen_sockets], tcp_fd, IO_READ);
io_add(&listen_socket[listen_sockets].udp, handle_incoming_vpn_data, &listen_socket[listen_sockets], udp_fd, IO_READ);
if(debug_level >= DEBUG_CONNECTIONS) {
hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr);
@ -990,10 +985,10 @@ void close_network_connections(void) {
}
for(int i = 0; i < listen_sockets; i++) {
event_del(&listen_socket[i].ev_tcp);
event_del(&listen_socket[i].ev_udp);
close(listen_socket[i].tcp);
close(listen_socket[i].udp);
io_del(&listen_socket[i].tcp);
io_del(&listen_socket[i].udp);
close(listen_socket[i].tcp.fd);
close(listen_socket[i].udp.fd);
}
char *envp[5];

View file

@ -271,7 +271,7 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
return nfd;
} /* 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);
}
@ -281,12 +281,9 @@ void retry_outgoing(outgoing_t *outgoing) {
if(outgoing->timeout > maxtimeout)
outgoing->timeout = maxtimeout;
timeout_set(&outgoing->ev, retry_outgoing_handler, outgoing);
event_add(&outgoing->ev, &(struct timeval){outgoing->timeout, 0});
timeout_add(&outgoing->ev, retry_outgoing_handler, outgoing, &(struct timeval){outgoing->timeout, rand() % 100000});
logger(DEBUG_CONNECTIONS, LOG_NOTICE,
"Trying to re-establish outgoing connection in %d seconds",
outgoing->timeout);
logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Trying to re-establish outgoing connection in %d seconds", outgoing->timeout);
}
void finish_connecting(connection_t *c) {
@ -349,9 +346,7 @@ static void do_outgoing_pipe(connection_t *c, char *command) {
#endif
}
static void handle_meta_write(int sock, short events, void *data) {
connection_t *c = data;
static void handle_meta_write(connection_t *c) {
ssize_t outlen = send(c->socket, c->outbuf.data + c->outbuf.offset, c->outbuf.len - c->outbuf.offset, 0);
if(outlen <= 0) {
if(!errno || errno == EPIPE) {
@ -368,10 +363,16 @@ static void handle_meta_write(int sock, short events, void *data) {
}
buffer_read(&c->outbuf, outlen);
if(!c->outbuf.len && event_initialized(&c->outevent))
event_del(&c->outevent);
if(!c->outbuf.len)
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) {
char *address, *port, *space;
@ -487,16 +488,13 @@ begin:
connection_add(c);
event_set(&c->inevent, c->socket, EV_READ | EV_PERSIST, handle_meta_connection_data, c);
event_set(&c->outevent, c->socket, EV_WRITE | EV_PERSIST, handle_meta_write, c);
event_add(&c->inevent, NULL);
io_add(&c->io, handle_meta_io, c, c->socket, IO_READ);
return true;
}
void setup_outgoing_connection(outgoing_t *outgoing) {
if(event_initialized(&outgoing->ev))
event_del(&outgoing->ev);
timeout_del(&outgoing->ev);
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
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;
sockaddr_t sa;
int fd;
socklen_t len = sizeof sa;
fd = accept(sock, &sa.sa, &len);
fd = accept(l->tcp.fd, &sa.sa, &len);
if(fd < 0) {
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);
event_set(&c->inevent, c->socket, EV_READ | EV_PERSIST, handle_meta_connection_data, c);
event_set(&c->outevent, c->socket, EV_WRITE | EV_PERSIST, handle_meta_write, c);
event_add(&c->inevent, NULL);
io_add(&c->io, handle_meta_io, c, c->socket, IO_READ);
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) {
if(event_initialized(&outgoing->ev))
event_del(&outgoing->ev);
timeout_del(&outgoing->ev);
if(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) {
struct addrinfo *ai, hint = {0};
sockaddr_t result;
sockaddr_t result = {{0}};
int err;
hint.ai_family = AF_UNSPEC;

View file

@ -78,8 +78,7 @@ void free_node(node_t *n) {
ecdsa_free(&n->ecdsa);
sptps_stop(&n->sptps);
if(timeout_initialized(&n->mtuevent))
event_del(&n->mtuevent);
timeout_del(&n->mtutimeout);
if(n->hostname)
free(n->hostname);
@ -129,6 +128,13 @@ void update_node_udp(node_t *n, const sockaddr_t *sa) {
if(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);
free(n->hostname);
n->hostname = sockaddr2hostname(&n->address);

View file

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

View file

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

View file

@ -165,7 +165,24 @@ static void free_past_request(past_request_t *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) {
past_request_t *new, p = {NULL};
@ -180,39 +197,17 @@ bool seen_request(const char *request) {
new->request = xstrdup(request);
new->firstseen = time(NULL);
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;
}
}
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) {
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) {
splay_delete_tree(past_request_tree);
if(timeout_initialized(&past_request_event))
event_del(&past_request_event);
timeout_del(&past_request_timeout);
}

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))
#endif
static struct event age_subnets_event;
static timeout_t age_subnets_timeout;
/* RFC 1071 */
@ -84,13 +84,12 @@ static uint16_t inet_checksum(void *data, int len, uint16_t prevsum) {
static bool ratelimit(int frequency) {
static time_t lasttime = 0;
static int count = 0;
time_t now = time(NULL);
if(lasttime == now) {
if(lasttime == now.tv_sec) {
if(count >= frequency)
return true;
} else {
lasttime = now;
lasttime = now.tv_sec;
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;
/* Find TCP header */
int start = 0;
int start = ether_size;
uint16_t type = packet->data[12] << 8 | packet->data[13];
if(type == ETH_P_IP && packet->data[23] == 6)
start = 14 + (packet->data[14] & 0xf) * 4;
else if(type == ETH_P_IPV6 && packet->data[20] == 6)
start = 14 + 40;
if(type == ETH_P_8021Q) {
start += 4;
type = packet->data[16] << 8 | packet->data[17];
}
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;
/* 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);
}
static void age_subnets(int fd, short events, void *data) {
static void age_subnets(void *data) {
bool left = false;
time_t now = time(NULL);
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) {
char netstr[MAXNETSTR];
if(net2str(netstr, sizeof netstr, s))
@ -209,7 +214,7 @@ static void age_subnets(int fd, short events, void *data) {
}
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) {
@ -236,9 +241,7 @@ static void learn_mac(mac_t *address) {
if(c->status.active)
send_add_subnet(c, subnet);
if(!timeout_initialized(&age_subnets_event))
timeout_set(&age_subnets_event, age_subnets, NULL);
event_add(&age_subnets_event, &(struct timeval){10, 0});
timeout_add(&age_subnets_timeout, age_subnets, NULL, &(struct timeval){10, rand() % 100000});
} else {
if(subnet->expires)
subnet->expires = time(NULL) + macexpire;
@ -247,7 +250,7 @@ static void learn_mac(mac_t *address) {
/* 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 icmp icmp = {0};
@ -320,7 +323,7 @@ static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, uint8_t
/* 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;
vpn_packet_t fragment;
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[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;
}
@ -394,10 +397,10 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) {
}
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)
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)
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)
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) {
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) {
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 {
fragment_ipv4_packet(via, packet);
fragment_ipv4_packet(via, packet, ether_size);
}
return;
@ -445,7 +448,7 @@ static void route_ipv4(node_t *source, vpn_packet_t *packet) {
/* 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 icmp6_hdr icmp6 = {0};
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[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;
}
@ -553,10 +556,10 @@ static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) {
}
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)
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;
@ -566,12 +569,12 @@ static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) {
}
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) {
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);
route_ipv6_unreachable(source, packet, ICMP6_PACKET_TOO_BIG, 0);
route_ipv6_unreachable(source, packet, ether_size, ICMP6_PACKET_TOO_BIG, 0);
return;
}
@ -842,17 +845,24 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
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);
uint16_t type = packet->data[12] << 8 | packet->data[13];
if(type == ETH_P_IP && packet->len > 590) {
if(packet->data[20] & 0x40) {
length_t ethlen = 14;
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;
route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED);
route_ipv4_unreachable(source, packet, ethlen, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED);
} else {
fragment_ipv4_packet(via, packet);
fragment_ipv4_packet(via, packet, ethlen);
}
return;
} else if(type == ETH_P_IPV6 && packet->len > 1294) {
} else if(type == ETH_P_IPV6 && packet->len > 1280 + ethlen) {
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;
}
}
@ -881,42 +891,48 @@ static void send_pcap(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];
length_t ethlen = ether_size;
if(type == ETH_P_8021Q) {
type = packet->data[16] << 8 | packet->data[17];
ethlen += 4;
}
switch (type) {
case ETH_P_IP:
if(!checklength(source, packet, 14 + 32))
if(!checklength(source, packet, ethlen + ip_size))
return false;
if(packet->data[22] < 1) {
if(packet->data[25] != IPPROTO_ICMP || packet->data[46] != ICMP_TIME_EXCEEDED)
route_ipv4_unreachable(source, packet, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL);
if(packet->data[ethlen + 8] < 1) {
if(packet->data[ethlen + 11] != IPPROTO_ICMP || packet->data[ethlen + 32] != ICMP_TIME_EXCEEDED)
route_ipv4_unreachable(source, packet, ethlen, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL);
return false;
}
uint16_t old = packet->data[22] << 8 | packet->data[23];
packet->data[22]--;
uint16_t new = packet->data[22] << 8 | packet->data[23];
uint16_t old = packet->data[ethlen + 8] << 8 | packet->data[ethlen + 9];
packet->data[ethlen + 8]--;
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);
while(checksum >> 16)
checksum = (checksum & 0xFFFF) + (checksum >> 16);
packet->data[24] = checksum >> 8;
packet->data[25] = checksum & 0xff;
packet->data[ethlen + 10] = checksum >> 8;
packet->data[ethlen + 11] = checksum & 0xff;
return true;
case ETH_P_IPV6:
if(!checklength(source, packet, 14 + 40))
if(!checklength(source, packet, ethlen + ip6_size))
return false;
if(packet->data[21] < 1) {
if(packet->data[20] != IPPROTO_ICMPV6 || packet->data[54] != ICMP6_TIME_EXCEEDED)
route_ipv6_unreachable(source, packet, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT);
if(packet->data[ethlen + 7] < 1) {
if(packet->data[ethlen + 6] != IPPROTO_ICMPV6 || packet->data[ethlen + 40] != ICMP6_TIME_EXCEEDED)
route_ipv6_unreachable(source, packet, ethlen, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT);
return false;
}
packet->data[21]--;
packet->data[ethlen + 7]--;
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;
int result;
node->left = node->right = node->parent = node->next = node->prev = NULL;
if(!tree->root)
splay_insert_top(tree, node);
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) {
node->prev = node->next = node->left = node->right = node->parent = NULL;
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) {
@ -446,6 +449,7 @@ void splay_insert_before(splay_tree_t *tree, splay_node_t *before, splay_node_t
node->parent = NULL;
tree->root = node;
tree->count++;
}
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;
tree->root = node;
tree->count++;
}
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 {
tree->root = NULL;
}
tree->count--;
}
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_action_t delete;
int count;
} splay_tree_t;
/* (De)constructors */

View file

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

View file

@ -57,11 +57,12 @@ static char *name = NULL;
static char *identname = NULL; /* program name for syslog */
static char *pidfilename = NULL; /* pid file location */
static char *confdir = NULL;
static char controlcookie[1024];
static char controlcookie[1025];
char *netname = NULL;
char *confbase = NULL;
static char *tinc_conf = NULL;
static char *hosts_dir = NULL;
struct timeval now;
// Horrible global variables...
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-ecdsa-keys Generate a new ECDSA public/private keypair.\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"
" subnets - all known subnets in the VPN\n"
" connections - all meta connections with ourself\n"
@ -708,8 +709,8 @@ static bool connect_tincd(bool verbose) {
return false;
}
char host[128];
char port[128];
char host[129];
char port[129];
if(fscanf(f, "%20d %1024s %128s port %128s", &pid, controlcookie, host, port) != 4) {
if(verbose)
@ -911,6 +912,19 @@ static int cmd_reload(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) {
fprintf(stderr, "Invalid number of arguments.\n");
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);
return 1;
}
if(do_graph) {
memcpy(&status, &status_int, sizeof status);
if(do_graph) {
const char *color = "black";
if(!strcmp(host, "MYSELF"))
color = "green";
@ -1000,6 +1016,8 @@ static int cmd_dump(int argc, char *argv[]) {
color = "green";
printf(" %s [label = \"%s\", color = \"%s\"%s];\n", node, node, color, strcmp(host, "MYSELF") ? "" : ", style = \"filled\"");
} 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",
node, host, port, cipher, digest, maclength, compression, options, status_int, nexthop, via, distance, pmtu, minmtu, maxmtu);
}
@ -1233,6 +1251,7 @@ static struct {
} const variables[] = {
/* Server configuration */
{"AddressFamily", VAR_SERVER},
{"AutoConnect", VAR_SERVER},
{"BindToAddress", VAR_SERVER | VAR_MULTIPLE},
{"BindToInterface", 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) {
const char *matches[] = {"nodes", "edges", "subnets", "connections", "graph", NULL};
const char *matches[] = {"reachable", "nodes", "edges", "subnets", "connections", "graph", NULL};
static int i;
if(!state)

View file

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

View file

@ -57,11 +57,13 @@ static int sortmode = 0;
static bool cumulative = false;
static list_t node_list;
static struct timeval now, prev, diff;
static struct timeval cur, prev, diff;
static int delay = 1000;
static bool changed = true;
static const char *unit = "bytes";
static float scale = 1;
static const char *bunit = "bytes";
static float bscale = 1;
static const char *punit = "pkts";
static float pscale = 1;
#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)
@ -69,10 +71,10 @@ static float scale = 1;
static void update(int fd) {
sendline(fd, "%d %d", CONTROL, REQ_DUMP_TRAFFIC);
gettimeofday(&now, NULL);
gettimeofday(&cur, NULL);
timersub(&now, &prev, &diff);
prev = now;
timersub(&cur, &prev, &diff);
prev = cur;
float interval = diff.tv_sec + diff.tv_usec * 1e-6;
char line[4096];
@ -136,46 +138,25 @@ static void update(int fd) {
}
}
static void redraw(void) {
erase();
mvprintw(0, 0, "Tinc %-16s Nodes: %4d Sort: %-10s %s", netname ?: "", node_list.count, sortname[sortmode], cumulative ? "Cumulative" : "Current");
attrset(A_REVERSE);
mvprintw(2, 0, "Node IN pkts IN %s OUT pkts OUT %s", unit, unit);
chgat(-1, A_REVERSE, 0, NULL);
static nodestats_t **sorted = 0;
static int n = 0;
if(changed) {
n = 0;
sorted = xrealloc(sorted, node_list.count * sizeof *sorted);
for list_each(nodestats_t, ns, &node_list)
sorted[n++] = ns;
changed = false;
}
for(int i = 0; i < n; i++)
sorted[i]->i = i;
int cmpfloat(float a, float b) {
static 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) {
static 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) {
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) {
@ -212,8 +193,29 @@ static void redraw(void) {
default:
return strcmp(na->name, nb->name) ?: na->i - nb->i;
}
}
static void redraw(void) {
erase();
mvprintw(0, 0, "Tinc %-16s Nodes: %4d Sort: %-10s %s", netname ?: "", node_list.count, sortname[sortmode], cumulative ? "Cumulative" : "Current");
attrset(A_REVERSE);
mvprintw(2, 0, "Node IN %s IN %s OUT %s OUT %s", punit, bunit, punit, bunit);
chgat(-1, A_REVERSE, 0, NULL);
static nodestats_t **sorted = 0;
static int n = 0;
if(changed) {
n = 0;
sorted = xrealloc(sorted, node_list.count * sizeof *sorted);
for list_each(nodestats_t, ns, &node_list)
sorted[n++] = ns;
changed = false;
}
for(int i = 0; i < n; i++)
sorted[i]->i = i;
qsort(sorted, n, sizeof *sorted, sortfunc);
for(int i = 0, row = 3; i < n; i++, row++) {
@ -228,10 +230,10 @@ static void redraw(void) {
if(cumulative)
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
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);
@ -286,20 +288,28 @@ void top(int fd) {
sortmode = 5;
break;
case 'b':
unit = "bytes";
scale = 1;
bunit = "bytes";
bscale = 1;
punit = "pkts";
pscale = 1;
break;
case 'k':
unit = "kbyte";
scale = 1e-3;
bunit = "kbyte";
bscale = 1e-3;
punit = "pkts";
pscale = 1;
break;
case 'M':
unit = "Mbyte";
scale = 1e-6;
bunit = "Mbyte";
bscale = 1e-6;
punit = "kpkt";
pscale = 1e-3;
break;
case 'G':
unit = "Gbyte";
scale = 1e-9;
bunit = "Gbyte";
bscale = 1e-9;
punit = "Mpkt";
pscale = 1e-6;
break;
case 'q':
case KEY_BREAK: