Merge remote-tracking branch 'guus/1.1' into thkr-foor2Vup
This commit is contained in:
commit
4be26caf4e
64 changed files with 3013 additions and 2400 deletions
.gitignoreCOPYINGCOPYING.READMENEWSREADMEREADME.androidREADME.gitTHANKS
bash_completion.d
configure.acdoc
gui
m4
src
Makefile.am
bsd
conf.hcygwin
dropin.cdropin.hfake-gai-errnos.hfake-getaddrinfo.cfake-getaddrinfo.hfake-getnameinfo.cfake-getnameinfo.hfsck.cgcrypt
have.hifconfig.cifconfig.hinvitation.cipv6.hmingw
multicast_device.cnames.cnet.cnet.hnet_packet.cnet_setup.cnet_socket.cnode.cnode.hprocess.cprotocol_auth.cprotocol_edge.cprotocol_key.croute.cscript.csptps.csptps_test.csubnet.hsystem.htincctl.ctincctl.htincd.cutils.cutils.htest
47
.gitignore
vendored
47
.gitignore
vendored
|
@ -1,23 +1,40 @@
|
||||||
Makefile
|
|
||||||
Makefile.in
|
|
||||||
*.o
|
|
||||||
*.lo
|
|
||||||
*.la
|
|
||||||
*.a
|
*.a
|
||||||
/config.*
|
*.dirstamp
|
||||||
/src/tincd
|
*.o
|
||||||
/src/tinc
|
*.orig
|
||||||
.libs/
|
*.swp
|
||||||
/autom4te.cache
|
.deps
|
||||||
|
.libs
|
||||||
|
/ChangeLog
|
||||||
|
/INSTALL
|
||||||
/aclocal.m4
|
/aclocal.m4
|
||||||
|
/autom4te.cache
|
||||||
/compile
|
/compile
|
||||||
|
/config.*
|
||||||
/configure
|
/configure
|
||||||
/depcomp
|
/depcomp
|
||||||
|
/doc/sample-config.tar.gz
|
||||||
|
/doc/*.tex
|
||||||
|
/doc/*.info
|
||||||
|
/doc/*.5
|
||||||
|
/doc/*.8
|
||||||
|
/doc/*.html
|
||||||
|
/doc/*.pdf
|
||||||
|
/doc/*.t2p
|
||||||
|
/doc/tincinclude.texi
|
||||||
/install-sh
|
/install-sh
|
||||||
/missing
|
/missing
|
||||||
/m4/
|
|
||||||
INSTALL
|
|
||||||
.deps
|
|
||||||
.dir-locals.el
|
|
||||||
stamp-h1
|
|
||||||
/src/device.c
|
/src/device.c
|
||||||
|
/src/tincd
|
||||||
|
/src/tinc
|
||||||
|
/src/sptps_keypair
|
||||||
|
/src/sptps_speed
|
||||||
|
/src/sptps_test
|
||||||
|
/src/version_git.h
|
||||||
|
/stamp-h1
|
||||||
|
/test-driver
|
||||||
|
Makefile
|
||||||
|
Makefile.in
|
||||||
|
core*
|
||||||
|
*.tar.gz*
|
||||||
|
.Tpo
|
||||||
|
|
2
COPYING
2
COPYING
|
@ -1,4 +1,4 @@
|
||||||
Copyright (C) 1998-2014 Ivo Timmermans, Guus Sliepen and others.
|
Copyright (C) 1998-2016 Ivo Timmermans, Guus Sliepen and others.
|
||||||
See the AUTHORS file for a complete list.
|
See the AUTHORS file for a complete list.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
The following applies to tinc:
|
The following applies to tinc:
|
||||||
|
|
||||||
This program is released under the GPL with the additional exemption that
|
> This program is released under the GPL with the additional exemption that
|
||||||
compiling, linking, and/or using OpenSSL is allowed. You may provide binary
|
> compiling, linking, and/or using OpenSSL is allowed. You may provide binary
|
||||||
packages linked to the OpenSSL libraries, provided that all other requirements
|
> packages linked to the OpenSSL libraries, provided that all other requirements
|
||||||
of the GPL are met.
|
> of the GPL are met.
|
||||||
|
|
||||||
The following applies to the LZO library:
|
The following applies to the LZO library:
|
||||||
|
|
||||||
Hereby I grant a special exception to the tinc VPN project
|
> Hereby I grant a special exception to the tinc VPN project
|
||||||
(http://tinc.nl.linux.org/) to link the LZO library with the OpenSSL library
|
> (https://www.tinc-vpn.org/) to link the LZO library with the OpenSSL library
|
||||||
(http://www.openssl.org).
|
> (https://openssl.org).
|
||||||
|
>
|
||||||
Markus F.X.J. Oberhumer
|
> Markus F.X.J. Oberhumer
|
||||||
|
|
||||||
When tinc is compiled with the --enable-tunemu option, the resulting binary
|
When tinc is compiled with the --enable-tunemu option, the resulting binary
|
||||||
falls under the GPL version 3 or later.
|
falls under the GPL version 3 or later.
|
||||||
|
|
||||||
|
|
||||||
|
|
371
NEWS
371
NEWS
|
@ -1,179 +1,163 @@
|
||||||
Version 1.1pre11 December 27 2014
|
# Version 1.1pre13 May 1 2016
|
||||||
|
|
||||||
|
* Add tinc.service back.
|
||||||
|
|
||||||
|
# Version 1.1pre13 April 30 2016
|
||||||
|
|
||||||
|
* Fix BSD tun device support that was broken in 1.1pre12.
|
||||||
|
* Speed up AutoConnect when there are many host config files present without
|
||||||
|
an Address.
|
||||||
|
|
||||||
|
# Version 1.1pre12 April 24 2016
|
||||||
|
|
||||||
|
* Added a "--syslog" option to force logging to syslog even if running in the
|
||||||
|
foreground.
|
||||||
|
* Fixes and improvements to the DecrementTTL function.
|
||||||
|
* Improved PMTU discovery and UDP keepalive probes.
|
||||||
|
* More efficient relaying of UDP packets through intermediate nodes.
|
||||||
|
* Improved compatibility with newer TAP-Win32 drivers.
|
||||||
|
* Added support for UPnP.
|
||||||
|
* Allow tinc to be compiled without LibreSSL or OpenSSL (this drops
|
||||||
|
compatibility with nodes running 1.0.x).
|
||||||
|
* Added a "fsck" command to check the configuration files for problems.
|
||||||
|
* Tinc "start" now checks whether the daemon really started succesfully, and
|
||||||
|
displays error messages otherwise.
|
||||||
|
* Added systemd service files.
|
||||||
|
* Use the recvmmsg() function if available.
|
||||||
|
* Support ToS/Diffserv on IPv6 connections.
|
||||||
|
* Updated support for BSD tun/tap devices.
|
||||||
|
* Added support for OS X utun interfaces.
|
||||||
|
* Dropped support for Windows 2000.
|
||||||
|
* Initial support for generating a tinc-up script from an invitation.
|
||||||
|
* Many small fixes, documentation updates.
|
||||||
|
|
||||||
|
Thanks to Etienne Dechamps, Rafał Leśniak, Vittorio Gambaletta, Martin Weinelt,
|
||||||
|
Sven-Haegar Koch, Florian Klink, LunnarShadow, Dato Simó, Jo-Philipp Wich,
|
||||||
|
Jochen Voss, Nathan Stratton Treadway, Pierre Emeriaud, xentec, Samuel
|
||||||
|
Thibault and Michael Tokarev for their contributions to this version of tinc.
|
||||||
|
|
||||||
|
# Version 1.1pre11 December 27 2014
|
||||||
|
|
||||||
* Added a "network" command to list or switch networks.
|
* Added a "network" command to list or switch networks.
|
||||||
|
|
||||||
* Switched to Ed25519 keys and the ChaCha-Poly1305 cipher for the new protocol.
|
* Switched to Ed25519 keys and the ChaCha-Poly1305 cipher for the new protocol.
|
||||||
|
|
||||||
* AutoConnect is now a boolean option, when enabled tinc always tries to keep
|
* AutoConnect is now a boolean option, when enabled tinc always tries to keep
|
||||||
at least three meta-connections open.
|
at least three meta-connections open.
|
||||||
|
|
||||||
* The new protocol now uses UDP much more often.
|
* The new protocol now uses UDP much more often.
|
||||||
|
|
||||||
* Tinc "del" and "get" commands now return a non-zero exit code when they
|
* Tinc "del" and "get" commands now return a non-zero exit code when they
|
||||||
don't find the requested variable.
|
don't find the requested variable.
|
||||||
|
|
||||||
* Updated documentation.
|
* Updated documentation.
|
||||||
|
|
||||||
* Added a "DeviceStandby" option to defer running tinc-up until a working
|
* Added a "DeviceStandby" option to defer running tinc-up until a working
|
||||||
connection is made, and which on Windows will also change the network
|
connection is made, and which on Windows will also change the network
|
||||||
interface link status accordingly.
|
interface link status accordingly.
|
||||||
|
|
||||||
* Tinc now tells the resolver to reload /etc/resolv.conf when it receives
|
* Tinc now tells the resolver to reload /etc/resolv.conf when it receives
|
||||||
SIGALRM.
|
SIGALRM.
|
||||||
|
|
||||||
* Improved error messages and event loop handling on Windows.
|
* Improved error messages and event loop handling on Windows.
|
||||||
|
|
||||||
* LocalDiscovery now uses local address learned from other nodes, and is
|
* LocalDiscovery now uses local address learned from other nodes, and is
|
||||||
enabled by default.
|
enabled by default.
|
||||||
|
|
||||||
* Added a "BroadcastSubnet" option to change the behavior of broadcast packets
|
* Added a "BroadcastSubnet" option to change the behavior of broadcast packets
|
||||||
in router mode.
|
in router mode.
|
||||||
|
|
||||||
* Added support for dotted quad notation in IPv6 (e.g. ::1.2.3.4).
|
* Added support for dotted quad notation in IPv6 (e.g. ::1.2.3.4).
|
||||||
|
|
||||||
* Improved format of printed Subnets, MAC and IPv6 addresses.
|
* Improved format of printed Subnets, MAC and IPv6 addresses.
|
||||||
|
|
||||||
* Added a "--batch" option to force the tinc CLI to run in non-interactive
|
* Added a "--batch" option to force the tinc CLI to run in non-interactive
|
||||||
mode.
|
mode.
|
||||||
|
|
||||||
* Improve default Device selection on *BSD and Mac OS X.
|
* Improve default Device selection on *BSD and Mac OS X.
|
||||||
|
|
||||||
* Allow running tinc without RSA keys.
|
* Allow running tinc without RSA keys.
|
||||||
|
|
||||||
Thanks to Etienne Dechamps, Sven-Haegar Koch, William A. Kennington III,
|
Thanks to Etienne Dechamps, Sven-Haegar Koch, William A. Kennington III,
|
||||||
Baptiste Jonglez, Alexis Hildebrandt, Armin Fisslthaler, Franz Pletz, Alexander
|
Baptiste Jonglez, Alexis Hildebrandt, Armin Fisslthaler, Franz Pletz, Alexander
|
||||||
Ried and Saverio Proto for their contributions to this version of tinc.
|
Ried and Saverio Proto for their contributions to this version of tinc.
|
||||||
|
|
||||||
Version 1.1pre10 February 7 2014
|
# Version 1.1pre10 February 7 2014
|
||||||
|
|
||||||
* Added a benchmark tool (sptps_speed) for the new protocol.
|
* Added a benchmark tool (sptps_speed) for the new protocol.
|
||||||
|
|
||||||
* Fixed a crash when using Name = $HOST while $HOST is not set.
|
* Fixed a crash when using Name = $HOST while $HOST is not set.
|
||||||
|
|
||||||
* Use AES-256-GCM for the new protocol.
|
* Use AES-256-GCM for the new protocol.
|
||||||
|
|
||||||
* Updated support for Solaris.
|
* Updated support for Solaris.
|
||||||
|
|
||||||
* Allow running tincd without a private ECDSA key present when
|
* Allow running tincd without a private ECDSA key present when
|
||||||
ExperimentalProtocol is not explicitly set.
|
ExperimentalProtocol is not explicitly set.
|
||||||
|
|
||||||
* Enable various compiler hardening flags by default.
|
* Enable various compiler hardening flags by default.
|
||||||
|
|
||||||
* Added support for a "conf.d" configuration directory.
|
* Added support for a "conf.d" configuration directory.
|
||||||
|
|
||||||
* Fix tinc-gui on Windows, also allowing it to connect to a 32-bits tincd when
|
* Fix tinc-gui on Windows, also allowing it to connect to a 32-bits tincd when
|
||||||
tinc-gui is run in a 64-bits Python environment.
|
tinc-gui is run in a 64-bits Python environment.
|
||||||
|
|
||||||
* Added a "ListenAddress" option, which like BindToAddress adds more listening
|
* Added a "ListenAddress" option, which like BindToAddress adds more listening
|
||||||
address/ports, but doesn't bind to them for outgoing sockets.
|
address/ports, but doesn't bind to them for outgoing sockets.
|
||||||
|
|
||||||
* Make invitations work better when the "invite" and "join" commands are not
|
* Make invitations work better when the "invite" and "join" commands are not
|
||||||
run interactively.
|
run interactively.
|
||||||
|
|
||||||
* When creating meta-connections to a node for which no Address statement is
|
* When creating meta-connections to a node for which no Address statement is
|
||||||
specified, try to use addresses learned from other nodes.
|
specified, try to use addresses learned from other nodes.
|
||||||
|
|
||||||
Thanks to Dennis Joachimsthaler and Florent Clairambault for their contribution
|
Thanks to Dennis Joachimsthaler and Florent Clairambault for their contribution
|
||||||
to this version of tinc.
|
to this version of tinc.
|
||||||
|
|
||||||
Version 1.1pre9 September 8 2013
|
# Version 1.1pre9 September 8 2013
|
||||||
|
|
||||||
* The UNIX socket is now created before tinc-up is called.
|
* The UNIX socket is now created before tinc-up is called.
|
||||||
|
|
||||||
* Windows users can now use any extension that is in %PATHEXT% for scripts,
|
* Windows users can now use any extension that is in %PATHEXT% for scripts,
|
||||||
not only .bat.
|
not only .bat.
|
||||||
|
|
||||||
* Outgoing sockets are bound to the address of the listening sockets again,
|
* Outgoing sockets are bound to the address of the listening sockets again,
|
||||||
when there is no ambiguity.
|
when there is no ambiguity.
|
||||||
|
|
||||||
* Added invitation-created and invitation-accepted scripts.
|
* Added invitation-created and invitation-accepted scripts.
|
||||||
|
|
||||||
* Invited nodes now learn of the Mode and Broadcast settings of the VPN.
|
* Invited nodes now learn of the Mode and Broadcast settings of the VPN.
|
||||||
|
|
||||||
* Joining a VPN with an invitation now also works on Windows.
|
* Joining a VPN with an invitation now also works on Windows.
|
||||||
|
|
||||||
* The port number tincd is listening on is now always included in the
|
* The port number tincd is listening on is now always included in the
|
||||||
invitation URL.
|
invitation URL.
|
||||||
|
|
||||||
* A running tincd is now correctly informed when a new invitation has been
|
* A running tincd is now correctly informed when a new invitation has been
|
||||||
generated.
|
generated.
|
||||||
|
|
||||||
* Several bug fixes for the new protocol.
|
* Several bug fixes for the new protocol.
|
||||||
|
|
||||||
* Added a test suite.
|
* Added a test suite.
|
||||||
|
|
||||||
Thanks to Etienne Dechamps for his contribution to this version of tinc.
|
Thanks to Etienne Dechamps for his contribution to this version of tinc.
|
||||||
|
|
||||||
Version 1.1pre8 August 13 2013
|
# Version 1.1pre8 August 13 2013
|
||||||
|
|
||||||
* ExperimentalProtocol is now enabled by default.
|
* ExperimentalProtocol is now enabled by default.
|
||||||
|
|
||||||
* Added an invitation protocol that makes it easy to invite new nodes.
|
* Added an invitation protocol that makes it easy to invite new nodes.
|
||||||
|
|
||||||
* Added the LocalDiscoveryAddress option to change the broadcast address used
|
* Added the LocalDiscoveryAddress option to change the broadcast address used
|
||||||
to find local nodes.
|
to find local nodes.
|
||||||
|
|
||||||
* Limit the rate of incoming meta-connections.
|
* Limit the rate of incoming meta-connections.
|
||||||
|
|
||||||
* Many small bug fixes and code cleanups.
|
* Many small bug fixes and code cleanups.
|
||||||
|
|
||||||
Thanks to Etienne Dechamps and Sven-Haegar Koch for their contributions to this
|
Thanks to Etienne Dechamps and Sven-Haegar Koch for their contributions to this
|
||||||
version of tinc.
|
version of tinc.
|
||||||
|
|
||||||
Version 1.1pre7 April 22 2013
|
# Version 1.1pre7 April 22 2013
|
||||||
|
|
||||||
* Fixed large latencies on Windows.
|
* Fixed large latencies on Windows.
|
||||||
|
|
||||||
* Renamed the tincctl tool to tinc.
|
* Renamed the tincctl tool to tinc.
|
||||||
|
|
||||||
* Simplified changing the configuration using the tinc tool.
|
* Simplified changing the configuration using the tinc tool.
|
||||||
|
|
||||||
* Added a full description of the ExperimentalProtocol to the manual.
|
* Added a full description of the ExperimentalProtocol to the manual.
|
||||||
|
|
||||||
* Drop packets forwarded via TCP if they are too big (CVE-2013-1428).
|
* Drop packets forwarded via TCP if they are too big (CVE-2013-1428).
|
||||||
|
|
||||||
Thanks to Martin Schobert for auditing tinc and reporting the vulnerability.
|
Thanks to Martin Schobert for auditing tinc and reporting the vulnerability.
|
||||||
|
|
||||||
Version 1.1pre6 February 20 2013
|
# Version 1.1pre6 February 20 2013
|
||||||
|
|
||||||
* Fixed tincd exitting immediately on Windows.
|
* Fixed tincd exitting immediately on Windows.
|
||||||
|
|
||||||
* Detect PMTU increases.
|
* Detect PMTU increases.
|
||||||
|
|
||||||
* Fixed crashes when using a SOCKS5 proxy.
|
* Fixed crashes when using a SOCKS5 proxy.
|
||||||
|
|
||||||
* Fixed control connection when using a proxy.
|
* Fixed control connection when using a proxy.
|
||||||
|
|
||||||
Version 1.1pre5 January 20 2013
|
# Version 1.1pre5 January 20 2013
|
||||||
|
|
||||||
* Fixed long delays and possible hangs on Windows.
|
* Fixed long delays and possible hangs on Windows.
|
||||||
|
|
||||||
* Fixed support for the tunemu device on iOS, the UML and VDE devices.
|
* Fixed support for the tunemu device on iOS, the UML and VDE devices.
|
||||||
|
|
||||||
* Small improvements to the documentation and error messages.
|
* Small improvements to the documentation and error messages.
|
||||||
|
|
||||||
* Fixed broadcast packets not reaching the whole VPN.
|
* Fixed broadcast packets not reaching the whole VPN.
|
||||||
|
|
||||||
* Tincctl now connects via a UNIX socket to the tincd on platforms that
|
* Tincctl now connects via a UNIX socket to the tincd on platforms that
|
||||||
support this.
|
support this.
|
||||||
|
|
||||||
* The PriorityInheritance option now also works in switch mode.
|
* The PriorityInheritance option now also works in switch mode.
|
||||||
|
|
||||||
Version 1.1pre4 December 5 2012
|
# Version 1.1pre4 December 5 2012
|
||||||
|
|
||||||
* Added the "AutoConnect" option which will let tinc automatically select
|
* Added the "AutoConnect" option which will let tinc automatically select
|
||||||
which nodes to connect to.
|
which nodes to connect to.
|
||||||
|
|
||||||
* Improved performance of VLAN-tagged IP traffic inside the VPN.
|
* Improved performance of VLAN-tagged IP traffic inside the VPN.
|
||||||
|
|
||||||
* Ensured LocalDiscovery works with multiple BindToAddress statements and/or
|
* Ensured LocalDiscovery works with multiple BindToAddress statements and/or
|
||||||
IPv6-only LANs.
|
IPv6-only LANs.
|
||||||
|
|
||||||
* Dropped dependency on libevent.
|
* Dropped dependency on libevent.
|
||||||
|
|
||||||
* Fixed Windows version not reading packets from the TAP adapter.
|
* Fixed Windows version not reading packets from the TAP adapter.
|
||||||
|
|
||||||
Version 1.1pre3 October 14 2012
|
# Version 1.1pre3 October 14 2012
|
||||||
|
|
||||||
* New experimental protocol:
|
* New experimental protocol:
|
||||||
* Uses 521 bit ECDSA keys for authentication.
|
* Uses 521 bit ECDSA keys for authentication.
|
||||||
|
@ -181,7 +165,6 @@ Version 1.1pre3 October 14 2012
|
||||||
* Always provides perfect forward secrecy.
|
* Always provides perfect forward secrecy.
|
||||||
* Used for both meta-connections and VPN packets.
|
* Used for both meta-connections and VPN packets.
|
||||||
* VPN packets are encrypted end-to-end.
|
* VPN packets are encrypted end-to-end.
|
||||||
|
|
||||||
* Many improvements to tincctl:
|
* Many improvements to tincctl:
|
||||||
* "config" command shows/adds/changes configuration variables.
|
* "config" command shows/adds/changes configuration variables.
|
||||||
* "export" and "import" commands help exchange configuration files.
|
* "export" and "import" commands help exchange configuration files.
|
||||||
|
@ -191,16 +174,13 @@ Version 1.1pre3 October 14 2012
|
||||||
* Without a command it acts as a shell, with history and TAB completion.
|
* Without a command it acts as a shell, with history and TAB completion.
|
||||||
* Improved starting/stopping tincd.
|
* Improved starting/stopping tincd.
|
||||||
* Improved graph output.
|
* Improved graph output.
|
||||||
|
|
||||||
* When trying to directly send UDP packets to a node for which multiple
|
* When trying to directly send UDP packets to a node for which multiple
|
||||||
addresses are known, all of them are tried.
|
addresses are known, all of them are tried.
|
||||||
|
|
||||||
* Many small fixes, code cleanups and documentation updates.
|
* Many small fixes, code cleanups and documentation updates.
|
||||||
|
|
||||||
Version 1.1pre2 July 17 2011
|
# Version 1.1pre2 July 17 2011
|
||||||
|
|
||||||
* .cookie files are renamed to .pid files, which are compatible with 1.0.x.
|
* .cookie files are renamed to .pid files, which are compatible with 1.0.x.
|
||||||
|
|
||||||
* Experimental protocol enhancements that can be enabled with the option
|
* Experimental protocol enhancements that can be enabled with the option
|
||||||
ExperimentalProtocol = yes:
|
ExperimentalProtocol = yes:
|
||||||
|
|
||||||
|
@ -210,441 +190,328 @@ Version 1.1pre2 July 17 2011
|
||||||
* ECDSA public keys are automatically exchanged after RSA authentication if
|
* ECDSA public keys are automatically exchanged after RSA authentication if
|
||||||
nodes do not know each other's ECDSA public key yet.
|
nodes do not know each other's ECDSA public key yet.
|
||||||
|
|
||||||
Version 1.1pre1 June 25 2011
|
# Version 1.1pre1 June 25 2011
|
||||||
|
|
||||||
* Control interface allows control of a running tinc daemon. Used by:
|
* Control interface allows control of a running tinc daemon. Used by:
|
||||||
* tincctl, a commandline utility
|
* tincctl, a commandline utility
|
||||||
* tinc-gui, a preliminary GUI implemented in Python/wxWidgets
|
* tinc-gui, a preliminary GUI implemented in Python/wxWidgets
|
||||||
|
|
||||||
* Code cleanups and reorganization.
|
* Code cleanups and reorganization.
|
||||||
|
|
||||||
* Repleacable cryptography backend, currently supports OpenSSL and libgcrypt.
|
* Repleacable cryptography backend, currently supports OpenSSL and libgcrypt.
|
||||||
|
|
||||||
* Use libevent to handle I/O events and timeouts.
|
* Use libevent to handle I/O events and timeouts.
|
||||||
|
|
||||||
* Use splay trees instead of AVL trees to manage internal datastructures.
|
* Use splay trees instead of AVL trees to manage internal datastructures.
|
||||||
|
|
||||||
Thanks to Scott Lamb and Sven-Haegar Koch for their contributions to this
|
Thanks to Scott Lamb and Sven-Haegar Koch for their contributions to this
|
||||||
version of tinc.
|
version of tinc.
|
||||||
|
|
||||||
Version 1.0.22 August 13 2013
|
# Version 1.0.22 August 13 2013
|
||||||
|
|
||||||
* Fixed the combination of Mode = router and DeviceType = tap.
|
* Fixed the combination of Mode = router and DeviceType = tap.
|
||||||
|
|
||||||
* The $NAME variable is now set in subnet-up/down scripts.
|
* The $NAME variable is now set in subnet-up/down scripts.
|
||||||
|
|
||||||
* Tinc now gives an error when unknown options are given on the command line.
|
* Tinc now gives an error when unknown options are given on the command line.
|
||||||
|
|
||||||
* Tinc now correctly handles a space between a short command line option and
|
* Tinc now correctly handles a space between a short command line option and
|
||||||
an optional argument.
|
an optional argument.
|
||||||
|
|
||||||
Thanks to Etienne Dechamps for his contribution to this version of tinc.
|
Thanks to Etienne Dechamps for his contribution to this version of tinc.
|
||||||
|
|
||||||
Version 1.0.21 April 22 2013
|
# Version 1.0.21 April 22 2013
|
||||||
|
|
||||||
* Drop packets forwarded via TCP if they are too big (CVE-2013-1428).
|
* Drop packets forwarded via TCP if they are too big (CVE-2013-1428).
|
||||||
|
|
||||||
Thanks to Martin Schobert for auditing tinc and reporting this vulnerability.
|
Thanks to Martin Schobert for auditing tinc and reporting this vulnerability.
|
||||||
|
|
||||||
Version 1.0.20 March 03 2013
|
# Version 1.0.20 March 03 2013
|
||||||
|
|
||||||
* Use /dev/tap0 by default on FreeBSD and NetBSD when using switch mode.
|
* Use /dev/tap0 by default on FreeBSD and NetBSD when using switch mode.
|
||||||
|
|
||||||
* Minor improvements and clarifications in the documentation.
|
* Minor improvements and clarifications in the documentation.
|
||||||
|
|
||||||
* Allow tinc to be cross-compiled with Android's NDK.
|
* Allow tinc to be cross-compiled with Android's NDK.
|
||||||
|
|
||||||
* The discovered PMTU is now also applied to VLAN tagged traffic.
|
* The discovered PMTU is now also applied to VLAN tagged traffic.
|
||||||
|
|
||||||
* The LocalDiscovery option now makes use of all addresses tinc is bound to.
|
* The LocalDiscovery option now makes use of all addresses tinc is bound to.
|
||||||
|
|
||||||
* Fixed support for tunemu on iOS devices.
|
* Fixed support for tunemu on iOS devices.
|
||||||
|
|
||||||
* The PriorityInheritance option now also works with switch mode.
|
* The PriorityInheritance option now also works with switch mode.
|
||||||
|
|
||||||
* Fixed tinc crashing when using a SOCKS5 proxy.
|
* Fixed tinc crashing when using a SOCKS5 proxy.
|
||||||
|
|
||||||
Thanks to Mesar Hameed, Vilbrekin and Martin Schürrer for their contributions
|
Thanks to Mesar Hameed, Vilbrekin and Martin Schürrer for their contributions
|
||||||
to this version of tinc.
|
to this version of tinc.
|
||||||
|
|
||||||
Version 1.0.19 June 25 2012
|
# Version 1.0.19 June 25 2012
|
||||||
|
|
||||||
* Allow :: notation in IPv6 Subnets.
|
* Allow :: notation in IPv6 Subnets.
|
||||||
|
|
||||||
* Add support for systemd style socket activation.
|
* Add support for systemd style socket activation.
|
||||||
|
|
||||||
* Allow environment variables to be used for the Name option.
|
* Allow environment variables to be used for the Name option.
|
||||||
|
|
||||||
* Add basic support for SOCKS proxies, HTTP proxies, and proxying through an
|
* Add basic support for SOCKS proxies, HTTP proxies, and proxying through an
|
||||||
external command.
|
external command.
|
||||||
|
|
||||||
Version 1.0.18 March 25 2012
|
# Version 1.0.18 March 25 2012
|
||||||
|
|
||||||
* Fixed IPv6 in switch mode by turning off DecrementTTL by default.
|
* Fixed IPv6 in switch mode by turning off DecrementTTL by default.
|
||||||
|
|
||||||
* Allow a port number to be specified in BindToAddress, which also allows tinc
|
* Allow a port number to be specified in BindToAddress, which also allows tinc
|
||||||
to listen on multiple ports.
|
to listen on multiple ports.
|
||||||
|
|
||||||
* Add support for multicast communication with UML/QEMU/KVM.
|
* Add support for multicast communication with UML/QEMU/KVM.
|
||||||
|
|
||||||
Version 1.0.17 March 10 2012
|
# Version 1.0.17 March 10 2012
|
||||||
|
|
||||||
* The DeviceType option can now be used to select dummy, raw socket, UML and
|
* The DeviceType option can now be used to select dummy, raw socket, UML and
|
||||||
VDE devices without needing to recompile tinc.
|
VDE devices without needing to recompile tinc.
|
||||||
|
|
||||||
* Allow multiple BindToAddress statements.
|
* Allow multiple BindToAddress statements.
|
||||||
|
|
||||||
* Decrement TTL value of IPv4 and IPv6 packets.
|
* Decrement TTL value of IPv4 and IPv6 packets.
|
||||||
|
|
||||||
* Add LocalDiscovery option allowing tinc to detect peers that are behind the
|
* Add LocalDiscovery option allowing tinc to detect peers that are behind the
|
||||||
same NAT.
|
same NAT.
|
||||||
|
|
||||||
* Accept Subnets passed with the -o option when StrictSubnets = yes.
|
* Accept Subnets passed with the -o option when StrictSubnets = yes.
|
||||||
|
|
||||||
* Disabling old RSA keys when generating new ones now also works properly on
|
* Disabling old RSA keys when generating new ones now also works properly on
|
||||||
Windows.
|
Windows.
|
||||||
|
|
||||||
Version 1.0.16 July 23 2011
|
# Version 1.0.16 July 23 2011
|
||||||
|
|
||||||
* Fixed a performance issue with TCP communication under Windows.
|
* Fixed a performance issue with TCP communication under Windows.
|
||||||
|
|
||||||
* Fixed code that, during network outages, would cause tinc to exit when it
|
* Fixed code that, during network outages, would cause tinc to exit when it
|
||||||
thought two nodes with identical Names were on the VPN.
|
thought two nodes with identical Names were on the VPN.
|
||||||
|
|
||||||
Version 1.0.15 June 24 2011
|
# Version 1.0.15 June 24 2011
|
||||||
|
|
||||||
* Improved logging to file.
|
* Improved logging to file.
|
||||||
|
|
||||||
* Reduced amount of process wakeups on platforms which support pselect().
|
* Reduced amount of process wakeups on platforms which support pselect().
|
||||||
|
|
||||||
* Fixed ProcessPriority option under Windows.
|
* Fixed ProcessPriority option under Windows.
|
||||||
|
|
||||||
Thanks to Loïc Grenié for his contribution to this version of tinc.
|
Thanks to Loïc Grenié for his contribution to this version of tinc.
|
||||||
|
|
||||||
Version 1.0.14 May 8 2011
|
# Version 1.0.14 May 8 2011
|
||||||
|
|
||||||
* Fixed reading configuration files that do not end with a newline. Again.
|
* Fixed reading configuration files that do not end with a newline. Again.
|
||||||
|
|
||||||
* Allow arbitrary configuration options being specified on the command line.
|
* Allow arbitrary configuration options being specified on the command line.
|
||||||
|
|
||||||
* Allow all options in both tinc.conf and the local host config file.
|
* Allow all options in both tinc.conf and the local host config file.
|
||||||
|
|
||||||
* Configurable replay window, UDP send and receive buffers for performance tuning.
|
* Configurable replay window, UDP send and receive buffers for performance tuning.
|
||||||
|
|
||||||
* Try harder to get UDP communication back after falling back to TCP.
|
* Try harder to get UDP communication back after falling back to TCP.
|
||||||
|
|
||||||
* Initial support for attaching tinc to a VDE switch.
|
* Initial support for attaching tinc to a VDE switch.
|
||||||
|
|
||||||
* DragonFly BSD support.
|
* DragonFly BSD support.
|
||||||
|
|
||||||
* Allow linking with OpenSSL 1.0.0.
|
* Allow linking with OpenSSL 1.0.0.
|
||||||
|
|
||||||
Thanks to Brandon Black, Julien Muchembled, Michael Tokarev, Rumko and Timothy
|
Thanks to Brandon Black, Julien Muchembled, Michael Tokarev, Rumko and Timothy
|
||||||
Redaelli for their contributions to this version of tinc.
|
Redaelli for their contributions to this version of tinc.
|
||||||
|
|
||||||
Version 1.0.13 Apr 11 2010
|
# Version 1.0.13 Apr 11 2010
|
||||||
|
|
||||||
* Allow building tinc without LZO and/or Zlib.
|
* Allow building tinc without LZO and/or Zlib.
|
||||||
|
|
||||||
* Clamp MSS of TCP packets in both directions.
|
* Clamp MSS of TCP packets in both directions.
|
||||||
|
|
||||||
* Experimental StrictSubnets, Forwarding and DirectOnly options,
|
* Experimental StrictSubnets, Forwarding and DirectOnly options,
|
||||||
giving more control over information and packets received from/sent to other
|
giving more control over information and packets received from/sent to other
|
||||||
nodes.
|
nodes.
|
||||||
|
|
||||||
* Ensure tinc never sends symbolic names for ports over the wire.
|
* Ensure tinc never sends symbolic names for ports over the wire.
|
||||||
|
|
||||||
Version 1.0.12 Feb 3 2010
|
# Version 1.0.12 Feb 3 2010
|
||||||
|
|
||||||
* Really allow fast roaming of hosts to other nodes in a switched VPN.
|
* Really allow fast roaming of hosts to other nodes in a switched VPN.
|
||||||
|
|
||||||
* Fixes missing or incorrect environment variables when calling host-up/down
|
* Fixes missing or incorrect environment variables when calling host-up/down
|
||||||
and subnet-up/down scripts in some cases.
|
and subnet-up/down scripts in some cases.
|
||||||
|
|
||||||
* Allow port to be specified in Address statements.
|
* Allow port to be specified in Address statements.
|
||||||
|
|
||||||
* Clamp MSS of TCP packets to the discovered path MTU.
|
* Clamp MSS of TCP packets to the discovered path MTU.
|
||||||
|
|
||||||
* Let two nodes behind NAT learn each others current UDP address and port via
|
* Let two nodes behind NAT learn each others current UDP address and port via
|
||||||
a third node, potentially allowing direct communications in a similar way to
|
a third node, potentially allowing direct communications in a similar way to
|
||||||
STUN.
|
STUN.
|
||||||
|
|
||||||
Version 1.0.11 Nov 1 2009
|
# Version 1.0.11 Nov 1 2009
|
||||||
|
|
||||||
* Fixed potential crash when the HUP signal is sent.
|
* Fixed potential crash when the HUP signal is sent.
|
||||||
|
|
||||||
* Fixes handling of weighted Subnets in switch and hub modes, preventing
|
* Fixes handling of weighted Subnets in switch and hub modes, preventing
|
||||||
unnecessary broadcasts.
|
unnecessary broadcasts.
|
||||||
|
|
||||||
* Works around a MinGW bug that caused packets to Windows nodes to always be
|
* Works around a MinGW bug that caused packets to Windows nodes to always be
|
||||||
sent via TCP.
|
sent via TCP.
|
||||||
|
|
||||||
* Improvements to the PMTU discovery code, especially on Windows.
|
* Improvements to the PMTU discovery code, especially on Windows.
|
||||||
|
|
||||||
* Use UDP again in certain cases where 1.0.10 was too conservative and fell
|
* Use UDP again in certain cases where 1.0.10 was too conservative and fell
|
||||||
back to TCP unnecessarily.
|
back to TCP unnecessarily.
|
||||||
|
|
||||||
* Allow fast roaming of hosts to other nodes in a switched VPN.
|
* Allow fast roaming of hosts to other nodes in a switched VPN.
|
||||||
|
|
||||||
Version 1.0.10 Oct 18 2009
|
# Version 1.0.10 Oct 18 2009
|
||||||
|
|
||||||
* Fixed potential crashes during shutdown and (in rare conditions) when other
|
* Fixed potential crashes during shutdown and (in rare conditions) when other
|
||||||
nodes disconnected from the VPN.
|
nodes disconnected from the VPN.
|
||||||
|
|
||||||
* Improved NAT handling: tinc now copes with mangled port numbers, and will
|
* Improved NAT handling: tinc now copes with mangled port numbers, and will
|
||||||
automatically fall back to TCP if direct UDP connection between nodes is not
|
automatically fall back to TCP if direct UDP connection between nodes is not
|
||||||
possible. The TCPOnly option should not have to be used anymore.
|
possible. The TCPOnly option should not have to be used anymore.
|
||||||
|
|
||||||
* Allow configuration files with CRLF line endings to be read on UNIX.
|
* Allow configuration files with CRLF line endings to be read on UNIX.
|
||||||
|
|
||||||
* Disable old RSA keys when generating new ones, and raise the default size of
|
* Disable old RSA keys when generating new ones, and raise the default size of
|
||||||
new RSA keys to 2048 bits.
|
new RSA keys to 2048 bits.
|
||||||
|
|
||||||
* Many fixes in the path MTU discovery code, especially when Compression is
|
* Many fixes in the path MTU discovery code, especially when Compression is
|
||||||
being used.
|
being used.
|
||||||
|
|
||||||
* Tinc can now drop privileges and/or chroot itself.
|
* Tinc can now drop privileges and/or chroot itself.
|
||||||
|
|
||||||
* The TunnelServer code now just ignores information from clients instead of
|
* The TunnelServer code now just ignores information from clients instead of
|
||||||
disconnecting them.
|
disconnecting them.
|
||||||
|
|
||||||
* Improved performance on Windows by using the new ProcessPriority option and
|
* Improved performance on Windows by using the new ProcessPriority option and
|
||||||
by making the handling of packets received from the TAP-Win32 adapter more
|
by making the handling of packets received from the TAP-Win32 adapter more
|
||||||
efficient.
|
efficient.
|
||||||
|
|
||||||
* Code cleanups: tinc now follows the C99 standard, copyright headers have
|
* Code cleanups: tinc now follows the C99 standard, copyright headers have
|
||||||
been updated to include patch authors, checkpoint tracing and localisation
|
been updated to include patch authors, checkpoint tracing and localisation
|
||||||
features have been removed.
|
features have been removed.
|
||||||
|
|
||||||
* Support for (jailbroken) iPhone and iPod Touch has been added.
|
* Support for (jailbroken) iPhone and iPod Touch has been added.
|
||||||
|
|
||||||
Thanks to Florian Forster, Grzegorz Dymarek and especially Michael Tokarev for
|
Thanks to Florian Forster, Grzegorz Dymarek and especially Michael Tokarev for
|
||||||
their contributions to this version of tinc.
|
their contributions to this version of tinc.
|
||||||
|
|
||||||
Version 1.0.9 Dec 26 2008
|
# Version 1.0.9 Dec 26 2008
|
||||||
|
|
||||||
* Fixed tinc as a service under Windows 2003.
|
* Fixed tinc as a service under Windows 2003.
|
||||||
|
|
||||||
* Fixed reading configuration files that do not end with a newline.
|
* Fixed reading configuration files that do not end with a newline.
|
||||||
|
|
||||||
* Fixed crashes in situations where hostnames could not be resolved or hosts
|
* Fixed crashes in situations where hostnames could not be resolved or hosts
|
||||||
would disconnect at the same time as session keys were exchanged.
|
would disconnect at the same time as session keys were exchanged.
|
||||||
|
|
||||||
* Improved default settings of tun and tap devices on BSD platforms.
|
* Improved default settings of tun and tap devices on BSD platforms.
|
||||||
|
|
||||||
* Make IPv6 sockets bind only to IPv6 on Linux.
|
* Make IPv6 sockets bind only to IPv6 on Linux.
|
||||||
|
|
||||||
* Enable path MTU discovery by default.
|
* Enable path MTU discovery by default.
|
||||||
|
|
||||||
* Fixed a memory leak that occured when connections were closed.
|
* Fixed a memory leak that occured when connections were closed.
|
||||||
|
|
||||||
Thanks to Max Rijevski for his contributions to this version of tinc.
|
Thanks to Max Rijevski for his contributions to this version of tinc.
|
||||||
|
|
||||||
Version 1.0.8 May 16 2007
|
# Version 1.0.8 May 16 2007
|
||||||
|
|
||||||
* Fixed some memory and resource leaks.
|
* Fixed some memory and resource leaks.
|
||||||
|
|
||||||
* Made network sockets non-blocking under Windows.
|
* Made network sockets non-blocking under Windows.
|
||||||
|
|
||||||
Thanks to Scott Lamb and "dnk" for their contributions to this version of tinc.
|
Thanks to Scott Lamb and "dnk" for their contributions to this version of tinc.
|
||||||
|
|
||||||
Version 1.0.7 Jan 5 2007
|
# Version 1.0.7 Jan 5 2007
|
||||||
|
|
||||||
* Fixed a bug that caused slow network speeds on Windows.
|
* Fixed a bug that caused slow network speeds on Windows.
|
||||||
|
|
||||||
* Fixed a bug that caused tinc unable to write packets to the tun device on
|
* Fixed a bug that caused tinc unable to write packets to the tun device on
|
||||||
OpenBSD.
|
OpenBSD.
|
||||||
|
|
||||||
Version 1.0.6 Dec 18 2006
|
# Version 1.0.6 Dec 18 2006
|
||||||
|
|
||||||
* More flexible detection of the LZO libraries when compiling.
|
* More flexible detection of the LZO libraries when compiling.
|
||||||
|
|
||||||
* Fixed a bug where broadcasts in switch and hub modes sometimes would not
|
* Fixed a bug where broadcasts in switch and hub modes sometimes would not
|
||||||
work anymore when part of the VPN had become disconnected from the rest.
|
work anymore when part of the VPN had become disconnected from the rest.
|
||||||
|
|
||||||
Version 1.0.5 Nov 14 2006
|
# Version 1.0.5 Nov 14 2006
|
||||||
|
|
||||||
* Lots of small fixes.
|
* Lots of small fixes.
|
||||||
|
|
||||||
* Broadcast packets no longer grow in size with each hop. This should
|
* Broadcast packets no longer grow in size with each hop. This should
|
||||||
fix switch mode (again).
|
fix switch mode (again).
|
||||||
|
|
||||||
* Generic host-up and host-down scripts.
|
* Generic host-up and host-down scripts.
|
||||||
|
|
||||||
* Optionally dump graph in graphviz format to a file or a script.
|
* Optionally dump graph in graphviz format to a file or a script.
|
||||||
|
|
||||||
* Support LZO 2.0 and later.
|
* Support LZO 2.0 and later.
|
||||||
|
|
||||||
Thanks to Scott Lamb for his contributions to this version of tinc.
|
Thanks to Scott Lamb for his contributions to this version of tinc.
|
||||||
|
|
||||||
Version 1.0.4 May 4 2005
|
# Version 1.0.4 May 4 2005
|
||||||
|
|
||||||
* Fix switch and hub modes.
|
* Fix switch and hub modes.
|
||||||
|
|
||||||
* Optionally start scripts when a Subnet becomes (un)reachable.
|
* Optionally start scripts when a Subnet becomes (un)reachable.
|
||||||
|
|
||||||
Version 1.0.3 Nov 11 2004
|
# Version 1.0.3 Nov 11 2004
|
||||||
|
|
||||||
* Show error message when failing to write a PID file.
|
* Show error message when failing to write a PID file.
|
||||||
|
|
||||||
* Ignore spaces at end of lines in config files.
|
* Ignore spaces at end of lines in config files.
|
||||||
|
|
||||||
* Fix handling of late packets.
|
* Fix handling of late packets.
|
||||||
|
|
||||||
* Unify BSD tun/tap device handling. This allows IPv6 on tun devices and
|
* Unify BSD tun/tap device handling. This allows IPv6 on tun devices and
|
||||||
anything on tap devices as long as the underlying OS supports it.
|
anything on tap devices as long as the underlying OS supports it.
|
||||||
|
|
||||||
* Handle IPv6 on Solaris tun devices.
|
* Handle IPv6 on Solaris tun devices.
|
||||||
|
|
||||||
* Allow tinc to work properly under Windows XP SP2.
|
* Allow tinc to work properly under Windows XP SP2.
|
||||||
|
|
||||||
* Allow VLAN tagged Ethernet frames in switch and hub mode.
|
* Allow VLAN tagged Ethernet frames in switch and hub mode.
|
||||||
|
|
||||||
* Experimental PMTUDiscovery, TunnelServer and BlockingTCP options.
|
* Experimental PMTUDiscovery, TunnelServer and BlockingTCP options.
|
||||||
|
|
||||||
Version 1.0.2 Nov 8 2003
|
# Version 1.0.2 Nov 8 2003
|
||||||
|
|
||||||
* Fix address and hostname resolving under Windows.
|
* Fix address and hostname resolving under Windows.
|
||||||
|
|
||||||
* Remove warnings about non-existing scripts and unsupported address families.
|
* Remove warnings about non-existing scripts and unsupported address families.
|
||||||
|
|
||||||
* Use the event logger under Windows.
|
* Use the event logger under Windows.
|
||||||
|
|
||||||
* Fix quoting of filenames and command line arguments under Windows.
|
* Fix quoting of filenames and command line arguments under Windows.
|
||||||
|
|
||||||
* Strict checks for length incoming network packets and return values of
|
* Strict checks for length incoming network packets and return values of
|
||||||
cryptographic functions,
|
cryptographic functions,
|
||||||
|
|
||||||
* Fix a bug in metadata handling that made the tinc daemon abort.
|
* Fix a bug in metadata handling that made the tinc daemon abort.
|
||||||
|
|
||||||
Version 1.0.1 Aug 14 2003
|
# Version 1.0.1 Aug 14 2003
|
||||||
|
|
||||||
* Allow empty lines in config files.
|
* Allow empty lines in config files.
|
||||||
|
|
||||||
* Fix handling of spaces and backslashes in filenames under native Windows.
|
* Fix handling of spaces and backslashes in filenames under native Windows.
|
||||||
|
|
||||||
* Allow scripts to be executed under native Windows.
|
* Allow scripts to be executed under native Windows.
|
||||||
|
|
||||||
* Update documentation, make it less Linux specific.
|
* Update documentation, make it less Linux specific.
|
||||||
|
|
||||||
Version 1.0 Aug 4 2003
|
# Version 1.0 Aug 4 2003
|
||||||
|
|
||||||
* Lots of small bugfixes and code cleanups.
|
* Lots of small bugfixes and code cleanups.
|
||||||
|
|
||||||
* Throughput doubled and latency reduced.
|
* Throughput doubled and latency reduced.
|
||||||
|
|
||||||
* Added support for LZO compression.
|
* Added support for LZO compression.
|
||||||
|
|
||||||
* No need to set MAC address or disable ARP anymore.
|
* No need to set MAC address or disable ARP anymore.
|
||||||
|
|
||||||
* Added support for Windows 2000 and XP, both natively and in a Cygwin
|
* Added support for Windows 2000 and XP, both natively and in a Cygwin
|
||||||
environment.
|
environment.
|
||||||
|
|
||||||
Version 1.0pre8 Sep 16 2002
|
# Version 1.0pre8 Sep 16 2002
|
||||||
|
|
||||||
* More fixes for subnets with prefixlength undivisible by 8.
|
* More fixes for subnets with prefixlength undivisible by 8.
|
||||||
|
|
||||||
* Added support for NetBSD and MacOS/X.
|
* Added support for NetBSD and MacOS/X.
|
||||||
|
|
||||||
* Switched from undirected graphs to directed graphs to avoid certain race
|
* Switched from undirected graphs to directed graphs to avoid certain race
|
||||||
conditions and improve scalability.
|
conditions and improve scalability.
|
||||||
|
|
||||||
* Generalized broadcasting and forwarding of protocol messages.
|
* Generalized broadcasting and forwarding of protocol messages.
|
||||||
|
|
||||||
* Cleanup of source code.
|
* Cleanup of source code.
|
||||||
|
|
||||||
Version 1.0pre7 Apr 7 2002
|
# Version 1.0pre7 Apr 7 2002
|
||||||
|
|
||||||
* Don't do blocking read()s when getting a signal.
|
* Don't do blocking read()s when getting a signal.
|
||||||
|
|
||||||
* Remove RSA key checking code, since it sometimes thinks perfectly good RSA
|
* Remove RSA key checking code, since it sometimes thinks perfectly good RSA
|
||||||
keys are bad.
|
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.
|
* Non-blocking connects.
|
||||||
* Protocol broadcast messages can no longer go into an infinite loop.
|
* Protocol broadcast messages can no longer go into an infinite loop.
|
||||||
* Graph algorithm updated to look harder for direct connections.
|
* 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.
|
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.
|
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
|
* Added sequence number and optional message authentication code to
|
||||||
the packets.
|
the packets.
|
||||||
* Configurable encryption cipher and digest algorithms.
|
* 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
|
# Version 1.0pre4 Jan 17 2001
|
||||||
|
|
||||||
* Updated documentation; the documentation now reflects the
|
* Updated documentation; the documentation now reflects the
|
||||||
configuration as it is.
|
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
|
networks, such as using AVL trees instead of linked lists for the
|
||||||
connection list.
|
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.
|
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
|
still under discussion, this is secure. Care has been taken to
|
||||||
resist most, if not all, attacks.
|
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
|
nor are earlier versions compatible with this version. Because the
|
||||||
older protocol has huge security flaws, we feel that not
|
older protocol has huge security flaws, we feel that not
|
||||||
implementing backwards compatibility is justified.
|
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
|
* It uses public/private RSA keys for authentication (this is the
|
||||||
actual fix for the security hole).
|
actual fix for the security hole).
|
||||||
* All cryptographic functions have been taken out of tinc, instead
|
* All cryptographic functions have been taken out of tinc, instead
|
||||||
it uses the OpenSSL library functions.
|
it uses the OpenSSL library functions.
|
||||||
* Offers support for multiple subnets per tinc daemon.
|
* 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.
|
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.
|
More information on getting and installing OpenSSL is in the manual.
|
||||||
This also means that the GMP library is no longer required.
|
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.
|
Carrasco provided us with a Spanish translation of the manual.
|
||||||
|
|
||||||
Version 1.0pre2 May 31 2000
|
# 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.
|
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
|
* VpnMask - the IP network mask for the entire VPN, not just our
|
||||||
subnet (as given by MyVirtualIP). The Redhat and Debian packages
|
subnet (as given by MyVirtualIP). The Redhat and Debian packages
|
||||||
|
@ -653,178 +520,158 @@ Version 1.0pre2 May 31 2000
|
||||||
* Hostnames - if set to `yes', look up the names of IP addresses
|
* Hostnames - if set to `yes', look up the names of IP addresses
|
||||||
trying to connect to us. Default set to `no', to prevent lockups
|
trying to connect to us. Default set to `no', to prevent lockups
|
||||||
during lookups.
|
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
|
/etc/tinc/nets.boot to find out which networks need to be started
|
||||||
during system boot.
|
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),
|
after connecting (and even when the connection has been established),
|
||||||
either random garbage or just nonsensical protocol fields.
|
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.
|
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
|
deleted from the internal list, to prevent hogging eachother with
|
||||||
add and delete requests when the connection is restored.
|
add and delete requests when the connection is restored.
|
||||||
|
|
||||||
Version 1.0pre1 May 12 2000
|
# Version 1.0pre1 May 12 2000
|
||||||
|
|
||||||
* New meta-protocol
|
* New meta-protocol
|
||||||
|
|
||||||
* Various other bugfixes
|
* Various other bugfixes
|
||||||
|
|
||||||
* Documentation updates
|
* Documentation updates
|
||||||
|
|
||||||
Version 0.3.3 Feb 9 2000
|
# Version 0.3.3 Feb 9 2000
|
||||||
|
|
||||||
* Fixed bug that made tinc stop working with latest kernels
|
* Fixed bug that made tinc stop working with latest kernels
|
||||||
|
|
||||||
* Updated the manual
|
* Updated the manual
|
||||||
|
|
||||||
Version 0.3.2 Nov 12 1999
|
# Version 0.3.2 Nov 12 1999
|
||||||
|
|
||||||
* No more `Invalid filedescriptor' when working with multiple
|
* No more `Invalid filedescriptor' when working with multiple
|
||||||
connections.
|
connections.
|
||||||
|
|
||||||
* Forward unknown packets to uplink.
|
* Forward unknown packets to uplink.
|
||||||
|
|
||||||
Version 0.3.1 Oct 20 1999
|
# Version 0.3.1 Oct 20 1999
|
||||||
|
|
||||||
* Fixed a bug where tinc would exit without a trace.
|
* Fixed a bug where tinc would exit without a trace.
|
||||||
|
|
||||||
Version 0.3 Aug 20 1999
|
# Version 0.3 Aug 20 1999
|
||||||
|
|
||||||
* Pings now work immediately.
|
* Pings now work immediately.
|
||||||
|
|
||||||
* All packet sizes get transmitted correctly.
|
* All packet sizes get transmitted correctly.
|
||||||
|
|
||||||
Version 0.2.26 Aug 15 1999
|
# Version 0.2.26 Aug 15 1999
|
||||||
|
|
||||||
* Fixed some remaining bugs.
|
* Fixed some remaining bugs.
|
||||||
|
|
||||||
* --sysconfdir works with configure.
|
* --sysconfdir works with configure.
|
||||||
|
|
||||||
* Last version before 0.3.
|
* Last version before 0.3.
|
||||||
|
|
||||||
Version 0.2.25 Aug 8 1999
|
# Version 0.2.25 Aug 8 1999
|
||||||
|
|
||||||
* Improved stability, going towards 0.3 now.
|
* Improved stability, going towards 0.3 now.
|
||||||
|
|
||||||
Version 0.2.24 Aug 7 1999
|
# Version 0.2.24 Aug 7 1999
|
||||||
|
|
||||||
* Added key aging, there's a new config variable, KeyExpire.
|
* Added key aging, there's a new config variable, KeyExpire.
|
||||||
|
|
||||||
* Updated man and info pages.
|
* Updated man and info pages.
|
||||||
|
|
||||||
Version 0.2.23 Aug 5 1999
|
# Version 0.2.23 Aug 5 1999
|
||||||
|
|
||||||
* All known bugs fixed, this is a candidate for 0.3.
|
* All known bugs fixed, this is a candidate for 0.3.
|
||||||
|
|
||||||
Version 0.2.22 Apr 11 1999
|
# Version 0.2.22 Apr 11 1999
|
||||||
|
|
||||||
* Multiconnection thing is now working nearly perfect :)
|
* Multiconnection thing is now working nearly perfect :)
|
||||||
|
|
||||||
Version 0.2.21 Apr 10 1999
|
# Version 0.2.21 Apr 10 1999
|
||||||
|
|
||||||
* You shouldn't notice a thing, but a lot has changed wrt key
|
* You shouldn't notice a thing, but a lot has changed wrt key
|
||||||
management - except that it refuses to talk to versions < 0.2.20
|
management - except that it refuses to talk to versions < 0.2.20
|
||||||
|
|
||||||
Version 0.2.19 Apr 3 1999
|
# Version 0.2.19 Apr 3 1999
|
||||||
|
|
||||||
* Don't install a libcipher.so.
|
* Don't install a libcipher.so.
|
||||||
|
|
||||||
Version 0.2.18 Apr 3 1999
|
# Version 0.2.18 Apr 3 1999
|
||||||
|
|
||||||
* Blowfish library dynamically loaded upon execution.
|
* Blowfish library dynamically loaded upon execution.
|
||||||
|
|
||||||
* Included Eric Young's IDEA library.
|
* Included Eric Young's IDEA library.
|
||||||
|
|
||||||
Version 0.2.17 Apr 1 1999
|
# Version 0.2.17 Apr 1 1999
|
||||||
|
|
||||||
* Tincd now re-executes itself in case of a segmentation fault.
|
* Tincd now re-executes itself in case of a segmentation fault.
|
||||||
|
|
||||||
Version 0.2.16 Apr 1 1999
|
# Version 0.2.16 Apr 1 1999
|
||||||
|
|
||||||
* Wrote tincd.conf(5) man page, which still needs a lot of work.
|
* Wrote tincd.conf(5) man page, which still needs a lot of work.
|
||||||
|
|
||||||
* Config file now accepts and tolerates spaces, and any integer base
|
* Config file now accepts and tolerates spaces, and any integer base
|
||||||
for integer variables, and better error reporting. See
|
for integer variables, and better error reporting. See
|
||||||
doc/tincd.conf.sample for an example.
|
doc/tincd.conf.sample for an example.
|
||||||
|
|
||||||
Version 0.2.15 Mar 29 1999
|
# Version 0.2.15 Mar 29 1999
|
||||||
|
|
||||||
* Fixed bugs.
|
* Fixed bugs.
|
||||||
|
|
||||||
Version 0.2.14 Feb 10 1999
|
# Version 0.2.14 Feb 10 1999
|
||||||
|
|
||||||
* Added --timeout flag and PingTimeout configuration.
|
* Added --timeout flag and PingTimeout configuration.
|
||||||
* Did some first syslog cleanup work.
|
* Did some first syslog cleanup work.
|
||||||
|
|
||||||
Version 0.2.13 Jan 23 1999
|
# Version 0.2.13 Jan 23 1999
|
||||||
|
|
||||||
* Bugfixes.
|
* Bugfixes.
|
||||||
|
|
||||||
Version 0.2.12 Jan 23 1999
|
# Version 0.2.12 Jan 23 1999
|
||||||
|
|
||||||
* Fixed nauseating bug so that it would crash whenever a connection
|
* Fixed nauseating bug so that it would crash whenever a connection
|
||||||
got lost.
|
got lost.
|
||||||
|
|
||||||
Version 0.2.11 Jan 22 1999
|
# Version 0.2.11 Jan 22 1999
|
||||||
|
|
||||||
* Framework for multiple connections has been done.
|
* Framework for multiple connections has been done.
|
||||||
|
|
||||||
* Simple manpage for tincd.
|
* Simple manpage for tincd.
|
||||||
|
|
||||||
Version 0.2.10 Jan 18 1999
|
# Version 0.2.10 Jan 18 1999
|
||||||
|
|
||||||
* Passphrase support added.
|
* Passphrase support added.
|
||||||
|
|
||||||
Version 0.2.9 Jan 13 1999
|
# Version 0.2.9 Jan 13 1999
|
||||||
|
|
||||||
* Bugs fixed.
|
* Bugs fixed.
|
||||||
|
|
||||||
Version 0.2.8 Jan 11 1999
|
# Version 0.2.8 Jan 11 1999
|
||||||
|
|
||||||
* A reworked protocol version.
|
* A reworked protocol version.
|
||||||
|
|
||||||
* A ping/pong system.
|
* A ping/pong system.
|
||||||
|
|
||||||
* More reliable networking code.
|
* More reliable networking code.
|
||||||
|
|
||||||
* Automatic reconnection.
|
* Automatic reconnection.
|
||||||
|
|
||||||
* Still does not work with more than one connection :)
|
* Still does not work with more than one connection :)
|
||||||
|
|
||||||
* Strips MAC addresses before sending, so there's less overhead, and
|
* Strips MAC addresses before sending, so there's less overhead, and
|
||||||
less redundancy.
|
less redundancy.
|
||||||
|
|
||||||
Version 0.2.7 Jan 3 1999
|
# Version 0.2.7 Jan 3 1999
|
||||||
|
|
||||||
* Several updates to make extending more easy.
|
* Several updates to make extending more easy.
|
||||||
|
|
||||||
Version 0.2.6 Dec 20 1998
|
# Version 0.2.6 Dec 20 1998
|
||||||
|
|
||||||
* Point-to-Point connections have been established, including
|
* Point-to-Point connections have been established, including
|
||||||
Blowfish encryption and a secret key-exchange.
|
Blowfish encryption and a secret key-exchange.
|
||||||
|
|
||||||
Version 0.2.5 Dec 16 1998
|
# Version 0.2.5 Dec 16 1998
|
||||||
|
|
||||||
* Project renamed to tinc, in honour of TINC.
|
* Project renamed to tinc, in honour of TINC.
|
||||||
|
|
||||||
Version 0.2.4 Dec 16 1998
|
# Version 0.2.4 Dec 16 1998
|
||||||
|
|
||||||
* Now it really does ;)
|
* Now it really does ;)
|
||||||
|
|
||||||
Version 0.2.3 Nov 24 1998
|
# Version 0.2.3 Nov 24 1998
|
||||||
|
|
||||||
* It sort of works now.
|
* It sort of works now.
|
||||||
|
|
||||||
Version 0.2.2 Nov 20 1998
|
# Version 0.2.2 Nov 20 1998
|
||||||
|
|
||||||
* Uses GNU gmp.
|
* Uses GNU gmp.
|
||||||
|
|
||||||
Version 0.2.1 Nov 14 1998
|
# Version 0.2.1 Nov 14 1998
|
||||||
|
|
||||||
* Bare version.
|
* Bare version.
|
||||||
|
|
36
README
36
README
|
@ -1,11 +1,7 @@
|
||||||
This is the README file for tinc version 1.1pre11. Installation
|
This is the README file for tinc version 1.1pre14. Installation
|
||||||
instructions may be found in the INSTALL file.
|
instructions may be found in the INSTALL file.
|
||||||
|
|
||||||
tinc is Copyright (C) 1998-2014 by:
|
tinc is Copyright © 1998-2016 Ivo Timmermans, Guus Sliepen <guus@tinc-vpn.org>, and others.
|
||||||
|
|
||||||
Ivo Timmermans,
|
|
||||||
Guus Sliepen <guus@tinc-vpn.org>,
|
|
||||||
and others.
|
|
||||||
|
|
||||||
For a complete list of authors see the AUTHORS file.
|
For a complete list of authors see the AUTHORS file.
|
||||||
|
|
||||||
|
@ -36,11 +32,12 @@ at your own risk.
|
||||||
Compatibility
|
Compatibility
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
Version 1.1pre11 is compatible with 1.0pre8, 1.0 and later, but not with older
|
Version 1.1pre14 is compatible with 1.0pre8, 1.0 and later, but not with older
|
||||||
versions of tinc.
|
versions of tinc.
|
||||||
|
|
||||||
When the ExperimentalProtocol option is used, tinc is still compatible with
|
When the ExperimentalProtocol option is used, tinc is still compatible with
|
||||||
1.0.X and 1.1pre11 itself, but not with any other 1.1preX version.
|
1.0.X, 1.1pre11 and later, but not with any version between 1.1pre1 and
|
||||||
|
1.1pre10.
|
||||||
|
|
||||||
|
|
||||||
Requirements
|
Requirements
|
||||||
|
@ -49,15 +46,14 @@ Requirements
|
||||||
In order to compile tinc, you will need a GNU C compiler environment. Please
|
In order to compile tinc, you will need a GNU C compiler environment. Please
|
||||||
ensure you have the latest stable versions of all the required libraries:
|
ensure you have the latest stable versions of all the required libraries:
|
||||||
|
|
||||||
- OpenSSL (http://www.openssl.org/) version 1.0.0 or later, with support for
|
- LibreSSL (http://www.libressl.org/) or OpenSSL (https://openssl.org/) version 1.0.0 or later.
|
||||||
elliptic curve cryptography (ECC) and Galois counter mode (GCM) enabled.
|
|
||||||
|
|
||||||
The following libraries are used by default, but can be disabled if necessary:
|
The following libraries are used by default, but can be disabled if necessary:
|
||||||
|
|
||||||
- zlib (http://www.gzip.org/zlib/)
|
- zlib (http://www.zlib.net/)
|
||||||
- lzo (http://www.oberhumer.com/opensource/lzo/)
|
- LZO (https://www.oberhumer.com/opensource/lzo/)
|
||||||
- ncurses (http://invisible-island.net/ncurses/)
|
- ncurses (http://invisible-island.net/ncurses/)
|
||||||
- readline (ftp://ftp.gnu.org/pub/gnu/readline/)
|
- readline (https://cnswww.cns.cwru.edu/php/chet/readline/rltop.html)
|
||||||
|
|
||||||
|
|
||||||
Features
|
Features
|
||||||
|
@ -70,12 +66,12 @@ those nodes, tinc will learn about all other nodes on the VPN, and will make
|
||||||
connections automatically. When direct connections are not possible, data will
|
connections automatically. When direct connections are not possible, data will
|
||||||
be forwarded by intermediate nodes.
|
be forwarded by intermediate nodes.
|
||||||
|
|
||||||
By default, nodes authenticate each other using 2048 bit RSA (or 521 bit
|
Tinc 1.1 support two protocols. The first is a legacy protocol that provides
|
||||||
ECDSA*) keys. Traffic is encrypted using Blowfish in CBC mode (or AES-256 in
|
backwards compatibility with tinc 1.0 nodes, and which by default uses 2048 bit
|
||||||
GCM mode*), authenticated using HMAC-SHA1 (or GCM*), and is protected against
|
RSA keys for authentication, and encrypts traffic using Blowfish in CBC mode
|
||||||
replay attacks.
|
and HMAC-SHA1. The second is a new protocol which uses Curve25519 keys for
|
||||||
|
authentication, and encrypts traffic using Chacha20-Poly1305, and provides
|
||||||
*) When using the ExperimentalProtocol option.
|
forward secrecy.
|
||||||
|
|
||||||
Tinc fully supports IPv6.
|
Tinc fully supports IPv6.
|
||||||
|
|
||||||
|
@ -85,7 +81,7 @@ modes, "switch" and "hub", let the tinc daemons work together to form a virtual
|
||||||
Ethernet network switch or hub.
|
Ethernet network switch or hub.
|
||||||
|
|
||||||
Normally, when started tinc will detach and run in the background. In a native
|
Normally, when started tinc will detach and run in the background. In a native
|
||||||
Windows environment this means tinc will intall itself as a service, which will
|
Windows environment this means tinc will install itself as a service, which will
|
||||||
restart after reboots. To prevent tinc from detaching or running as a service,
|
restart after reboots. To prevent tinc from detaching or running as a service,
|
||||||
use the -D option.
|
use the -D option.
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
Quick how-o cross compile tinc for android (done from $HOME/android/):
|
Quick how-to cross compile tinc for Android (done from $HOME/android/):
|
||||||
|
|
||||||
|
- Download Android NDK and setup local ARM toolchain:
|
||||||
|
|
||||||
- Download android NDK and setup local ARM toolchain:
|
|
||||||
wget http://dl.google.com/android/ndk/android-ndk-r8b-linux-x86.tar.bz2
|
wget http://dl.google.com/android/ndk/android-ndk-r8b-linux-x86.tar.bz2
|
||||||
tar xfj android-ndk-r8b-linux-x86.tar.bz2
|
tar xfj android-ndk-r8b-linux-x86.tar.bz2
|
||||||
./android-ndk-r8b/build/tools/make-standalone-toolchain.sh --platform=android-5 --install-dir=/tmp/my-android-toolchain
|
./android-ndk-r8b/build/tools/make-standalone-toolchain.sh --platform=android-5 --install-dir=/tmp/my-android-toolchain
|
||||||
|
|
||||||
- Download and cross-compile openSSL for ARM:
|
- Download and cross-compile OpenSSL for ARM:
|
||||||
|
|
||||||
wget http://www.openssl.org/source/openssl-1.0.1c.tar.gz
|
wget http://www.openssl.org/source/openssl-1.0.1c.tar.gz
|
||||||
tar xfz openssl-1.0.1c.tar.gz
|
tar xfz openssl-1.0.1c.tar.gz
|
||||||
cd openssl-1.0.1c
|
cd openssl-1.0.1c
|
||||||
|
@ -13,6 +15,7 @@ cd openssl-1.0.1c
|
||||||
make CC=/tmp/my-android-toolchain/bin/arm-linux-androideabi-gcc AR="/tmp/my-android-toolchain/bin/arm-linux-androideabi-ar r" RANLIB=/tmp/my-android-toolchain/bin/arm-linux-androideabi-ranlib
|
make CC=/tmp/my-android-toolchain/bin/arm-linux-androideabi-gcc AR="/tmp/my-android-toolchain/bin/arm-linux-androideabi-ar r" RANLIB=/tmp/my-android-toolchain/bin/arm-linux-androideabi-ranlib
|
||||||
|
|
||||||
- Clone and cross-compile tinc:
|
- Clone and cross-compile tinc:
|
||||||
|
|
||||||
git clone git://tinc-vpn.org/tinc
|
git clone git://tinc-vpn.org/tinc
|
||||||
cd tinc
|
cd tinc
|
||||||
autoreconf -fsi
|
autoreconf -fsi
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
Before you can start compiling tinc from a fresh git clone, you have
|
Before you can start compiling tinc from a fresh git clone, you have
|
||||||
to install the very latest versions of the following packages:
|
to install the very latest versions of the following packages:
|
||||||
|
|
||||||
- OpenSSL
|
- LibreSSL or OpenSSL
|
||||||
- zlib
|
- zlib
|
||||||
- lzo
|
- LZO
|
||||||
- GCC
|
- GCC
|
||||||
- automake
|
- automake
|
||||||
- autoconf
|
- autoconf
|
||||||
|
|
16
THANKS
16
THANKS
|
@ -14,6 +14,7 @@ We would like to thank the following people for their contributions to tinc:
|
||||||
* Cheng LI
|
* Cheng LI
|
||||||
* Cris van Pelt
|
* Cris van Pelt
|
||||||
* Darius Jahandarie
|
* Darius Jahandarie
|
||||||
|
* Dato Simó
|
||||||
* David Pflug
|
* David Pflug
|
||||||
* Delf Eldkraft
|
* Delf Eldkraft
|
||||||
* Dennis Joachimsthaler
|
* Dennis Joachimsthaler
|
||||||
|
@ -22,6 +23,8 @@ We would like to thank the following people for their contributions to tinc:
|
||||||
* Erik Tews
|
* Erik Tews
|
||||||
* Etienne Dechamps
|
* Etienne Dechamps
|
||||||
* Florent Clairambault
|
* Florent Clairambault
|
||||||
|
* Florian Klink
|
||||||
|
* Florian Weik
|
||||||
* Flynn Marquardt
|
* Flynn Marquardt
|
||||||
* Franz Pletz
|
* Franz Pletz
|
||||||
* Gary Kessler and Claudia Gonzalez
|
* Gary Kessler and Claudia Gonzalez
|
||||||
|
@ -45,6 +48,7 @@ We would like to thank the following people for their contributions to tinc:
|
||||||
* Loïc Dachary
|
* Loïc Dachary
|
||||||
* Loïc Grenié
|
* Loïc Grenié
|
||||||
* Lubomír Bulej
|
* Lubomír Bulej
|
||||||
|
* LunarShaddow
|
||||||
* Mads Kiilerich
|
* Mads Kiilerich
|
||||||
* Marc A. Lehmann
|
* Marc A. Lehmann
|
||||||
* Mark Glines
|
* Mark Glines
|
||||||
|
@ -53,17 +57,22 @@ We would like to thank the following people for their contributions to tinc:
|
||||||
* Martin Kihlgren
|
* Martin Kihlgren
|
||||||
* Martin Schobert
|
* Martin Schobert
|
||||||
* Martin Schürrer
|
* Martin Schürrer
|
||||||
|
* Martin Weinelt
|
||||||
* Matias Carrasco
|
* Matias Carrasco
|
||||||
* Max Rijevski
|
* Max Rijevski
|
||||||
* Menno Smits
|
* Menno Smits
|
||||||
* Mesar Hameed
|
* Mesar Hameed
|
||||||
* Michael Tokarev
|
* Michael Tokarev
|
||||||
* Miles Nordin
|
* Miles Nordin
|
||||||
|
* Nathan Stratton Treadway
|
||||||
* Murat Donmez
|
* Murat Donmez
|
||||||
* Nick Hibma
|
* Nick Hibma
|
||||||
* Nick Patavalis
|
* Nick Patavalis
|
||||||
* Paul Littlefield
|
* Paul Littlefield
|
||||||
* Philipp Babel
|
* Philipp Babel
|
||||||
|
* Pierre Emeriaud
|
||||||
|
* Rafał Leśniak
|
||||||
|
* Rhosyn Celyn
|
||||||
* Robert van der Meulen
|
* Robert van der Meulen
|
||||||
* Rumko
|
* Rumko
|
||||||
* Sam Bryan
|
* Sam Bryan
|
||||||
|
@ -80,15 +89,18 @@ We would like to thank the following people for their contributions to tinc:
|
||||||
* Tomislav Čohar
|
* Tomislav Čohar
|
||||||
* Tommy Arnkværn
|
* Tommy Arnkværn
|
||||||
* Tonnerre Lombard
|
* Tonnerre Lombard
|
||||||
|
* Ulrich Seifert
|
||||||
* Vil Brekin
|
* Vil Brekin
|
||||||
* Vittorio Gambaletta
|
* Vittorio Gambaletta
|
||||||
* Wessel Dankers
|
* Wessel Dankers
|
||||||
* William A. Kennington III
|
* William A. Kennington III
|
||||||
* William McArthur
|
* William McArthur
|
||||||
* Wouter van Heyst
|
* Wouter van Heyst
|
||||||
|
* xentec
|
||||||
* 戴 鸣
|
* 戴 鸣
|
||||||
|
|
||||||
And everyone we forgot (if we did, please let us know). Thank you!
|
And everyone we forgot (if we did, please let us know). Thank you!
|
||||||
|
|
||||||
Ivo Timmermans
|
---
|
||||||
Guus Sliepen
|
Ivo Timmermans,
|
||||||
|
Guus Sliepen.
|
||||||
|
|
|
@ -5,7 +5,7 @@ _tinc() {
|
||||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||||
opts="-c -d -D -K -n -o -L -R -U --config --no-detach --debug --net --option --mlock --logfile --pidfile --chroot --user --help --version"
|
opts="-c -d -D -K -n -o -L -R -U --config --no-detach --debug --net --option --mlock --logfile --pidfile --chroot --user --help --version"
|
||||||
confvars="Address AddressFamily BindToAddress BindToInterface Broadcast BroadcastSubnet Cipher ClampMSS Compression ConnectTo DecrementTTL Device DeviceStandby DeviceType Digest DirectOnly Ed25519PrivateKeyFile Ed25519PublicKey Ed25519PublicKeyFile ExperimentalProtocol Forwarding GraphDumpFile Hostnames IffOneQueue IndirectData Interface KeyExpire ListenAddress LocalDiscovery MACExpire MACLength MaxOutputBufferSize MaxTimeout Mode MTUInfoInterval Name PMTU PMTUDiscovery PingInterval PingTimeout Port PriorityInheritance PrivateKeyFile ProcessPriority Proxy PublicKeyFile ReplayWindow StrictSubnets Subnet TCPOnly TunnelServer UDPDiscovery UDPDiscoveryKeepaliveInterval UDPDiscoveryInterval UDPDiscoveryTimeout UDPInfoInterval UDPRcvBuf UDPSndBuf UPnP UPnPDiscoverWait UPnPRefreshPeriod VDEGroup VDEPort Weight"
|
confvars="Address AddressFamily BindToAddress BindToInterface Broadcast BroadcastSubnet Cipher ClampMSS Compression ConnectTo DecrementTTL Device DeviceStandby DeviceType Digest DirectOnly Ed25519PrivateKeyFile Ed25519PublicKey Ed25519PublicKeyFile ExperimentalProtocol Forwarding GraphDumpFile Hostnames IffOneQueue IndirectData Interface KeyExpire ListenAddress LocalDiscovery MACExpire MACLength MaxOutputBufferSize MaxTimeout Mode MTUInfoInterval Name PMTU PMTUDiscovery PingInterval PingTimeout Port PriorityInheritance PrivateKeyFile ProcessPriority Proxy PublicKeyFile ReplayWindow StrictSubnets Subnet TCPOnly TunnelServer UDPDiscovery UDPDiscoveryKeepaliveInterval UDPDiscoveryInterval UDPDiscoveryTimeout UDPInfoInterval UDPRcvBuf UDPSndBuf UPnP UPnPDiscoverWait UPnPRefreshPeriod VDEGroup VDEPort Weight"
|
||||||
commands="add connect debug del disconnect dump edit export export-all generate-ed25519-keys generate-keys generate-rsa-keys get help import info init invite join list log network pcap pid purge reload restart retry set start stop top version"
|
commands="add connect debug del disconnect dump edit export export-all generate-ed25519-keys generate-keys generate-rsa-keys get help import info init invite join list log network pcap pid purge reload restart retry set sign start stop top verify version"
|
||||||
|
|
||||||
case ${prev} in
|
case ${prev} in
|
||||||
-c|--config)
|
-c|--config)
|
||||||
|
|
82
configure.ac
82
configure.ac
|
@ -1,15 +1,13 @@
|
||||||
dnl Process this file with autoconf to produce a configure script.
|
dnl Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
AC_PREREQ(2.61)
|
AC_PREREQ(2.61)
|
||||||
AC_CONFIG_MACRO_DIRS([m4])
|
|
||||||
AC_INIT([tinc], m4_esyscmd_s((git describe || echo UNKNOWN) | sed 's/release-//'))
|
AC_INIT([tinc], m4_esyscmd_s((git describe || echo UNKNOWN) | sed 's/release-//'))
|
||||||
AC_CONFIG_SRCDIR([src/tincd.c])
|
AC_CONFIG_SRCDIR([src/tincd.c])
|
||||||
AC_GNU_SOURCE
|
AC_GNU_SOURCE
|
||||||
AM_INIT_AUTOMAKE([std-options subdir-objects -Wall])
|
AM_INIT_AUTOMAKE([std-options subdir-objects nostdinc silent-rules -Wall])
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
AM_PROG_AR
|
|
||||||
LT_INIT
|
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
|
AM_SILENT_RULES([yes])
|
||||||
|
|
||||||
# Enable GNU extensions.
|
# Enable GNU extensions.
|
||||||
# Define this here, not in acconfig's @TOP@ section, since definitions
|
# Define this here, not in acconfig's @TOP@ section, since definitions
|
||||||
|
@ -116,24 +114,6 @@ AC_ARG_ENABLE(tunemu,
|
||||||
[tunemu=false]
|
[tunemu=false]
|
||||||
)
|
)
|
||||||
|
|
||||||
AC_ARG_ENABLE(devel,
|
|
||||||
AS_HELP_STRING([--enable-devel], [enable compiler warnings/errors for developement]),
|
|
||||||
[ AS_IF([test "x$enable_devel" = "xyes"],
|
|
||||||
[ AC_DEFINE(ENABLE_DEVEL, 1, [Support for devel])
|
|
||||||
devel=true
|
|
||||||
],
|
|
||||||
[devel=false])
|
|
||||||
],
|
|
||||||
[devel=false]
|
|
||||||
)
|
|
||||||
|
|
||||||
AC_ARG_WITH(windows2000,
|
|
||||||
AS_HELP_STRING([--with-windows2000], [compile with support for Windows 2000. This disables support for tunneling over existing IPv6 networks.]),
|
|
||||||
[ AS_IF([test "x$with_windows2000" = "xyes"],
|
|
||||||
[AC_DEFINE(WITH_WINDOWS2000, 1, [Compile with support for Windows 2000])])
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
AC_ARG_WITH(systemd,
|
AC_ARG_WITH(systemd,
|
||||||
AS_HELP_STRING([--with-systemd@<:@=DIR@:>@], [install systemd service files @<:@to DIR if specified@:>@]),
|
AS_HELP_STRING([--with-systemd@<:@=DIR@:>@], [install systemd service files @<:@to DIR if specified@:>@]),
|
||||||
[ systemd=true; systemd_path="$with_systemd" ],
|
[ systemd=true; systemd_path="$with_systemd" ],
|
||||||
|
@ -166,15 +146,6 @@ dnl Compiler hardening flags
|
||||||
dnl No -fstack-protector-all because it doesn't work on all platforms or architectures.
|
dnl No -fstack-protector-all because it doesn't work on all platforms or architectures.
|
||||||
|
|
||||||
AC_ARG_ENABLE([hardening], AS_HELP_STRING([--disable-hardening], [disable compiler and linker hardening flags]))
|
AC_ARG_ENABLE([hardening], AS_HELP_STRING([--disable-hardening], [disable compiler and linker hardening flags]))
|
||||||
AS_IF([test "x$enable_devel" = "xyes"],
|
|
||||||
[AX_CHECK_COMPILE_FLAG([-Werror=conditional-uninitialized], [CFLAGS="$CFLAGS -Werror=conditional-uninitialized"])
|
|
||||||
AX_CHECK_COMPILE_FLAG([-Werror=uninitialized], [CFLAGS="$CFLAGS -Werror=uninitialized"])
|
|
||||||
AX_CHECK_COMPILE_FLAG([-Werror=unused-variable], [CFLAGS="$CFLAGS -Werror=unused-variable"])
|
|
||||||
AX_CHECK_COMPILE_FLAG([-Werror=unused-parameter], [CFLAGS="$CFLAGS -Werror=unused-parameter"])
|
|
||||||
AX_CHECK_COMPILE_FLAG([-Werror=missing-field-initializers], [CFLAGS="$CFLAGS -Werror=missing-field-initializers"])
|
|
||||||
AX_CHECK_COMPILE_FLAG([-Werror=missing-variable-declarations], [CFLAGS="$CFLAGS -Werror=missing-variable-declarations"])
|
|
||||||
AX_CHECK_COMPILE_FLAG([-Werror=missing-prototypes], [CFLAGS="$CFLAGS -Werror=missing-prototypes"])
|
|
||||||
])
|
|
||||||
|
|
||||||
AS_IF([test "x$enable_hardening" != "xno"],
|
AS_IF([test "x$enable_hardening" != "xno"],
|
||||||
[AX_CHECK_COMPILE_FLAG([-DFORTIFY_SOURCE=2], [CPPFLAGS="$CPPFLAGS -DFORTIFY_SOURCE=2"])
|
[AX_CHECK_COMPILE_FLAG([-DFORTIFY_SOURCE=2], [CPPFLAGS="$CPPFLAGS -DFORTIFY_SOURCE=2"])
|
||||||
|
@ -210,9 +181,8 @@ dnl AX_CHECK_COMPILE_FLAG([-Wno-cast-qual], [CFLAGS="$CFLAGS -Wno-cast-qual"])
|
||||||
dnl Checks for header files.
|
dnl Checks for header files.
|
||||||
dnl We do this in multiple stages, because unlike Linux all the other operating systems really suck and don't include their own dependencies.
|
dnl We do this in multiple stages, because unlike Linux all the other operating systems really suck and don't include their own dependencies.
|
||||||
|
|
||||||
AC_HEADER_STDC
|
AC_CHECK_HEADERS([syslog.h sys/file.h sys/ioctl.h sys/mman.h sys/param.h sys/resource.h sys/socket.h sys/time.h sys/un.h sys/wait.h netdb.h arpa/inet.h dirent.h getopt.h])
|
||||||
AC_CHECK_HEADERS([stdbool.h syslog.h sys/file.h sys/ioctl.h sys/mman.h sys/param.h sys/resource.h sys/socket.h sys/time.h sys/uio.h sys/un.h sys/wait.h netdb.h arpa/inet.h dirent.h])
|
AC_CHECK_HEADERS([net/if.h net/if_types.h net/ethernet.h net/if_arp.h netinet/in_systm.h netinet/in.h netinet/in6.h netpacket/packet.h],
|
||||||
AC_CHECK_HEADERS([net/if.h net/if_types.h linux/if_tun.h net/if_tun.h net/tun/if_tun.h net/if_tap.h net/tap/if_tap.h net/ethernet.h net/if_arp.h netinet/in_systm.h netinet/in.h netinet/in6.h time.h netpacket/packet.h],
|
|
||||||
[], [], [#include "$srcdir/src/have.h"]
|
[], [], [#include "$srcdir/src/have.h"]
|
||||||
)
|
)
|
||||||
AC_CHECK_HEADERS([netinet/if_ether.h netinet/ip.h netinet/ip6.h resolv.h],
|
AC_CHECK_HEADERS([netinet/if_ether.h netinet/ip.h netinet/ip6.h resolv.h],
|
||||||
|
@ -223,44 +193,46 @@ AC_CHECK_HEADERS([netinet/tcp.h netinet/ip_icmp.h netinet/icmp6.h],
|
||||||
)
|
)
|
||||||
|
|
||||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||||
AC_C_CONST
|
|
||||||
AC_C_VOLATILE
|
|
||||||
AC_TYPE_PID_T
|
|
||||||
AC_TYPE_SIZE_T
|
|
||||||
AC_HEADER_TIME
|
|
||||||
AC_STRUCT_TM
|
|
||||||
|
|
||||||
tinc_ATTRIBUTE(__malloc__)
|
tinc_ATTRIBUTE(__malloc__)
|
||||||
tinc_ATTRIBUTE(__warn_unused_result__)
|
tinc_ATTRIBUTE(__warn_unused_result__)
|
||||||
|
|
||||||
AC_CHECK_TYPES([socklen_t, struct ether_header, struct arphdr, struct ether_arp, struct in_addr, struct addrinfo, struct ip, struct icmp, struct in6_addr, struct sockaddr_in6, struct ip6_hdr, struct icmp6_hdr, struct nd_neighbor_solicit, struct nd_opt_hdr], , ,
|
AC_CHECK_TYPES([struct ether_header, struct arphdr, struct ether_arp, struct ip, struct icmp, struct ip6_hdr, struct icmp6_hdr, struct nd_neighbor_solicit, struct nd_opt_hdr], , ,
|
||||||
[#include "$srcdir/src/have.h"]
|
[#include "$srcdir/src/have.h"]
|
||||||
)
|
)
|
||||||
|
|
||||||
dnl Checks for library functions.
|
dnl Checks for library functions.
|
||||||
AC_TYPE_SIGNAL
|
AC_TYPE_SIGNAL
|
||||||
AC_CHECK_FUNCS([asprintf daemon fchmod flock ftime fork get_current_dir_name gettimeofday mlockall putenv random recvmmsg select strdup strerror strsignal strtol system time usleep unsetenv vsyslog writev],
|
AC_CHECK_FUNCS([asprintf daemon fchmod flock ftime fork gettimeofday mlockall putenv recvmmsg strsignal nanosleep unsetenv vsyslog devname fdevname],
|
||||||
[], [], [#include "$srcdir/src/have.h"]
|
[], [], [#include "$srcdir/src/have.h"]
|
||||||
)
|
)
|
||||||
|
|
||||||
dnl Support for SunOS
|
AC_CHECK_FUNC(getopt_long, [getopt=true; AC_DEFINE(HAVE_GETOPT_LONG, 1, [getopt_long()])], [getopt=false])
|
||||||
|
AM_CONDITIONAL(GETOPT, test "$getopt" = true)
|
||||||
AC_CHECK_FUNC(socket, [], [
|
|
||||||
AC_CHECK_LIB(socket, connect)
|
|
||||||
])
|
|
||||||
AC_CHECK_FUNC(gethostbyname, [], [
|
|
||||||
AC_CHECK_LIB(nsl, gethostbyname)
|
|
||||||
])
|
|
||||||
|
|
||||||
AC_CHECK_DECLS([freeaddrinfo, gai_strerror, getaddrinfo, getnameinfo],
|
|
||||||
[], [], [#include "$srcdir/src/have.h"]
|
|
||||||
)
|
|
||||||
|
|
||||||
AC_CHECK_DECLS([res_init], [AC_CHECK_LIB(resolv, res_init)], [], [
|
AC_CHECK_DECLS([res_init], [AC_CHECK_LIB(resolv, res_init)], [], [
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <resolv.h>
|
#include <resolv.h>
|
||||||
])
|
])
|
||||||
|
|
||||||
|
dnl Operating system specific checks
|
||||||
|
case $host_os in
|
||||||
|
*linux*)
|
||||||
|
AC_CHECK_HEADERS([linux/if_tun.h],
|
||||||
|
[], [AC_MSG_ERROR([Required header file missng])], [#include "$srcdir/src/have.h"]
|
||||||
|
)
|
||||||
|
;;
|
||||||
|
*bsd*|*dragonfly*|*darwin*)
|
||||||
|
AC_CHECK_HEADERS([net/if_tun.h net/if_utun.h net/tun/if_tun.h net/if_tap.h net/tap/if_tap.h],
|
||||||
|
[], [], [#include "$srcdir/src/have.h"]
|
||||||
|
)
|
||||||
|
;;
|
||||||
|
*solaris*)
|
||||||
|
AC_CHECK_FUNC(socket, [], [AC_CHECK_LIB(socket, connect)])
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
AC_CACHE_SAVE
|
AC_CACHE_SAVE
|
||||||
|
|
||||||
AC_ARG_ENABLE(legacy-protocol,
|
AC_ARG_ENABLE(legacy-protocol,
|
||||||
|
|
|
@ -6,7 +6,7 @@ man_MANS = tincd.8 tinc.8 tinc.conf.5 tinc-gui.8
|
||||||
|
|
||||||
EXTRA_DIST = tincinclude.texi.in tincd.8.in tinc.8.in tinc.conf.5.in tinc-gui.8.in sample-config.tar.gz
|
EXTRA_DIST = tincinclude.texi.in tincd.8.in tinc.8.in tinc.conf.5.in tinc-gui.8.in sample-config.tar.gz
|
||||||
|
|
||||||
CLEANFILES = *.html tincd.8 tinc.8 tinc.conf.5 tinc-gui.8 tincinclude.texi
|
CLEANFILES = *.html tincd.8 tinc.8 tinc.conf.5 tinc-gui.8 tincinclude.texi sample-config.tar.gz
|
||||||
|
|
||||||
# Use `ginstall' in the definition of man_MANS to avoid
|
# Use `ginstall' in the definition of man_MANS to avoid
|
||||||
# confusion with the `install' target. The install rule transforms `ginstall'
|
# confusion with the `install' target. The install rule transforms `ginstall'
|
||||||
|
@ -17,19 +17,19 @@ transform = s/ginstall/install/; @program_transform_name@
|
||||||
# see GNUmakefile and Makefile.maint.
|
# see GNUmakefile and Makefile.maint.
|
||||||
|
|
||||||
sample-config.tar.gz: sample-config
|
sample-config.tar.gz: sample-config
|
||||||
GZIP=$(GZIP_ENV) $(AMTAR) chozf $@ --exclude .svn $<
|
$(AM_V_GEN)GZIP=$(GZIP_ENV) $(AMTAR) chozf $@ --exclude .svn $<
|
||||||
|
|
||||||
tincd.8.html: tincd.8
|
tincd.8.html: tincd.8
|
||||||
w3mman2html $? > $@
|
$(AM_V_GEN)w3mman2html $? > $@
|
||||||
|
|
||||||
tinc.8.html: tinc.8
|
tinc.8.html: tinc.8
|
||||||
w3mman2html $? > $@
|
$(AM_V_GEN)w3mman2html $? > $@
|
||||||
|
|
||||||
tinc-gui.8.html: tinc-gui.8
|
tinc-gui.8.html: tinc-gui.8
|
||||||
w3mman2html $? > $@
|
$(AM_V_GEN)w3mman2html $? > $@
|
||||||
|
|
||||||
tinc.conf.5.html: tinc.conf.5
|
tinc.conf.5.html: tinc.conf.5
|
||||||
w3mman2html $? > $@
|
$(AM_V_GEN)w3mman2html $? > $@
|
||||||
|
|
||||||
substitute = sed \
|
substitute = sed \
|
||||||
-e s,'@PACKAGE\@',"$(PACKAGE)",g \
|
-e s,'@PACKAGE\@',"$(PACKAGE)",g \
|
||||||
|
@ -38,18 +38,18 @@ substitute = sed \
|
||||||
-e s,'@localstatedir\@',"$(localstatedir)",g
|
-e s,'@localstatedir\@',"$(localstatedir)",g
|
||||||
|
|
||||||
tincd.8: tincd.8.in
|
tincd.8: tincd.8.in
|
||||||
$(substitute) $? > $@
|
$(AM_V_GEN)$(substitute) $? > $@
|
||||||
|
|
||||||
tinc.8: tinc.8.in
|
tinc.8: tinc.8.in
|
||||||
$(substitute) $? > $@
|
$(AM_V_GEN)$(substitute) $? > $@
|
||||||
|
|
||||||
tinc-gui.8: tinc-gui.8.in
|
tinc-gui.8: tinc-gui.8.in
|
||||||
$(substitute) $? > $@
|
$(AM_V_GEN)$(substitute) $? > $@
|
||||||
|
|
||||||
tinc.conf.5: tinc.conf.5.in
|
tinc.conf.5: tinc.conf.5.in
|
||||||
$(substitute) $? > $@
|
$(AM_V_GEN)$(substitute) $? > $@
|
||||||
|
|
||||||
tincinclude.texi: tincinclude.texi.in
|
tincinclude.texi: tincinclude.texi.in
|
||||||
$(substitute) $? > $@
|
$(AM_V_GEN)$(substitute) $? > $@
|
||||||
|
|
||||||
tinc.texi: tincinclude.texi
|
tinc.texi: tincinclude.texi
|
||||||
|
|
|
@ -230,6 +230,30 @@ unknown and obsolete configuration variables, wrong public and/or private keys,
|
||||||
When problems are found, this will be printed on a line with WARNING or ERROR in front of it.
|
When problems are found, this will be printed on a line with WARNING or ERROR in front of it.
|
||||||
Most problems must be corrected by the user itself, however in some cases (like file permissions and missing public keys),
|
Most problems must be corrected by the user itself, however in some cases (like file permissions and missing public keys),
|
||||||
tinc will ask if it should fix the problem.
|
tinc will ask if it should fix the problem.
|
||||||
|
.It sign Op Ar filename
|
||||||
|
Sign a file with the local node's private key.
|
||||||
|
If no
|
||||||
|
.Ar filename
|
||||||
|
is given, the file is read from standard input.
|
||||||
|
The signed file is written to standard output.
|
||||||
|
.It verify Ar name Op Ar filename
|
||||||
|
Check the signature of a file against a node's public key.
|
||||||
|
The
|
||||||
|
.Ar name
|
||||||
|
of the node must be given,
|
||||||
|
or can be
|
||||||
|
.Li .
|
||||||
|
to check against the local node's public key, or
|
||||||
|
.Li *
|
||||||
|
to allow a signature from any node whose public key is known.
|
||||||
|
If no
|
||||||
|
.Ar filename
|
||||||
|
is given, the file is read from standard input.
|
||||||
|
If the verification is succesful,
|
||||||
|
a copy of the input with the signature removed is written to standard output,
|
||||||
|
and the exit code will be zero.
|
||||||
|
If the verification failed,
|
||||||
|
nothing will be written to standard output, and the exit code will be non-zero.
|
||||||
.El
|
.El
|
||||||
.Sh EXAMPLES
|
.Sh EXAMPLES
|
||||||
Examples of some commands:
|
Examples of some commands:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
.Dd 2014-01-29
|
.Dd 2016-04-11
|
||||||
.Dt TINC.CONF 5
|
.Dt TINC.CONF 5
|
||||||
.\" Manual page created by:
|
.\" Manual page created by:
|
||||||
.\" Ivo Timmermans
|
.\" Ivo Timmermans
|
||||||
|
@ -42,7 +42,7 @@ the configuration file should be
|
||||||
and the host configuration files are now expected to be in
|
and the host configuration files are now expected to be in
|
||||||
.Pa @sysconfdir@/tinc/hosts/ .
|
.Pa @sysconfdir@/tinc/hosts/ .
|
||||||
.Sh NAMES
|
.Sh NAMES
|
||||||
Each tinc daemon should have a name that is unique in the network which it will be part of.
|
Each tinc daemon must have a name that is unique in the network which it will be part of.
|
||||||
The name will be used by other tinc daemons for identification.
|
The name will be used by other tinc daemons for identification.
|
||||||
The name has to be declared in the
|
The name has to be declared in the
|
||||||
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf
|
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf
|
||||||
|
@ -266,6 +266,10 @@ Tinc will expect packets read from the virtual network device
|
||||||
to start with a four byte header containing the address family,
|
to start with a four byte header containing the address family,
|
||||||
followed by an IP header.
|
followed by an IP header.
|
||||||
This mode should support both IPv4 and IPv6 packets.
|
This mode should support both IPv4 and IPv6 packets.
|
||||||
|
.It utun Pq OS X
|
||||||
|
Set type to utun.
|
||||||
|
This is only supported on OS X version 10.6.8 and higher, but doesn't require the tuntaposx module.
|
||||||
|
This mode should support both IPv4 and IPv6 packets.
|
||||||
.It tap Pq BSD and Linux
|
.It tap Pq BSD and Linux
|
||||||
Set type to tap.
|
Set type to tap.
|
||||||
Tinc will expect packets read from the virtual network device
|
Tinc will expect packets read from the virtual network device
|
||||||
|
@ -551,7 +555,7 @@ variables can be specified, in which case each address will be tried until a wor
|
||||||
connection has been established.
|
connection has been established.
|
||||||
.It Va Cipher Li = Ar cipher Pq blowfish
|
.It Va Cipher Li = Ar cipher Pq blowfish
|
||||||
The symmetric cipher algorithm used to encrypt UDP packets.
|
The symmetric cipher algorithm used to encrypt UDP packets.
|
||||||
Any cipher supported by OpenSSL is recognised.
|
Any cipher supported by LibreSSL or OpenSSL is recognised.
|
||||||
Furthermore, specifying
|
Furthermore, specifying
|
||||||
.Qq none
|
.Qq none
|
||||||
will turn off packet encryption.
|
will turn off packet encryption.
|
||||||
|
@ -568,7 +572,7 @@ Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib),
|
||||||
10 (fast lzo) and 11 (best lzo).
|
10 (fast lzo) and 11 (best lzo).
|
||||||
.It Va Digest Li = Ar digest Pq sha1
|
.It Va Digest Li = Ar digest Pq sha1
|
||||||
The digest algorithm used to authenticate UDP packets.
|
The digest algorithm used to authenticate UDP packets.
|
||||||
Any digest supported by OpenSSL is recognised.
|
Any digest supported by LibreSSL or OpenSSL is recognised.
|
||||||
Furthermore, specifying
|
Furthermore, specifying
|
||||||
.Qq none
|
.Qq none
|
||||||
will turn off packet authentication.
|
will turn off packet authentication.
|
||||||
|
@ -663,10 +667,18 @@ forwarding packets.
|
||||||
.Sh SCRIPTS
|
.Sh SCRIPTS
|
||||||
Apart from reading the server and host configuration files,
|
Apart from reading the server and host configuration files,
|
||||||
tinc can also run scripts at certain moments.
|
tinc can also run scripts at certain moments.
|
||||||
Under Windows (not Cygwin), the scripts should have the extension
|
Below is a list of filenames of scripts and a description of when they are run.
|
||||||
|
A script is only run if it exists and if it is executable.
|
||||||
|
.Pp
|
||||||
|
Scripts are run synchronously;
|
||||||
|
this means that tinc will temporarily stop processing packets until the called script finishes executing.
|
||||||
|
This guarantees that scripts will execute in the exact same order as the events that trigger them.
|
||||||
|
If you need to run commands asynchronously, you have to ensure yourself that they are being run in the background.
|
||||||
|
.Pp
|
||||||
|
Under Windows (not Cygwin), the scripts must have the extension
|
||||||
.Pa .bat
|
.Pa .bat
|
||||||
or
|
or
|
||||||
.Pa cmd .
|
.Pa .cmd .
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up
|
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up
|
||||||
This is the most important script.
|
This is the most important script.
|
||||||
|
@ -675,6 +687,7 @@ If it is present it will be executed right after the tinc daemon has been starte
|
||||||
is used).
|
is used).
|
||||||
It should be used to set up the corresponding network interface,
|
It should be used to set up the corresponding network interface,
|
||||||
but can also be used to start other things.
|
but can also be used to start other things.
|
||||||
|
.Pp
|
||||||
Under Windows you can use the Network Connections control panel instead of creating this script.
|
Under Windows you can use the Network Connections control panel instead of creating this script.
|
||||||
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-down
|
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-down
|
||||||
This script is started right before the tinc daemon quits (or when the last node becomes unreachable if
|
This script is started right before the tinc daemon quits (or when the last node becomes unreachable if
|
||||||
|
@ -772,7 +785,7 @@ its connection to the virtual network device.
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr tincd 8 ,
|
.Xr tincd 8 ,
|
||||||
.Xr tinc 8 ,
|
.Xr tinc 8 ,
|
||||||
.Pa http://www.tinc-vpn.org/ ,
|
.Pa https://www.tinc-vpn.org/ ,
|
||||||
.Pa http://www.tldp.org/LDP/nag2/ .
|
.Pa http://www.tldp.org/LDP/nag2/ .
|
||||||
.Pp
|
.Pp
|
||||||
The full documentation for
|
The full documentation for
|
||||||
|
|
291
doc/tinc.texi
291
doc/tinc.texi
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
This is the info manual for @value{PACKAGE} version @value{VERSION}, a Virtual Private Network daemon.
|
This is the info manual for @value{PACKAGE} version @value{VERSION}, a Virtual Private Network daemon.
|
||||||
|
|
||||||
Copyright @copyright{} 1998-2015 Ivo Timmermans,
|
Copyright @copyright{} 1998-2016 Ivo Timmermans,
|
||||||
Guus Sliepen <guus@@tinc-vpn.org> and
|
Guus Sliepen <guus@@tinc-vpn.org> and
|
||||||
Wessel Dankers <wsl@@tinc-vpn.org>.
|
Wessel Dankers <wsl@@tinc-vpn.org>.
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ permission notice identical to this one.
|
||||||
@vskip 0pt plus 1filll
|
@vskip 0pt plus 1filll
|
||||||
This is the info manual for @value{PACKAGE} version @value{VERSION}, a Virtual Private Network daemon.
|
This is the info manual for @value{PACKAGE} version @value{VERSION}, a Virtual Private Network daemon.
|
||||||
|
|
||||||
Copyright @copyright{} 1998-2015 Ivo Timmermans,
|
Copyright @copyright{} 1998-2016 Ivo Timmermans,
|
||||||
Guus Sliepen <guus@@tinc-vpn.org> and
|
Guus Sliepen <guus@@tinc-vpn.org> and
|
||||||
Wessel Dankers <wsl@@tinc-vpn.org>.
|
Wessel Dankers <wsl@@tinc-vpn.org>.
|
||||||
|
|
||||||
|
@ -70,6 +70,7 @@ permission notice identical to this one.
|
||||||
* Configuration::
|
* Configuration::
|
||||||
* Running tinc::
|
* Running tinc::
|
||||||
* Controlling tinc::
|
* Controlling tinc::
|
||||||
|
* Invitations::
|
||||||
* Technical information::
|
* Technical information::
|
||||||
* Platform specific information::
|
* Platform specific information::
|
||||||
* About us::
|
* About us::
|
||||||
|
@ -191,7 +192,7 @@ packets.
|
||||||
@cindex release
|
@cindex release
|
||||||
For an up to date list of supported platforms, please check the list on
|
For an up to date list of supported platforms, please check the list on
|
||||||
our website:
|
our website:
|
||||||
@uref{http://www.tinc-vpn.org/platforms/}.
|
@uref{https://www.tinc-vpn.org/platforms/}.
|
||||||
|
|
||||||
@c
|
@c
|
||||||
@c
|
@c
|
||||||
|
@ -273,12 +274,7 @@ The tap driver can be loaded with @code{kldload if_tap}, or by adding @code{if_t
|
||||||
@node Configuration of OpenBSD kernels
|
@node Configuration of OpenBSD kernels
|
||||||
@subsection Configuration of OpenBSD kernels
|
@subsection Configuration of OpenBSD kernels
|
||||||
|
|
||||||
For OpenBSD version 2.9 and higher,
|
Recent versions of OpenBSD come with both tun and tap devices enabled in the default kernel configuration.
|
||||||
the tun driver is included in the default kernel configuration.
|
|
||||||
There is also a kernel patch from @uref{http://diehard.n-r-g.com/stuff/openbsd/}
|
|
||||||
which adds a tap device to OpenBSD which should work with tinc,
|
|
||||||
but with recent versions of OpenBSD,
|
|
||||||
a tun device can act as a tap device by setting the link0 option with ifconfig.
|
|
||||||
|
|
||||||
|
|
||||||
@c ==================================================================
|
@c ==================================================================
|
||||||
|
@ -298,7 +294,7 @@ Tunneling IPv6 may not work on NetBSD's tun device.
|
||||||
For Solaris 8 (SunOS 5.8) and higher,
|
For Solaris 8 (SunOS 5.8) and higher,
|
||||||
the tun driver may or may not be included in the default kernel configuration.
|
the tun driver may or may not be included in the default kernel configuration.
|
||||||
If it isn't, the source can be downloaded from @uref{http://vtun.sourceforge.net/tun/}.
|
If it isn't, the source can be downloaded from @uref{http://vtun.sourceforge.net/tun/}.
|
||||||
For x86 and sparc64 architectures, precompiled versions can be found at @uref{http://www.monkey.org/~dugsong/fragroute/}.
|
For x86 and sparc64 architectures, precompiled versions can be found at @uref{https://www.monkey.org/~dugsong/fragroute/}.
|
||||||
If the @file{net/if_tun.h} header file is missing, install it from the source package.
|
If the @file{net/if_tun.h} header file is missing, install it from the source package.
|
||||||
|
|
||||||
|
|
||||||
|
@ -307,15 +303,14 @@ If the @file{net/if_tun.h} header file is missing, install it from the source pa
|
||||||
@subsection Configuration of Darwin (MacOS/X) kernels
|
@subsection Configuration of Darwin (MacOS/X) kernels
|
||||||
|
|
||||||
Tinc on Darwin relies on a tunnel driver for its data acquisition from the kernel.
|
Tinc on Darwin relies on a tunnel driver for its data acquisition from the kernel.
|
||||||
Tinc supports either the driver from @uref{http://tuntaposx.sourceforge.net/},
|
OS X version 10.6.8 and later have a built-in tun driver called "utun".
|
||||||
|
Tinc also supports the driver from @uref{http://tuntaposx.sourceforge.net/},
|
||||||
which supports both tun and tap style devices,
|
which supports both tun and tap style devices,
|
||||||
and also the driver from from @uref{http://chrisp.de/en/projects/tunnel.html}.
|
|
||||||
The former driver is recommended.
|
|
||||||
The tunnel driver must be loaded before starting tinc with the following command:
|
|
||||||
|
|
||||||
@example
|
By default, tinc expects the tuntaposx driver to be installed.
|
||||||
kmodload tunnel
|
To use the utun driver, set add @code{Device = utunX} to @file{tinc.conf},
|
||||||
@end example
|
where X is the desired number for the utun interface.
|
||||||
|
You can also omit the number, in which case the first free number will be chosen.
|
||||||
|
|
||||||
|
|
||||||
@c ==================================================================
|
@c ==================================================================
|
||||||
|
@ -323,7 +318,7 @@ kmodload tunnel
|
||||||
@subsection Configuration of Windows
|
@subsection Configuration of Windows
|
||||||
|
|
||||||
You will need to install the latest TAP-Win32 driver from OpenVPN.
|
You will need to install the latest TAP-Win32 driver from OpenVPN.
|
||||||
You can download it from @uref{http://openvpn.sourceforge.net}.
|
You can download it from @uref{https://openvpn.net/index.php/open-source/downloads.html}.
|
||||||
Using the Network Connections control panel,
|
Using the Network Connections control panel,
|
||||||
configure the TAP-Win32 network interface in the same way as you would do from the tinc-up script,
|
configure the TAP-Win32 network interface in the same way as you would do from the tinc-up script,
|
||||||
as explained in the rest of the documentation.
|
as explained in the rest of the documentation.
|
||||||
|
@ -335,13 +330,13 @@ as explained in the rest of the documentation.
|
||||||
|
|
||||||
@cindex requirements
|
@cindex requirements
|
||||||
@cindex libraries
|
@cindex libraries
|
||||||
Before you can configure or build tinc, you need to have the OpenSSL, zlib,
|
Before you can configure or build tinc, you need to have the LibreSSL or OpenSSL, zlib,
|
||||||
lzo, curses and readline libraries installed on your system. If you try to
|
lzo, curses and readline libraries installed on your system. If you try to
|
||||||
configure tinc without having them installed, configure will give you an error
|
configure tinc without having them installed, configure will give you an error
|
||||||
message, and stop.
|
message, and stop.
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* OpenSSL::
|
* LibreSSL/OpenSSL::
|
||||||
* zlib::
|
* zlib::
|
||||||
* lzo::
|
* lzo::
|
||||||
* libcurses::
|
* libcurses::
|
||||||
|
@ -350,12 +345,13 @@ message, and stop.
|
||||||
|
|
||||||
|
|
||||||
@c ==================================================================
|
@c ==================================================================
|
||||||
@node OpenSSL
|
@node LibreSSL/OpenSSL
|
||||||
@subsection OpenSSL
|
@subsection LibreSSL/OpenSSL
|
||||||
|
|
||||||
|
@cindex LibreSSL
|
||||||
@cindex OpenSSL
|
@cindex OpenSSL
|
||||||
For all cryptography-related functions, tinc uses the functions provided
|
For all cryptography-related functions, tinc uses the functions provided
|
||||||
by the OpenSSL library.
|
by the LibreSSL or the OpenSSL library.
|
||||||
|
|
||||||
If this library is not installed, you wil get an error when configuring
|
If this library is not installed, you wil get an error when configuring
|
||||||
tinc for build. Support for running tinc with other cryptographic libraries
|
tinc for build. Support for running tinc with other cryptographic libraries
|
||||||
|
@ -365,21 +361,23 @@ You can use your operating system's package manager to install this if
|
||||||
available. Make sure you install the development AND runtime versions
|
available. Make sure you install the development AND runtime versions
|
||||||
of this package.
|
of this package.
|
||||||
|
|
||||||
If you have to install OpenSSL manually, you can get the source code
|
If your operating system comes neither with LibreSSL or OpenSSL, you have to
|
||||||
from @url{http://www.openssl.org/}. Instructions on how to configure,
|
install one manually. It is recommended that you get the latest version of
|
||||||
build and install this package are included within the package. Please
|
LibreSSL from @url{http://www.libressl.org/}. Instructions on how to
|
||||||
make sure you build development and runtime libraries (which is the
|
configure, build and install this package are included within the package.
|
||||||
|
Please make sure you build development and runtime libraries (which is the
|
||||||
default).
|
default).
|
||||||
|
|
||||||
If you installed the OpenSSL libraries from source, it may be necessary
|
If you installed the LibreSSL or OpenSSL libraries from source, it may be necessary
|
||||||
to let configure know where they are, by passing configure one of the
|
to let configure know where they are, by passing configure one of the
|
||||||
--with-openssl-* parameters.
|
--with-openssl-* parameters. Note that you even have to use --with-openssl-* if you
|
||||||
|
are using LibreSSL.
|
||||||
|
|
||||||
@example
|
@example
|
||||||
--with-openssl=DIR OpenSSL library and headers prefix
|
--with-openssl=DIR LibreSSL/OpenSSL library and headers prefix
|
||||||
--with-openssl-include=DIR OpenSSL headers directory
|
--with-openssl-include=DIR LibreSSL/OpenSSL headers directory
|
||||||
(Default is OPENSSL_DIR/include)
|
(Default is OPENSSL_DIR/include)
|
||||||
--with-openssl-lib=DIR OpenSSL library directory
|
--with-openssl-lib=DIR LibreSSL/OpenSSL library directory
|
||||||
(Default is OPENSSL_DIR/lib)
|
(Default is OPENSSL_DIR/lib)
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
@ -390,7 +388,7 @@ to let configure know where they are, by passing configure one of the
|
||||||
The complete source code of tinc is covered by the GNU GPL version 2.
|
The complete source code of tinc is covered by the GNU GPL version 2.
|
||||||
Since the license under which OpenSSL is distributed is not directly
|
Since the license under which OpenSSL is distributed is not directly
|
||||||
compatible with the terms of the GNU GPL
|
compatible with the terms of the GNU GPL
|
||||||
@uref{http://www.openssl.org/support/faq.html#LEGAL2}, we
|
@uref{https://www.openssl.org/support/faq.html#LEGAL2}, we
|
||||||
include an exemption to the GPL (see also the file COPYING.README) to allow
|
include an exemption to the GPL (see also the file COPYING.README) to allow
|
||||||
everyone to create a statically or dynamically linked executable:
|
everyone to create a statically or dynamically linked executable:
|
||||||
|
|
||||||
|
@ -406,8 +404,8 @@ we also present the following exemption:
|
||||||
|
|
||||||
@quotation
|
@quotation
|
||||||
Hereby I grant a special exception to the tinc VPN project
|
Hereby I grant a special exception to the tinc VPN project
|
||||||
(http://www.tinc-vpn.org/) to link the LZO library with the OpenSSL library
|
(https://www.tinc-vpn.org/) to link the LZO library with the OpenSSL library
|
||||||
(http://www.openssl.org).
|
(https://www.openssl.org).
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer
|
Markus F.X.J. Oberhumer
|
||||||
@end quotation
|
@end quotation
|
||||||
|
@ -432,7 +430,7 @@ available. Make sure you install the development AND runtime versions
|
||||||
of this package.
|
of this package.
|
||||||
|
|
||||||
If you have to install zlib manually, you can get the source code
|
If you have to install zlib manually, you can get the source code
|
||||||
from @url{http://www.gzip.org/zlib/}. Instructions on how to configure,
|
from @url{http://www.zlib.net/}. Instructions on how to configure,
|
||||||
build and install this package are included within the package. Please
|
build and install this package are included within the package. Please
|
||||||
make sure you build development and runtime libraries (which is the
|
make sure you build development and runtime libraries (which is the
|
||||||
default).
|
default).
|
||||||
|
@ -456,7 +454,7 @@ available. Make sure you install the development AND runtime versions
|
||||||
of this package.
|
of this package.
|
||||||
|
|
||||||
If you have to install lzo manually, you can get the source code
|
If you have to install lzo manually, you can get the source code
|
||||||
from @url{http://www.oberhumer.com/opensource/lzo/}. Instructions on how to configure,
|
from @url{https://www.oberhumer.com/opensource/lzo/}. Instructions on how to configure,
|
||||||
build and install this package are included within the package. Please
|
build and install this package are included within the package. Please
|
||||||
make sure you build development and runtime libraries (which is the
|
make sure you build development and runtime libraries (which is the
|
||||||
default).
|
default).
|
||||||
|
@ -527,9 +525,7 @@ system startup scripts and sample configurations.
|
||||||
If you cannot use one of the precompiled packages, or you want to compile tinc
|
If you cannot use one of the precompiled packages, or you want to compile tinc
|
||||||
for yourself, you can use the source. The source is distributed under
|
for yourself, you can use the source. The source is distributed under
|
||||||
the GNU General Public License (GPL). Download the source from the
|
the GNU General Public License (GPL). Download the source from the
|
||||||
@uref{http://www.tinc-vpn.org/download/, download page}, which has
|
@uref{https://www.tinc-vpn.org/download/, download page}.
|
||||||
the checksums of these files listed; you may wish to check these with
|
|
||||||
md5sum before continuing.
|
|
||||||
|
|
||||||
Tinc comes in a convenient autoconf/automake package, which you can just
|
Tinc comes in a convenient autoconf/automake package, which you can just
|
||||||
treat the same as any other package. Which is just untar it, type
|
treat the same as any other package. Which is just untar it, type
|
||||||
|
@ -566,19 +562,18 @@ The documentation that comes along with your distribution will tell you how to d
|
||||||
@node Darwin (MacOS/X) build environment
|
@node Darwin (MacOS/X) build environment
|
||||||
@subsection Darwin (MacOS/X) build environment
|
@subsection Darwin (MacOS/X) build environment
|
||||||
|
|
||||||
In order to build tinc on Darwin, you need to install the MacOS/X Developer Tools
|
In order to build tinc on Darwin, you need to install Xcode from @uref{https://developer.apple.com/xcode/}.
|
||||||
from @uref{http://developer.apple.com/tools/macosxtools.html} and
|
It might also help to install a recent version of Fink from @uref{http://www.finkproject.org/}.
|
||||||
a recent version of Fink from @uref{http://www.finkproject.org/}.
|
|
||||||
|
|
||||||
After installation use fink to download and install the following packages:
|
You need to download and install LibreSSL (or OpenSSL) and LZO,
|
||||||
autoconf25, automake, dlcompat, m4, openssl, zlib and lzo.
|
either directly from their websites (see @ref{Libraries}) or using Fink.
|
||||||
|
|
||||||
@c ==================================================================
|
@c ==================================================================
|
||||||
@node Cygwin (Windows) build environment
|
@node Cygwin (Windows) build environment
|
||||||
@subsection Cygwin (Windows) build environment
|
@subsection Cygwin (Windows) build environment
|
||||||
|
|
||||||
If Cygwin hasn't already been installed, install it directly from
|
If Cygwin hasn't already been installed, install it directly from
|
||||||
@uref{http://www.cygwin.com/}.
|
@uref{https://www.cygwin.com/}.
|
||||||
|
|
||||||
When tinc is compiled in a Cygwin environment, it can only be run in this environment,
|
When tinc is compiled in a Cygwin environment, it can only be run in this environment,
|
||||||
but all programs, including those started outside the Cygwin environment, will be able to use the VPN.
|
but all programs, including those started outside the Cygwin environment, will be able to use the VPN.
|
||||||
|
@ -589,6 +584,7 @@ It will also support all features.
|
||||||
@subsection MinGW (Windows) build environment
|
@subsection MinGW (Windows) build environment
|
||||||
|
|
||||||
You will need to install the MinGW environment from @uref{http://www.mingw.org}.
|
You will need to install the MinGW environment from @uref{http://www.mingw.org}.
|
||||||
|
You also need to download and install LibreSSL (or OpenSSL) and LZO.
|
||||||
|
|
||||||
When tinc is compiled using MinGW it runs natively under Windows,
|
When tinc is compiled using MinGW it runs natively under Windows,
|
||||||
it is not necessary to keep MinGW installed.
|
it is not necessary to keep MinGW installed.
|
||||||
|
@ -999,6 +995,12 @@ to start with a four byte header containing the address family,
|
||||||
followed by an IP header.
|
followed by an IP header.
|
||||||
This mode should support both IPv4 and IPv6 packets.
|
This mode should support both IPv4 and IPv6 packets.
|
||||||
|
|
||||||
|
@cindex utun
|
||||||
|
@item utun (OS X)
|
||||||
|
Set type to utun.
|
||||||
|
This is only supported on OS X version 10.6.8 and higher, but doesn't require the tuntaposx module.
|
||||||
|
This mode should support both IPv4 and IPv6 packets.
|
||||||
|
|
||||||
@item tap (BSD and Linux)
|
@item tap (BSD and Linux)
|
||||||
Set type to tap.
|
Set type to tap.
|
||||||
Tinc will expect packets read from the virtual network device
|
Tinc will expect packets read from the virtual network device
|
||||||
|
@ -1139,7 +1141,7 @@ until the burst has passed.
|
||||||
@cindex Name
|
@cindex Name
|
||||||
@item Name = <@var{name}> [required]
|
@item Name = <@var{name}> [required]
|
||||||
This is a symbolic name for this connection.
|
This is a symbolic name for this connection.
|
||||||
The name should consist only of alfanumeric and underscore characters (a-z, A-Z, 0-9 and _), and is case sensitive.
|
The name must consist only of alfanumeric and underscore characters (a-z, A-Z, 0-9 and _), and is case sensitive.
|
||||||
|
|
||||||
If Name starts with a $, then the contents of the environment variable that follows will be used.
|
If Name starts with a $, then the contents of the environment variable that follows will be used.
|
||||||
In that case, invalid characters will be converted to underscores.
|
In that case, invalid characters will be converted to underscores.
|
||||||
|
@ -1307,7 +1309,7 @@ tried until a working connection has been established.
|
||||||
@cindex Cipher
|
@cindex Cipher
|
||||||
@item Cipher = <@var{cipher}> (blowfish)
|
@item Cipher = <@var{cipher}> (blowfish)
|
||||||
The symmetric cipher algorithm used to encrypt UDP packets using the legacy protocol.
|
The symmetric cipher algorithm used to encrypt UDP packets using the legacy protocol.
|
||||||
Any cipher supported by OpenSSL is recognized.
|
Any cipher supported by LibreSSL or OpenSSL is recognized.
|
||||||
Furthermore, specifying "none" will turn off packet encryption.
|
Furthermore, specifying "none" will turn off packet encryption.
|
||||||
It is best to use only those ciphers which support CBC mode.
|
It is best to use only those ciphers which support CBC mode.
|
||||||
This option has no effect for connections using the SPTPS protocol, which always use AES-256-CTR.
|
This option has no effect for connections using the SPTPS protocol, which always use AES-256-CTR.
|
||||||
|
@ -1327,7 +1329,7 @@ Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib),
|
||||||
@cindex Digest
|
@cindex Digest
|
||||||
@item Digest = <@var{digest}> (sha1)
|
@item Digest = <@var{digest}> (sha1)
|
||||||
The digest algorithm used to authenticate UDP packets using the legacy protocol.
|
The digest algorithm used to authenticate UDP packets using the legacy protocol.
|
||||||
Any digest supported by OpenSSL is recognized.
|
Any digest supported by LibreSSL or OpenSSL is recognized.
|
||||||
Furthermore, specifying "none" will turn off packet authentication.
|
Furthermore, specifying "none" will turn off packet authentication.
|
||||||
This option has no effect for connections using the SPTPS protocol, which always use HMAC-SHA-256.
|
This option has no effect for connections using the SPTPS protocol, which always use HMAC-SHA-256.
|
||||||
|
|
||||||
|
@ -1402,7 +1404,7 @@ MAC addresses are notated like 0:1a:2b:3c:4d:5e.
|
||||||
Prefixlength is the number of bits set to 1 in the netmask part; for
|
Prefixlength is the number of bits set to 1 in the netmask part; for
|
||||||
example: netmask 255.255.255.0 would become /24, 255.255.252.0 becomes
|
example: netmask 255.255.255.0 would become /24, 255.255.252.0 becomes
|
||||||
/22. This conforms to standard CIDR notation as described in
|
/22. This conforms to standard CIDR notation as described in
|
||||||
@uref{http://www.ietf.org/rfc/rfc1519.txt, RFC1519}
|
@uref{https://www.ietf.org/rfc/rfc1519.txt, RFC1519}
|
||||||
|
|
||||||
A Subnet can be given a weight to indicate its priority over identical Subnets
|
A Subnet can be given a weight to indicate its priority over identical Subnets
|
||||||
owned by different nodes. The default weight is 10. Lower values indicate
|
owned by different nodes. The default weight is 10. Lower values indicate
|
||||||
|
@ -1433,6 +1435,14 @@ connection when broadcasting or forwarding packets.
|
||||||
@cindex scripts
|
@cindex scripts
|
||||||
Apart from reading the server and host configuration files,
|
Apart from reading the server and host configuration files,
|
||||||
tinc can also run scripts at certain moments.
|
tinc can also run scripts at certain moments.
|
||||||
|
Below is a list of filenames of scripts and a description of when they are run.
|
||||||
|
A script is only run if it exists and if it is executable.
|
||||||
|
|
||||||
|
Scripts are run synchronously;
|
||||||
|
this means that tinc will temporarily stop processing packets until the called script finishes executing.
|
||||||
|
This guarantees that scripts will execute in the exact same order as the events that trigger them.
|
||||||
|
If you need to run commands asynchronously, you have to ensure yourself that they are being run in the background.
|
||||||
|
|
||||||
Under Windows (not Cygwin), the scripts should have the extension @file{.bat} or @file{.cmd}.
|
Under Windows (not Cygwin), the scripts should have the extension @file{.bat} or @file{.cmd}.
|
||||||
|
|
||||||
@table @file
|
@table @file
|
||||||
|
@ -1443,6 +1453,7 @@ If it is present it will be executed right after the tinc daemon has been
|
||||||
started and has connected to the virtual network device.
|
started and has connected to the virtual network device.
|
||||||
It should be used to set up the corresponding network interface,
|
It should be used to set up the corresponding network interface,
|
||||||
but can also be used to start other things.
|
but can also be used to start other things.
|
||||||
|
|
||||||
Under Windows you can use the Network Connections control panel instead of creating this script.
|
Under Windows you can use the Network Connections control panel instead of creating this script.
|
||||||
|
|
||||||
@cindex tinc-down
|
@cindex tinc-down
|
||||||
|
@ -2487,6 +2498,23 @@ When problems are found, this will be printed on a line with WARNING or ERROR in
|
||||||
Most problems must be corrected by the user itself, however in some cases (like file permissions and missing public keys),
|
Most problems must be corrected by the user itself, however in some cases (like file permissions and missing public keys),
|
||||||
tinc will ask if it should fix the problem.
|
tinc will ask if it should fix the problem.
|
||||||
|
|
||||||
|
@cindex sign
|
||||||
|
@item sign [@var{filename}]
|
||||||
|
Sign a file with the local node's private key.
|
||||||
|
If no @var{filename} is given, the file is read from standard input.
|
||||||
|
The signed file is written to standard output.
|
||||||
|
|
||||||
|
@cindex verify
|
||||||
|
@item verify @var{name} [@var{filename}]
|
||||||
|
|
||||||
|
Check the signature of a file against a node's public key.
|
||||||
|
The @var{name} of the node must be given,
|
||||||
|
or can be "." to check against the local node's public key,
|
||||||
|
or "*" to allow a signature from any node whose public key is known.
|
||||||
|
If no @var{filename} is given, the file is read from standard input.
|
||||||
|
If the verification is succesful, a copy of the input with the signature removed is written to standard output, and the exit code will be zero.
|
||||||
|
If the verification failed, nothing will be written to standard output, and the exit code will be non-zero.
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@c ==================================================================
|
@c ==================================================================
|
||||||
|
@ -2573,6 +2601,159 @@ Quit.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
|
||||||
|
@c ==================================================================
|
||||||
|
@node Invitations
|
||||||
|
@chapter Invitations
|
||||||
|
|
||||||
|
Invitations are an easy way to add new nodes to an existing VPN. Invitations
|
||||||
|
can be created on an existing node using the @code{tinc invite} command, which
|
||||||
|
generates a relatively short URL which can be given to someone else, who uses
|
||||||
|
the @code{tinc join} command to automatically set up tinc so it can connect to
|
||||||
|
the inviting node. The next sections describe how invitations actually work,
|
||||||
|
and how to further automate the invitations.
|
||||||
|
|
||||||
|
@menu
|
||||||
|
* How invitations work::
|
||||||
|
* Invitation file format::
|
||||||
|
* Writing an invitation-created script::
|
||||||
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
|
@c ==================================================================
|
||||||
|
@node How invitations work
|
||||||
|
@section How invitations work
|
||||||
|
|
||||||
|
When an invitation is created on a node (which from now on we will call the
|
||||||
|
server) using the @code{tinc invite} command, an invitation file is created
|
||||||
|
that contains all the information necessary for the invitee (which we will call
|
||||||
|
the client) to create its configuration files. The invitation file is stays on
|
||||||
|
the server, but a URL is generated that has enough information for the client
|
||||||
|
to contact the server and to retrieve the invitation file. The whole URL is
|
||||||
|
around 80 characters long and looks like this:
|
||||||
|
|
||||||
|
@example
|
||||||
|
server.example.org:12345/cW1NhLHS-1WPFlcFio8ztYHvewTTKYZp8BjEKg3vbMtDz7w4
|
||||||
|
@end example
|
||||||
|
|
||||||
|
It is composed of four parts:
|
||||||
|
|
||||||
|
@example
|
||||||
|
hostname : port / keyhash cookie
|
||||||
|
@end example
|
||||||
|
|
||||||
|
The hostname and port tell the client how to reach the tinc daemon on the server.
|
||||||
|
The part after the slash looks like one blob, but is composed of two parts.
|
||||||
|
The keyhash is the hash of the public key of the server.
|
||||||
|
The cookie is a shared secret that identifies the client to the server.
|
||||||
|
|
||||||
|
When the client connects to the server in order to join the VPN, the client and
|
||||||
|
server will exchange temporary public keys. The client verifies that the hash
|
||||||
|
of the server's public key matches the keyhash from the invitation URL. If
|
||||||
|
not, it will immediately exit with an error. Otherwise, an ECDH exchange will
|
||||||
|
happen so the client and server can communicate privately with each other. The
|
||||||
|
client will then present the cookie to the server. The server uses this to
|
||||||
|
look up the corresponding invitation file it generated earlier. If it exists,
|
||||||
|
it will send the invitation file to the client. The client will also create a
|
||||||
|
permanent public key, and send it to the server. After the exchange is
|
||||||
|
completed, the connection is broken. The server creates a host config file for
|
||||||
|
the client containing the client's permanent public key, and the client creates
|
||||||
|
tinc.conf, host config files and possibly a tinc-up script based on the
|
||||||
|
information in the invitation file.
|
||||||
|
|
||||||
|
It is important that the invitation URL is kept secret until it is used; if
|
||||||
|
another person gets a copy of the invitation URL before the real client runs
|
||||||
|
the @code{tinc join} command, then that other person can try to join the VPN.
|
||||||
|
|
||||||
|
|
||||||
|
@c ==================================================================
|
||||||
|
@node Invitation file format
|
||||||
|
@section Invitation file format
|
||||||
|
|
||||||
|
The contents of an invitation file that is generated by the @code{tinc invite}
|
||||||
|
command looks like this:
|
||||||
|
|
||||||
|
@example
|
||||||
|
Name = client
|
||||||
|
Netname = vpn
|
||||||
|
ConnectTo = server
|
||||||
|
#-------------------------------------#
|
||||||
|
Name = server
|
||||||
|
Ed25519PublicKey = augbnwegoij123587...
|
||||||
|
Address = server.example.com
|
||||||
|
@end example
|
||||||
|
|
||||||
|
The file is basically a concatenation of several host config blocks. Each host
|
||||||
|
config block starts with @code{Name = ...}. Lines that look like @code{#---#}
|
||||||
|
are not important, it just makes it easier for humans to read the file.
|
||||||
|
|
||||||
|
The first host config block is always the one representing the invitee. So the
|
||||||
|
first Name statement determines the name that the invitee will get. From the
|
||||||
|
first block, the @file{tinc.conf} and @file{hosts/client} files will be
|
||||||
|
generated; the @code{tinc join} command on the client will automatically
|
||||||
|
separate statements based on whether they should be in @file{tinc.conf} or in a
|
||||||
|
host config file. Some statements are special and are treated differently:
|
||||||
|
|
||||||
|
@table @asis
|
||||||
|
@item Netname = <@var{netname}>
|
||||||
|
This is a hint to the invitee which netname to use for the VPN. It is used if
|
||||||
|
the invitee did not already specify a netname, and if there is no pre-existing
|
||||||
|
configuration with the same netname.
|
||||||
|
|
||||||
|
@cindex Ifconfig
|
||||||
|
@item Ifconfig = <@var{address}[/@var{netmask}] | dhcp | dhcp6 | slaac>
|
||||||
|
This is a hint for generating a @file{tinc-up} script.
|
||||||
|
If an address is specified, a command will be added to @file{tinc-up} so the VPN interface will be configured to have the given address.
|
||||||
|
If it is the word "dhcp", a command will be added to start a DHCP client on the VPN interface.
|
||||||
|
If it is the word dhcpv6, it will be a DHCPv6 client.
|
||||||
|
If it is "slaac", then it will add commands to enable IPv6 stateless address autoconfiguration.
|
||||||
|
It is also possible to specify a MAC address, in which case a command will be added to set the MAC address of the VPN interface.
|
||||||
|
|
||||||
|
The exact commands added to the @file{tinc-up} script depends on the operating system the client is using.
|
||||||
|
Multiple Ifconfig statements can be specified, however one should only use one Ifconfig statement per address family.
|
||||||
|
|
||||||
|
@cindex Route
|
||||||
|
@item Route = <@var{address}[/@var{netmask}]> [<@var{gateway}>]
|
||||||
|
This is a hint for generating a @file{tinc-up} script.
|
||||||
|
Route statements are similar to Ifconfig statements, but add routes instead of addresses.
|
||||||
|
These only allow IPv4 and IPv6 routes.
|
||||||
|
If no gateway address is specified, the route is directed to the VPN interface.
|
||||||
|
In general, a gateway is only necessary when running tinc in switch mode.
|
||||||
|
@end table
|
||||||
|
|
||||||
|
Subsequent host config blocks are copied verbatim into their respective files
|
||||||
|
in @file{hosts/}. The invitation file generated by @code{tinc invite} will
|
||||||
|
normally only contain two blocks; one for the client and one for the server.
|
||||||
|
|
||||||
|
|
||||||
|
@c ==================================================================
|
||||||
|
@node Writing an invitation-created script
|
||||||
|
@section Writing an invitation-created script
|
||||||
|
|
||||||
|
When an invitation is generated, the "invitation-created" script is called (if
|
||||||
|
it exists) right after the invitation file is written, but before the URL has
|
||||||
|
been written to stdout. This allows one to change the invitation file
|
||||||
|
automatically before the invitation URL is passed to the invitee. Here is an
|
||||||
|
example shell script that aproximately recreates the default invitation file:
|
||||||
|
|
||||||
|
@example
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
cat >$INVITATION_FILE <<EOF
|
||||||
|
Name = $NODE
|
||||||
|
Netname = $NETNAME
|
||||||
|
ConnectTo = $NAME
|
||||||
|
#----------------#
|
||||||
|
EOF
|
||||||
|
|
||||||
|
tinc export >>$INVITATION_FILE
|
||||||
|
@end example
|
||||||
|
|
||||||
|
You can add more ConnectTo statements, and change `tinc export` to `tinc
|
||||||
|
export-all` for example. But you can also use the script to automatically hand
|
||||||
|
out a Subnet to the invitee. Note that the script doesn't have to be a shell script,
|
||||||
|
you can use any language, it just has to be executable.
|
||||||
|
|
||||||
|
|
||||||
@c ==================================================================
|
@c ==================================================================
|
||||||
@node Technical information
|
@node Technical information
|
||||||
@chapter Technical information
|
@chapter Technical information
|
||||||
|
@ -3143,7 +3324,7 @@ eavesdroppers cannot get and cannot change any information at all from the
|
||||||
packets they can intercept. The encryption algorithm and message authentication
|
packets they can intercept. The encryption algorithm and message authentication
|
||||||
algorithm can be changed in the configuration. The length of the message
|
algorithm can be changed in the configuration. The length of the message
|
||||||
authentication codes is also adjustable. The length of the key for the
|
authentication codes is also adjustable. The length of the key for the
|
||||||
encryption algorithm is always the default length used by OpenSSL.
|
encryption algorithm is always the default length used by LibreSSL/OpenSSL.
|
||||||
|
|
||||||
The SPTPS protocol is described in @ref{Simple Peer-to-Peer Security}.
|
The SPTPS protocol is described in @ref{Simple Peer-to-Peer Security}.
|
||||||
For comparison, this is how SPTPS UDP packets look:
|
For comparison, this is how SPTPS UDP packets look:
|
||||||
|
@ -3170,7 +3351,7 @@ this cannot be changed.
|
||||||
In August 2000, we discovered the existence of a security hole in all versions
|
In August 2000, we discovered the existence of a security hole in all versions
|
||||||
of tinc up to and including 1.0pre2. This had to do with the way we exchanged
|
of tinc up to and including 1.0pre2. This had to do with the way we exchanged
|
||||||
keys. Since then, we have been working on a new authentication scheme to make
|
keys. Since then, we have been working on a new authentication scheme to make
|
||||||
tinc as secure as possible. The current version uses the OpenSSL library and
|
tinc as secure as possible. The current version uses the LibreSSL or OpenSSL library and
|
||||||
uses strong authentication with RSA keys.
|
uses strong authentication with RSA keys.
|
||||||
|
|
||||||
On the 29th of December 2001, Jerome Etienne posted a security analysis of tinc
|
On the 29th of December 2001, Jerome Etienne posted a security analysis of tinc
|
||||||
|
@ -3345,14 +3526,14 @@ Adding routes to IPv6 subnets:
|
||||||
@section Contact information
|
@section Contact information
|
||||||
|
|
||||||
@cindex website
|
@cindex website
|
||||||
Tinc's website is at @url{http://www.tinc-vpn.org/},
|
Tinc's website is at @url{https://www.tinc-vpn.org/},
|
||||||
this server is located in the Netherlands.
|
this server is located in the Netherlands.
|
||||||
|
|
||||||
@cindex IRC
|
@cindex IRC
|
||||||
We have an IRC channel on the FreeNode and OFTC IRC networks. Connect to
|
We have an IRC channel on the FreeNode and OFTC IRC networks. Connect to
|
||||||
@uref{http://www.freenode.net/, irc.freenode.net}
|
@uref{https://freenode.net/, irc.freenode.net}
|
||||||
or
|
or
|
||||||
@uref{http://www.oftc.net/, irc.oftc.net}
|
@uref{https://www.oftc.net/, irc.oftc.net}
|
||||||
and join channel #tinc.
|
and join channel #tinc.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -191,7 +191,7 @@ A lot, especially security auditing.
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr tinc 8 ,
|
.Xr tinc 8 ,
|
||||||
.Xr tinc.conf 5 ,
|
.Xr tinc.conf 5 ,
|
||||||
.Pa http://www.tinc-vpn.org/ ,
|
.Pa https://www.tinc-vpn.org/ ,
|
||||||
.Pa http://www.cabal.org/ .
|
.Pa http://www.cabal.org/ .
|
||||||
.Pp
|
.Pp
|
||||||
The full documentation for tinc is maintained as a Texinfo manual.
|
The full documentation for tinc is maintained as a Texinfo manual.
|
||||||
|
|
330
gui/tinc-gui
330
gui/tinc-gui
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python2
|
||||||
|
|
||||||
# tinc-gui -- GUI for controlling a running tincd
|
# tinc-gui -- GUI for controlling a running tincd
|
||||||
# Copyright (C) 2009-2014 Guus Sliepen <guus@tinc-vpn.org>
|
# Copyright (C) 2009-2014 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
@ -20,11 +20,12 @@
|
||||||
|
|
||||||
import string
|
import string
|
||||||
import socket
|
import socket
|
||||||
import wx
|
|
||||||
import sys
|
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import time
|
import time
|
||||||
|
from argparse import ArgumentParser
|
||||||
|
|
||||||
|
import wx
|
||||||
from wx.lib.mixins.listctrl import ColumnSorterMixin
|
from wx.lib.mixins.listctrl import ColumnSorterMixin
|
||||||
from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin
|
from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin
|
||||||
|
|
||||||
|
@ -32,7 +33,6 @@ if platform.system() == 'Windows':
|
||||||
import _winreg
|
import _winreg
|
||||||
|
|
||||||
# Classes to interface with a running tinc daemon
|
# Classes to interface with a running tinc daemon
|
||||||
|
|
||||||
REQ_STOP = 0
|
REQ_STOP = 0
|
||||||
REQ_RELOAD = 1
|
REQ_RELOAD = 1
|
||||||
REQ_RESTART = 2
|
REQ_RESTART = 2
|
||||||
|
@ -51,65 +51,120 @@ ID = 0
|
||||||
ACK = 4
|
ACK = 4
|
||||||
CONTROL = 18
|
CONTROL = 18
|
||||||
|
|
||||||
class Node:
|
|
||||||
def parse(self, args):
|
class Node(object):
|
||||||
|
def __init__(self, args):
|
||||||
self.name = args[0]
|
self.name = args[0]
|
||||||
self.address = args[1]
|
self.id = args[1]
|
||||||
self.port = args[3]
|
|
||||||
self.cipher = int(args[4])
|
self.address = args[2]
|
||||||
self.digest = int(args[5])
|
self.port = args[4]
|
||||||
self.maclength = int(args[6])
|
|
||||||
self.compression = int(args[7])
|
self.cipher = int(args[5])
|
||||||
self.options = int(args[8], 0x10)
|
self.digest = int(args[6])
|
||||||
self.status = int(args[9], 0x10)
|
self.maclength = int(args[7])
|
||||||
self.nexthop = args[10]
|
|
||||||
self.via = args[11]
|
self.compression = int(args[8])
|
||||||
self.distance = int(args[12])
|
self.options = int(args[9], 0x10)
|
||||||
self.pmtu = int(args[13])
|
self.status = int(args[10], 0x10)
|
||||||
self.minmtu = int(args[14])
|
|
||||||
self.maxmtu = int(args[15])
|
self.nexthop = args[11]
|
||||||
self.last_state_change = float(args[16])
|
self.via = args[12]
|
||||||
|
self.distance = int(args[13])
|
||||||
|
self.pmtu = int(args[14])
|
||||||
|
self.minmtu = int(args[15])
|
||||||
|
self.maxmtu = int(args[16])
|
||||||
|
|
||||||
|
self.last_state_change = float(args[17])
|
||||||
|
|
||||||
self.subnets = {}
|
self.subnets = {}
|
||||||
|
|
||||||
class Edge:
|
|
||||||
def parse(self, args):
|
class Edge(object):
|
||||||
self.fr = args[0]
|
def __init__(self, args):
|
||||||
self.to = args[1]
|
self.source = args[0]
|
||||||
|
self.sink = args[1]
|
||||||
|
|
||||||
self.address = args[2]
|
self.address = args[2]
|
||||||
self.port = args[4]
|
self.port = args[4]
|
||||||
|
|
||||||
self.options = int(args[-2], 16)
|
self.options = int(args[-2], 16)
|
||||||
self.weight = int(args[-1])
|
self.weight = int(args[-1])
|
||||||
|
|
||||||
class Subnet:
|
|
||||||
def parse(self, args):
|
class Subnet(object):
|
||||||
|
def __init__(self, args):
|
||||||
if args[0].find('#') >= 0:
|
if args[0].find('#') >= 0:
|
||||||
(address, self.weight) = args[0].split('#', 1)
|
address, self.weight = args[0].split('#', 1)
|
||||||
else:
|
else:
|
||||||
self.weight = 10
|
self.weight = 10
|
||||||
address = args[0]
|
address = args[0]
|
||||||
|
|
||||||
if address.find('/') >= 0:
|
if address.find('/') >= 0:
|
||||||
(self.address, self.prefixlen) = address.split('/', 1)
|
self.address, self.prefixlen = address.split('/', 1)
|
||||||
else:
|
else:
|
||||||
self.address = address
|
self.address = address
|
||||||
self.prefixlen = '48'
|
self.prefixlen = '48'
|
||||||
|
|
||||||
self.owner = args[1]
|
self.owner = args[1]
|
||||||
|
|
||||||
class Connection:
|
|
||||||
def parse(self, args):
|
class Connection(object):
|
||||||
|
def __init__(self, args):
|
||||||
self.name = args[0]
|
self.name = args[0]
|
||||||
|
|
||||||
self.address = args[1]
|
self.address = args[1]
|
||||||
self.port = args[3]
|
self.port = args[3]
|
||||||
|
|
||||||
self.options = int(args[4], 0x10)
|
self.options = int(args[4], 0x10)
|
||||||
self.socket = int(args[5])
|
self.socket = int(args[5])
|
||||||
self.status = int(args[6], 0x10)
|
self.status = int(args[6], 0x10)
|
||||||
self.weight = 123
|
|
||||||
|
|
||||||
class VPN:
|
self.weight = 'n/a'
|
||||||
confdir = '/etc/tinc'
|
|
||||||
piddir = '/var/run/'
|
|
||||||
|
class VPN(object):
|
||||||
|
def __init__(self, netname=None, pidfile=None, confdir='/etc/tinc', piddir='/run'):
|
||||||
|
if platform.system() == 'Windows':
|
||||||
|
sam = _winreg.KEY_READ
|
||||||
|
if platform.machine().endswith('64'):
|
||||||
|
sam = sam | _winreg.KEY_WOW64_64KEY
|
||||||
|
try:
|
||||||
|
reg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
|
||||||
|
try:
|
||||||
|
key = _winreg.OpenKey(reg, "SOFTWARE\\tinc", 0, sam)
|
||||||
|
except WindowsError:
|
||||||
|
key = _winreg.OpenKey(reg, "SOFTWARE\\Wow6432Node\\tinc", 0, sam)
|
||||||
|
confdir = _winreg.QueryValue(key, None)
|
||||||
|
except WindowsError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if netname:
|
||||||
|
self.netname = netname
|
||||||
|
self.confbase = os.path.join(confdir, netname)
|
||||||
|
else:
|
||||||
|
self.confbase = confdir
|
||||||
|
|
||||||
|
self.tincconf = os.path.join(self.confbase, 'tinc.conf')
|
||||||
|
|
||||||
|
if pidfile is not None:
|
||||||
|
self.pidfile = pidfile
|
||||||
|
else:
|
||||||
|
if platform.system() == 'Windows':
|
||||||
|
self.pidfile = os.path.join(self.confbase, 'pid')
|
||||||
|
else:
|
||||||
|
if netname:
|
||||||
|
self.pidfile = os.path.join(piddir, 'tinc.' + netname + '.pid')
|
||||||
|
else:
|
||||||
|
self.pidfile = os.path.join(piddir, 'tinc.pid')
|
||||||
|
|
||||||
|
self.sf = None
|
||||||
|
self.name = None
|
||||||
|
self.port = None
|
||||||
|
self.nodes = {}
|
||||||
|
self.edges = {}
|
||||||
|
self.subnets = {}
|
||||||
|
self.connections = {}
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
# read the pidfile
|
# read the pidfile
|
||||||
|
@ -118,10 +173,10 @@ class VPN:
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
# check if there is a UNIX socket as well
|
# check if there is a UNIX socket as well
|
||||||
if self.pidfile.endswith(".pid"):
|
if self.pidfile.endswith('.pid'):
|
||||||
unixfile = self.pidfile.replace(".pid", ".socket");
|
unixfile = self.pidfile.replace('.pid', '.socket');
|
||||||
else:
|
else:
|
||||||
unixfile = self.pidfile + ".socket";
|
unixfile = self.pidfile + '.socket';
|
||||||
|
|
||||||
if os.path.exists(unixfile):
|
if os.path.exists(unixfile):
|
||||||
# use it if it exists
|
# use it if it exists
|
||||||
|
@ -146,14 +201,11 @@ class VPN:
|
||||||
self.sf.flush()
|
self.sf.flush()
|
||||||
resp = string.split(self.sf.readline())
|
resp = string.split(self.sf.readline())
|
||||||
self.port = info[4]
|
self.port = info[4]
|
||||||
self.nodes = {}
|
|
||||||
self.edges = {}
|
|
||||||
self.subnets = {}
|
|
||||||
self.connections = {}
|
|
||||||
self.refresh()
|
self.refresh()
|
||||||
|
|
||||||
def refresh(self):
|
def refresh(self):
|
||||||
self.sf.write('18 3\r\n18 4\r\n18 5\r\n18 6\r\n')
|
for request in (REQ_DUMP_NODES, REQ_DUMP_EDGES, REQ_DUMP_SUBNETS, REQ_DUMP_CONNECTIONS):
|
||||||
|
self.sf.write('{} {}\r\n'.format(CONTROL, request))
|
||||||
self.sf.flush()
|
self.sf.flush()
|
||||||
|
|
||||||
for node in self.nodes.values():
|
for node in self.nodes.values():
|
||||||
|
@ -174,22 +226,19 @@ class VPN:
|
||||||
if resp[1] == '3':
|
if resp[1] == '3':
|
||||||
if len(resp) < 19:
|
if len(resp) < 19:
|
||||||
continue
|
continue
|
||||||
node = self.nodes.get(resp[2]) or Node()
|
node = self.nodes.get(resp[2]) or Node(resp[2:])
|
||||||
node.parse(resp[2:])
|
|
||||||
node.visited = True
|
node.visited = True
|
||||||
self.nodes[resp[2]] = node
|
self.nodes[resp[2]] = node
|
||||||
elif resp[1] == '4':
|
elif resp[1] == '4':
|
||||||
if len(resp) < 9:
|
if len(resp) < 9:
|
||||||
continue
|
continue
|
||||||
edge = self.nodes.get((resp[2], resp[3])) or Edge()
|
edge = self.nodes.get((resp[2], resp[3])) or Edge(resp[2:])
|
||||||
edge.parse(resp[2:])
|
|
||||||
edge.visited = True
|
edge.visited = True
|
||||||
self.edges[(resp[2], resp[3])] = edge
|
self.edges[(resp[2], resp[3])] = edge
|
||||||
elif resp[1] == '5':
|
elif resp[1] == '5':
|
||||||
if len(resp) < 4:
|
if len(resp) < 4:
|
||||||
continue
|
continue
|
||||||
subnet = self.subnets.get((resp[2], resp[3])) or Subnet()
|
subnet = self.subnets.get((resp[2], resp[3])) or Subnet(resp[2:])
|
||||||
subnet.parse(resp[2:])
|
|
||||||
subnet.visited = True
|
subnet.visited = True
|
||||||
self.subnets[(resp[2], resp[3])] = subnet
|
self.subnets[(resp[2], resp[3])] = subnet
|
||||||
if subnet.owner == "(broadcast)":
|
if subnet.owner == "(broadcast)":
|
||||||
|
@ -198,8 +247,7 @@ class VPN:
|
||||||
elif resp[1] == '6':
|
elif resp[1] == '6':
|
||||||
if len(resp) < 9:
|
if len(resp) < 9:
|
||||||
break
|
break
|
||||||
connection = self.connections.get((resp[2], resp[3], resp[5])) or Connection()
|
connection = self.connections.get((resp[2], resp[3], resp[5])) or Connection(resp[2:])
|
||||||
connection.parse(resp[2:])
|
|
||||||
connection.visited = True
|
connection.visited = True
|
||||||
self.connections[(resp[2], resp[3], resp[5])] = connection
|
self.connections[(resp[2], resp[3], resp[5])] = connection
|
||||||
else:
|
else:
|
||||||
|
@ -239,79 +287,6 @@ class VPN:
|
||||||
resp = string.split(self.sf.readline())
|
resp = string.split(self.sf.readline())
|
||||||
return int(resp[2])
|
return int(resp[2])
|
||||||
|
|
||||||
def __init__(self, netname = None, pidfile = None):
|
|
||||||
if platform.system() == 'Windows':
|
|
||||||
sam = _winreg.KEY_READ
|
|
||||||
if platform.machine().endswith('64'):
|
|
||||||
sam = sam | _winreg.KEY_WOW64_64KEY
|
|
||||||
try:
|
|
||||||
reg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
|
|
||||||
try:
|
|
||||||
key = _winreg.OpenKey(reg, "SOFTWARE\\tinc", 0, sam)
|
|
||||||
except WindowsError:
|
|
||||||
key = _winreg.OpenKey(reg, "SOFTWARE\\Wow6432Node\\tinc", 0, sam)
|
|
||||||
VPN.confdir = _winreg.QueryValue(key, None)
|
|
||||||
except WindowsError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if netname:
|
|
||||||
self.netname = netname
|
|
||||||
self.confbase = os.path.join(VPN.confdir, netname)
|
|
||||||
else:
|
|
||||||
self.confbase = VPN.confdir
|
|
||||||
|
|
||||||
self.tincconf = os.path.join(self.confbase, 'tinc.conf')
|
|
||||||
|
|
||||||
if pidfile != None:
|
|
||||||
self.pidfile = pidfile
|
|
||||||
else:
|
|
||||||
if platform.system() == 'Windows':
|
|
||||||
self.pidfile = os.path.join(self.confbase, 'pid')
|
|
||||||
else:
|
|
||||||
if netname:
|
|
||||||
self.pidfile = os.path.join(VPN.piddir, 'tinc.' + netname + '.pid')
|
|
||||||
else:
|
|
||||||
self.pidfile = os.path.join(VPN.piddir, 'tinc.pid')
|
|
||||||
|
|
||||||
# GUI starts here
|
|
||||||
|
|
||||||
argv0 = sys.argv[0]
|
|
||||||
del sys.argv[0]
|
|
||||||
netname = None
|
|
||||||
pidfile = None
|
|
||||||
|
|
||||||
def usage(exitcode = 0):
|
|
||||||
print('Usage: ' + argv0 + ' [options]')
|
|
||||||
print('\nValid options are:')
|
|
||||||
print(' -n, --net=NETNAME Connect to net NETNAME.')
|
|
||||||
print(' --pidfile=FILENAME Read control cookie from FILENAME.')
|
|
||||||
print(' --help Display this help and exit.')
|
|
||||||
print('\nReport bugs to tinc@tinc-vpn.org.')
|
|
||||||
sys.exit(exitcode)
|
|
||||||
|
|
||||||
while sys.argv:
|
|
||||||
if sys.argv[0] in ('-n', '--net'):
|
|
||||||
del sys.argv[0]
|
|
||||||
netname = sys.argv[0]
|
|
||||||
elif sys.argv[0] in ('--pidfile'):
|
|
||||||
del sys.argv[0]
|
|
||||||
pidfile = sys.argv[0]
|
|
||||||
elif sys.argv[0] in ('--help'):
|
|
||||||
usage(0)
|
|
||||||
else:
|
|
||||||
print(argv0 + ': unrecognized option \'' + sys.argv[0] + '\'')
|
|
||||||
usage(1)
|
|
||||||
|
|
||||||
del sys.argv[0]
|
|
||||||
|
|
||||||
if netname == None:
|
|
||||||
netname = os.getenv("NETNAME")
|
|
||||||
|
|
||||||
if netname == ".":
|
|
||||||
netname = None
|
|
||||||
|
|
||||||
vpn = VPN(netname, pidfile)
|
|
||||||
vpn.connect()
|
|
||||||
|
|
||||||
class SuperListCtrl(wx.ListCtrl, ColumnSorterMixin, ListCtrlAutoWidthMixin):
|
class SuperListCtrl(wx.ListCtrl, ColumnSorterMixin, ListCtrlAutoWidthMixin):
|
||||||
def __init__(self, parent, style):
|
def __init__(self, parent, style):
|
||||||
|
@ -324,7 +299,7 @@ class SuperListCtrl(wx.ListCtrl, ColumnSorterMixin, ListCtrlAutoWidthMixin):
|
||||||
|
|
||||||
|
|
||||||
class SettingsPage(wx.Panel):
|
class SettingsPage(wx.Panel):
|
||||||
def OnDebugLevel(self, event):
|
def on_debug_level(self, event):
|
||||||
vpn.debug(self.debug.GetValue())
|
vpn.debug(self.debug.GetValue())
|
||||||
|
|
||||||
def __init__(self, parent, id):
|
def __init__(self, parent, id):
|
||||||
|
@ -344,7 +319,7 @@ class SettingsPage(wx.Panel):
|
||||||
|
|
||||||
debuglabel = wx.StaticText(self, -1, 'Debug level:')
|
debuglabel = wx.StaticText(self, -1, 'Debug level:')
|
||||||
self.debug = wx.SpinCtrl(self, min=0, max=5, initial=vpn.debug())
|
self.debug = wx.SpinCtrl(self, min=0, max=5, initial=vpn.debug())
|
||||||
self.debug.Bind(wx.EVT_SPINCTRL, self.OnDebugLevel)
|
self.debug.Bind(wx.EVT_SPINCTRL, self.on_debug_level)
|
||||||
grid.Add(debuglabel)
|
grid.Add(debuglabel)
|
||||||
grid.Add(self.debug)
|
grid.Add(self.debug)
|
||||||
|
|
||||||
|
@ -355,6 +330,7 @@ class SettingsPage(wx.Panel):
|
||||||
|
|
||||||
self.SetSizer(grid)
|
self.SetSizer(grid)
|
||||||
|
|
||||||
|
|
||||||
class ConnectionsPage(wx.Panel):
|
class ConnectionsPage(wx.Panel):
|
||||||
def __init__(self, parent, id):
|
def __init__(self, parent, id):
|
||||||
wx.Panel.__init__(self, parent, id)
|
wx.Panel.__init__(self, parent, id)
|
||||||
|
@ -378,13 +354,13 @@ class ConnectionsPage(wx.Panel):
|
||||||
|
|
||||||
disconnect = wx.MenuItem(self, -1, 'Disconnect')
|
disconnect = wx.MenuItem(self, -1, 'Disconnect')
|
||||||
self.AppendItem(disconnect)
|
self.AppendItem(disconnect)
|
||||||
self.Bind(wx.EVT_MENU, self.OnDisconnect, id=disconnect.GetId())
|
self.Bind(wx.EVT_MENU, self.on_disconnect, id=disconnect.GetId())
|
||||||
|
|
||||||
def OnDisconnect(self, event):
|
def on_disconnect(self, event):
|
||||||
vpn.disconnect(self.item[0])
|
vpn.disconnect(self.item[0])
|
||||||
|
|
||||||
def OnContext(self, event):
|
def on_context(self, event):
|
||||||
i = event.GetIndex()
|
idx = event.GetIndex()
|
||||||
self.PopupMenu(self.ContextMenu(self.list.itemDataMap[event.GetIndex()]), event.GetPosition())
|
self.PopupMenu(self.ContextMenu(self.list.itemDataMap[event.GetIndex()]), event.GetPosition())
|
||||||
|
|
||||||
def refresh(self):
|
def refresh(self):
|
||||||
|
@ -401,8 +377,9 @@ class ConnectionsPage(wx.Panel):
|
||||||
self.list.SetStringItem(i, 2, connection.port)
|
self.list.SetStringItem(i, 2, connection.port)
|
||||||
self.list.SetStringItem(i, 3, str(connection.options))
|
self.list.SetStringItem(i, 3, str(connection.options))
|
||||||
self.list.SetStringItem(i, 4, str(connection.weight))
|
self.list.SetStringItem(i, 4, str(connection.weight))
|
||||||
self.list.itemDataMap[i] = (connection.name, connection.address, connection.port, connection.options, connection.weight)
|
self.list.itemDataMap[i] = (connection.name, connection.address, connection.port, connection.options,
|
||||||
self.list.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnContext)
|
connection.weight)
|
||||||
|
self.list.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.on_context)
|
||||||
self.list.SetItemData(i, i)
|
self.list.SetItemData(i, i)
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
|
@ -411,6 +388,7 @@ class ConnectionsPage(wx.Panel):
|
||||||
|
|
||||||
self.list.SortListItems(sortstate[0], sortstate[1])
|
self.list.SortListItems(sortstate[0], sortstate[1])
|
||||||
|
|
||||||
|
|
||||||
class NodesPage(wx.Panel):
|
class NodesPage(wx.Panel):
|
||||||
def __init__(self, parent, id):
|
def __init__(self, parent, id):
|
||||||
wx.Panel.__init__(self, parent, id)
|
wx.Panel.__init__(self, parent, id)
|
||||||
|
@ -466,7 +444,9 @@ class NodesPage(wx.Panel):
|
||||||
else:
|
else:
|
||||||
since = "never"
|
since = "never"
|
||||||
self.list.SetStringItem(i, 15, since)
|
self.list.SetStringItem(i, 15, since)
|
||||||
self.list.itemDataMap[i] = (node.name, node.address, node.port, node.cipher, node.digest, node.maclength, node.compression, node.options, node.status, node.nexthop, node.via, node.distance, node.pmtu, node.minmtu, node.maxmtu, since)
|
self.list.itemDataMap[i] = (node.name, node.address, node.port, node.cipher, node.digest, node.maclength,
|
||||||
|
node.compression, node.options, node.status, node.nexthop, node.via,
|
||||||
|
node.distance, node.pmtu, node.minmtu, node.maxmtu, since)
|
||||||
self.list.SetItemData(i, i)
|
self.list.SetItemData(i, i)
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
|
@ -475,6 +455,7 @@ class NodesPage(wx.Panel):
|
||||||
|
|
||||||
self.list.SortListItems(sortstate[0], sortstate[1])
|
self.list.SortListItems(sortstate[0], sortstate[1])
|
||||||
|
|
||||||
|
|
||||||
class EdgesPage(wx.Panel):
|
class EdgesPage(wx.Panel):
|
||||||
def __init__(self, parent, id):
|
def __init__(self, parent, id):
|
||||||
wx.Panel.__init__(self, parent, id)
|
wx.Panel.__init__(self, parent, id)
|
||||||
|
@ -498,15 +479,15 @@ class EdgesPage(wx.Panel):
|
||||||
|
|
||||||
for key, edge in vpn.edges.items():
|
for key, edge in vpn.edges.items():
|
||||||
if self.list.GetItemCount() <= i:
|
if self.list.GetItemCount() <= i:
|
||||||
self.list.InsertStringItem(i, edge.fr)
|
self.list.InsertStringItem(i, edge.source)
|
||||||
else:
|
else:
|
||||||
self.list.SetStringItem(i, 0, edge.fr)
|
self.list.SetStringItem(i, 0, edge.source)
|
||||||
self.list.SetStringItem(i, 1, edge.to)
|
self.list.SetStringItem(i, 1, edge.sink)
|
||||||
self.list.SetStringItem(i, 2, edge.address)
|
self.list.SetStringItem(i, 2, edge.address)
|
||||||
self.list.SetStringItem(i, 3, edge.port)
|
self.list.SetStringItem(i, 3, edge.port)
|
||||||
self.list.SetStringItem(i, 4, format(edge.options, "x"))
|
self.list.SetStringItem(i, 4, format(edge.options, "x"))
|
||||||
self.list.SetStringItem(i, 5, str(edge.weight))
|
self.list.SetStringItem(i, 5, str(edge.weight))
|
||||||
self.list.itemDataMap[i] = (edge.fr, edge.to, edge.address, edge.port, edge.options, edge.weight)
|
self.list.itemDataMap[i] = (edge.source, edge.sink, edge.address, edge.port, edge.options, edge.weight)
|
||||||
self.list.SetItemData(i, i)
|
self.list.SetItemData(i, i)
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
|
@ -515,6 +496,7 @@ class EdgesPage(wx.Panel):
|
||||||
|
|
||||||
self.list.SortListItems(sortstate[0], sortstate[1])
|
self.list.SortListItems(sortstate[0], sortstate[1])
|
||||||
|
|
||||||
|
|
||||||
class SubnetsPage(wx.Panel):
|
class SubnetsPage(wx.Panel):
|
||||||
def __init__(self, parent, id):
|
def __init__(self, parent, id):
|
||||||
wx.Panel.__init__(self, parent, id)
|
wx.Panel.__init__(self, parent, id)
|
||||||
|
@ -548,14 +530,17 @@ class SubnetsPage(wx.Panel):
|
||||||
|
|
||||||
self.list.SortListItems(sortstate[0], sortstate[1])
|
self.list.SortListItems(sortstate[0], sortstate[1])
|
||||||
|
|
||||||
|
|
||||||
class StatusPage(wx.Panel):
|
class StatusPage(wx.Panel):
|
||||||
def __init__(self, parent, id):
|
def __init__(self, parent, id):
|
||||||
wx.Panel.__init__(self, parent, id)
|
wx.Panel.__init__(self, parent, id)
|
||||||
|
|
||||||
|
|
||||||
class GraphPage(wx.Window):
|
class GraphPage(wx.Window):
|
||||||
def __init__(self, parent, id):
|
def __init__(self, parent, id):
|
||||||
wx.Window.__init__(self, parent, id)
|
wx.Window.__init__(self, parent, id)
|
||||||
|
|
||||||
|
|
||||||
class NetPage(wx.Notebook):
|
class NetPage(wx.Notebook):
|
||||||
def __init__(self, parent, id):
|
def __init__(self, parent, id):
|
||||||
wx.Notebook.__init__(self, parent)
|
wx.Notebook.__init__(self, parent)
|
||||||
|
@ -573,27 +558,19 @@ class NetPage(wx.Notebook):
|
||||||
self.AddPage(self.nodes, 'Nodes')
|
self.AddPage(self.nodes, 'Nodes')
|
||||||
self.AddPage(self.edges, 'Edges')
|
self.AddPage(self.edges, 'Edges')
|
||||||
self.AddPage(self.subnets, 'Subnets')
|
self.AddPage(self.subnets, 'Subnets')
|
||||||
|
|
||||||
# self.AddPage(self.graph, 'Graph')
|
# self.AddPage(self.graph, 'Graph')
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(wx.Frame):
|
class MainWindow(wx.Frame):
|
||||||
def OnQuit(self, event):
|
|
||||||
app.ExitMainLoop()
|
|
||||||
|
|
||||||
def OnTimer(self, event):
|
|
||||||
vpn.refresh()
|
|
||||||
self.np.nodes.refresh()
|
|
||||||
self.np.subnets.refresh()
|
|
||||||
self.np.edges.refresh()
|
|
||||||
self.np.connections.refresh()
|
|
||||||
|
|
||||||
def __init__(self, parent, id, title):
|
def __init__(self, parent, id, title):
|
||||||
wx.Frame.__init__(self, parent, id, title)
|
wx.Frame.__init__(self, parent, id, title)
|
||||||
|
|
||||||
menubar = wx.MenuBar()
|
menubar = wx.MenuBar()
|
||||||
file = wx.Menu()
|
|
||||||
file.Append(1, '&Quit\tCtrl-X', 'Quit tinc GUI')
|
menu = wx.Menu()
|
||||||
menubar.Append(file, '&File')
|
menu.Append(1, '&Quit\tCtrl-X', 'Quit tinc GUI')
|
||||||
|
menubar.Append(menu, '&File')
|
||||||
|
|
||||||
# nb = wx.Notebook(self, -1)
|
# nb = wx.Notebook(self, -1)
|
||||||
# nb.SetPadding((0, 0))
|
# nb.SetPadding((0, 0))
|
||||||
|
@ -601,22 +578,57 @@ class MainWindow(wx.Frame):
|
||||||
# nb.AddPage(np, 'VPN')
|
# nb.AddPage(np, 'VPN')
|
||||||
|
|
||||||
self.timer = wx.Timer(self, -1)
|
self.timer = wx.Timer(self, -1)
|
||||||
self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
|
self.Bind(wx.EVT_TIMER, self.on_timer, self.timer)
|
||||||
self.timer.Start(1000)
|
self.timer.Start(1000)
|
||||||
self.Bind(wx.EVT_MENU, self.OnQuit, id=1)
|
self.Bind(wx.EVT_MENU, self.on_quit, id=1)
|
||||||
self.SetMenuBar(menubar)
|
self.SetMenuBar(menubar)
|
||||||
self.Show()
|
self.Show()
|
||||||
|
|
||||||
|
def on_quit(self, event):
|
||||||
|
app.ExitMainLoop()
|
||||||
|
|
||||||
|
def on_timer(self, event):
|
||||||
|
vpn.refresh()
|
||||||
|
self.np.nodes.refresh()
|
||||||
|
self.np.subnets.refresh()
|
||||||
|
self.np.edges.refresh()
|
||||||
|
self.np.connections.refresh()
|
||||||
|
|
||||||
|
|
||||||
|
def main(netname, pidfile):
|
||||||
|
global vpn, app
|
||||||
|
|
||||||
|
if netname is None:
|
||||||
|
netname = os.getenv('NETNAME')
|
||||||
|
|
||||||
|
vpn = VPN(netname, pidfile)
|
||||||
|
vpn.connect()
|
||||||
|
|
||||||
app = wx.App()
|
app = wx.App()
|
||||||
mw = MainWindow(None, -1, 'Tinc GUI')
|
mw = MainWindow(None, -1, 'Tinc GUI')
|
||||||
|
|
||||||
#def OnTaskBarIcon(event):
|
"""
|
||||||
# mw.Raise()
|
def OnTaskBarIcon(event):
|
||||||
#
|
mw.Raise()
|
||||||
#icon = wx.Icon("tincgui.ico", wx.BITMAP_TYPE_PNG)
|
"""
|
||||||
#taskbaricon = wx.TaskBarIcon()
|
|
||||||
#taskbaricon.SetIcon(icon, 'Tinc GUI')
|
"""
|
||||||
#wx.EVT_TASKBAR_RIGHT_UP(taskbaricon, OnTaskBarIcon)
|
icon = wx.Icon("tincgui.ico", wx.BITMAP_TYPE_PNG)
|
||||||
|
taskbaricon = wx.TaskBarIcon()
|
||||||
|
taskbaricon.SetIcon(icon, 'Tinc GUI')
|
||||||
|
wx.EVT_TASKBAR_RIGHT_UP(taskbaricon, OnTaskBarIcon)
|
||||||
|
"""
|
||||||
|
|
||||||
app.MainLoop()
|
app.MainLoop()
|
||||||
vpn.close()
|
vpn.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
argparser = ArgumentParser(epilog='Report bugs to tinc@tinc-vpn.org.')
|
||||||
|
|
||||||
|
argparser.add_argument('-n', '--net', metavar='NETNAME', dest='netname', help='Connect to net NETNAME')
|
||||||
|
argparser.add_argument('-p', '--pidfile', help='Path to the pid file (containing the controlcookie)')
|
||||||
|
|
||||||
|
options = argparser.parse_args()
|
||||||
|
|
||||||
|
main(options.netname, options.pidfile)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
dnl Check to find the OpenSSL headers/libraries
|
dnl Check to find the LibreSSL/OpenSSL headers/libraries
|
||||||
|
|
||||||
AC_DEFUN([tinc_OPENSSL],
|
AC_DEFUN([tinc_OPENSSL],
|
||||||
[
|
[
|
||||||
|
@ -10,47 +10,47 @@ AC_DEFUN([tinc_OPENSSL],
|
||||||
[],
|
[],
|
||||||
[AC_CHECK_LIB(dl, dlopen,
|
[AC_CHECK_LIB(dl, dlopen,
|
||||||
[LIBS="$LIBS -ldl"],
|
[LIBS="$LIBS -ldl"],
|
||||||
[AC_MSG_ERROR([OpenSSL depends on libdl.]); break]
|
[AC_MSG_ERROR([LibreSSL/OpenSSL depends on libdl.]); break]
|
||||||
)]
|
)]
|
||||||
)
|
)
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
AC_ARG_WITH(openssl,
|
AC_ARG_WITH(openssl,
|
||||||
AS_HELP_STRING([--with-openssl=DIR], [OpenSSL base directory, or:]),
|
AS_HELP_STRING([--with-openssl=DIR], [LibreSSL/OpenSSL base directory, or:]),
|
||||||
[openssl="$withval"
|
[openssl="$withval"
|
||||||
CPPFLAGS="$CPPFLAGS -I$withval/include"
|
CPPFLAGS="$CPPFLAGS -I$withval/include"
|
||||||
LDFLAGS="$LDFLAGS -L$withval/lib"]
|
LDFLAGS="$LDFLAGS -L$withval/lib"]
|
||||||
)
|
)
|
||||||
|
|
||||||
AC_ARG_WITH(openssl-include,
|
AC_ARG_WITH(openssl-include,
|
||||||
AS_HELP_STRING([--with-openssl-include=DIR], [OpenSSL headers directory (without trailing /openssl)]),
|
AS_HELP_STRING([--with-openssl-include=DIR], [LibreSSL/OpenSSL headers directory (without trailing /openssl)]),
|
||||||
[openssl_include="$withval"
|
[openssl_include="$withval"
|
||||||
CPPFLAGS="$CPPFLAGS -I$withval"]
|
CPPFLAGS="$CPPFLAGS -I$withval"]
|
||||||
)
|
)
|
||||||
|
|
||||||
AC_ARG_WITH(openssl-lib,
|
AC_ARG_WITH(openssl-lib,
|
||||||
AS_HELP_STRING([--with-openssl-lib=DIR], [OpenSSL library directory]),
|
AS_HELP_STRING([--with-openssl-lib=DIR], [LibreSSL/OpenSSL library directory]),
|
||||||
[openssl_lib="$withval"
|
[openssl_lib="$withval"
|
||||||
LDFLAGS="$LDFLAGS -L$withval"]
|
LDFLAGS="$LDFLAGS -L$withval"]
|
||||||
)
|
)
|
||||||
|
|
||||||
AC_CHECK_HEADERS([openssl/evp.h openssl/rsa.h openssl/rand.h openssl/err.h openssl/sha.h openssl/pem.h openssl/engine.h],
|
AC_CHECK_HEADERS([openssl/evp.h openssl/rsa.h openssl/rand.h openssl/err.h openssl/sha.h openssl/pem.h openssl/engine.h],
|
||||||
[],
|
[],
|
||||||
[AC_MSG_ERROR([OpenSSL header files not found.]); break]
|
[AC_MSG_ERROR([LibreSSL/OpenSSL header files not found.]); break]
|
||||||
)
|
)
|
||||||
|
|
||||||
AC_CHECK_LIB(crypto, EVP_EncryptInit_ex,
|
AC_CHECK_LIB(crypto, EVP_EncryptInit_ex,
|
||||||
[LIBS="-lcrypto $LIBS"],
|
[LIBS="-lcrypto $LIBS"],
|
||||||
[AC_MSG_ERROR([OpenSSL libraries not found.])]
|
[AC_MSG_ERROR([LibreSSL/OpenSSL libraries not found.])]
|
||||||
)
|
)
|
||||||
|
|
||||||
AC_CHECK_FUNCS([RAND_status EVP_EncryptInit_ex], ,
|
AC_CHECK_FUNCS([RAND_status EVP_EncryptInit_ex], ,
|
||||||
[AC_MSG_ERROR([Missing OpenSSL functionality, make sure you have installed the latest version.]); break],
|
[AC_MSG_ERROR([Missing LibreSSL/OpenSSL functionality, make sure you have installed the latest version.]); break],
|
||||||
)
|
)
|
||||||
|
|
||||||
AC_CHECK_DECLS([OpenSSL_add_all_algorithms], ,
|
AC_CHECK_DECLS([OpenSSL_add_all_algorithms], ,
|
||||||
[AC_MSG_ERROR([Missing OpenSSL functionality, make sure you have installed the latest version.]); break],
|
[AC_MSG_ERROR([Missing LibreSSL/OpenSSL functionality, make sure you have installed the latest version.]); break],
|
||||||
[#include <openssl/evp.h>]
|
[#include <openssl/evp.h>]
|
||||||
)
|
)
|
||||||
])
|
])
|
||||||
|
|
242
src/Makefile.am
242
src/Makefile.am
|
@ -2,25 +2,26 @@
|
||||||
|
|
||||||
sbin_PROGRAMS = tincd tinc sptps_test sptps_keypair
|
sbin_PROGRAMS = tincd tinc sptps_test sptps_keypair
|
||||||
|
|
||||||
## Make sure version.c is always rebuilt with the latest git information
|
CLEANFILES = version_git.h
|
||||||
.PHONY: ${srcdir}/version.c version_git.h
|
|
||||||
version_git.h:
|
.PHONY: version-stamp
|
||||||
echo >$@
|
version-stamp:
|
||||||
-(cd $(srcdir) && git describe) && echo '#define GIT_DESCRIPTION "'`(cd $(srcdir) && git describe) | sed 's/release-//'`'"' >$@
|
|
||||||
|
version_git.h: version-stamp
|
||||||
|
$(AM_V_GEN)echo >$@
|
||||||
|
@-(cd $(srcdir) && git describe 2>/dev/null >/dev/null) && echo '#define GIT_DESCRIPTION "'`(cd $(srcdir) && git describe) | sed 's/release-//'`'"' >$@ ||:
|
||||||
${srcdir}/version.c: version_git.h
|
${srcdir}/version.c: version_git.h
|
||||||
|
|
||||||
|
## Now a hack to appease some versions of BSD make that don't understand that "./foo" is the same as "foo".
|
||||||
|
if BSD
|
||||||
|
version.c: ${srcdir}/version.c
|
||||||
|
endif
|
||||||
|
|
||||||
if LINUX
|
if LINUX
|
||||||
sbin_PROGRAMS += sptps_speed
|
sbin_PROGRAMS += sptps_speed
|
||||||
endif
|
endif
|
||||||
|
|
||||||
lib_LTLIBRARIES = libtincd.la libed25519.la libchacha_poly1305.la libtincconf.la
|
ed25519_SOURCES = \
|
||||||
|
|
||||||
libchacha_poly1305_la_SOURCES = \
|
|
||||||
chacha-poly1305/chacha.c chacha-poly1305/chacha.h \
|
|
||||||
chacha-poly1305/chacha-poly1305.c chacha-poly1305/chacha-poly1305.h \
|
|
||||||
chacha-poly1305/poly1305.c chacha-poly1305/poly1305.h
|
|
||||||
|
|
||||||
libed25519_la_SOURCES = \
|
|
||||||
ed25519/add_scalar.c \
|
ed25519/add_scalar.c \
|
||||||
ed25519/ed25519.h \
|
ed25519/ed25519.h \
|
||||||
ed25519/fe.c ed25519/fe.h \
|
ed25519/fe.c ed25519/fe.h \
|
||||||
|
@ -31,26 +32,25 @@ libed25519_la_SOURCES = \
|
||||||
ed25519/precomp_data.h \
|
ed25519/precomp_data.h \
|
||||||
ed25519/sc.c ed25519/sc.h \
|
ed25519/sc.c ed25519/sc.h \
|
||||||
ed25519/sha512.c ed25519/sha512.h \
|
ed25519/sha512.c ed25519/sha512.h \
|
||||||
ed25519/ecdsa.c \
|
|
||||||
ed25519/sign.c \
|
ed25519/sign.c \
|
||||||
ed25519/verify.c
|
ed25519/verify.c
|
||||||
|
|
||||||
libtincconf_la_SOURCES = \
|
chacha_poly1305_SOURCES = \
|
||||||
conf.h\
|
chacha-poly1305/chacha.c chacha-poly1305/chacha.h \
|
||||||
conf.c
|
chacha-poly1305/chacha-poly1305.c chacha-poly1305/chacha-poly1305.h \
|
||||||
|
chacha-poly1305/poly1305.c chacha-poly1305/poly1305.h
|
||||||
|
|
||||||
libtincd_la_SOURCES = \
|
tincd_SOURCES = \
|
||||||
conf.h \
|
|
||||||
conf.c \
|
|
||||||
buffer.c buffer.h \
|
buffer.c buffer.h \
|
||||||
cipher.h \
|
cipher.h \
|
||||||
|
conf.c conf.h \
|
||||||
connection.c connection.h \
|
connection.c connection.h \
|
||||||
control.c control.h \
|
control.c control.h \
|
||||||
control_common.h \
|
control_common.h \
|
||||||
crypto.h \
|
crypto.h \
|
||||||
device.h \
|
device.h \
|
||||||
digest.h \
|
digest.h \
|
||||||
dropin.c \
|
dropin.c dropin.h \
|
||||||
dummy_device.c \
|
dummy_device.c \
|
||||||
ecdh.h \
|
ecdh.h \
|
||||||
ecdsa.h \
|
ecdsa.h \
|
||||||
|
@ -58,9 +58,6 @@ libtincd_la_SOURCES = \
|
||||||
edge.c edge.h \
|
edge.c edge.h \
|
||||||
ethernet.h \
|
ethernet.h \
|
||||||
event.c event.h \
|
event.c event.h \
|
||||||
fake-gai-errnos.h \
|
|
||||||
fake-getaddrinfo.c fake-getaddrinfo.h \
|
|
||||||
fake-getnameinfo.c fake-getnameinfo.h \
|
|
||||||
graph.c graph.h \
|
graph.c graph.h \
|
||||||
hash.c hash.h \
|
hash.c hash.h \
|
||||||
have.h \
|
have.h \
|
||||||
|
@ -78,6 +75,7 @@ libtincd_la_SOURCES = \
|
||||||
netutl.c netutl.h \
|
netutl.c netutl.h \
|
||||||
node.c node.h \
|
node.c node.h \
|
||||||
prf.h \
|
prf.h \
|
||||||
|
process.c process.h \
|
||||||
protocol.c protocol.h \
|
protocol.c protocol.h \
|
||||||
protocol_auth.c \
|
protocol_auth.c \
|
||||||
protocol_edge.c \
|
protocol_edge.c \
|
||||||
|
@ -94,117 +92,189 @@ libtincd_la_SOURCES = \
|
||||||
subnet.c subnet.h \
|
subnet.c subnet.h \
|
||||||
subnet_parse.c \
|
subnet_parse.c \
|
||||||
system.h \
|
system.h \
|
||||||
|
tincd.c \
|
||||||
utils.c utils.h \
|
utils.c utils.h \
|
||||||
xalloc.h \
|
xalloc.h \
|
||||||
version.c version.h \
|
version.c version.h \
|
||||||
ed25519/ecdh.c \
|
ed25519/ecdh.c \
|
||||||
ed25519/ecdsa.c \
|
ed25519/ecdsa.c \
|
||||||
getopt.c getopt.h \
|
$(ed25519_SOURCES) \
|
||||||
process.h process.c \
|
$(chacha_poly1305_SOURCES)
|
||||||
getopt1.c
|
|
||||||
|
tinc_SOURCES = \
|
||||||
|
dropin.c dropin.h \
|
||||||
|
fsck.c fsck.h \
|
||||||
|
ifconfig.c ifconfig.h \
|
||||||
|
info.c info.h \
|
||||||
|
invitation.c invitation.h \
|
||||||
|
list.c list.h \
|
||||||
|
names.c names.h \
|
||||||
|
netutl.c netutl.h \
|
||||||
|
script.c script.h \
|
||||||
|
sptps.c sptps.h \
|
||||||
|
subnet_parse.c subnet.h \
|
||||||
|
tincctl.c tincctl.h \
|
||||||
|
top.c top.h \
|
||||||
|
utils.c utils.h \
|
||||||
|
version.c version.h \
|
||||||
|
ed25519/ecdh.c \
|
||||||
|
ed25519/ecdsa.c \
|
||||||
|
ed25519/ecdsagen.c \
|
||||||
|
$(ed25519_SOURCES) \
|
||||||
|
$(chacha_poly1305_SOURCES)
|
||||||
|
|
||||||
|
sptps_test_SOURCES = \
|
||||||
|
logger.c logger.h \
|
||||||
|
sptps.c sptps.h \
|
||||||
|
sptps_test.c \
|
||||||
|
utils.c utils.h \
|
||||||
|
ed25519/ecdh.c \
|
||||||
|
ed25519/ecdsa.c \
|
||||||
|
$(ed25519_SOURCES) \
|
||||||
|
$(chacha_poly1305_SOURCES)
|
||||||
|
|
||||||
|
sptps_keypair_SOURCES = \
|
||||||
|
sptps_keypair.c \
|
||||||
|
utils.c utils.h \
|
||||||
|
ed25519/ecdsagen.c \
|
||||||
|
$(ed25519_SOURCES)
|
||||||
|
|
||||||
|
sptps_speed_SOURCES = \
|
||||||
|
logger.c logger.h \
|
||||||
|
sptps.c sptps.h \
|
||||||
|
sptps_speed.c \
|
||||||
|
utils.c utils.h \
|
||||||
|
ed25519/ecdh.c \
|
||||||
|
ed25519/ecdsa.c \
|
||||||
|
ed25519/ecdsagen.c \
|
||||||
|
$(ed25519_SOURCES) \
|
||||||
|
$(chacha_poly1305_SOURCES)
|
||||||
|
|
||||||
## Conditionally compile device drivers
|
## Conditionally compile device drivers
|
||||||
|
|
||||||
|
if !GETOPT
|
||||||
|
tincd_SOURCES += \
|
||||||
|
getopt.c getopt.h \
|
||||||
|
getopt1.c
|
||||||
|
tinc_SOURCES += \
|
||||||
|
getopt.c getopt.h \
|
||||||
|
getopt1.c
|
||||||
|
sptps_test_SOURCES += \
|
||||||
|
getopt.c getopt.h \
|
||||||
|
getopt1.c
|
||||||
|
sptps_keypair_SOURCES += \
|
||||||
|
getopt.c getopt.h \
|
||||||
|
getopt1.c
|
||||||
|
endif
|
||||||
|
|
||||||
if LINUX
|
if LINUX
|
||||||
libtincd_la_SOURCES += linux/device.c
|
tincd_SOURCES += linux/device.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if BSD
|
if BSD
|
||||||
libtincd_la_SOURCES += bsd/device.c
|
tincd_SOURCES += bsd/device.c
|
||||||
if TUNEMU
|
if TUNEMU
|
||||||
libtincd_la_SOURCES += bsd/tunemu.c bsd/tunemu.h
|
tincd_SOURCES += bsd/tunemu.c bsd/tunemu.h
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if SOLARIS
|
if SOLARIS
|
||||||
libtincd_la_SOURCES += solaris/device.c
|
tincd_SOURCES += solaris/device.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if MINGW
|
if MINGW
|
||||||
libtincd_la_SOURCES += mingw/device.c mingw/common.h
|
tincd_SOURCES += mingw/device.c mingw/common.h
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if CYGWIN
|
if CYGWIN
|
||||||
libtincd_la_SOURCES += cygwin/device.c
|
tincd_SOURCES += cygwin/device.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if UML
|
if UML
|
||||||
libtincd_la_SOURCES += uml_device.c
|
tincd_SOURCES += uml_device.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if VDE
|
if VDE
|
||||||
libtincd_la_SOURCES += vde_device.c
|
tincd_SOURCES += vde_device.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if OPENSSL
|
if OPENSSL
|
||||||
libtincd_la_SOURCES += \
|
tincd_SOURCES += \
|
||||||
|
openssl/cipher.c \
|
||||||
|
openssl/crypto.c \
|
||||||
|
openssl/digest.c openssl/digest.h \
|
||||||
|
openssl/prf.c \
|
||||||
|
openssl/rsa.c
|
||||||
|
tinc_SOURCES += \
|
||||||
openssl/cipher.c \
|
openssl/cipher.c \
|
||||||
openssl/crypto.c \
|
openssl/crypto.c \
|
||||||
openssl/digest.c openssl/digest.h \
|
openssl/digest.c openssl/digest.h \
|
||||||
openssl/prf.c \
|
openssl/prf.c \
|
||||||
openssl/rsa.c \
|
openssl/rsa.c \
|
||||||
openssl/rsagen.c
|
openssl/rsagen.c
|
||||||
|
sptps_test_SOURCES += \
|
||||||
|
openssl/crypto.c \
|
||||||
|
openssl/digest.c openssl/digest.h \
|
||||||
|
openssl/prf.c
|
||||||
|
sptps_keypair_SOURCES += \
|
||||||
|
openssl/crypto.c
|
||||||
|
sptps_speed_SOURCES += \
|
||||||
|
openssl/crypto.c \
|
||||||
|
openssl/digest.c openssl/digest.h \
|
||||||
|
openssl/prf.c
|
||||||
else
|
else
|
||||||
if GCRYPT
|
if GCRYPT
|
||||||
libtincd_la_SOURCES += \
|
tincd_SOURCES += \
|
||||||
|
gcrypt/cipher.c \
|
||||||
|
gcrypt/crypto.c \
|
||||||
|
gcrypt/digest.c gcrypt/digest.h \
|
||||||
|
gcrypt/prf.c \
|
||||||
|
gcrypt/rsa.c
|
||||||
|
tinc_SOURCES += \
|
||||||
gcrypt/cipher.c \
|
gcrypt/cipher.c \
|
||||||
gcrypt/crypto.c \
|
gcrypt/crypto.c \
|
||||||
gcrypt/digest.c gcrypt/digest.h \
|
gcrypt/digest.c gcrypt/digest.h \
|
||||||
gcrypt/prf.c \
|
gcrypt/prf.c \
|
||||||
gcrypt/rsa.c \
|
gcrypt/rsa.c \
|
||||||
gcrypt/rsagen.c
|
gcrypt/rsagen.c
|
||||||
|
sptps_test_SOURCES += \
|
||||||
|
gcrypt/cipher.c \
|
||||||
|
gcrypt/crypto.c \
|
||||||
|
gcrypt/digest.c gcrypt/digest.h \
|
||||||
|
gcrypt/prf.c
|
||||||
|
sptps_keypair_SOURCES += \
|
||||||
|
openssl/crypto.c
|
||||||
|
sptps_speed_SOURCES += \
|
||||||
|
openssl/crypto.c \
|
||||||
|
openssl/digest.c openssl/digest.h \
|
||||||
|
openssl/prf.c
|
||||||
else
|
else
|
||||||
libtincd_la_SOURCES += \
|
tincd_SOURCES += \
|
||||||
|
nolegacy/crypto.c \
|
||||||
|
nolegacy/prf.c
|
||||||
|
tinc_SOURCES += \
|
||||||
|
nolegacy/crypto.c \
|
||||||
|
nolegacy/prf.c
|
||||||
|
sptps_test_SOURCES += \
|
||||||
|
nolegacy/crypto.c \
|
||||||
|
nolegacy/prf.c
|
||||||
|
sptps_keypair_SOURCES += \
|
||||||
|
nolegacy/crypto.c
|
||||||
|
sptps_speed_SOURCES += \
|
||||||
nolegacy/crypto.c \
|
nolegacy/crypto.c \
|
||||||
nolegacy/prf.c
|
nolegacy/prf.c
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
tincd_SOURCES = \
|
|
||||||
conf.h \
|
|
||||||
tincd.c
|
|
||||||
|
|
||||||
tinc_SOURCES = \
|
|
||||||
invitation.c invitation.h \
|
|
||||||
top.c top.h \
|
|
||||||
fsck.c fsck.h \
|
|
||||||
info.c info.h \
|
|
||||||
ed25519/ecdsagen.c \
|
|
||||||
tincctl.c tincctl.h
|
|
||||||
|
|
||||||
sptps_test_SOURCES = \
|
|
||||||
sptps_test.c
|
|
||||||
|
|
||||||
sptps_keypair_SOURCES = \
|
|
||||||
ed25519/ecdsagen.c \
|
|
||||||
sptps_keypair.c
|
|
||||||
|
|
||||||
sptps_speed_SOURCES = \
|
|
||||||
ed25519/ecdsagen.c \
|
|
||||||
sptps_speed.c
|
|
||||||
|
|
||||||
|
|
||||||
tincd_LDADD = libtincd.la libed25519.la libchacha_poly1305.la libtincconf.la
|
|
||||||
tinc_LDADD = $(READLINE_LIBS) $(CURSES_LIBS) libtincd.la libtincconf.la libed25519.la libchacha_poly1305.la
|
|
||||||
|
|
||||||
sptps_speed_LDADD = libtincd.la libed25519.la libtincconf.la libchacha_poly1305.la libchacha_poly1305.la
|
|
||||||
sptps_test_LDADD = libtincd.la libed25519.la libtincconf.la libchacha_poly1305.la libchacha_poly1305.la
|
|
||||||
sptps_keypair_LDADD = libed25519.la libtincconf.la libchacha_poly1305.la libtincd.la libchacha_poly1305.la
|
|
||||||
|
|
||||||
if !DARWIN
|
|
||||||
if !OPENBSD
|
|
||||||
sptps_speed_LDADD += -lrt
|
|
||||||
sptps_test_LDADD += -lrt
|
|
||||||
sptps_keypair_LDADD += -lrt
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
if MINIUPNPC
|
if MINIUPNPC
|
||||||
tincd_SOURCES += upnp.h upnp.c
|
tincd_SOURCES += upnp.h upnp.c
|
||||||
tincd_LDADD += $(MINIUPNPC_LIBS)
|
tincd_LDADD = $(MINIUPNPC_LIBS)
|
||||||
tincd_LDFLAGS = ${tincd_LDFLAGS} -pthread
|
tincd_LDFLAGS = -pthread
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
tinc_LDADD = $(READLINE_LIBS) $(CURSES_LIBS)
|
||||||
|
sptps_speed_LDADD = -lrt
|
||||||
|
|
||||||
LIBS = @LIBS@ -lm
|
LIBS = @LIBS@ -lm
|
||||||
|
|
||||||
if TUNEMU
|
if TUNEMU
|
||||||
|
@ -212,17 +282,3 @@ LIBS += -lpcap
|
||||||
endif
|
endif
|
||||||
|
|
||||||
AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\" -iquote.
|
AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\" -iquote.
|
||||||
if OPENBSD
|
|
||||||
AM_CFLAGS += -fstack-protector-all
|
|
||||||
endif
|
|
||||||
|
|
||||||
if BSD
|
|
||||||
tincd_LDADD += -lexecinfo
|
|
||||||
tinc_LDADD += -lexecinfo
|
|
||||||
sptps_test_LDADD += -lexecinfo
|
|
||||||
sptps_keypair_LDADD += -lexecinfo
|
|
||||||
sptps_speed_LDADD += -lexecinfo
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
#-fsanitize=address
|
|
||||||
|
|
156
src/bsd/device.c
156
src/bsd/device.c
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
device.c -- Interaction BSD tun/tap device
|
device.c -- Interaction BSD tun/tap device
|
||||||
Copyright (C) 2001-2005 Ivo Timmermans,
|
Copyright (C) 2001-2005 Ivo Timmermans,
|
||||||
2001-2014 Guus Sliepen <guus@tinc-vpn.org>
|
2001-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
2009 Grzegorz Dymarek <gregd72002@googlemail.com>
|
2009 Grzegorz Dymarek <gregd72002@googlemail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -34,13 +34,15 @@
|
||||||
#include "bsd/tunemu.h"
|
#include "bsd/tunemu.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DEFAULT_TUN_DEVICE "/dev/tun0"
|
#ifdef HAVE_NET_IF_UTUN_H
|
||||||
#if defined(HAVE_DARWIN) || defined(HAVE_FREEBSD) || defined(HAVE_NETBSD)
|
#include <sys/sys_domain.h>
|
||||||
#define DEFAULT_TAP_DEVICE "/dev/tap0"
|
#include <sys/kern_control.h>
|
||||||
#else
|
#include <net/if_utun.h>
|
||||||
#define DEFAULT_TAP_DEVICE "/dev/tun0"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define DEFAULT_TUN_DEVICE "/dev/tun0"
|
||||||
|
#define DEFAULT_TAP_DEVICE "/dev/tap0"
|
||||||
|
|
||||||
typedef enum device_type {
|
typedef enum device_type {
|
||||||
DEVICE_TYPE_TUN,
|
DEVICE_TYPE_TUN,
|
||||||
DEVICE_TYPE_TUNIFHEAD,
|
DEVICE_TYPE_TUNIFHEAD,
|
||||||
|
@ -48,6 +50,7 @@ typedef enum device_type {
|
||||||
#ifdef ENABLE_TUNEMU
|
#ifdef ENABLE_TUNEMU
|
||||||
DEVICE_TYPE_TUNEMU,
|
DEVICE_TYPE_TUNEMU,
|
||||||
#endif
|
#endif
|
||||||
|
DEVICE_TYPE_UTUN,
|
||||||
} device_type_t;
|
} device_type_t;
|
||||||
|
|
||||||
int device_fd = -1;
|
int device_fd = -1;
|
||||||
|
@ -62,9 +65,64 @@ static device_type_t device_type = DEVICE_TYPE_TUNIFHEAD;
|
||||||
static device_type_t device_type = DEVICE_TYPE_TUN;
|
static device_type_t device_type = DEVICE_TYPE_TUN;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_NET_IF_UTUN_H
|
||||||
|
static bool setup_utun(void) {
|
||||||
|
device_fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
|
||||||
|
if(device_fd == -1) {
|
||||||
|
logger(DEBUG_ALWAYS, LOG_ERR, "Could not open PF_SYSTEM socket: %s\n", strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ctl_info info = {};
|
||||||
|
strlcpy(info.ctl_name, UTUN_CONTROL_NAME, sizeof info.ctl_name);
|
||||||
|
|
||||||
|
if(ioctl(device_fd, CTLIOCGINFO, &info) == -1) {
|
||||||
|
logger(DEBUG_ALWAYS, LOG_ERR, "ioctl(CTLIOCGINFO) failed: %s", strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int unit = -1;
|
||||||
|
char *p = strstr(device, "utun"), *e = NULL;
|
||||||
|
if(p) {
|
||||||
|
unit = strtol(p + 4, &e, 10);
|
||||||
|
if(!e)
|
||||||
|
unit = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_ctl sc = {
|
||||||
|
.sc_id = info.ctl_id,
|
||||||
|
.sc_len = sizeof sc,
|
||||||
|
.sc_family = AF_SYSTEM,
|
||||||
|
.ss_sysaddr = AF_SYS_CONTROL,
|
||||||
|
.sc_unit = unit + 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
if(connect(device_fd, (struct sockaddr *)&sc, sizeof(sc)) == -1) {
|
||||||
|
logger(DEBUG_ALWAYS, LOG_ERR, "Could not connect utun socket: %s\n", strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char name[64] = "";
|
||||||
|
socklen_t len = sizeof name;
|
||||||
|
if(getsockopt(device_fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, name, &len)) {
|
||||||
|
iface = xstrdup(device);
|
||||||
|
} else {
|
||||||
|
iface = xstrdup(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
device_info = "OS X utun device";
|
||||||
|
|
||||||
|
logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static bool setup_device(void) {
|
static bool setup_device(void) {
|
||||||
get_config_string(lookup_config(config_tree, "Device"), &device);
|
get_config_string(lookup_config(config_tree, "Device"), &device);
|
||||||
|
|
||||||
|
// Find out if it's supposed to be a tun or a tap device
|
||||||
|
|
||||||
char *type;
|
char *type;
|
||||||
if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
|
if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
|
||||||
if(!strcasecmp(type, "tun"))
|
if(!strcasecmp(type, "tun"))
|
||||||
|
@ -72,6 +130,10 @@ static bool setup_device(void) {
|
||||||
#ifdef ENABLE_TUNEMU
|
#ifdef ENABLE_TUNEMU
|
||||||
else if(!strcasecmp(type, "tunemu"))
|
else if(!strcasecmp(type, "tunemu"))
|
||||||
device_type = DEVICE_TYPE_TUNEMU;
|
device_type = DEVICE_TYPE_TUNEMU;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NET_IF_UTUN_H
|
||||||
|
else if(!strcasecmp(type, "utun"))
|
||||||
|
device_type = DEVICE_TYPE_UTUN;
|
||||||
#endif
|
#endif
|
||||||
else if(!strcasecmp(type, "tunnohead"))
|
else if(!strcasecmp(type, "tunnohead"))
|
||||||
device_type = DEVICE_TYPE_TUN;
|
device_type = DEVICE_TYPE_TUN;
|
||||||
|
@ -84,10 +146,22 @@ static bool setup_device(void) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef HAVE_NET_IF_UTUN_H
|
||||||
|
if(device && (strncmp(device, "utun", 4) == 0 || strncmp(device, "/dev/utun", 9) == 0))
|
||||||
|
device_type = DEVICE_TYPE_UTUN;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
if((device && strstr(device, "tap")) || routing_mode != RMODE_ROUTER)
|
if((device && strstr(device, "tap")) || routing_mode != RMODE_ROUTER)
|
||||||
device_type = DEVICE_TYPE_TAP;
|
device_type = DEVICE_TYPE_TAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(routing_mode == RMODE_SWITCH && device_type != DEVICE_TYPE_TAP) {
|
||||||
|
logger(DEBUG_ALWAYS, LOG_ERR, "Only tap devices support switch mode!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find out which device file to open
|
||||||
|
|
||||||
if(!device) {
|
if(!device) {
|
||||||
if(device_type == DEVICE_TYPE_TAP)
|
if(device_type == DEVICE_TYPE_TAP)
|
||||||
device = xstrdup(DEFAULT_TAP_DEVICE);
|
device = xstrdup(DEFAULT_TAP_DEVICE);
|
||||||
|
@ -95,17 +169,7 @@ static bool setup_device(void) {
|
||||||
device = xstrdup(DEFAULT_TUN_DEVICE);
|
device = xstrdup(DEFAULT_TUN_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
|
// Open the device
|
||||||
iface = NULL;
|
|
||||||
#ifndef TAPGIFNAME
|
|
||||||
if (iface) {
|
|
||||||
logger(DEBUG_ALWAYS, LOG_WARNING, "Ignoring specified interface name '%s' as device rename is not supported on this platform", iface);
|
|
||||||
free(iface);
|
|
||||||
iface = NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (!iface)
|
|
||||||
iface = xstrdup(strrchr(device, '/') ? strrchr(device, '/') + 1 : device);
|
|
||||||
|
|
||||||
switch(device_type) {
|
switch(device_type) {
|
||||||
#ifdef ENABLE_TUNEMU
|
#ifdef ENABLE_TUNEMU
|
||||||
|
@ -114,6 +178,10 @@ static bool setup_device(void) {
|
||||||
device_fd = tunemu_open(dynamic_name);
|
device_fd = tunemu_open(dynamic_name);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NET_IF_UTUN_H
|
||||||
|
case DEVICE_TYPE_UTUN:
|
||||||
|
return setup_utun();
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
device_fd = open(device, O_RDWR | O_NONBLOCK);
|
device_fd = open(device, O_RDWR | O_NONBLOCK);
|
||||||
|
@ -128,6 +196,27 @@ static bool setup_device(void) {
|
||||||
fcntl(device_fd, F_SETFD, FD_CLOEXEC);
|
fcntl(device_fd, F_SETFD, FD_CLOEXEC);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Guess what the corresponding interface is called
|
||||||
|
|
||||||
|
char *realname;
|
||||||
|
|
||||||
|
#if defined(HAVE_FDEVNAME)
|
||||||
|
realname = fdevname(device_fd) ? : device;
|
||||||
|
#elif defined(HAVE_DEVNAME)
|
||||||
|
struct stat buf;
|
||||||
|
if(!fstat(device_fd, &buf))
|
||||||
|
realname = devname(buf.st_rdev, S_IFCHR) ? : device;
|
||||||
|
#else
|
||||||
|
realname = device;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
|
||||||
|
iface = xstrdup(strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname);
|
||||||
|
else if(strcmp(iface, strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname))
|
||||||
|
logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: Interface does not match Device. $INTERFACE might be set incorrectly.");
|
||||||
|
|
||||||
|
// Configure the device as best as we can
|
||||||
|
|
||||||
switch(device_type) {
|
switch(device_type) {
|
||||||
default:
|
default:
|
||||||
device_type = DEVICE_TYPE_TUN;
|
device_type = DEVICE_TYPE_TUN;
|
||||||
|
@ -192,6 +281,11 @@ static bool setup_device(void) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SIOCGIFADDR
|
||||||
|
if(overwrite_mac)
|
||||||
|
ioctl(device_fd, SIOCGIFADDR, mymac.x);
|
||||||
|
#endif
|
||||||
|
|
||||||
logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
|
logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -253,31 +347,29 @@ static bool read_packet(vpn_packet_t *packet) {
|
||||||
packet->len = inlen + 14;
|
packet->len = inlen + 14;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DEVICE_TYPE_UTUN:
|
||||||
case DEVICE_TYPE_TUNIFHEAD: {
|
case DEVICE_TYPE_TUNIFHEAD: {
|
||||||
u_int32_t type;
|
if((inlen = read(device_fd, DATA(packet) + 10, MTU - 10)) <= 0) {
|
||||||
struct iovec vector[2] = {{&type, sizeof type}, {DATA(packet) + 14, MTU - 14}};
|
|
||||||
|
|
||||||
if((inlen = readv(device_fd, vector, 2)) <= 0) {
|
|
||||||
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
|
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
|
||||||
device, strerror(errno));
|
device, strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ntohl(type)) {
|
switch (DATA(packet)[14] >> 4) {
|
||||||
case AF_INET:
|
case 4:
|
||||||
DATA(packet)[12] = 0x08;
|
DATA(packet)[12] = 0x08;
|
||||||
DATA(packet)[13] = 0x00;
|
DATA(packet)[13] = 0x00;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AF_INET6:
|
case 6:
|
||||||
DATA(packet)[12] = 0x86;
|
DATA(packet)[12] = 0x86;
|
||||||
DATA(packet)[13] = 0xDD;
|
DATA(packet)[13] = 0xDD;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
logger(DEBUG_TRAFFIC, LOG_ERR,
|
logger(DEBUG_TRAFFIC, LOG_ERR,
|
||||||
"Unknown address family %x while reading packet from %s %s",
|
"Unknown IP version %d while reading packet from %s %s",
|
||||||
ntohl(type), device_info, device);
|
DATA(packet)[14] >> 4, device_info, device);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,12 +411,10 @@ static bool write_packet(vpn_packet_t *packet) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DEVICE_TYPE_UTUN:
|
||||||
case DEVICE_TYPE_TUNIFHEAD: {
|
case DEVICE_TYPE_TUNIFHEAD: {
|
||||||
u_int32_t type;
|
int af = (DATA(packet)[12] << 8) + DATA(packet)[13];
|
||||||
struct iovec vector[2] = {{&type, sizeof type}, {DATA(packet) + 14, packet->len - 14}};
|
uint32_t type;
|
||||||
int af;
|
|
||||||
|
|
||||||
af = (DATA(packet)[12] << 8) + DATA(packet)[13];
|
|
||||||
|
|
||||||
switch (af) {
|
switch (af) {
|
||||||
case 0x0800:
|
case 0x0800:
|
||||||
|
@ -340,7 +430,9 @@ static bool write_packet(vpn_packet_t *packet) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(writev(device_fd, vector, 2) < 0) {
|
memcpy(DATA(packet) + 10, &type, sizeof type);
|
||||||
|
|
||||||
|
if(write(device_fd, DATA(packet) + 10, packet->len - 10) < 0) {
|
||||||
logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
|
logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -21,8 +21,9 @@
|
||||||
#ifndef __TINC_CONF_H__
|
#ifndef __TINC_CONF_H__
|
||||||
#define __TINC_CONF_H__
|
#define __TINC_CONF_H__
|
||||||
|
|
||||||
#include "splay_tree.h"
|
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
#include "splay_tree.h"
|
||||||
|
#include "subnet.h"
|
||||||
|
|
||||||
typedef struct config_t {
|
typedef struct config_t {
|
||||||
char *variable;
|
char *variable;
|
||||||
|
@ -31,7 +32,6 @@ typedef struct config_t {
|
||||||
int line;
|
int line;
|
||||||
} config_t;
|
} config_t;
|
||||||
|
|
||||||
#include "subnet.h"
|
|
||||||
|
|
||||||
extern splay_tree_t *config_tree;
|
extern splay_tree_t *config_tree;
|
||||||
extern bool use_logfile;
|
extern bool use_logfile;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../system.h"
|
#include "../system.h"
|
||||||
|
#include "../net.h"
|
||||||
|
|
||||||
#include <w32api/windows.h>
|
#include <w32api/windows.h>
|
||||||
#include <w32api/winioctl.h>
|
#include <w32api/winioctl.h>
|
||||||
|
@ -27,7 +28,6 @@
|
||||||
#include "../device.h"
|
#include "../device.h"
|
||||||
#include "../logger.h"
|
#include "../logger.h"
|
||||||
#include "../names.h"
|
#include "../names.h"
|
||||||
#include "../net.h"
|
|
||||||
#include "../route.h"
|
#include "../route.h"
|
||||||
#include "../utils.h"
|
#include "../utils.h"
|
||||||
#include "../xalloc.h"
|
#include "../xalloc.h"
|
||||||
|
@ -59,6 +59,9 @@ static bool setup_device(void) {
|
||||||
get_config_string(lookup_config(config_tree, "Device"), &device);
|
get_config_string(lookup_config(config_tree, "Device"), &device);
|
||||||
get_config_string(lookup_config(config_tree, "Interface"), &iface);
|
get_config_string(lookup_config(config_tree, "Interface"), &iface);
|
||||||
|
|
||||||
|
if(device && iface)
|
||||||
|
logger(LOG_WARNING, "Warning: both Device and Interface specified, results may not be as expected");
|
||||||
|
|
||||||
/* Open registry and look for network adapters */
|
/* Open registry and look for network adapters */
|
||||||
|
|
||||||
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &key)) {
|
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &key)) {
|
||||||
|
|
45
src/dropin.c
45
src/dropin.c
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
dropin.c -- a set of drop-in replacements for libc functions
|
dropin.c -- a set of drop-in replacements for libc functions
|
||||||
Copyright (C) 2000-2005 Ivo Timmermans,
|
Copyright (C) 2000-2005 Ivo Timmermans,
|
||||||
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
|
2000-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -86,40 +86,6 @@ int daemon(int nochdir, int noclose) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_GET_CURRENT_DIR_NAME
|
|
||||||
/*
|
|
||||||
Replacement for the GNU get_current_dir_name function:
|
|
||||||
|
|
||||||
get_current_dir_name will malloc(3) an array big enough to hold the
|
|
||||||
current directory name. If the environment variable PWD is set, and
|
|
||||||
its value is correct, then that value will be returned.
|
|
||||||
*/
|
|
||||||
char *get_current_dir_name(void) {
|
|
||||||
size_t size;
|
|
||||||
char *buf;
|
|
||||||
char *r;
|
|
||||||
|
|
||||||
/* Start with 100 bytes. If this turns out to be insufficient to
|
|
||||||
contain the working directory, double the size. */
|
|
||||||
size = 100;
|
|
||||||
buf = xmalloc(size);
|
|
||||||
|
|
||||||
errno = 0; /* Success */
|
|
||||||
r = getcwd(buf, size);
|
|
||||||
|
|
||||||
/* getcwd returns NULL and sets errno to ERANGE if the bufferspace
|
|
||||||
is insufficient to contain the entire working directory. */
|
|
||||||
while(r == NULL && errno == ERANGE) {
|
|
||||||
free(buf);
|
|
||||||
size <<= 1; /* double the size */
|
|
||||||
buf = xmalloc(size);
|
|
||||||
r = getcwd(buf, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef HAVE_ASPRINTF
|
#ifndef HAVE_ASPRINTF
|
||||||
int asprintf(char **buf, const char *fmt, ...) {
|
int asprintf(char **buf, const char *fmt, ...) {
|
||||||
int result;
|
int result;
|
||||||
|
@ -174,10 +140,9 @@ int gettimeofday(struct timeval *tv, void *tz) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_USLEEP
|
#ifndef HAVE_NANOSLEEP
|
||||||
int usleep(long long usec) {
|
int nanosleep(const struct timespec *req, struct timespec *rem) {
|
||||||
struct timeval tv = {usec / 1000000, (usec / 1000) % 1000};
|
struct timeval tv = {req->tv_sec, req->tv_nsec / 1000};
|
||||||
select(0, NULL, NULL, NULL, &tv);
|
return select(0, NULL, NULL, NULL, &tv);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
17
src/dropin.h
17
src/dropin.h
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
dropin.h -- header file for dropin.c
|
dropin.h -- header file for dropin.c
|
||||||
Copyright (C) 2000-2005 Ivo Timmermans,
|
Copyright (C) 2000-2005 Ivo Timmermans,
|
||||||
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
|
2000-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -21,17 +21,10 @@
|
||||||
#ifndef __DROPIN_H__
|
#ifndef __DROPIN_H__
|
||||||
#define __DROPIN_H__
|
#define __DROPIN_H__
|
||||||
|
|
||||||
#include "fake-getaddrinfo.h"
|
|
||||||
#include "fake-getnameinfo.h"
|
|
||||||
|
|
||||||
#ifndef HAVE_DAEMON
|
#ifndef HAVE_DAEMON
|
||||||
extern int daemon(int, int);
|
extern int daemon(int, int);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_GET_CURRENT_DIR_NAME
|
|
||||||
extern char *get_current_dir_name(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef HAVE_ASPRINTF
|
#ifndef HAVE_ASPRINTF
|
||||||
extern int asprintf(char **, const char *, ...);
|
extern int asprintf(char **, const char *, ...);
|
||||||
extern int vasprintf(char **, const char *, va_list ap);
|
extern int vasprintf(char **, const char *, va_list ap);
|
||||||
|
@ -41,8 +34,8 @@ extern int vasprintf(char **, const char *, va_list ap);
|
||||||
extern int gettimeofday(struct timeval *, void *);
|
extern int gettimeofday(struct timeval *, void *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_USLEEP
|
#ifndef HAVE_NANOSLEEP
|
||||||
extern int usleep(long long usec);
|
extern int nanosleep(const struct timespec *req, struct timespec *rem);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef timeradd
|
#ifndef timeradd
|
||||||
|
@ -70,4 +63,8 @@ extern int usleep(long long usec);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef EAI_SYSTEM
|
||||||
|
#define EAI_SYSTEM 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __DROPIN_H__ */
|
#endif /* __DROPIN_H__ */
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
/*
|
|
||||||
* fake library for ssh
|
|
||||||
*
|
|
||||||
* This file is included in getaddrinfo.c and getnameinfo.c.
|
|
||||||
* See getaddrinfo.c and getnameinfo.c.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* for old netdb.h */
|
|
||||||
#ifndef EAI_NODATA
|
|
||||||
#define EAI_NODATA 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef EAI_MEMORY
|
|
||||||
#define EAI_MEMORY 2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef EAI_FAMILY
|
|
||||||
#define EAI_FAMILY 3
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef EAI_SYSTEM
|
|
||||||
#define EAI_SYSTEM 4
|
|
||||||
#endif
|
|
|
@ -1,102 +0,0 @@
|
||||||
/*
|
|
||||||
* fake library for ssh
|
|
||||||
*
|
|
||||||
* This file includes getaddrinfo(), freeaddrinfo() and gai_strerror().
|
|
||||||
* These funtions are defined in rfc2133.
|
|
||||||
*
|
|
||||||
* But these functions are not implemented correctly. The minimum subset
|
|
||||||
* is implemented for ssh use only. For exapmle, this routine assumes
|
|
||||||
* that ai_family is AF_INET. Don't use it for another purpose.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "system.h"
|
|
||||||
|
|
||||||
#include "ipv4.h"
|
|
||||||
#include "ipv6.h"
|
|
||||||
#include "fake-getaddrinfo.h"
|
|
||||||
#include "xalloc.h"
|
|
||||||
|
|
||||||
|
|
||||||
#if !HAVE_DECL_GAI_STRERROR
|
|
||||||
char *gai_strerror(int ecode) {
|
|
||||||
switch (ecode) {
|
|
||||||
case EAI_NODATA:
|
|
||||||
return "No address associated with hostname";
|
|
||||||
case EAI_MEMORY:
|
|
||||||
return "Memory allocation failure";
|
|
||||||
case EAI_FAMILY:
|
|
||||||
return "Address family not supported";
|
|
||||||
default:
|
|
||||||
return "Unknown error";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* !HAVE_GAI_STRERROR */
|
|
||||||
|
|
||||||
#if !HAVE_DECL_FREEADDRINFO
|
|
||||||
void freeaddrinfo(struct addrinfo *ai) {
|
|
||||||
struct addrinfo *next;
|
|
||||||
|
|
||||||
while(ai) {
|
|
||||||
next = ai->ai_next;
|
|
||||||
free(ai);
|
|
||||||
ai = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* !HAVE_FREEADDRINFO */
|
|
||||||
|
|
||||||
#if !HAVE_DECL_GETADDRINFO
|
|
||||||
static struct addrinfo *malloc_ai(uint16_t port, uint32_t addr) {
|
|
||||||
struct addrinfo *ai;
|
|
||||||
|
|
||||||
ai = xzalloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
|
|
||||||
|
|
||||||
ai->ai_addr = (struct sockaddr *)(ai + 1);
|
|
||||||
ai->ai_addrlen = sizeof(struct sockaddr_in);
|
|
||||||
ai->ai_addr->sa_family = ai->ai_family = AF_INET;
|
|
||||||
|
|
||||||
((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
|
|
||||||
((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
|
|
||||||
|
|
||||||
return ai;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res) {
|
|
||||||
struct addrinfo *prev = NULL;
|
|
||||||
struct hostent *hp;
|
|
||||||
struct in_addr in = {0};
|
|
||||||
int i;
|
|
||||||
uint16_t port = 0;
|
|
||||||
|
|
||||||
if(hints && hints->ai_family != AF_INET && hints->ai_family != AF_UNSPEC)
|
|
||||||
return EAI_FAMILY;
|
|
||||||
|
|
||||||
if (servname)
|
|
||||||
port = htons(atoi(servname));
|
|
||||||
|
|
||||||
if (hints && hints->ai_flags & AI_PASSIVE) {
|
|
||||||
*res = malloc_ai(port, htonl(0x00000000));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hostname) {
|
|
||||||
*res = malloc_ai(port, htonl(0x7f000001));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
hp = gethostbyname(hostname);
|
|
||||||
|
|
||||||
if(!hp || !hp->h_addr_list || !hp->h_addr_list[0])
|
|
||||||
return EAI_NODATA;
|
|
||||||
|
|
||||||
for (i = 0; hp->h_addr_list[i]; i++) {
|
|
||||||
*res = malloc_ai(port, ((struct in_addr *)hp->h_addr_list[i])->s_addr);
|
|
||||||
|
|
||||||
if(prev)
|
|
||||||
prev->ai_next = *res;
|
|
||||||
|
|
||||||
prev = *res;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /* !HAVE_GETADDRINFO */
|
|
|
@ -1,46 +0,0 @@
|
||||||
#ifndef _FAKE_GETADDRINFO_H
|
|
||||||
#define _FAKE_GETADDRINFO_H
|
|
||||||
|
|
||||||
#include "fake-gai-errnos.h"
|
|
||||||
|
|
||||||
#ifndef AI_PASSIVE
|
|
||||||
# define AI_PASSIVE 1
|
|
||||||
# define AI_CANONNAME 2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef NI_NUMERICHOST
|
|
||||||
# define NI_NUMERICHOST 2
|
|
||||||
# define NI_NAMEREQD 4
|
|
||||||
# define NI_NUMERICSERV 8
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AI_NUMERICHOST
|
|
||||||
#define AI_NUMERICHOST 4
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef HAVE_STRUCT_ADDRINFO
|
|
||||||
struct addrinfo {
|
|
||||||
int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
|
|
||||||
int ai_family; /* PF_xxx */
|
|
||||||
int ai_socktype; /* SOCK_xxx */
|
|
||||||
int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
|
|
||||||
size_t ai_addrlen; /* length of ai_addr */
|
|
||||||
char *ai_canonname; /* canonical name for hostname */
|
|
||||||
struct sockaddr *ai_addr; /* binary address */
|
|
||||||
struct addrinfo *ai_next; /* next structure in linked list */
|
|
||||||
};
|
|
||||||
#endif /* !HAVE_STRUCT_ADDRINFO */
|
|
||||||
|
|
||||||
#if !HAVE_DECL_GETADDRINFO
|
|
||||||
int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res);
|
|
||||||
#endif /* !HAVE_GETADDRINFO */
|
|
||||||
|
|
||||||
#if !HAVE_DECL_GAI_STRERROR
|
|
||||||
char *gai_strerror(int ecode);
|
|
||||||
#endif /* !HAVE_GAI_STRERROR */
|
|
||||||
|
|
||||||
#if !HAVE_DECL_FREEADDRINFO
|
|
||||||
void freeaddrinfo(struct addrinfo *ai);
|
|
||||||
#endif /* !HAVE_FREEADDRINFO */
|
|
||||||
|
|
||||||
#endif /* _FAKE_GETADDRINFO_H */
|
|
|
@ -1,54 +0,0 @@
|
||||||
/*
|
|
||||||
* fake library for ssh
|
|
||||||
*
|
|
||||||
* This file includes getnameinfo().
|
|
||||||
* These funtions are defined in rfc2133.
|
|
||||||
*
|
|
||||||
* But these functions are not implemented correctly. The minimum subset
|
|
||||||
* is implemented for ssh use only. For exapmle, this routine assumes
|
|
||||||
* that ai_family is AF_INET. Don't use it for another purpose.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "system.h"
|
|
||||||
|
|
||||||
#include "fake-getnameinfo.h"
|
|
||||||
#include "fake-getaddrinfo.h"
|
|
||||||
|
|
||||||
#if !HAVE_DECL_GETNAMEINFO
|
|
||||||
|
|
||||||
int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) {
|
|
||||||
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
|
|
||||||
struct hostent *hp;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
if(sa->sa_family != AF_INET)
|
|
||||||
return EAI_FAMILY;
|
|
||||||
|
|
||||||
if(serv && servlen) {
|
|
||||||
len = snprintf(serv, servlen, "%d", ntohs(sin->sin_port));
|
|
||||||
if(len < 0 || len >= servlen)
|
|
||||||
return EAI_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!host || !hostlen)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if(flags & NI_NUMERICHOST) {
|
|
||||||
len = snprintf(host, hostlen, "%s", inet_ntoa(sin->sin_addr));
|
|
||||||
if(len < 0 || len >= hostlen)
|
|
||||||
return EAI_MEMORY;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
hp = gethostbyaddr((char *)&sin->sin_addr, sizeof(struct in_addr), AF_INET);
|
|
||||||
|
|
||||||
if(!hp || !hp->h_name || !hp->h_name[0])
|
|
||||||
return EAI_NODATA;
|
|
||||||
|
|
||||||
len = snprintf(host, hostlen, "%s", hp->h_name);
|
|
||||||
if(len < 0 || len >= hostlen)
|
|
||||||
return EAI_MEMORY;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /* !HAVE_GETNAMEINFO */
|
|
|
@ -1,15 +0,0 @@
|
||||||
#ifndef _FAKE_GETNAMEINFO_H
|
|
||||||
#define _FAKE_GETNAMEINFO_H
|
|
||||||
|
|
||||||
#if !HAVE_DECL_GETNAMEINFO
|
|
||||||
int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags);
|
|
||||||
#endif /* !HAVE_GETNAMEINFO */
|
|
||||||
|
|
||||||
#ifndef NI_MAXSERV
|
|
||||||
# define NI_MAXSERV 32
|
|
||||||
#endif /* !NI_MAXSERV */
|
|
||||||
#ifndef NI_MAXHOST
|
|
||||||
# define NI_MAXHOST 1025
|
|
||||||
#endif /* !NI_MAXHOST */
|
|
||||||
|
|
||||||
#endif /* _FAKE_GETNAMEINFO_H */
|
|
16
src/fsck.c
16
src/fsck.c
|
@ -217,6 +217,7 @@ int fsck(const char *argv0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(HAVE_MINGW) && !defined(HAVE_CYGWIN)
|
||||||
if(st.st_mode & 077) {
|
if(st.st_mode & 077) {
|
||||||
fprintf(stderr, "WARNING: unsafe file permissions on %s.\n", fname);
|
fprintf(stderr, "WARNING: unsafe file permissions on %s.\n", fname);
|
||||||
if(st.st_uid != uid) {
|
if(st.st_uid != uid) {
|
||||||
|
@ -228,6 +229,7 @@ int fsck(const char *argv0) {
|
||||||
fprintf(stderr, "Fixed permissions of %s.\n", fname);
|
fprintf(stderr, "Fixed permissions of %s.\n", fname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -256,6 +258,7 @@ int fsck(const char *argv0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(HAVE_MINGW) && !defined(HAVE_CYGWIN)
|
||||||
if(st.st_mode & 077) {
|
if(st.st_mode & 077) {
|
||||||
fprintf(stderr, "WARNING: unsafe file permissions on %s.\n", fname);
|
fprintf(stderr, "WARNING: unsafe file permissions on %s.\n", fname);
|
||||||
if(st.st_uid != uid) {
|
if(st.st_uid != uid) {
|
||||||
|
@ -267,6 +270,7 @@ int fsck(const char *argv0) {
|
||||||
fprintf(stderr, "Fixed permissions of %s.\n", fname);
|
fprintf(stderr, "Fixed permissions of %s.\n", fname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DISABLE_LEGACY
|
#ifdef DISABLE_LEGACY
|
||||||
|
@ -282,7 +286,7 @@ int fsck(const char *argv0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for public keys.
|
// Check for public keys.
|
||||||
// TODO: use RSAPublicKeyFile and Ed25519PublicKeyFile variables if present.
|
// TODO: use RSAPublicKeyFile variable if present.
|
||||||
|
|
||||||
snprintf(fname, sizeof fname, "%s/hosts/%s", confbase, name);
|
snprintf(fname, sizeof fname, "%s/hosts/%s", confbase, name);
|
||||||
if(access(fname, R_OK))
|
if(access(fname, R_OK))
|
||||||
|
@ -343,13 +347,17 @@ int fsck(const char *argv0) {
|
||||||
fprintf(stderr, "WARNING: A public RSA key was found but no private key is known.\n");
|
fprintf(stderr, "WARNING: A public RSA key was found but no private key is known.\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
//
|
|
||||||
// TODO: this should read the Ed25519PublicKey config variable instead.
|
|
||||||
ecdsa_t *ecdsa_pub = NULL;
|
ecdsa_t *ecdsa_pub = NULL;
|
||||||
|
|
||||||
f = fopen(fname, "r");
|
f = fopen(fname, "r");
|
||||||
if(f)
|
if(f) {
|
||||||
|
ecdsa_pub = get_pubkey(f);
|
||||||
|
if(!f) {
|
||||||
|
rewind(f);
|
||||||
ecdsa_pub = ecdsa_read_pem_public_key(f);
|
ecdsa_pub = ecdsa_read_pem_public_key(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
if(ecdsa_priv) {
|
if(ecdsa_priv) {
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
/*
|
|
||||||
ecdsa.c -- ECDSA key handling
|
|
||||||
Copyright (C) 2011-2013 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 "../logger.h"
|
|
||||||
#include "../ecdsa.h"
|
|
||||||
#include "../utils.h"
|
|
||||||
#include "../xalloc.h"
|
|
||||||
|
|
||||||
// Get and set ECDSA keys
|
|
||||||
//
|
|
||||||
ecdsa_t *ecdsa_set_base64_public_key(const char *p) {
|
|
||||||
logger(DEBUG_ALWAYS, LOG_ERR, "EC support using libgcrypt not implemented");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read PEM ECDSA keys
|
|
||||||
|
|
||||||
ecdsa_t *ecdsa_read_pem_public_key(FILE *fp) {
|
|
||||||
logger(DEBUG_ALWAYS, LOG_ERR, "EC support using libgcrypt not implemented");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ecdsa_t *ecdsa_read_pem_private_key(FILE *fp) {
|
|
||||||
logger(DEBUG_ALWAYS, LOG_ERR, "EC support using libgcrypt not implemented");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ecdsa_size(ecdsa_t *ecdsa) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t len, void *sig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ecdsa_verify(ecdsa_t *ecdsa, const void *in, size_t len, const void *sig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ecdsa_active(ecdsa_t *ecdsa) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ecdsa_free(ecdsa_t *ecdsa) {
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
ecdsagen.c -- ECDSA key generation and export
|
|
||||||
Copyright (C) 2011-2013 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 "../ecdsagen.h"
|
|
||||||
#include "../utils.h"
|
|
||||||
#include "../xalloc.h"
|
|
||||||
|
|
||||||
// Generate ECDSA key
|
|
||||||
|
|
||||||
ecdsa_t *ecdsa_generate(void) {
|
|
||||||
logger(DEBUG_ALWAYS, LOG_ERR, "EC support using libgcrypt not implemented");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write PEM ECDSA keys
|
|
||||||
|
|
||||||
bool ecdsa_write_pem_public_key(ecdsa_t *ecdsa, FILE *fp) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ecdsa_write_pem_private_key(ecdsa_t *ecdsa, FILE *fp) {
|
|
||||||
return false;
|
|
||||||
}
|
|
|
@ -19,11 +19,88 @@
|
||||||
|
|
||||||
#include "../system.h"
|
#include "../system.h"
|
||||||
|
|
||||||
#include "digest.h"
|
|
||||||
#include "../digest.h"
|
|
||||||
#include "../prf.h"
|
#include "../prf.h"
|
||||||
|
#include "../ed25519/sha512.h"
|
||||||
|
|
||||||
|
static void memxor(char *buf, char c, size_t len) {
|
||||||
|
for(size_t i = 0; i < len; i++)
|
||||||
|
buf[i] ^= c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const size_t mdlen = 64;
|
||||||
|
static const size_t blklen = 128;
|
||||||
|
|
||||||
|
static bool hmac_sha512(const char *key, size_t keylen, const char *msg, size_t msglen, char *out) {
|
||||||
|
char tmp[blklen + mdlen];
|
||||||
|
sha512_context md;
|
||||||
|
|
||||||
|
if(keylen <= blklen) {
|
||||||
|
memcpy(tmp, key, keylen);
|
||||||
|
memset(tmp + keylen, 0, blklen - keylen);
|
||||||
|
} else {
|
||||||
|
if(sha512(key, keylen, tmp) != 0)
|
||||||
|
return false;
|
||||||
|
memset(tmp + mdlen, 0, blklen - mdlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sha512_init(&md) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// ipad
|
||||||
|
memxor(tmp, 0x36, blklen);
|
||||||
|
if(sha512_update(&md, tmp, blklen) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// message
|
||||||
|
if(sha512_update(&md, msg, msglen) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(sha512_final(&md, tmp + blklen) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// opad
|
||||||
|
memxor(tmp, 0x36 ^ 0x5c, blklen);
|
||||||
|
if(sha512(tmp, sizeof tmp, out) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Generate key material from a master secret and a seed, based on RFC 4346 section 5.
|
||||||
|
We use SHA512 instead of MD5 and SHA1.
|
||||||
|
*/
|
||||||
|
|
||||||
bool prf(const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, size_t outlen) {
|
bool prf(const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, size_t outlen) {
|
||||||
logger(DEBUG_ALWAYS, LOG_ERR, "PRF support using libgcrypt not implemented");
|
/* Data is what the "inner" HMAC function processes.
|
||||||
|
It consists of the previous HMAC result plus the seed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
char data[mdlen + seedlen];
|
||||||
|
memset(data, 0, mdlen);
|
||||||
|
memcpy(data + mdlen, seed, seedlen);
|
||||||
|
|
||||||
|
char hash[mdlen];
|
||||||
|
|
||||||
|
while(outlen > 0) {
|
||||||
|
/* Inner HMAC */
|
||||||
|
if(!hmac_sha512(secret, secretlen, data, sizeof data, data))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
/* Outer HMAC */
|
||||||
|
if(outlen >= mdlen) {
|
||||||
|
if(!hmac_sha512(secret, secretlen, data, sizeof data, out))
|
||||||
|
return false;
|
||||||
|
out += mdlen;
|
||||||
|
outlen -= mdlen;
|
||||||
|
} else {
|
||||||
|
if(!hmac_sha512(secret, secretlen, data, sizeof data, hash))
|
||||||
|
return false;
|
||||||
|
memcpy(out, hash, outlen);
|
||||||
|
out += outlen;
|
||||||
|
outlen = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
25
src/have.h
25
src/have.h
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
have.h -- include headers which are known to exist
|
have.h -- include headers which are known to exist
|
||||||
Copyright (C) 1998-2005 Ivo Timmermans
|
Copyright (C) 1998-2005 Ivo Timmermans
|
||||||
2003-2013 Guus Sliepen <guus@tinc-vpn.org>
|
2003-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -22,17 +22,14 @@
|
||||||
#define __TINC_HAVE_H__
|
#define __TINC_HAVE_H__
|
||||||
|
|
||||||
#ifdef HAVE_MINGW
|
#ifdef HAVE_MINGW
|
||||||
#ifdef WITH_WINDOWS2000
|
|
||||||
#define WINVER Windows2000
|
|
||||||
#else
|
|
||||||
#define WINVER WindowsXP
|
#define WINVER WindowsXP
|
||||||
#endif
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
@ -41,6 +38,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#ifdef HAVE_MINGW
|
#ifdef HAVE_MINGW
|
||||||
#include <w32api.h>
|
#include <w32api.h>
|
||||||
|
@ -49,10 +47,6 @@
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_STDBOOL_H
|
|
||||||
#include <stdbool.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_TERMIOS_H
|
#ifdef HAVE_TERMIOS_H
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -71,9 +65,6 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_TIME_H
|
|
||||||
#include <time.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -103,10 +94,6 @@
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SYS_UIO_H
|
|
||||||
#include <sys/uio.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_SYS_UN_H
|
#ifdef HAVE_SYS_UN_H
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -210,6 +197,12 @@
|
||||||
#include <linux/if_tun.h>
|
#include <linux/if_tun.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_GETOPT_H
|
||||||
|
#include <getopt.h>
|
||||||
|
#else
|
||||||
|
#include "getopt.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef STATUS
|
#ifdef STATUS
|
||||||
#undef STATUS
|
#undef STATUS
|
||||||
#endif
|
#endif
|
||||||
|
|
198
src/ifconfig.c
Normal file
198
src/ifconfig.c
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
/*
|
||||||
|
ifconfig.c -- Generate platform specific interface configuration commands
|
||||||
|
Copyright (C) 2016 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 "conf.h"
|
||||||
|
#include "ifconfig.h"
|
||||||
|
#include "subnet.h"
|
||||||
|
|
||||||
|
static long start;
|
||||||
|
|
||||||
|
#ifndef HAVE_MINGW
|
||||||
|
void ifconfig_header(FILE *out) {
|
||||||
|
fprintf(out, "#!/bin/sh\n");
|
||||||
|
start = ftell(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ifconfig_dhcp(FILE *out) {
|
||||||
|
fprintf(out, "dhclient -nw \"$INTERFACE\"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ifconfig_dhcp6(FILE *out) {
|
||||||
|
fprintf(out, "dhclient -6 -nw \"$INTERFACE\"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ifconfig_slaac(FILE *out) {
|
||||||
|
#ifdef HAVE_LINUX
|
||||||
|
fprintf(out, "echo 1 >\"/proc/sys/net/ipv6/conf/$INTERFACE/accept_ra\"\n");
|
||||||
|
fprintf(out, "echo 1 >\"/proc/sys/net/ipv6/conf/$INTERFACE/autoconf\"\n");
|
||||||
|
#else
|
||||||
|
fprintf(out, "rtsol \"$INTERFACE\" &\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ifconfig_footer(FILE *out) {
|
||||||
|
if(ftell(out) == start) {
|
||||||
|
fprintf(out, "echo 'Unconfigured tinc-up script, please edit '$0'!'\n\n#ifconfig $INTERFACE <your vpn IP address> netmask <netmask of whole VPN>\n");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
#ifdef HAVE_LINUX
|
||||||
|
fprintf(out, "ip link set \"$INTERFACE\" up\n");
|
||||||
|
#else
|
||||||
|
fprintf(out, "ifconfig \"$INTERFACE\" up\n");
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void ifconfig_header(FILE *out) {
|
||||||
|
start = ftell(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ifconfig_dhcp(FILE *out) {
|
||||||
|
fprintf(out, "netsh interface ipv4 set address \"%%INTERFACE%%\" dhcp\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ifconfig_dhcp6(FILE *out) {
|
||||||
|
fprintf(stderr, "DHCPv6 requested, but not supported by tinc on this platform\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ifconfig_slaac(FILE *out) {
|
||||||
|
// It's the default?
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ifconfig_footer(FILE *out) {
|
||||||
|
return ftell(out) != start;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static subnet_t ipv4, ipv6;
|
||||||
|
|
||||||
|
void ifconfig_address(FILE *out, const char *value) {
|
||||||
|
subnet_t address = {};
|
||||||
|
char address_str[MAXNETSTR];
|
||||||
|
if(!str2net(&address, value) || !net2str(address_str, sizeof address_str, &address)) {
|
||||||
|
fprintf(stderr, "Could not parse address in Ifconfig statement\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch(address.type) {
|
||||||
|
case SUBNET_IPV4: ipv4 = address; break;
|
||||||
|
case SUBNET_IPV6: ipv6 = address; break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
#if defined(HAVE_LINUX)
|
||||||
|
switch(address.type) {
|
||||||
|
case SUBNET_MAC: fprintf(out, "ip link set \"$INTERFACE\" address %s\n", address_str); break;
|
||||||
|
case SUBNET_IPV4: fprintf(out, "ip addr replace %s dev \"$INTERFACE\"\n", address_str); break;
|
||||||
|
case SUBNET_IPV6: fprintf(out, "ip addr replace %s dev \"$INTERFACE\"\n", address_str); break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
#elif defined(HAVE_BSD)
|
||||||
|
switch(address.type) {
|
||||||
|
case SUBNET_MAC: fprintf(out, "ifconfig \"$INTERFACE\" link %s\n", address_str); break;
|
||||||
|
case SUBNET_IPV4: fprintf(out, "ifconfig \"$INTERFACE\" %s\n", address_str); break;
|
||||||
|
case SUBNET_IPV6: fprintf(out, "ifconfig \"$INTERFACE\" inet6 %s\n", address_str); break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
#elif defined(HAVE_MINGW) || defined(HAVE_CYGWIN)
|
||||||
|
switch(address.type) {
|
||||||
|
case SUBNET_MAC: fprintf(out, "ip link set \"$INTERFACE\" address %s\n", address_str); break;
|
||||||
|
case SUBNET_IPV4: fprintf(out, "netsh inetface ipv4 set address \"$INTERFACE\" static %s\n", address_str); break;
|
||||||
|
case SUBNET_IPV6: fprintf(out, "netsh inetface ipv6 set address \"$INTERFACE\" static %s\n", address_str); break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void ifconfig_route(FILE *out, const char *value) {
|
||||||
|
subnet_t subnet = {}, gateway = {};
|
||||||
|
char subnet_str[MAXNETSTR] = "", gateway_str[MAXNETSTR] = "";
|
||||||
|
char *sep = strchr(value, ' ');
|
||||||
|
if(sep)
|
||||||
|
*sep++ = 0;
|
||||||
|
if(!str2net(&subnet, value) || !net2str(subnet_str, sizeof subnet_str, &subnet) || subnet.type == SUBNET_MAC) {
|
||||||
|
fprintf(stderr, "Could not parse subnet in Route statement\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(sep) {
|
||||||
|
if(!str2net(&gateway, sep) || !net2str(gateway_str, sizeof gateway_str, &gateway) || gateway.type != subnet.type) {
|
||||||
|
fprintf(stderr, "Could not parse gateway in Route statement\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char *slash = strchr(gateway_str, '/'); if(slash) *slash = 0;
|
||||||
|
}
|
||||||
|
#if defined(HAVE_LINUX)
|
||||||
|
if(*gateway_str) {
|
||||||
|
switch(subnet.type) {
|
||||||
|
case SUBNET_IPV4: fprintf(out, "ip route add %s via %s dev \"$INTERFACE\"\n", subnet_str, gateway_str); break;
|
||||||
|
case SUBNET_IPV6: fprintf(out, "ip route add %s via %s dev \"$INTERFACE\"\n", subnet_str, gateway_str); break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch(subnet.type) {
|
||||||
|
case SUBNET_IPV4: fprintf(out, "ip route add %s dev \"$INTERFACE\"\n", subnet_str); break;
|
||||||
|
case SUBNET_IPV6: fprintf(out, "ip route add %s dev \"$INTERFACE\"\n", subnet_str); break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#elif defined(HAVE_BSD)
|
||||||
|
// BSD route command is silly and doesn't accept an interface name as a destination.
|
||||||
|
if(!*gateway_str) {
|
||||||
|
switch(subnet.type) {
|
||||||
|
case SUBNET_IPV4:
|
||||||
|
if(!ipv4.type) {
|
||||||
|
fprintf(stderr, "Route requested but no Ifconfig\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
net2str(gateway_str, sizeof gateway_str, &ipv4);
|
||||||
|
break;
|
||||||
|
case SUBNET_IPV6:
|
||||||
|
if(!ipv6.type) {
|
||||||
|
fprintf(stderr, "Route requested but no Ifconfig\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
net2str(gateway_str, sizeof gateway_str, &ipv6);
|
||||||
|
break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
char *slash = strchr(gateway_str, '/'); if(slash) *slash = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(subnet.type) {
|
||||||
|
case SUBNET_IPV4: fprintf(out, "route add %s %s\n", subnet_str, gateway_str); break;
|
||||||
|
case SUBNET_IPV6: fprintf(out, "route add -inet6 %s %s\n", subnet_str, gateway_str); break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
#elif defined(HAVE_MINGW) || defined(HAVE_CYGWIN)
|
||||||
|
if(*gateway_str) {
|
||||||
|
switch(subnet.type) {
|
||||||
|
case SUBNET_IPV4: fprintf(out, "netsh inetface ipv4 add route %s \"%%INTERFACE%%\" %s\n", subnet_str, gateway_str); break;
|
||||||
|
case SUBNET_IPV6: fprintf(out, "netsh inetface ipv6 add route %s \"%%INTERFACE%%\" %s\n", subnet_str, gateway_str); break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch(subnet.type) {
|
||||||
|
case SUBNET_IPV4: fprintf(out, "netsh inetface ipv4 add route %s \"%%INTERFACE%%\"\n", subnet_str); break;
|
||||||
|
case SUBNET_IPV6: fprintf(out, "netsh inetface ipv6 add route %s \"%%INTERFACE%%\"\n", subnet_str); break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
ecdh.c -- Diffie-Hellman key exchange handling
|
ifconfig.h -- header for ifconfig.c.
|
||||||
Copyright (C) 2011-2013 Guus Sliepen <guus@tinc-vpn.org>
|
Copyright (C) 2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -17,21 +17,15 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../system.h"
|
#ifndef __TINC_IFCONFIG_H__
|
||||||
|
#define __TINC_IFCONFIG_H__
|
||||||
|
|
||||||
#include "../ecdh.h"
|
extern void ifconfig_dhcp(FILE *out);
|
||||||
#include "../logger.h"
|
extern void ifconfig_dhcp6(FILE *out);
|
||||||
#include "../utils.h"
|
extern void ifconfig_slaac(FILE *out);
|
||||||
#include "../xalloc.h"
|
extern void ifconfig_address(FILE *out, const char *value);
|
||||||
|
extern void ifconfig_route(FILE *out, const char *value);
|
||||||
|
extern void ifconfig_header(FILE *out);
|
||||||
|
extern bool ifconfig_footer(FILE *out);
|
||||||
|
|
||||||
ecdh_t *ecdh_generate_public(void *pubkey) {
|
#endif
|
||||||
logger(DEBUG_ALWAYS, LOG_ERR, "EC support using libgcrypt not implemented");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ecdh_compute_shared(ecdh_t *ecdh, const void *pubkey, void *shared) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
void ecdh_free(ecdh_t *ecdh) {
|
|
||||||
}
|
|
|
@ -23,12 +23,14 @@
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "ecdsa.h"
|
#include "ecdsa.h"
|
||||||
#include "ecdsagen.h"
|
#include "ecdsagen.h"
|
||||||
|
#include "ifconfig.h"
|
||||||
#include "invitation.h"
|
#include "invitation.h"
|
||||||
#include "names.h"
|
#include "names.h"
|
||||||
#include "netutl.h"
|
#include "netutl.h"
|
||||||
#include "rsagen.h"
|
#include "rsagen.h"
|
||||||
#include "script.h"
|
#include "script.h"
|
||||||
#include "sptps.h"
|
#include "sptps.h"
|
||||||
|
#include "subnet.h"
|
||||||
#include "tincctl.h"
|
#include "tincctl.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "xalloc.h"
|
#include "xalloc.h"
|
||||||
|
@ -390,7 +392,7 @@ int cmd_invite(int argc, char *argv[]) {
|
||||||
|
|
||||||
// Fill in the details.
|
// Fill in the details.
|
||||||
fprintf(f, "Name = %s\n", argv[1]);
|
fprintf(f, "Name = %s\n", argv[1]);
|
||||||
if(netname)
|
if(check_netname(netname, true))
|
||||||
fprintf(f, "NetName = %s\n", netname);
|
fprintf(f, "NetName = %s\n", netname);
|
||||||
fprintf(f, "ConnectTo = %s\n", myname);
|
fprintf(f, "ConnectTo = %s\n", myname);
|
||||||
|
|
||||||
|
@ -539,12 +541,17 @@ static bool finalize_join(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!check_id(name)) {
|
if(!check_id(name)) {
|
||||||
fprintf(stderr, "Invalid Name found in invitation: %s!\n", name);
|
fprintf(stderr, "Invalid Name found in invitation!\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!netname)
|
if(!netname) {
|
||||||
netname = grep(data, "NetName");
|
netname = grep(data, "NetName");
|
||||||
|
if(netname && !check_netname(netname, true)) {
|
||||||
|
fprintf(stderr, "Unsafe NetName found in invitation!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool ask_netname = false;
|
bool ask_netname = false;
|
||||||
char temp_netname[32];
|
char temp_netname[32];
|
||||||
|
@ -602,7 +609,19 @@ make_names:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snprintf(filename, sizeof filename, "%s" SLASH "tinc-up.invitation", confbase);
|
||||||
|
FILE *fup = fopen(filename, "w");
|
||||||
|
if(!fup) {
|
||||||
|
fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno));
|
||||||
|
fclose(f);
|
||||||
|
fclose(fh);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifconfig_header(fup);
|
||||||
|
|
||||||
// Filter first chunk on approved keywords, split between tinc.conf and hosts/Name
|
// Filter first chunk on approved keywords, split between tinc.conf and hosts/Name
|
||||||
|
// Generate a tinc-up script from Ifconfig and Route keywords.
|
||||||
// Other chunks go unfiltered to their respective host config files
|
// Other chunks go unfiltered to their respective host config files
|
||||||
const char *p = data;
|
const char *p = data;
|
||||||
char *l, *value = NULL;
|
char *l, *value = NULL;
|
||||||
|
@ -641,6 +660,24 @@ make_names:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle Ifconfig and Route statements
|
||||||
|
if(!found) {
|
||||||
|
if(!strcasecmp(l, "Ifconfig")) {
|
||||||
|
if(!strcasecmp(value, "dhcp"))
|
||||||
|
ifconfig_dhcp(fup);
|
||||||
|
else if(!strcasecmp(value, "dhcp6"))
|
||||||
|
ifconfig_dhcp6(fup);
|
||||||
|
else if(!strcasecmp(value, "slaac"))
|
||||||
|
ifconfig_slaac(fup);
|
||||||
|
else
|
||||||
|
ifconfig_address(fup, value);
|
||||||
|
continue;
|
||||||
|
} else if(!strcasecmp(l, "Route")) {
|
||||||
|
ifconfig_route(fup, value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Ignore unknown and unsafe variables
|
// Ignore unknown and unsafe variables
|
||||||
if(!found) {
|
if(!found) {
|
||||||
fprintf(stderr, "Ignoring unknown variable '%s' in invitation.\n", l);
|
fprintf(stderr, "Ignoring unknown variable '%s' in invitation.\n", l);
|
||||||
|
@ -655,6 +692,8 @@ make_names:
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
bool valid_tinc_up = ifconfig_footer(fup);
|
||||||
|
fclose(fup);
|
||||||
|
|
||||||
while(l && !strcasecmp(l, "Name")) {
|
while(l && !strcasecmp(l, "Name")) {
|
||||||
if(!check_id(value)) {
|
if(!check_id(value)) {
|
||||||
|
@ -769,6 +808,60 @@ ask_netname:
|
||||||
make_names(false);
|
make_names(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char filename2[PATH_MAX];
|
||||||
|
snprintf(filename, sizeof filename, "%s" SLASH "tinc-up.invitation", confbase);
|
||||||
|
snprintf(filename2, sizeof filename2, "%s" SLASH "tinc-up", confbase);
|
||||||
|
|
||||||
|
if(valid_tinc_up) {
|
||||||
|
if(tty) {
|
||||||
|
FILE *fup = fopen(filename, "r");
|
||||||
|
if(fup) {
|
||||||
|
fprintf(stderr, "\nPlease review the following tinc-up script:\n\n");
|
||||||
|
|
||||||
|
char buf[MAXSIZE];
|
||||||
|
while(fgets(buf, sizeof buf, fup))
|
||||||
|
fputs(buf, stderr);
|
||||||
|
fclose(fup);
|
||||||
|
|
||||||
|
int response = 0;
|
||||||
|
do {
|
||||||
|
fprintf(stderr, "\nDo you want to use this script [y]es/[n]o/[e]dit? ");
|
||||||
|
response = tolower(getchar());
|
||||||
|
} while(!strchr("yne", response));
|
||||||
|
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
|
if(response == 'e') {
|
||||||
|
char *command;
|
||||||
|
#ifndef HAVE_MINGW
|
||||||
|
xasprintf(&command, "\"%s\" \"%s\"", getenv("VISUAL") ?: getenv("EDITOR") ?: "vi", filename);
|
||||||
|
#else
|
||||||
|
xasprintf(&command, "edit \"%s\"", filename);
|
||||||
|
#endif
|
||||||
|
if(system(command))
|
||||||
|
response = 'n';
|
||||||
|
else
|
||||||
|
response = 'y';
|
||||||
|
free(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(response == 'y') {
|
||||||
|
rename(filename, filename2);
|
||||||
|
chmod(filename2, 0755);
|
||||||
|
fprintf(stderr, "tinc-up enabled.\n");
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "tinc-up has been left disabled.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "A tinc-up script was generated, but has been left disabled.\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// A placeholder was generated.
|
||||||
|
rename(filename, filename2);
|
||||||
|
chmod(filename2, 0755);
|
||||||
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Configuration stored in: %s\n", confbase);
|
fprintf(stderr, "Configuration stored in: %s\n", confbase);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
25
src/ipv6.h
25
src/ipv6.h
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
ipv6.h -- missing IPv6 related definitions
|
ipv6.h -- missing IPv6 related definitions
|
||||||
Copyright (C) 2005 Ivo Timmermans
|
Copyright (C) 2005 Ivo Timmermans
|
||||||
2006-2012 Guus Sliepen <guus@tinc-vpn.org>
|
2006-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -29,29 +29,6 @@
|
||||||
#define IPPROTO_ICMPV6 58
|
#define IPPROTO_ICMPV6 58
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_STRUCT_IN6_ADDR
|
|
||||||
struct in6_addr {
|
|
||||||
union {
|
|
||||||
uint8_t u6_addr8[16];
|
|
||||||
uint16_t u6_addr16[8];
|
|
||||||
uint32_t u6_addr32[4];
|
|
||||||
} in6_u;
|
|
||||||
} __attribute__ ((__gcc_struct__, __packed__));
|
|
||||||
#define s6_addr in6_u.u6_addr8
|
|
||||||
#define s6_addr16 in6_u.u6_addr16
|
|
||||||
#define s6_addr32 in6_u.u6_addr32
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef HAVE_STRUCT_SOCKADDR_IN6
|
|
||||||
struct sockaddr_in6 {
|
|
||||||
uint16_t sin6_family;
|
|
||||||
uint16_t sin6_port;
|
|
||||||
uint32_t sin6_flowinfo;
|
|
||||||
struct in6_addr sin6_addr;
|
|
||||||
uint32_t sin6_scope_id;
|
|
||||||
} __attribute__ ((__gcc_struct__, __packed__));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef IN6_IS_ADDR_V4MAPPED
|
#ifndef IN6_IS_ADDR_V4MAPPED
|
||||||
#define IN6_IS_ADDR_V4MAPPED(a) \
|
#define IN6_IS_ADDR_V4MAPPED(a) \
|
||||||
((((__const uint32_t *) (a))[0] == 0) \
|
((((__const uint32_t *) (a))[0] == 0) \
|
||||||
|
|
|
@ -101,6 +101,9 @@ static bool setup_device(void) {
|
||||||
get_config_string(lookup_config(config_tree, "Device"), &device);
|
get_config_string(lookup_config(config_tree, "Device"), &device);
|
||||||
get_config_string(lookup_config(config_tree, "Interface"), &iface);
|
get_config_string(lookup_config(config_tree, "Interface"), &iface);
|
||||||
|
|
||||||
|
if(device && iface)
|
||||||
|
logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: both Device and Interface specified, results may not be as expected");
|
||||||
|
|
||||||
/* Open registry and look for network adapters */
|
/* Open registry and look for network adapters */
|
||||||
|
|
||||||
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &key)) {
|
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &key)) {
|
||||||
|
|
|
@ -162,7 +162,7 @@ static void close_device(void) {
|
||||||
static bool read_packet(vpn_packet_t *packet) {
|
static bool read_packet(vpn_packet_t *packet) {
|
||||||
int lenin;
|
int lenin;
|
||||||
|
|
||||||
if((lenin = recv(device_fd, DATA(packet), MTU, 0)) <= 0) {
|
if((lenin = recv(device_fd, (void *)DATA(packet), MTU, 0)) <= 0) {
|
||||||
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
|
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
|
||||||
device, sockstrerror(sockerrno));
|
device, sockstrerror(sockerrno));
|
||||||
return false;
|
return false;
|
||||||
|
@ -185,7 +185,7 @@ static bool write_packet(vpn_packet_t *packet) {
|
||||||
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s",
|
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s",
|
||||||
packet->len, device_info);
|
packet->len, device_info);
|
||||||
|
|
||||||
if(sendto(device_fd, DATA(packet), packet->len, 0, ai->ai_addr, ai->ai_addrlen) < 0) {
|
if(sendto(device_fd, (void *)DATA(packet), packet->len, 0, ai->ai_addr, ai->ai_addrlen) < 0) {
|
||||||
logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
|
logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
|
||||||
sockstrerror(sockerrno));
|
sockstrerror(sockerrno));
|
||||||
return false;
|
return false;
|
||||||
|
|
18
src/names.c
18
src/names.c
|
@ -57,14 +57,14 @@ void make_names(bool daemon) {
|
||||||
if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\tinc", 0, KEY_READ, &key)) {
|
if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\tinc", 0, KEY_READ, &key)) {
|
||||||
if(!RegQueryValueEx(key, NULL, 0, 0, (LPBYTE)installdir, &len)) {
|
if(!RegQueryValueEx(key, NULL, 0, 0, (LPBYTE)installdir, &len)) {
|
||||||
confdir = xstrdup(installdir);
|
confdir = xstrdup(installdir);
|
||||||
if(!logfilename)
|
|
||||||
xasprintf(&logfilename, "%s" SLASH "log" SLASH "%s.log", installdir, identname);
|
|
||||||
if(!confbase) {
|
if(!confbase) {
|
||||||
if(netname)
|
if(netname)
|
||||||
xasprintf(&confbase, "%s" SLASH "%s", installdir, netname);
|
xasprintf(&confbase, "%s" SLASH "%s", installdir, netname);
|
||||||
else
|
else
|
||||||
xasprintf(&confbase, "%s", installdir);
|
xasprintf(&confbase, "%s", installdir);
|
||||||
}
|
}
|
||||||
|
if(!logfilename)
|
||||||
|
xasprintf(&logfilename, "%s" SLASH "tinc.log", confbase);
|
||||||
}
|
}
|
||||||
RegCloseKey(key);
|
RegCloseKey(key);
|
||||||
}
|
}
|
||||||
|
@ -121,11 +121,11 @@ void make_names(bool daemon) {
|
||||||
if(!unixsocketname) {
|
if(!unixsocketname) {
|
||||||
int len = strlen(pidfilename);
|
int len = strlen(pidfilename);
|
||||||
unixsocketname = xmalloc(len + 8);
|
unixsocketname = xmalloc(len + 8);
|
||||||
strcpy(unixsocketname, pidfilename);
|
memcpy(unixsocketname, pidfilename, len);
|
||||||
if(len > 4 && !strcmp(pidfilename + len - 4, ".pid"))
|
if(len > 4 && !strcmp(pidfilename + len - 4, ".pid"))
|
||||||
strcpy(unixsocketname + len - 4, ".socket");
|
strncpy(unixsocketname + len - 4, ".socket", 8);
|
||||||
else
|
else
|
||||||
strcpy(unixsocketname + len, ".socket");
|
strncpy(unixsocketname + len, ".socket", 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,4 +137,12 @@ void free_names(void) {
|
||||||
free(logfilename);
|
free(logfilename);
|
||||||
free(confbase);
|
free(confbase);
|
||||||
free(confdir);
|
free(confdir);
|
||||||
|
|
||||||
|
identname = NULL;
|
||||||
|
netname = NULL;
|
||||||
|
unixsocketname = NULL;
|
||||||
|
pidfilename = NULL;
|
||||||
|
logfilename = NULL;
|
||||||
|
confbase = NULL;
|
||||||
|
confdir = NULL;
|
||||||
}
|
}
|
||||||
|
|
51
src/net.c
51
src/net.c
|
@ -180,7 +180,7 @@ static void periodic_handler(void *data) {
|
||||||
|
|
||||||
if(contradicting_del_edge > 100 && contradicting_add_edge > 100) {
|
if(contradicting_del_edge > 100 && contradicting_add_edge > 100) {
|
||||||
logger(DEBUG_ALWAYS, LOG_WARNING, "Possible node with same Name as us! Sleeping %d seconds.", sleeptime);
|
logger(DEBUG_ALWAYS, LOG_WARNING, "Possible node with same Name as us! Sleeping %d seconds.", sleeptime);
|
||||||
usleep(sleeptime * 1000000LL);
|
nanosleep(&(struct timespec){sleeptime, 0}, NULL);
|
||||||
sleeptime *= 2;
|
sleeptime *= 2;
|
||||||
if(sleeptime < 0)
|
if(sleeptime < 0)
|
||||||
sleeptime = 3600;
|
sleeptime = 3600;
|
||||||
|
@ -209,13 +209,25 @@ static void periodic_handler(void *data) {
|
||||||
and we are not already trying to make one, create an
|
and we are not already trying to make one, create an
|
||||||
outgoing connection to this node.
|
outgoing connection to this node.
|
||||||
*/
|
*/
|
||||||
splay_tree_t *tmp_node_tree;
|
int count = 0;
|
||||||
|
for splay_each(node_t, n, node_tree) {
|
||||||
|
if(n == myself || n->connection || !(n->status.has_address || n->status.reachable))
|
||||||
|
continue;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
tmp_node_tree = splay_alloc_tree((splay_compare_t) node_compare, NULL);
|
if(!count) {
|
||||||
|
logger(DEBUG_ALWAYS, LOG_INFO, "No more nodes available for autoconnect!");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
int r = rand() % count;
|
||||||
|
|
||||||
for splay_each(node_t, n, node_tree) {
|
for splay_each(node_t, n, node_tree) {
|
||||||
|
if(n == myself || n->connection || !(n->status.has_address || n->status.reachable))
|
||||||
|
continue;
|
||||||
|
|
||||||
if ((!n->status.has_known_address && !n->status.has_cfg_address) || n->connection)
|
if(r--)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
@ -226,29 +238,8 @@ static void periodic_handler(void *data) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found)
|
break;
|
||||||
splay_insert(tmp_node_tree, n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmp_node_tree->count) {
|
|
||||||
int r = rand() % tmp_node_tree->count;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
for splay_each(node_t, n, tmp_node_tree) {
|
|
||||||
|
|
||||||
if(i++ != r)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
logger(DEBUG_CONNECTIONS, LOG_INFO, "Autoconnecting to %s", n->name);
|
|
||||||
outgoing_t *outgoing = xzalloc(sizeof *outgoing);
|
|
||||||
outgoing->name = xstrdup(n->name);
|
|
||||||
list_insert_tail(outgoing_list, outgoing);
|
|
||||||
setup_outgoing_connection(outgoing);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logger(DEBUG_ALWAYS, LOG_INFO, "No more nodes available for autoconnect!");
|
|
||||||
}
|
|
||||||
splay_delete_tree(tmp_node_tree);
|
|
||||||
} else if(nc > 3) {
|
} else if(nc > 3) {
|
||||||
/* Too many active connections, try to remove one.
|
/* Too many active connections, try to remove one.
|
||||||
Choose a random outgoing connection to a node
|
Choose a random outgoing connection to a node
|
||||||
|
@ -295,6 +286,7 @@ static void periodic_handler(void *data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
timeout_set(data, &(struct timeval){5, rand() % 100000});
|
timeout_set(data, &(struct timeval){5, rand() % 100000});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,9 +344,14 @@ int reload_configuration(void) {
|
||||||
for splay_each(subnet_t, subnet, subnet_tree)
|
for splay_each(subnet_t, subnet, subnet_tree)
|
||||||
if (subnet->owner)
|
if (subnet->owner)
|
||||||
subnet->expires = 1;
|
subnet->expires = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for splay_each(node_t, n, node_tree)
|
||||||
|
n->status.has_address = false;
|
||||||
|
|
||||||
load_all_nodes();
|
load_all_nodes();
|
||||||
|
|
||||||
|
if(strictsubnets) {
|
||||||
for splay_each(subnet_t, subnet, subnet_tree) {
|
for splay_each(subnet_t, subnet, subnet_tree) {
|
||||||
if (!subnet->owner)
|
if (!subnet->owner)
|
||||||
continue;
|
continue;
|
||||||
|
@ -455,7 +452,7 @@ void retry(void) {
|
||||||
*/
|
*/
|
||||||
int main_loop(void) {
|
int main_loop(void) {
|
||||||
timeout_add(&pingtimer, timeout_handler, &pingtimer, &(struct timeval){pingtimeout, rand() % 100000});
|
timeout_add(&pingtimer, timeout_handler, &pingtimer, &(struct timeval){pingtimeout, rand() % 100000});
|
||||||
timeout_add(&periodictimer, periodic_handler, &periodictimer, &(struct timeval){pingtimeout, rand() % 100000});
|
timeout_add(&periodictimer, periodic_handler, &periodictimer, &(struct timeval){0, 0});
|
||||||
|
|
||||||
#ifndef HAVE_MINGW
|
#ifndef HAVE_MINGW
|
||||||
signal_t sighup;
|
signal_t sighup;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
net.h -- header for net.c
|
net.h -- header for net.c
|
||||||
Copyright (C) 1998-2005 Ivo Timmermans
|
Copyright (C) 1998-2005 Ivo Timmermans
|
||||||
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
|
2000-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -115,6 +115,7 @@ typedef struct listen_socket_t {
|
||||||
io_t udp;
|
io_t udp;
|
||||||
sockaddr_t sa;
|
sockaddr_t sa;
|
||||||
bool bindto;
|
bool bindto;
|
||||||
|
int priority;
|
||||||
} listen_socket_t;
|
} listen_socket_t;
|
||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
net_packet.c -- Handles in- and outgoing VPN packets
|
net_packet.c -- Handles in- and outgoing VPN packets
|
||||||
Copyright (C) 1998-2005 Ivo Timmermans,
|
Copyright (C) 1998-2005 Ivo Timmermans,
|
||||||
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
|
2000-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
2010 Timothy Redaelli <timothy@redaelli.eu>
|
2010 Timothy Redaelli <timothy@redaelli.eu>
|
||||||
2010 Brandon Black <blblack@gmail.com>
|
2010 Brandon Black <blblack@gmail.com>
|
||||||
|
|
||||||
|
@ -622,10 +622,7 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
|
||||||
vpn_packet_t *outpkt;
|
vpn_packet_t *outpkt;
|
||||||
int origlen = origpkt->len;
|
int origlen = origpkt->len;
|
||||||
size_t outlen;
|
size_t outlen;
|
||||||
#if defined(SOL_IP) && defined(IP_TOS)
|
|
||||||
static int priority = 0;
|
|
||||||
int origpriority = origpkt->priority;
|
int origpriority = origpkt->priority;
|
||||||
#endif
|
|
||||||
|
|
||||||
pkt1.offset = DEFAULT_PACKET_OFFSET;
|
pkt1.offset = DEFAULT_PACKET_OFFSET;
|
||||||
pkt2.offset = DEFAULT_PACKET_OFFSET;
|
pkt2.offset = DEFAULT_PACKET_OFFSET;
|
||||||
|
@ -720,17 +717,29 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
|
||||||
if(!sa)
|
if(!sa)
|
||||||
choose_udp_address(n, &sa, &sock);
|
choose_udp_address(n, &sa, &sock);
|
||||||
|
|
||||||
#if defined(SOL_IP) && defined(IP_TOS)
|
if(priorityinheritance && origpriority != listen_socket[sock].priority) {
|
||||||
if(priorityinheritance && origpriority != priority
|
listen_socket[sock].priority = origpriority;
|
||||||
&& listen_socket[n->sock].sa.sa.sa_family == AF_INET) {
|
switch(sa->sa.sa_family) {
|
||||||
priority = origpriority;
|
#if defined(IPPROTO_IP) && defined(IP_TOS)
|
||||||
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Setting outgoing packet priority to %d", priority);
|
case AF_INET:
|
||||||
if(setsockopt(listen_socket[n->sock].udp.fd, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */
|
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Setting IPv4 outgoing packet priority to %d", origpriority);
|
||||||
|
if(setsockopt(listen_socket[sock].udp.fd, IPPROTO_IP, IP_TOS, (void *)&origpriority, sizeof origpriority)) /* SO_PRIORITY doesn't seem to work */
|
||||||
logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setsockopt", sockstrerror(sockerrno));
|
logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setsockopt", sockstrerror(sockerrno));
|
||||||
}
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(IPPROTO_IPV6) & defined(IPV6_TCLASS)
|
||||||
|
case AF_INET6:
|
||||||
|
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Setting IPv6 outgoing packet priority to %d", origpriority);
|
||||||
|
if(setsockopt(listen_socket[sock].udp.fd, IPPROTO_IPV6, IPV6_TCLASS, (void *)&origpriority, sizeof origpriority)) /* SO_PRIORITY doesn't seem to work */
|
||||||
|
logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setsockopt", sockstrerror(sockerrno));
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(sendto(listen_socket[sock].udp.fd, SEQNO(inpkt), inpkt->len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) {
|
if(sendto(listen_socket[sock].udp.fd, (void *)SEQNO(inpkt), inpkt->len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) {
|
||||||
if(sockmsgsize(sockerrno)) {
|
if(sockmsgsize(sockerrno)) {
|
||||||
if(n->maxmtu >= origlen)
|
if(n->maxmtu >= origlen)
|
||||||
n->maxmtu = origlen - 1;
|
n->maxmtu = origlen - 1;
|
||||||
|
@ -1557,7 +1566,7 @@ void handle_incoming_vpn_data(void *data, int flags) {
|
||||||
socklen_t addrlen = sizeof addr;
|
socklen_t addrlen = sizeof addr;
|
||||||
|
|
||||||
pkt.offset = 0;
|
pkt.offset = 0;
|
||||||
int len = recvfrom(ls->udp.fd, DATA(&pkt), MAXSIZE, 0, &addr.sa, &addrlen);
|
int len = recvfrom(ls->udp.fd, (void *)DATA(&pkt), MAXSIZE, 0, &addr.sa, &addrlen);
|
||||||
|
|
||||||
if(len <= 0 || len > MAXSIZE) {
|
if(len <= 0 || len > MAXSIZE) {
|
||||||
if(!sockwouldblock(sockerrno))
|
if(!sockwouldblock(sockerrno))
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
net_setup.c -- Setup.
|
net_setup.c -- Setup.
|
||||||
Copyright (C) 1998-2005 Ivo Timmermans,
|
Copyright (C) 1998-2005 Ivo Timmermans,
|
||||||
2000-2015 Guus Sliepen <guus@tinc-vpn.org>
|
2000-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
2006 Scott Lamb <slamb@slamb.org>
|
2006 Scott Lamb <slamb@slamb.org>
|
||||||
2010 Brandon Black <blblack@gmail.com>
|
2010 Brandon Black <blblack@gmail.com>
|
||||||
|
|
||||||
|
@ -370,17 +370,17 @@ void load_all_nodes(void) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
node_t *n = lookup_node(ent->d_name);
|
node_t *n = lookup_node(ent->d_name);
|
||||||
|
splay_tree_t *config_tree;
|
||||||
|
init_configuration(&config_tree);
|
||||||
|
read_config_options(config_tree, ent->d_name);
|
||||||
|
read_host_config(config_tree, ent->d_name);
|
||||||
|
|
||||||
if(!n) {
|
if(!n) {
|
||||||
n = new_node();
|
n = new_node();
|
||||||
n->name = xstrdup(ent->d_name);
|
n->name = xstrdup(ent->d_name);
|
||||||
node_add(n);
|
node_add(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
splay_tree_t *config_tree;
|
|
||||||
init_configuration(&config_tree);
|
|
||||||
read_config_options(config_tree, ent->d_name);
|
|
||||||
read_host_config(config_tree, ent->d_name);
|
|
||||||
|
|
||||||
if(strictsubnets) {
|
if(strictsubnets) {
|
||||||
for(config_t *cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
|
for(config_t *cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
|
||||||
subnet_t *s, *s2;
|
subnet_t *s, *s2;
|
||||||
|
@ -397,10 +397,8 @@ void load_all_nodes(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lookup_config(config_tree, "Address")) {
|
if(lookup_config(config_tree, "Address"))
|
||||||
n->status.has_known_address = true;
|
n->status.has_address = true;
|
||||||
n->status.has_cfg_address = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
exit_configuration(&config_tree);
|
exit_configuration(&config_tree);
|
||||||
}
|
}
|
||||||
|
@ -601,16 +599,14 @@ bool setup_myself_reloadable(void) {
|
||||||
subnet_add(NULL, s);
|
subnet_add(NULL, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (config_t* cfg = lookup_config(config_tree, "MulticastSubnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
|
#if !defined(IPPROTO_IP) || !defined(IP_TOS)
|
||||||
subnet_t *s;
|
|
||||||
if (!get_config_subnet(cfg, &s))
|
|
||||||
continue;
|
|
||||||
subnet_add(NULL, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(SOL_IP) || !defined(IP_TOS)
|
|
||||||
if(priorityinheritance)
|
if(priorityinheritance)
|
||||||
logger(DEBUG_ALWAYS, LOG_WARNING, "%s not supported on this platform", "PriorityInheritance");
|
logger(DEBUG_ALWAYS, LOG_WARNING, "%s not supported on this platform for IPv4 connections", "PriorityInheritance");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(IPPROTO_IPV6) || !defined(IPV6_TCLASS)
|
||||||
|
if(priorityinheritance)
|
||||||
|
logger(DEBUG_ALWAYS, LOG_WARNING, "%s not supported on this platform for IPv6 connections", "PriorityInheritance");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire))
|
if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire))
|
||||||
|
@ -1172,8 +1168,7 @@ void close_network_connections(void) {
|
||||||
|
|
||||||
if(myself && myself->connection) {
|
if(myself && myself->connection) {
|
||||||
subnet_update(myself, NULL, false);
|
subnet_update(myself, NULL, false);
|
||||||
terminate_connection(myself->connection, false);
|
connection_del(myself->connection);
|
||||||
free_connection(myself->connection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < listen_sockets; i++) {
|
for(int i = 0; i < listen_sockets; i++) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
net_socket.c -- Handle various kinds of sockets.
|
net_socket.c -- Handle various kinds of sockets.
|
||||||
Copyright (C) 1998-2005 Ivo Timmermans,
|
Copyright (C) 1998-2005 Ivo Timmermans,
|
||||||
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
|
2000-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
2006 Scott Lamb <slamb@slamb.org>
|
2006 Scott Lamb <slamb@slamb.org>
|
||||||
2009 Florian Forster <octo@verplant.org>
|
2009 Florian Forster <octo@verplant.org>
|
||||||
|
|
||||||
|
@ -35,11 +35,6 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "xalloc.h"
|
#include "xalloc.h"
|
||||||
|
|
||||||
/* Needed on Mac OS/X */
|
|
||||||
#ifndef SOL_TCP
|
|
||||||
#define SOL_TCP IPPROTO_TCP
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int addressfamily = AF_UNSPEC;
|
int addressfamily = AF_UNSPEC;
|
||||||
int maxtimeout = 900;
|
int maxtimeout = 900;
|
||||||
int seconds_till_retry = 5;
|
int seconds_till_retry = 5;
|
||||||
|
@ -73,14 +68,19 @@ static void configure_tcp(connection_t *c) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SOL_TCP) && defined(TCP_NODELAY)
|
#if defined(IPPROTO_TCP) && defined(TCP_NODELAY)
|
||||||
option = 1;
|
option = 1;
|
||||||
setsockopt(c->socket, SOL_TCP, TCP_NODELAY, (void *)&option, sizeof option);
|
setsockopt(c->socket, IPPROTO_TCP, TCP_NODELAY, (void *)&option, sizeof option);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SOL_IP) && defined(IP_TOS) && defined(IPTOS_LOWDELAY)
|
#if defined(IPPROTO_IP) && defined(IP_TOS) && defined(IPTOS_LOWDELAY)
|
||||||
option = IPTOS_LOWDELAY;
|
option = IPTOS_LOWDELAY;
|
||||||
setsockopt(c->socket, SOL_IP, IP_TOS, (void *)&option, sizeof option);
|
setsockopt(c->socket, IPPROTO_IP, IP_TOS, (void *)&option, sizeof option);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS) && defined(IPTOS_LOWDELAY)
|
||||||
|
option = IPTOS_LOWDELAY;
|
||||||
|
setsockopt(c->socket, IPPROTO_IPV6, IPV6_TCLASS, (void *)&option, sizeof option);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,9 +163,9 @@ int setup_listen_socket(const sockaddr_t *sa) {
|
||||||
option = 1;
|
option = 1;
|
||||||
setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof option);
|
setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof option);
|
||||||
|
|
||||||
#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
|
#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
|
||||||
if(sa->sa.sa_family == AF_INET6)
|
if(sa->sa.sa_family == AF_INET6)
|
||||||
setsockopt(nfd, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
|
setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(get_config_string
|
if(get_config_string
|
||||||
|
@ -261,10 +261,10 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
|
||||||
#define IP_DONTFRAGMENT IP_DONTFRAG
|
#define IP_DONTFRAGMENT IP_DONTFRAG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SOL_IP) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
|
#if defined(IPPROTO_IP) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
|
||||||
if(myself->options & OPTION_PMTU_DISCOVERY) {
|
if(myself->options & OPTION_PMTU_DISCOVERY) {
|
||||||
option = IP_PMTUDISC_DO;
|
option = IP_PMTUDISC_DO;
|
||||||
setsockopt(nfd, SOL_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option));
|
setsockopt(nfd, IPPROTO_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option));
|
||||||
}
|
}
|
||||||
#elif defined(IPPROTO_IP) && defined(IP_DONTFRAGMENT)
|
#elif defined(IPPROTO_IP) && defined(IP_DONTFRAGMENT)
|
||||||
if(myself->options & OPTION_PMTU_DISCOVERY) {
|
if(myself->options & OPTION_PMTU_DISCOVERY) {
|
||||||
|
@ -273,10 +273,10 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SOL_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
|
#if defined(IPPROTO_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
|
||||||
if(myself->options & OPTION_PMTU_DISCOVERY) {
|
if(myself->options & OPTION_PMTU_DISCOVERY) {
|
||||||
option = IPV6_PMTUDISC_DO;
|
option = IPV6_PMTUDISC_DO;
|
||||||
setsockopt(nfd, SOL_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option));
|
setsockopt(nfd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option));
|
||||||
}
|
}
|
||||||
#elif defined(IPPROTO_IPV6) && defined(IPV6_DONTFRAG)
|
#elif defined(IPPROTO_IPV6) && defined(IPV6_DONTFRAG)
|
||||||
if(myself->options & OPTION_PMTU_DISCOVERY) {
|
if(myself->options & OPTION_PMTU_DISCOVERY) {
|
||||||
|
@ -517,10 +517,10 @@ begin:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(proxytype != PROXY_EXEC) {
|
if(proxytype != PROXY_EXEC) {
|
||||||
#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
|
#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
|
||||||
int option = 1;
|
int option = 1;
|
||||||
if(c->address.sa.sa_family == AF_INET6)
|
if(c->address.sa.sa_family == AF_INET6)
|
||||||
setsockopt(c->socket, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
|
setsockopt(c->socket, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bind_to_interface(c->socket);
|
bind_to_interface(c->socket);
|
||||||
|
@ -547,6 +547,7 @@ begin:
|
||||||
|
|
||||||
/* Now that there is a working socket, fill in the rest and register this connection. */
|
/* Now that there is a working socket, fill in the rest and register this connection. */
|
||||||
|
|
||||||
|
c->last_ping_time = time(NULL);
|
||||||
c->status.connecting = true;
|
c->status.connecting = true;
|
||||||
c->name = xstrdup(outgoing->name);
|
c->name = xstrdup(outgoing->name);
|
||||||
#ifndef DISABLE_LEGACY
|
#ifndef DISABLE_LEGACY
|
||||||
|
|
|
@ -190,7 +190,7 @@ bool dump_nodes(connection_t *c) {
|
||||||
for splay_each(node_t, n, node_tree) {
|
for splay_each(node_t, n, node_tree) {
|
||||||
char id[2 * sizeof n->id + 1];
|
char id[2 * sizeof n->id + 1];
|
||||||
for (size_t c = 0; c < sizeof n->id; ++c)
|
for (size_t c = 0; c < sizeof n->id; ++c)
|
||||||
sprintf(id + 2 * c, "%02hhx", n->id.x[c]);
|
snprintf(id + 2 * c, 3, "%02hhx", n->id.x[c]);
|
||||||
id[sizeof id - 1] = 0;
|
id[sizeof id - 1] = 0;
|
||||||
send_request(c, "%d %d %s %s %s %d %d %d %d %x %x %s %s %d %hd %hd %hd %ld", CONTROL, REQ_DUMP_NODES,
|
send_request(c, "%d %d %s %s %s %d %d %d %d %x %x %s %s %d %hd %hd %hd %ld", CONTROL, REQ_DUMP_NODES,
|
||||||
n->name, id, n->hostname ?: "unknown port unknown",
|
n->name, id, n->hostname ?: "unknown port unknown",
|
||||||
|
|
|
@ -40,9 +40,8 @@ typedef struct node_status_t {
|
||||||
unsigned int send_locally:1; /* 1 if the next UDP packet should be sent on the local network */
|
unsigned int send_locally:1; /* 1 if the next UDP packet should be sent on the local network */
|
||||||
unsigned int udppacket:1; /* 1 if the most recently received packet was UDP */
|
unsigned int udppacket:1; /* 1 if the most recently received packet was UDP */
|
||||||
unsigned int validkey_in:1; /* 1 if we have sent a valid key to him */
|
unsigned int validkey_in:1; /* 1 if we have sent a valid key to him */
|
||||||
unsigned int has_known_address; /* 1 if this node has UDP Address */
|
unsigned int has_address:1; /* 1 if we know an external address for this node */
|
||||||
unsigned int has_cfg_address; /* 1 if this node has Address in node's config */
|
unsigned int unused:20;
|
||||||
unsigned int unused:21;
|
|
||||||
} node_status_t;
|
} node_status_t;
|
||||||
|
|
||||||
typedef struct node_t {
|
typedef struct node_t {
|
||||||
|
|
|
@ -62,12 +62,9 @@ static bool install_service(void) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!strchr(program_name, '\\')) {
|
HMODULE module = GetModuleHandle(NULL);
|
||||||
GetCurrentDirectory(sizeof command - 1, command + 1);
|
GetModuleFileName(module, command + 1, sizeof command - 1);
|
||||||
strncat(command, "\\", sizeof command - strlen(command));
|
command[sizeof command - 1] = 0;
|
||||||
}
|
|
||||||
|
|
||||||
strncat(command, program_name, sizeof command - strlen(command));
|
|
||||||
|
|
||||||
strncat(command, "\"", sizeof command - strlen(command));
|
strncat(command, "\"", sizeof command - strlen(command));
|
||||||
|
|
||||||
|
@ -203,7 +200,7 @@ bool detach(void) {
|
||||||
|
|
||||||
if(do_detach) {
|
if(do_detach) {
|
||||||
#ifndef HAVE_MINGW
|
#ifndef HAVE_MINGW
|
||||||
if(daemon(0, 0)) {
|
if(daemon(1, 0)) {
|
||||||
logger(DEBUG_ALWAYS, LOG_ERR, "Couldn't detach from terminal: %s", strerror(errno));
|
logger(DEBUG_ALWAYS, LOG_ERR, "Couldn't detach from terminal: %s", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ static bool send_proxyrequest(connection_t *c) {
|
||||||
i += 2;
|
i += 2;
|
||||||
c->tcplen += 22;
|
c->tcplen += 22;
|
||||||
} else {
|
} else {
|
||||||
logger(DEBUG_ALWAYS, LOG_ERR, "Address family %hx not supported for SOCKS 5 proxies!", c->address.sa.sa_family);
|
logger(DEBUG_ALWAYS, LOG_ERR, "Address family %x not supported for SOCKS 5 proxies!", c->address.sa.sa_family);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(i > len)
|
if(i > len)
|
||||||
|
|
|
@ -159,7 +159,7 @@ bool add_edge_h(connection_t *c, const char *request) {
|
||||||
"ADD_EDGE", c->name, c->hostname, e->from->name, e->to->name);
|
"ADD_EDGE", c->name, c->hostname, e->from->name, e->to->name);
|
||||||
e->address = address;
|
e->address = address;
|
||||||
}
|
}
|
||||||
goto exit_with_graph;
|
goto done;
|
||||||
}
|
}
|
||||||
} else if(sockaddrcmp(&e->local_address, &local_address)) {
|
} else if(sockaddrcmp(&e->local_address, &local_address)) {
|
||||||
if(from == myself) {
|
if(from == myself) {
|
||||||
|
@ -221,8 +221,8 @@ bool add_edge_h(connection_t *c, const char *request) {
|
||||||
e->avg_rtt = weight/10;
|
e->avg_rtt = weight/10;
|
||||||
edge_add(e);
|
edge_add(e);
|
||||||
|
|
||||||
|
done:
|
||||||
/* Tell the rest about the new edge */
|
/* Tell the rest about the new edge */
|
||||||
exit_with_graph:
|
|
||||||
if(!tunnelserver)
|
if(!tunnelserver)
|
||||||
forward_request(c, request);
|
forward_request(c, request);
|
||||||
|
|
||||||
|
|
|
@ -412,7 +412,7 @@ bool ans_key_h(connection_t *c, const char *request) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!*address && from->address.sa.sa_family != AF_UNSPEC) {
|
if(!*address && from->address.sa.sa_family != AF_UNSPEC && to->minmtu) {
|
||||||
char *address, *port;
|
char *address, *port;
|
||||||
logger(DEBUG_PROTOCOL, LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name);
|
logger(DEBUG_PROTOCOL, LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name);
|
||||||
sockaddr2str(&from->address, &address, &port);
|
sockaddr2str(&from->address, &address, &port);
|
||||||
|
|
505
src/route.c
505
src/route.c
|
@ -105,6 +105,260 @@ static bool checklength(node_t *source, vpn_packet_t *packet, length_t length) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void swap_mac_addresses(vpn_packet_t *packet) {
|
||||||
|
mac_t tmp;
|
||||||
|
memcpy(&tmp, &DATA(packet)[0], sizeof tmp);
|
||||||
|
memcpy(&DATA(packet)[0], &DATA(packet)[6], sizeof tmp);
|
||||||
|
memcpy(&DATA(packet)[6], &tmp, sizeof tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RFC 792 */
|
||||||
|
|
||||||
|
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};
|
||||||
|
|
||||||
|
struct in_addr ip_src;
|
||||||
|
struct in_addr ip_dst;
|
||||||
|
uint32_t oldlen;
|
||||||
|
|
||||||
|
if(ratelimit(3))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Swap Ethernet source and destination addresses */
|
||||||
|
|
||||||
|
swap_mac_addresses(packet);
|
||||||
|
|
||||||
|
/* Copy headers from packet into properly aligned structs on the stack */
|
||||||
|
|
||||||
|
memcpy(&ip, DATA(packet) + ether_size, ip_size);
|
||||||
|
|
||||||
|
/* Remember original source and destination */
|
||||||
|
|
||||||
|
ip_src = ip.ip_src;
|
||||||
|
ip_dst = ip.ip_dst;
|
||||||
|
|
||||||
|
/* Try to reply with an IP address assigned to the local machine */
|
||||||
|
|
||||||
|
if (type == ICMP_TIME_EXCEEDED && code == ICMP_EXC_TTL) {
|
||||||
|
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (sockfd != -1) {
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_addr = ip.ip_src;
|
||||||
|
if (!connect(sockfd, (const struct sockaddr*) &addr, sizeof(addr))) {
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
socklen_t addrlen = sizeof(addr);
|
||||||
|
if (!getsockname(sockfd, (struct sockaddr*) &addr, &addrlen) && addrlen <= sizeof(addr)) {
|
||||||
|
ip_dst = addr.sin_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(sockfd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oldlen = packet->len - ether_size;
|
||||||
|
|
||||||
|
if(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
|
||||||
|
icmp.icmp_nextmtu = htons(packet->len - ether_size);
|
||||||
|
|
||||||
|
if(oldlen >= IP_MSS - ip_size - icmp_size)
|
||||||
|
oldlen = IP_MSS - ip_size - icmp_size;
|
||||||
|
|
||||||
|
/* Copy first part of original contents to ICMP message */
|
||||||
|
|
||||||
|
memmove(DATA(packet) + ether_size + ip_size + icmp_size, DATA(packet) + ether_size, oldlen);
|
||||||
|
|
||||||
|
/* Fill in IPv4 header */
|
||||||
|
|
||||||
|
ip.ip_v = 4;
|
||||||
|
ip.ip_hl = ip_size / 4;
|
||||||
|
ip.ip_tos = 0;
|
||||||
|
ip.ip_len = htons(ip_size + icmp_size + oldlen);
|
||||||
|
ip.ip_id = 0;
|
||||||
|
ip.ip_off = 0;
|
||||||
|
ip.ip_ttl = 255;
|
||||||
|
ip.ip_p = IPPROTO_ICMP;
|
||||||
|
ip.ip_sum = 0;
|
||||||
|
ip.ip_src = ip_dst;
|
||||||
|
ip.ip_dst = ip_src;
|
||||||
|
|
||||||
|
ip.ip_sum = inet_checksum(&ip, ip_size, ~0);
|
||||||
|
|
||||||
|
/* Fill in ICMP header */
|
||||||
|
|
||||||
|
icmp.icmp_type = type;
|
||||||
|
icmp.icmp_code = code;
|
||||||
|
icmp.icmp_cksum = 0;
|
||||||
|
|
||||||
|
icmp.icmp_cksum = inet_checksum(&icmp, icmp_size, ~0);
|
||||||
|
icmp.icmp_cksum = inet_checksum(DATA(packet) + ether_size + ip_size + icmp_size, oldlen, icmp.icmp_cksum);
|
||||||
|
|
||||||
|
/* Copy structs on stack back to packet */
|
||||||
|
|
||||||
|
memcpy(DATA(packet) + ether_size, &ip, ip_size);
|
||||||
|
memcpy(DATA(packet) + ether_size + ip_size, &icmp, icmp_size);
|
||||||
|
|
||||||
|
packet->len = ether_size + ip_size + icmp_size + oldlen;
|
||||||
|
|
||||||
|
send_packet(source, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RFC 2463 */
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct in6_addr ip6_src; /* source address */
|
||||||
|
struct in6_addr ip6_dst; /* destination address */
|
||||||
|
uint32_t length;
|
||||||
|
uint32_t next;
|
||||||
|
} pseudo;
|
||||||
|
|
||||||
|
if(ratelimit(3))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Swap Ethernet source and destination addresses */
|
||||||
|
|
||||||
|
swap_mac_addresses(packet);
|
||||||
|
|
||||||
|
/* Copy headers from packet to structs on the stack */
|
||||||
|
|
||||||
|
memcpy(&ip6, DATA(packet) + ether_size, ip6_size);
|
||||||
|
|
||||||
|
/* Remember original source and destination */
|
||||||
|
|
||||||
|
pseudo.ip6_src = ip6.ip6_dst;
|
||||||
|
pseudo.ip6_dst = ip6.ip6_src;
|
||||||
|
|
||||||
|
/* Try to reply with an IP address assigned to the local machine */
|
||||||
|
|
||||||
|
if (type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT) {
|
||||||
|
int sockfd = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||||
|
if (sockfd != -1) {
|
||||||
|
struct sockaddr_in6 addr;
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sin6_family = AF_INET6;
|
||||||
|
addr.sin6_addr = ip6.ip6_src;
|
||||||
|
if (!connect(sockfd, (const struct sockaddr*) &addr, sizeof(addr))) {
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sin6_family = AF_INET6;
|
||||||
|
socklen_t addrlen = sizeof(addr);
|
||||||
|
if (!getsockname(sockfd, (struct sockaddr*) &addr, &addrlen) && addrlen <= sizeof(addr)) {
|
||||||
|
pseudo.ip6_src = addr.sin6_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(sockfd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pseudo.length = packet->len - ether_size;
|
||||||
|
|
||||||
|
if(type == ICMP6_PACKET_TOO_BIG)
|
||||||
|
icmp6.icmp6_mtu = htonl(pseudo.length);
|
||||||
|
|
||||||
|
if(pseudo.length >= IP_MSS - ip6_size - icmp6_size)
|
||||||
|
pseudo.length = IP_MSS - ip6_size - icmp6_size;
|
||||||
|
|
||||||
|
/* Copy first part of original contents to ICMP message */
|
||||||
|
|
||||||
|
memmove(DATA(packet) + ether_size + ip6_size + icmp6_size, DATA(packet) + ether_size, pseudo.length);
|
||||||
|
|
||||||
|
/* Fill in IPv6 header */
|
||||||
|
|
||||||
|
ip6.ip6_flow = htonl(0x60000000UL);
|
||||||
|
ip6.ip6_plen = htons(icmp6_size + pseudo.length);
|
||||||
|
ip6.ip6_nxt = IPPROTO_ICMPV6;
|
||||||
|
ip6.ip6_hlim = 255;
|
||||||
|
ip6.ip6_src = pseudo.ip6_src;
|
||||||
|
ip6.ip6_dst = pseudo.ip6_dst;
|
||||||
|
|
||||||
|
/* Fill in ICMP header */
|
||||||
|
|
||||||
|
icmp6.icmp6_type = type;
|
||||||
|
icmp6.icmp6_code = code;
|
||||||
|
icmp6.icmp6_cksum = 0;
|
||||||
|
|
||||||
|
/* Create pseudo header */
|
||||||
|
|
||||||
|
pseudo.length = htonl(icmp6_size + pseudo.length);
|
||||||
|
pseudo.next = htonl(IPPROTO_ICMPV6);
|
||||||
|
|
||||||
|
/* Generate checksum */
|
||||||
|
|
||||||
|
checksum = inet_checksum(&pseudo, sizeof pseudo, ~0);
|
||||||
|
checksum = inet_checksum(&icmp6, icmp6_size, checksum);
|
||||||
|
checksum = inet_checksum(DATA(packet) + ether_size + ip6_size + icmp6_size, ntohl(pseudo.length) - icmp6_size, checksum);
|
||||||
|
|
||||||
|
icmp6.icmp6_cksum = checksum;
|
||||||
|
|
||||||
|
/* Copy structs on stack back to packet */
|
||||||
|
|
||||||
|
memcpy(DATA(packet) + ether_size, &ip6, ip6_size);
|
||||||
|
memcpy(DATA(packet) + ether_size + ip6_size, &icmp6, icmp6_size);
|
||||||
|
|
||||||
|
packet->len = ether_size + ip6_size + ntohl(pseudo.length);
|
||||||
|
|
||||||
|
send_packet(source, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool do_decrement_ttl(node_t *source, vpn_packet_t *packet) {
|
||||||
|
uint16_t type = DATA(packet)[12] << 8 | DATA(packet)[13];
|
||||||
|
length_t ethlen = ether_size;
|
||||||
|
|
||||||
|
if(type == ETH_P_8021Q) {
|
||||||
|
type = DATA(packet)[16] << 8 | DATA(packet)[17];
|
||||||
|
ethlen += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case ETH_P_IP:
|
||||||
|
if(!checklength(source, packet, ethlen + ip_size))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(DATA(packet)[ethlen + 8] <= 1) {
|
||||||
|
if(DATA(packet)[ethlen + 11] != IPPROTO_ICMP || DATA(packet)[ethlen + 32] != ICMP_TIME_EXCEEDED)
|
||||||
|
route_ipv4_unreachable(source, packet, ethlen, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t old = DATA(packet)[ethlen + 8] << 8 | DATA(packet)[ethlen + 9];
|
||||||
|
DATA(packet)[ethlen + 8]--;
|
||||||
|
uint16_t new = DATA(packet)[ethlen + 8] << 8 | DATA(packet)[ethlen + 9];
|
||||||
|
|
||||||
|
uint32_t checksum = DATA(packet)[ethlen + 10] << 8 | DATA(packet)[ethlen + 11];
|
||||||
|
checksum += old + (~new & 0xFFFF);
|
||||||
|
while(checksum >> 16)
|
||||||
|
checksum = (checksum & 0xFFFF) + (checksum >> 16);
|
||||||
|
DATA(packet)[ethlen + 10] = checksum >> 8;
|
||||||
|
DATA(packet)[ethlen + 11] = checksum & 0xff;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case ETH_P_IPV6:
|
||||||
|
if(!checklength(source, packet, ethlen + ip6_size))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(DATA(packet)[ethlen + 7] <= 1) {
|
||||||
|
if(DATA(packet)[ethlen + 6] != IPPROTO_ICMPV6 || DATA(packet)[ethlen + 40] != ICMP6_TIME_EXCEEDED)
|
||||||
|
route_ipv6_unreachable(source, packet, ethlen, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DATA(packet)[ethlen + 7]--;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *packet) {
|
static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *packet) {
|
||||||
if(!source || !via || !(via->options & OPTION_CLAMP_MSS))
|
if(!source || !via || !(via->options & OPTION_CLAMP_MSS))
|
||||||
return;
|
return;
|
||||||
|
@ -186,13 +440,6 @@ static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *pac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void swap_mac_addresses(vpn_packet_t *packet) {
|
|
||||||
mac_t tmp;
|
|
||||||
memcpy(&tmp, &DATA(packet)[0], sizeof tmp);
|
|
||||||
memcpy(&DATA(packet)[0], &DATA(packet)[6], sizeof tmp);
|
|
||||||
memcpy(&DATA(packet)[6], &tmp, sizeof tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void age_subnets(void *data) {
|
static void age_subnets(void *data) {
|
||||||
bool left = false;
|
bool left = false;
|
||||||
UNUSED(data);
|
UNUSED(data);
|
||||||
|
@ -251,80 +498,12 @@ static void learn_mac(mac_t *address) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RFC 792 */
|
static void route_broadcast(node_t *source, vpn_packet_t *packet) {
|
||||||
|
if(decrement_ttl && source != myself)
|
||||||
static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, length_t ether_size, uint8_t type, uint8_t code) {
|
if(!do_decrement_ttl(source, packet))
|
||||||
struct ip ip;
|
|
||||||
struct icmp icmp;
|
|
||||||
|
|
||||||
struct in_addr ip_src;
|
|
||||||
struct in_addr ip_dst;
|
|
||||||
uint32_t oldlen;
|
|
||||||
|
|
||||||
memset(&ip, 0x0, sizeof(ip));
|
|
||||||
memset(&icmp, 0x0, sizeof(icmp));
|
|
||||||
|
|
||||||
if(ratelimit(3))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Swap Ethernet source and destination addresses */
|
broadcast_packet(source, packet);
|
||||||
|
|
||||||
swap_mac_addresses(packet);
|
|
||||||
|
|
||||||
/* Copy headers from packet into properly aligned structs on the stack */
|
|
||||||
|
|
||||||
memcpy(&ip, DATA(packet) + ether_size, ip_size);
|
|
||||||
|
|
||||||
/* Remember original source and destination */
|
|
||||||
|
|
||||||
ip_src = ip.ip_src;
|
|
||||||
ip_dst = ip.ip_dst;
|
|
||||||
|
|
||||||
oldlen = packet->len - ether_size;
|
|
||||||
|
|
||||||
if(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
|
|
||||||
icmp.icmp_nextmtu = htons(packet->len - ether_size);
|
|
||||||
|
|
||||||
if(oldlen >= IP_MSS - ip_size - icmp_size)
|
|
||||||
oldlen = IP_MSS - ip_size - icmp_size;
|
|
||||||
|
|
||||||
/* Copy first part of original contents to ICMP message */
|
|
||||||
|
|
||||||
memmove(DATA(packet) + ether_size + ip_size + icmp_size, DATA(packet) + ether_size, oldlen);
|
|
||||||
|
|
||||||
/* Fill in IPv4 header */
|
|
||||||
|
|
||||||
ip.ip_v = 4;
|
|
||||||
ip.ip_hl = ip_size / 4;
|
|
||||||
ip.ip_tos = 0;
|
|
||||||
ip.ip_len = htons(ip_size + icmp_size + oldlen);
|
|
||||||
ip.ip_id = 0;
|
|
||||||
ip.ip_off = 0;
|
|
||||||
ip.ip_ttl = 255;
|
|
||||||
ip.ip_p = IPPROTO_ICMP;
|
|
||||||
ip.ip_sum = 0;
|
|
||||||
ip.ip_src = ip_dst;
|
|
||||||
ip.ip_dst = ip_src;
|
|
||||||
|
|
||||||
ip.ip_sum = inet_checksum(&ip, ip_size, ~0);
|
|
||||||
|
|
||||||
/* Fill in ICMP header */
|
|
||||||
|
|
||||||
icmp.icmp_type = type;
|
|
||||||
icmp.icmp_code = code;
|
|
||||||
icmp.icmp_cksum = 0;
|
|
||||||
|
|
||||||
icmp.icmp_cksum = inet_checksum(&icmp, icmp_size, ~0);
|
|
||||||
icmp.icmp_cksum = inet_checksum(DATA(packet) + ether_size + ip_size + icmp_size, oldlen, icmp.icmp_cksum);
|
|
||||||
|
|
||||||
/* Copy structs on stack back to packet */
|
|
||||||
|
|
||||||
memcpy(DATA(packet) + ether_size, &ip, ip_size);
|
|
||||||
memcpy(DATA(packet) + ether_size + ip_size, &icmp, icmp_size);
|
|
||||||
|
|
||||||
packet->len = ether_size + ip_size + icmp_size + oldlen;
|
|
||||||
|
|
||||||
send_packet(source, packet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RFC 791 */
|
/* RFC 791 */
|
||||||
|
@ -411,7 +590,7 @@ static void route_ipv4(node_t *source, vpn_packet_t *packet) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!subnet->owner) {
|
if (!subnet->owner) {
|
||||||
broadcast_packet(source, packet);
|
route_broadcast(source, packet);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,6 +605,10 @@ static void route_ipv4(node_t *source, vpn_packet_t *packet) {
|
||||||
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
|
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
|
||||||
return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_ANO);
|
return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_ANO);
|
||||||
|
|
||||||
|
if(decrement_ttl && source != myself && subnet->owner != myself)
|
||||||
|
if(!do_decrement_ttl(source, packet))
|
||||||
|
return;
|
||||||
|
|
||||||
if(priorityinheritance)
|
if(priorityinheritance)
|
||||||
packet->priority = DATA(packet)[15];
|
packet->priority = DATA(packet)[15];
|
||||||
|
|
||||||
|
@ -456,90 +639,6 @@ static void route_ipv4(node_t *source, vpn_packet_t *packet) {
|
||||||
send_packet(subnet->owner, packet);
|
send_packet(subnet->owner, packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RFC 2463 */
|
|
||||||
|
|
||||||
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;
|
|
||||||
uint16_t checksum;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
struct in6_addr ip6_src; /* source address */
|
|
||||||
struct in6_addr ip6_dst; /* destination address */
|
|
||||||
uint32_t length;
|
|
||||||
uint32_t next;
|
|
||||||
} pseudo;
|
|
||||||
|
|
||||||
memset(&ip6, 0x0, sizeof(struct ip6_hdr));
|
|
||||||
memset(&icmp6, 0x0, sizeof(struct icmp6_hdr));
|
|
||||||
memset(&pseudo, 0x0, sizeof(pseudo));
|
|
||||||
|
|
||||||
if(ratelimit(3))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Swap Ethernet source and destination addresses */
|
|
||||||
|
|
||||||
swap_mac_addresses(packet);
|
|
||||||
|
|
||||||
/* Copy headers from packet to structs on the stack */
|
|
||||||
|
|
||||||
memcpy(&ip6, DATA(packet) + ether_size, ip6_size);
|
|
||||||
|
|
||||||
/* Remember original source and destination */
|
|
||||||
|
|
||||||
pseudo.ip6_src = ip6.ip6_dst;
|
|
||||||
pseudo.ip6_dst = ip6.ip6_src;
|
|
||||||
|
|
||||||
pseudo.length = packet->len - ether_size;
|
|
||||||
|
|
||||||
if(type == ICMP6_PACKET_TOO_BIG)
|
|
||||||
icmp6.icmp6_mtu = htonl(pseudo.length);
|
|
||||||
|
|
||||||
if(pseudo.length >= IP_MSS - ip6_size - icmp6_size)
|
|
||||||
pseudo.length = IP_MSS - ip6_size - icmp6_size;
|
|
||||||
|
|
||||||
/* Copy first part of original contents to ICMP message */
|
|
||||||
|
|
||||||
memmove(DATA(packet) + ether_size + ip6_size + icmp6_size, DATA(packet) + ether_size, pseudo.length);
|
|
||||||
|
|
||||||
/* Fill in IPv6 header */
|
|
||||||
|
|
||||||
ip6.ip6_flow = htonl(0x60000000UL);
|
|
||||||
ip6.ip6_plen = htons(icmp6_size + pseudo.length);
|
|
||||||
ip6.ip6_nxt = IPPROTO_ICMPV6;
|
|
||||||
ip6.ip6_hlim = 255;
|
|
||||||
ip6.ip6_src = pseudo.ip6_src;
|
|
||||||
ip6.ip6_dst = pseudo.ip6_dst;
|
|
||||||
|
|
||||||
/* Fill in ICMP header */
|
|
||||||
|
|
||||||
icmp6.icmp6_type = type;
|
|
||||||
icmp6.icmp6_code = code;
|
|
||||||
icmp6.icmp6_cksum = 0;
|
|
||||||
|
|
||||||
/* Create pseudo header */
|
|
||||||
|
|
||||||
pseudo.length = htonl(icmp6_size + pseudo.length);
|
|
||||||
pseudo.next = htonl(IPPROTO_ICMPV6);
|
|
||||||
|
|
||||||
/* Generate checksum */
|
|
||||||
|
|
||||||
checksum = inet_checksum(&pseudo, sizeof pseudo, ~0);
|
|
||||||
checksum = inet_checksum(&icmp6, icmp6_size, checksum);
|
|
||||||
checksum = inet_checksum(DATA(packet) + ether_size + ip6_size + icmp6_size, ntohl(pseudo.length) - icmp6_size, checksum);
|
|
||||||
|
|
||||||
icmp6.icmp6_cksum = checksum;
|
|
||||||
|
|
||||||
/* Copy structs on stack back to packet */
|
|
||||||
|
|
||||||
memcpy(DATA(packet) + ether_size, &ip6, ip6_size);
|
|
||||||
memcpy(DATA(packet) + ether_size + ip6_size, &icmp6, icmp6_size);
|
|
||||||
|
|
||||||
packet->len = ether_size + ip6_size + ntohl(pseudo.length);
|
|
||||||
|
|
||||||
send_packet(source, packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void route_neighborsol(node_t *source, vpn_packet_t *packet);
|
static void route_neighborsol(node_t *source, vpn_packet_t *packet);
|
||||||
|
|
||||||
static void route_ipv6(node_t *source, vpn_packet_t *packet) {
|
static void route_ipv6(node_t *source, vpn_packet_t *packet) {
|
||||||
|
@ -611,7 +710,7 @@ static void route_ipv6(node_t *source, vpn_packet_t *packet) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
broadcast_packet(source, packet);
|
route_broadcast(source, packet);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -626,6 +725,10 @@ static void route_ipv6(node_t *source, vpn_packet_t *packet) {
|
||||||
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
|
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
|
||||||
return route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN);
|
return route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN);
|
||||||
|
|
||||||
|
if(decrement_ttl && source != myself && subnet->owner != myself)
|
||||||
|
if(!do_decrement_ttl(source, packet))
|
||||||
|
return;
|
||||||
|
|
||||||
via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
|
via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
|
||||||
|
|
||||||
if(via == source) {
|
if(via == source) {
|
||||||
|
@ -742,6 +845,10 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet) {
|
||||||
if(subnet->owner == myself)
|
if(subnet->owner == myself)
|
||||||
return; /* silently ignore */
|
return; /* silently ignore */
|
||||||
|
|
||||||
|
if(decrement_ttl)
|
||||||
|
if(!do_decrement_ttl(source, packet))
|
||||||
|
return;
|
||||||
|
|
||||||
/* Create neighbor advertation reply */
|
/* Create neighbor advertation reply */
|
||||||
|
|
||||||
memcpy(DATA(packet), DATA(packet) + ETH_ALEN, ETH_ALEN); /* copy destination address */
|
memcpy(DATA(packet), DATA(packet) + ETH_ALEN, ETH_ALEN); /* copy destination address */
|
||||||
|
@ -837,6 +944,10 @@ static void route_arp(node_t *source, vpn_packet_t *packet) {
|
||||||
if(subnet->owner == myself)
|
if(subnet->owner == myself)
|
||||||
return; /* silently ignore */
|
return; /* silently ignore */
|
||||||
|
|
||||||
|
if(decrement_ttl)
|
||||||
|
if(!do_decrement_ttl(source, packet))
|
||||||
|
return;
|
||||||
|
|
||||||
memcpy(&addr, arp.arp_tpa, sizeof addr); /* save protocol addr */
|
memcpy(&addr, arp.arp_tpa, sizeof addr); /* save protocol addr */
|
||||||
memcpy(arp.arp_tpa, arp.arp_spa, sizeof addr); /* swap destination and source protocol address */
|
memcpy(arp.arp_tpa, arp.arp_spa, sizeof addr); /* swap destination and source protocol address */
|
||||||
memcpy(arp.arp_spa, &addr, sizeof addr); /* ... */
|
memcpy(arp.arp_spa, &addr, sizeof addr); /* ... */
|
||||||
|
@ -871,7 +982,7 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
|
||||||
subnet = lookup_subnet_mac(NULL, &dest);
|
subnet = lookup_subnet_mac(NULL, &dest);
|
||||||
|
|
||||||
if(!subnet || !subnet->owner) {
|
if(!subnet || !subnet->owner) {
|
||||||
broadcast_packet(source, packet);
|
route_broadcast(source, packet);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -883,6 +994,10 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
|
||||||
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
|
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(decrement_ttl && source != myself && subnet->owner != myself)
|
||||||
|
if(!do_decrement_ttl(source, packet))
|
||||||
|
return;
|
||||||
|
|
||||||
uint16_t type = DATA(packet)[12] << 8 | DATA(packet)[13];
|
uint16_t type = DATA(packet)[12] << 8 | DATA(packet)[13];
|
||||||
|
|
||||||
if(priorityinheritance && type == ETH_P_IP && packet->len >= ether_size + ip_size)
|
if(priorityinheritance && type == ETH_P_IP && packet->len >= ether_size + ip_size)
|
||||||
|
@ -941,58 +1056,6 @@ static void send_pcap(vpn_packet_t *packet) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool do_decrement_ttl(node_t *source, vpn_packet_t *packet) {
|
|
||||||
uint16_t type = DATA(packet)[12] << 8 | DATA(packet)[13];
|
|
||||||
length_t ethlen = ether_size;
|
|
||||||
|
|
||||||
if(type == ETH_P_8021Q) {
|
|
||||||
type = DATA(packet)[16] << 8 | DATA(packet)[17];
|
|
||||||
ethlen += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case ETH_P_IP:
|
|
||||||
if(!checklength(source, packet, ethlen + ip_size))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(DATA(packet)[ethlen + 8] < 1) {
|
|
||||||
if(DATA(packet)[ethlen + 11] != IPPROTO_ICMP || DATA(packet)[ethlen + 32] != ICMP_TIME_EXCEEDED)
|
|
||||||
route_ipv4_unreachable(source, packet, ethlen, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t old = DATA(packet)[ethlen + 8] << 8 | DATA(packet)[ethlen + 9];
|
|
||||||
DATA(packet)[ethlen + 8]--;
|
|
||||||
uint16_t new = DATA(packet)[ethlen + 8] << 8 | DATA(packet)[ethlen + 9];
|
|
||||||
|
|
||||||
uint32_t checksum = DATA(packet)[ethlen + 10] << 8 | DATA(packet)[ethlen + 11];
|
|
||||||
checksum += old + (~new & 0xFFFF);
|
|
||||||
while(checksum >> 16)
|
|
||||||
checksum = (checksum & 0xFFFF) + (checksum >> 16);
|
|
||||||
DATA(packet)[ethlen + 10] = checksum >> 8;
|
|
||||||
DATA(packet)[ethlen + 11] = checksum & 0xff;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case ETH_P_IPV6:
|
|
||||||
if(!checklength(source, packet, ethlen + ip6_size))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(DATA(packet)[ethlen + 7] < 1) {
|
|
||||||
if(DATA(packet)[ethlen + 6] != IPPROTO_ICMPV6 || DATA(packet)[ethlen + 40] != ICMP6_TIME_EXCEEDED)
|
|
||||||
route_ipv6_unreachable(source, packet, ethlen, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DATA(packet)[ethlen + 7]--;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void route(node_t *source, vpn_packet_t *packet) {
|
void route(node_t *source, vpn_packet_t *packet) {
|
||||||
if(pcap)
|
if(pcap)
|
||||||
send_pcap(packet);
|
send_pcap(packet);
|
||||||
|
@ -1005,10 +1068,6 @@ void route(node_t *source, vpn_packet_t *packet) {
|
||||||
if(!checklength(source, packet, ether_size))
|
if(!checklength(source, packet, ether_size))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(decrement_ttl && source != myself)
|
|
||||||
if(!do_decrement_ttl(source, packet))
|
|
||||||
return;
|
|
||||||
|
|
||||||
uint16_t type = DATA(packet)[12] << 8 | DATA(packet)[13];
|
uint16_t type = DATA(packet)[12] << 8 | DATA(packet)[13];
|
||||||
|
|
||||||
switch (routing_mode) {
|
switch (routing_mode) {
|
||||||
|
@ -1037,7 +1096,7 @@ void route(node_t *source, vpn_packet_t *packet) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RMODE_HUB:
|
case RMODE_HUB:
|
||||||
broadcast_packet(source, packet);
|
route_broadcast(source, packet);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
63
src/script.c
63
src/script.c
|
@ -26,8 +26,44 @@
|
||||||
#include "script.h"
|
#include "script.h"
|
||||||
#include "xalloc.h"
|
#include "xalloc.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_PUTENV
|
||||||
|
static void unputenv(const char *p) {
|
||||||
|
const char *e = strchr(p, '=');
|
||||||
|
if(!e)
|
||||||
|
return;
|
||||||
|
int len = e - p;
|
||||||
|
#ifndef HAVE_UNSETENV
|
||||||
|
#ifdef HAVE_MINGW
|
||||||
|
// Windows requires putenv("FOO=") to unset %FOO%
|
||||||
|
len++;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
char var[len + 1];
|
||||||
|
strncpy(var, p, len);
|
||||||
|
var[len] = 0;
|
||||||
|
#ifdef HAVE_UNSETENV
|
||||||
|
unsetenv(var);
|
||||||
|
#else
|
||||||
|
// We must keep what we putenv() around in memory.
|
||||||
|
// To do this without memory leaks, keep things in a list and reuse if possible.
|
||||||
|
static list_t list = {};
|
||||||
|
for list_each(char, data, &list) {
|
||||||
|
if(!strcmp(data, var)) {
|
||||||
|
putenv(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
char *data = xstrdup(var);
|
||||||
|
list_insert_tail(&list, data);
|
||||||
|
putenv(data);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void putenv(const char *p) {}
|
||||||
|
static void unputenv(const char *p) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool execute_script(const char *name, char **envp) {
|
bool execute_script(const char *name, char **envp) {
|
||||||
#ifdef HAVE_SYSTEM
|
|
||||||
char scriptname[PATH_MAX];
|
char scriptname[PATH_MAX];
|
||||||
char *command;
|
char *command;
|
||||||
|
|
||||||
|
@ -38,9 +74,11 @@ bool execute_script(const char *name, char **envp) {
|
||||||
#ifdef HAVE_MINGW
|
#ifdef HAVE_MINGW
|
||||||
if(!*scriptextension) {
|
if(!*scriptextension) {
|
||||||
const char *pathext = getenv("PATHEXT") ?: ".COM;.EXE;.BAT;.CMD";
|
const char *pathext = getenv("PATHEXT") ?: ".COM;.EXE;.BAT;.CMD";
|
||||||
char fullname[strlen(scriptname) + strlen(pathext)];
|
size_t pathlen = strlen(pathext);
|
||||||
char *ext = fullname + strlen(scriptname);
|
size_t scriptlen = strlen(scriptname);
|
||||||
strcpy(fullname, scriptname);
|
char fullname[scriptlen + pathlen + 1];
|
||||||
|
char *ext = fullname + scriptlen;
|
||||||
|
strncpy(fullname, scriptname, sizeof fullname);
|
||||||
|
|
||||||
const char *p = pathext;
|
const char *p = pathext;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
@ -51,7 +89,7 @@ bool execute_script(const char *name, char **envp) {
|
||||||
ext[q - p] = 0;
|
ext[q - p] = 0;
|
||||||
q++;
|
q++;
|
||||||
} else {
|
} else {
|
||||||
strcpy(ext, p);
|
strncpy(ext, p, pathlen + 1);
|
||||||
}
|
}
|
||||||
if((found = !access(fullname, F_OK)))
|
if((found = !access(fullname, F_OK)))
|
||||||
break;
|
break;
|
||||||
|
@ -67,12 +105,10 @@ bool execute_script(const char *name, char **envp) {
|
||||||
|
|
||||||
logger(DEBUG_STATUS, LOG_INFO, "Executing script %s", name);
|
logger(DEBUG_STATUS, LOG_INFO, "Executing script %s", name);
|
||||||
|
|
||||||
#ifdef HAVE_PUTENV
|
|
||||||
/* Set environment */
|
/* Set environment */
|
||||||
|
|
||||||
for(int i = 0; envp[i]; i++)
|
for(int i = 0; envp[i]; i++)
|
||||||
putenv(envp[i]);
|
putenv(envp[i]);
|
||||||
#endif
|
|
||||||
|
|
||||||
if(scriptinterpreter)
|
if(scriptinterpreter)
|
||||||
xasprintf(&command, "%s \"%s\"", scriptinterpreter, scriptname);
|
xasprintf(&command, "%s \"%s\"", scriptinterpreter, scriptname);
|
||||||
|
@ -85,15 +121,8 @@ bool execute_script(const char *name, char **envp) {
|
||||||
|
|
||||||
/* Unset environment */
|
/* Unset environment */
|
||||||
|
|
||||||
for(int i = 0; envp[i]; i++) {
|
for(int i = 0; envp[i]; i++)
|
||||||
char *e = strchr(envp[i], '=');
|
unputenv(envp[i]);
|
||||||
if(e) {
|
|
||||||
char p[e - envp[i] + 1];
|
|
||||||
strncpy(p, envp[i], e - envp[i]);
|
|
||||||
p[e - envp[i]] = '\0';
|
|
||||||
putenv(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(status != -1) {
|
if(status != -1) {
|
||||||
#ifdef WEXITSTATUS
|
#ifdef WEXITSTATUS
|
||||||
|
@ -116,6 +145,6 @@ bool execute_script(const char *name, char **envp) {
|
||||||
logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "system", strerror(errno));
|
logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "system", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,7 +222,7 @@ static bool generate_key_material(sptps_t *s, const char *shared, size_t len) {
|
||||||
|
|
||||||
// Create the HMAC seed, which is "key expansion" + session label + server nonce + client nonce
|
// Create the HMAC seed, which is "key expansion" + session label + server nonce + client nonce
|
||||||
char seed[s->labellen + 64 + 13];
|
char seed[s->labellen + 64 + 13];
|
||||||
strcpy(seed, "key expansion");
|
memcpy(seed, "key expansion", 13);
|
||||||
if(s->initiator) {
|
if(s->initiator) {
|
||||||
memcpy(seed + 13, s->mykex + 1, 32);
|
memcpy(seed + 13, s->mykex + 1, 32);
|
||||||
memcpy(seed + 45, s->hiskex + 1, 32);
|
memcpy(seed + 45, s->hiskex + 1, 32);
|
||||||
|
|
|
@ -30,6 +30,15 @@
|
||||||
#include "sptps.h"
|
#include "sptps.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
// Symbols necessary to link with logger.o
|
||||||
|
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;
|
||||||
|
bool do_detach = false;
|
||||||
|
struct timeval now;
|
||||||
|
|
||||||
|
static bool special;
|
||||||
static bool verbose;
|
static bool verbose;
|
||||||
static bool readonly;
|
static bool readonly;
|
||||||
static bool writeonly;
|
static bool writeonly;
|
||||||
|
@ -64,6 +73,7 @@ static struct option const long_options[] = {
|
||||||
{"writeonly", no_argument, NULL, 'w'},
|
{"writeonly", no_argument, NULL, 'w'},
|
||||||
{"packet-loss", required_argument, NULL, 'L'},
|
{"packet-loss", required_argument, NULL, 'L'},
|
||||||
{"replay-window", required_argument, NULL, 'W'},
|
{"replay-window", required_argument, NULL, 'W'},
|
||||||
|
{"special", no_argument, NULL, 's'},
|
||||||
{"verbose", required_argument, NULL, 'v'},
|
{"verbose", required_argument, NULL, 'v'},
|
||||||
{"help", no_argument, NULL, 1},
|
{"help", no_argument, NULL, 1},
|
||||||
{NULL, 0, NULL, 0}
|
{NULL, 0, NULL, 0}
|
||||||
|
@ -83,6 +93,7 @@ static void usage() {
|
||||||
" -w, --writeonly Only send data from stdin to the socket.\n"
|
" -w, --writeonly Only send data from stdin to the socket.\n"
|
||||||
" -L, --packet-loss RATE Fake packet loss of RATE percent.\n"
|
" -L, --packet-loss RATE Fake packet loss of RATE percent.\n"
|
||||||
" -R, --replay-window N Set replay window to N bytes.\n"
|
" -R, --replay-window N Set replay window to N bytes.\n"
|
||||||
|
" -s, --special Enable special handling of lines starting with #, ^ and $.\n"
|
||||||
" -v, --verbose Display debug messages.\n"
|
" -v, --verbose Display debug messages.\n"
|
||||||
"\n");
|
"\n");
|
||||||
fprintf(stderr, "Report bugs to tinc@tinc-vpn.org.\n");
|
fprintf(stderr, "Report bugs to tinc@tinc-vpn.org.\n");
|
||||||
|
@ -101,7 +112,7 @@ int main(int argc, char *argv[]) {
|
||||||
ecdsa_t *mykey = NULL, *hiskey = NULL;
|
ecdsa_t *mykey = NULL, *hiskey = NULL;
|
||||||
bool quit = false;
|
bool quit = false;
|
||||||
|
|
||||||
while((r = getopt_long(argc, argv, "dqrtwL:W:v", long_options, &option_index)) != EOF) {
|
while((r = getopt_long(argc, argv, "dqrstwL:W:v", long_options, &option_index)) != EOF) {
|
||||||
switch (r) {
|
switch (r) {
|
||||||
case 0: /* long option */
|
case 0: /* long option */
|
||||||
break;
|
break;
|
||||||
|
@ -144,6 +155,10 @@ int main(int argc, char *argv[]) {
|
||||||
verbose = true;
|
verbose = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 's': /* special character handling */
|
||||||
|
special = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case '?': /* wrong options */
|
case '?': /* wrong options */
|
||||||
usage();
|
usage();
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -318,11 +333,11 @@ int main(int argc, char *argv[]) {
|
||||||
readonly = true;
|
readonly = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(buf[0] == '#')
|
if(special && buf[0] == '#')
|
||||||
s.outseqno = atoi(buf + 1);
|
s.outseqno = atoi(buf + 1);
|
||||||
if(buf[0] == '^')
|
if(special && buf[0] == '^')
|
||||||
sptps_send_record(&s, SPTPS_HANDSHAKE, NULL, 0);
|
sptps_send_record(&s, SPTPS_HANDSHAKE, NULL, 0);
|
||||||
else if(buf[0] == '$') {
|
else if(special && buf[0] == '$') {
|
||||||
sptps_force_kex(&s);
|
sptps_force_kex(&s);
|
||||||
if(len > 1)
|
if(len > 1)
|
||||||
sptps_send_record(&s, 0, buf, len);
|
sptps_send_record(&s, 0, buf, len);
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#define __TINC_SUBNET_H__
|
#define __TINC_SUBNET_H__
|
||||||
|
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "hash.h"
|
#include "node.h"
|
||||||
|
|
||||||
typedef enum subnet_type_t {
|
typedef enum subnet_type_t {
|
||||||
SUBNET_MAC = 0,
|
SUBNET_MAC = 0,
|
||||||
|
@ -45,8 +45,6 @@ typedef struct subnet_ipv6_t {
|
||||||
int prefixlength;
|
int prefixlength;
|
||||||
} subnet_ipv6_t;
|
} subnet_ipv6_t;
|
||||||
|
|
||||||
#include "node.h"
|
|
||||||
|
|
||||||
typedef struct subnet_t {
|
typedef struct subnet_t {
|
||||||
struct node_t *owner; /* the owner of this subnet */
|
struct node_t *owner; /* the owner of this subnet */
|
||||||
|
|
||||||
|
|
12
src/system.h
12
src/system.h
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
system.h -- system headers
|
system.h -- system headers
|
||||||
Copyright (C) 1998-2005 Ivo Timmermans
|
Copyright (C) 1998-2005 Ivo Timmermans
|
||||||
2003-2013 Guus Sliepen <guus@tinc-vpn.org>
|
2003-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -25,12 +25,6 @@
|
||||||
|
|
||||||
#include "have.h"
|
#include "have.h"
|
||||||
|
|
||||||
#ifndef HAVE_STDBOOL_H
|
|
||||||
typedef int bool;
|
|
||||||
#define true 1
|
|
||||||
#define false 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef HAVE_STRSIGNAL
|
#ifndef HAVE_STRSIGNAL
|
||||||
# define strsignal(p) ""
|
# define strsignal(p) ""
|
||||||
#endif
|
#endif
|
||||||
|
@ -39,10 +33,6 @@ typedef int bool;
|
||||||
|
|
||||||
#include "dropin.h"
|
#include "dropin.h"
|
||||||
|
|
||||||
#ifndef HAVE_SOCKLEN_T
|
|
||||||
typedef int socklen_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define UNUSED(n) (void)(n);
|
#define UNUSED(n) (void)(n);
|
||||||
|
|
||||||
#endif /* __TINC_SYSTEM_H__ */
|
#endif /* __TINC_SYSTEM_H__ */
|
||||||
|
|
285
src/tincctl.c
285
src/tincctl.c
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
tincctl.c -- Controlling a running tincd
|
tincctl.c -- Controlling a running tincd
|
||||||
Copyright (C) 2007-2015 Guus Sliepen <guus@tinc-vpn.org>
|
Copyright (C) 2007-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -88,7 +88,7 @@ static struct option const long_options[] = {
|
||||||
static void version(void) {
|
static void version(void) {
|
||||||
printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
|
printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
|
||||||
BUILD_VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
|
BUILD_VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
|
||||||
printf("Copyright (C) 1998-2015 Ivo Timmermans, Guus Sliepen and others.\n"
|
printf("Copyright (C) 1998-2016 Ivo Timmermans, Guus Sliepen and others.\n"
|
||||||
"See the AUTHORS file for a complete list.\n\n"
|
"See the AUTHORS file for a complete list.\n\n"
|
||||||
"tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
|
"tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
|
||||||
"and you are welcome to redistribute it under certain conditions;\n"
|
"and you are welcome to redistribute it under certain conditions;\n"
|
||||||
|
@ -153,6 +153,8 @@ static void usage(bool status) {
|
||||||
" join INVITATION Join a VPN using an INVITATION\n"
|
" join INVITATION Join a VPN using an INVITATION\n"
|
||||||
" network [NETNAME] List all known networks, or switch to the one named NETNAME.\n"
|
" network [NETNAME] List all known networks, or switch to the one named NETNAME.\n"
|
||||||
" fsck Check the configuration files for problems.\n"
|
" fsck Check the configuration files for problems.\n"
|
||||||
|
" sign [FILE] Generate a signed version of a file.\n"
|
||||||
|
" verify NODE [FILE] Verify that a file was signed by the given NODE.\n"
|
||||||
"\n");
|
"\n");
|
||||||
printf("Report bugs to tinc@tinc-vpn.org.\n");
|
printf("Report bugs to tinc@tinc-vpn.org.\n");
|
||||||
}
|
}
|
||||||
|
@ -327,7 +329,7 @@ static void disable_old_keys(const char *filename, const char *what) {
|
||||||
|
|
||||||
static FILE *ask_and_open(const char *filename, const char *what, const char *mode, bool ask, mode_t perms) {
|
static FILE *ask_and_open(const char *filename, const char *what, const char *mode, bool ask, mode_t perms) {
|
||||||
FILE *r;
|
FILE *r;
|
||||||
char *directory;
|
char directory[PATH_MAX] = ".";
|
||||||
char buf[PATH_MAX];
|
char buf[PATH_MAX];
|
||||||
char buf2[PATH_MAX];
|
char buf2[PATH_MAX];
|
||||||
|
|
||||||
|
@ -355,7 +357,7 @@ static FILE *ask_and_open(const char *filename, const char *what, const char *mo
|
||||||
if(filename[0] != '/') {
|
if(filename[0] != '/') {
|
||||||
#endif
|
#endif
|
||||||
/* The directory is a relative path or a filename. */
|
/* The directory is a relative path or a filename. */
|
||||||
directory = get_current_dir_name();
|
getcwd(directory, sizeof directory);
|
||||||
snprintf(buf2, sizeof buf2, "%s" SLASH "%s", directory, filename);
|
snprintf(buf2, sizeof buf2, "%s" SLASH "%s", directory, filename);
|
||||||
filename = buf2;
|
filename = buf2;
|
||||||
}
|
}
|
||||||
|
@ -1437,6 +1439,29 @@ char *get_my_name(bool verbose) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ecdsa_t *get_pubkey(FILE *f) {
|
||||||
|
char buf[4096];
|
||||||
|
char *value;
|
||||||
|
while(fgets(buf, sizeof buf, f)) {
|
||||||
|
int len = strcspn(buf, "\t =");
|
||||||
|
value = buf + len;
|
||||||
|
value += strspn(value, "\t ");
|
||||||
|
if(*value == '=') {
|
||||||
|
value++;
|
||||||
|
value += strspn(value, "\t ");
|
||||||
|
}
|
||||||
|
if(!rstrip(value))
|
||||||
|
continue;
|
||||||
|
buf[len] = 0;
|
||||||
|
if(strcasecmp(buf, "Ed25519PublicKey"))
|
||||||
|
continue;
|
||||||
|
if(*value)
|
||||||
|
return ecdsa_set_base64_public_key(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
const var_t variables[] = {
|
const var_t variables[] = {
|
||||||
/* Server configuration */
|
/* Server configuration */
|
||||||
{"AddressFamily", VAR_SERVER},
|
{"AddressFamily", VAR_SERVER},
|
||||||
|
@ -2272,26 +2297,29 @@ static int cmd_exchange_all(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int switch_network(char *name) {
|
static int switch_network(char *name) {
|
||||||
|
if(strcmp(name, ".")) {
|
||||||
|
if(!check_netname(name, false)) {
|
||||||
|
fprintf(stderr, "Invalid character in netname!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!check_netname(name, true))
|
||||||
|
fprintf(stderr, "Warning: unsafe character in netname!\n");
|
||||||
|
}
|
||||||
|
|
||||||
if(fd >= 0) {
|
if(fd >= 0) {
|
||||||
close(fd);
|
close(fd);
|
||||||
fd = -1;
|
fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(confbase);
|
free_names();
|
||||||
confbase = NULL;
|
netname = strcmp(name, ".") ? xstrdup(name) : NULL;
|
||||||
free(pidfilename);
|
make_names(false);
|
||||||
pidfilename = NULL;
|
|
||||||
free(logfilename);
|
|
||||||
logfilename = NULL;
|
|
||||||
free(unixsocketname);
|
|
||||||
unixsocketname = NULL;
|
|
||||||
free(tinc_conf);
|
free(tinc_conf);
|
||||||
free(hosts_dir);
|
free(hosts_dir);
|
||||||
free(prompt);
|
free(prompt);
|
||||||
|
|
||||||
free(netname);
|
|
||||||
netname = strcmp(name, ".") ? xstrdup(name) : NULL;
|
|
||||||
|
|
||||||
xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
|
xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
|
||||||
xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
|
xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
|
||||||
xasprintf(&prompt, "%s> ", identname);
|
xasprintf(&prompt, "%s> ", identname);
|
||||||
|
@ -2345,6 +2373,231 @@ static int cmd_fsck(int argc, char *argv[]) {
|
||||||
return fsck(orig_argv[0]);
|
return fsck(orig_argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *readfile(FILE *in, size_t *len) {
|
||||||
|
size_t count = 0;
|
||||||
|
size_t alloced = 4096;
|
||||||
|
char *buf = xmalloc(alloced);
|
||||||
|
|
||||||
|
while(!feof(in)) {
|
||||||
|
size_t read = fread(buf + count, 1, alloced - count, in);
|
||||||
|
if(!read)
|
||||||
|
break;
|
||||||
|
count += read;
|
||||||
|
if(count >= alloced) {
|
||||||
|
alloced *= 2;
|
||||||
|
buf = xrealloc(buf, alloced);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(len)
|
||||||
|
*len = count;
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmd_sign(int argc, char *argv[]) {
|
||||||
|
if(argc > 2) {
|
||||||
|
fprintf(stderr, "Too many arguments!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!name) {
|
||||||
|
name = get_my_name(true);
|
||||||
|
if(!name)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char fname[PATH_MAX];
|
||||||
|
snprintf(fname, sizeof fname, "%s" SLASH "ed25519_key.priv", confbase);
|
||||||
|
FILE *fp = fopen(fname, "r");
|
||||||
|
if(!fp) {
|
||||||
|
fprintf(stderr, "Could not open %s: %s\n", fname, strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecdsa_t *key = ecdsa_read_pem_private_key(fp);
|
||||||
|
|
||||||
|
if(!key) {
|
||||||
|
fprintf(stderr, "Could not read private key from %s\n", fname);
|
||||||
|
fclose(fp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
FILE *in;
|
||||||
|
|
||||||
|
if(argc == 2) {
|
||||||
|
in = fopen(argv[1], "rb");
|
||||||
|
if(!in) {
|
||||||
|
fprintf(stderr, "Could not open %s: %s\n", argv[1], strerror(errno));
|
||||||
|
ecdsa_free(key);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
in = stdin;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t len;
|
||||||
|
char *data = readfile(in, &len);
|
||||||
|
if(in != stdin)
|
||||||
|
fclose(in);
|
||||||
|
if(!data) {
|
||||||
|
fprintf(stderr, "Error reading %s: %s\n", argv[1], strerror(errno));
|
||||||
|
ecdsa_free(key);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure we sign our name and current time as well
|
||||||
|
long t = time(NULL);
|
||||||
|
char *trailer;
|
||||||
|
xasprintf(&trailer, " %s %ld", name, t);
|
||||||
|
int trailer_len = strlen(trailer);
|
||||||
|
|
||||||
|
data = xrealloc(data, len + trailer_len);
|
||||||
|
memcpy(data + len, trailer, trailer_len);
|
||||||
|
free(trailer);
|
||||||
|
|
||||||
|
char sig[87];
|
||||||
|
if(!ecdsa_sign(key, data, len + trailer_len, sig)) {
|
||||||
|
fprintf(stderr, "Error generating signature\n");
|
||||||
|
free(data);
|
||||||
|
ecdsa_free(key);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
b64encode(sig, sig, 64);
|
||||||
|
ecdsa_free(key);
|
||||||
|
|
||||||
|
fprintf(stdout, "Signature = %s %ld %s\n", name, t, sig);
|
||||||
|
fwrite(data, len, 1, stdout);
|
||||||
|
|
||||||
|
free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmd_verify(int argc, char *argv[]) {
|
||||||
|
if(argc < 2) {
|
||||||
|
fprintf(stderr, "Not enough arguments!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(argc > 3) {
|
||||||
|
fprintf(stderr, "Too many arguments!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *node = argv[1];
|
||||||
|
if(!strcmp(node, ".")) {
|
||||||
|
if(!name) {
|
||||||
|
name = get_my_name(true);
|
||||||
|
if(!name)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
node = name;
|
||||||
|
} else if(!strcmp(node, "*")) {
|
||||||
|
node = NULL;
|
||||||
|
} else {
|
||||||
|
if(!check_id(node)) {
|
||||||
|
fprintf(stderr, "Invalid node name\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *in;
|
||||||
|
|
||||||
|
if(argc == 3) {
|
||||||
|
in = fopen(argv[2], "rb");
|
||||||
|
if(!in) {
|
||||||
|
fprintf(stderr, "Could not open %s: %s\n", argv[2], strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
in = stdin;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t len;
|
||||||
|
char *data = readfile(in, &len);
|
||||||
|
if(in != stdin)
|
||||||
|
fclose(in);
|
||||||
|
if(!data) {
|
||||||
|
fprintf(stderr, "Error reading %s: %s\n", argv[1], strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *newline = memchr(data, '\n', len);
|
||||||
|
if(!newline || (newline - data > MAX_STRING_SIZE - 1)) {
|
||||||
|
fprintf(stderr, "Invalid input\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*newline++ = '\0';
|
||||||
|
size_t skip = newline - data;
|
||||||
|
|
||||||
|
char signer[MAX_STRING_SIZE] = "";
|
||||||
|
char sig[MAX_STRING_SIZE] = "";
|
||||||
|
long t = 0;
|
||||||
|
|
||||||
|
if(sscanf(data, "Signature = %s %ld %s", signer, &t, sig) != 3 || strlen(sig) != 86 || !t || !check_id(signer)) {
|
||||||
|
fprintf(stderr, "Invalid input\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(node && strcmp(node, signer)) {
|
||||||
|
fprintf(stderr, "Signature is not made by %s\n", node);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!node)
|
||||||
|
node = signer;
|
||||||
|
|
||||||
|
char *trailer;
|
||||||
|
xasprintf(&trailer, " %s %ld", signer, t);
|
||||||
|
int trailer_len = strlen(trailer);
|
||||||
|
|
||||||
|
data = xrealloc(data, len + trailer_len);
|
||||||
|
memcpy(data + len, trailer, trailer_len);
|
||||||
|
free(trailer);
|
||||||
|
|
||||||
|
newline = data + skip;
|
||||||
|
|
||||||
|
char fname[PATH_MAX];
|
||||||
|
snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, node);
|
||||||
|
FILE *fp = fopen(fname, "r");
|
||||||
|
if(!fp) {
|
||||||
|
fprintf(stderr, "Could not open %s: %s\n", fname, strerror(errno));
|
||||||
|
free(data);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecdsa_t *key = get_pubkey(fp);
|
||||||
|
if(!key) {
|
||||||
|
rewind(fp);
|
||||||
|
key = ecdsa_read_pem_public_key(fp);
|
||||||
|
}
|
||||||
|
if(!key) {
|
||||||
|
fprintf(stderr, "Could not read public key from %s\n", fname);
|
||||||
|
fclose(fp);
|
||||||
|
free(data);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
if(b64decode(sig, sig, 86) != 64 || !ecdsa_verify(key, newline, len + trailer_len - (newline - data), sig)) {
|
||||||
|
fprintf(stderr, "Invalid signature\n");
|
||||||
|
free(data);
|
||||||
|
ecdsa_free(key);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecdsa_free(key);
|
||||||
|
|
||||||
|
fwrite(newline, len - (newline - data), 1, stdout);
|
||||||
|
|
||||||
|
free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
const char *command;
|
const char *command;
|
||||||
int (*function)(int argc, char *argv[]);
|
int (*function)(int argc, char *argv[]);
|
||||||
|
@ -2389,6 +2642,8 @@ static const struct {
|
||||||
{"join", cmd_join, false},
|
{"join", cmd_join, false},
|
||||||
{"network", cmd_network, false},
|
{"network", cmd_network, false},
|
||||||
{"fsck", cmd_fsck, false},
|
{"fsck", cmd_fsck, false},
|
||||||
|
{"sign", cmd_sign, false},
|
||||||
|
{"verify", cmd_verify, false},
|
||||||
{NULL, NULL, NULL},
|
{NULL, NULL, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
tincctl.h -- header for tincctl.c.
|
tincctl.h -- header for tincctl.c.
|
||||||
Copyright (C) 2011-2013 Guus Sliepen <guus@tinc-vpn.org>
|
Copyright (C) 2011-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -50,6 +50,7 @@ extern bool sendline(int fd, char *format, ...);
|
||||||
extern bool recvline(int fd, char *line, size_t len);
|
extern bool recvline(int fd, char *line, size_t len);
|
||||||
extern int check_port(char *name);
|
extern int check_port(char *name);
|
||||||
extern FILE *fopenmask(const char *filename, const char *mode, mode_t perms);
|
extern FILE *fopenmask(const char *filename, const char *mode, mode_t perms);
|
||||||
|
extern ecdsa_t *get_pubkey(FILE *f);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
12
src/tincd.c
12
src/tincd.c
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
tincd.c -- the main file for tincd
|
tincd.c -- the main file for tincd
|
||||||
Copyright (C) 1998-2005 Ivo Timmermans
|
Copyright (C) 1998-2005 Ivo Timmermans
|
||||||
2000-2015 Guus Sliepen <guus@tinc-vpn.org>
|
2000-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
2008 Max Rijevski <maksuf@gmail.com>
|
2008 Max Rijevski <maksuf@gmail.com>
|
||||||
2009 Michael Tokarev <mjt@tls.msk.ru>
|
2009 Michael Tokarev <mjt@tls.msk.ru>
|
||||||
2010 Julien Muchembled <jm@jmuchemb.eu>
|
2010 Julien Muchembled <jm@jmuchemb.eu>
|
||||||
|
@ -43,8 +43,6 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <getopt.h>
|
|
||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
|
@ -254,11 +252,14 @@ static bool parse_options(int argc, char **argv) {
|
||||||
netname = NULL;
|
netname = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(netname && (strpbrk(netname, "\\/") || *netname == '.')) {
|
if(netname && !check_netname(netname, false)) {
|
||||||
fprintf(stderr, "Invalid character in netname!\n");
|
fprintf(stderr, "Invalid character in netname!\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(netname && !check_netname(netname, true))
|
||||||
|
fprintf(stderr, "Warning: unsafe character in netname!\n");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,11 +332,12 @@ int main(int argc, char **argv) {
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
make_names(true);
|
make_names(true);
|
||||||
|
chdir(confbase);
|
||||||
|
|
||||||
if(show_version) {
|
if(show_version) {
|
||||||
printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
|
printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
|
||||||
BUILD_VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
|
BUILD_VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
|
||||||
printf("Copyright (C) 1998-2015 Ivo Timmermans, Guus Sliepen and others.\n"
|
printf("Copyright (C) 1998-2016 Ivo Timmermans, Guus Sliepen and others.\n"
|
||||||
"See the AUTHORS file for a complete list.\n\n"
|
"See the AUTHORS file for a complete list.\n\n"
|
||||||
"tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
|
"tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
|
||||||
"and you are welcome to redistribute it under certain conditions;\n"
|
"and you are welcome to redistribute it under certain conditions;\n"
|
||||||
|
|
18
src/utils.c
18
src/utils.c
|
@ -158,7 +158,7 @@ int b64encode_urlsafe(const void *src, char *dst, int length) {
|
||||||
const char *winerror(int err) {
|
const char *winerror(int err) {
|
||||||
static char buf[1024], *ptr;
|
static char buf[1024], *ptr;
|
||||||
|
|
||||||
ptr = buf + sprintf(buf, "(%d) ", err);
|
ptr = buf + snprintf(buf, sizeof buf, "(%d) ", err);
|
||||||
|
|
||||||
if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), ptr, sizeof(buf) - (ptr - buf), NULL)) {
|
NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), ptr, sizeof(buf) - (ptr - buf), NULL)) {
|
||||||
|
@ -191,6 +191,22 @@ bool check_id(const char *id) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool check_netname(const char *netname, bool strict) {
|
||||||
|
if(!netname || !*netname || *netname == '.')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for(const char *c = netname; *c; c++) {
|
||||||
|
if(iscntrl(*c))
|
||||||
|
return false;
|
||||||
|
if(*c == '/' || *c == '\\')
|
||||||
|
return false;
|
||||||
|
if(strict && strchr(" $%<>:`\"|?*", *c))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Windows doesn't define HOST_NAME_MAX. */
|
/* Windows doesn't define HOST_NAME_MAX. */
|
||||||
#ifndef HOST_NAME_MAX
|
#ifndef HOST_NAME_MAX
|
||||||
#define HOST_NAME_MAX 255
|
#define HOST_NAME_MAX 255
|
||||||
|
|
|
@ -51,6 +51,7 @@ extern const char *winerror(int);
|
||||||
extern unsigned int bitfield_to_int(const void *bitfield, size_t size);
|
extern unsigned int bitfield_to_int(const void *bitfield, size_t size);
|
||||||
|
|
||||||
extern bool check_id(const char *);
|
extern bool check_id(const char *);
|
||||||
|
extern bool check_netname(const char *, bool strict);
|
||||||
char *replace_name(const char *name);
|
char *replace_name(const char *name);
|
||||||
|
|
||||||
#endif /* __TINC_UTILS_H__ */
|
#endif /* __TINC_UTILS_H__ */
|
||||||
|
|
|
@ -11,12 +11,18 @@ test_scripts = \
|
||||||
variables.test
|
variables.test
|
||||||
|
|
||||||
TESTS = \
|
TESTS = \
|
||||||
simple \
|
basic.test \
|
||||||
$(test_scripts)
|
commandline.test \
|
||||||
|
executables.test \
|
||||||
|
import-export.test \
|
||||||
|
invite-join.test \
|
||||||
|
invite-tinc-up.test \
|
||||||
|
ns-ping.test \
|
||||||
|
ping.test \
|
||||||
|
sptps-basic.test \
|
||||||
|
variables.test
|
||||||
|
|
||||||
CC=clang
|
dist_check_SCRIPTS = $(TESTS)
|
||||||
|
|
||||||
dist_check_SCRIPTS = $(test_scripts)
|
|
||||||
|
|
||||||
EXTRA_DIST = testlib.sh
|
EXTRA_DIST = testlib.sh
|
||||||
|
|
||||||
|
|
51
test/invite-tinc-up.test
Executable file
51
test/invite-tinc-up.test
Executable file
|
@ -0,0 +1,51 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
. ./testlib.sh
|
||||||
|
|
||||||
|
# Initialize one node
|
||||||
|
|
||||||
|
$tinc $c1 <<EOF
|
||||||
|
init foo
|
||||||
|
set DeviceType dummy
|
||||||
|
set Address localhost
|
||||||
|
set Port 32751
|
||||||
|
start $r1
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Generate an invitation and let another node join the VPN
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
cat >$d1/invitation-created <<EOF
|
||||||
|
#!/bin/sh
|
||||||
|
echo Name = \$NODE >\$INVITATION_FILE
|
||||||
|
echo Ifconfig = 93.184.216.34/24 >>\$INVITATION_FILE
|
||||||
|
echo Route = 2606:2800:220:1::/64 2606:2800:220:1:248:1893:25c8:1946 >>\$INVITATION_FILE
|
||||||
|
echo Route = 1.2.3.4 1234:: >>\$INVITATION_FILE
|
||||||
|
$tinc $c1 export >>\$INVITATION_FILE
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod u+x $d1/invitation-created
|
||||||
|
|
||||||
|
$tinc $c1 invite bar | $tinc $c2 --batch join
|
||||||
|
|
||||||
|
# Test equivalence of host config files
|
||||||
|
|
||||||
|
cmp $d1/hosts/foo $d2/hosts/foo
|
||||||
|
test "`grep ^Ed25519PublicKey $d1/hosts/bar`" = "`grep ^Ed25519PublicKey $d2/hosts/bar`"
|
||||||
|
|
||||||
|
# Check if the tinc-up.invitation file is created and contains the right commands
|
||||||
|
|
||||||
|
test -f $d2/tinc-up.invitation
|
||||||
|
|
||||||
|
fgrep -q "93.184.216.34/24" $d2/tinc-up.invitation
|
||||||
|
fgrep -q "2606:2800:220:1::/64" $d2/tinc-up.invitation
|
||||||
|
fgrep -q "2606:2800:220:1:248:1893:25c8:1946" $d2/tinc-up.invitation
|
||||||
|
fgrep -q "1234::" $d2/tinc-up.invitation && exit 1
|
||||||
|
|
||||||
|
# Check that no tinc-up is created and that tinc-up.invitation is not executable
|
||||||
|
|
||||||
|
test -x $d2/tinc-up.invitation && exit 1
|
||||||
|
test -f $d2/tinc-up && exit 1
|
||||||
|
|
||||||
|
$tinc $c1 stop
|
Loading…
Add table
Reference in a new issue