Import Debian changes 1.1~pre11-1

tinc (1.1~pre11-1) experimental; urgency=medium

  * New upstream release.
  * Update NEWS.Debian to reflect that tincctl has been renamed to tinc.
    Closes: #729889
  * Warn about incompatibility with previous 1.1preX releases, and that new
    Ed25519 keys should be generated.
  * Add native systemd service files.
  * Automatically convert networks listed in nets.boot to systemd service
    instances on upgrade.
  * Don't restart tinc on upgrade for now.
This commit is contained in:
Guus Sliepen 2015-01-08 14:51:34 +01:00
commit ff4039db4b
138 changed files with 11154 additions and 3157 deletions

22
AUTHORS
View file

@ -1,20 +1,25 @@
Main tinc authors: Main tinc authors:
- Guus Sliepen <guus@tinc-vpn.org> - Guus Sliepen <guus@tinc-vpn.org>
- Ivo Timmermans (inactive) - Ivo Timmermans (inactive)
Significant contributions from: Significant code contributions from:
- Michael Tokarev <mjt@tls.msk.ru>
- Brandon Black <blblack@gmail.com>
- Etienne Dechamps <etienne@edechamps.fr>
- Florian Forster <octo@verplant.org> - Florian Forster <octo@verplant.org>
- Grzegorz Dymarek <gregd72002@googlemail.com> - Grzegorz Dymarek <gregd72002@googlemail.com>
- Max Rijevski <maksuf@gmail.com>
- Scott Lamb <slamb@slamb.org>
- Julien Muchembled <jm@jmuchemb.eu> - Julien Muchembled <jm@jmuchemb.eu>
- Timothy Redaelli <timothy@redaelli.eu>
- Brandon Black <blblack@gmail.com>
- Loïc Grenié <loic.grenie@gmail.com> - Loïc Grenié <loic.grenie@gmail.com>
- Max Rijevski <maksuf@gmail.com>
- Michael Tokarev <mjt@tls.msk.ru>
- Scott Lamb <slamb@slamb.org>
- Sven-Haegar Koch <haegar@sdinet.de>
- Timothy Redaelli <timothy@redaelli.eu>
These files are from other sources: These files are from other sources:
* lib/pidfile.h and lib/pidfile.c are by Martin Schulze, taken from
* lib/pidfile.h and lib/pidfile.c are by Martin Schulze, taken from
the syslog 1.3 sources. the syslog 1.3 sources.
* src/bsd/tunemu.c and tunemu.h are by Friedrich Schöller * src/bsd/tunemu.c and tunemu.h are by Friedrich Schöller
@ -23,5 +28,4 @@ These files are from other sources:
Also some of the macro files in the directory m4, and their Also some of the macro files in the directory m4, and their
accompanying files in lib, were taken from GNU fileutils. accompanying files in lib, were taken from GNU fileutils.
Please see the file THANKS for more information on contributions from Please see the file THANKS for a list of all contributors to tinc.
users.

View file

@ -1,4 +1,4 @@
Copyright (C) 1998-2013 Ivo Timmermans, Guus Sliepen and others. Copyright (C) 1998-2014 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

237
ChangeLog
View file

@ -1,3 +1,240 @@
Version 1.1pre11 December 27 2014
------------------------------------------------------------------------
Etienne Dechamps (68):
Move Solaris if_fd to local scope.
Make device close cleaner.
Cleanly remove the device FD from the event loop before closing it.
Add DeviceStandby option to only enable the device when nodes are reachable.
Make DeviceStandby control network interface link status on Windows.
Fix Windows includes.
Fix errno references when handling socket errors.
Protect against spurious connection events.
Fix connection event error handling.
Use native Windows events for the event loop.
Make the event loop expose a Windows event interface.
Use a Windows event to stop tinc when running as a service.
Remove the TAP-Win32 reader thread.
Add local address information to edges.
Use edge local addresses for local discovery.
Remove broadcast-based local discovery mechanism.
Enable LocalDiscovery by default.
Implement sptps_verify_datagram().
Make broadcast addresses configurable.
Make IPv4 multicast space 224.0.0.0/4 broadcast by default.
Regenerate build date and time every time tinc is built.
Use git description as the tinc version.
Rewrite, fix and improve str2net().
When printing MAC addresses, always use trailing zeroes.
Don't print subnet prefix lengths and weights for one-host subnets.
Canonicalize IPv6 addresses as per RFC 5952 before printing them.
Fix tinc event loop reentrancy from timeout handlers.
Make sure myport is set correctly when running with Port = 0.
Fix event loop io tree inconsistency on Windows.
Fix a typo (FORTIFY_SOURCE).
Handle the "no local address" case in send_sptps_data().
Don't initialize outpkt to an unused value.
Remove redundant connection_t::status.active field.
Only declare the origpriority variable if we support priority.
Remove an unnecessary pointer dereference in execute_script().
Fix callback signature for TAP-Win32 device_handle_read().
Remove unused variable in TAP-Win32 setup_device().
Remove unused device stats variables.
Resolve KEY_EVENT conflict between Windows and ncurses.
Check if devops is valid before closing the device.
Shutdown cleanly when receiving a Windows console shutdown request.
Fix "tinc start" on Windows when the path contains spaces.
Improve subprocess behavior in tinc start command.
Add documentation about using system-assigned ports.
Verify seqno early in sptps_verify_datagram().
Add a non-interactive mode to tinc commands.
Only read from TAP-Win32 if the device is enabled.
Handle TAP-Win32 immediate reads correctly.
Clarify copyright ownership for code authored by Etienne Dechamps.
Remove Google from the list of copyright owners.
Fix undefined HOST_NAME_MAX on Windows.
Don't enable the device if the reachable count is zero.
Fix wrong identifier in SO_NOSIGPIPE call.
Fix default TAP device on Darwin.
Ignore the Interface option if device rename is impossible.
Fix default device path selection on BSD.
Preemptively mirror REQ_PUBKEY messages from nodes with unknown keys.
Fix protocol version check for type 2 MTU probe replies.
Invalidate UDP information on address changes.
Introduce node IDs.
Change vpn_packet_t::seqno from uint32_t to uint8_t[4].
Prepend source node ID information to UDP datagrams.
Add UDP datagram relay support to SPTPS.
Don't send MTU probes to nodes we can't reach directly.
Make sure to discover MTU with relays.
Query the Linux device for its MAC address.
Don't spontaneously start SPTPS with neighbors.
Use plain old PACKET for TCP packets sent directly to a neighbor.
Guus Sliepen (68):
Really fix compiling under Windows.
Add missing attribution for 1.1pre10 to the NEWS file.
Add "network" command to list or switch networks.
Rewind the file before trying to use PEM_read_RSA_PUBKEY().
Handle a disconnecting tincd better.
Fix return value of b64encode().
Use Ed25519 keys.
Properly initialize buffers.
Merge branch '1.1-ed25519' into 1.1
Use the ChaCha-Poly1305 cipher for the SPTPS protocol.
sptps_test: allow using a tun device instead of stdio.
Put brackets around IPv6 addresses in invitation URL, even if there is no port number.
Nexthop calculation should always use the shortest path.
Fix compiler warnings.
Change AutoConnect from int to bool.
Use void pointers to opaque buffers.
Add missing closedir().
Fix a crash when we have a malformed public ECDSA key of another node.
Fix PMTU discovery via datagram SPTPS.
Add sanity checks when generating new RSA keys.
Rename ECDSA to Ed25519.
Implement a PEM-like format for Ed25519 keys.
Allow Cipher and Digest "none".
Fix base64 decoding of Ed25519 keys.
Return non-zero exit code when "tinc get" does not find the requested variable.
Unconditionally return non-zero exit code when "tinc del" does not find the requested variable.
Remove the warnings when IP_DONTFRAGMENT/IPV6-DONTFRAG is not supported.
Merge branch 'winevents-clean' of https://github.com/dechamps/tinc into 1.1
Give getsockopt() a reference to a socklen_t.
Fix compiler warnings.
Fix segmentation fault when dumping subnets.
Fix incorrect format qualifiers.
Reserve legacy active bit in connection_status_t.
Fix a potential file descriptor leak.
Fix unsafe use of strncpy() and sprintf().
Merge branch 'winwarnings' of https://github.com/dechamps/tinc into 1.1
Merge branch 'ctrl' of https://github.com/dechamps/tinc into 1.1
Merge branch 'tincstart' of https://github.com/dechamps/tinc into 1.1
Merge branch 'keysegfault' of https://github.com/dechamps/tinc into 1.1
Revert "Use git description as the tinc version."
Fix compiler warnings.
Check validity of Ed25519 key during an upgrade.
Log an error message with the node's name when receiving bad SPTPS packets.
Better log messages when we already know the peer's key during an upgrade.
Add an explicit hash_delete() function.
Cache node IDs in a hash table for faster lookups.
Avoid memmove() for legacy UDP packets.
Make UDP packet handling more efficient.
Changes that should have been in commit 46fa12e666badb79e480c4b2399787551f8266d0.
Fix segfault when receiving UDP packets with an unknown source address.
Fix reception of SPTPS UDP packets.
Avoid using OpenSSL's random number functions.
Don't pass uninitialized bytes to ioctl().
Don't use myself->name in device_disable(), it's already freed.
Fix memory leaks found by Valgrind.
Use void pointers for opaque data blobs in the SPTPS code.
Add a variable offset to vpn_packet_t, drop sptps_packet_t.
Merge remote-tracking branch 'groxxda/gui-fixes' into 1.1
Allow running tinc without RSA keys.
Update THANKS file.
Check whether res_init() really lives in libresolv.
BSD make doesn't like .PHONY .c files.
We don't depend on ECDH functions from OpenSSL anymore.
Linux doesn't like .PHONY .o files.
Remove AES-GCM support.
Better default paths for log and PID files on Windows.
Add BroadcastSubnet and DeviceStandby options to the manual and completion.
Releasing 1.1pre11.
Sven-Haegar Koch (4):
Fix exit code of "tinc get".
commandline.test: Adding test that fetching non-existing config setting really fails.
Do not disconnect when no ecdsa key is known yet.
Try handling the case when the first side knows the ecdsa key of
William A. Kennington III (3):
utils: Refactor get_name's functionality into util for global access
utils: Refactor check_id out of protocol for global access
tincctl: Use replace_name to properly replace and validate input hostnames
Baptiste Jonglez (2):
Clarify man page regarding the IndirectData option
Fix typos in the manual page
Alexis Hildebrandt (1):
Add support to link against libresolv Mac OS X
Armin Fisslthaler (1):
reload /etc/resolv.conf in SIGALRM handler
Franz Pletz (1):
tinc-gui: Use /usr/bin/env to resolve path to python
Saverio Proto (1):
Fix typo in comment
groxxda (1):
tinc-gui: Don't assign broadcast subnets to any node, fix parsing of Edges, fix diplay of Subnet.weight.
Version 1.1pre10 February 07 2014
------------------------------------------------------------------------
Guus Sliepen (52):
Wrong date for the 1.1pre9 release in the NEWS.
Avoid using BIOs.
Add a benchmark for the SPTPS protocol.
Don't leak memory during the key generation speed test.
Link sptps_speed with -lrt.
Fix segfault when Name = $HOST but $HOST is not set.
Fix typos in the documentation.
Use AES-256-GCM for the SPTPS protocol.
Fix sending empty SPTPS records.
Clean up child processes from proxy type exec.
Make sptps_test less verbose by default.
Fix sending bulk data starting with a newline.
Fix two warnings from Clang's static analyzer.
Remove an unused variable.
Make LocalDiscovery work for SPTPS packets.
Allow "none" for Cipher and Digest again.
Mention in the manual that multiple Address staments are allowed.
If no Port is specified, set myport to actual port of first listening socket.
Update support for Solaris.
Include <limits.h> for PATH_MAX.
Stricter check for raw socket support.
Avoid using a variable named "sun". Solaris doesn't like it.
Use hardcoded value for TUNNEWPPA if net/if_tun.h is missing on Solaris.
Prefer ncurses over curses.
Don't print device statistics when exiting tinc.
Allow running without ECDSA keys If ExperimentalProtocol is not explicitly set.
Give full path to unconfigured tinc-up script.
Don't print an error when no ECDSA key is known for a node using the legacy protocol.
Remove erroneous warning about SPTPS being disabled.
Enable compiler hardening flags by default.
Add our own autoconf check for libgcrypt.
Don't enable -fstack-protector-all.
Fix handling of --with-libgcrypt.
Clarify StrictSubnets.
Update the documentation of the tinc command.
Add index entries for the CLI commands.
Let tinc-gui use correct address family when connecting to tincd via TCP.
Document clearly that tinc depends on curses and readline libraries.
Document that 1.1 uses AES-256 in GCM mode.
Add the ListenAddress option.
Test two tinc daemons using network namespaces.
Add missing newlines when copying variables from tinc.conf to an invitation file.
Don't ask questions if we are not running interactively.
Document Weight and also allow it to be set from tinc.conf.
Use addresses learned from other nodes when making outgoing connections.
Attribution for various contributors.
Handle errors from TAP-Win32/64 adapter in a better way.
Attribution for Dennis Joachimsthaler.
Update copyright notices.
Fix compiling for Windows.
Check whether OpenSSL has support for GCM.
Releasing 1.1pre10.
Dennis Joachimsthaler (2):
Fix tinc-gui on Windows.
Ensure tinc-gui running in 64 bits mode can find tinc's 32 bit registry key.
Florent Clairambault (1):
Adding "conf.d" configuration dir support.
Version 1.1pre9 September 08 2013 Version 1.1pre9 September 08 2013
------------------------------------------------------------------------ ------------------------------------------------------------------------

View file

@ -12,8 +12,8 @@ without warranty of any kind.
Basic Installation Basic Installation
================== ==================
Briefly, the shell commands `./configure; make; make install' should Briefly, the shell command `./configure && make && make install'
configure, build, and install this package. The following should configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for more-detailed instructions are generic; see the `README' file for
instructions specific to this package. Some packages provide this instructions specific to this package. Some packages provide this
`INSTALL' file but do not implement all of the features documented `INSTALL' file but do not implement all of the features documented

View file

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.14 from Makefile.am. # Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc. # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@ -85,9 +85,12 @@ DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \
config.sub depcomp install-sh missing config.sub depcomp install-sh missing
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \ $(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \ $(top_srcdir)/m4/ax_check_link_flag.m4 \
$(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.ac $(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/libgcrypt.m4 \
$(top_srcdir)/m4/lzo.m4 $(top_srcdir)/m4/openssl.m4 \
$(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/zlib.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4) $(ACLOCAL_M4)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
@ -223,9 +226,6 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@ LDFLAGS = @LDFLAGS@
LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
LIBOBJS = @LIBOBJS@ LIBOBJS = @LIBOBJS@
LIBS = @LIBS@ LIBS = @LIBS@
LN_S = @LN_S@ LN_S = @LN_S@
@ -241,7 +241,6 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@ PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@ PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
READLINE_LIBS = @READLINE_LIBS@ READLINE_LIBS = @READLINE_LIBS@
SET_MAKE = @SET_MAKE@ SET_MAKE = @SET_MAKE@
SHELL = @SHELL@ SHELL = @SHELL@
@ -599,9 +598,10 @@ distcheck: dist
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
&& am__cwd=`pwd` \ && am__cwd=`pwd` \
&& $(am__cd) $(distdir)/_build \ && $(am__cd) $(distdir)/_build \
&& ../configure --srcdir=.. --prefix="$$dc_install_base" \ && ../configure \
$(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \
$(DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \
--srcdir=.. --prefix="$$dc_install_base" \
&& $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) check \

78
NEWS
View file

@ -1,3 +1,81 @@
Version 1.1pre11 December 27 2014
* Added a "network" command to list or switch networks.
* 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
at least three meta-connections open.
* The new protocol now uses UDP much more often.
* Tinc "del" and "get" commands now return a non-zero exit code when they
don't find the requested variable.
* Updated documentation.
* Added a "DeviceStandby" option to defer running tinc-up until a working
connection is made, and which on Windows will also change the network
interface link status accordingly.
* Tinc now tells the resolver to reload /etc/resolv.conf when it receives
SIGALRM.
* Improved error messages and event loop handling on Windows.
* LocalDiscovery now uses local address learned from other nodes, and is
enabled by default.
* Added a "BroadcastSubnet" option to change the behavior of broadcast packets
in router mode.
* Added support for dotted quad notation in IPv6 (e.g. ::1.2.3.4).
* Improved format of printed Subnets, MAC and IPv6 addresses.
* Added a "--batch" option to force the tinc CLI to run in non-interactive
mode.
* Improve default Device selection on *BSD and Mac OS X.
* Allow running tinc without RSA keys.
Thanks to Etienne Dechamps, Sven-Haegar Koch, William A. Kennington III,
Baptiste Jonglez, Alexis Hildebrandt, Armin Fisslthaler, Franz Pletz, Alexander
Ried and Saverio Proto for their contributions to this version of tinc.
Version 1.1pre10 February 7 2014
* Added a benchmark tool (sptps_speed) for the new protocol.
* Fixed a crash when using Name = $HOST while $HOST is not set.
* Use AES-256-GCM for the new protocol.
* Updated support for Solaris.
* Allow running tincd without a private ECDSA key present when
ExperimentalProtocol is not explicitly set.
* Enable various compiler hardening flags by default.
* Added support for a "conf.d" configuration directory.
* 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.
* Added a "ListenAddress" option, which like BindToAddress adds more listening
address/ports, but doesn't bind to them for outgoing sockets.
* Make invitations work better when the "invite" and "join" commands are not
run interactively.
* When creating meta-connections to a node for which no Address statement is
specified, try to use addresses learned from other nodes.
Thanks to Dennis Joachimsthaler and Florent Clairambault for their contribution
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.

17
README
View file

@ -1,7 +1,7 @@
This is the README file for tinc version 1.1pre9. Installation This is the README file for tinc version 1.1pre11. Installation
instructions may be found in the INSTALL file. instructions may be found in the INSTALL file.
tinc is Copyright (C) 1998-2013 by: tinc is Copyright (C) 1998-2014 by:
Ivo Timmermans, Ivo Timmermans,
Guus Sliepen <guus@tinc-vpn.org>, Guus Sliepen <guus@tinc-vpn.org>,
@ -36,12 +36,11 @@ at your own risk.
Compatibility Compatibility
------------- -------------
Version 1.1pre9 is compatible with 1.0pre8, 1.0 and later, but not with older Version 1.1pre11 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, which is the default since When the ExperimentalProtocol option is used, tinc is still compatible with
1.1pre8, tinc is still compatible with 1.0.X and 1.1pre9 itself, but not with 1.0.X and 1.1pre11 itself, but not with any other 1.1preX version.
any other 1.1preX version.
Requirements Requirements
@ -51,7 +50,7 @@ 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 - OpenSSL (http://www.openssl.org/) version 1.0.0 or later, with support for
elliptic curve cryptography (ECC) enabeld. 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:
@ -73,8 +72,8 @@ be forwarded by intermediate nodes.
By default, nodes authenticate each other using 2048 bit RSA (or 521 bit By default, nodes authenticate each other using 2048 bit RSA (or 521 bit
ECDSA*) keys. Traffic is encrypted using Blowfish in CBC mode (or AES-256 in ECDSA*) keys. Traffic is encrypted using Blowfish in CBC mode (or AES-256 in
CTR mode*), authenticated using HMAC-SHA1 (or HMAC-SHA-256*), and is protected GCM mode*), authenticated using HMAC-SHA1 (or GCM*), and is protected against
against replay attacks. replay attacks.
*) When using the ExperimentalProtocol option. *) When using the ExperimentalProtocol option.

27
THANKS
View file

@ -1,34 +1,51 @@
We would like to thank the following people for their contributions to tinc: We would like to thank the following people for their contributions to tinc:
* Alexander Reil and Gemeinde Berg * Alexander Reil and Gemeinde Berg
* Alexander Ried
* Alexis Hildebrandt
* Allesandro Gatti * Allesandro Gatti
* Andreas van Cranenburgh * Andreas van Cranenburgh
* Anthony G. Basile * Anthony G. Basile
* Armijn Hemel * Armijn Hemel
* Armin Fisslthaler
* Baptiste Jonglez
* Borg
* Brandon Black * Brandon Black
* Cheng LI * Cheng LI
* Cris van Pelt * Cris van Pelt
* Darius Jahandarie * Darius Jahandarie
* David Pflug
* Delf Eldkraft * Delf Eldkraft
* Dennis Joachimsthaler
* dnk * dnk
* Enrique Zanardi * Enrique Zanardi
* Erik Tews * Erik Tews
* Etienne Dechamps * Etienne Dechamps
* Florent Clairambault
* Flynn Marquardt * Flynn Marquardt
* Franz Pletz
* Gary Kessler and Claudia Gonzalez
* Grzegorz Dymarek * Grzegorz Dymarek
* Hans Bayle * Hans Bayle
* Ivo van Dong * Ivo van Dong
* James Cook
* James MacLean * James MacLean
* Jamie Briggs * Jamie Briggs
* Jason Harper * Jason Harper
* Jason Livesay
* Jelle de Jong
* Jeroen Ubbink * Jeroen Ubbink
* Jerome Etienne * Jerome Etienne
* Jochen Voss
* Julien Muchembled * Julien Muchembled
* Lavrans Laading
* Loïc Dachary
* Loïc Grenié * Loïc Grenié
* Lubomír Bulej * Lubomír Bulej
* Mads Kiilerich * Mads Kiilerich
* Marc A. Lehmann * Marc A. Lehmann
* Mark Glines * Mark Glines
* Mark Petryk
* Markus Goetz * Markus Goetz
* Martin Kihlgren * Martin Kihlgren
* Martin Schobert * Martin Schobert
@ -45,16 +62,24 @@ We would like to thank the following people for their contributions to tinc:
* Philipp Babel * Philipp Babel
* Robert van der Meulen * Robert van der Meulen
* Rumko * Rumko
* Saverio Proto
* Scott Lamb * Scott Lamb
* Steffan Karger
* Sven-Haegar Koch * Sven-Haegar Koch
* Teemu Kiviniemi * Teemu Kiviniemi
* Thomas Tsiakalakis
* Timothy Redaelli * Timothy Redaelli
* Tomislav Čohar
* Tommy Arnkværn
* Tonnerre Lombard * Tonnerre Lombard
* Vil Brekin * Vil Brekin
* Vittorio Gambaletta
* Wessel Dankers * Wessel Dankers
* William A. Kennington III
* William McArthur
* Wouter van Heyst * Wouter van Heyst
And everyone we forgot. Thank you! And everyone we forgot (if we did, please let us know). Thank you!
Ivo Timmermans Ivo Timmermans
Guus Sliepen Guus Sliepen

143
aclocal.m4 vendored
View file

@ -1,4 +1,4 @@
# generated automatically by aclocal 1.14 -*- Autoconf -*- # generated automatically by aclocal 1.14.1 -*- Autoconf -*-
# Copyright (C) 1996-2013 Free Software Foundation, Inc. # Copyright (C) 1996-2013 Free Software Foundation, Inc.
@ -20,130 +20,6 @@ You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely. If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically 'autoreconf'.])]) To do so, use the procedure documented by the package, typically 'autoreconf'.])])
dnl Autoconf macros for libgcrypt
dnl Copyright (C) 2002, 2004 Free Software Foundation, Inc.
dnl
dnl This file is free software; as a special exception the author gives
dnl unlimited permission to copy and/or distribute it, with or without
dnl modifications, as long as this notice is preserved.
dnl
dnl This file is distributed in the hope that it will be useful, but
dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION,
dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
dnl Test for libgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS.
dnl MINIMUN-VERSION is a string with the version number optionalliy prefixed
dnl with the API version to also check the API compatibility. Example:
dnl a MINIMUN-VERSION of 1:1.2.5 won't pass the test unless the installed
dnl version of libgcrypt is at least 1.2.5 *and* the API number is 1. Using
dnl this features allows to prevent build against newer versions of libgcrypt
dnl with a changed API.
dnl
AC_DEFUN([AM_PATH_LIBGCRYPT],
[ AC_ARG_WITH(libgcrypt-prefix,
AC_HELP_STRING([--with-libgcrypt-prefix=PFX],
[prefix where LIBGCRYPT is installed (optional)]),
libgcrypt_config_prefix="$withval", libgcrypt_config_prefix="")
if test x$libgcrypt_config_prefix != x ; then
if test x${LIBGCRYPT_CONFIG+set} != xset ; then
LIBGCRYPT_CONFIG=$libgcrypt_config_prefix/bin/libgcrypt-config
fi
fi
AC_PATH_TOOL(LIBGCRYPT_CONFIG, libgcrypt-config, no)
tmp=ifelse([$1], ,1:1.2.0,$1)
if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then
req_libgcrypt_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'`
min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'`
else
req_libgcrypt_api=0
min_libgcrypt_version="$tmp"
fi
AC_MSG_CHECKING(for LIBGCRYPT - version >= $min_libgcrypt_version)
ok=no
if test "$LIBGCRYPT_CONFIG" != "no" ; then
req_major=`echo $min_libgcrypt_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'`
req_minor=`echo $min_libgcrypt_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
req_micro=`echo $min_libgcrypt_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version`
major=`echo $libgcrypt_config_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
minor=`echo $libgcrypt_config_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'`
micro=`echo $libgcrypt_config_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'`
if test "$major" -gt "$req_major"; then
ok=yes
else
if test "$major" -eq "$req_major"; then
if test "$minor" -gt "$req_minor"; then
ok=yes
else
if test "$minor" -eq "$req_minor"; then
if test "$micro" -ge "$req_micro"; then
ok=yes
fi
fi
fi
fi
fi
fi
if test $ok = yes; then
AC_MSG_RESULT([yes ($libgcrypt_config_version)])
else
AC_MSG_RESULT(no)
fi
if test $ok = yes; then
# If we have a recent libgcrypt, we should also check that the
# API is compatible
if test "$req_libgcrypt_api" -gt 0 ; then
tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0`
if test "$tmp" -gt 0 ; then
AC_MSG_CHECKING([LIBGCRYPT API version])
if test "$req_libgcrypt_api" -eq "$tmp" ; then
AC_MSG_RESULT([okay])
else
ok=no
AC_MSG_RESULT([does not match. want=$req_libgcrypt_api got=$tmp])
fi
fi
fi
fi
if test $ok = yes; then
LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags`
LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs`
ifelse([$2], , :, [$2])
if test x"$host" != x ; then
libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none`
if test x"$libgcrypt_config_host" != xnone ; then
if test x"$libgcrypt_config_host" != x"$host" ; then
AC_MSG_WARN([[
***
*** The config script $LIBGCRYPT_CONFIG was
*** built for $libgcrypt_config_host and thus may not match the
*** used host $host.
*** You may want to use the configure option --with-libgcrypt-prefix
*** to specify a matching config script.
***]])
fi
fi
fi
else
LIBGCRYPT_CFLAGS=""
LIBGCRYPT_LIBS=""
ifelse([$3], , :, [$3])
fi
AC_SUBST(LIBGCRYPT_CFLAGS)
AC_SUBST(LIBGCRYPT_LIBS)
])
# Copyright (C) 2002-2013 Free Software Foundation, Inc. # Copyright (C) 2002-2013 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
@ -159,7 +35,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.14' [am__api_version='1.14'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro. dnl require some minimum version. Point them to the right macro.
m4_if([$1], [1.14], [], m4_if([$1], [1.14.1], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
]) ])
@ -175,7 +51,7 @@ m4_define([_AM_AUTOCONF_VERSION], [])
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.14])dnl [AM_AUTOMAKE_VERSION([1.14.1])dnl
m4_ifndef([AC_AUTOCONF_VERSION], m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
@ -227,10 +103,9 @@ _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# configured tree to be moved without reconfiguration. # configured tree to be moved without reconfiguration.
AC_DEFUN([AM_AUX_DIR_EXPAND], AC_DEFUN([AM_AUX_DIR_EXPAND],
[dnl Rely on autoconf to set up CDPATH properly. [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
AC_PREREQ([2.50])dnl # Expand $ac_aux_dir to an absolute path.
# expand $ac_aux_dir to an absolute path am_aux_dir=`cd "$ac_aux_dir" && pwd`
am_aux_dir=`cd $ac_aux_dir && pwd`
]) ])
# AM_CONDITIONAL -*- Autoconf -*- # AM_CONDITIONAL -*- Autoconf -*-
@ -697,7 +572,8 @@ to "yes", and re-run configure.
END END
AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
fi fi
fi]) fi
])
dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
@ -1272,7 +1148,10 @@ AC_SUBST([am__untar])
]) # _AM_PROG_TAR ]) # _AM_PROG_TAR
m4_include([m4/attribute.m4]) m4_include([m4/attribute.m4])
m4_include([m4/ax_check_compile_flag.m4])
m4_include([m4/ax_check_link_flag.m4])
m4_include([m4/curses.m4]) m4_include([m4/curses.m4])
m4_include([m4/libgcrypt.m4])
m4_include([m4/lzo.m4]) m4_include([m4/lzo.m4])
m4_include([m4/openssl.m4]) m4_include([m4/openssl.m4])
m4_include([m4/readline.m4]) m4_include([m4/readline.m4])

174
config.guess vendored
View file

@ -1,8 +1,8 @@
#! /bin/sh #! /bin/sh
# Attempt to guess a canonical system name. # Attempt to guess a canonical system name.
# Copyright 1992-2013 Free Software Foundation, Inc. # Copyright 1992-2014 Free Software Foundation, Inc.
timestamp='2013-06-10' timestamp='2014-03-23'
# This file is free software; you can redistribute it and/or modify it # This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by # under the terms of the GNU General Public License as published by
@ -50,7 +50,7 @@ version="\
GNU config.guess ($timestamp) GNU config.guess ($timestamp)
Originally written by Per Bothner. Originally written by Per Bothner.
Copyright 1992-2013 Free Software Foundation, Inc. Copyright 1992-2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@ -149,7 +149,7 @@ Linux|GNU|GNU/*)
LIBC=gnu LIBC=gnu
#endif #endif
EOF EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
;; ;;
esac esac
@ -826,7 +826,7 @@ EOF
*:MINGW*:*) *:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32 echo ${UNAME_MACHINE}-pc-mingw32
exit ;; exit ;;
i*:MSYS*:*) *:MSYS*:*)
echo ${UNAME_MACHINE}-pc-msys echo ${UNAME_MACHINE}-pc-msys
exit ;; exit ;;
i*:windows32*:*) i*:windows32*:*)
@ -969,10 +969,10 @@ EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
;; ;;
or1k:Linux:*:*) openrisc*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC} echo or1k-unknown-linux-${LIBC}
exit ;; exit ;;
or32:Linux:*:*) or32:Linux:*:* | or1k*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC} echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;; exit ;;
padre:Linux:*:*) padre:Linux:*:*)
@ -1260,6 +1260,7 @@ EOF
if test "$UNAME_PROCESSOR" = unknown ; then if test "$UNAME_PROCESSOR" = unknown ; then
UNAME_PROCESSOR=powerpc UNAME_PROCESSOR=powerpc
fi fi
if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
@ -1271,6 +1272,15 @@ EOF
esac esac
fi fi
fi fi
elif test "$UNAME_PROCESSOR" = i386 ; then
# Avoid executing cc on OS X 10.9, as it ships with a stub
# that puts up a graphical alert prompting to install
# developer tools. Any system running Mac OS X 10.7 or
# later (Darwin 11 and later) is required to have a 64-bit
# processor. This is not true of the ARM version of Darwin
# that Apple uses in portable devices.
UNAME_PROCESSOR=x86_64
fi
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
exit ;; exit ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*) *:procnto*:*:* | *:QNX:[0123456789]*:*)
@ -1361,154 +1371,6 @@ EOF
exit ;; exit ;;
esac esac
eval $set_cc_for_build
cat >$dummy.c <<EOF
#ifdef _SEQUENT_
# include <sys/types.h>
# include <sys/utsname.h>
#endif
main ()
{
#if defined (sony)
#if defined (MIPSEB)
/* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
I don't know.... */
printf ("mips-sony-bsd\n"); exit (0);
#else
#include <sys/param.h>
printf ("m68k-sony-newsos%s\n",
#ifdef NEWSOS4
"4"
#else
""
#endif
); exit (0);
#endif
#endif
#if defined (__arm) && defined (__acorn) && defined (__unix)
printf ("arm-acorn-riscix\n"); exit (0);
#endif
#if defined (hp300) && !defined (hpux)
printf ("m68k-hp-bsd\n"); exit (0);
#endif
#if defined (NeXT)
#if !defined (__ARCHITECTURE__)
#define __ARCHITECTURE__ "m68k"
#endif
int version;
version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
if (version < 4)
printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
else
printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
exit (0);
#endif
#if defined (MULTIMAX) || defined (n16)
#if defined (UMAXV)
printf ("ns32k-encore-sysv\n"); exit (0);
#else
#if defined (CMU)
printf ("ns32k-encore-mach\n"); exit (0);
#else
printf ("ns32k-encore-bsd\n"); exit (0);
#endif
#endif
#endif
#if defined (__386BSD__)
printf ("i386-pc-bsd\n"); exit (0);
#endif
#if defined (sequent)
#if defined (i386)
printf ("i386-sequent-dynix\n"); exit (0);
#endif
#if defined (ns32000)
printf ("ns32k-sequent-dynix\n"); exit (0);
#endif
#endif
#if defined (_SEQUENT_)
struct utsname un;
uname(&un);
if (strncmp(un.version, "V2", 2) == 0) {
printf ("i386-sequent-ptx2\n"); exit (0);
}
if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
printf ("i386-sequent-ptx1\n"); exit (0);
}
printf ("i386-sequent-ptx\n"); exit (0);
#endif
#if defined (vax)
# if !defined (ultrix)
# include <sys/param.h>
# if defined (BSD)
# if BSD == 43
printf ("vax-dec-bsd4.3\n"); exit (0);
# else
# if BSD == 199006
printf ("vax-dec-bsd4.3reno\n"); exit (0);
# else
printf ("vax-dec-bsd\n"); exit (0);
# endif
# endif
# else
printf ("vax-dec-bsd\n"); exit (0);
# endif
# else
printf ("vax-dec-ultrix\n"); exit (0);
# endif
#endif
#if defined (alliant) && defined (i860)
printf ("i860-alliant-bsd\n"); exit (0);
#endif
exit (1);
}
EOF
$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
{ echo "$SYSTEM_NAME"; exit; }
# Apollos put the system type in the environment.
test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
# Convex versions that predate uname can use getsysinfo(1)
if [ -x /usr/convex/getsysinfo ]
then
case `getsysinfo -f cpu_type` in
c1*)
echo c1-convex-bsd
exit ;;
c2*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit ;;
c34*)
echo c34-convex-bsd
exit ;;
c38*)
echo c38-convex-bsd
exit ;;
c4*)
echo c4-convex-bsd
exit ;;
esac
fi
cat >&2 <<EOF cat >&2 <<EOF
$0: unable to guess system type $0: unable to guess system type

View file

@ -52,18 +52,20 @@
don't. */ don't. */
#undef HAVE_DECL_GETNAMEINFO #undef HAVE_DECL_GETNAMEINFO
/* Define to 1 if you have the declaration of `OpenSSL_add_all_algorithms',
and to 0 if you don't. */
#undef HAVE_DECL_OPENSSL_ADD_ALL_ALGORITHMS
/* Define to 1 if you have the declaration of `res_init', and to 0 if you
don't. */
#undef HAVE_DECL_RES_INIT
/* Define to 1 if you have the <dirent.h> header file. */ /* Define to 1 if you have the <dirent.h> header file. */
#undef HAVE_DIRENT_H #undef HAVE_DIRENT_H
/* DragonFly */ /* DragonFly */
#undef HAVE_DRAGONFLY #undef HAVE_DRAGONFLY
/* Define to 1 if you have the `ECDH_compute_key' function. */
#undef HAVE_ECDH_COMPUTE_KEY
/* Define to 1 if you have the `ECDSA_verify' function. */
#undef HAVE_ECDSA_VERIFY
/* Define to 1 if you have the `EVP_EncryptInit_ex' function. */ /* Define to 1 if you have the `EVP_EncryptInit_ex' function. */
#undef HAVE_EVP_ENCRYPTINIT_EX #undef HAVE_EVP_ENCRYPTINIT_EX
@ -82,6 +84,9 @@
/* Define to 1 if you have the `ftime' function. */ /* Define to 1 if you have the `ftime' function. */
#undef HAVE_FTIME #undef HAVE_FTIME
/* Define to 1 if you have the <gcrypt.h> header file. */
#undef HAVE_GCRYPT_H
/* Define to 1 if you have the `gettimeofday' function. */ /* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY #undef HAVE_GETTIMEOFDAY
@ -94,6 +99,9 @@
/* Define to 1 if you have the `nsl' library (-lnsl). */ /* Define to 1 if you have the `nsl' library (-lnsl). */
#undef HAVE_LIBNSL #undef HAVE_LIBNSL
/* Define to 1 if you have the `resolv' library (-lresolv). */
#undef HAVE_LIBRESOLV
/* Define to 1 if you have the `socket' library (-lsocket). */ /* Define to 1 if you have the `socket' library (-lsocket). */
#undef HAVE_LIBSOCKET #undef HAVE_LIBSOCKET
@ -190,12 +198,6 @@
/* OpenBSD */ /* OpenBSD */
#undef HAVE_OPENBSD #undef HAVE_OPENBSD
/* Define to 1 if you have the <openssl/ecdh.h> header file. */
#undef HAVE_OPENSSL_ECDH_H
/* Define to 1 if you have the <openssl/ec.h> header file. */
#undef HAVE_OPENSSL_EC_H
/* Define to 1 if you have the <openssl/engine.h> header file. */ /* Define to 1 if you have the <openssl/engine.h> header file. */
#undef HAVE_OPENSSL_ENGINE_H #undef HAVE_OPENSSL_ENGINE_H
@ -223,8 +225,8 @@
/* Define to 1 if you have the `random' function. */ /* Define to 1 if you have the `random' function. */
#undef HAVE_RANDOM #undef HAVE_RANDOM
/* Define to 1 if you have the `RAND_pseudo_bytes' function. */ /* Define to 1 if you have the `RAND_status' function. */
#undef HAVE_RAND_PSEUDO_BYTES #undef HAVE_RAND_STATUS
/* have readline support */ /* have readline support */
#undef HAVE_READLINE #undef HAVE_READLINE
@ -235,6 +237,9 @@
/* Define to 1 if you have the <readline/readline.h> header file. */ /* Define to 1 if you have the <readline/readline.h> header file. */
#undef HAVE_READLINE_READLINE_H #undef HAVE_READLINE_READLINE_H
/* Define to 1 if you have the <resolv.h> header file. */
#undef HAVE_RESOLV_H
/* Define to 1 if you have the `select' function. */ /* Define to 1 if you have the `select' function. */
#undef HAVE_SELECT #undef HAVE_SELECT

30
config.sub vendored
View file

@ -1,8 +1,8 @@
#! /bin/sh #! /bin/sh
# Configuration validation subroutine script. # Configuration validation subroutine script.
# Copyright 1992-2013 Free Software Foundation, Inc. # Copyright 1992-2014 Free Software Foundation, Inc.
timestamp='2013-08-10' timestamp='2014-09-11'
# This file is free software; you can redistribute it and/or modify it # This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by # under the terms of the GNU General Public License as published by
@ -68,7 +68,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\ version="\
GNU config.sub ($timestamp) GNU config.sub ($timestamp)
Copyright 1992-2013 Free Software Foundation, Inc. Copyright 1992-2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@ -265,6 +265,7 @@ case $basic_machine in
| hexagon \ | hexagon \
| i370 | i860 | i960 | ia64 \ | i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \ | ip2k | iq2000 \
| k1om \
| le32 | le64 \ | le32 | le64 \
| lm32 \ | lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \ | m32c | m32r | m32rle | m68000 | m68k | m88k \
@ -282,8 +283,10 @@ case $basic_machine in
| mips64vr5900 | mips64vr5900el \ | mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \ | mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \ | mipsisa32r2 | mipsisa32r2el \
| mipsisa32r6 | mipsisa32r6el \
| mipsisa64 | mipsisa64el \ | mipsisa64 | mipsisa64el \
| mipsisa64r2 | mipsisa64r2el \ | mipsisa64r2 | mipsisa64r2el \
| mipsisa64r6 | mipsisa64r6el \
| mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \ | mipsisa64sr71k | mipsisa64sr71kel \
| mipsr5900 | mipsr5900el \ | mipsr5900 | mipsr5900el \
@ -295,11 +298,11 @@ case $basic_machine in
| nds32 | nds32le | nds32be \ | nds32 | nds32le | nds32be \
| nios | nios2 | nios2eb | nios2el \ | nios | nios2 | nios2eb | nios2el \
| ns16k | ns32k \ | ns16k | ns32k \
| open8 \ | open8 | or1k | or1knd | or32 \
| or1k | or32 \
| pdp10 | pdp11 | pj | pjl \ | pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle \ | powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \ | pyramid \
| riscv32 | riscv64 \
| rl78 | rx \ | rl78 | rx \
| score \ | score \
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
@ -324,7 +327,7 @@ case $basic_machine in
c6x) c6x)
basic_machine=tic6x-unknown basic_machine=tic6x-unknown
;; ;;
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
basic_machine=$basic_machine-unknown basic_machine=$basic_machine-unknown
os=-none os=-none
;; ;;
@ -381,6 +384,7 @@ case $basic_machine in
| hexagon-* \ | hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \ | i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \ | ip2k-* | iq2000-* \
| k1om-* \
| le32-* | le64-* \ | le32-* | le64-* \
| lm32-* \ | lm32-* \
| m32c-* | m32r-* | m32rle-* \ | m32c-* | m32r-* | m32rle-* \
@ -400,8 +404,10 @@ case $basic_machine in
| mips64vr5900-* | mips64vr5900el-* \ | mips64vr5900-* | mips64vr5900el-* \
| mipsisa32-* | mipsisa32el-* \ | mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa32r2-* | mipsisa32r2el-* \
| mipsisa32r6-* | mipsisa32r6el-* \
| mipsisa64-* | mipsisa64el-* \ | mipsisa64-* | mipsisa64el-* \
| mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64r2-* | mipsisa64r2el-* \
| mipsisa64r6-* | mipsisa64r6el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipsr5900-* | mipsr5900el-* \ | mipsr5900-* | mipsr5900el-* \
@ -413,6 +419,7 @@ case $basic_machine in
| nios-* | nios2-* | nios2eb-* | nios2el-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \
| none-* | np1-* | ns16k-* | ns32k-* \ | none-* | np1-* | ns16k-* | ns32k-* \
| open8-* \ | open8-* \
| or1k*-* \
| orion-* \ | orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
@ -822,6 +829,10 @@ case $basic_machine in
basic_machine=powerpc-unknown basic_machine=powerpc-unknown
os=-morphos os=-morphos
;; ;;
moxiebox)
basic_machine=moxie-unknown
os=-moxiebox
;;
msdos) msdos)
basic_machine=i386-pc basic_machine=i386-pc
os=-msdos os=-msdos
@ -1367,14 +1378,14 @@ case $os in
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
| -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
# Remember, each alternative MUST END IN *, to match a version number. # Remember, each alternative MUST END IN *, to match a version number.
;; ;;
-qnx*) -qnx*)
@ -1592,9 +1603,6 @@ case $basic_machine in
mips*-*) mips*-*)
os=-elf os=-elf
;; ;;
or1k-*)
os=-elf
;;
or32-*) or32-*)
os=-coff os=-coff
;; ;;

1024
configure vendored

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
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_INIT([tinc], [1.1pre9]) AC_INIT([tinc], [1.1pre11])
AC_CONFIG_SRCDIR([src/tincd.c]) AC_CONFIG_SRCDIR([src/tincd.c])
AC_GNU_SOURCE AC_GNU_SOURCE
AM_INIT_AUTOMAKE([check-news std-options subdir-objects -Wall]) AM_INIT_AUTOMAKE([check-news std-options subdir-objects -Wall])
@ -18,7 +18,6 @@ AC_PROG_CC_C99
AC_PROG_CPP AC_PROG_CPP
AC_PROG_INSTALL AC_PROG_INSTALL
AC_PROG_LN_S AC_PROG_LN_S
AC_PROG_RANLIB
AM_PROG_CC_C_O AM_PROG_CC_C_O
@ -109,7 +108,7 @@ AC_ARG_ENABLE(tunemu,
) )
AC_ARG_WITH(windows2000, AC_ARG_WITH(windows2000,
AS_HELP_STRING([--without-windows2000], [compile with support for Windows 2000. This disables support for tunneling over existing IPv6 networks.]), 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"], [ AS_IF([test "x$with_windows2000" = "xyes"],
[AC_DEFINE(WITH_WINDOWS2000, 1, [Compile with support for Windows 2000])]) [AC_DEFINE(WITH_WINDOWS2000, 1, [Compile with support for Windows 2000])])
] ]
@ -133,6 +132,29 @@ if test -d /sw/lib ; then
LIBS="$LIBS -L/sw/lib" LIBS="$LIBS -L/sw/lib"
fi fi
dnl Compiler hardening flags
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]))
AS_IF([test "x$enable_hardening" != "xno"],
[AX_CHECK_COMPILE_FLAG([-DFORTIFY_SOURCE=2], [CPPFLAGS="$CPPFLAGS -DFORTIFY_SOURCE=2"])
AX_CHECK_COMPILE_FLAG([-fno-strict-overflow], [CPPFLAGS="$CPPFLAGS -fno-strict-overflow"])
AX_CHECK_COMPILE_FLAG([-fwrapv], [CPPFLAGS="$CPPFLAGS -fwrapv"])
case $host_os in
*mingw*)
AX_CHECK_LINK_FLAG([-Wl,--dynamicbase], [LDFLAGS="$LDFLAGS -Wl,--dynamicbase"])
AX_CHECK_LINK_FLAG([-Wl,--nxcompat], [LDFLAGS="$LDFLAGS -Wl,--nxcompat"])
;;
*)
AX_CHECK_COMPILE_FLAG([-fPIE], [CPPFLAGS="$CPPFLAGS -fPIE"])
AX_CHECK_LINK_FLAG([-pie], [LDFLAGS="$LDFLAGS -pie"])
;;
esac
AX_CHECK_LINK_FLAG([-Wl,-z,relro], [LDFLAGS="$LDFLAGS -Wl,-z,relro"])
AX_CHECK_LINK_FLAG([-Wl,-z,now], [LDFLAGS="$LDFLAGS -Wl,-z,now"])
]
);
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.
@ -141,7 +163,7 @@ AC_CHECK_HEADERS([stdbool.h syslog.h sys/file.h sys/ioctl.h sys/mman.h sys/param
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], 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 "src/have.h"] [], [], [#include "src/have.h"]
) )
AC_CHECK_HEADERS([netinet/if_ether.h netinet/ip.h netinet/ip6.h], AC_CHECK_HEADERS([netinet/if_ether.h netinet/ip.h netinet/ip6.h resolv.h],
[], [], [#include "src/have.h"] [], [], [#include "src/have.h"]
) )
AC_CHECK_HEADERS([netinet/tcp.h netinet/ip_icmp.h netinet/icmp6.h], AC_CHECK_HEADERS([netinet/tcp.h netinet/ip_icmp.h netinet/icmp6.h],
@ -182,6 +204,11 @@ AC_CHECK_DECLS([freeaddrinfo, gai_strerror, getaddrinfo, getnameinfo],
[], [], [#include "src/have.h"] [], [], [#include "src/have.h"]
) )
AC_CHECK_DECLS([res_init], [AC_CHECK_LIB(resolv, res_init)], [], [
#include <netinet/in.h>
#include <resolv.h>
])
AC_CACHE_SAVE AC_CACHE_SAVE
dnl These are defined in files in m4/ dnl These are defined in files in m4/
@ -193,20 +220,20 @@ tinc_READLINE
tinc_ZLIB tinc_ZLIB
tinc_LZO tinc_LZO
if test "$with_libgcrypt" = yes; then if test -n "$with_libgcrypt"; then
gcrypt=true gcrypt=true
AM_PATH_LIBGCRYPT([1.4.0], [], []) tinc_LIBGCRYPT
else else
openssl=true openssl=true
tinc_OPENSSL tinc_OPENSSL
fi fi
AM_CONDITIONAL(OPENSSL, test -n "$openssl") AM_CONDITIONAL(OPENSSL, test -n "$openssl")
AM_CONDITIONAL(GCRYPT, test "$gcrypt" = true) AM_CONDITIONAL(GCRYPT, test -n "$gcrypt")
dnl Check if support for jumbograms is requested dnl Check if support for jumbograms is requested
AC_ARG_ENABLE(jumbograms, AC_ARG_ENABLE(jumbograms,
AS_HELP_STRING([--disable-jumbograms], [enable support for jumbograms (packets up to 9000 bytes)]), AS_HELP_STRING([--enable-jumbograms], [enable support for jumbograms (packets up to 9000 bytes)]),
[ AS_IF([test "x$enable_jumbograms" = "xyes"], [ AS_IF([test "x$enable_jumbograms" = "xyes"],
[ AC_DEFINE(ENABLE_JUMBOGRAMS, 1, [Support for jumbograms (packets up to 9000 bytes)]) ]) [ AC_DEFINE(ENABLE_JUMBOGRAMS, 1, [Support for jumbograms (packets up to 9000 bytes)]) ])
] ]

46
debian/NEWS vendored
View file

@ -1,11 +1,43 @@
tinc (1.1~pre11-1) experimental; urgency=medium
This package now provides a native systemd service file, allowing multiple
instances of tinc to be managed. Existing networks listed in
/etc/tinc/nets.boot will be converted to service instances once during this
upgrade. Afterwards, you can enable and disable networks using:
systemctl enable tinc@<netname>
systemctl disable tinc@<netname>
If you do not have systemd installed, the SysV init script will continue to
work as usual. For more information, see README.Debian.
Please note that tinc 1.1pre11 is backwards compatible with tinc 1.0.x, but
is not backwards compatible with 1.1pre1 to 1.1pre10 nodes if
ExperimentalProtocol is enabled, which is the default.
If you have more than one node running an 1.1 prerelease version in your VPN,
make sure you upgrade them all at the same time, or disable the new protocol
by adding the following line to tinc.conf:
ExperimentalProtocol = no
If you do want to use the new protocol, be aware that this version of tinc
switched to Ed25519 keys. You can generate a new Ed25519 keypair by running
the following command:
tinc -n <netname> generate-ed25519-keys
You have to manually restart tinc after this upgrade.
-- Guus Sliepen <guus@debian.org> Sat, 08 Jan 2015 14:02:27 +0100
tinc (1.1~pre2-1) experimental; urgency=low tinc (1.1~pre2-1) experimental; urgency=low
tinc-1.1 has separate control utility, tincctl, which is now used tinc-1.1 has separate control utility, tinc (without the d), which is now
to start/stop tinc instances, to reload configuration, to get used to start/stop tinc instances, to reload configuration, to get various
various information about running tincd (including dump of nodes information about running tincd (including dump of nodes and connections)
and connections) and so on. tincd still reacts to some signals and so on. tincd still reacts to some signals as before, but this usage is
as before, but this usage is deprecated. In particular, -k deprecated. In particular, -k option is now gone. Also, node/connection/etc
option is now gone. Also, node/connection/etc dumps are dumps are produced on tincctl stdout, not into syslog.
produced on tincctl stdout, not into syslog.
-- Michael Tokarev <mjt@tls.msk.ru> Sun, 07 Aug 2011 13:16:17 +0400 -- Michael Tokarev <mjt@tls.msk.ru> Sun, 07 Aug 2011 13:16:17 +0400

55
debian/README.Debian vendored
View file

@ -1,17 +1,54 @@
tinc for Debian tinc for Debian
---------------------- ---------------
The manual for tinc is also available as info pages, type `info tinc' The manual for tinc is also available as info pages, type `info tinc'
to read it. to read it.
The system startup script for tinc, /etc/init.d/tinc, uses the file There are several ways in which tinc may be automatically started at boot:
/etc/tinc/nets.boot to find out which networks have to be started.
Alternatively, you can create a stanza in /etc/network/interfaces, and add a Systemd
line with "tinc-net <netname>". This will cause a tincd to be started which -------
uses the configuration from /etc/tinc/<netname>. You can use an inet static
(with address and netmask options) or inet dhcp stanza, in which case the ifup Since 1.1~pre11-1, the tinc package comes with native systemd service files.
will configure the VPN interface and you do not need to have a tinc-up script. To enable and start a net, call:
systemctl enable tinc@<netname>
systemctl start tinc@<netname>
This will cause a tincd to be started which uses the configuration from
/etc/tinc/<netname>, and also makes sure that it will be started next time your
system boots.
Apart from controlling individual instances, you can also start/stop/reload all
enabled instances simultaneously by omitting @<netname>, for example:
systemctl reload tinc
Note that when you have systemd installed on your system, the file
/etc/tinc/nets.boot will not be used anymore to automatically start tinc
daemons. If the variable EXTRA is defined in /etc/default/tinc, it will be
passed on to tinc. The variable LIMITS is however not used.
The service files that come with this package start tinc unconditionally.
However, tinc does support socket activation. If you wish to write a socket
unit for tinc, use the ListenStream option to specify on which port(s) and
address(es) tinc should listen.
SysVinit
--------
The system startup script for tinc, /etc/init.d/tinc, uses the file
/etc/tinc/nets.boot to find out which networks have to be started. Use one
netname per line. Lines starting with a # are ignored.
/etc/network/interfaces
-----------------------
You can create a stanza in /etc/network/interfaces, and add a line with
"tinc-net <netname>". This will cause a tincd to be started which uses the
configuration from /etc/tinc/<netname>. You can use an inet static (with
address and netmask options) or inet dhcp stanza, in which case the ifup will
configure the VPN interface and you do not need to have a tinc-up script.
The following options are also recognized and map directly to the corresponding The following options are also recognized and map directly to the corresponding
command line options for tincd: command line options for tincd:
@ -38,4 +75,4 @@ This will start a tinc daemon that reads its configuration from
nobody, and creates a network interface called "vpn". Ifup then sets the nobody, and creates a network interface called "vpn". Ifup then sets the
address and netmask on that interface. address and netmask on that interface.
-- Guus Sliepen <guus@debian.org>, Fri, 24 June 2011, 18:10:53 +0200 -- Guus Sliepen <guus@debian.org>, Thu, 8 January 2015, 13:37:46 +0100

14
debian/changelog vendored
View file

@ -1,3 +1,17 @@
tinc (1.1~pre11-1) experimental; urgency=medium
* New upstream release.
* Update NEWS.Debian to reflect that tincctl has been renamed to tinc.
Closes: #729889
* Warn about incompatibility with previous 1.1preX releases, and that new
Ed25519 keys should be generated.
* Add native systemd service files.
* Automatically convert networks listed in nets.boot to systemd service
instances on upgrade.
* Don't restart tinc on upgrade for now.
-- Guus Sliepen <guus@debian.org> Thu, 08 Jan 2015 14:51:34 +0100
tinc (1.1~pre9-1) experimental; urgency=low tinc (1.1~pre9-1) experimental; urgency=low
* New upstream release. * New upstream release.

2
debian/control vendored
View file

@ -2,7 +2,7 @@ Source: tinc
Section: net Section: net
Priority: optional Priority: optional
Maintainer: Guus Sliepen <guus@debian.org> Maintainer: Guus Sliepen <guus@debian.org>
Standards-Version: 3.9.4 Standards-Version: 3.9.6
Build-Depends: libssl-dev (>>1.0.0), debhelper (>= 9), texinfo, zlib1g-dev, liblzo2-dev, libncurses5-dev, libreadline-dev, libvdeplug-dev Build-Depends: libssl-dev (>>1.0.0), debhelper (>= 9), texinfo, zlib1g-dev, liblzo2-dev, libncurses5-dev, libreadline-dev, libvdeplug-dev
Homepage: http://www.tinc-vpn.org/ Homepage: http://www.tinc-vpn.org/

7
debian/postinst vendored
View file

@ -6,13 +6,6 @@ set -e
case "$1" in case "$1" in
configure) configure)
if [ ! -e /dev/.devfsd ] ; then if [ ! -e /dev/.devfs ] ; then
if [ ! -e /dev/net/tun ] ; then if [ ! -e /dev/tun ] ; then
echo "Creating tun device..."
cd /dev && ./MAKEDEV net/tun 2>/dev/null || ./MAKEDEV tun 2>/dev/null || echo "Failed to create tun device."
fi; fi
fi; fi
if [ ! -e $NETSFILE ] ; then if [ ! -e $NETSFILE ] ; then
echo "## This file contains all names of the networks to be started on system startup." > $NETSFILE echo "## This file contains all names of the networks to be started on system startup." > $NETSFILE
fi fi

28
debian/preinst vendored Normal file
View file

@ -0,0 +1,28 @@
#!/bin/sh
NETSFILE="/etc/tinc/nets.boot"
SYSTEM="/lib/systemd/system"
WANTS="/etc/systemd/system/multi-user.target.wants"
set -e
case "$1" in
upgrade)
if dpkg --compare-versions "$2" '<' "1.1~pre11-1"; then
if [ -f "$NETSFILE" ]; then
echo -n "Creating systemd service instances from nets.boot:"
mkdir -p "$WANTS"
egrep '^[ ]*[a-zA-Z0-9_-]+' $NETSFILE | while read net args; do
echo -n " $net"
ln -s "$SYSTEM/tinc@.service" "$WANTS/tinc@$net.service" 2>/dev/null || true
done
echo "."
fi
fi
;;
*)
;;
esac
#DEBHELPER#

2
debian/rules vendored
View file

@ -28,4 +28,4 @@ override_dh_auto_test:
# I don't think the autobuilders will like this. # I don't think the autobuilders will like this.
override_dh_installinit: override_dh_installinit:
dh_installinit -R dh_installinit -r

1
debian/tinc.install vendored
View file

@ -5,3 +5,4 @@ usr/share/man/man5
usr/share/man/man8/tincd.* usr/share/man/man8/tincd.*
usr/share/man/man8/tinc.* usr/share/man/man8/tinc.*
usr/share/info usr/share/info
debian/*.service /lib/systemd/system/

16
debian/tinc.service vendored Normal file
View file

@ -0,0 +1,16 @@
# This is a mostly empty service, but allows commands like stop, start, reload
# to propagate to all tinc@ service instances.
[Unit]
Description=Tinc VPN
After=network.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/true
ExecReload=/bin/true
WorkingDirectory=/etc/tinc
[Install]
WantedBy=multi-user.target

17
debian/tinc@.service vendored Normal file
View file

@ -0,0 +1,17 @@
[Unit]
Description=Tinc net %i
PartOf=tinc.service
ReloadPropagatedFrom=tinc.service
[Service]
Type=simple
WorkingDirectory=/etc/tinc/%i
ExecStart=/usr/sbin/tinc -n %i start -D
ExecReload=/usr/sbin/tinc -n %i reload
ExecStop=/usr/sbin/tinc -n %i stop
TimeoutStopSec=5
Restart=always
RestartSec=60
[Install]
WantedBy=tinc.service

View file

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.14 from Makefile.am. # Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc. # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@ -80,9 +80,12 @@ subdir = doc
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am texinfo.tex DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am texinfo.tex
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \ $(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \ $(top_srcdir)/m4/ax_check_link_flag.m4 \
$(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.ac $(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/libgcrypt.m4 \
$(top_srcdir)/m4/lzo.m4 $(top_srcdir)/m4/openssl.m4 \
$(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/zlib.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4) $(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d mkinstalldirs = $(install_sh) -d
@ -216,9 +219,6 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@ LDFLAGS = @LDFLAGS@
LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
LIBOBJS = @LIBOBJS@ LIBOBJS = @LIBOBJS@
LIBS = @LIBS@ LIBS = @LIBS@
LN_S = @LN_S@ LN_S = @LN_S@
@ -234,7 +234,6 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@ PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@ PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
READLINE_LIBS = @READLINE_LIBS@ READLINE_LIBS = @READLINE_LIBS@
SET_MAKE = @SET_MAKE@ SET_MAKE = @SET_MAKE@
SHELL = @SHELL@ SHELL = @SHELL@

View file

@ -1,4 +1,4 @@
.Dd 2013-01-15 .Dd 2014-01-16
.Dt TINCCTL 8 .Dt TINCCTL 8
.\" Manual page created by: .\" Manual page created by:
.\" Scott Lamb .\" Scott Lamb
@ -13,14 +13,36 @@
.Op Fl -pidfile Ns = Ns Ar FILENAME .Op Fl -pidfile Ns = Ns Ar FILENAME
.Op Fl -help .Op Fl -help
.Op Fl -version .Op Fl -version
.Ar COMMAND .Op Ar COMMAND
.Sh DESCRIPTION .Sh DESCRIPTION
This is the control program of tinc, a secure virtual private network (VPN) This is the control program of tinc, a secure virtual private network (VPN)
project. project.
.Nm .Nm
communicates with can start and stop
.Xr tincd 8 .Xr tincd 8 ,
to alter and inspect the running VPN's state. and can to alter and inspect the state of a running VPN.
It can also be used to change the configuration,
or to import or export host configuration files from other nodes.
If
.Nm
is started with a
.Ar COMMAND ,
this command is immediately executed, after which
.Nm
exits.
If no
.Ar COMMAND
is given,
.Nm
will act as a shell;
it will display a prompt, and commands can be entered on the prompt.
If
.Nm
is compiled with libreadline, history and command completion are available on the prompt.
One can also pipe a script containing commands through
.Nm .
In that case, lines starting with a # symbol will be ignored.
.Sh OPTIONS .Sh OPTIONS
.Bl -tag -width indent .Bl -tag -width indent
.It Fl n, -net Ns = Ns Ar NETNAME .It Fl n, -net Ns = Ns Ar NETNAME
@ -47,7 +69,7 @@ option, the value of this environment variable is used.
.Sh COMMANDS .Sh COMMANDS
.Bl -tag -width indent .Bl -tag -width indent
.It init Op Ar name .It init Op Ar name
Create initial configuration files and RSA and ECDSA keypairs with default length. Create initial configuration files and RSA and Ed25519 keypairs with default length.
If no If no
.Ar name .Ar name
for this node is given, it will be asked for. for this node is given, it will be asked for.
@ -120,9 +142,9 @@ will be made.
Shows the PID of the currently running Shows the PID of the currently running
.Xr tincd 8 . .Xr tincd 8 .
.It generate-keys Op bits .It generate-keys Op bits
Generate both RSA and ECDSA keypairs (see below) and exit. Generate both RSA and Ed25519 keypairs (see below) and exit.
.It generate-ecdsa-keys .It generate-ed25519-keys
Generate public/private ECDSA keypair and exit. Generate public/private Ed25519 keypair and exit.
.It generate-rsa-keys Op bits .It generate-rsa-keys Op bits
Generate public/private RSA keypair and exit. Generate public/private RSA keypair and exit.
If If
@ -188,6 +210,11 @@ format to standard output,
from where it can be redirected to a file or piped through a program that can parse it directly, from where it can be redirected to a file or piped through a program that can parse it directly,
such as such as
.Xr tcpdump 8 . .Xr tcpdump 8 .
.It network Op Ar netname
If
.Ar netname
is given, switch to that network.
Otherwise, display a list of all networks for which configuration files exist.
.El .El
.Sh EXAMPLES .Sh EXAMPLES
Examples of some commands: Examples of some commands:
@ -197,7 +224,7 @@ tinc -n vpn pcap | tcpdump -r -
tinc -n vpn top tinc -n vpn top
.Pp .Pp
.Ed .Ed
Example of configuring tinc using Examples of changing the configuration using
.Nm : .Nm :
.Bd -literal -offset indent .Bd -literal -offset indent
tinc -n vpn init foo tinc -n vpn init foo

View file

@ -1,4 +1,4 @@
.Dd 2013-01-14 .Dd 2014-01-29
.Dt TINC.CONF 5 .Dt TINC.CONF 5
.\" Manual page created by: .\" Manual page created by:
.\" Ivo Timmermans .\" Ivo Timmermans
@ -64,20 +64,20 @@ or by using
.Sh PUBLIC/PRIVATE KEYS .Sh PUBLIC/PRIVATE KEYS
The The
.Nm tinc Li init .Nm tinc Li init
command will have generated both RSA and ECDSA public/private keypairs. command will have generated both RSA and Ed25519 public/private keypairs.
The private keys should be stored in files named The private keys should be stored in files named
.Pa rsa_key.priv .Pa rsa_key.priv
and and
.Pa ecdsa_key.priv .Pa ed25519_key.priv
in the directory in the directory
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa / .Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /
The public keys should be stored in the host configuration file The public keys should be stored in the host configuration file
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Va NAME . .Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Va NAME .
The RSA keys are used for backwards compatibility with tinc version 1.0. The RSA keys are used for backwards compatibility with tinc version 1.0.
If you are upgrading from version 1.0 to 1.1, you can keep the old configuration files, If you are upgrading from version 1.0 to 1.1, you can keep the old configuration files,
but you will need to create ECDSA keys using the following command: but you will need to create Ed25519 keys using the following command:
.Bd -literal -offset indent .Bd -literal -offset indent
.Nm tinc Fl n Ar NETNAME Li generate-ecdsa-keys .Nm tinc Fl n Ar NETNAME Li generate-ed25519-keys
.Ed .Ed
.Sh SERVER CONFIGURATION .Sh SERVER CONFIGURATION
The server configuration of the daemon is done in the file The server configuration of the daemon is done in the file
@ -114,33 +114,24 @@ If
.Qq any .Qq any
is selected, then depending on the operating system both IPv4 and IPv6 or just is selected, then depending on the operating system both IPv4 and IPv6 or just
IPv6 listening sockets will be created. IPv6 listening sockets will be created.
.It Va AutoConnect Li = Ar count Po 0 Pc Bq experimental .It Va AutoConnect Li = yes | no Po no Pc Bq experimental
If set to a non-zero value, If set to yes,
.Nm
will try to only have
.Ar count
meta connections to other nodes,
by automatically making or breaking connections to known nodes.
Higher values increase redundancy but also increase meta data overhead.
When using this option, a good value is 3.
.It Va BindToAddress Li = Ar address Op Ar port
If your computer has more than one IPv4 or IPv6 address,
.Nm tinc .Nm tinc
will by default listen on all of them for incoming connections. will automatically set up meta connections to other nodes,
Multiple without requiring
.Va BindToAddress .Va ConnectTo
variables may be specified, variables.
in which case listening sockets for each specified address are made.
.Pp .Pp
If no Note: it is not possible to connect to nodes using zero (system-assigned) ports in this way.
.Ar port .It Va BindToAddress Li = Ar address Op Ar port
is specified, the socket will be bound to the port specified by the This is the same as
.Va Port .Va ListenAddress ,
option, or to port 655 if neither is given. however the address given with the
To only bind to a specific port but not to a specific address, use .Va BindToAddress
.Li * option will also be used for outgoing connections. This is useful if your
for the computer has more than one IPv4 or IPv6 address, and you want
.Ar address . .Nm tinc
to only use a specific one for outgoing packets.
.It Va BindToInterface Li = Ar interface Bq experimental .It Va BindToInterface Li = Ar interface Bq experimental
If your computer has more than one network interface, If your computer has more than one network interface,
.Nm tinc .Nm tinc
@ -166,6 +157,13 @@ Broadcast packets are sent directly to all nodes that can be reached directly.
Broadcast packets received from other nodes are never forwarded. Broadcast packets received from other nodes are never forwarded.
If the IndirectData option is also set, broadcast packets will only be sent to nodes which we have a meta connection to. If the IndirectData option is also set, broadcast packets will only be sent to nodes which we have a meta connection to.
.El .El
.It Va BroadcastSubnet Li = Ar address Ns Op Li / Ns Ar prefixlength
Declares a broadcast subnet. Any packet with a destination address falling into such a subnet will be routed as a broadcast (provided all nodes have it declared).
This is most useful to declare subnet broadcast addresses (e.g. 10.42.255.255), otherwise
.Nm tinc
won't know what to do with them.
.Pp
Note that global broadcast addresses (MAC ff:ff:ff:ff:ff:ff, IPv4 255.255.255.255), as well as multicast space (IPv4 224.0.0.0/4, IPv6 ff00::/8) are always considered broadcast addresses and don't need to be declared.
.It Va ConnectTo Li = Ar name .It Va ConnectTo Li = Ar name
Specifies which other tinc daemon to connect to on startup. Specifies which other tinc daemon to connect to on startup.
Multiple Multiple
@ -178,7 +176,9 @@ The names should be known to this tinc daemon
line). line).
.Pp .Pp
If you don't specify a host with If you don't specify a host with
.Va ConnectTo , .Va ConnectTo
and don't enable
.Va AutoConnect ,
.Nm tinc .Nm tinc
won't try to connect to other daemons at all, won't try to connect to other daemons at all,
and will instead just listen for incoming connections. and will instead just listen for incoming connections.
@ -202,6 +202,13 @@ instead of
.Va Device . .Va Device .
The info pages of the tinc package contain more information The info pages of the tinc package contain more information
about configuring the virtual network device. about configuring the virtual network device.
.It Va DeviceStandby Li = yes | no Po no Pc
When disabled,
.Nm tinc
calls tinc-up on startup, and tinc-down on shutdown. When enabled,
.Nm tinc
will only call tinc-up when at least one node is reachable, and will call tinc-down as soon as no nodes are reachable.
On Windows, this also determines when the virtual network interface "cable" is "plugged".
.It Va DeviceType Li = Ar type Pq platform dependent .It Va DeviceType Li = Ar type Pq platform dependent
The type of the virtual network device. The type of the virtual network device.
Tinc will normally automatically select the right type of tun/tap interface, and this option should not be used. Tinc will normally automatically select the right type of tun/tap interface, and this option should not be used.
@ -269,17 +276,17 @@ When this option is enabled, packets that cannot be sent directly to the destina
but which would have to be forwarded by an intermediate node, are dropped instead. but which would have to be forwarded by an intermediate node, are dropped instead.
When combined with the IndirectData option, When combined with the IndirectData option,
packets for nodes for which we do not have a meta connection with are also dropped. packets for nodes for which we do not have a meta connection with are also dropped.
.It Va ECDSAPrivateKeyFile Li = Ar filename Po Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /ecdsa_key.priv Pc .It Va Ed25519PrivateKeyFile Li = Ar filename Po Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /ed25519_key.priv Pc
The file in which the private ECDSA key of this tinc daemon resides. The file in which the private Ed25519 key of this tinc daemon resides.
This is only used if This is only used if
.Va ExperimentalProtocol .Va ExperimentalProtocol
is enabled. is enabled.
.It Va ExperimentalProtocol Li = yes | no Pq yes .It Va ExperimentalProtocol Li = yes | no Pq yes
When this option is enabled, the SPTPS protocol will be used when connecting to nodes that also support it. When this option is enabled, the SPTPS protocol will be used when connecting to nodes that also support it.
Ephemeral ECDH will be used for key exchanges, Ephemeral ECDH will be used for key exchanges,
and ECDSA will be used instead of RSA for authentication. and Ed25519 will be used instead of RSA for authentication.
When enabled, an ECDSA key must have been generated before with When enabled, an Ed25519 key must have been generated before with
.Nm tinc generate-ecdsa-keys . .Nm tinc generate-ed25519-keys .
.It Va Forwarding Li = off | internal | kernel Po internal Pc Bq experimental .It Va Forwarding Li = off | internal | kernel Po internal Pc Bq experimental
This option selects the way indirect packets are forwarded. This option selects the way indirect packets are forwarded.
.Bl -tag -width indent .Bl -tag -width indent
@ -316,7 +323,34 @@ this variable is almost always already correctly set.
This option controls the period the encryption keys used to encrypt the data are valid. This option controls the period the encryption keys used to encrypt the data are valid.
It is common practice to change keys at regular intervals to make it even harder for crackers, It is common practice to change keys at regular intervals to make it even harder for crackers,
even though it is thought to be nearly impossible to crack a single key. even though it is thought to be nearly impossible to crack a single key.
.It Va LocalDiscovery Li = yes | no Pq no .It Va ListenAddress Li = Ar address Op Ar port
If your computer has more than one IPv4 or IPv6 address,
.Nm tinc
will by default listen on all of them for incoming connections.
This option can be used to restrict which addresses tinc listens on.
Multiple
.Va ListenAddress
variables may be specified,
in which case listening sockets for each specified address are made.
.Pp
If no
.Ar port
is specified, the socket will listen on the port specified by the
.Va Port
option, or to port 655 if neither is given.
To only listen on a specific port but not on a specific address, use
.Li *
for the
.Ar address .
.Pp
If
.Ar port
is set to zero, it will be randomly assigned by the system. This is useful to randomize source ports of UDP packets, which can improve UDP hole punching reliability. In this case it is recommended to set
.Va AddressFamily
as well, otherwise
.Nm tinc
will assign different ports to different address families but other nodes can only know of one.
.It Va LocalDiscovery Li = yes | no Pq yes
When enabled, When enabled,
.Nm tinc .Nm tinc
will try to detect peers that are on the same local network. will try to detect peers that are on the same local network.
@ -324,11 +358,7 @@ This will allow direct communication using LAN addresses, even if both peers are
and they only ConnectTo a third node outside the NAT, and they only ConnectTo a third node outside the NAT,
which normally would prevent the peers from learning each other's LAN address. which normally would prevent the peers from learning each other's LAN address.
.Pp .Pp
Currently, local discovery is implemented by sending broadcast packets to the LAN during path MTU discovery. Currently, local discovery is implemented by sending some packets to the local address of the node during path MTU discovery. This will not work with old nodes that don't transmit their local address.
This feature may not work in all possible situations.
.It Va LocalDiscoveryAddress Li = Ar address
If this variable is specified, local discovery packets are sent to the given
.Ar address .
.It Va MACExpire Li = Ar seconds Pq 600 .It Va MACExpire Li = Ar seconds Pq 600
This option controls the amount of time MAC addresses are kept before they are removed. This option controls the amount of time MAC addresses are kept before they are removed.
This only has effect when This only has effect when
@ -367,7 +397,8 @@ while no routing table is managed.
.It Va Name Li = Ar name Bq required .It Va Name Li = Ar name Bq required
This is the name which identifies this tinc daemon. This is the name which identifies this tinc daemon.
It must be unique for the virtual private network this daemon will connect to. It must be unique for the virtual private network this daemon will connect to.
The Name may only consist of alphanumeric and underscore characters (a-z, A-Z, 0-9 and _), and is case sensitive. .Va Name
may only consist of alphanumeric and underscore characters (a-z, A-Z, 0-9 and _), and is case sensitive.
If If
.Va Name .Va Name
starts with a starts with a
@ -446,7 +477,8 @@ traffic.
When this option is enabled tinc will only use Subnet statements which are When this option is enabled tinc will only use Subnet statements which are
present in the host config files in the local present in the host config files in the local
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ .Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/
directory. directory. Subnets learned via connections to other nodes and which are not
present in the local host config files are ignored.
.It Va TunnelServer Li = yes | no Po no Pc Bq experimental .It Va TunnelServer Li = yes | no Po no Pc Bq experimental
When this option is enabled tinc will no longer forward information between other tinc daemons, When this option is enabled tinc will no longer forward information between other tinc daemons,
and will only allow connections with nodes for which host config files are present in the local and will only allow connections with nodes for which host config files are present in the local
@ -507,8 +539,8 @@ will turn off packet authentication.
This option has no effect for connections between nodes using This option has no effect for connections between nodes using
.Va ExperimentalProtocol . .Va ExperimentalProtocol .
.It Va IndirectData Li = yes | no Pq no .It Va IndirectData Li = yes | no Pq no
When set to yes, other nodes which do not already have a meta connection to you When set to yes, only nodes which already have a meta connection to you
will not try to establish direct communication with you. will try to establish direct communication with you.
It is best to leave this option out or set it to no. It is best to leave this option out or set it to no.
.It Va MACLength Li = Ar length Pq 4 .It Va MACLength Li = Ar length Pq 4
The length of the message authentication code used to authenticate UDP packets. The length of the message authentication code used to authenticate UDP packets.
@ -527,6 +559,14 @@ The port number on which this tinc daemon is listening for incoming connections,
which is used if no port number is specified in an which is used if no port number is specified in an
.Va Address .Va Address
statement. statement.
.Pp
If this is set to zero, the port will be randomly assigned by the system. This is useful to randomize source ports of UDP packets, which can improve UDP hole punching reliability. When setting
.Va Port
to zero it is recommended to set
.Va AddressFamily
as well, otherwise
.Nm tinc
will assign different ports to different address families but other nodes can only know of one.
.It Va PublicKey Li = Ar key Bq obsolete .It Va PublicKey Li = Ar key Bq obsolete
The public RSA key of this tinc daemon. The public RSA key of this tinc daemon.
It will be used to cryptographically verify it's identity and to set up a secure connection. It will be used to cryptographically verify it's identity and to set up a secure connection.
@ -575,6 +615,12 @@ Setting this options also implicitly sets IndirectData.
.Pp .Pp
Since version 1.0.10, tinc will automatically detect whether communication via Since version 1.0.10, tinc will automatically detect whether communication via
UDP is possible or not. UDP is possible or not.
.It Va Weight Li = Ar weight
If this variable is set, it overrides the weight given to connections made with
another host. A higher
.Ar weight
means a lower priority is given to this connection when broadcasting or
forwarding packets.
.El .El
.Sh SCRIPTS .Sh SCRIPTS
Apart from reading the server and host configuration files, Apart from reading the server and host configuration files,
@ -586,12 +632,16 @@ or
.Bl -tag -width indent .Bl -tag -width indent
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up
This is the most important script. This is the most important script.
If it is present it will be executed right after the tinc daemon has been started and has connected to the virtual network device. If it is present it will be executed right after the tinc daemon has been started and has connected to the virtual network device (or when the first node becomes reachable if
.Va DeviceStandby
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.
Under Windows you can use the Network Connections control panel instead of creating this script. Under Windows you can use the Network Connections control panel instead of creating this script.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-down .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-down
This script is started right before the tinc daemon quits. This script is started right before the tinc daemon quits (or when the last node becomes unreachable if
.Va DeviceStandby
is used).
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Ar HOST Ns Pa -up .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Ar HOST Ns Pa -up
This script is started when the tinc daemon with name This script is started when the tinc daemon with name
.Ar HOST .Ar HOST
@ -668,6 +718,8 @@ The top directory for configuration files.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf
The default name of the server configuration file for net The default name of the server configuration file for net
.Ar NETNAME . .Ar NETNAME .
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /conf.d/
Optional directory from which any .conf file will be loaded
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/
Host configuration files are kept in this directory. Host configuration files are kept in this directory.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up

View file

@ -1,14 +1,14 @@
This is tinc.info, produced by makeinfo version 5.1 from tinc.texi. This is tinc.info, produced by makeinfo version 5.2 from tinc.texi.
INFO-DIR-SECTION Networking tools INFO-DIR-SECTION Networking tools
START-INFO-DIR-ENTRY START-INFO-DIR-ENTRY
* tinc: (tinc). The tinc Manual. * tinc: (tinc). The tinc Manual.
END-INFO-DIR-ENTRY END-INFO-DIR-ENTRY
This is the info manual for tinc version 1.1pre9, a Virtual Private This is the info manual for tinc version 1.1pre10, a Virtual Private
Network daemon. Network daemon.
Copyright (C) 1998-2013 Ivo Timmermans, Guus Sliepen Copyright (C) 1998-2014 Ivo Timmermans, Guus Sliepen
<guus@tinc-vpn.org> and Wessel Dankers <wsl@tinc-vpn.org>. <guus@tinc-vpn.org> and Wessel Dankers <wsl@tinc-vpn.org>.
Permission is granted to make and distribute verbatim copies of this Permission is granted to make and distribute verbatim copies of this
@ -286,9 +286,9 @@ File: tinc.info, Node: Libraries, Prev: Configuring the kernel, Up: Preparati
============= =============
Before you can configure or build tinc, you need to have the OpenSSL, Before you can configure or build tinc, you need to have the OpenSSL,
zlib and lzo libraries installed on your system. If you try to zlib, lzo, curses and readline libraries installed on your system. If
configure tinc without having them installed, configure will give you an you try to configure tinc without having them installed, configure will
error message, and stop. give you an error message, and stop.
* Menu: * Menu:
@ -724,6 +724,9 @@ The actual configuration of the daemon is done in the file
'/etc/tinc/NETNAME/tinc.conf' and at least one other file in the '/etc/tinc/NETNAME/tinc.conf' and at least one other file in the
directory '/etc/tinc/NETNAME/hosts/'. directory '/etc/tinc/NETNAME/hosts/'.
An optionnal directory '/etc/tinc/NETNAME/conf.d' can be added from
which any .conf file will be read.
These file consists of comments (lines started with a #) or assignments These file consists of comments (lines started with a #) or assignments
in the form of in the form of
@ -767,23 +770,16 @@ AddressFamily = <ipv4|ipv6|any> (any)
system both IPv4 and IPv6 or just IPv6 listening sockets will be system both IPv4 and IPv6 or just IPv6 listening sockets will be
created. created.
AutoConnect = <count> (0) [experimental] AutoConnect = <yes|no> (no) [experimental]
If set to a non-zero value, tinc will try to only have count meta If set to yes, tinc will automatically set up meta connections to
connections to other nodes, by automatically making or breaking other nodes, without requiring CONNECTTO variables.
connections to known nodes. Higher values increase redundancy but
also increase meta data overhead. When using this option, a good
value is 3.
BindToAddress = <ADDRESS> [<PORT>] BindToAddress = <ADDRESS> [<PORT>]
If your computer has more than one IPv4 or IPv6 address, tinc will This is the same as ListenAddress, however the address given with
by default listen on all of them for incoming connections. the BindToAddress option will also be used for outgoing
Multiple BindToAddress variables may be specified, in which case connections. This is useful if your computer has more than one
listening sockets for each specified address are made. IPv4 or IPv6 address, and you want tinc to only use a specific one
for outgoing packets.
If no PORT is specified, the socket will be bound to the port
specified by the Port option, or to port 655 if neither is given.
To only bind to a specific port but not to a specific address, use
"*" for the ADDRESS.
BindToInterface = <INTERFACE> [experimental] BindToInterface = <INTERFACE> [experimental]
If you have more than one network interface in your computer, tinc If you have more than one network interface in your computer, tinc
@ -815,6 +811,18 @@ Broadcast = <no | mst | direct> (mst) [experimental]
broadcast packets will only be sent to nodes which we have a broadcast packets will only be sent to nodes which we have a
meta connection to. meta connection to.
BroadcastSubnet = ADDRESS[/PREFIXLENGTH]
Declares a broadcast subnet. Any packet with a destination address
falling into such a subnet will be routed as a broadcast (provided
all nodes have it declared). This is most useful to declare subnet
broadcast addresses (e.g. 10.42.255.255), otherwise tinc won't
know what to do with them.
Note that global broadcast addresses (MAC ff:ff:ff:ff:ff:ff, IPv4
255.255.255.255), as well as multicast space (IPv4 224.0.0.0/4,
IPv6 ff00::/8) are always considered broadcast addresses and don't
need to be declared.
ConnectTo = <NAME> ConnectTo = <NAME>
Specifies which other tinc daemon to connect to on startup. Specifies which other tinc daemon to connect to on startup.
Multiple ConnectTo variables may be specified, in which case Multiple ConnectTo variables may be specified, in which case
@ -822,9 +830,9 @@ ConnectTo = <NAME>
names should be known to this tinc daemon (i.e., there should be a names should be known to this tinc daemon (i.e., there should be a
host configuration file for the name on the ConnectTo line). host configuration file for the name on the ConnectTo line).
If you don't specify a host with ConnectTo, tinc won't try to If you don't specify a host with ConnectTo and don't enable
connect to other daemons at all, and will instead just listen for AutoConnect, tinc won't try to connect to other daemons at all, and
incoming connections. will instead just listen for incoming connections.
DecrementTTL = <yes | no> (no) [experimental] DecrementTTL = <yes | no> (no) [experimental]
When enabled, tinc will decrement the Time To Live field in IPv4 When enabled, tinc will decrement the Time To Live field in IPv4
@ -842,6 +850,13 @@ Device = <DEVICE> ('/dev/tap0', '/dev/net/tun' or other depending on platform)
that you can only use one device per daemon. See also *note Device that you can only use one device per daemon. See also *note Device
files::. files::.
DeviceStandby = <yes | no> (no)
When disabled, tinc calls 'tinc-up' on startup, and 'tinc-down' on
shutdown. When enabled, tinc will only call 'tinc-up' when at
least one node is reachable, and will call 'tinc-down' as soon as
no nodes are reachable. On Windows, this also determines when the
virtual network interface "cable" is "plugged".
DeviceType = <TYPE> (platform dependent) DeviceType = <TYPE> (platform dependent)
The type of the virtual network device. Tinc will normally The type of the virtual network device. Tinc will normally
automatically select the right type of tun/tap interface, and this automatically select the right type of tun/tap interface, and this
@ -914,16 +929,16 @@ DirectOnly = <yes|no> (no) [experimental]
IndirectData option, packets for nodes for which we do not have a IndirectData option, packets for nodes for which we do not have a
meta connection with are also dropped. meta connection with are also dropped.
ECDSAPrivateKeyFile = <PATH> ('/etc/tinc/NETNAME/ecdsa_key.priv') Ed25519PrivateKeyFile = <PATH> ('/etc/tinc/NETNAME/ed25519_key.priv')
The file in which the private ECDSA key of this tinc daemon The file in which the private Ed25519 key of this tinc daemon
resides. This is only used if ExperimentalProtocol is enabled. resides. This is only used if ExperimentalProtocol is enabled.
ExperimentalProtocol = <yes|no> (yes) ExperimentalProtocol = <yes|no> (yes)
When this option is enabled, the SPTPS protocol will be used when When this option is enabled, the SPTPS protocol will be used when
connecting to nodes that also support it. Ephemeral ECDH will be connecting to nodes that also support it. Ephemeral ECDH will be
used for key exchanges, and ECDSA will be used instead of RSA for used for key exchanges, and Ed25519 will be used instead of RSA for
authentication. When enabled, an ECDSA key must have been authentication. When enabled, an Ed25519 key must have been
generated before with 'tinc generate-ecdsa-keys'. generated before with 'tinc generate-ed25519-keys'.
Forwarding = <off|internal|kernel> (internal) [experimental] Forwarding = <off|internal|kernel> (internal) [experimental]
This option selects the way indirect packets are forwarded. This option selects the way indirect packets are forwarded.
@ -964,6 +979,18 @@ Interface = <INTERFACE>
interface will be used. If you specified a Device, this variable interface will be used. If you specified a Device, this variable
is almost always already correctly set. is almost always already correctly set.
ListenAddress = <ADDRESS> [<PORT>]
If your computer has more than one IPv4 or IPv6 address, tinc will
by default listen on all of them for incoming connections. This
option can be used to restrict which addresses tinc listens on.
Multiple ListenAddress variables may be specified, in which case
listening sockets for each specified address are made.
If no PORT is specified, the socket will listen on the port
specified by the Port option, or to port 655 if neither is given.
To only listen on a specific port but not to a specific address,
use "*" for the ADDRESS.
LocalDiscovery = <yes | no> (no) LocalDiscovery = <yes | no> (no)
When enabled, tinc will try to detect peers that are on the same When enabled, tinc will try to detect peers that are on the same
local network. This will allow direct communication using LAN local network. This will allow direct communication using LAN
@ -1065,7 +1092,7 @@ ProcessPriority = <low|normal|high>
adjusted. Increasing the priority may help to reduce latency and adjusted. Increasing the priority may help to reduce latency and
packet loss on the VPN. packet loss on the VPN.
Proxy = socks4 | socks4 | http | exec ... [experimental] Proxy = socks4 | socks5 | http | exec ... [experimental]
Use a proxy when making outgoing connections. The following proxy Use a proxy when making outgoing connections. The following proxy
types are currently supported: types are currently supported:
@ -1074,7 +1101,7 @@ Proxy = socks4 | socks4 | http | exec ... [experimental]
Optionally, a USERNAME can be supplied which will be passed on Optionally, a USERNAME can be supplied which will be passed on
to the proxy server. to the proxy server.
socks4 <ADDRESS> <PORT> [<USERNAME> <PASSWORD>] socks5 <ADDRESS> <PORT> [<USERNAME> <PASSWORD>]
Connect to the proxy using the SOCKS version 5 protocol. If a Connect to the proxy using the SOCKS version 5 protocol. If a
USERNAME and PASSWORD are given, basic username/password USERNAME and PASSWORD are given, basic username/password
authentication will be used, otherwise no authentication will authentication will be used, otherwise no authentication will
@ -1099,10 +1126,12 @@ ReplayWindow = <bytes> (16)
pass all traffic, but leaves tinc vulnerable to replay-based pass all traffic, but leaves tinc vulnerable to replay-based
attacks on your traffic. attacks on your traffic.
StrictSubnets <yes|no> (no) [experimental] StrictSubnets = <yes|no> (no) [experimental]
When this option is enabled tinc will only use Subnet statements When this option is enabled tinc will only use Subnet statements
which are present in the host config files in the local which are present in the host config files in the local
'/etc/tinc/NETNAME/hosts/' directory. '/etc/tinc/NETNAME/hosts/' directory. Subnets learned via
connections to other nodes and which are not present in the local
host config files are ignored.
TunnelServer = <yes|no> (no) [experimental] TunnelServer = <yes|no> (no) [experimental]
When this option is enabled tinc will no longer forward information When this option is enabled tinc will no longer forward information
@ -1131,7 +1160,9 @@ Address = <IP ADDRESS|HOSTNAME> [<port>] [recommended]
This variable is only required if you want to connect to this host. This variable is only required if you want to connect to this host.
It must resolve to the external IP address where the host can be It must resolve to the external IP address where the host can be
reached, not the one that is internal to the VPN. If no port is reached, not the one that is internal to the VPN. If no port is
specified, the default Port is used. specified, the default Port is used. Multiple Address variables
can be specified, in which case each address will be tried until a
working connection has been established.
Cipher = <CIPHER> (blowfish) Cipher = <CIPHER> (blowfish)
The symmetric cipher algorithm used to encrypt UDP packets using The symmetric cipher algorithm used to encrypt UDP packets using
@ -1234,6 +1265,12 @@ TCPonly = <yes|no> (no)
masquerading firewall, or if UDP packet routing is disabled masquerading firewall, or if UDP packet routing is disabled
somehow. Setting this options also implicitly sets IndirectData. somehow. Setting this options also implicitly sets IndirectData.
Weight = <weight>
If this variable is set, it overrides the weight given to
connections made with another host. A higher weight means a lower
priority is given to this connection when broadcasting or
forwarding packets.
 
File: tinc.info, Node: Scripts, Next: How to configure, Prev: Host configuration variables, Up: Configuration files File: tinc.info, Node: Scripts, Next: How to configure, Prev: Host configuration variables, Up: Configuration files
@ -1353,10 +1390,10 @@ contents:
Name = NAME Name = NAME
It will also create private RSA and ECDSA keys, which will be stored in It will also create private RSA and Ed25519 keys, which will be stored
the files 'rsa_key.priv' and 'ecdsa_key.priv'. It will also create a in the files 'rsa_key.priv' and 'ed25519_key.priv'. It will also create
host configuration file 'hosts/NAME', which will contain the a host configuration file 'hosts/NAME', which will contain the
corresponding public RSA and ECDSA keys. corresponding public RSA and Ed25519 keys.
Finally, on UNIX operating systems, it will create an executable script Finally, on UNIX operating systems, it will create an executable script
'tinc-up', which will initially not do anything except warning that you 'tinc-up', which will initially not do anything except warning that you
@ -1375,7 +1412,7 @@ should run the following command:
This will add a Subnet statement to your host configuration file. Try This will add a Subnet statement to your host configuration file. Try
opening the file '/etc/tinc/NETNAME/hosts/NAME' in an editor. You opening the file '/etc/tinc/NETNAME/hosts/NAME' in an editor. You
should now see a file containing the public RSA and ECDSA keys (which should now see a file containing the public RSA and Ed25519 keys (which
looks like a bunch of random characters), and the following line at the looks like a bunch of random characters), and the following line at the
bottom: bottom:
@ -1657,9 +1694,9 @@ Key files
A, B, C and D all have their own public/private keypairs: A, B, C and D all have their own public/private keypairs:
The private RSA key is stored in '/etc/tinc/company/rsa_key.priv', the The private RSA key is stored in '/etc/tinc/company/rsa_key.priv', the
private ECDSA key is stored in '/etc/tinc/company/ecdsa_key.priv', and private Ed25519 key is stored in '/etc/tinc/company/ed25519_key.priv',
the public RSA and ECDSA keys are put into the host configuration file and the public RSA and Ed25519 keys are put into the host configuration
in the '/etc/tinc/company/hosts/' directory. file in the '/etc/tinc/company/hosts/' directory.
Starting Starting
........ ........
@ -1997,11 +2034,17 @@ File: tinc.info, Node: Controlling tinc, Next: Technical information, Prev: R
6 Controlling tinc 6 Controlling tinc
****************** ******************
You can control and inspect a running tincd through the tinc command. A You can start, stop, control and inspect a running tincd through the
quick example: tinc command. A quick example:
tinc -n NETNAME reload tinc -n NETNAME reload
If tinc is started without a command, it will act as a shell; it will
display a prompt, and commands can be entered on the prompt. If tinc is
compiled with libreadline, history and command completion are available
on the prompt. One can also pipe a script containing commands through
tinc. In that case, lines starting with a # symbol will be ignored.
* Menu: * Menu:
* tinc runtime options:: * tinc runtime options::
@ -2052,8 +2095,8 @@ File: tinc.info, Node: tinc commands, Next: tinc examples, Prev: tinc environ
================= =================
'init [NAME]' 'init [NAME]'
Create initial configuration files and RSA and ECDSA keypairs with Create initial configuration files and RSA and Ed25519 keypairs
default length. If no NAME for this node is given, it will be with default length. If no NAME for this node is given, it will be
asked for. asked for.
'get VARIABLE' 'get VARIABLE'
@ -2126,12 +2169,12 @@ File: tinc.info, Node: tinc commands, Next: tinc examples, Prev: tinc environ
Shows the PID of the currently running 'tincd'. Shows the PID of the currently running 'tincd'.
'generate-keys [BITS]' 'generate-keys [BITS]'
Generate both RSA and ECDSA keypairs (see below) and exit. tinc Generate both RSA and Ed25519 keypairs (see below) and exit. tinc
will ask where you want to store the files, but will default to the will ask where you want to store the files, but will default to the
configuration directory (you can use the -c or -n option). configuration directory (you can use the -c or -n option).
'generate-ecdsa-keys' 'generate-ed25519-keys'
Generate public/private ECDSA keypair and exit. Generate public/private Ed25519 keypair and exit.
'generate-rsa-keys [BITS]' 'generate-rsa-keys [BITS]'
Generate public/private RSA keypair and exit. If BITS is omitted, Generate public/private RSA keypair and exit. If BITS is omitted,
@ -2195,6 +2238,10 @@ File: tinc.info, Node: tinc commands, Next: tinc examples, Prev: tinc environ
file or piped through a program that can parse it directly, such as file or piped through a program that can parse it directly, such as
tcpdump. tcpdump.
'network'
If NETNAME is given, switch to that network. Otherwise, display a
list of all networks for which configuration files exist.
 
File: tinc.info, Node: tinc examples, Next: tinc top, Prev: tinc commands, Up: Controlling tinc File: tinc.info, Node: tinc examples, Next: tinc top, Prev: tinc commands, Up: Controlling tinc
@ -2207,7 +2254,7 @@ Examples of some commands:
tinc -n vpn pcap | tcpdump -r - tinc -n vpn pcap | tcpdump -r -
tinc -n vpn top tinc -n vpn top
Example of configuring tinc using the tinc command: Examples of changing the configuration using tinc:
tinc -n vpn init foo tinc -n vpn init foo
tinc -n vpn add Subnet 192.168.1.0/24 tinc -n vpn add Subnet 192.168.1.0/24
@ -2776,11 +2823,11 @@ The expanded key is used as follows:
Where initiator_cipher_key is the key used by session initiator to Where initiator_cipher_key is the key used by session initiator to
encrypt messages sent to the responder. encrypt messages sent to the responder.
When using 521 bits EC keys, the AES-256-CTR cipher and HMAC-SHA-256 When using 256 bits Ed25519 keys, the AES-256-CTR cipher and
digest algorithm, the sizes are as follows: HMAC-SHA-256 digest algorithm, the sizes are as follows:
ECDH_SIZE: 67 (= ceil(521/8) + 1) ECDH_SIZE: 32 (= 256/8)
ECDSA_SIZE: 141 (= 2 * ceil(521/8) + 9) ECDSA_SIZE: 64 (= 2 * 256/8)
CIPHER_KEYSIZE: 48 (= 256/8 + 128/8) CIPHER_KEYSIZE: 48 (= 256/8 + 128/8)
DIGEST_KEYSIZE: 32 (= 256/8) DIGEST_KEYSIZE: 32 (= 256/8)
@ -3019,6 +3066,7 @@ Concept Index
* ACK: Legacy authentication protocol. * ACK: Legacy authentication protocol.
(line 6) (line 6)
* add: tinc commands. (line 22)
* Address: Host configuration variables. * Address: Host configuration variables.
(line 6) (line 6)
* AddressFamily: Main configuration variables. * AddressFamily: Main configuration variables.
@ -3031,83 +3079,107 @@ Concept Index
* binary package: Building and installing tinc. * binary package: Building and installing tinc.
(line 9) (line 9)
* BindToAddress: Main configuration variables. * BindToAddress: Main configuration variables.
(line 19) (line 16)
* BindToInterface: Main configuration variables. * BindToInterface: Main configuration variables.
(line 30) (line 23)
* Broadcast: Main configuration variables. * Broadcast: Main configuration variables.
(line 40) (line 33)
* BroadcastSubnet: Main configuration variables.
(line 53)
* Cabal: Security. (line 6) * Cabal: Security. (line 6)
* CHALLENGE: Legacy authentication protocol. * CHALLENGE: Legacy authentication protocol.
(line 6) (line 6)
* CHAL_REPLY: Legacy authentication protocol. * CHAL_REPLY: Legacy authentication protocol.
(line 6) (line 6)
* CIDR notation: Host configuration variables. * CIDR notation: Host configuration variables.
(line 94) (line 96)
* Cipher: Host configuration variables. * Cipher: Host configuration variables.
(line 12) (line 14)
* ClampMSS: Host configuration variables. * ClampMSS: Host configuration variables.
(line 20) (line 22)
* client: How connections work. * client: How connections work.
(line 18) (line 18)
* command line: Runtime options. (line 9) * command line: Runtime options. (line 9)
* command line interface: Controlling tinc. (line 6)
* Compression: Host configuration variables. * Compression: Host configuration variables.
(line 26) (line 28)
* connection: The connection. (line 6) * connection: The connection. (line 6)
* ConnectTo: Main configuration variables. * ConnectTo: Main configuration variables.
(line 60) (line 65)
* daemon: Running tinc. (line 11) * daemon: Running tinc. (line 11)
* data-protocol: The meta-connection. (line 18) * data-protocol: The meta-connection. (line 18)
* debug: tinc commands. (line 121)
* debug level: Runtime options. (line 17) * debug level: Runtime options. (line 17)
* debug levels: Debug levels. (line 6) * debug levels: Debug levels. (line 6)
* DecrementTTL: Main configuration variables. * DecrementTTL: Main configuration variables.
(line 71) (line 76)
* del: tinc commands. (line 26)
* DEL_EDGE: The meta-protocol. (line 46) * DEL_EDGE: The meta-protocol. (line 46)
* DEL_SUBNET: The meta-protocol. (line 46) * DEL_SUBNET: The meta-protocol. (line 46)
* Device: Main configuration variables. * Device: Main configuration variables.
(line 80) (line 85)
* DEVICE: Scripts. (line 60) * DEVICE: Scripts. (line 60)
* device files: Device files. (line 6) * device files: Device files. (line 6)
* DeviceStandby: Main configuration variables.
(line 92)
* DeviceType: Main configuration variables. * DeviceType: Main configuration variables.
(line 87) (line 99)
* Digest: Host configuration variables. * Digest: Host configuration variables.
(line 31) (line 33)
* DirectOnly: Main configuration variables. * DirectOnly: Main configuration variables.
(line 152) (line 164)
* disconnect: tinc commands. (line 136)
* dummy: Main configuration variables. * dummy: Main configuration variables.
(line 94) (line 106)
* ECDSAPrivateKeyFile: Main configuration variables. * dump: tinc commands. (line 94)
(line 159) * Ed25519PrivateKeyFile: Main configuration variables.
(line 171)
* edit: tinc commands. (line 31)
* encapsulating: The UDP tunnel. (line 30) * encapsulating: The UDP tunnel. (line 30)
* encryption: Encryption of network packets. * encryption: Encryption of network packets.
(line 6) (line 6)
* environment variables: Scripts. (line 48) * environment variables: Scripts. (line 48)
* example: Example configuration. * example: Example configuration.
(line 6) (line 6)
* exchange: tinc commands. (line 47)
* exchange-all: tinc commands. (line 50)
* exec: Main configuration variables. * exec: Main configuration variables.
(line 328) (line 352)
* ExperimentalProtocol: Main configuration variables. * ExperimentalProtocol: Main configuration variables.
(line 163) (line 175)
* export: tinc commands. (line 35)
* export-all: tinc commands. (line 39)
* Forwarding: Main configuration variables. * Forwarding: Main configuration variables.
(line 170) (line 182)
* frame type: The UDP tunnel. (line 6) * frame type: The UDP tunnel. (line 6)
* generate-ed25519-keys: tinc commands. (line 85)
* generate-keys: tinc commands. (line 80)
* generate-rsa-keys: tinc commands. (line 88)
* get: tinc commands. (line 11)
* graph: tinc commands. (line 107)
* Hostnames: Main configuration variables. * Hostnames: Main configuration variables.
(line 190) (line 202)
* http: Main configuration variables. * http: Main configuration variables.
(line 325) (line 349)
* hub: Main configuration variables. * hub: Main configuration variables.
(line 246) (line 270)
* ID: Legacy authentication protocol. * ID: Legacy authentication protocol.
(line 6) (line 6)
* import: tinc commands. (line 42)
* IndirectData: Host configuration variables. * IndirectData: Host configuration variables.
(line 38) (line 40)
* info: tinc commands. (line 114)
* init: tinc commands. (line 6)
* Interface: Main configuration variables. * Interface: Main configuration variables.
(line 201) (line 213)
* INTERFACE: Scripts. (line 63) * INTERFACE: Scripts. (line 63)
* INVITATION_FILE: Scripts. (line 86) * INVITATION_FILE: Scripts. (line 86)
* INVITATION_URL: Scripts. (line 90) * INVITATION_URL: Scripts. (line 90)
* invite: tinc commands. (line 53)
* IRC: Contact information. (line 9) * IRC: Contact information. (line 9)
* join: tinc commands. (line 58)
* KeyExpire: Main configuration variables. * KeyExpire: Main configuration variables.
(line 251) (line 275)
* KEY_CHANGED: The meta-protocol. (line 63) * KEY_CHANGED: The meta-protocol. (line 63)
* legacy authentication protocol: Legacy authentication protocol. * legacy authentication protocol: Legacy authentication protocol.
(line 6) (line 6)
@ -3115,27 +3187,30 @@ Concept Index
* libraries: Libraries. (line 6) * libraries: Libraries. (line 6)
* libreadline: libreadline. (line 6) * libreadline: libreadline. (line 6)
* license: OpenSSL. (line 35) * license: OpenSSL. (line 35)
* ListenAddress: Main configuration variables.
(line 221)
* LocalDiscovery: Main configuration variables. * LocalDiscovery: Main configuration variables.
(line 209) (line 233)
* LocalDiscoveryAddress: Main configuration variables. * LocalDiscoveryAddress: Main configuration variables.
(line 220) (line 244)
* log: tinc commands. (line 124)
* lzo: lzo. (line 6) * lzo: lzo. (line 6)
* MACExpire: Main configuration variables. * MACExpire: Main configuration variables.
(line 257) (line 281)
* MACLength: Host configuration variables. * MACLength: Host configuration variables.
(line 43) (line 45)
* MaxConnectionBurst: Main configuration variables. * MaxConnectionBurst: Main configuration variables.
(line 262) (line 286)
* meta-protocol: The meta-connection. (line 18) * meta-protocol: The meta-connection. (line 18)
* META_KEY: Legacy authentication protocol. * META_KEY: Legacy authentication protocol.
(line 6) (line 6)
* Mode: Main configuration variables. * Mode: Main configuration variables.
(line 224) (line 248)
* multicast: Main configuration variables. * multicast: Main configuration variables.
(line 106) (line 118)
* multiple networks: Multiple networks. (line 6) * multiple networks: Multiple networks. (line 6)
* Name: Main configuration variables. * Name: Main configuration variables.
(line 268) (line 292)
* NAME: Scripts. (line 57) * NAME: Scripts. (line 57)
* netmask: Network interfaces. (line 39) * netmask: Network interfaces. (line 39)
* netname: Multiple networks. (line 6) * netname: Multiple networks. (line 6)
@ -3144,101 +3219,114 @@ Concept Index
(line 6) (line 6)
* Network Administrators Guide: Configuration introduction. * Network Administrators Guide: Configuration introduction.
(line 15) (line 15)
* network [NETNAME]: tinc commands. (line 150)
* NODE: Scripts. (line 67) * NODE: Scripts. (line 67)
* OpenSSL: OpenSSL. (line 6) * OpenSSL: OpenSSL. (line 6)
* options: Runtime options. (line 9) * options: Runtime options. (line 9)
* pcap: tinc commands. (line 144)
* PEM format: Host configuration variables. * PEM format: Host configuration variables.
(line 70) (line 72)
* pid: tinc commands. (line 77)
* PING: The meta-protocol. (line 88) * PING: The meta-protocol. (line 88)
* PingInterval: Main configuration variables. * PingInterval: Main configuration variables.
(line 279) (line 303)
* PingTimeout: Main configuration variables. * PingTimeout: Main configuration variables.
(line 283) (line 307)
* platforms: Supported platforms. (line 6) * platforms: Supported platforms. (line 6)
* PMTU: Host configuration variables. * PMTU: Host configuration variables.
(line 50) (line 52)
* PMTUDiscovery: Host configuration variables. * PMTUDiscovery: Host configuration variables.
(line 53) (line 55)
* PONG: The meta-protocol. (line 88) * PONG: The meta-protocol. (line 88)
* Port: Host configuration variables. * Port: Host configuration variables.
(line 58) (line 60)
* port numbers: Other files. (line 17) * port numbers: Other files. (line 17)
* PriorityInheritance: Main configuration variables. * PriorityInheritance: Main configuration variables.
(line 289) (line 313)
* private: Virtual Private Networks. * private: Virtual Private Networks.
(line 10) (line 10)
* PrivateKey: Main configuration variables. * PrivateKey: Main configuration variables.
(line 294) (line 318)
* PrivateKeyFile: Main configuration variables. * PrivateKeyFile: Main configuration variables.
(line 300) (line 324)
* ProcessPriority: Main configuration variables. * ProcessPriority: Main configuration variables.
(line 305) (line 329)
* Proxy: Main configuration variables. * Proxy: Main configuration variables.
(line 310) (line 334)
* PublicKey: Host configuration variables. * PublicKey: Host configuration variables.
(line 62) (line 64)
* PublicKeyFile: Host configuration variables. * PublicKeyFile: Host configuration variables.
(line 65) (line 67)
* purge: tinc commands. (line 118)
* raw_socket: Main configuration variables. * raw_socket: Main configuration variables.
(line 99) (line 111)
* release: Supported platforms. (line 14) * release: Supported platforms. (line 14)
* reload: tinc commands. (line 72)
* REMOTEADDRESS: Scripts. (line 72) * REMOTEADDRESS: Scripts. (line 72)
* REMOTEPORT: Scripts. (line 75) * REMOTEPORT: Scripts. (line 75)
* ReplayWindow: Main configuration variables. * ReplayWindow: Main configuration variables.
(line 333) (line 357)
* requirements: Libraries. (line 6) * requirements: Libraries. (line 6)
* REQ_KEY: The meta-protocol. (line 63) * REQ_KEY: The meta-protocol. (line 63)
* restart: tinc commands. (line 69)
* retry: tinc commands. (line 129)
* router: Main configuration variables. * router: Main configuration variables.
(line 227) (line 251)
* runtime options: Runtime options. (line 9) * runtime options: Runtime options. (line 9)
* scalability: tinc. (line 19) * scalability: tinc. (line 19)
* scripts: Scripts. (line 6) * scripts: Scripts. (line 6)
* server: How connections work. * server: How connections work.
(line 18) (line 18)
* set: tinc commands. (line 16)
* shell: Controlling tinc. (line 11)
* signals: Signals. (line 6) * signals: Signals. (line 6)
* socks4: Main configuration variables. * socks4: Main configuration variables.
(line 314) (line 338)
* socks5: Main configuration variables. * socks5: Main configuration variables.
(line 319) (line 343)
* SPTPS: Simple Peer-to-Peer Security. * SPTPS: Simple Peer-to-Peer Security.
(line 6) (line 6)
* start: tinc commands. (line 63)
* stop: tinc commands. (line 66)
* StrictSubnets: Main configuration variables. * StrictSubnets: Main configuration variables.
(line 344) (line 368)
* Subnet: Host configuration variables. * Subnet: Host configuration variables.
(line 77) (line 79)
* SUBNET: Scripts. (line 79) * SUBNET: Scripts. (line 79)
* SVPN: Security. (line 11) * SVPN: Security. (line 11)
* switch: Main configuration variables. * switch: Main configuration variables.
(line 235) (line 259)
* TCP: The meta-connection. (line 10) * TCP: The meta-connection. (line 10)
* TCPonly: Host configuration variables. * TCPonly: Host configuration variables.
(line 106) (line 108)
* tinc: Introduction. (line 6) * tinc: Introduction. (line 6)
* TINC: Security. (line 6) * TINC: Security. (line 6)
* tinc-down: Scripts. (line 18) * tinc-down: Scripts. (line 18)
* tinc-up: Scripts. (line 10) * tinc-up: Scripts. (line 10)
* tinc-up <1>: Network interfaces. (line 19) * tinc-up <1>: Network interfaces. (line 19)
* tincd: tinc. (line 14) * tincd: tinc. (line 14)
* top: tinc commands. (line 139)
* top <1>: tinc top. (line 6)
* traditional VPNs: tinc. (line 19) * traditional VPNs: tinc. (line 19)
* tunifhead: Main configuration variables. * tunifhead: Main configuration variables.
(line 141) (line 153)
* TunnelServer: Main configuration variables. * TunnelServer: Main configuration variables.
(line 349) (line 375)
* tunnohead: Main configuration variables. * tunnohead: Main configuration variables.
(line 135) (line 147)
* UDP: The UDP tunnel. (line 30) * UDP: The UDP tunnel. (line 30)
* UDP <1>: Encryption of network packets. * UDP <1>: Encryption of network packets.
(line 11) (line 11)
* UDPRcvBuf: Main configuration variables. * UDPRcvBuf: Main configuration variables.
(line 356) (line 382)
* UDPSndBuf: Main configuration variables. * UDPSndBuf: Main configuration variables.
(line 361) (line 387)
* UML: Main configuration variables. * UML: Main configuration variables.
(line 117) (line 129)
* Universal tun/tap: Configuration of Linux kernels. * Universal tun/tap: Configuration of Linux kernels.
(line 6) (line 6)
* VDE: Main configuration variables. * VDE: Main configuration variables.
(line 122) (line 134)
* virtual: Virtual Private Networks. * virtual: Virtual Private Networks.
(line 18) (line 18)
* virtual network device: The UDP tunnel. (line 6) * virtual network device: The UDP tunnel. (line 6)
@ -3246,80 +3334,82 @@ Concept Index
(line 6) (line 6)
* vpnd: tinc. (line 6) * vpnd: tinc. (line 6)
* website: Contact information. (line 6) * website: Contact information. (line 6)
* Weight: Host configuration variables.
(line 115)
* WEIGHT: Scripts. (line 82) * WEIGHT: Scripts. (line 82)
* zlib: zlib. (line 6) * zlib: zlib. (line 6)
 
Tag Table: Tag Table:
Node: Top807 Node: Top808
Node: Introduction1127 Node: Introduction1128
Node: Virtual Private Networks1931 Node: Virtual Private Networks1932
Node: tinc3643 Node: tinc3644
Node: Supported platforms5155 Node: Supported platforms5156
Node: Preparations5851 Node: Preparations5852
Node: Configuring the kernel6107 Node: Configuring the kernel6108
Node: Configuration of Linux kernels6516 Node: Configuration of Linux kernels6517
Node: Configuration of FreeBSD kernels7365 Node: Configuration of FreeBSD kernels7366
Node: Configuration of OpenBSD kernels7830 Node: Configuration of OpenBSD kernels7831
Node: Configuration of NetBSD kernels8438 Node: Configuration of NetBSD kernels8439
Node: Configuration of Solaris kernels8840 Node: Configuration of Solaris kernels8841
Node: Configuration of Darwin (MacOS/X) kernels9501 Node: Configuration of Darwin (MacOS/X) kernels9502
Node: Configuration of Windows10190 Node: Configuration of Windows10191
Node: Libraries10703 Node: Libraries10704
Node: OpenSSL11121 Node: OpenSSL11140
Node: zlib13393 Node: zlib13412
Node: lzo14411 Node: lzo14430
Node: libcurses15401 Node: libcurses15420
Node: libreadline16311 Node: libreadline16330
Node: Installation17248 Node: Installation17267
Node: Building and installing tinc18257 Node: Building and installing tinc18276
Node: Darwin (MacOS/X) build environment18913 Node: Darwin (MacOS/X) build environment18932
Node: Cygwin (Windows) build environment19477 Node: Cygwin (Windows) build environment19496
Node: MinGW (Windows) build environment20061 Node: MinGW (Windows) build environment20080
Node: System files20579 Node: System files20598
Node: Device files20844 Node: Device files20863
Node: Other files21257 Node: Other files21276
Node: Configuration21870 Node: Configuration21889
Node: Configuration introduction22157 Node: Configuration introduction22176
Node: Multiple networks23678 Node: Multiple networks23697
Node: How connections work25046 Node: How connections work25065
Node: Configuration files27607 Node: Configuration files27626
Node: Main configuration variables29135 Node: Main configuration variables29258
Node: Host configuration variables45893 Node: Host configuration variables47397
Node: Scripts51364 Node: Scripts53256
Node: How to configure54765 Node: How to configure56657
Node: Network interfaces59241 Node: Network interfaces61141
Node: Example configuration61620 Node: Example configuration63520
Node: Running tinc66713 Node: Running tinc68619
Node: Runtime options67300 Node: Runtime options69206
Node: Signals70160 Node: Signals72066
Node: Debug levels71009 Node: Debug levels72915
Node: Solving problems71945 Node: Solving problems73851
Node: Error messages73371 Node: Error messages75277
Node: Sending bug reports77688 Node: Sending bug reports79594
Node: Controlling tinc78635 Node: Controlling tinc80541
Node: tinc runtime options79012 Node: tinc runtime options81287
Node: tinc environment variables79699 Node: tinc environment variables81974
Node: tinc commands80028 Node: tinc commands82303
Node: tinc examples85138 Node: tinc examples87567
Node: tinc top85701 Node: tinc top88129
Node: Technical information87286 Node: Technical information89714
Node: The connection87521 Node: The connection89949
Node: The UDP tunnel87833 Node: The UDP tunnel90261
Node: The meta-connection90878 Node: The meta-connection93306
Node: The meta-protocol92336 Node: The meta-protocol94764
Node: Security97319 Node: Security99747
Node: Legacy authentication protocol98656 Node: Legacy authentication protocol101084
Node: Simple Peer-to-Peer Security103273 Node: Simple Peer-to-Peer Security105701
Node: Encryption of network packets108933 Node: Encryption of network packets111346
Node: Security issues111562 Node: Security issues113975
Node: Platform specific information113297 Node: Platform specific information115710
Node: Interface configuration113525 Node: Interface configuration115938
Node: Routes115966 Node: Routes118379
Node: About us117877 Node: About us120290
Node: Contact information118052 Node: Contact information120465
Node: Authors118454 Node: Authors120867
Node: Concept Index118856 Node: Concept Index121269
 
End Tag Table End Tag Table

View file

@ -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-2013 Ivo Timmermans, Copyright @copyright{} 1998-2014 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-2013 Ivo Timmermans, Copyright @copyright{} 1998-2014 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>.
@ -335,9 +335,10 @@ 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, Before you can configure or build tinc, you need to have the OpenSSL, zlib,
zlib and lzo libraries installed on your system. If you try to configure tinc without lzo, curses and readline libraries installed on your system. If you try to
having them installed, configure will give you an error message, and stop. configure tinc without having them installed, configure will give you an error
message, and stop.
@menu @menu
* OpenSSL:: * OpenSSL::
@ -793,6 +794,9 @@ The actual configuration of the daemon is done in the file
@file{@value{sysconfdir}/tinc/@var{netname}/tinc.conf} and at least one other file in the directory @file{@value{sysconfdir}/tinc/@var{netname}/tinc.conf} and at least one other file in the directory
@file{@value{sysconfdir}/tinc/@var{netname}/hosts/}. @file{@value{sysconfdir}/tinc/@var{netname}/hosts/}.
An optionnal directory @file{@value{sysconfdir}/tinc/@var{netname}/conf.d} can be added from which
any .conf file will be read.
These file consists of comments (lines started with a #) or assignments These file consists of comments (lines started with a #) or assignments
in the form of in the form of
@ -839,23 +843,16 @@ If any is selected, then depending on the operating system
both IPv4 and IPv6 or just IPv6 listening sockets will be created. both IPv4 and IPv6 or just IPv6 listening sockets will be created.
@cindex AutoConnect @cindex AutoConnect
@item AutoConnect = <count> (0) [experimental] @item AutoConnect = <yes|no> (no) [experimental]
If set to a non-zero value, If set to yes, tinc will automatically set up meta connections to other nodes,
tinc will try to only have count meta connections to other nodes, without requiring @var{ConnectTo} variables.
by automatically making or breaking connections to known nodes.
Higher values increase redundancy but also increase meta data overhead.
When using this option, a good value is 3.
@cindex BindToAddress @cindex BindToAddress
@item BindToAddress = <@var{address}> [<@var{port}>] @item BindToAddress = <@var{address}> [<@var{port}>]
If your computer has more than one IPv4 or IPv6 address, tinc This is the same as ListenAddress, however the address given with the BindToAddress option
will by default listen on all of them for incoming connections. will also be used for outgoing connections.
Multiple BindToAddress variables may be specified, This is useful if your computer has more than one IPv4 or IPv6 address,
in which case listening sockets for each specified address are made. and you want tinc to only use a specific one for outgoing packets.
If no @var{port} is specified, the socket will be bound to the port specified by the Port option,
or to port 655 if neither is given.
To only bind to a specific port but not to a specific address, use "*" for the @var{address}.
@cindex BindToInterface @cindex BindToInterface
@item BindToInterface = <@var{interface}> [experimental] @item BindToInterface = <@var{interface}> [experimental]
@ -887,6 +884,18 @@ Broadcast packets received from other nodes are never forwarded.
If the IndirectData option is also set, broadcast packets will only be sent to nodes which we have a meta connection to. If the IndirectData option is also set, broadcast packets will only be sent to nodes which we have a meta connection to.
@end table @end table
@cindex BroadcastSubnet
@item BroadcastSubnet = @var{address}[/@var{prefixlength}]
Declares a broadcast subnet.
Any packet with a destination address falling into such a subnet will be routed as a broadcast
(provided all nodes have it declared).
This is most useful to declare subnet broadcast addresses (e.g. 10.42.255.255),
otherwise tinc won't know what to do with them.
Note that global broadcast addresses (MAC ff:ff:ff:ff:ff:ff, IPv4 255.255.255.255),
as well as multicast space (IPv4 224.0.0.0/4, IPv6 ff00::/8)
are always considered broadcast addresses and don't need to be declared.
@cindex ConnectTo @cindex ConnectTo
@item ConnectTo = <@var{name}> @item ConnectTo = <@var{name}>
Specifies which other tinc daemon to connect to on startup. Specifies which other tinc daemon to connect to on startup.
@ -895,7 +904,7 @@ in which case outgoing connections to each specified tinc daemon are made.
The names should be known to this tinc daemon The names should be known to this tinc daemon
(i.e., there should be a host configuration file for the name on the ConnectTo line). (i.e., there should be a host configuration file for the name on the ConnectTo line).
If you don't specify a host with ConnectTo, If you don't specify a host with ConnectTo and don't enable AutoConnect,
tinc won't try to connect to other daemons at all, tinc won't try to connect to other daemons at all,
and will instead just listen for incoming connections. and will instead just listen for incoming connections.
@ -917,6 +926,13 @@ Under Windows, use @var{Interface} instead of @var{Device}.
Note that you can only use one device per daemon. Note that you can only use one device per daemon.
See also @ref{Device files}. See also @ref{Device files}.
@cindex DeviceStandby
@item DeviceStandby = <yes | no> (no)
When disabled, tinc calls @file{tinc-up} on startup, and @file{tinc-down} on shutdown.
When enabled, tinc will only call @file{tinc-up} when at least one node is reachable,
and will call @file{tinc-down} as soon as no nodes are reachable.
On Windows, this also determines when the virtual network interface "cable" is "plugged".
@cindex DeviceType @cindex DeviceType
@item DeviceType = <@var{type}> (platform dependent) @item DeviceType = <@var{type}> (platform dependent)
The type of the virtual network device. The type of the virtual network device.
@ -996,18 +1012,18 @@ but which would have to be forwarded by an intermediate node, are dropped instea
When combined with the IndirectData option, When combined with the IndirectData option,
packets for nodes for which we do not have a meta connection with are also dropped. packets for nodes for which we do not have a meta connection with are also dropped.
@cindex ECDSAPrivateKeyFile @cindex Ed25519PrivateKeyFile
@item ECDSAPrivateKeyFile = <@var{path}> (@file{@value{sysconfdir}/tinc/@var{netname}/ecdsa_key.priv}) @item Ed25519PrivateKeyFile = <@var{path}> (@file{@value{sysconfdir}/tinc/@var{netname}/ed25519_key.priv})
The file in which the private ECDSA key of this tinc daemon resides. The file in which the private Ed25519 key of this tinc daemon resides.
This is only used if ExperimentalProtocol is enabled. This is only used if ExperimentalProtocol is enabled.
@cindex ExperimentalProtocol @cindex ExperimentalProtocol
@item ExperimentalProtocol = <yes|no> (yes) @item ExperimentalProtocol = <yes|no> (yes)
When this option is enabled, the SPTPS protocol will be used when connecting to nodes that also support it. When this option is enabled, the SPTPS protocol will be used when connecting to nodes that also support it.
Ephemeral ECDH will be used for key exchanges, Ephemeral ECDH will be used for key exchanges,
and ECDSA will be used instead of RSA for authentication. and Ed25519 will be used instead of RSA for authentication.
When enabled, an ECDSA key must have been generated before with When enabled, an Ed25519 key must have been generated before with
@samp{tinc generate-ecdsa-keys}. @samp{tinc generate-ed25519-keys}.
@cindex Forwarding @cindex Forwarding
@item Forwarding = <off|internal|kernel> (internal) [experimental] @item Forwarding = <off|internal|kernel> (internal) [experimental]
@ -1046,6 +1062,18 @@ Depending on the operating system and the type of device this may or may not act
Under Windows, this variable is used to select which network interface will be used. Under Windows, this variable is used to select which network interface will be used.
If you specified a Device, this variable is almost always already correctly set. If you specified a Device, this variable is almost always already correctly set.
@cindex ListenAddress
@item ListenAddress = <@var{address}> [<@var{port}>]
If your computer has more than one IPv4 or IPv6 address, tinc
will by default listen on all of them for incoming connections.
This option can be used to restrict which addresses tinc listens on.
Multiple ListenAddress variables may be specified,
in which case listening sockets for each specified address are made.
If no @var{port} is specified, the socket will listen on the port specified by the Port option,
or to port 655 if neither is given.
To only listen on a specific port but not to a specific address, use "*" for the @var{address}.
@cindex LocalDiscovery @cindex LocalDiscovery
@item LocalDiscovery = <yes | no> (no) @item LocalDiscovery = <yes | no> (no)
When enabled, tinc will try to detect peers that are on the same local network. When enabled, tinc will try to detect peers that are on the same local network.
@ -1152,7 +1180,7 @@ When this option is used the priority of the tincd process will be adjusted.
Increasing the priority may help to reduce latency and packet loss on the VPN. Increasing the priority may help to reduce latency and packet loss on the VPN.
@cindex Proxy @cindex Proxy
@item Proxy = socks4 | socks4 | http | exec @var{...} [experimental] @item Proxy = socks4 | socks5 | http | exec @var{...} [experimental]
Use a proxy when making outgoing connections. Use a proxy when making outgoing connections.
The following proxy types are currently supported: The following proxy types are currently supported:
@ -1163,7 +1191,7 @@ Connects to the proxy using the SOCKS version 4 protocol.
Optionally, a @var{username} can be supplied which will be passed on to the proxy server. Optionally, a @var{username} can be supplied which will be passed on to the proxy server.
@cindex socks5 @cindex socks5
@item socks4 <@var{address}> <@var{port}> [<@var{username}> <@var{password}>] @item socks5 <@var{address}> <@var{port}> [<@var{username}> <@var{password}>]
Connect to the proxy using the SOCKS version 5 protocol. Connect to the proxy using the SOCKS version 5 protocol.
If a @var{username} and @var{password} are given, basic username/password authentication will be used, If a @var{username} and @var{password} are given, basic username/password authentication will be used,
otherwise no authentication will be used. otherwise no authentication will be used.
@ -1190,10 +1218,12 @@ pass all traffic, but leaves tinc vulnerable to replay-based attacks on your
traffic. traffic.
@cindex StrictSubnets @cindex StrictSubnets
@item StrictSubnets <yes|no> (no) [experimental] @item StrictSubnets = <yes|no> (no) [experimental]
When this option is enabled tinc will only use Subnet statements which are When this option is enabled tinc will only use Subnet statements which are
present in the host config files in the local present in the host config files in the local
@file{@value{sysconfdir}/tinc/@var{netname}/hosts/} directory. @file{@value{sysconfdir}/tinc/@var{netname}/hosts/} directory.
Subnets learned via connections to other nodes and which are not
present in the local host config files are ignored.
@cindex TunnelServer @cindex TunnelServer
@item TunnelServer = <yes|no> (no) [experimental] @item TunnelServer = <yes|no> (no) [experimental]
@ -1226,6 +1256,8 @@ This variable is only required if you want to connect to this host. It
must resolve to the external IP address where the host can be reached, must resolve to the external IP address where the host can be reached,
not the one that is internal to the VPN. not the one that is internal to the VPN.
If no port is specified, the default Port is used. If no port is specified, the default Port is used.
Multiple Address variables can be specified, in which case each address will be
tried until a working connection has been established.
@cindex Cipher @cindex Cipher
@item Cipher = <@var{cipher}> (blowfish) @item Cipher = <@var{cipher}> (blowfish)
@ -1336,6 +1368,12 @@ TCP connection instead of a UDP connection. This is especially useful
for those who want to run a tinc daemon from behind a masquerading for those who want to run a tinc daemon from behind a masquerading
firewall, or if UDP packet routing is disabled somehow. firewall, or if UDP packet routing is disabled somehow.
Setting this options also implicitly sets IndirectData. Setting this options also implicitly sets IndirectData.
@cindex Weight
@item Weight = <weight>
If this variable is set, it overrides the weight given to connections made with
another host. A higher weight means a lower priority is given to this
connection when broadcasting or forwarding packets.
@end table @end table
@ -1471,9 +1509,9 @@ In the configuration directory, it will create the file @file{tinc.conf} with th
Name = @var{name} Name = @var{name}
@end example @end example
It will also create private RSA and ECDSA keys, which will be stored in the files @file{rsa_key.priv} and @file{ecdsa_key.priv}. It will also create private RSA and Ed25519 keys, which will be stored in the files @file{rsa_key.priv} and @file{ed25519_key.priv}.
It will also create a host configuration file @file{hosts/@var{name}}, It will also create a host configuration file @file{hosts/@var{name}},
which will contain the corresponding public RSA and ECDSA keys. which will contain the corresponding public RSA and Ed25519 keys.
Finally, on UNIX operating systems, it will create an executable script @file{tinc-up}, Finally, on UNIX operating systems, it will create an executable script @file{tinc-up},
which will initially not do anything except warning that you should edit it. which will initially not do anything except warning that you should edit it.
@ -1492,7 +1530,7 @@ tinc -n @var{netname} add subnet 192.168.2.0/24
This will add a Subnet statement to your host configuration file. This will add a Subnet statement to your host configuration file.
Try opening the file @file{@value{sysconfdir}/tinc/@var{netname}/hosts/@var{name}} in an editor. Try opening the file @file{@value{sysconfdir}/tinc/@var{netname}/hosts/@var{name}} in an editor.
You should now see a file containing the public RSA and ECDSA keys (which looks like a bunch of random characters), You should now see a file containing the public RSA and Ed25519 keys (which looks like a bunch of random characters),
and the following line at the bottom: and the following line at the bottom:
@example @example
@ -1803,8 +1841,8 @@ Address = 4.5.6.7
A, B, C and D all have their own public/private keypairs: A, B, C and D all have their own public/private keypairs:
The private RSA key is stored in @file{@value{sysconfdir}/tinc/company/rsa_key.priv}, The private RSA key is stored in @file{@value{sysconfdir}/tinc/company/rsa_key.priv},
the private ECDSA key is stored in @file{@value{sysconfdir}/tinc/company/ecdsa_key.priv}, the private Ed25519 key is stored in @file{@value{sysconfdir}/tinc/company/ed25519_key.priv},
and the public RSA and ECDSA keys are put into the host configuration file in the @file{@value{sysconfdir}/tinc/company/hosts/} directory. and the public RSA and Ed25519 keys are put into the host configuration file in the @file{@value{sysconfdir}/tinc/company/hosts/} directory.
@subsubheading Starting @subsubheading Starting
@ -2146,13 +2184,21 @@ Be sure to include the following information in your bugreport:
@node Controlling tinc @node Controlling tinc
@chapter Controlling tinc @chapter Controlling tinc
You can control and inspect a running tincd through the tinc @cindex command line interface
You can start, stop, control and inspect a running tincd through the tinc
command. A quick example: command. A quick example:
@example @example
tinc -n @var{netname} reload tinc -n @var{netname} reload
@end example @end example
@cindex shell
If tinc is started without a command, it will act as a shell; it will display a
prompt, and commands can be entered on the prompt. If tinc is compiled with
libreadline, history and command completion are available on the prompt. One
can also pipe a script containing commands through tinc. In that case, lines
starting with a # symbol will be ignored.
@menu @menu
* tinc runtime options:: * tinc runtime options::
* tinc environment variables:: * tinc environment variables::
@ -2206,85 +2252,107 @@ the value of this environment variable is used.
@c from the manpage @c from the manpage
@table @code @table @code
@cindex init
@item init [@var{name}] @item init [@var{name}]
Create initial configuration files and RSA and ECDSA keypairs with default length. Create initial configuration files and RSA and Ed25519 keypairs with default length.
If no @var{name} for this node is given, it will be asked for. If no @var{name} for this node is given, it will be asked for.
@cindex get
@item get @var{variable} @item get @var{variable}
Print the current value of configuration variable @var{variable}. Print the current value of configuration variable @var{variable}.
If more than one variable with the same name exists, If more than one variable with the same name exists,
the value of each of them will be printed on a separate line. the value of each of them will be printed on a separate line.
@cindex set
@item set @var{variable} @var{value} @item set @var{variable} @var{value}
Set configuration variable @var{variable} to the given @var{value}. Set configuration variable @var{variable} to the given @var{value}.
All previously existing configuration variables with the same name are removed. All previously existing configuration variables with the same name are removed.
To set a variable for a specific host, use the notation @var{host}.@var{variable}. To set a variable for a specific host, use the notation @var{host}.@var{variable}.
@cindex add
@item add @var{variable} @var{value} @item add @var{variable} @var{value}
As above, but without removing any previously existing configuration variables. As above, but without removing any previously existing configuration variables.
@cindex del
@item del @var{variable} [@var{value}] @item del @var{variable} [@var{value}]
Remove configuration variables with the same name and @var{value}. Remove configuration variables with the same name and @var{value}.
If no @var{value} is given, all configuration variables with the same name will be removed. If no @var{value} is given, all configuration variables with the same name will be removed.
@cindex edit
@item edit @var{filename} @item edit @var{filename}
Start an editor for the given configuration file. Start an editor for the given configuration file.
You do not need to specify the full path to the file. You do not need to specify the full path to the file.
@cindex export
@item export @item export
Export the host configuration file of the local node to standard output. Export the host configuration file of the local node to standard output.
@cindex export-all
@item export-all @item export-all
Export all host configuration files to standard output. Export all host configuration files to standard output.
@cindex import
@item import [--force] @item import [--force]
Import host configuration file(s) generated by the tinc export command from standard input. Import host configuration file(s) generated by the tinc export command from standard input.
Already existing host configuration files are not overwritten unless the option --force is used. Already existing host configuration files are not overwritten unless the option --force is used.
@cindex exchange
@item exchange [--force] @item exchange [--force]
The same as export followed by import. The same as export followed by import.
@cindex exchange-all
@item exchange-all [--force] @item exchange-all [--force]
The same as export-all followed by import. The same as export-all followed by import.
@cindex invite
@item invite @var{name} @item invite @var{name}
Prepares an invitation for a new node with the given @var{name}, Prepares an invitation for a new node with the given @var{name},
and prints a short invitation URL that can be used with the join command. and prints a short invitation URL that can be used with the join command.
@cindex join
@item join [@var{URL}] @item join [@var{URL}]
Join an existing VPN using an invitation URL created using the invite command. Join an existing VPN using an invitation URL created using the invite command.
If no @var{URL} is given, it will be read from standard input. If no @var{URL} is given, it will be read from standard input.
@cindex start
@item start [tincd options] @item start [tincd options]
Start @samp{tincd}, optionally with the given extra options. Start @samp{tincd}, optionally with the given extra options.
@cindex stop
@item stop @item stop
Stop @samp{tincd}. Stop @samp{tincd}.
@cindex restart
@item restart [tincd options] @item restart [tincd options]
Restart @samp{tincd}, optionally with the given extra options. Restart @samp{tincd}, optionally with the given extra options.
@cindex reload
@item reload @item reload
Partially rereads configuration files. Connections to hosts whose host Partially rereads configuration files. Connections to hosts whose host
config files are removed are closed. New outgoing connections specified config files are removed are closed. New outgoing connections specified
in @file{tinc.conf} will be made. in @file{tinc.conf} will be made.
@cindex pid
@item pid @item pid
Shows the PID of the currently running @samp{tincd}. Shows the PID of the currently running @samp{tincd}.
@cindex generate-keys
@item generate-keys [@var{bits}] @item generate-keys [@var{bits}]
Generate both RSA and ECDSA keypairs (see below) and exit. Generate both RSA and Ed25519 keypairs (see below) and exit.
tinc will ask where you want to store the files, but will default to the tinc will ask where you want to store the files, but will default to the
configuration directory (you can use the -c or -n option). configuration directory (you can use the -c or -n option).
@item generate-ecdsa-keys @cindex generate-ed25519-keys
Generate public/private ECDSA keypair and exit. @item generate-ed25519-keys
Generate public/private Ed25519 keypair and exit.
@cindex generate-rsa-keys
@item generate-rsa-keys [@var{bits}] @item generate-rsa-keys [@var{bits}]
Generate public/private RSA keypair and exit. If @var{bits} is omitted, the Generate public/private RSA keypair and exit. If @var{bits} is omitted, the
default length will be 2048 bits. When saving keys to existing files, tinc default length will be 2048 bits. When saving keys to existing files, tinc
will not delete the old keys; you have to remove them manually. will not delete the old keys; you have to remove them manually.
@cindex dump
@item dump [reachable] nodes @item dump [reachable] nodes
Dump a list of all known nodes in the VPN. Dump a list of all known nodes in the VPN.
If the reachable keyword is used, only lists reachable nodes. If the reachable keyword is used, only lists reachable nodes.
@ -2298,26 +2366,32 @@ Dump a list of all known subnets in the VPN.
@item dump connections @item dump connections
Dump a list of all meta connections with ourself. Dump a list of all meta connections with ourself.
@cindex graph
@item dump graph | digraph @item dump graph | digraph
Dump a graph of the VPN in dotty format. Dump a graph of the VPN in dotty format.
Nodes are colored according to their reachability: Nodes are colored according to their reachability:
red nodes are unreachable, orange nodes are indirectly reachable, green nodes are directly reachable. red nodes are unreachable, orange nodes are indirectly reachable, green nodes are directly reachable.
Black nodes are either directly or indirectly reachable, but direct reachability has not been tried yet. Black nodes are either directly or indirectly reachable, but direct reachability has not been tried yet.
@cindex info
@item info @var{node} | @var{subnet} | @var{address} @item info @var{node} | @var{subnet} | @var{address}
Show information about a particular @var{node}, @var{subnet} or @var{address}. Show information about a particular @var{node}, @var{subnet} or @var{address}.
If an @var{address} is given, any matching subnet will be shown. If an @var{address} is given, any matching subnet will be shown.
@cindex purge
@item purge @item purge
Purges all information remembered about unreachable nodes. Purges all information remembered about unreachable nodes.
@cindex debug
@item debug @var{level} @item debug @var{level}
Sets debug level to @var{level}. Sets debug level to @var{level}.
@cindex log
@item log [@var{level}] @item log [@var{level}]
Capture log messages from a running tinc daemon. Capture log messages from a running tinc daemon.
An optional debug level can be given that will be applied only for log messages sent to tinc. An optional debug level can be given that will be applied only for log messages sent to tinc.
@cindex retry
@item retry @item retry
Forces tinc to try to connect to all uplinks immediately. Forces tinc to try to connect to all uplinks immediately.
Usually tinc attempts to do this itself, Usually tinc attempts to do this itself,
@ -2325,19 +2399,27 @@ but increases the time it waits between the attempts each time it failed,
and if tinc didn't succeed to connect to an uplink the first time after it started, and if tinc didn't succeed to connect to an uplink the first time after it started,
it defaults to the maximum time of 15 minutes. it defaults to the maximum time of 15 minutes.
@cindex disconnect
@item disconnect @var{node} @item disconnect @var{node}
Closes the meta connection with the given @var{node}. Closes the meta connection with the given @var{node}.
@cindex top
@item top @item top
If tinc is compiled with libcurses support, this will display live traffic statistics for all the known nodes, If tinc is compiled with libcurses support, this will display live traffic statistics for all the known nodes,
similar to the UNIX top command. similar to the UNIX top command.
See below for more information. See below for more information.
@cindex pcap
@item pcap @item pcap
Dump VPN traffic going through the local tinc node in pcap-savefile format to standard output, Dump VPN traffic going through the local tinc node in pcap-savefile format to standard output,
from where it can be redirected to a file or piped through a program that can parse it directly, from where it can be redirected to a file or piped through a program that can parse it directly,
such as tcpdump. such as tcpdump.
@cindex network [@var{netname}]
@item network
If @var{netname} is given, switch to that network.
Otherwise, display a list of all networks for which configuration files exist.
@end table @end table
@c ================================================================== @c ==================================================================
@ -2352,7 +2434,7 @@ tinc -n vpn pcap | tcpdump -r -
tinc -n vpn top tinc -n vpn top
@end example @end example
Example of configuring tinc using the tinc command: Examples of changing the configuration using tinc:
@example @example
tinc -n vpn init foo tinc -n vpn init foo
@ -2366,6 +2448,7 @@ tinc -n vpn export | gpg --clearsign | mail -s "My config" vpnmaster@@example.co
@node tinc top @node tinc top
@section tinc top @section tinc top
@cindex top
The top command connects to a running tinc daemon and repeatedly queries its per-node traffic counters. The top command connects to a running tinc daemon and repeatedly queries its per-node traffic counters.
It displays a list of all the known nodes in the left-most column, It displays a list of all the known nodes in the left-most column,
and the amount of bytes and packets read from and sent to each node in the other columns. and the amount of bytes and packets read from and sent to each node in the other columns.
@ -2946,12 +3029,12 @@ The expanded key is used as follows:
Where initiator_cipher_key is the key used by session initiator to encrypt Where initiator_cipher_key is the key used by session initiator to encrypt
messages sent to the responder. messages sent to the responder.
When using 521 bits EC keys, the AES-256-CTR cipher and HMAC-SHA-256 digest algorithm, When using 256 bits Ed25519 keys, the AES-256-CTR cipher and HMAC-SHA-256 digest algorithm,
the sizes are as follows: the sizes are as follows:
@example @example
ECDH_SIZE: 67 (= ceil(521/8) + 1) ECDH_SIZE: 32 (= 256/8)
ECDSA_SIZE: 141 (= 2 * ceil(521/8) + 9) ECDSA_SIZE: 64 (= 2 * 256/8)
CIPHER_KEYSIZE: 48 (= 256/8 + 128/8) CIPHER_KEYSIZE: 48 (= 256/8 + 128/8)
DIGEST_KEYSIZE: 32 (= 256/8) DIGEST_KEYSIZE: 32 (= 256/8)
@end example @end example

View file

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.14 from Makefile.am. # Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc. # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@ -83,9 +83,12 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(dist_bin_SCRIPTS) $(dist_bin_SCRIPTS)
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \ $(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \ $(top_srcdir)/m4/ax_check_link_flag.m4 \
$(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.ac $(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/libgcrypt.m4 \
$(top_srcdir)/m4/lzo.m4 $(top_srcdir)/m4/openssl.m4 \
$(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/zlib.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4) $(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d mkinstalldirs = $(install_sh) -d
@ -170,9 +173,6 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@ LDFLAGS = @LDFLAGS@
LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
LIBOBJS = @LIBOBJS@ LIBOBJS = @LIBOBJS@
LIBS = @LIBS@ LIBS = @LIBS@
LN_S = @LN_S@ LN_S = @LN_S@
@ -188,7 +188,6 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@ PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@ PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
READLINE_LIBS = @READLINE_LIBS@ READLINE_LIBS = @READLINE_LIBS@
SET_MAKE = @SET_MAKE@ SET_MAKE = @SET_MAKE@
SHELL = @SHELL@ SHELL = @SHELL@

View file

@ -1,7 +1,8 @@
#!/usr/bin/python #!/usr/bin/env python
# tinc-gui -- GUI for controlling a running tincd # tinc-gui -- GUI for controlling a running tincd
# Copyright (C) 2009-2012 Guus Sliepen <guus@tinc-vpn.org> # Copyright (C) 2009-2014 Guus Sliepen <guus@tinc-vpn.org>
# 2014 Dennis Joachimsthaler <dennis@efjot.de>
# #
# 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
@ -27,7 +28,7 @@ import time
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
if platform.system == 'Windows': if platform.system() == 'Windows':
import _winreg import _winreg
# Classes to interface with a running tinc daemon # Classes to interface with a running tinc daemon
@ -77,8 +78,8 @@ class Edge:
self.to = args[1] self.to = args[1]
self.address = args[2] self.address = args[2]
self.port = args[4] self.port = args[4]
self.options = int(args[5], 16) self.options = int(args[-2], 16)
self.weight = int(args[6]) self.weight = int(args[-1])
class Subnet: class Subnet:
def parse(self, args): def parse(self, args):
@ -130,7 +131,11 @@ class VPN:
else: else:
# otherwise connect via TCP # otherwise connect via TCP
print(unixfile + " does not exist."); print(unixfile + " does not exist.");
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) if ':' in info[2]:
af = socket.AF_INET6
else:
af = socket.AF_INET
s = socket.socket(af, socket.SOCK_STREAM)
s.connect((info[2], int(info[4]))) s.connect((info[2], int(info[4])))
self.sf = s.makefile() self.sf = s.makefile()
@ -187,6 +192,8 @@ class VPN:
subnet.parse(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)":
continue
self.nodes[subnet.owner].subnets[resp[2]] = subnet self.nodes[subnet.owner].subnets[resp[2]] = subnet
elif resp[1] == '6': elif resp[1] == '6':
if len(resp) < 9: if len(resp) < 9:
@ -233,10 +240,16 @@ class VPN:
return int(resp[2]) return int(resp[2])
def __init__(self, netname = None, pidfile = None): def __init__(self, netname = None, pidfile = None):
if platform.system == 'Windows': if platform.system() == 'Windows':
sam = _winreg.KEY_READ
if platform.machine().endswith('64'):
sam = sam | _winreg.KEY_WOW64_64KEY
try: try:
reg = _winreg.ConnectRegistry(None, HKEY_LOCAL_MACHINE) reg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
key = _winreg.OpenKey(reg, "SOFTWARE\\tinc") 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) VPN.confdir = _winreg.QueryValue(key, None)
except WindowsError: except WindowsError:
pass pass
@ -252,7 +265,7 @@ class VPN:
if pidfile != None: if pidfile != None:
self.pidfile = pidfile self.pidfile = pidfile
else: else:
if platform.system == 'Windows': if platform.system() == 'Windows':
self.pidfile = os.path.join(self.confbase, 'pid') self.pidfile = os.path.join(self.confbase, 'pid')
else: else:
if netname: if netname:
@ -524,7 +537,7 @@ class SubnetsPage(wx.Panel):
self.list.InsertStringItem(i, subnet.address + '/' + subnet.prefixlen) self.list.InsertStringItem(i, subnet.address + '/' + subnet.prefixlen)
else: else:
self.list.SetStringItem(i, 0, subnet.address + '/' + subnet.prefixlen) self.list.SetStringItem(i, 0, subnet.address + '/' + subnet.prefixlen)
self.list.SetStringItem(i, 1, subnet.weight) self.list.SetStringItem(i, 1, str(subnet.weight))
self.list.SetStringItem(i, 2, subnet.owner) self.list.SetStringItem(i, 2, subnet.owner)
self.list.itemDataMap[i] = (subnet.address + '/' + subnet.prefixlen, subnet.weight, subnet.owner) self.list.itemDataMap[i] = (subnet.address + '/' + subnet.prefixlen, subnet.weight, subnet.owner)
self.list.SetItemData(i, i) self.list.SetItemData(i, i)

View file

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.14 from Makefile.am. # Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc. # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@ -81,9 +81,12 @@ subdir = m4
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am README DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am README
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \ $(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \ $(top_srcdir)/m4/ax_check_link_flag.m4 \
$(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.ac $(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/libgcrypt.m4 \
$(top_srcdir)/m4/lzo.m4 $(top_srcdir)/m4/openssl.m4 \
$(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/zlib.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4) $(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d mkinstalldirs = $(install_sh) -d
@ -139,9 +142,6 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@ LDFLAGS = @LDFLAGS@
LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
LIBOBJS = @LIBOBJS@ LIBOBJS = @LIBOBJS@
LIBS = @LIBS@ LIBS = @LIBS@
LN_S = @LN_S@ LN_S = @LN_S@
@ -157,7 +157,6 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@ PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@ PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
READLINE_LIBS = @READLINE_LIBS@ READLINE_LIBS = @READLINE_LIBS@
SET_MAKE = @SET_MAKE@ SET_MAKE = @SET_MAKE@
SHELL = @SHELL@ SHELL = @SHELL@

View file

@ -0,0 +1,72 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS])
#
# DESCRIPTION
#
# Check whether the given FLAG works with the current language's compiler
# or gives an error. (Warnings, however, are ignored)
#
# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
# success/failure.
#
# If EXTRA-FLAGS is defined, it is added to the current language's default
# flags (e.g. CFLAGS) when the check is done. The check is thus made with
# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
# force the compiler to issue an error when a bad flag is given.
#
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
#
# LICENSE
#
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
#
# 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 3 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, see <http://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 2
AC_DEFUN([AX_CHECK_COMPILE_FLAG],
[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
_AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
[AS_VAR_SET(CACHEVAR,[yes])],
[AS_VAR_SET(CACHEVAR,[no])])
_AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes],
[m4_default([$2], :)],
[m4_default([$3], :)])
AS_VAR_POPDEF([CACHEVAR])dnl
])dnl AX_CHECK_COMPILE_FLAGS

71
m4/ax_check_link_flag.m4 Normal file
View file

@ -0,0 +1,71 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS])
#
# DESCRIPTION
#
# Check whether the given FLAG works with the linker or gives an error.
# (Warnings, however, are ignored)
#
# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
# success/failure.
#
# If EXTRA-FLAGS is defined, it is added to the linker's default flags
# when the check is done. The check is thus made with the flags: "LDFLAGS
# EXTRA-FLAGS FLAG". This can for example be used to force the linker to
# issue an error when a bad flag is given.
#
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG.
#
# LICENSE
#
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
#
# 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 3 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, see <http://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 2
AC_DEFUN([AX_CHECK_LINK_FLAG],
[AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl
AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [
ax_check_save_flags=$LDFLAGS
LDFLAGS="$LDFLAGS $4 $1"
AC_LINK_IFELSE([AC_LANG_PROGRAM()],
[AS_VAR_SET(CACHEVAR,[yes])],
[AS_VAR_SET(CACHEVAR,[no])])
LDFLAGS=$ax_check_save_flags])
AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes],
[m4_default([$2], :)],
[m4_default([$3], :)])
AS_VAR_POPDEF([CACHEVAR])dnl
])dnl AX_CHECK_LINK_FLAGS

View file

@ -31,9 +31,12 @@ AC_DEFUN([tinc_CURSES],
[AC_MSG_ERROR("curses header files not found."); break] [AC_MSG_ERROR("curses header files not found."); break]
) )
AC_CHECK_LIB(curses, initscr, AC_CHECK_LIB(ncurses, initscr,
[CURSES_LIBS="-lncurses"],
[AC_CHECK_LIB(curses, initscr,
[CURSES_LIBS="-lcurses"], [CURSES_LIBS="-lcurses"],
[AC_MSG_ERROR("curses libraries not found.")] [AC_MSG_ERROR("curses libraries not found.")]
)]
) )
]) ])

33
m4/libgcrypt.m4 Normal file
View file

@ -0,0 +1,33 @@
dnl Check to find the libgcrypt headers/libraries
AC_DEFUN([tinc_LIBGCRYPT],
[
AC_ARG_WITH(libgcrypt,
AS_HELP_STRING([--with-libgcrypt=DIR], [libgcrypt base directory, or:]),
[libgcrypt="$withval"
CPPFLAGS="$CPPFLAGS -I$withval/include"
LDFLAGS="$LDFLAGS -L$withval/lib"]
)
AC_ARG_WITH(libgcrypt-include,
AS_HELP_STRING([--with-libgcrypt-include=DIR], [libgcrypt headers directory (without trailing /libgcrypt)]),
[libgcrypt_include="$withval"
CPPFLAGS="$CPPFLAGS -I$withval"]
)
AC_ARG_WITH(libgcrypt-lib,
AS_HELP_STRING([--with-libgcrypt-lib=DIR], [libgcrypt library directory]),
[libgcrypt_lib="$withval"
LDFLAGS="$LDFLAGS -L$withval"]
)
AC_CHECK_HEADERS([gcrypt.h],
[],
[AC_MSG_ERROR([libgcrypt header files not found.]); break]
)
AC_CHECK_LIB(gcrypt, gcry_cipher_encrypt,
[LIBS="-lgcrypt $LIBS"],
[AC_MSG_ERROR([libgcrypt libraries not found.])]
)
])

View file

@ -35,7 +35,7 @@ AC_DEFUN([tinc_OPENSSL],
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 openssl/ecdh.h openssl/ec.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([OpenSSL header files not found.]); break]
) )
@ -45,11 +45,11 @@ AC_DEFUN([tinc_OPENSSL],
[AC_MSG_ERROR([OpenSSL libraries not found.])] [AC_MSG_ERROR([OpenSSL libraries not found.])]
) )
AC_CHECK_FUNCS([RAND_pseudo_bytes EVP_EncryptInit_ex ECDH_compute_key ECDSA_verify], , 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 OpenSSL functionality, make sure you have installed the latest version.]); break],
) )
AC_CHECK_DECL([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 OpenSSL functionality, make sure you have installed the latest version.]); break],
[#include <openssl/evp.h>] [#include <openssl/evp.h>]
) )

View file

@ -1,7 +1,7 @@
#! /bin/sh #! /bin/sh
# Common wrapper for a few potentially missing GNU programs. # Common wrapper for a few potentially missing GNU programs.
scriptversion=2012-06-26.16; # UTC scriptversion=2013-10-28.13; # UTC
# Copyright (C) 1996-2013 Free Software Foundation, Inc. # Copyright (C) 1996-2013 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996. # Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
@ -160,7 +160,7 @@ give_advice ()
;; ;;
autom4te*) autom4te*)
echo "You might have modified some maintainer files that require" echo "You might have modified some maintainer files that require"
echo "the 'automa4te' program to be rebuilt." echo "the 'autom4te' program to be rebuilt."
program_details 'autom4te' program_details 'autom4te'
;; ;;
bison*|yacc*) bison*|yacc*)

View file

@ -1,9 +1,36 @@
## Produce this file with automake to get Makefile.in ## Produce this file with automake to get Makefile.in
sbin_PROGRAMS = tincd tinc sptps_test sbin_PROGRAMS = tincd tinc sptps_test sptps_keypair
## Make sure version.c is always rebuilt
.PHONY: version.c
version.c:
if LINUX
sbin_PROGRAMS += sptps_speed
endif
DEFAULT_INCLUDES = DEFAULT_INCLUDES =
ed25519_SOURCES = \
ed25519/add_scalar.c \
ed25519/ed25519.h \
ed25519/fe.c ed25519/fe.h \
ed25519/fixedint.h \
ed25519/ge.c ed25519/ge.h \
ed25519/key_exchange.c \
ed25519/keypair.c \
ed25519/precomp_data.h \
ed25519/sc.c ed25519/sc.h \
ed25519/sha512.c ed25519/sha512.h \
ed25519/sign.c \
ed25519/verify.c
chacha_poly1305_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
tincd_SOURCES = \ tincd_SOURCES = \
buffer.c buffer.h \ buffer.c buffer.h \
cipher.h \ cipher.h \
@ -63,7 +90,10 @@ tincd_SOURCES = \
system.h \ system.h \
tincd.c \ tincd.c \
utils.c utils.h \ utils.c utils.h \
xalloc.h xalloc.h \
version.c version.h \
$(ed25519_SOURCES) \
$(chacha_poly1305_SOURCES)
tinc_SOURCES = \ tinc_SOURCES = \
dropin.c dropin.h \ dropin.c dropin.h \
@ -79,13 +109,31 @@ tinc_SOURCES = \
subnet_parse.c subnet.h \ subnet_parse.c subnet.h \
tincctl.c tincctl.h \ tincctl.c tincctl.h \
top.c top.h \ top.c top.h \
utils.c utils.h utils.c utils.h \
version.c version.h \
$(ed25519_SOURCES) \
$(chacha_poly1305_SOURCES)
sptps_test_SOURCES = \ sptps_test_SOURCES = \
logger.c logger.h \ logger.c logger.h \
sptps.c sptps.h \ sptps.c sptps.h \
sptps_test.c \ sptps_test.c \
utils.c utils.h utils.c utils.h \
$(ed25519_SOURCES) \
$(chacha_poly1305_SOURCES)
sptps_keypair_SOURCES = \
sptps_keypair.c \
utils.c utils.h \
$(ed25519_SOURCES)
sptps_speed_SOURCES = \
logger.c logger.h \
sptps.c sptps.h \
sptps_speed.c \
utils.c utils.h \
$(ed25519_SOURCES) \
$(chacha_poly1305_SOURCES)
## Conditionally compile device drivers ## Conditionally compile device drivers
@ -125,26 +173,35 @@ tincd_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/ecdh.c \ ed25519/ecdh.c \
openssl/ecdsa.c \ ed25519/ecdsa.c \
openssl/prf.c \ openssl/prf.c \
openssl/rsa.c openssl/rsa.c
tinc_SOURCES += \ 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/ecdh.c \ ed25519/ecdh.c \
openssl/ecdsa.c \ ed25519/ecdsa.c \
openssl/ecdsagen.c \ ed25519/ecdsagen.c \
openssl/prf.c \ openssl/prf.c \
openssl/rsa.c \ openssl/rsa.c \
openssl/rsagen.c openssl/rsagen.c
sptps_test_SOURCES += \ sptps_test_SOURCES += \
openssl/cipher.c \
openssl/crypto.c \ openssl/crypto.c \
openssl/digest.c openssl/digest.h \ openssl/digest.c openssl/digest.h \
openssl/ecdh.c \ ed25519/ecdh.c \
openssl/ecdsa.c \ ed25519/ecdsa.c \
openssl/prf.c
sptps_keypair_SOURCES += \
openssl/crypto.c \
ed25519/ecdsagen.c
sptps_speed_SOURCES += \
openssl/crypto.c \
openssl/digest.c openssl/digest.h \
ed25519/ecdh.c \
ed25519/ecdsa.c \
ed25519/ecdsagen.c \
openssl/prf.c openssl/prf.c
endif endif
@ -177,8 +234,9 @@ sptps_test_SOURCES += \
endif endif
tinc_LDADD = $(READLINE_LIBS) $(CURSES_LIBS) tinc_LDADD = $(READLINE_LIBS) $(CURSES_LIBS)
sptps_speed_LDADD = -lrt
LIBS = @LIBS@ @LIBGCRYPT_LIBS@ LIBS = @LIBS@
if TUNEMU if TUNEMU
LIBS += -lpcap LIBS += -lpcap

View file

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.14 from Makefile.am. # Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc. # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@ -78,44 +78,57 @@ PRE_UNINSTALL = :
POST_UNINSTALL = : POST_UNINSTALL = :
build_triplet = @build@ build_triplet = @build@
host_triplet = @host@ host_triplet = @host@
sbin_PROGRAMS = tincd$(EXEEXT) tinc$(EXEEXT) sptps_test$(EXEEXT) sbin_PROGRAMS = tincd$(EXEEXT) tinc$(EXEEXT) sptps_test$(EXEEXT) \
@LINUX_TRUE@am__append_1 = linux/device.c sptps_keypair$(EXEEXT) $(am__EXEEXT_1)
@BSD_TRUE@am__append_2 = bsd/device.c @LINUX_TRUE@am__append_1 = sptps_speed
@BSD_TRUE@@TUNEMU_TRUE@am__append_3 = bsd/tunemu.c bsd/tunemu.h @LINUX_TRUE@am__append_2 = linux/device.c
@SOLARIS_TRUE@am__append_4 = solaris/device.c @BSD_TRUE@am__append_3 = bsd/device.c
@MINGW_TRUE@am__append_5 = mingw/device.c mingw/common.h @BSD_TRUE@@TUNEMU_TRUE@am__append_4 = bsd/tunemu.c bsd/tunemu.h
@CYGWIN_TRUE@am__append_6 = cygwin/device.c @SOLARIS_TRUE@am__append_5 = solaris/device.c
@UML_TRUE@am__append_7 = uml_device.c @MINGW_TRUE@am__append_6 = mingw/device.c mingw/common.h
@VDE_TRUE@am__append_8 = vde_device.c @CYGWIN_TRUE@am__append_7 = cygwin/device.c
@OPENSSL_TRUE@am__append_9 = \ @UML_TRUE@am__append_8 = uml_device.c
@OPENSSL_TRUE@ openssl/cipher.c \ @VDE_TRUE@am__append_9 = vde_device.c
@OPENSSL_TRUE@ openssl/crypto.c \
@OPENSSL_TRUE@ openssl/digest.c openssl/digest.h \
@OPENSSL_TRUE@ openssl/ecdh.c \
@OPENSSL_TRUE@ openssl/ecdsa.c \
@OPENSSL_TRUE@ openssl/prf.c \
@OPENSSL_TRUE@ openssl/rsa.c
@OPENSSL_TRUE@am__append_10 = \ @OPENSSL_TRUE@am__append_10 = \
@OPENSSL_TRUE@ openssl/cipher.c \ @OPENSSL_TRUE@ openssl/cipher.c \
@OPENSSL_TRUE@ openssl/crypto.c \ @OPENSSL_TRUE@ openssl/crypto.c \
@OPENSSL_TRUE@ openssl/digest.c openssl/digest.h \ @OPENSSL_TRUE@ openssl/digest.c openssl/digest.h \
@OPENSSL_TRUE@ openssl/ecdh.c \ @OPENSSL_TRUE@ ed25519/ecdh.c \
@OPENSSL_TRUE@ openssl/ecdsa.c \ @OPENSSL_TRUE@ ed25519/ecdsa.c \
@OPENSSL_TRUE@ openssl/ecdsagen.c \
@OPENSSL_TRUE@ openssl/prf.c \ @OPENSSL_TRUE@ openssl/prf.c \
@OPENSSL_TRUE@ openssl/rsa.c \ @OPENSSL_TRUE@ openssl/rsa.c
@OPENSSL_TRUE@ openssl/rsagen.c
@OPENSSL_TRUE@am__append_11 = \ @OPENSSL_TRUE@am__append_11 = \
@OPENSSL_TRUE@ openssl/cipher.c \ @OPENSSL_TRUE@ openssl/cipher.c \
@OPENSSL_TRUE@ openssl/crypto.c \ @OPENSSL_TRUE@ openssl/crypto.c \
@OPENSSL_TRUE@ openssl/digest.c openssl/digest.h \ @OPENSSL_TRUE@ openssl/digest.c openssl/digest.h \
@OPENSSL_TRUE@ openssl/ecdh.c \ @OPENSSL_TRUE@ ed25519/ecdh.c \
@OPENSSL_TRUE@ openssl/ecdsa.c \ @OPENSSL_TRUE@ ed25519/ecdsa.c \
@OPENSSL_TRUE@ ed25519/ecdsagen.c \
@OPENSSL_TRUE@ openssl/prf.c \
@OPENSSL_TRUE@ openssl/rsa.c \
@OPENSSL_TRUE@ openssl/rsagen.c
@OPENSSL_TRUE@am__append_12 = \
@OPENSSL_TRUE@ openssl/crypto.c \
@OPENSSL_TRUE@ openssl/digest.c openssl/digest.h \
@OPENSSL_TRUE@ ed25519/ecdh.c \
@OPENSSL_TRUE@ ed25519/ecdsa.c \
@OPENSSL_TRUE@ openssl/prf.c @OPENSSL_TRUE@ openssl/prf.c
@GCRYPT_TRUE@am__append_12 = \ @OPENSSL_TRUE@am__append_13 = \
@OPENSSL_TRUE@ openssl/crypto.c \
@OPENSSL_TRUE@ ed25519/ecdsagen.c
@OPENSSL_TRUE@am__append_14 = \
@OPENSSL_TRUE@ openssl/crypto.c \
@OPENSSL_TRUE@ openssl/digest.c openssl/digest.h \
@OPENSSL_TRUE@ ed25519/ecdh.c \
@OPENSSL_TRUE@ ed25519/ecdsa.c \
@OPENSSL_TRUE@ ed25519/ecdsagen.c \
@OPENSSL_TRUE@ openssl/prf.c
@GCRYPT_TRUE@am__append_15 = \
@GCRYPT_TRUE@ gcrypt/cipher.c \ @GCRYPT_TRUE@ gcrypt/cipher.c \
@GCRYPT_TRUE@ gcrypt/crypto.c \ @GCRYPT_TRUE@ gcrypt/crypto.c \
@GCRYPT_TRUE@ gcrypt/digest.c gcrypt/digest.h \ @GCRYPT_TRUE@ gcrypt/digest.c gcrypt/digest.h \
@ -124,7 +137,7 @@ sbin_PROGRAMS = tincd$(EXEEXT) tinc$(EXEEXT) sptps_test$(EXEEXT)
@GCRYPT_TRUE@ gcrypt/prf.c \ @GCRYPT_TRUE@ gcrypt/prf.c \
@GCRYPT_TRUE@ gcrypt/rsa.c @GCRYPT_TRUE@ gcrypt/rsa.c
@GCRYPT_TRUE@am__append_13 = \ @GCRYPT_TRUE@am__append_16 = \
@GCRYPT_TRUE@ gcrypt/cipher.c \ @GCRYPT_TRUE@ gcrypt/cipher.c \
@GCRYPT_TRUE@ gcrypt/crypto.c \ @GCRYPT_TRUE@ gcrypt/crypto.c \
@GCRYPT_TRUE@ gcrypt/digest.c gcrypt/digest.h \ @GCRYPT_TRUE@ gcrypt/digest.c gcrypt/digest.h \
@ -135,7 +148,7 @@ sbin_PROGRAMS = tincd$(EXEEXT) tinc$(EXEEXT) sptps_test$(EXEEXT)
@GCRYPT_TRUE@ gcrypt/rsa.c \ @GCRYPT_TRUE@ gcrypt/rsa.c \
@GCRYPT_TRUE@ gcrypt/rsagen.c @GCRYPT_TRUE@ gcrypt/rsagen.c
@GCRYPT_TRUE@am__append_14 = \ @GCRYPT_TRUE@am__append_17 = \
@GCRYPT_TRUE@ gcrypt/cipher.c \ @GCRYPT_TRUE@ gcrypt/cipher.c \
@GCRYPT_TRUE@ gcrypt/crypto.c \ @GCRYPT_TRUE@ gcrypt/crypto.c \
@GCRYPT_TRUE@ gcrypt/digest.c gcrypt/digest.h \ @GCRYPT_TRUE@ gcrypt/digest.c gcrypt/digest.h \
@ -143,60 +156,120 @@ sbin_PROGRAMS = tincd$(EXEEXT) tinc$(EXEEXT) sptps_test$(EXEEXT)
@GCRYPT_TRUE@ gcrypt/ecdsa.c \ @GCRYPT_TRUE@ gcrypt/ecdsa.c \
@GCRYPT_TRUE@ gcrypt/prf.c @GCRYPT_TRUE@ gcrypt/prf.c
@TUNEMU_TRUE@am__append_15 = -lpcap @TUNEMU_TRUE@am__append_18 = -lpcap
subdir = src subdir = src
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/depcomp $(top_srcdir)/depcomp
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \ $(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \ $(top_srcdir)/m4/ax_check_link_flag.m4 \
$(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.ac $(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/libgcrypt.m4 \
$(top_srcdir)/m4/lzo.m4 $(top_srcdir)/m4/openssl.m4 \
$(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/zlib.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4) $(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES = CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES = CONFIG_CLEAN_VPATH_FILES =
@LINUX_TRUE@am__EXEEXT_1 = sptps_speed$(EXEEXT)
am__installdirs = "$(DESTDIR)$(sbindir)" am__installdirs = "$(DESTDIR)$(sbindir)"
PROGRAMS = $(sbin_PROGRAMS) PROGRAMS = $(sbin_PROGRAMS)
am__sptps_test_SOURCES_DIST = logger.c logger.h sptps.c sptps.h \ am__sptps_keypair_SOURCES_DIST = sptps_keypair.c utils.c utils.h \
sptps_test.c utils.c utils.h openssl/cipher.c openssl/crypto.c \ ed25519/add_scalar.c ed25519/ed25519.h ed25519/fe.c \
openssl/digest.c openssl/digest.h openssl/ecdh.c \ ed25519/fe.h ed25519/fixedint.h ed25519/ge.c ed25519/ge.h \
openssl/ecdsa.c openssl/prf.c gcrypt/cipher.c gcrypt/crypto.c \ ed25519/key_exchange.c ed25519/keypair.c \
gcrypt/digest.c gcrypt/digest.h gcrypt/ecdh.c gcrypt/ecdsa.c \ ed25519/precomp_data.h ed25519/sc.c ed25519/sc.h \
gcrypt/prf.c ed25519/sha512.c ed25519/sha512.h ed25519/sign.c \
ed25519/verify.c openssl/crypto.c ed25519/ecdsagen.c
am__dirstamp = $(am__leading_dot)dirstamp am__dirstamp = $(am__leading_dot)dirstamp
@OPENSSL_TRUE@am__objects_1 = openssl/cipher.$(OBJEXT) \ am__objects_1 = ed25519/add_scalar.$(OBJEXT) ed25519/fe.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/crypto.$(OBJEXT) \ ed25519/ge.$(OBJEXT) ed25519/key_exchange.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/digest.$(OBJEXT) openssl/ecdh.$(OBJEXT) \ ed25519/keypair.$(OBJEXT) ed25519/sc.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/ecdsa.$(OBJEXT) openssl/prf.$(OBJEXT) ed25519/sha512.$(OBJEXT) ed25519/sign.$(OBJEXT) \
@GCRYPT_TRUE@am__objects_2 = gcrypt/cipher.$(OBJEXT) \ ed25519/verify.$(OBJEXT)
@OPENSSL_TRUE@am__objects_2 = openssl/crypto.$(OBJEXT) \
@OPENSSL_TRUE@ ed25519/ecdsagen.$(OBJEXT)
am_sptps_keypair_OBJECTS = sptps_keypair.$(OBJEXT) utils.$(OBJEXT) \
$(am__objects_1) $(am__objects_2)
sptps_keypair_OBJECTS = $(am_sptps_keypair_OBJECTS)
sptps_keypair_LDADD = $(LDADD)
am__sptps_speed_SOURCES_DIST = logger.c logger.h sptps.c sptps.h \
sptps_speed.c utils.c utils.h ed25519/add_scalar.c \
ed25519/ed25519.h ed25519/fe.c ed25519/fe.h ed25519/fixedint.h \
ed25519/ge.c ed25519/ge.h ed25519/key_exchange.c \
ed25519/keypair.c ed25519/precomp_data.h ed25519/sc.c \
ed25519/sc.h ed25519/sha512.c ed25519/sha512.h ed25519/sign.c \
ed25519/verify.c 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 openssl/crypto.c openssl/digest.c \
openssl/digest.h ed25519/ecdh.c ed25519/ecdsa.c \
ed25519/ecdsagen.c openssl/prf.c
am__objects_3 = chacha-poly1305/chacha.$(OBJEXT) \
chacha-poly1305/chacha-poly1305.$(OBJEXT) \
chacha-poly1305/poly1305.$(OBJEXT)
@OPENSSL_TRUE@am__objects_4 = openssl/crypto.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/digest.$(OBJEXT) ed25519/ecdh.$(OBJEXT) \
@OPENSSL_TRUE@ ed25519/ecdsa.$(OBJEXT) \
@OPENSSL_TRUE@ ed25519/ecdsagen.$(OBJEXT) openssl/prf.$(OBJEXT)
am_sptps_speed_OBJECTS = logger.$(OBJEXT) sptps.$(OBJEXT) \
sptps_speed.$(OBJEXT) utils.$(OBJEXT) $(am__objects_1) \
$(am__objects_3) $(am__objects_4)
sptps_speed_OBJECTS = $(am_sptps_speed_OBJECTS)
sptps_speed_DEPENDENCIES =
am__sptps_test_SOURCES_DIST = logger.c logger.h sptps.c sptps.h \
sptps_test.c utils.c utils.h ed25519/add_scalar.c \
ed25519/ed25519.h ed25519/fe.c ed25519/fe.h ed25519/fixedint.h \
ed25519/ge.c ed25519/ge.h ed25519/key_exchange.c \
ed25519/keypair.c ed25519/precomp_data.h ed25519/sc.c \
ed25519/sc.h ed25519/sha512.c ed25519/sha512.h ed25519/sign.c \
ed25519/verify.c 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 openssl/crypto.c openssl/digest.c \
openssl/digest.h ed25519/ecdh.c ed25519/ecdsa.c openssl/prf.c \
gcrypt/cipher.c gcrypt/crypto.c gcrypt/digest.c \
gcrypt/digest.h gcrypt/ecdh.c gcrypt/ecdsa.c gcrypt/prf.c
@OPENSSL_TRUE@am__objects_5 = openssl/crypto.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/digest.$(OBJEXT) ed25519/ecdh.$(OBJEXT) \
@OPENSSL_TRUE@ ed25519/ecdsa.$(OBJEXT) openssl/prf.$(OBJEXT)
@GCRYPT_TRUE@am__objects_6 = gcrypt/cipher.$(OBJEXT) \
@GCRYPT_TRUE@ gcrypt/crypto.$(OBJEXT) gcrypt/digest.$(OBJEXT) \ @GCRYPT_TRUE@ gcrypt/crypto.$(OBJEXT) gcrypt/digest.$(OBJEXT) \
@GCRYPT_TRUE@ gcrypt/ecdh.$(OBJEXT) gcrypt/ecdsa.$(OBJEXT) \ @GCRYPT_TRUE@ gcrypt/ecdh.$(OBJEXT) gcrypt/ecdsa.$(OBJEXT) \
@GCRYPT_TRUE@ gcrypt/prf.$(OBJEXT) @GCRYPT_TRUE@ gcrypt/prf.$(OBJEXT)
am_sptps_test_OBJECTS = logger.$(OBJEXT) sptps.$(OBJEXT) \ am_sptps_test_OBJECTS = logger.$(OBJEXT) sptps.$(OBJEXT) \
sptps_test.$(OBJEXT) utils.$(OBJEXT) $(am__objects_1) \ sptps_test.$(OBJEXT) utils.$(OBJEXT) $(am__objects_1) \
$(am__objects_2) $(am__objects_3) $(am__objects_5) $(am__objects_6)
sptps_test_OBJECTS = $(am_sptps_test_OBJECTS) sptps_test_OBJECTS = $(am_sptps_test_OBJECTS)
sptps_test_LDADD = $(LDADD) sptps_test_LDADD = $(LDADD)
am__tinc_SOURCES_DIST = dropin.c dropin.h getopt.c getopt.h getopt1.c \ am__tinc_SOURCES_DIST = dropin.c dropin.h getopt.c getopt.h getopt1.c \
info.c info.h invitation.c invitation.h list.c list.h names.c \ 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 \ 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 \ subnet_parse.c subnet.h tincctl.c tincctl.h top.c top.h \
utils.c utils.h openssl/cipher.c openssl/crypto.c \ utils.c utils.h version.c version.h ed25519/add_scalar.c \
openssl/digest.c openssl/digest.h openssl/ecdh.c \ ed25519/ed25519.h ed25519/fe.c ed25519/fe.h ed25519/fixedint.h \
openssl/ecdsa.c openssl/ecdsagen.c openssl/prf.c openssl/rsa.c \ ed25519/ge.c ed25519/ge.h ed25519/key_exchange.c \
ed25519/keypair.c ed25519/precomp_data.h ed25519/sc.c \
ed25519/sc.h ed25519/sha512.c ed25519/sha512.h ed25519/sign.c \
ed25519/verify.c 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 openssl/cipher.c openssl/crypto.c \
openssl/digest.c openssl/digest.h ed25519/ecdh.c \
ed25519/ecdsa.c ed25519/ecdsagen.c openssl/prf.c openssl/rsa.c \
openssl/rsagen.c gcrypt/cipher.c gcrypt/crypto.c \ openssl/rsagen.c gcrypt/cipher.c gcrypt/crypto.c \
gcrypt/digest.c gcrypt/digest.h gcrypt/ecdh.c gcrypt/ecdsa.c \ gcrypt/digest.c gcrypt/digest.h gcrypt/ecdh.c gcrypt/ecdsa.c \
gcrypt/ecdsagen.c gcrypt/prf.c gcrypt/rsa.c gcrypt/rsagen.c gcrypt/ecdsagen.c gcrypt/prf.c gcrypt/rsa.c gcrypt/rsagen.c
@OPENSSL_TRUE@am__objects_3 = openssl/cipher.$(OBJEXT) \ @OPENSSL_TRUE@am__objects_7 = openssl/cipher.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/crypto.$(OBJEXT) \ @OPENSSL_TRUE@ openssl/crypto.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/digest.$(OBJEXT) openssl/ecdh.$(OBJEXT) \ @OPENSSL_TRUE@ openssl/digest.$(OBJEXT) ed25519/ecdh.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/ecdsa.$(OBJEXT) \ @OPENSSL_TRUE@ ed25519/ecdsa.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/ecdsagen.$(OBJEXT) openssl/prf.$(OBJEXT) \ @OPENSSL_TRUE@ ed25519/ecdsagen.$(OBJEXT) openssl/prf.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/rsa.$(OBJEXT) openssl/rsagen.$(OBJEXT) @OPENSSL_TRUE@ openssl/rsa.$(OBJEXT) openssl/rsagen.$(OBJEXT)
@GCRYPT_TRUE@am__objects_4 = gcrypt/cipher.$(OBJEXT) \ @GCRYPT_TRUE@am__objects_8 = gcrypt/cipher.$(OBJEXT) \
@GCRYPT_TRUE@ gcrypt/crypto.$(OBJEXT) gcrypt/digest.$(OBJEXT) \ @GCRYPT_TRUE@ gcrypt/crypto.$(OBJEXT) gcrypt/digest.$(OBJEXT) \
@GCRYPT_TRUE@ gcrypt/ecdh.$(OBJEXT) gcrypt/ecdsa.$(OBJEXT) \ @GCRYPT_TRUE@ gcrypt/ecdh.$(OBJEXT) gcrypt/ecdsa.$(OBJEXT) \
@GCRYPT_TRUE@ gcrypt/ecdsagen.$(OBJEXT) gcrypt/prf.$(OBJEXT) \ @GCRYPT_TRUE@ gcrypt/ecdsagen.$(OBJEXT) gcrypt/prf.$(OBJEXT) \
@ -205,8 +278,9 @@ am_tinc_OBJECTS = dropin.$(OBJEXT) getopt.$(OBJEXT) getopt1.$(OBJEXT) \
info.$(OBJEXT) invitation.$(OBJEXT) list.$(OBJEXT) \ info.$(OBJEXT) invitation.$(OBJEXT) list.$(OBJEXT) \
names.$(OBJEXT) netutl.$(OBJEXT) script.$(OBJEXT) \ names.$(OBJEXT) netutl.$(OBJEXT) script.$(OBJEXT) \
sptps.$(OBJEXT) subnet_parse.$(OBJEXT) tincctl.$(OBJEXT) \ sptps.$(OBJEXT) subnet_parse.$(OBJEXT) tincctl.$(OBJEXT) \
top.$(OBJEXT) utils.$(OBJEXT) $(am__objects_3) \ top.$(OBJEXT) utils.$(OBJEXT) version.$(OBJEXT) \
$(am__objects_4) $(am__objects_1) $(am__objects_3) $(am__objects_7) \
$(am__objects_8)
tinc_OBJECTS = $(am_tinc_OBJECTS) tinc_OBJECTS = $(am_tinc_OBJECTS)
am__DEPENDENCIES_1 = am__DEPENDENCIES_1 =
tinc_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) tinc_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
@ -225,28 +299,37 @@ am__tincd_SOURCES_DIST = buffer.c buffer.h cipher.h conf.c conf.h \
protocol_subnet.c raw_socket_device.c route.c route.h rsa.h \ protocol_subnet.c raw_socket_device.c route.c route.h rsa.h \
rsagen.h script.c script.h splay_tree.c splay_tree.h sptps.c \ rsagen.h script.c script.h splay_tree.c splay_tree.h sptps.c \
sptps.h subnet.c subnet.h subnet_parse.c system.h tincd.c \ sptps.h subnet.c subnet.h subnet_parse.c system.h tincd.c \
utils.c utils.h xalloc.h linux/device.c bsd/device.c \ utils.c utils.h xalloc.h version.c version.h \
ed25519/add_scalar.c ed25519/ed25519.h ed25519/fe.c \
ed25519/fe.h ed25519/fixedint.h ed25519/ge.c ed25519/ge.h \
ed25519/key_exchange.c ed25519/keypair.c \
ed25519/precomp_data.h ed25519/sc.c ed25519/sc.h \
ed25519/sha512.c ed25519/sha512.h ed25519/sign.c \
ed25519/verify.c 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 linux/device.c bsd/device.c \
bsd/tunemu.c bsd/tunemu.h solaris/device.c mingw/device.c \ bsd/tunemu.c bsd/tunemu.h solaris/device.c mingw/device.c \
mingw/common.h cygwin/device.c uml_device.c vde_device.c \ mingw/common.h cygwin/device.c uml_device.c vde_device.c \
openssl/cipher.c openssl/crypto.c openssl/digest.c \ openssl/cipher.c openssl/crypto.c openssl/digest.c \
openssl/digest.h openssl/ecdh.c openssl/ecdsa.c openssl/prf.c \ openssl/digest.h ed25519/ecdh.c ed25519/ecdsa.c openssl/prf.c \
openssl/rsa.c gcrypt/cipher.c gcrypt/crypto.c gcrypt/digest.c \ openssl/rsa.c gcrypt/cipher.c gcrypt/crypto.c gcrypt/digest.c \
gcrypt/digest.h gcrypt/ecdh.c gcrypt/ecdsa.c gcrypt/prf.c \ gcrypt/digest.h gcrypt/ecdh.c gcrypt/ecdsa.c gcrypt/prf.c \
gcrypt/rsa.c gcrypt/rsa.c
@LINUX_TRUE@am__objects_5 = linux/device.$(OBJEXT) @LINUX_TRUE@am__objects_9 = linux/device.$(OBJEXT)
@BSD_TRUE@am__objects_6 = bsd/device.$(OBJEXT) @BSD_TRUE@am__objects_10 = bsd/device.$(OBJEXT)
@BSD_TRUE@@TUNEMU_TRUE@am__objects_7 = bsd/tunemu.$(OBJEXT) @BSD_TRUE@@TUNEMU_TRUE@am__objects_11 = bsd/tunemu.$(OBJEXT)
@SOLARIS_TRUE@am__objects_8 = solaris/device.$(OBJEXT) @SOLARIS_TRUE@am__objects_12 = solaris/device.$(OBJEXT)
@MINGW_TRUE@am__objects_9 = mingw/device.$(OBJEXT) @MINGW_TRUE@am__objects_13 = mingw/device.$(OBJEXT)
@CYGWIN_TRUE@am__objects_10 = cygwin/device.$(OBJEXT) @CYGWIN_TRUE@am__objects_14 = cygwin/device.$(OBJEXT)
@UML_TRUE@am__objects_11 = uml_device.$(OBJEXT) @UML_TRUE@am__objects_15 = uml_device.$(OBJEXT)
@VDE_TRUE@am__objects_12 = vde_device.$(OBJEXT) @VDE_TRUE@am__objects_16 = vde_device.$(OBJEXT)
@OPENSSL_TRUE@am__objects_13 = openssl/cipher.$(OBJEXT) \ @OPENSSL_TRUE@am__objects_17 = openssl/cipher.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/crypto.$(OBJEXT) \ @OPENSSL_TRUE@ openssl/crypto.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/digest.$(OBJEXT) openssl/ecdh.$(OBJEXT) \ @OPENSSL_TRUE@ openssl/digest.$(OBJEXT) ed25519/ecdh.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/ecdsa.$(OBJEXT) openssl/prf.$(OBJEXT) \ @OPENSSL_TRUE@ ed25519/ecdsa.$(OBJEXT) openssl/prf.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/rsa.$(OBJEXT) @OPENSSL_TRUE@ openssl/rsa.$(OBJEXT)
@GCRYPT_TRUE@am__objects_14 = gcrypt/cipher.$(OBJEXT) \ @GCRYPT_TRUE@am__objects_18 = gcrypt/cipher.$(OBJEXT) \
@GCRYPT_TRUE@ gcrypt/crypto.$(OBJEXT) gcrypt/digest.$(OBJEXT) \ @GCRYPT_TRUE@ gcrypt/crypto.$(OBJEXT) gcrypt/digest.$(OBJEXT) \
@GCRYPT_TRUE@ gcrypt/ecdh.$(OBJEXT) gcrypt/ecdsa.$(OBJEXT) \ @GCRYPT_TRUE@ gcrypt/ecdh.$(OBJEXT) gcrypt/ecdsa.$(OBJEXT) \
@GCRYPT_TRUE@ gcrypt/prf.$(OBJEXT) gcrypt/rsa.$(OBJEXT) @GCRYPT_TRUE@ gcrypt/prf.$(OBJEXT) gcrypt/rsa.$(OBJEXT)
@ -265,10 +348,11 @@ am_tincd_OBJECTS = buffer.$(OBJEXT) conf.$(OBJEXT) \
raw_socket_device.$(OBJEXT) route.$(OBJEXT) script.$(OBJEXT) \ raw_socket_device.$(OBJEXT) route.$(OBJEXT) script.$(OBJEXT) \
splay_tree.$(OBJEXT) sptps.$(OBJEXT) subnet.$(OBJEXT) \ splay_tree.$(OBJEXT) sptps.$(OBJEXT) subnet.$(OBJEXT) \
subnet_parse.$(OBJEXT) tincd.$(OBJEXT) utils.$(OBJEXT) \ subnet_parse.$(OBJEXT) tincd.$(OBJEXT) utils.$(OBJEXT) \
$(am__objects_5) $(am__objects_6) $(am__objects_7) \ version.$(OBJEXT) $(am__objects_1) $(am__objects_3) \
$(am__objects_8) $(am__objects_9) $(am__objects_10) \ $(am__objects_9) $(am__objects_10) $(am__objects_11) \
$(am__objects_11) $(am__objects_12) $(am__objects_13) \ $(am__objects_12) $(am__objects_13) $(am__objects_14) \
$(am__objects_14) $(am__objects_15) $(am__objects_16) $(am__objects_17) \
$(am__objects_18)
tincd_OBJECTS = $(am_tincd_OBJECTS) tincd_OBJECTS = $(am_tincd_OBJECTS)
tincd_LDADD = $(LDADD) tincd_LDADD = $(LDADD)
AM_V_P = $(am__v_P_@AM_V@) AM_V_P = $(am__v_P_@AM_V@)
@ -298,9 +382,11 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 = am__v_CCLD_1 =
SOURCES = $(sptps_test_SOURCES) $(tinc_SOURCES) $(tincd_SOURCES) SOURCES = $(sptps_keypair_SOURCES) $(sptps_speed_SOURCES) \
DIST_SOURCES = $(am__sptps_test_SOURCES_DIST) $(am__tinc_SOURCES_DIST) \ $(sptps_test_SOURCES) $(tinc_SOURCES) $(tincd_SOURCES)
$(am__tincd_SOURCES_DIST) DIST_SOURCES = $(am__sptps_keypair_SOURCES_DIST) \
$(am__sptps_speed_SOURCES_DIST) $(am__sptps_test_SOURCES_DIST) \
$(am__tinc_SOURCES_DIST) $(am__tincd_SOURCES_DIST)
am__can_run_installinfo = \ am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \ case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \ n|no|NO) false;; \
@ -354,11 +440,8 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@ LDFLAGS = @LDFLAGS@
LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
LIBOBJS = @LIBOBJS@ LIBOBJS = @LIBOBJS@
LIBS = @LIBS@ @LIBGCRYPT_LIBS@ $(am__append_15) LIBS = @LIBS@ $(am__append_18)
LN_S = @LN_S@ LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@ LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@ MAKEINFO = @MAKEINFO@
@ -372,7 +455,6 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@ PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@ PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
READLINE_LIBS = @READLINE_LIBS@ READLINE_LIBS = @READLINE_LIBS@
SET_MAKE = @SET_MAKE@ SET_MAKE = @SET_MAKE@
SHELL = @SHELL@ SHELL = @SHELL@
@ -429,6 +511,25 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@ top_srcdir = @top_srcdir@
DEFAULT_INCLUDES = DEFAULT_INCLUDES =
ed25519_SOURCES = \
ed25519/add_scalar.c \
ed25519/ed25519.h \
ed25519/fe.c ed25519/fe.h \
ed25519/fixedint.h \
ed25519/ge.c ed25519/ge.h \
ed25519/key_exchange.c \
ed25519/keypair.c \
ed25519/precomp_data.h \
ed25519/sc.c ed25519/sc.h \
ed25519/sha512.c ed25519/sha512.h \
ed25519/sign.c \
ed25519/verify.c
chacha_poly1305_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
tincd_SOURCES = buffer.c buffer.h cipher.h conf.c conf.h connection.c \ tincd_SOURCES = buffer.c buffer.h cipher.h conf.c conf.h connection.c \
connection.h control.c control.h control_common.h crypto.h \ connection.h control.c control.h control_common.h crypto.h \
device.h digest.h dropin.c dropin.h dummy_device.c ecdh.h \ device.h digest.h dropin.c dropin.h dummy_device.c ecdh.h \
@ -444,18 +545,27 @@ tincd_SOURCES = buffer.c buffer.h cipher.h conf.c conf.h connection.c \
protocol_subnet.c raw_socket_device.c route.c route.h rsa.h \ protocol_subnet.c raw_socket_device.c route.c route.h rsa.h \
rsagen.h script.c script.h splay_tree.c splay_tree.h sptps.c \ rsagen.h script.c script.h splay_tree.c splay_tree.h sptps.c \
sptps.h subnet.c subnet.h subnet_parse.c system.h tincd.c \ sptps.h subnet.c subnet.h subnet_parse.c system.h tincd.c \
utils.c utils.h xalloc.h $(am__append_1) $(am__append_2) \ utils.c utils.h xalloc.h version.c version.h \
$(ed25519_SOURCES) $(chacha_poly1305_SOURCES) $(am__append_2) \
$(am__append_3) $(am__append_4) $(am__append_5) \ $(am__append_3) $(am__append_4) $(am__append_5) \
$(am__append_6) $(am__append_7) $(am__append_8) \ $(am__append_6) $(am__append_7) $(am__append_8) \
$(am__append_9) $(am__append_12) $(am__append_9) $(am__append_10) $(am__append_15)
tinc_SOURCES = dropin.c dropin.h getopt.c getopt.h getopt1.c info.c \ tinc_SOURCES = dropin.c dropin.h getopt.c getopt.h getopt1.c info.c \
info.h invitation.c invitation.h list.c list.h names.c names.h \ 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 \ 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 \ subnet_parse.c subnet.h tincctl.c tincctl.h top.c top.h \
utils.c utils.h $(am__append_10) $(am__append_13) utils.c utils.h version.c version.h $(ed25519_SOURCES) \
$(chacha_poly1305_SOURCES) $(am__append_11) $(am__append_16)
sptps_test_SOURCES = logger.c logger.h sptps.c sptps.h sptps_test.c \ sptps_test_SOURCES = logger.c logger.h sptps.c sptps.h sptps_test.c \
utils.c utils.h $(am__append_11) $(am__append_14) utils.c utils.h $(ed25519_SOURCES) $(chacha_poly1305_SOURCES) \
$(am__append_12) $(am__append_17)
sptps_keypair_SOURCES = sptps_keypair.c utils.c utils.h \
$(ed25519_SOURCES) $(am__append_13)
sptps_speed_SOURCES = logger.c logger.h sptps.c sptps.h sptps_speed.c \
utils.c utils.h $(ed25519_SOURCES) $(chacha_poly1305_SOURCES) \
$(am__append_14)
tinc_LDADD = $(READLINE_LIBS) $(CURSES_LIBS) tinc_LDADD = $(READLINE_LIBS) $(CURSES_LIBS)
sptps_speed_LDADD = -lrt
AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\" AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\"
all: all-am all: all-am
@ -549,24 +659,69 @@ installcheck-sbinPROGRAMS: $(sbin_PROGRAMS)
else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \ else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \
done; \ done; \
done; rm -f c$${pid}_.???; exit $$bad done; rm -f c$${pid}_.???; exit $$bad
ed25519/$(am__dirstamp):
@$(MKDIR_P) ed25519
@: > ed25519/$(am__dirstamp)
ed25519/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) ed25519/$(DEPDIR)
@: > ed25519/$(DEPDIR)/$(am__dirstamp)
ed25519/add_scalar.$(OBJEXT): ed25519/$(am__dirstamp) \
ed25519/$(DEPDIR)/$(am__dirstamp)
ed25519/fe.$(OBJEXT): ed25519/$(am__dirstamp) \
ed25519/$(DEPDIR)/$(am__dirstamp)
ed25519/ge.$(OBJEXT): ed25519/$(am__dirstamp) \
ed25519/$(DEPDIR)/$(am__dirstamp)
ed25519/key_exchange.$(OBJEXT): ed25519/$(am__dirstamp) \
ed25519/$(DEPDIR)/$(am__dirstamp)
ed25519/keypair.$(OBJEXT): ed25519/$(am__dirstamp) \
ed25519/$(DEPDIR)/$(am__dirstamp)
ed25519/sc.$(OBJEXT): ed25519/$(am__dirstamp) \
ed25519/$(DEPDIR)/$(am__dirstamp)
ed25519/sha512.$(OBJEXT): ed25519/$(am__dirstamp) \
ed25519/$(DEPDIR)/$(am__dirstamp)
ed25519/sign.$(OBJEXT): ed25519/$(am__dirstamp) \
ed25519/$(DEPDIR)/$(am__dirstamp)
ed25519/verify.$(OBJEXT): ed25519/$(am__dirstamp) \
ed25519/$(DEPDIR)/$(am__dirstamp)
openssl/$(am__dirstamp): openssl/$(am__dirstamp):
@$(MKDIR_P) openssl @$(MKDIR_P) openssl
@: > openssl/$(am__dirstamp) @: > openssl/$(am__dirstamp)
openssl/$(DEPDIR)/$(am__dirstamp): openssl/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) openssl/$(DEPDIR) @$(MKDIR_P) openssl/$(DEPDIR)
@: > openssl/$(DEPDIR)/$(am__dirstamp) @: > openssl/$(DEPDIR)/$(am__dirstamp)
openssl/cipher.$(OBJEXT): openssl/$(am__dirstamp) \
openssl/$(DEPDIR)/$(am__dirstamp)
openssl/crypto.$(OBJEXT): openssl/$(am__dirstamp) \ openssl/crypto.$(OBJEXT): openssl/$(am__dirstamp) \
openssl/$(DEPDIR)/$(am__dirstamp) openssl/$(DEPDIR)/$(am__dirstamp)
ed25519/ecdsagen.$(OBJEXT): ed25519/$(am__dirstamp) \
ed25519/$(DEPDIR)/$(am__dirstamp)
sptps_keypair$(EXEEXT): $(sptps_keypair_OBJECTS) $(sptps_keypair_DEPENDENCIES) $(EXTRA_sptps_keypair_DEPENDENCIES)
@rm -f sptps_keypair$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(sptps_keypair_OBJECTS) $(sptps_keypair_LDADD) $(LIBS)
chacha-poly1305/$(am__dirstamp):
@$(MKDIR_P) chacha-poly1305
@: > chacha-poly1305/$(am__dirstamp)
chacha-poly1305/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) chacha-poly1305/$(DEPDIR)
@: > chacha-poly1305/$(DEPDIR)/$(am__dirstamp)
chacha-poly1305/chacha.$(OBJEXT): chacha-poly1305/$(am__dirstamp) \
chacha-poly1305/$(DEPDIR)/$(am__dirstamp)
chacha-poly1305/chacha-poly1305.$(OBJEXT): \
chacha-poly1305/$(am__dirstamp) \
chacha-poly1305/$(DEPDIR)/$(am__dirstamp)
chacha-poly1305/poly1305.$(OBJEXT): chacha-poly1305/$(am__dirstamp) \
chacha-poly1305/$(DEPDIR)/$(am__dirstamp)
openssl/digest.$(OBJEXT): openssl/$(am__dirstamp) \ openssl/digest.$(OBJEXT): openssl/$(am__dirstamp) \
openssl/$(DEPDIR)/$(am__dirstamp) openssl/$(DEPDIR)/$(am__dirstamp)
openssl/ecdh.$(OBJEXT): openssl/$(am__dirstamp) \ ed25519/ecdh.$(OBJEXT): ed25519/$(am__dirstamp) \
openssl/$(DEPDIR)/$(am__dirstamp) ed25519/$(DEPDIR)/$(am__dirstamp)
openssl/ecdsa.$(OBJEXT): openssl/$(am__dirstamp) \ ed25519/ecdsa.$(OBJEXT): ed25519/$(am__dirstamp) \
openssl/$(DEPDIR)/$(am__dirstamp) ed25519/$(DEPDIR)/$(am__dirstamp)
openssl/prf.$(OBJEXT): openssl/$(am__dirstamp) \ openssl/prf.$(OBJEXT): openssl/$(am__dirstamp) \
openssl/$(DEPDIR)/$(am__dirstamp) openssl/$(DEPDIR)/$(am__dirstamp)
sptps_speed$(EXEEXT): $(sptps_speed_OBJECTS) $(sptps_speed_DEPENDENCIES) $(EXTRA_sptps_speed_DEPENDENCIES)
@rm -f sptps_speed$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(sptps_speed_OBJECTS) $(sptps_speed_LDADD) $(LIBS)
gcrypt/$(am__dirstamp): gcrypt/$(am__dirstamp):
@$(MKDIR_P) gcrypt @$(MKDIR_P) gcrypt
@: > gcrypt/$(am__dirstamp) @: > gcrypt/$(am__dirstamp)
@ -589,7 +744,7 @@ gcrypt/prf.$(OBJEXT): gcrypt/$(am__dirstamp) \
sptps_test$(EXEEXT): $(sptps_test_OBJECTS) $(sptps_test_DEPENDENCIES) $(EXTRA_sptps_test_DEPENDENCIES) sptps_test$(EXEEXT): $(sptps_test_OBJECTS) $(sptps_test_DEPENDENCIES) $(EXTRA_sptps_test_DEPENDENCIES)
@rm -f sptps_test$(EXEEXT) @rm -f sptps_test$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(sptps_test_OBJECTS) $(sptps_test_LDADD) $(LIBS) $(AM_V_CCLD)$(LINK) $(sptps_test_OBJECTS) $(sptps_test_LDADD) $(LIBS)
openssl/ecdsagen.$(OBJEXT): openssl/$(am__dirstamp) \ openssl/cipher.$(OBJEXT): openssl/$(am__dirstamp) \
openssl/$(DEPDIR)/$(am__dirstamp) openssl/$(DEPDIR)/$(am__dirstamp)
openssl/rsa.$(OBJEXT): openssl/$(am__dirstamp) \ openssl/rsa.$(OBJEXT): openssl/$(am__dirstamp) \
openssl/$(DEPDIR)/$(am__dirstamp) openssl/$(DEPDIR)/$(am__dirstamp)
@ -655,7 +810,9 @@ tincd$(EXEEXT): $(tincd_OBJECTS) $(tincd_DEPENDENCIES) $(EXTRA_tincd_DEPENDENCIE
mostlyclean-compile: mostlyclean-compile:
-rm -f *.$(OBJEXT) -rm -f *.$(OBJEXT)
-rm -f bsd/*.$(OBJEXT) -rm -f bsd/*.$(OBJEXT)
-rm -f chacha-poly1305/*.$(OBJEXT)
-rm -f cygwin/*.$(OBJEXT) -rm -f cygwin/*.$(OBJEXT)
-rm -f ed25519/*.$(OBJEXT)
-rm -f gcrypt/*.$(OBJEXT) -rm -f gcrypt/*.$(OBJEXT)
-rm -f linux/*.$(OBJEXT) -rm -f linux/*.$(OBJEXT)
-rm -f mingw/*.$(OBJEXT) -rm -f mingw/*.$(OBJEXT)
@ -704,6 +861,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/splay_tree.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/splay_tree.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sptps.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sptps.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sptps_keypair.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sptps_speed.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sptps_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sptps_test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnet.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnet.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnet_parse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnet_parse.Po@am__quote@
@ -713,9 +872,25 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uml_device.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uml_device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vde_device.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vde_device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@bsd/$(DEPDIR)/device.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@bsd/$(DEPDIR)/device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@bsd/$(DEPDIR)/tunemu.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@bsd/$(DEPDIR)/tunemu.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@chacha-poly1305/$(DEPDIR)/chacha-poly1305.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@chacha-poly1305/$(DEPDIR)/chacha.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@chacha-poly1305/$(DEPDIR)/poly1305.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@cygwin/$(DEPDIR)/device.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@cygwin/$(DEPDIR)/device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/add_scalar.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/ecdh.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/ecdsa.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/ecdsagen.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/fe.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/ge.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/key_exchange.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/keypair.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/sc.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/sha512.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/sign.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/verify.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/cipher.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/cipher.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/crypto.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/crypto.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/digest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/digest.Po@am__quote@
@ -730,9 +905,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/cipher.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/cipher.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/crypto.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/crypto.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/digest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/digest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/ecdh.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/ecdsa.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/ecdsagen.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/prf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/prf.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/rsa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/rsa.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/rsagen.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/rsagen.Po@am__quote@
@ -871,8 +1043,12 @@ distclean-generic:
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-rm -f bsd/$(DEPDIR)/$(am__dirstamp) -rm -f bsd/$(DEPDIR)/$(am__dirstamp)
-rm -f bsd/$(am__dirstamp) -rm -f bsd/$(am__dirstamp)
-rm -f chacha-poly1305/$(DEPDIR)/$(am__dirstamp)
-rm -f chacha-poly1305/$(am__dirstamp)
-rm -f cygwin/$(DEPDIR)/$(am__dirstamp) -rm -f cygwin/$(DEPDIR)/$(am__dirstamp)
-rm -f cygwin/$(am__dirstamp) -rm -f cygwin/$(am__dirstamp)
-rm -f ed25519/$(DEPDIR)/$(am__dirstamp)
-rm -f ed25519/$(am__dirstamp)
-rm -f gcrypt/$(DEPDIR)/$(am__dirstamp) -rm -f gcrypt/$(DEPDIR)/$(am__dirstamp)
-rm -f gcrypt/$(am__dirstamp) -rm -f gcrypt/$(am__dirstamp)
-rm -f linux/$(DEPDIR)/$(am__dirstamp) -rm -f linux/$(DEPDIR)/$(am__dirstamp)
@ -892,7 +1068,7 @@ clean: clean-am
clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am
distclean: distclean-am distclean: distclean-am
-rm -rf ./$(DEPDIR) bsd/$(DEPDIR) cygwin/$(DEPDIR) gcrypt/$(DEPDIR) linux/$(DEPDIR) mingw/$(DEPDIR) openssl/$(DEPDIR) solaris/$(DEPDIR) -rm -rf ./$(DEPDIR) bsd/$(DEPDIR) chacha-poly1305/$(DEPDIR) cygwin/$(DEPDIR) ed25519/$(DEPDIR) gcrypt/$(DEPDIR) linux/$(DEPDIR) mingw/$(DEPDIR) openssl/$(DEPDIR) solaris/$(DEPDIR)
-rm -f Makefile -rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \ distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags distclean-tags
@ -938,7 +1114,7 @@ install-ps-am:
installcheck-am: installcheck-sbinPROGRAMS installcheck-am: installcheck-sbinPROGRAMS
maintainer-clean: maintainer-clean-am maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR) bsd/$(DEPDIR) cygwin/$(DEPDIR) gcrypt/$(DEPDIR) linux/$(DEPDIR) mingw/$(DEPDIR) openssl/$(DEPDIR) solaris/$(DEPDIR) -rm -rf ./$(DEPDIR) bsd/$(DEPDIR) chacha-poly1305/$(DEPDIR) cygwin/$(DEPDIR) ed25519/$(DEPDIR) gcrypt/$(DEPDIR) linux/$(DEPDIR) mingw/$(DEPDIR) openssl/$(DEPDIR) solaris/$(DEPDIR)
-rm -f Makefile -rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic maintainer-clean-am: distclean-am maintainer-clean-generic
@ -973,6 +1149,9 @@ uninstall-am: uninstall-sbinPROGRAMS
uninstall-am uninstall-sbinPROGRAMS uninstall-am uninstall-sbinPROGRAMS
.PHONY: version.c
version.c:
# Tell versions [3.59,3.63) of GNU make to not export all variables. # Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded. # Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT: .NOEXPORT:

View file

@ -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-2013 Guus Sliepen <guus@tinc-vpn.org> 2001-2014 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
@ -35,7 +35,7 @@
#endif #endif
#define DEFAULT_TUN_DEVICE "/dev/tun0" #define DEFAULT_TUN_DEVICE "/dev/tun0"
#if defined(HAVE_FREEBSD) || defined(HAVE_NETBSD) #if defined(HAVE_DARWIN) || defined(HAVE_FREEBSD) || defined(HAVE_NETBSD)
#define DEFAULT_TAP_DEVICE "/dev/tap0" #define DEFAULT_TAP_DEVICE "/dev/tap0"
#else #else
#define DEFAULT_TAP_DEVICE "/dev/tun0" #define DEFAULT_TAP_DEVICE "/dev/tun0"
@ -54,8 +54,6 @@ int device_fd = -1;
char *device = NULL; char *device = NULL;
char *iface = NULL; char *iface = NULL;
static char *device_info = NULL; static char *device_info = NULL;
static uint64_t device_total_in = 0;
static uint64_t device_total_out = 0;
#if defined(ENABLE_TUNEMU) #if defined(ENABLE_TUNEMU)
static device_type_t device_type = DEVICE_TYPE_TUNEMU; static device_type_t device_type = DEVICE_TYPE_TUNEMU;
#elif defined(HAVE_OPENBSD) || defined(HAVE_FREEBSD) || defined(HAVE_DRAGONFLY) #elif defined(HAVE_OPENBSD) || defined(HAVE_FREEBSD) || defined(HAVE_DRAGONFLY)
@ -65,18 +63,9 @@ static device_type_t device_type = DEVICE_TYPE_TUN;
#endif #endif
static bool setup_device(void) { static bool setup_device(void) {
get_config_string(lookup_config(config_tree, "Device"), &device);
char *type; char *type;
if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
if(routing_mode == RMODE_ROUTER)
device = xstrdup(DEFAULT_TUN_DEVICE);
else
device = xstrdup(DEFAULT_TAP_DEVICE);
}
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
iface = xstrdup(strrchr(device, '/') ? strrchr(device, '/') + 1 : device);
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"))
/* use default */; /* use default */;
@ -95,10 +84,29 @@ static bool setup_device(void) {
return false; return false;
} }
} else { } else {
if(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(!device) {
if(device_type == DEVICE_TYPE_TAP)
device = xstrdup(DEFAULT_TAP_DEVICE);
else
device = xstrdup(DEFAULT_TUN_DEVICE);
}
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
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
case DEVICE_TYPE_TUNEMU: { case DEVICE_TYPE_TUNEMU: {
@ -199,9 +207,11 @@ static void close_device(void) {
default: default:
close(device_fd); close(device_fd);
} }
device_fd = -1;
free(device); free(device); device = NULL;
free(iface); free(iface); iface = NULL;
device_info = NULL;
} }
static bool read_packet(vpn_packet_t *packet) { static bool read_packet(vpn_packet_t *packet) {
@ -212,10 +222,10 @@ static bool read_packet(vpn_packet_t *packet) {
#ifdef ENABLE_TUNEMU #ifdef ENABLE_TUNEMU
case DEVICE_TYPE_TUNEMU: case DEVICE_TYPE_TUNEMU:
if(device_type == DEVICE_TYPE_TUNEMU) if(device_type == DEVICE_TYPE_TUNEMU)
inlen = tunemu_read(device_fd, packet->data + 14, MTU - 14); inlen = tunemu_read(device_fd, DATA(packet) + 14, MTU - 14);
else else
#endif #endif
inlen = read(device_fd, packet->data + 14, MTU - 14); inlen = read(device_fd, DATA(packet) + 14, MTU - 14);
if(inlen <= 0) { if(inlen <= 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,
@ -223,29 +233,29 @@ static bool read_packet(vpn_packet_t *packet) {
return false; return false;
} }
switch(packet->data[14] >> 4) { switch(DATA(packet)[14] >> 4) {
case 4: case 4:
packet->data[12] = 0x08; DATA(packet)[12] = 0x08;
packet->data[13] = 0x00; DATA(packet)[13] = 0x00;
break; break;
case 6: case 6:
packet->data[12] = 0x86; DATA(packet)[12] = 0x86;
packet->data[13] = 0xDD; DATA(packet)[13] = 0xDD;
break; break;
default: default:
logger(DEBUG_TRAFFIC, LOG_ERR, logger(DEBUG_TRAFFIC, LOG_ERR,
"Unknown IP version %d while reading packet from %s %s", "Unknown IP version %d while reading packet from %s %s",
packet->data[14] >> 4, device_info, device); DATA(packet)[14] >> 4, device_info, device);
return false; return false;
} }
memset(packet->data, 0, 12); memset(DATA(packet), 0, 12);
packet->len = inlen + 14; packet->len = inlen + 14;
break; break;
case DEVICE_TYPE_TUNIFHEAD: { case DEVICE_TYPE_TUNIFHEAD: {
u_int32_t type; u_int32_t type;
struct iovec vector[2] = {{&type, sizeof type}, {packet->data + 14, MTU - 14}}; struct iovec vector[2] = {{&type, sizeof type}, {DATA(packet) + 14, MTU - 14}};
if((inlen = readv(device_fd, vector, 2)) <= 0) { 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,
@ -255,13 +265,13 @@ static bool read_packet(vpn_packet_t *packet) {
switch (ntohl(type)) { switch (ntohl(type)) {
case AF_INET: case AF_INET:
packet->data[12] = 0x08; DATA(packet)[12] = 0x08;
packet->data[13] = 0x00; DATA(packet)[13] = 0x00;
break; break;
case AF_INET6: case AF_INET6:
packet->data[12] = 0x86; DATA(packet)[12] = 0x86;
packet->data[13] = 0xDD; DATA(packet)[13] = 0xDD;
break; break;
default: default:
@ -271,13 +281,13 @@ static bool read_packet(vpn_packet_t *packet) {
return false; return false;
} }
memset(packet->data, 0, 12); memset(DATA(packet), 0, 12);
packet->len = inlen + 10; packet->len = inlen + 10;
break; break;
} }
case DEVICE_TYPE_TAP: case DEVICE_TYPE_TAP:
if((inlen = read(device_fd, packet->data, MTU)) <= 0) { if((inlen = read(device_fd, DATA(packet), MTU)) <= 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;
@ -290,8 +300,6 @@ static bool read_packet(vpn_packet_t *packet) {
return false; return false;
} }
device_total_in += packet->len;
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s",
packet->len, device_info); packet->len, device_info);
@ -304,7 +312,7 @@ static bool write_packet(vpn_packet_t *packet) {
switch(device_type) { switch(device_type) {
case DEVICE_TYPE_TUN: case DEVICE_TYPE_TUN:
if(write(device_fd, packet->data + 14, packet->len - 14) < 0) { if(write(device_fd, DATA(packet) + 14, packet->len - 14) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info, logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info,
device, strerror(errno)); device, strerror(errno));
return false; return false;
@ -313,10 +321,10 @@ static bool write_packet(vpn_packet_t *packet) {
case DEVICE_TYPE_TUNIFHEAD: { case DEVICE_TYPE_TUNIFHEAD: {
u_int32_t type; u_int32_t type;
struct iovec vector[2] = {{&type, sizeof type}, {packet->data + 14, packet->len - 14}}; struct iovec vector[2] = {{&type, sizeof type}, {DATA(packet) + 14, packet->len - 14}};
int af; int af;
af = (packet->data[12] << 8) + packet->data[13]; af = (DATA(packet)[12] << 8) + DATA(packet)[13];
switch (af) { switch (af) {
case 0x0800: case 0x0800:
@ -341,7 +349,7 @@ static bool write_packet(vpn_packet_t *packet) {
} }
case DEVICE_TYPE_TAP: case DEVICE_TYPE_TAP:
if(write(device_fd, packet->data, packet->len) < 0) { if(write(device_fd, DATA(packet), packet->len) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info, logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info,
device, strerror(errno)); device, strerror(errno));
return false; return false;
@ -350,7 +358,7 @@ static bool write_packet(vpn_packet_t *packet) {
#ifdef ENABLE_TUNEMU #ifdef ENABLE_TUNEMU
case DEVICE_TYPE_TUNEMU: case DEVICE_TYPE_TUNEMU:
if(tunemu_write(device_fd, packet->data + 14, packet->len - 14) < 0) { if(tunemu_write(device_fd, DATA(packet) + 14, packet->len - 14) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info, logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info,
device, strerror(errno)); device, strerror(errno));
return false; return false;
@ -362,21 +370,12 @@ static bool write_packet(vpn_packet_t *packet) {
return false; return false;
} }
device_total_out += packet->len;
return true; return true;
} }
static void dump_device_stats(void) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "Statistics for %s %s:", device_info, device);
logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
}
const devops_t os_devops = { const devops_t os_devops = {
.setup = setup_device, .setup = setup_device,
.close = close_device, .close = close_device,
.read = read_packet, .read = read_packet,
.write = write_packet, .write = write_packet,
.dump_stats = dump_device_stats,
}; };

View file

@ -0,0 +1,103 @@
#include "../system.h"
#include "../cipher.h"
#include "../xalloc.h"
#include "chacha.h"
#include "chacha-poly1305.h"
#include "poly1305.h"
struct chacha_poly1305_ctx {
struct chacha_ctx main_ctx, header_ctx;
};
chacha_poly1305_ctx_t *chacha_poly1305_init(void)
{
chacha_poly1305_ctx_t *ctx = xzalloc(sizeof *ctx);
return ctx;
}
void chacha_poly1305_exit(chacha_poly1305_ctx_t *ctx)
{
free(ctx);
}
bool chacha_poly1305_set_key(chacha_poly1305_ctx_t *ctx, const void *key)
{
chacha_keysetup(&ctx->main_ctx, key, 256);
chacha_keysetup(&ctx->header_ctx, key + 32, 256);
return true;
}
static void put_u64(void *vp, uint64_t v)
{
uint8_t *p = (uint8_t *) vp;
p[0] = (uint8_t) (v >> 56) & 0xff;
p[1] = (uint8_t) (v >> 48) & 0xff;
p[2] = (uint8_t) (v >> 40) & 0xff;
p[3] = (uint8_t) (v >> 32) & 0xff;
p[4] = (uint8_t) (v >> 24) & 0xff;
p[5] = (uint8_t) (v >> 16) & 0xff;
p[6] = (uint8_t) (v >> 8) & 0xff;
p[7] = (uint8_t) v & 0xff;
}
bool chacha_poly1305_encrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen, void *outdata, size_t *outlen) {
uint8_t seqbuf[8];
const uint8_t one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */
uint8_t poly_key[POLY1305_KEYLEN];
/*
* Run ChaCha20 once to generate the Poly1305 key. The IV is the
* packet sequence number.
*/
memset(poly_key, 0, sizeof(poly_key));
put_u64(seqbuf, seqnr);
chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL);
chacha_encrypt_bytes(&ctx->main_ctx, poly_key, poly_key, sizeof(poly_key));
/* Set Chacha's block counter to 1 */
chacha_ivsetup(&ctx->main_ctx, seqbuf, one);
chacha_encrypt_bytes(&ctx->main_ctx, indata, outdata, inlen);
poly1305_auth(outdata + inlen, outdata, inlen, poly_key);
if (outlen)
*outlen = inlen + POLY1305_TAGLEN;
return true;
}
bool chacha_poly1305_decrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen, void *outdata, size_t *outlen) {
uint8_t seqbuf[8];
const uint8_t one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */
uint8_t expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN];
/*
* Run ChaCha20 once to generate the Poly1305 key. The IV is the
* packet sequence number.
*/
memset(poly_key, 0, sizeof(poly_key));
put_u64(seqbuf, seqnr);
chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL);
chacha_encrypt_bytes(&ctx->main_ctx, poly_key, poly_key, sizeof(poly_key));
/* Set Chacha's block counter to 1 */
chacha_ivsetup(&ctx->main_ctx, seqbuf, one);
/* Check tag before anything else */
inlen -= POLY1305_TAGLEN;
const uint8_t *tag = indata + inlen;
poly1305_auth(expected_tag, indata, inlen, poly_key);
if (memcmp(expected_tag, tag, POLY1305_TAGLEN))
return false;
chacha_encrypt_bytes(&ctx->main_ctx, indata, outdata, inlen);
if (outlen)
*outlen = inlen;
return true;
}

View file

@ -0,0 +1,15 @@
#ifndef CHACHA_POLY1305_H
#define CHACHA_POLY1305_H
#define CHACHA_POLY1305_KEYLEN 64
typedef struct chacha_poly1305_ctx chacha_poly1305_ctx_t;
extern chacha_poly1305_ctx_t *chacha_poly1305_init(void);
extern void chacha_poly1305_exit(chacha_poly1305_ctx_t *);
extern bool chacha_poly1305_set_key(chacha_poly1305_ctx_t *ctx, const void *key);
extern bool chacha_poly1305_encrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen, void *outdata, size_t *outlen);
extern bool chacha_poly1305_decrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen, void *outdata, size_t *outlen);
#endif //CHACHA_POLY1305_H

View file

@ -0,0 +1,215 @@
/*
chacha-merged.c version 20080118
D. J. Bernstein
Public domain.
*/
#include "../system.h"
#include "chacha.h"
typedef struct chacha_ctx chacha_ctx;
#define U8C(v) (v##U)
#define U32C(v) (v##U)
#define U8V(v) ((uint8_t)(v) & U8C(0xFF))
#define U32V(v) ((uint32_t)(v) & U32C(0xFFFFFFFF))
#define ROTL32(v, n) \
(U32V((v) << (n)) | ((v) >> (32 - (n))))
#define U8TO32_LITTLE(p) \
(((uint32_t)((p)[0]) ) | \
((uint32_t)((p)[1]) << 8) | \
((uint32_t)((p)[2]) << 16) | \
((uint32_t)((p)[3]) << 24))
#define U32TO8_LITTLE(p, v) \
do { \
(p)[0] = U8V((v) ); \
(p)[1] = U8V((v) >> 8); \
(p)[2] = U8V((v) >> 16); \
(p)[3] = U8V((v) >> 24); \
} while (0)
#define ROTATE(v,c) (ROTL32(v,c))
#define XOR(v,w) ((v) ^ (w))
#define PLUS(v,w) (U32V((v) + (w)))
#define PLUSONE(v) (PLUS((v),1))
#define QUARTERROUND(a,b,c,d) \
a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
static const char sigma[16] = "expand 32-byte k";
static const char tau[16] = "expand 16-byte k";
void chacha_keysetup(chacha_ctx *x, const uint8_t *k, uint32_t kbits)
{
const char *constants;
x->input[4] = U8TO32_LITTLE(k + 0);
x->input[5] = U8TO32_LITTLE(k + 4);
x->input[6] = U8TO32_LITTLE(k + 8);
x->input[7] = U8TO32_LITTLE(k + 12);
if (kbits == 256) { /* recommended */
k += 16;
constants = sigma;
} else { /* kbits == 128 */
constants = tau;
}
x->input[8] = U8TO32_LITTLE(k + 0);
x->input[9] = U8TO32_LITTLE(k + 4);
x->input[10] = U8TO32_LITTLE(k + 8);
x->input[11] = U8TO32_LITTLE(k + 12);
x->input[0] = U8TO32_LITTLE(constants + 0);
x->input[1] = U8TO32_LITTLE(constants + 4);
x->input[2] = U8TO32_LITTLE(constants + 8);
x->input[3] = U8TO32_LITTLE(constants + 12);
}
void chacha_ivsetup(chacha_ctx *x, const uint8_t *iv, const uint8_t *counter)
{
x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0);
x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4);
x->input[14] = U8TO32_LITTLE(iv + 0);
x->input[15] = U8TO32_LITTLE(iv + 4);
}
void
chacha_encrypt_bytes(chacha_ctx *x, const uint8_t *m, uint8_t *c, uint32_t bytes)
{
uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
uint8_t *ctarget = NULL;
uint8_t tmp[64];
uint32_t i;
if (!bytes)
return;
j0 = x->input[0];
j1 = x->input[1];
j2 = x->input[2];
j3 = x->input[3];
j4 = x->input[4];
j5 = x->input[5];
j6 = x->input[6];
j7 = x->input[7];
j8 = x->input[8];
j9 = x->input[9];
j10 = x->input[10];
j11 = x->input[11];
j12 = x->input[12];
j13 = x->input[13];
j14 = x->input[14];
j15 = x->input[15];
for (;;) {
if (bytes < 64) {
for (i = 0; i < bytes; ++i)
tmp[i] = m[i];
m = tmp;
ctarget = c;
c = tmp;
}
x0 = j0;
x1 = j1;
x2 = j2;
x3 = j3;
x4 = j4;
x5 = j5;
x6 = j6;
x7 = j7;
x8 = j8;
x9 = j9;
x10 = j10;
x11 = j11;
x12 = j12;
x13 = j13;
x14 = j14;
x15 = j15;
for (i = 20; i > 0; i -= 2) {
QUARTERROUND(x0, x4, x8, x12)
QUARTERROUND(x1, x5, x9, x13)
QUARTERROUND(x2, x6, x10, x14)
QUARTERROUND(x3, x7, x11, x15)
QUARTERROUND(x0, x5, x10, x15)
QUARTERROUND(x1, x6, x11, x12)
QUARTERROUND(x2, x7, x8, x13)
QUARTERROUND(x3, x4, x9, x14)
}
x0 = PLUS(x0, j0);
x1 = PLUS(x1, j1);
x2 = PLUS(x2, j2);
x3 = PLUS(x3, j3);
x4 = PLUS(x4, j4);
x5 = PLUS(x5, j5);
x6 = PLUS(x6, j6);
x7 = PLUS(x7, j7);
x8 = PLUS(x8, j8);
x9 = PLUS(x9, j9);
x10 = PLUS(x10, j10);
x11 = PLUS(x11, j11);
x12 = PLUS(x12, j12);
x13 = PLUS(x13, j13);
x14 = PLUS(x14, j14);
x15 = PLUS(x15, j15);
x0 = XOR(x0, U8TO32_LITTLE(m + 0));
x1 = XOR(x1, U8TO32_LITTLE(m + 4));
x2 = XOR(x2, U8TO32_LITTLE(m + 8));
x3 = XOR(x3, U8TO32_LITTLE(m + 12));
x4 = XOR(x4, U8TO32_LITTLE(m + 16));
x5 = XOR(x5, U8TO32_LITTLE(m + 20));
x6 = XOR(x6, U8TO32_LITTLE(m + 24));
x7 = XOR(x7, U8TO32_LITTLE(m + 28));
x8 = XOR(x8, U8TO32_LITTLE(m + 32));
x9 = XOR(x9, U8TO32_LITTLE(m + 36));
x10 = XOR(x10, U8TO32_LITTLE(m + 40));
x11 = XOR(x11, U8TO32_LITTLE(m + 44));
x12 = XOR(x12, U8TO32_LITTLE(m + 48));
x13 = XOR(x13, U8TO32_LITTLE(m + 52));
x14 = XOR(x14, U8TO32_LITTLE(m + 56));
x15 = XOR(x15, U8TO32_LITTLE(m + 60));
j12 = PLUSONE(j12);
if (!j12) {
j13 = PLUSONE(j13);
/* stopping at 2^70 bytes per nonce is user's responsibility */
}
U32TO8_LITTLE(c + 0, x0);
U32TO8_LITTLE(c + 4, x1);
U32TO8_LITTLE(c + 8, x2);
U32TO8_LITTLE(c + 12, x3);
U32TO8_LITTLE(c + 16, x4);
U32TO8_LITTLE(c + 20, x5);
U32TO8_LITTLE(c + 24, x6);
U32TO8_LITTLE(c + 28, x7);
U32TO8_LITTLE(c + 32, x8);
U32TO8_LITTLE(c + 36, x9);
U32TO8_LITTLE(c + 40, x10);
U32TO8_LITTLE(c + 44, x11);
U32TO8_LITTLE(c + 48, x12);
U32TO8_LITTLE(c + 52, x13);
U32TO8_LITTLE(c + 56, x14);
U32TO8_LITTLE(c + 60, x15);
if (bytes <= 64) {
if (bytes < 64) {
for (i = 0; i < bytes; ++i)
ctarget[i] = c[i];
}
x->input[12] = j12;
x->input[13] = j13;
return;
}
bytes -= 64;
c += 64;
m += 64;
}
}

View file

@ -0,0 +1,24 @@
/*
chacha-merged.c version 20080118
D. J. Bernstein
Public domain.
*/
#ifndef CHACHA_H
#define CHACHA_H
struct chacha_ctx {
uint32_t input[16];
};
#define CHACHA_MINKEYLEN 16
#define CHACHA_NONCELEN 8
#define CHACHA_CTRLEN 8
#define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN)
#define CHACHA_BLOCKLEN 64
void chacha_keysetup(struct chacha_ctx *x, const uint8_t *k, uint32_t kbits);
void chacha_ivsetup(struct chacha_ctx *x, const uint8_t *iv, const uint8_t *ctr);
void chacha_encrypt_bytes(struct chacha_ctx *x, const uint8_t *m, uint8_t * c, uint32_t bytes);
#endif /* CHACHA_H */

View file

@ -0,0 +1,197 @@
/*
* Public Domain poly1305 from Andrew Moon
* poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna
*/
#include "../system.h"
#include "poly1305.h"
#define mul32x32_64(a,b) ((uint64_t)(a) * (b))
#define U8TO32_LE(p) \
(((uint32_t)((p)[0])) | \
((uint32_t)((p)[1]) << 8) | \
((uint32_t)((p)[2]) << 16) | \
((uint32_t)((p)[3]) << 24))
#define U32TO8_LE(p, v) \
do { \
(p)[0] = (uint8_t)((v)); \
(p)[1] = (uint8_t)((v) >> 8); \
(p)[2] = (uint8_t)((v) >> 16); \
(p)[3] = (uint8_t)((v) >> 24); \
} while (0)
void
poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen, const unsigned char key[POLY1305_KEYLEN])
{
uint32_t t0, t1, t2, t3;
uint32_t h0, h1, h2, h3, h4;
uint32_t r0, r1, r2, r3, r4;
uint32_t s1, s2, s3, s4;
uint32_t b, nb;
size_t j;
uint64_t t[5];
uint64_t f0, f1, f2, f3;
uint32_t g0, g1, g2, g3, g4;
uint64_t c;
unsigned char mp[16];
/* clamp key */
t0 = U8TO32_LE(key + 0);
t1 = U8TO32_LE(key + 4);
t2 = U8TO32_LE(key + 8);
t3 = U8TO32_LE(key + 12);
/* precompute multipliers */
r0 = t0 & 0x3ffffff;
t0 >>= 26;
t0 |= t1 << 6;
r1 = t0 & 0x3ffff03;
t1 >>= 20;
t1 |= t2 << 12;
r2 = t1 & 0x3ffc0ff;
t2 >>= 14;
t2 |= t3 << 18;
r3 = t2 & 0x3f03fff;
t3 >>= 8;
r4 = t3 & 0x00fffff;
s1 = r1 * 5;
s2 = r2 * 5;
s3 = r3 * 5;
s4 = r4 * 5;
/* init state */
h0 = 0;
h1 = 0;
h2 = 0;
h3 = 0;
h4 = 0;
/* full blocks */
if (inlen < 16)
goto poly1305_donna_atmost15bytes;
poly1305_donna_16bytes:
m += 16;
inlen -= 16;
t0 = U8TO32_LE(m - 16);
t1 = U8TO32_LE(m - 12);
t2 = U8TO32_LE(m - 8);
t3 = U8TO32_LE(m - 4);
h0 += t0 & 0x3ffffff;
h1 += ((((uint64_t) t1 << 32) | t0) >> 26) & 0x3ffffff;
h2 += ((((uint64_t) t2 << 32) | t1) >> 20) & 0x3ffffff;
h3 += ((((uint64_t) t3 << 32) | t2) >> 14) & 0x3ffffff;
h4 += (t3 >> 8) | (1 << 24);
poly1305_donna_mul:
t[0] = mul32x32_64(h0, r0) + mul32x32_64(h1, s4) + mul32x32_64(h2, s3) + mul32x32_64(h3, s2) + mul32x32_64(h4, s1);
t[1] = mul32x32_64(h0, r1) + mul32x32_64(h1, r0) + mul32x32_64(h2, s4) + mul32x32_64(h3, s3) + mul32x32_64(h4, s2);
t[2] = mul32x32_64(h0, r2) + mul32x32_64(h1, r1) + mul32x32_64(h2, r0) + mul32x32_64(h3, s4) + mul32x32_64(h4, s3);
t[3] = mul32x32_64(h0, r3) + mul32x32_64(h1, r2) + mul32x32_64(h2, r1) + mul32x32_64(h3, r0) + mul32x32_64(h4, s4);
t[4] = mul32x32_64(h0, r4) + mul32x32_64(h1, r3) + mul32x32_64(h2, r2) + mul32x32_64(h3, r1) + mul32x32_64(h4, r0);
h0 = (uint32_t) t[0] & 0x3ffffff;
c = (t[0] >> 26);
t[1] += c;
h1 = (uint32_t) t[1] & 0x3ffffff;
b = (uint32_t) (t[1] >> 26);
t[2] += b;
h2 = (uint32_t) t[2] & 0x3ffffff;
b = (uint32_t) (t[2] >> 26);
t[3] += b;
h3 = (uint32_t) t[3] & 0x3ffffff;
b = (uint32_t) (t[3] >> 26);
t[4] += b;
h4 = (uint32_t) t[4] & 0x3ffffff;
b = (uint32_t) (t[4] >> 26);
h0 += b * 5;
if (inlen >= 16)
goto poly1305_donna_16bytes;
/* final bytes */
poly1305_donna_atmost15bytes:
if (!inlen)
goto poly1305_donna_finish;
for (j = 0; j < inlen; j++)
mp[j] = m[j];
mp[j++] = 1;
for (; j < 16; j++)
mp[j] = 0;
inlen = 0;
t0 = U8TO32_LE(mp + 0);
t1 = U8TO32_LE(mp + 4);
t2 = U8TO32_LE(mp + 8);
t3 = U8TO32_LE(mp + 12);
h0 += t0 & 0x3ffffff;
h1 += ((((uint64_t) t1 << 32) | t0) >> 26) & 0x3ffffff;
h2 += ((((uint64_t) t2 << 32) | t1) >> 20) & 0x3ffffff;
h3 += ((((uint64_t) t3 << 32) | t2) >> 14) & 0x3ffffff;
h4 += (t3 >> 8);
goto poly1305_donna_mul;
poly1305_donna_finish:
b = h0 >> 26;
h0 = h0 & 0x3ffffff;
h1 += b;
b = h1 >> 26;
h1 = h1 & 0x3ffffff;
h2 += b;
b = h2 >> 26;
h2 = h2 & 0x3ffffff;
h3 += b;
b = h3 >> 26;
h3 = h3 & 0x3ffffff;
h4 += b;
b = h4 >> 26;
h4 = h4 & 0x3ffffff;
h0 += b * 5;
b = h0 >> 26;
h0 = h0 & 0x3ffffff;
h1 += b;
g0 = h0 + 5;
b = g0 >> 26;
g0 &= 0x3ffffff;
g1 = h1 + b;
b = g1 >> 26;
g1 &= 0x3ffffff;
g2 = h2 + b;
b = g2 >> 26;
g2 &= 0x3ffffff;
g3 = h3 + b;
b = g3 >> 26;
g3 &= 0x3ffffff;
g4 = h4 + b - (1 << 26);
b = (g4 >> 31) - 1;
nb = ~b;
h0 = (h0 & nb) | (g0 & b);
h1 = (h1 & nb) | (g1 & b);
h2 = (h2 & nb) | (g2 & b);
h3 = (h3 & nb) | (g3 & b);
h4 = (h4 & nb) | (g4 & b);
f0 = ((h0) | (h1 << 26)) + (uint64_t) U8TO32_LE(&key[16]);
f1 = ((h1 >> 6) | (h2 << 20)) + (uint64_t) U8TO32_LE(&key[20]);
f2 = ((h2 >> 12) | (h3 << 14)) + (uint64_t) U8TO32_LE(&key[24]);
f3 = ((h3 >> 18) | (h4 << 8)) + (uint64_t) U8TO32_LE(&key[28]);
U32TO8_LE(&out[0], f0);
f1 += (f0 >> 32);
U32TO8_LE(&out[4], f1);
f2 += (f1 >> 32);
U32TO8_LE(&out[8], f2);
f3 += (f2 >> 32);
U32TO8_LE(&out[12], f3);
}

View file

@ -0,0 +1,16 @@
/* $OpenBSD: poly1305.h,v 1.2 2013/12/19 22:57:13 djm Exp $ */
/*
* Public Domain poly1305 from Andrew Moon
* poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna
*/
#ifndef POLY1305_H
#define POLY1305_H
#define POLY1305_KEYLEN 32
#define POLY1305_TAGLEN 16
void poly1305_auth(uint8_t out[POLY1305_TAGLEN], const uint8_t *m, size_t inlen, const uint8_t key[POLY1305_KEYLEN]);
#endif /* POLY1305_H */

View file

@ -34,11 +34,8 @@ extern size_t cipher_keylength(const cipher_t *);
extern void cipher_get_key(const cipher_t *, void *); extern void cipher_get_key(const cipher_t *, void *);
extern bool cipher_set_key(cipher_t *, void *, bool) __attribute__ ((__warn_unused_result__)); extern bool cipher_set_key(cipher_t *, void *, bool) __attribute__ ((__warn_unused_result__));
extern bool cipher_set_key_from_rsa(cipher_t *, void *, size_t, bool) __attribute__ ((__warn_unused_result__)); extern bool cipher_set_key_from_rsa(cipher_t *, void *, size_t, bool) __attribute__ ((__warn_unused_result__));
extern bool cipher_set_counter(cipher_t *, const void *, size_t) __attribute__ ((__warn_unused_result__));
extern bool cipher_set_counter_key(cipher_t *, void *) __attribute__ ((__warn_unused_result__));
extern bool cipher_encrypt(cipher_t *, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) __attribute__ ((__warn_unused_result__)); extern bool cipher_encrypt(cipher_t *, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) __attribute__ ((__warn_unused_result__));
extern bool cipher_decrypt(cipher_t *, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) __attribute__ ((__warn_unused_result__)); extern bool cipher_decrypt(cipher_t *, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) __attribute__ ((__warn_unused_result__));
extern bool cipher_counter_xor(cipher_t *, const void *indata, size_t inlen, void *outdata) __attribute__ ((__warn_unused_result__));
extern int cipher_get_nid(const cipher_t *); extern int cipher_get_nid(const cipher_t *);
extern bool cipher_active(const cipher_t *); extern bool cipher_active(const cipher_t *);

View file

@ -2,9 +2,10 @@
conf.c -- configuration code conf.c -- configuration code
Copyright (C) 1998 Robert van der Meulen Copyright (C) 1998 Robert van der Meulen
1998-2005 Ivo Timmermans 1998-2005 Ivo Timmermans
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
2010-2011 Julien Muchembled <jm@jmuchemb.eu>
2000 Cris van Pelt 2000 Cris van Pelt
2010-2011 Julien Muchembled <jm@jmuchemb.eu>
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
2013 Florent Clairambault <florent@clairambault.fr>
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
@ -376,6 +377,29 @@ bool read_server_config(void) {
errno = 0; errno = 0;
x = read_config_file(config_tree, fname); x = read_config_file(config_tree, fname);
// We will try to read the conf files in the "conf.d" dir
if (x) {
char * dname;
xasprintf(&dname, "%s" SLASH "conf.d", confbase);
DIR *dir = opendir (dname);
// If we can find this dir
if (dir) {
struct dirent *ep;
// We list all the files in it
while (x && (ep = readdir (dir))) {
size_t l = strlen(ep->d_name);
// And we try to read the ones that end with ".conf"
if (l > 5 && !strcmp(".conf", & ep->d_name[ l - 5 ])) {
free(fname);
xasprintf(&fname, "%s" SLASH "%s", dname, ep->d_name);
x = read_config_file(config_tree, fname);
}
}
closedir (dir);
}
free(dname);
}
if(!x && errno) if(!x && errno)
logger(DEBUG_ALWAYS, LOG_ERR, "Failed to read `%s': %s", fname, strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "Failed to read `%s': %s", fname, strerror(errno));

View file

@ -36,7 +36,7 @@
typedef struct connection_status_t { typedef struct connection_status_t {
unsigned int pinged:1; /* sent ping */ unsigned int pinged:1; /* sent ping */
unsigned int active:1; /* 1 if active.. */ unsigned int unused_active:1;
unsigned int connecting:1; /* 1 if we are waiting for a non-blocking connect() to finish */ unsigned int connecting:1; /* 1 if we are waiting for a non-blocking connect() to finish */
unsigned int unused_termreq:1; /* the termination of this connection was requested */ unsigned int unused_termreq:1; /* the termination of this connection was requested */
unsigned int remove_unused:1; /* Set to 1 if you want this connection removed */ unsigned int remove_unused:1; /* Set to 1 if you want this connection removed */
@ -49,7 +49,7 @@ typedef struct connection_status_t {
unsigned int log:1; /* 1 if this is a control connection requesting log dump */ unsigned int log:1; /* 1 if this is a control connection requesting log dump */
unsigned int invitation:1; /* 1 if this is an invitation */ unsigned int invitation:1; /* 1 if this is an invitation */
unsigned int invitation_used:1; /* 1 if the invitation has been consumed */ unsigned int invitation_used:1; /* 1 if the invitation has been consumed */
unsigned int unused:19; unsigned int unused:18;
} connection_status_t; } connection_status_t;
#include "ecdsa.h" #include "ecdsa.h"

View file

@ -106,7 +106,7 @@ bool control_h(connection_t *c, const char *request) {
for list_each(connection_t, other, connection_list) { for list_each(connection_t, other, connection_list) {
if(strcmp(other->name, name)) if(strcmp(other->name, name))
continue; continue;
terminate_connection(other, other->status.active); terminate_connection(other, other->edge);
found = true; found = true;
} }
@ -178,15 +178,15 @@ bool init_control(void) {
#ifndef HAVE_MINGW #ifndef HAVE_MINGW
int unix_fd = socket(AF_UNIX, SOCK_STREAM, 0); int unix_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if(unix_fd < 0) { if(unix_fd < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not create UNIX socket: %s", sockstrerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "Could not create UNIX socket: %s", sockstrerror(sockerrno));
return false; return false;
} }
struct sockaddr_un sun; struct sockaddr_un sa_un;
sun.sun_family = AF_UNIX; sa_un.sun_family = AF_UNIX;
strncpy(sun.sun_path, unixsocketname, sizeof sun.sun_path); strncpy(sa_un.sun_path, unixsocketname, sizeof sa_un.sun_path);
if(connect(unix_fd, (struct sockaddr *)&sun, sizeof sun) >= 0) { if(connect(unix_fd, (struct sockaddr *)&sa_un, sizeof sa_un) >= 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "UNIX socket %s is still in use!", unixsocketname); logger(DEBUG_ALWAYS, LOG_ERR, "UNIX socket %s is still in use!", unixsocketname);
return false; return false;
} }
@ -194,16 +194,16 @@ bool init_control(void) {
unlink(unixsocketname); unlink(unixsocketname);
umask(mask | 077); umask(mask | 077);
int result = bind(unix_fd, (struct sockaddr *)&sun, sizeof sun); int result = bind(unix_fd, (struct sockaddr *)&sa_un, sizeof sa_un);
umask(mask); umask(mask);
if(result < 0) { if(result < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not bind UNIX socket to %s: %s", unixsocketname, sockstrerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "Could not bind UNIX socket to %s: %s", unixsocketname, sockstrerror(sockerrno));
return false; return false;
} }
if(listen(unix_fd, 3) < 0) { if(listen(unix_fd, 3) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not listen on UNIX socket %s: %s", unixsocketname, sockstrerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "Could not listen on UNIX socket %s: %s", unixsocketname, sockstrerror(sockerrno));
return false; return false;
} }

View file

@ -1,7 +1,7 @@
/* /*
device.c -- Interaction with Windows tap driver in a Cygwin environment device.c -- Interaction with Windows tap driver in a Cygwin environment
Copyright (C) 2002-2005 Ivo Timmermans, Copyright (C) 2002-2005 Ivo Timmermans,
2002-2013 Guus Sliepen <guus@tinc-vpn.org> 2002-2014 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
@ -40,9 +40,6 @@ char *device = NULL;
char *iface = NULL; char *iface = NULL;
static char *device_info = NULL; static char *device_info = NULL;
static uint64_t device_total_in = 0;
static uint64_t device_total_out = 0;
static pid_t reader_pid; static pid_t reader_pid;
static int sp[2]; static int sp[2];
@ -218,18 +215,19 @@ static bool setup_device(void) {
static void close_device(void) { static void close_device(void) {
close(sp[0]); close(sp[0]);
close(sp[1]); close(sp[1]);
CloseHandle(device_handle); CloseHandle(device_handle); device_handle = INVALID_HANDLE_VALUE;
kill(reader_pid, SIGKILL); kill(reader_pid, SIGKILL);
free(device); free(device); device = NULL;
free(iface); free(iface); iface = NULL;
device_info = NULL;
} }
static bool read_packet(vpn_packet_t *packet) { static bool read_packet(vpn_packet_t *packet) {
int inlen; int inlen;
if((inlen = read(sp[0], packet->data, MTU)) <= 0) { if((inlen = read(sp[0], DATA(packet), MTU)) <= 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;
@ -237,8 +235,6 @@ static bool read_packet(vpn_packet_t *packet) {
packet->len = inlen; packet->len = inlen;
device_total_in += packet->len;
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len,
device_info); device_info);
@ -251,26 +247,17 @@ 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(!WriteFile (device_handle, packet->data, packet->len, &outlen, NULL)) { if(!WriteFile (device_handle, DATA(packet), packet->len, &outlen, NULL)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info, device, winerror(GetLastError())); logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info, device, winerror(GetLastError()));
return false; return false;
} }
device_total_out += packet->len;
return true; return true;
} }
static void dump_device_stats(void) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "Statistics for %s %s:", device_info, device);
logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
}
const devops_t os_devops = { const devops_t os_devops = {
.setup = setup_device, .setup = setup_device,
.close = close_device, .close = close_device,
.read = read_packet, .read = read_packet,
.write = write_packet, .write = write_packet,
.dump_stats = dump_device_stats,
}; };

View file

@ -27,17 +27,13 @@ extern int device_fd;
extern char *device; extern char *device;
extern char *iface; extern char *iface;
extern uint64_t device_in_packets;
extern uint64_t device_in_bytes;
extern uint64_t device_out_packets;
extern uint64_t device_out_bytes;
typedef struct devops_t { typedef struct devops_t {
bool (*setup)(void); bool (*setup)(void);
void (*close)(void); void (*close)(void);
bool (*read)(struct vpn_packet_t *); bool (*read)(struct vpn_packet_t *);
bool (*write)(struct vpn_packet_t *); bool (*write)(struct vpn_packet_t *);
void (*dump_stats)(void); void (*enable)(void); /* optional */
void (*disable)(void); /* optional */
} devops_t; } devops_t;
extern const devops_t os_devops; extern const devops_t os_devops;

View file

@ -25,9 +25,6 @@
static char *device_info = "dummy device"; static char *device_info = "dummy device";
static uint64_t device_total_in = 0;
static uint64_t device_total_out = 0;
static bool setup_device(void) { static bool setup_device(void) {
device = "dummy"; device = "dummy";
iface = "dummy"; iface = "dummy";
@ -43,20 +40,12 @@ static bool read_packet(vpn_packet_t *packet) {
} }
static bool write_packet(vpn_packet_t *packet) { static bool write_packet(vpn_packet_t *packet) {
device_total_out += packet->len;
return true; return true;
} }
static void dump_device_stats(void) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "Statistics for %s %s:", device_info, device);
logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
}
const devops_t dummy_devops = { const devops_t dummy_devops = {
.setup = setup_device, .setup = setup_device,
.close = close_device, .close = close_device,
.read = read_packet, .read = read_packet,
.write = write_packet, .write = write_packet,
.dump_stats = dump_device_stats,
}; };

View file

@ -20,8 +20,8 @@
#ifndef __TINC_ECDH_H__ #ifndef __TINC_ECDH_H__
#define __TINC_ECDH_H__ #define __TINC_ECDH_H__
#define ECDH_SIZE 67 #define ECDH_SIZE 32
#define ECDH_SHARED_SIZE 66 #define ECDH_SHARED_SIZE 32
#ifndef __TINC_ECDH_INTERNAL__ #ifndef __TINC_ECDH_INTERNAL__
typedef struct ecdh ecdh_t; typedef struct ecdh ecdh_t;

56
src/ed25519/add_scalar.c Normal file
View file

@ -0,0 +1,56 @@
#include "ed25519.h"
#include "ge.h"
#include "sc.h"
/* see http://crypto.stackexchange.com/a/6215/4697 */
void ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar) {
const unsigned char SC_1[32] = {1}; /* scalar with value 1 */
unsigned char n[32];
ge_p3 nB;
ge_p1p1 A_p1p1;
ge_p3 A;
ge_p3 public_key_unpacked;
ge_cached T;
int i;
/* copy the scalar and clear highest bit */
for (i = 0; i < 31; ++i) {
n[i] = scalar[i];
}
n[31] = scalar[31] & 127;
/* private key: a = n + t */
if (private_key) {
sc_muladd(private_key, SC_1, n, private_key);
}
/* public key: A = nB + T */
if (public_key) {
/* if we know the private key we don't need a point addition, which is faster */
/* using a "timing attack" you could find out wether or not we know the private
key, but this information seems rather useless - if this is important pass
public_key and private_key seperately in 2 function calls */
if (private_key) {
ge_scalarmult_base(&A, private_key);
} else {
/* unpack public key into T */
ge_frombytes_negate_vartime(&public_key_unpacked, public_key);
fe_neg(public_key_unpacked.X, public_key_unpacked.X); // undo negate
fe_neg(public_key_unpacked.T, public_key_unpacked.T); // undo negate
ge_p3_to_cached(&T, &public_key_unpacked);
/* calculate n*B */
ge_scalarmult_base(&nB, n);
/* A = n*B + T */
ge_add(&A_p1p1, &nB, &T);
ge_p1p1_to_p3(&A, &A_p1p1);
}
/* pack public key */
ge_p3_tobytes(public_key, &A);
}
}

51
src/ed25519/ecdh.c Normal file
View file

@ -0,0 +1,51 @@
/*
ecdh.c -- Diffie-Hellman key exchange 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 "ed25519.h"
#define __TINC_ECDH_INTERNAL__
typedef struct ecdh_t {
uint8_t private[64];
} ecdh_t;
#include "../crypto.h"
#include "../ecdh.h"
#include "../xalloc.h"
ecdh_t *ecdh_generate_public(void *pubkey) {
ecdh_t *ecdh = xzalloc(sizeof *ecdh);
uint8_t seed[32];
randomize(seed, sizeof seed);
ed25519_create_keypair(pubkey, ecdh->private, seed);
return ecdh;
}
bool ecdh_compute_shared(ecdh_t *ecdh, const void *pubkey, void *shared) {
ed25519_key_exchange(shared, pubkey, ecdh->private);
free(ecdh);
return true;
}
void ecdh_free(ecdh_t *ecdh) {
free(ecdh);
}

145
src/ed25519/ecdsa.c Normal file
View file

@ -0,0 +1,145 @@
/*
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 "ed25519.h"
#define __TINC_ECDSA_INTERNAL__
typedef struct {
uint8_t private[64];
uint8_t public[32];
} ecdsa_t;
#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) {
int len = strlen(p);
if(len != 43) {
logger(DEBUG_ALWAYS, LOG_ERR, "Invalid size %d for public key!", len);
return 0;
}
ecdsa_t *ecdsa = xzalloc(sizeof *ecdsa);
len = b64decode(p, ecdsa->public, len);
if(len != 32) {
logger(DEBUG_ALWAYS, LOG_ERR, "Invalid format of public key! len = %d", len);
free(ecdsa);
return 0;
}
return ecdsa;
}
char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa) {
char *base64 = xmalloc(44);
b64encode(ecdsa->public, base64, sizeof ecdsa->public);
return base64;
}
// Read PEM ECDSA keys
static bool read_pem(FILE *fp, const char *type, void *buf, size_t size) {
char line[1024];
bool data = false;
size_t typelen = strlen(type);
while(fgets(line, sizeof line, fp)) {
if(!data) {
if(strncmp(line, "-----BEGIN ", 11))
continue;
if(strncmp(line + 11, type, typelen))
continue;
data = true;
continue;
}
if(!strncmp(line, "-----END ", 9))
break;
size_t linelen = strcspn(line, "\r\n");
size_t len = b64decode(line, line, linelen);
if(!len) {
logger(DEBUG_ALWAYS, LOG_ERR, "Invalid base64 data in PEM file\n");
return false;
}
if(len > size) {
logger(DEBUG_ALWAYS, LOG_ERR, "Too much base64 data in PEM file\n");
return false;
}
memcpy(buf, line, len);
buf += len;
size -= len;
}
if(size) {
logger(DEBUG_ALWAYS, LOG_ERR, "Too little base64 data in PEM file\n");
return false;
}
return true;
}
ecdsa_t *ecdsa_read_pem_public_key(FILE *fp) {
ecdsa_t *ecdsa = xzalloc(sizeof *ecdsa);
if(read_pem(fp, "ED25519 PUBLIC KEY", ecdsa->public, sizeof ecdsa->public))
return ecdsa;
free(ecdsa);
return 0;
}
ecdsa_t *ecdsa_read_pem_private_key(FILE *fp) {
ecdsa_t *ecdsa = xmalloc(sizeof *ecdsa);
if(read_pem(fp, "ED25519 PRIVATE KEY", ecdsa->private, sizeof *ecdsa))
return ecdsa;
free(ecdsa);
return 0;
}
size_t ecdsa_size(ecdsa_t *ecdsa) {
return 64;
}
// TODO: standardise output format?
bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t len, void *sig) {
ed25519_sign(sig, in, len, ecdsa->public, ecdsa->private);
return true;
}
bool ecdsa_verify(ecdsa_t *ecdsa, const void *in, size_t len, const void *sig) {
return ed25519_verify(sig, in, len, ecdsa->public);
}
bool ecdsa_active(ecdsa_t *ecdsa) {
return ecdsa;
}
void ecdsa_free(ecdsa_t *ecdsa) {
free(ecdsa);
}

View file

@ -19,13 +19,15 @@
#include "../system.h" #include "../system.h"
#include <openssl/pem.h> #include "ed25519.h"
#include <openssl/err.h>
#include <openssl/obj_mac.h>
#define __TINC_ECDSA_INTERNAL__ #define __TINC_ECDSA_INTERNAL__
typedef EC_KEY ecdsa_t; typedef struct {
uint8_t private[64];
uint8_t public[32];
} ecdsa_t;
#include "../crypto.h"
#include "../ecdsagen.h" #include "../ecdsagen.h"
#include "../utils.h" #include "../utils.h"
#include "../xalloc.h" #include "../xalloc.h"
@ -33,38 +35,37 @@ typedef EC_KEY ecdsa_t;
// Generate ECDSA key // Generate ECDSA key
ecdsa_t *ecdsa_generate(void) { ecdsa_t *ecdsa_generate(void) {
ecdsa_t *ecdsa = EC_KEY_new_by_curve_name(NID_secp521r1); ecdsa_t *ecdsa = xzalloc(sizeof *ecdsa);
if(!ecdsa || !EC_KEY_generate_key(ecdsa)) { uint8_t seed[32];
fprintf(stderr, "Generating EC key failed: %s", ERR_error_string(ERR_get_error(), NULL)); randomize(seed, sizeof seed);
ecdsa_free(ecdsa); ed25519_create_keypair(ecdsa->public, ecdsa->private, seed);
return false;
}
EC_KEY_set_asn1_flag(ecdsa, OPENSSL_EC_NAMED_CURVE);
EC_KEY_set_conv_form(ecdsa, POINT_CONVERSION_COMPRESSED);
return ecdsa; return ecdsa;
} }
// Write PEM ECDSA keys // Write PEM ECDSA keys
static bool write_pem(FILE *fp, const char *type, void *buf, size_t size) {
fprintf(fp, "-----BEGIN %s-----\n", type);
char base64[65];
while(size) {
size_t todo = size > 48 ? 48 : size;
b64encode(buf, base64, todo);
fprintf(fp, "%s\n", base64);
buf += todo;
size -= todo;
}
fprintf(fp, "-----END %s-----\n", type);
return !ferror(fp);
}
bool ecdsa_write_pem_public_key(ecdsa_t *ecdsa, FILE *fp) { bool ecdsa_write_pem_public_key(ecdsa_t *ecdsa, FILE *fp) {
BIO *out = BIO_new(BIO_s_file()); return write_pem(fp, "ED25519 PUBLIC KEY", ecdsa->public, sizeof ecdsa->public);
if(!out)
return false;
BIO_set_fp(out, fp, BIO_NOCLOSE);
bool result = PEM_write_bio_EC_PUBKEY(out, ecdsa);
BIO_free(out);
return result;
} }
bool ecdsa_write_pem_private_key(ecdsa_t *ecdsa, FILE *fp) { bool ecdsa_write_pem_private_key(ecdsa_t *ecdsa, FILE *fp) {
BIO *out = BIO_new(BIO_s_file()); return write_pem(fp, "ED25519 PRIVATE KEY", ecdsa->private, sizeof *ecdsa);
if(!out)
return false;
BIO_set_fp(out, fp, BIO_NOCLOSE);
bool result = PEM_write_bio_ECPrivateKey(out, ecdsa, NULL, NULL, 0, NULL, NULL);
BIO_free(out);
return result;
} }

38
src/ed25519/ed25519.h Normal file
View file

@ -0,0 +1,38 @@
#ifndef ED25519_H
#define ED25519_H
#include <stddef.h>
#if defined(_WIN32)
#if defined(ED25519_BUILD_DLL)
#define ED25519_DECLSPEC __declspec(dllexport)
#elif defined(ED25519_DLL)
#define ED25519_DECLSPEC __declspec(dllimport)
#else
#define ED25519_DECLSPEC
#endif
#else
#define ED25519_DECLSPEC
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifndef ED25519_NO_SEED
int ED25519_DECLSPEC ed25519_create_seed(unsigned char *seed);
#endif
void ED25519_DECLSPEC ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed);
void ED25519_DECLSPEC ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key);
int ED25519_DECLSPEC ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *private_key);
void ED25519_DECLSPEC ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar);
void ED25519_DECLSPEC ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key);
#ifdef __cplusplus
}
#endif
#endif

1491
src/ed25519/fe.c Normal file

File diff suppressed because it is too large Load diff

41
src/ed25519/fe.h Normal file
View file

@ -0,0 +1,41 @@
#ifndef FE_H
#define FE_H
#include "fixedint.h"
/*
fe means field element.
Here the field is \Z/(2^255-19).
An element t, entries t[0]...t[9], represents the integer
t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9].
Bounds on each t[i] vary depending on context.
*/
typedef int32_t fe[10];
void fe_0(fe h);
void fe_1(fe h);
void fe_frombytes(fe h, const unsigned char *s);
void fe_tobytes(unsigned char *s, const fe h);
void fe_copy(fe h, const fe f);
int fe_isnegative(const fe f);
int fe_isnonzero(const fe f);
void fe_cmov(fe f, const fe g, unsigned int b);
void fe_cswap(fe f, fe g, unsigned int b);
void fe_neg(fe h, const fe f);
void fe_add(fe h, const fe f, const fe g);
void fe_invert(fe out, const fe z);
void fe_sq(fe h, const fe f);
void fe_sq2(fe h, const fe f);
void fe_mul(fe h, const fe f, const fe g);
void fe_mul121666(fe h, fe f);
void fe_pow22523(fe out, const fe z);
void fe_sub(fe h, const fe f, const fe g);
#endif

70
src/ed25519/fixedint.h Normal file
View file

@ -0,0 +1,70 @@
/*
Portable header to provide the 32 and 64 bits type.
Not a compatible replacement for <stdint.h>, do not blindly use it as such.
*/
#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined(__WATCOMC__) && (defined(_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_) || defined(__UINT_FAST64_TYPE__)) )) && !defined(FIXEDINT_H_INCLUDED)
#include <stdint.h>
#define FIXEDINT_H_INCLUDED
#if defined(__WATCOMC__) && __WATCOMC__ >= 1250 && !defined(UINT64_C)
#include <limits.h>
#define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX))
#endif
#endif
#ifndef FIXEDINT_H_INCLUDED
#define FIXEDINT_H_INCLUDED
/* (u)int32_t */
#ifndef uint32_t
#if (ULONG_MAX == 0xffffffffUL)
typedef unsigned long uint32_t;
#elif (UINT_MAX == 0xffffffffUL)
typedef unsigned int uint32_t;
#elif (USHRT_MAX == 0xffffffffUL)
typedef unsigned short uint32_t;
#endif
#endif
#ifndef int32_t
#if (LONG_MAX == 0x7fffffffL)
typedef signed long int32_t;
#elif (INT_MAX == 0x7fffffffL)
typedef signed int int32_t;
#elif (SHRT_MAX == 0x7fffffffL)
typedef signed short int32_t;
#endif
#endif
/* (u)int64_t */
#if (defined(__STDC__) && defined(__STDC_VERSION__) && __STDC__ && __STDC_VERSION__ >= 199901L)
typedef long long int64_t;
typedef unsigned long long uint64_t;
#define UINT64_C(v) v ##ULL
#define INT64_C(v) v ##LL
#elif defined(__GNUC__)
__extension__ typedef long long int64_t;
__extension__ typedef unsigned long long uint64_t;
#define UINT64_C(v) v ##ULL
#define INT64_C(v) v ##LL
#elif defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) || defined(__APPLE_CC__) || defined(_LONG_LONG) || defined(_CRAYC)
typedef long long int64_t;
typedef unsigned long long uint64_t;
#define UINT64_C(v) v ##ULL
#define INT64_C(v) v ##LL
#elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined(__BORLANDC__) && __BORLANDC__ > 0x460) || defined(__alpha) || defined(__DECC)
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#define UINT64_C(v) v ##UI64
#define INT64_C(v) v ##I64
#endif
#endif

467
src/ed25519/ge.c Normal file
View file

@ -0,0 +1,467 @@
#include "ge.h"
#include "precomp_data.h"
/*
r = p + q
*/
void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->YplusX);
fe_mul(r->Y, r->Y, q->YminusX);
fe_mul(r->T, q->T2d, p->T);
fe_mul(r->X, p->Z, q->Z);
fe_add(t0, r->X, r->X);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_add(r->Z, t0, r->T);
fe_sub(r->T, t0, r->T);
}
static void slide(signed char *r, const unsigned char *a) {
int i;
int b;
int k;
for (i = 0; i < 256; ++i) {
r[i] = 1 & (a[i >> 3] >> (i & 7));
}
for (i = 0; i < 256; ++i)
if (r[i]) {
for (b = 1; b <= 6 && i + b < 256; ++b) {
if (r[i + b]) {
if (r[i] + (r[i + b] << b) <= 15) {
r[i] += r[i + b] << b;
r[i + b] = 0;
} else if (r[i] - (r[i + b] << b) >= -15) {
r[i] -= r[i + b] << b;
for (k = i + b; k < 256; ++k) {
if (!r[k]) {
r[k] = 1;
break;
}
r[k] = 0;
}
} else {
break;
}
}
}
}
}
/*
r = a * A + b * B
where a = a[0]+256*a[1]+...+256^31 a[31].
and b = b[0]+256*b[1]+...+256^31 b[31].
B is the Ed25519 base point (x,4/5) with x positive.
*/
void ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b) {
signed char aslide[256];
signed char bslide[256];
ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
ge_p1p1 t;
ge_p3 u;
ge_p3 A2;
int i;
slide(aslide, a);
slide(bslide, b);
ge_p3_to_cached(&Ai[0], A);
ge_p3_dbl(&t, A);
ge_p1p1_to_p3(&A2, &t);
ge_add(&t, &A2, &Ai[0]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[1], &u);
ge_add(&t, &A2, &Ai[1]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[2], &u);
ge_add(&t, &A2, &Ai[2]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[3], &u);
ge_add(&t, &A2, &Ai[3]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[4], &u);
ge_add(&t, &A2, &Ai[4]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[5], &u);
ge_add(&t, &A2, &Ai[5]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[6], &u);
ge_add(&t, &A2, &Ai[6]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[7], &u);
ge_p2_0(r);
for (i = 255; i >= 0; --i) {
if (aslide[i] || bslide[i]) {
break;
}
}
for (; i >= 0; --i) {
ge_p2_dbl(&t, r);
if (aslide[i] > 0) {
ge_p1p1_to_p3(&u, &t);
ge_add(&t, &u, &Ai[aslide[i] / 2]);
} else if (aslide[i] < 0) {
ge_p1p1_to_p3(&u, &t);
ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
}
if (bslide[i] > 0) {
ge_p1p1_to_p3(&u, &t);
ge_madd(&t, &u, &Bi[bslide[i] / 2]);
} else if (bslide[i] < 0) {
ge_p1p1_to_p3(&u, &t);
ge_msub(&t, &u, &Bi[(-bslide[i]) / 2]);
}
ge_p1p1_to_p2(r, &t);
}
}
static const fe d = {
-10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116
};
static const fe sqrtm1 = {
-32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482
};
int ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s) {
fe u;
fe v;
fe v3;
fe vxx;
fe check;
fe_frombytes(h->Y, s);
fe_1(h->Z);
fe_sq(u, h->Y);
fe_mul(v, u, d);
fe_sub(u, u, h->Z); /* u = y^2-1 */
fe_add(v, v, h->Z); /* v = dy^2+1 */
fe_sq(v3, v);
fe_mul(v3, v3, v); /* v3 = v^3 */
fe_sq(h->X, v3);
fe_mul(h->X, h->X, v);
fe_mul(h->X, h->X, u); /* x = uv^7 */
fe_pow22523(h->X, h->X); /* x = (uv^7)^((q-5)/8) */
fe_mul(h->X, h->X, v3);
fe_mul(h->X, h->X, u); /* x = uv^3(uv^7)^((q-5)/8) */
fe_sq(vxx, h->X);
fe_mul(vxx, vxx, v);
fe_sub(check, vxx, u); /* vx^2-u */
if (fe_isnonzero(check)) {
fe_add(check, vxx, u); /* vx^2+u */
if (fe_isnonzero(check)) {
return -1;
}
fe_mul(h->X, h->X, sqrtm1);
}
if (fe_isnegative(h->X) == (s[31] >> 7)) {
fe_neg(h->X, h->X);
}
fe_mul(h->T, h->X, h->Y);
return 0;
}
/*
r = p + q
*/
void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->yplusx);
fe_mul(r->Y, r->Y, q->yminusx);
fe_mul(r->T, q->xy2d, p->T);
fe_add(t0, p->Z, p->Z);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_add(r->Z, t0, r->T);
fe_sub(r->T, t0, r->T);
}
/*
r = p - q
*/
void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->yminusx);
fe_mul(r->Y, r->Y, q->yplusx);
fe_mul(r->T, q->xy2d, p->T);
fe_add(t0, p->Z, p->Z);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_sub(r->Z, t0, r->T);
fe_add(r->T, t0, r->T);
}
/*
r = p
*/
void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) {
fe_mul(r->X, p->X, p->T);
fe_mul(r->Y, p->Y, p->Z);
fe_mul(r->Z, p->Z, p->T);
}
/*
r = p
*/
void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) {
fe_mul(r->X, p->X, p->T);
fe_mul(r->Y, p->Y, p->Z);
fe_mul(r->Z, p->Z, p->T);
fe_mul(r->T, p->X, p->Y);
}
void ge_p2_0(ge_p2 *h) {
fe_0(h->X);
fe_1(h->Y);
fe_1(h->Z);
}
/*
r = 2 * p
*/
void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p) {
fe t0;
fe_sq(r->X, p->X);
fe_sq(r->Z, p->Y);
fe_sq2(r->T, p->Z);
fe_add(r->Y, p->X, p->Y);
fe_sq(t0, r->Y);
fe_add(r->Y, r->Z, r->X);
fe_sub(r->Z, r->Z, r->X);
fe_sub(r->X, t0, r->Y);
fe_sub(r->T, r->T, r->Z);
}
void ge_p3_0(ge_p3 *h) {
fe_0(h->X);
fe_1(h->Y);
fe_1(h->Z);
fe_0(h->T);
}
/*
r = 2 * p
*/
void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p) {
ge_p2 q;
ge_p3_to_p2(&q, p);
ge_p2_dbl(r, &q);
}
/*
r = p
*/
static const fe d2 = {
-21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199
};
void ge_p3_to_cached(ge_cached *r, const ge_p3 *p) {
fe_add(r->YplusX, p->Y, p->X);
fe_sub(r->YminusX, p->Y, p->X);
fe_copy(r->Z, p->Z);
fe_mul(r->T2d, p->T, d2);
}
/*
r = p
*/
void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p) {
fe_copy(r->X, p->X);
fe_copy(r->Y, p->Y);
fe_copy(r->Z, p->Z);
}
void ge_p3_tobytes(unsigned char *s, const ge_p3 *h) {
fe recip;
fe x;
fe y;
fe_invert(recip, h->Z);
fe_mul(x, h->X, recip);
fe_mul(y, h->Y, recip);
fe_tobytes(s, y);
s[31] ^= fe_isnegative(x) << 7;
}
static unsigned char equal(signed char b, signed char c) {
unsigned char ub = b;
unsigned char uc = c;
unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */
uint64_t y = x; /* 0: yes; 1..255: no */
y -= 1; /* large: yes; 0..254: no */
y >>= 63; /* 1: yes; 0: no */
return (unsigned char) y;
}
static unsigned char negative(signed char b) {
uint64_t x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */
x >>= 63; /* 1: yes; 0: no */
return (unsigned char) x;
}
static void cmov(ge_precomp *t, ge_precomp *u, unsigned char b) {
fe_cmov(t->yplusx, u->yplusx, b);
fe_cmov(t->yminusx, u->yminusx, b);
fe_cmov(t->xy2d, u->xy2d, b);
}
static void select(ge_precomp *t, int pos, signed char b) {
ge_precomp minust;
unsigned char bnegative = negative(b);
unsigned char babs = b - (((-bnegative) & b) << 1);
fe_1(t->yplusx);
fe_1(t->yminusx);
fe_0(t->xy2d);
cmov(t, &base[pos][0], equal(babs, 1));
cmov(t, &base[pos][1], equal(babs, 2));
cmov(t, &base[pos][2], equal(babs, 3));
cmov(t, &base[pos][3], equal(babs, 4));
cmov(t, &base[pos][4], equal(babs, 5));
cmov(t, &base[pos][5], equal(babs, 6));
cmov(t, &base[pos][6], equal(babs, 7));
cmov(t, &base[pos][7], equal(babs, 8));
fe_copy(minust.yplusx, t->yminusx);
fe_copy(minust.yminusx, t->yplusx);
fe_neg(minust.xy2d, t->xy2d);
cmov(t, &minust, bnegative);
}
/*
h = a * B
where a = a[0]+256*a[1]+...+256^31 a[31]
B is the Ed25519 base point (x,4/5) with x positive.
Preconditions:
a[31] <= 127
*/
void ge_scalarmult_base(ge_p3 *h, const unsigned char *a) {
signed char e[64];
signed char carry;
ge_p1p1 r;
ge_p2 s;
ge_precomp t;
int i;
for (i = 0; i < 32; ++i) {
e[2 * i + 0] = (a[i] >> 0) & 15;
e[2 * i + 1] = (a[i] >> 4) & 15;
}
/* each e[i] is between 0 and 15 */
/* e[63] is between 0 and 7 */
carry = 0;
for (i = 0; i < 63; ++i) {
e[i] += carry;
carry = e[i] + 8;
carry >>= 4;
e[i] -= carry << 4;
}
e[63] += carry;
/* each e[i] is between -8 and 8 */
ge_p3_0(h);
for (i = 1; i < 64; i += 2) {
select(&t, i / 2, e[i]);
ge_madd(&r, h, &t);
ge_p1p1_to_p3(h, &r);
}
ge_p3_dbl(&r, h);
ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
ge_p1p1_to_p3(h, &r);
for (i = 0; i < 64; i += 2) {
select(&t, i / 2, e[i]);
ge_madd(&r, h, &t);
ge_p1p1_to_p3(h, &r);
}
}
/*
r = p - q
*/
void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->YminusX);
fe_mul(r->Y, r->Y, q->YplusX);
fe_mul(r->T, q->T2d, p->T);
fe_mul(r->X, p->Z, q->Z);
fe_add(t0, r->X, r->X);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_sub(r->Z, t0, r->T);
fe_add(r->T, t0, r->T);
}
void ge_tobytes(unsigned char *s, const ge_p2 *h) {
fe recip;
fe x;
fe y;
fe_invert(recip, h->Z);
fe_mul(x, h->X, recip);
fe_mul(y, h->Y, recip);
fe_tobytes(s, y);
s[31] ^= fe_isnegative(x) << 7;
}

74
src/ed25519/ge.h Normal file
View file

@ -0,0 +1,74 @@
#ifndef GE_H
#define GE_H
#include "fe.h"
/*
ge means group element.
Here the group is the set of pairs (x,y) of field elements (see fe.h)
satisfying -x^2 + y^2 = 1 + d x^2y^2
where d = -121665/121666.
Representations:
ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
ge_precomp (Duif): (y+x,y-x,2dxy)
*/
typedef struct {
fe X;
fe Y;
fe Z;
} ge_p2;
typedef struct {
fe X;
fe Y;
fe Z;
fe T;
} ge_p3;
typedef struct {
fe X;
fe Y;
fe Z;
fe T;
} ge_p1p1;
typedef struct {
fe yplusx;
fe yminusx;
fe xy2d;
} ge_precomp;
typedef struct {
fe YplusX;
fe YminusX;
fe Z;
fe T2d;
} ge_cached;
void ge_p3_tobytes(unsigned char *s, const ge_p3 *h);
void ge_tobytes(unsigned char *s, const ge_p2 *h);
int ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s);
void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q);
void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q);
void ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b);
void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q);
void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q);
void ge_scalarmult_base(ge_p3 *h, const unsigned char *a);
void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p);
void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p);
void ge_p2_0(ge_p2 *h);
void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p);
void ge_p3_0(ge_p3 *h);
void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p);
void ge_p3_to_cached(ge_cached *r, const ge_p3 *p);
void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p);
#endif

View file

@ -0,0 +1,79 @@
#include "ed25519.h"
#include "fe.h"
void ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key) {
unsigned char e[32];
unsigned int i;
fe x1;
fe x2;
fe z2;
fe x3;
fe z3;
fe tmp0;
fe tmp1;
int pos;
unsigned int swap;
unsigned int b;
/* copy the private key and make sure it's valid */
for (i = 0; i < 32; ++i) {
e[i] = private_key[i];
}
e[0] &= 248;
e[31] &= 63;
e[31] |= 64;
/* unpack the public key and convert edwards to montgomery */
/* due to CodesInChaos: montgomeryX = (edwardsY + 1)*inverse(1 - edwardsY) mod p */
fe_frombytes(x1, public_key);
fe_1(tmp1);
fe_add(tmp0, x1, tmp1);
fe_sub(tmp1, tmp1, x1);
fe_invert(tmp1, tmp1);
fe_mul(x1, tmp0, tmp1);
fe_1(x2);
fe_0(z2);
fe_copy(x3, x1);
fe_1(z3);
swap = 0;
for (pos = 254; pos >= 0; --pos) {
b = e[pos / 8] >> (pos & 7);
b &= 1;
swap ^= b;
fe_cswap(x2, x3, swap);
fe_cswap(z2, z3, swap);
swap = b;
/* from montgomery.h */
fe_sub(tmp0, x3, z3);
fe_sub(tmp1, x2, z2);
fe_add(x2, x2, z2);
fe_add(z2, x3, z3);
fe_mul(z3, tmp0, x2);
fe_mul(z2, z2, tmp1);
fe_sq(tmp0, tmp1);
fe_sq(tmp1, x2);
fe_add(x3, z3, z2);
fe_sub(z2, z3, z2);
fe_mul(x2, tmp1, tmp0);
fe_sub(tmp1, tmp1, tmp0);
fe_sq(z2, z2);
fe_mul121666(z3, tmp1);
fe_sq(x3, x3);
fe_add(tmp0, tmp0, z3);
fe_mul(z3, x1, z2);
fe_mul(z2, tmp1, tmp0);
}
fe_cswap(x2, x3, swap);
fe_cswap(z2, z3, swap);
fe_invert(z2, z2);
fe_mul(x2, x2, z2);
fe_tobytes(shared_secret, x2);
}

16
src/ed25519/keypair.c Normal file
View file

@ -0,0 +1,16 @@
#include "ed25519.h"
#include "sha512.h"
#include "ge.h"
void ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed) {
ge_p3 A;
sha512(seed, 32, private_key);
private_key[0] &= 248;
private_key[31] &= 63;
private_key[31] |= 64;
ge_scalarmult_base(&A, private_key);
ge_p3_tobytes(public_key, &A);
}

1391
src/ed25519/precomp_data.h Normal file

File diff suppressed because it is too large Load diff

809
src/ed25519/sc.c Normal file
View file

@ -0,0 +1,809 @@
#include "fixedint.h"
#include "sc.h"
static uint64_t load_3(const unsigned char *in) {
uint64_t result;
result = (uint64_t) in[0];
result |= ((uint64_t) in[1]) << 8;
result |= ((uint64_t) in[2]) << 16;
return result;
}
static uint64_t load_4(const unsigned char *in) {
uint64_t result;
result = (uint64_t) in[0];
result |= ((uint64_t) in[1]) << 8;
result |= ((uint64_t) in[2]) << 16;
result |= ((uint64_t) in[3]) << 24;
return result;
}
/*
Input:
s[0]+256*s[1]+...+256^63*s[63] = s
Output:
s[0]+256*s[1]+...+256^31*s[31] = s mod l
where l = 2^252 + 27742317777372353535851937790883648493.
Overwrites s in place.
*/
void sc_reduce(unsigned char *s) {
int64_t s0 = 2097151 & load_3(s);
int64_t s1 = 2097151 & (load_4(s + 2) >> 5);
int64_t s2 = 2097151 & (load_3(s + 5) >> 2);
int64_t s3 = 2097151 & (load_4(s + 7) >> 7);
int64_t s4 = 2097151 & (load_4(s + 10) >> 4);
int64_t s5 = 2097151 & (load_3(s + 13) >> 1);
int64_t s6 = 2097151 & (load_4(s + 15) >> 6);
int64_t s7 = 2097151 & (load_3(s + 18) >> 3);
int64_t s8 = 2097151 & load_3(s + 21);
int64_t s9 = 2097151 & (load_4(s + 23) >> 5);
int64_t s10 = 2097151 & (load_3(s + 26) >> 2);
int64_t s11 = 2097151 & (load_4(s + 28) >> 7);
int64_t s12 = 2097151 & (load_4(s + 31) >> 4);
int64_t s13 = 2097151 & (load_3(s + 34) >> 1);
int64_t s14 = 2097151 & (load_4(s + 36) >> 6);
int64_t s15 = 2097151 & (load_3(s + 39) >> 3);
int64_t s16 = 2097151 & load_3(s + 42);
int64_t s17 = 2097151 & (load_4(s + 44) >> 5);
int64_t s18 = 2097151 & (load_3(s + 47) >> 2);
int64_t s19 = 2097151 & (load_4(s + 49) >> 7);
int64_t s20 = 2097151 & (load_4(s + 52) >> 4);
int64_t s21 = 2097151 & (load_3(s + 55) >> 1);
int64_t s22 = 2097151 & (load_4(s + 57) >> 6);
int64_t s23 = (load_4(s + 60) >> 3);
int64_t carry0;
int64_t carry1;
int64_t carry2;
int64_t carry3;
int64_t carry4;
int64_t carry5;
int64_t carry6;
int64_t carry7;
int64_t carry8;
int64_t carry9;
int64_t carry10;
int64_t carry11;
int64_t carry12;
int64_t carry13;
int64_t carry14;
int64_t carry15;
int64_t carry16;
s11 += s23 * 666643;
s12 += s23 * 470296;
s13 += s23 * 654183;
s14 -= s23 * 997805;
s15 += s23 * 136657;
s16 -= s23 * 683901;
s23 = 0;
s10 += s22 * 666643;
s11 += s22 * 470296;
s12 += s22 * 654183;
s13 -= s22 * 997805;
s14 += s22 * 136657;
s15 -= s22 * 683901;
s22 = 0;
s9 += s21 * 666643;
s10 += s21 * 470296;
s11 += s21 * 654183;
s12 -= s21 * 997805;
s13 += s21 * 136657;
s14 -= s21 * 683901;
s21 = 0;
s8 += s20 * 666643;
s9 += s20 * 470296;
s10 += s20 * 654183;
s11 -= s20 * 997805;
s12 += s20 * 136657;
s13 -= s20 * 683901;
s20 = 0;
s7 += s19 * 666643;
s8 += s19 * 470296;
s9 += s19 * 654183;
s10 -= s19 * 997805;
s11 += s19 * 136657;
s12 -= s19 * 683901;
s19 = 0;
s6 += s18 * 666643;
s7 += s18 * 470296;
s8 += s18 * 654183;
s9 -= s18 * 997805;
s10 += s18 * 136657;
s11 -= s18 * 683901;
s18 = 0;
carry6 = (s6 + (1 << 20)) >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry8 = (s8 + (1 << 20)) >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry10 = (s10 + (1 << 20)) >> 21;
s11 += carry10;
s10 -= carry10 << 21;
carry12 = (s12 + (1 << 20)) >> 21;
s13 += carry12;
s12 -= carry12 << 21;
carry14 = (s14 + (1 << 20)) >> 21;
s15 += carry14;
s14 -= carry14 << 21;
carry16 = (s16 + (1 << 20)) >> 21;
s17 += carry16;
s16 -= carry16 << 21;
carry7 = (s7 + (1 << 20)) >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry9 = (s9 + (1 << 20)) >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry11 = (s11 + (1 << 20)) >> 21;
s12 += carry11;
s11 -= carry11 << 21;
carry13 = (s13 + (1 << 20)) >> 21;
s14 += carry13;
s13 -= carry13 << 21;
carry15 = (s15 + (1 << 20)) >> 21;
s16 += carry15;
s15 -= carry15 << 21;
s5 += s17 * 666643;
s6 += s17 * 470296;
s7 += s17 * 654183;
s8 -= s17 * 997805;
s9 += s17 * 136657;
s10 -= s17 * 683901;
s17 = 0;
s4 += s16 * 666643;
s5 += s16 * 470296;
s6 += s16 * 654183;
s7 -= s16 * 997805;
s8 += s16 * 136657;
s9 -= s16 * 683901;
s16 = 0;
s3 += s15 * 666643;
s4 += s15 * 470296;
s5 += s15 * 654183;
s6 -= s15 * 997805;
s7 += s15 * 136657;
s8 -= s15 * 683901;
s15 = 0;
s2 += s14 * 666643;
s3 += s14 * 470296;
s4 += s14 * 654183;
s5 -= s14 * 997805;
s6 += s14 * 136657;
s7 -= s14 * 683901;
s14 = 0;
s1 += s13 * 666643;
s2 += s13 * 470296;
s3 += s13 * 654183;
s4 -= s13 * 997805;
s5 += s13 * 136657;
s6 -= s13 * 683901;
s13 = 0;
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = (s0 + (1 << 20)) >> 21;
s1 += carry0;
s0 -= carry0 << 21;
carry2 = (s2 + (1 << 20)) >> 21;
s3 += carry2;
s2 -= carry2 << 21;
carry4 = (s4 + (1 << 20)) >> 21;
s5 += carry4;
s4 -= carry4 << 21;
carry6 = (s6 + (1 << 20)) >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry8 = (s8 + (1 << 20)) >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry10 = (s10 + (1 << 20)) >> 21;
s11 += carry10;
s10 -= carry10 << 21;
carry1 = (s1 + (1 << 20)) >> 21;
s2 += carry1;
s1 -= carry1 << 21;
carry3 = (s3 + (1 << 20)) >> 21;
s4 += carry3;
s3 -= carry3 << 21;
carry5 = (s5 + (1 << 20)) >> 21;
s6 += carry5;
s5 -= carry5 << 21;
carry7 = (s7 + (1 << 20)) >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry9 = (s9 + (1 << 20)) >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry11 = (s11 + (1 << 20)) >> 21;
s12 += carry11;
s11 -= carry11 << 21;
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = s0 >> 21;
s1 += carry0;
s0 -= carry0 << 21;
carry1 = s1 >> 21;
s2 += carry1;
s1 -= carry1 << 21;
carry2 = s2 >> 21;
s3 += carry2;
s2 -= carry2 << 21;
carry3 = s3 >> 21;
s4 += carry3;
s3 -= carry3 << 21;
carry4 = s4 >> 21;
s5 += carry4;
s4 -= carry4 << 21;
carry5 = s5 >> 21;
s6 += carry5;
s5 -= carry5 << 21;
carry6 = s6 >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry7 = s7 >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry8 = s8 >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry9 = s9 >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry10 = s10 >> 21;
s11 += carry10;
s10 -= carry10 << 21;
carry11 = s11 >> 21;
s12 += carry11;
s11 -= carry11 << 21;
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = s0 >> 21;
s1 += carry0;
s0 -= carry0 << 21;
carry1 = s1 >> 21;
s2 += carry1;
s1 -= carry1 << 21;
carry2 = s2 >> 21;
s3 += carry2;
s2 -= carry2 << 21;
carry3 = s3 >> 21;
s4 += carry3;
s3 -= carry3 << 21;
carry4 = s4 >> 21;
s5 += carry4;
s4 -= carry4 << 21;
carry5 = s5 >> 21;
s6 += carry5;
s5 -= carry5 << 21;
carry6 = s6 >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry7 = s7 >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry8 = s8 >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry9 = s9 >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry10 = s10 >> 21;
s11 += carry10;
s10 -= carry10 << 21;
s[0] = (unsigned char) (s0 >> 0);
s[1] = (unsigned char) (s0 >> 8);
s[2] = (unsigned char) ((s0 >> 16) | (s1 << 5));
s[3] = (unsigned char) (s1 >> 3);
s[4] = (unsigned char) (s1 >> 11);
s[5] = (unsigned char) ((s1 >> 19) | (s2 << 2));
s[6] = (unsigned char) (s2 >> 6);
s[7] = (unsigned char) ((s2 >> 14) | (s3 << 7));
s[8] = (unsigned char) (s3 >> 1);
s[9] = (unsigned char) (s3 >> 9);
s[10] = (unsigned char) ((s3 >> 17) | (s4 << 4));
s[11] = (unsigned char) (s4 >> 4);
s[12] = (unsigned char) (s4 >> 12);
s[13] = (unsigned char) ((s4 >> 20) | (s5 << 1));
s[14] = (unsigned char) (s5 >> 7);
s[15] = (unsigned char) ((s5 >> 15) | (s6 << 6));
s[16] = (unsigned char) (s6 >> 2);
s[17] = (unsigned char) (s6 >> 10);
s[18] = (unsigned char) ((s6 >> 18) | (s7 << 3));
s[19] = (unsigned char) (s7 >> 5);
s[20] = (unsigned char) (s7 >> 13);
s[21] = (unsigned char) (s8 >> 0);
s[22] = (unsigned char) (s8 >> 8);
s[23] = (unsigned char) ((s8 >> 16) | (s9 << 5));
s[24] = (unsigned char) (s9 >> 3);
s[25] = (unsigned char) (s9 >> 11);
s[26] = (unsigned char) ((s9 >> 19) | (s10 << 2));
s[27] = (unsigned char) (s10 >> 6);
s[28] = (unsigned char) ((s10 >> 14) | (s11 << 7));
s[29] = (unsigned char) (s11 >> 1);
s[30] = (unsigned char) (s11 >> 9);
s[31] = (unsigned char) (s11 >> 17);
}
/*
Input:
a[0]+256*a[1]+...+256^31*a[31] = a
b[0]+256*b[1]+...+256^31*b[31] = b
c[0]+256*c[1]+...+256^31*c[31] = c
Output:
s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
where l = 2^252 + 27742317777372353535851937790883648493.
*/
void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c) {
int64_t a0 = 2097151 & load_3(a);
int64_t a1 = 2097151 & (load_4(a + 2) >> 5);
int64_t a2 = 2097151 & (load_3(a + 5) >> 2);
int64_t a3 = 2097151 & (load_4(a + 7) >> 7);
int64_t a4 = 2097151 & (load_4(a + 10) >> 4);
int64_t a5 = 2097151 & (load_3(a + 13) >> 1);
int64_t a6 = 2097151 & (load_4(a + 15) >> 6);
int64_t a7 = 2097151 & (load_3(a + 18) >> 3);
int64_t a8 = 2097151 & load_3(a + 21);
int64_t a9 = 2097151 & (load_4(a + 23) >> 5);
int64_t a10 = 2097151 & (load_3(a + 26) >> 2);
int64_t a11 = (load_4(a + 28) >> 7);
int64_t b0 = 2097151 & load_3(b);
int64_t b1 = 2097151 & (load_4(b + 2) >> 5);
int64_t b2 = 2097151 & (load_3(b + 5) >> 2);
int64_t b3 = 2097151 & (load_4(b + 7) >> 7);
int64_t b4 = 2097151 & (load_4(b + 10) >> 4);
int64_t b5 = 2097151 & (load_3(b + 13) >> 1);
int64_t b6 = 2097151 & (load_4(b + 15) >> 6);
int64_t b7 = 2097151 & (load_3(b + 18) >> 3);
int64_t b8 = 2097151 & load_3(b + 21);
int64_t b9 = 2097151 & (load_4(b + 23) >> 5);
int64_t b10 = 2097151 & (load_3(b + 26) >> 2);
int64_t b11 = (load_4(b + 28) >> 7);
int64_t c0 = 2097151 & load_3(c);
int64_t c1 = 2097151 & (load_4(c + 2) >> 5);
int64_t c2 = 2097151 & (load_3(c + 5) >> 2);
int64_t c3 = 2097151 & (load_4(c + 7) >> 7);
int64_t c4 = 2097151 & (load_4(c + 10) >> 4);
int64_t c5 = 2097151 & (load_3(c + 13) >> 1);
int64_t c6 = 2097151 & (load_4(c + 15) >> 6);
int64_t c7 = 2097151 & (load_3(c + 18) >> 3);
int64_t c8 = 2097151 & load_3(c + 21);
int64_t c9 = 2097151 & (load_4(c + 23) >> 5);
int64_t c10 = 2097151 & (load_3(c + 26) >> 2);
int64_t c11 = (load_4(c + 28) >> 7);
int64_t s0;
int64_t s1;
int64_t s2;
int64_t s3;
int64_t s4;
int64_t s5;
int64_t s6;
int64_t s7;
int64_t s8;
int64_t s9;
int64_t s10;
int64_t s11;
int64_t s12;
int64_t s13;
int64_t s14;
int64_t s15;
int64_t s16;
int64_t s17;
int64_t s18;
int64_t s19;
int64_t s20;
int64_t s21;
int64_t s22;
int64_t s23;
int64_t carry0;
int64_t carry1;
int64_t carry2;
int64_t carry3;
int64_t carry4;
int64_t carry5;
int64_t carry6;
int64_t carry7;
int64_t carry8;
int64_t carry9;
int64_t carry10;
int64_t carry11;
int64_t carry12;
int64_t carry13;
int64_t carry14;
int64_t carry15;
int64_t carry16;
int64_t carry17;
int64_t carry18;
int64_t carry19;
int64_t carry20;
int64_t carry21;
int64_t carry22;
s0 = c0 + a0 * b0;
s1 = c1 + a0 * b1 + a1 * b0;
s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0;
s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0;
s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0;
s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0;
s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 + a6 * b1 + a7 * b0;
s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 + a6 * b2 + a7 * b1 + a8 * b0;
s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 + a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0;
s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 + a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0;
s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 + a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0;
s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1;
s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2;
s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + a9 * b5 + a10 * b4 + a11 * b3;
s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + a10 * b5 + a11 * b4;
s16 = a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5;
s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6;
s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7;
s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8;
s20 = a9 * b11 + a10 * b10 + a11 * b9;
s21 = a10 * b11 + a11 * b10;
s22 = a11 * b11;
s23 = 0;
carry0 = (s0 + (1 << 20)) >> 21;
s1 += carry0;
s0 -= carry0 << 21;
carry2 = (s2 + (1 << 20)) >> 21;
s3 += carry2;
s2 -= carry2 << 21;
carry4 = (s4 + (1 << 20)) >> 21;
s5 += carry4;
s4 -= carry4 << 21;
carry6 = (s6 + (1 << 20)) >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry8 = (s8 + (1 << 20)) >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry10 = (s10 + (1 << 20)) >> 21;
s11 += carry10;
s10 -= carry10 << 21;
carry12 = (s12 + (1 << 20)) >> 21;
s13 += carry12;
s12 -= carry12 << 21;
carry14 = (s14 + (1 << 20)) >> 21;
s15 += carry14;
s14 -= carry14 << 21;
carry16 = (s16 + (1 << 20)) >> 21;
s17 += carry16;
s16 -= carry16 << 21;
carry18 = (s18 + (1 << 20)) >> 21;
s19 += carry18;
s18 -= carry18 << 21;
carry20 = (s20 + (1 << 20)) >> 21;
s21 += carry20;
s20 -= carry20 << 21;
carry22 = (s22 + (1 << 20)) >> 21;
s23 += carry22;
s22 -= carry22 << 21;
carry1 = (s1 + (1 << 20)) >> 21;
s2 += carry1;
s1 -= carry1 << 21;
carry3 = (s3 + (1 << 20)) >> 21;
s4 += carry3;
s3 -= carry3 << 21;
carry5 = (s5 + (1 << 20)) >> 21;
s6 += carry5;
s5 -= carry5 << 21;
carry7 = (s7 + (1 << 20)) >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry9 = (s9 + (1 << 20)) >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry11 = (s11 + (1 << 20)) >> 21;
s12 += carry11;
s11 -= carry11 << 21;
carry13 = (s13 + (1 << 20)) >> 21;
s14 += carry13;
s13 -= carry13 << 21;
carry15 = (s15 + (1 << 20)) >> 21;
s16 += carry15;
s15 -= carry15 << 21;
carry17 = (s17 + (1 << 20)) >> 21;
s18 += carry17;
s17 -= carry17 << 21;
carry19 = (s19 + (1 << 20)) >> 21;
s20 += carry19;
s19 -= carry19 << 21;
carry21 = (s21 + (1 << 20)) >> 21;
s22 += carry21;
s21 -= carry21 << 21;
s11 += s23 * 666643;
s12 += s23 * 470296;
s13 += s23 * 654183;
s14 -= s23 * 997805;
s15 += s23 * 136657;
s16 -= s23 * 683901;
s23 = 0;
s10 += s22 * 666643;
s11 += s22 * 470296;
s12 += s22 * 654183;
s13 -= s22 * 997805;
s14 += s22 * 136657;
s15 -= s22 * 683901;
s22 = 0;
s9 += s21 * 666643;
s10 += s21 * 470296;
s11 += s21 * 654183;
s12 -= s21 * 997805;
s13 += s21 * 136657;
s14 -= s21 * 683901;
s21 = 0;
s8 += s20 * 666643;
s9 += s20 * 470296;
s10 += s20 * 654183;
s11 -= s20 * 997805;
s12 += s20 * 136657;
s13 -= s20 * 683901;
s20 = 0;
s7 += s19 * 666643;
s8 += s19 * 470296;
s9 += s19 * 654183;
s10 -= s19 * 997805;
s11 += s19 * 136657;
s12 -= s19 * 683901;
s19 = 0;
s6 += s18 * 666643;
s7 += s18 * 470296;
s8 += s18 * 654183;
s9 -= s18 * 997805;
s10 += s18 * 136657;
s11 -= s18 * 683901;
s18 = 0;
carry6 = (s6 + (1 << 20)) >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry8 = (s8 + (1 << 20)) >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry10 = (s10 + (1 << 20)) >> 21;
s11 += carry10;
s10 -= carry10 << 21;
carry12 = (s12 + (1 << 20)) >> 21;
s13 += carry12;
s12 -= carry12 << 21;
carry14 = (s14 + (1 << 20)) >> 21;
s15 += carry14;
s14 -= carry14 << 21;
carry16 = (s16 + (1 << 20)) >> 21;
s17 += carry16;
s16 -= carry16 << 21;
carry7 = (s7 + (1 << 20)) >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry9 = (s9 + (1 << 20)) >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry11 = (s11 + (1 << 20)) >> 21;
s12 += carry11;
s11 -= carry11 << 21;
carry13 = (s13 + (1 << 20)) >> 21;
s14 += carry13;
s13 -= carry13 << 21;
carry15 = (s15 + (1 << 20)) >> 21;
s16 += carry15;
s15 -= carry15 << 21;
s5 += s17 * 666643;
s6 += s17 * 470296;
s7 += s17 * 654183;
s8 -= s17 * 997805;
s9 += s17 * 136657;
s10 -= s17 * 683901;
s17 = 0;
s4 += s16 * 666643;
s5 += s16 * 470296;
s6 += s16 * 654183;
s7 -= s16 * 997805;
s8 += s16 * 136657;
s9 -= s16 * 683901;
s16 = 0;
s3 += s15 * 666643;
s4 += s15 * 470296;
s5 += s15 * 654183;
s6 -= s15 * 997805;
s7 += s15 * 136657;
s8 -= s15 * 683901;
s15 = 0;
s2 += s14 * 666643;
s3 += s14 * 470296;
s4 += s14 * 654183;
s5 -= s14 * 997805;
s6 += s14 * 136657;
s7 -= s14 * 683901;
s14 = 0;
s1 += s13 * 666643;
s2 += s13 * 470296;
s3 += s13 * 654183;
s4 -= s13 * 997805;
s5 += s13 * 136657;
s6 -= s13 * 683901;
s13 = 0;
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = (s0 + (1 << 20)) >> 21;
s1 += carry0;
s0 -= carry0 << 21;
carry2 = (s2 + (1 << 20)) >> 21;
s3 += carry2;
s2 -= carry2 << 21;
carry4 = (s4 + (1 << 20)) >> 21;
s5 += carry4;
s4 -= carry4 << 21;
carry6 = (s6 + (1 << 20)) >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry8 = (s8 + (1 << 20)) >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry10 = (s10 + (1 << 20)) >> 21;
s11 += carry10;
s10 -= carry10 << 21;
carry1 = (s1 + (1 << 20)) >> 21;
s2 += carry1;
s1 -= carry1 << 21;
carry3 = (s3 + (1 << 20)) >> 21;
s4 += carry3;
s3 -= carry3 << 21;
carry5 = (s5 + (1 << 20)) >> 21;
s6 += carry5;
s5 -= carry5 << 21;
carry7 = (s7 + (1 << 20)) >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry9 = (s9 + (1 << 20)) >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry11 = (s11 + (1 << 20)) >> 21;
s12 += carry11;
s11 -= carry11 << 21;
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = s0 >> 21;
s1 += carry0;
s0 -= carry0 << 21;
carry1 = s1 >> 21;
s2 += carry1;
s1 -= carry1 << 21;
carry2 = s2 >> 21;
s3 += carry2;
s2 -= carry2 << 21;
carry3 = s3 >> 21;
s4 += carry3;
s3 -= carry3 << 21;
carry4 = s4 >> 21;
s5 += carry4;
s4 -= carry4 << 21;
carry5 = s5 >> 21;
s6 += carry5;
s5 -= carry5 << 21;
carry6 = s6 >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry7 = s7 >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry8 = s8 >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry9 = s9 >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry10 = s10 >> 21;
s11 += carry10;
s10 -= carry10 << 21;
carry11 = s11 >> 21;
s12 += carry11;
s11 -= carry11 << 21;
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = s0 >> 21;
s1 += carry0;
s0 -= carry0 << 21;
carry1 = s1 >> 21;
s2 += carry1;
s1 -= carry1 << 21;
carry2 = s2 >> 21;
s3 += carry2;
s2 -= carry2 << 21;
carry3 = s3 >> 21;
s4 += carry3;
s3 -= carry3 << 21;
carry4 = s4 >> 21;
s5 += carry4;
s4 -= carry4 << 21;
carry5 = s5 >> 21;
s6 += carry5;
s5 -= carry5 << 21;
carry6 = s6 >> 21;
s7 += carry6;
s6 -= carry6 << 21;
carry7 = s7 >> 21;
s8 += carry7;
s7 -= carry7 << 21;
carry8 = s8 >> 21;
s9 += carry8;
s8 -= carry8 << 21;
carry9 = s9 >> 21;
s10 += carry9;
s9 -= carry9 << 21;
carry10 = s10 >> 21;
s11 += carry10;
s10 -= carry10 << 21;
s[0] = (unsigned char) (s0 >> 0);
s[1] = (unsigned char) (s0 >> 8);
s[2] = (unsigned char) ((s0 >> 16) | (s1 << 5));
s[3] = (unsigned char) (s1 >> 3);
s[4] = (unsigned char) (s1 >> 11);
s[5] = (unsigned char) ((s1 >> 19) | (s2 << 2));
s[6] = (unsigned char) (s2 >> 6);
s[7] = (unsigned char) ((s2 >> 14) | (s3 << 7));
s[8] = (unsigned char) (s3 >> 1);
s[9] = (unsigned char) (s3 >> 9);
s[10] = (unsigned char) ((s3 >> 17) | (s4 << 4));
s[11] = (unsigned char) (s4 >> 4);
s[12] = (unsigned char) (s4 >> 12);
s[13] = (unsigned char) ((s4 >> 20) | (s5 << 1));
s[14] = (unsigned char) (s5 >> 7);
s[15] = (unsigned char) ((s5 >> 15) | (s6 << 6));
s[16] = (unsigned char) (s6 >> 2);
s[17] = (unsigned char) (s6 >> 10);
s[18] = (unsigned char) ((s6 >> 18) | (s7 << 3));
s[19] = (unsigned char) (s7 >> 5);
s[20] = (unsigned char) (s7 >> 13);
s[21] = (unsigned char) (s8 >> 0);
s[22] = (unsigned char) (s8 >> 8);
s[23] = (unsigned char) ((s8 >> 16) | (s9 << 5));
s[24] = (unsigned char) (s9 >> 3);
s[25] = (unsigned char) (s9 >> 11);
s[26] = (unsigned char) ((s9 >> 19) | (s10 << 2));
s[27] = (unsigned char) (s10 >> 6);
s[28] = (unsigned char) ((s10 >> 14) | (s11 << 7));
s[29] = (unsigned char) (s11 >> 1);
s[30] = (unsigned char) (s11 >> 9);
s[31] = (unsigned char) (s11 >> 17);
}

12
src/ed25519/sc.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef SC_H
#define SC_H
/*
The set of scalars is \Z/l
where l = 2^252 + 27742317777372353535851937790883648493.
*/
void sc_reduce(unsigned char *s);
void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c);
#endif

275
src/ed25519/sha512.c Normal file
View file

@ -0,0 +1,275 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
*/
#include "fixedint.h"
#include "sha512.h"
/* the K array */
static const uint64_t K[80] = {
UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd),
UINT64_C(0xb5c0fbcfec4d3b2f), UINT64_C(0xe9b5dba58189dbbc),
UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019),
UINT64_C(0x923f82a4af194f9b), UINT64_C(0xab1c5ed5da6d8118),
UINT64_C(0xd807aa98a3030242), UINT64_C(0x12835b0145706fbe),
UINT64_C(0x243185be4ee4b28c), UINT64_C(0x550c7dc3d5ffb4e2),
UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1),
UINT64_C(0x9bdc06a725c71235), UINT64_C(0xc19bf174cf692694),
UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3),
UINT64_C(0x0fc19dc68b8cd5b5), UINT64_C(0x240ca1cc77ac9c65),
UINT64_C(0x2de92c6f592b0275), UINT64_C(0x4a7484aa6ea6e483),
UINT64_C(0x5cb0a9dcbd41fbd4), UINT64_C(0x76f988da831153b5),
UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210),
UINT64_C(0xb00327c898fb213f), UINT64_C(0xbf597fc7beef0ee4),
UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725),
UINT64_C(0x06ca6351e003826f), UINT64_C(0x142929670a0e6e70),
UINT64_C(0x27b70a8546d22ffc), UINT64_C(0x2e1b21385c26c926),
UINT64_C(0x4d2c6dfc5ac42aed), UINT64_C(0x53380d139d95b3df),
UINT64_C(0x650a73548baf63de), UINT64_C(0x766a0abb3c77b2a8),
UINT64_C(0x81c2c92e47edaee6), UINT64_C(0x92722c851482353b),
UINT64_C(0xa2bfe8a14cf10364), UINT64_C(0xa81a664bbc423001),
UINT64_C(0xc24b8b70d0f89791), UINT64_C(0xc76c51a30654be30),
UINT64_C(0xd192e819d6ef5218), UINT64_C(0xd69906245565a910),
UINT64_C(0xf40e35855771202a), UINT64_C(0x106aa07032bbd1b8),
UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53),
UINT64_C(0x2748774cdf8eeb99), UINT64_C(0x34b0bcb5e19b48a8),
UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb),
UINT64_C(0x5b9cca4f7763e373), UINT64_C(0x682e6ff3d6b2b8a3),
UINT64_C(0x748f82ee5defb2fc), UINT64_C(0x78a5636f43172f60),
UINT64_C(0x84c87814a1f0ab72), UINT64_C(0x8cc702081a6439ec),
UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9),
UINT64_C(0xbef9a3f7b2c67915), UINT64_C(0xc67178f2e372532b),
UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207),
UINT64_C(0xeada7dd6cde0eb1e), UINT64_C(0xf57d4f7fee6ed178),
UINT64_C(0x06f067aa72176fba), UINT64_C(0x0a637dc5a2c898a6),
UINT64_C(0x113f9804bef90dae), UINT64_C(0x1b710b35131c471b),
UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493),
UINT64_C(0x3c9ebe0a15c9bebc), UINT64_C(0x431d67c49c100d4c),
UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a),
UINT64_C(0x5fcb6fab3ad6faec), UINT64_C(0x6c44198c4a475817)
};
/* Various logical functions */
#define ROR64c(x, y) \
( ((((x)&UINT64_C(0xFFFFFFFFFFFFFFFF))>>((uint64_t)(y)&UINT64_C(63))) | \
((x)<<((uint64_t)(64-((y)&UINT64_C(63)))))) & UINT64_C(0xFFFFFFFFFFFFFFFF))
#define STORE64H(x, y) \
{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
#define LOAD64H(x, y) \
{ x = (((uint64_t)((y)[0] & 255))<<56)|(((uint64_t)((y)[1] & 255))<<48) | \
(((uint64_t)((y)[2] & 255))<<40)|(((uint64_t)((y)[3] & 255))<<32) | \
(((uint64_t)((y)[4] & 255))<<24)|(((uint64_t)((y)[5] & 255))<<16) | \
(((uint64_t)((y)[6] & 255))<<8)|(((uint64_t)((y)[7] & 255))); }
#define Ch(x,y,z) (z ^ (x & (y ^ z)))
#define Maj(x,y,z) (((x | y) & z) | (x & y))
#define S(x, n) ROR64c(x, n)
#define R(x, n) (((x) &UINT64_C(0xFFFFFFFFFFFFFFFF))>>((uint64_t)n))
#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39))
#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41))
#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7))
#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6))
#ifndef MIN
#define MIN(x, y) ( ((x)<(y))?(x):(y) )
#endif
/* compress 1024-bits */
static int sha512_compress(sha512_context *md, unsigned char *buf)
{
uint64_t S[8], W[80], t0, t1;
int i;
/* copy state into S */
for (i = 0; i < 8; i++) {
S[i] = md->state[i];
}
/* copy the state into 1024-bits into W[0..15] */
for (i = 0; i < 16; i++) {
LOAD64H(W[i], buf + (8*i));
}
/* fill W[16..79] */
for (i = 16; i < 80; i++) {
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
}
/* Compress */
#define RND(a,b,c,d,e,f,g,h,i) \
t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
t1 = Sigma0(a) + Maj(a, b, c);\
d += t0; \
h = t0 + t1;
for (i = 0; i < 80; i += 8) {
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
}
#undef RND
/* feedback */
for (i = 0; i < 8; i++) {
md->state[i] = md->state[i] + S[i];
}
return 0;
}
/**
Initialize the hash state
@param md The hash state you wish to initialize
@return 0 if successful
*/
int sha512_init(sha512_context * md) {
if (md == NULL) return 1;
md->curlen = 0;
md->length = 0;
md->state[0] = UINT64_C(0x6a09e667f3bcc908);
md->state[1] = UINT64_C(0xbb67ae8584caa73b);
md->state[2] = UINT64_C(0x3c6ef372fe94f82b);
md->state[3] = UINT64_C(0xa54ff53a5f1d36f1);
md->state[4] = UINT64_C(0x510e527fade682d1);
md->state[5] = UINT64_C(0x9b05688c2b3e6c1f);
md->state[6] = UINT64_C(0x1f83d9abfb41bd6b);
md->state[7] = UINT64_C(0x5be0cd19137e2179);
return 0;
}
/**
Process a block of memory though the hash
@param md The hash state
@param in The data to hash
@param inlen The length of the data (octets)
@return 0 if successful
*/
int sha512_update (sha512_context * md, const unsigned char *in, size_t inlen)
{
size_t n;
size_t i;
int err;
if (md == NULL) return 1;
if (in == NULL) return 1;
if (md->curlen > sizeof(md->buf)) {
return 1;
}
while (inlen > 0) {
if (md->curlen == 0 && inlen >= 128) {
if ((err = sha512_compress (md, (unsigned char *)in)) != 0) {
return err;
}
md->length += 128 * 8;
in += 128;
inlen -= 128;
} else {
n = MIN(inlen, (128 - md->curlen));
for (i = 0; i < n; i++) {
md->buf[i + md->curlen] = in[i];
}
md->curlen += n;
in += n;
inlen -= n;
if (md->curlen == 128) {
if ((err = sha512_compress (md, md->buf)) != 0) {
return err;
}
md->length += 8*128;
md->curlen = 0;
}
}
}
return 0;
}
/**
Terminate the hash to get the digest
@param md The hash state
@param out [out] The destination of the hash (64 bytes)
@return 0 if successful
*/
int sha512_final(sha512_context * md, unsigned char *out)
{
int i;
if (md == NULL) return 1;
if (out == NULL) return 1;
if (md->curlen >= sizeof(md->buf)) {
return 1;
}
/* increase the length of the message */
md->length += md->curlen * UINT64_C(8);
/* append the '1' bit */
md->buf[md->curlen++] = (unsigned char)0x80;
/* if the length is currently above 112 bytes we append zeros
* then compress. Then we can fall back to padding zeros and length
* encoding like normal.
*/
if (md->curlen > 112) {
while (md->curlen < 128) {
md->buf[md->curlen++] = (unsigned char)0;
}
sha512_compress(md, md->buf);
md->curlen = 0;
}
/* pad upto 120 bytes of zeroes
* note: that from 112 to 120 is the 64 MSB of the length. We assume that you won't hash
* > 2^64 bits of data... :-)
*/
while (md->curlen < 120) {
md->buf[md->curlen++] = (unsigned char)0;
}
/* store length */
STORE64H(md->length, md->buf+120);
sha512_compress(md, md->buf);
/* copy output */
for (i = 0; i < 8; i++) {
STORE64H(md->state[i], out+(8*i));
}
return 0;
}
int sha512(const unsigned char *message, size_t message_len, unsigned char *out)
{
sha512_context ctx;
int ret;
if ((ret = sha512_init(&ctx))) return ret;
if ((ret = sha512_update(&ctx, message, message_len))) return ret;
if ((ret = sha512_final(&ctx, out))) return ret;
return 0;
}

21
src/ed25519/sha512.h Normal file
View file

@ -0,0 +1,21 @@
#ifndef SHA512_H
#define SHA512_H
#include <stddef.h>
#include "fixedint.h"
/* state */
typedef struct sha512_context_ {
uint64_t length, state[8];
size_t curlen;
unsigned char buf[128];
} sha512_context;
int sha512_init(sha512_context * md);
int sha512_final(sha512_context * md, unsigned char *out);
int sha512_update(sha512_context * md, const unsigned char *in, size_t inlen);
int sha512(const unsigned char *message, size_t message_len, unsigned char *out);
#endif

31
src/ed25519/sign.c Normal file
View file

@ -0,0 +1,31 @@
#include "ed25519.h"
#include "sha512.h"
#include "ge.h"
#include "sc.h"
void ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key) {
sha512_context hash;
unsigned char hram[64];
unsigned char r[64];
ge_p3 R;
sha512_init(&hash);
sha512_update(&hash, private_key + 32, 32);
sha512_update(&hash, message, message_len);
sha512_final(&hash, r);
sc_reduce(r);
ge_scalarmult_base(&R, r);
ge_p3_tobytes(signature, &R);
sha512_init(&hash);
sha512_update(&hash, signature, 32);
sha512_update(&hash, public_key, 32);
sha512_update(&hash, message, message_len);
sha512_final(&hash, hram);
sc_reduce(hram);
sc_muladd(signature + 32, hram, private_key, r);
}

77
src/ed25519/verify.c Normal file
View file

@ -0,0 +1,77 @@
#include "ed25519.h"
#include "sha512.h"
#include "ge.h"
#include "sc.h"
static int consttime_equal(const unsigned char *x, const unsigned char *y) {
unsigned char r = 0;
r = x[0] ^ y[0];
#define F(i) r |= x[i] ^ y[i]
F(1);
F(2);
F(3);
F(4);
F(5);
F(6);
F(7);
F(8);
F(9);
F(10);
F(11);
F(12);
F(13);
F(14);
F(15);
F(16);
F(17);
F(18);
F(19);
F(20);
F(21);
F(22);
F(23);
F(24);
F(25);
F(26);
F(27);
F(28);
F(29);
F(30);
F(31);
#undef F
return !r;
}
int ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key) {
unsigned char h[64];
unsigned char checker[32];
sha512_context hash;
ge_p3 A;
ge_p2 R;
if (signature[63] & 224) {
return 0;
}
if (ge_frombytes_negate_vartime(&A, public_key) != 0) {
return 0;
}
sha512_init(&hash);
sha512_update(&hash, signature, 32);
sha512_update(&hash, public_key, 32);
sha512_update(&hash, message, message_len);
sha512_final(&hash, h);
sc_reduce(h);
ge_double_scalarmult_vartime(&R, h, &A, signature + 32);
ge_tobytes(checker, &R);
if (!consttime_equal(checker, signature)) {
return 0;
}
return 1;
}

View file

@ -110,11 +110,13 @@ bool dump_edges(connection_t *c) {
for splay_each(node_t, n, node_tree) { for splay_each(node_t, n, node_tree) {
for splay_each(edge_t, e, n->edge_tree) { for splay_each(edge_t, e, n->edge_tree) {
char *address = sockaddr2hostname(&e->address); char *address = sockaddr2hostname(&e->address);
send_request(c, "%d %d %s %s %s %x %d", char* local_address = sockaddr2hostname(&e->local_address);
send_request(c, "%d %d %s %s %s %s %x %d",
CONTROL, REQ_DUMP_EDGES, CONTROL, REQ_DUMP_EDGES,
e->from->name, e->to->name, address, e->from->name, e->to->name, address,
e->options, e->weight); local_address, e->options, e->weight);
free(address); free(address);
free(local_address);
} }
} }

View file

@ -30,6 +30,7 @@ typedef struct edge_t {
struct node_t *from; struct node_t *from;
struct node_t *to; struct node_t *to;
sockaddr_t address; sockaddr_t address;
sockaddr_t local_address;
uint32_t options; /* options turned on for this edge */ uint32_t options; /* options turned on for this edge */
int weight; /* weight of this edge */ int weight; /* weight of this edge */

View file

@ -23,15 +23,26 @@
#include "event.h" #include "event.h"
#include "net.h" #include "net.h"
#include "utils.h" #include "utils.h"
#include "xalloc.h"
struct timeval now; struct timeval now;
#ifndef HAVE_MINGW
static fd_set readfds; static fd_set readfds;
static fd_set writefds; static fd_set writefds;
static volatile bool running; #else
static const long READ_EVENTS = FD_READ | FD_ACCEPT | FD_CLOSE;
static const long WRITE_EVENTS = FD_WRITE | FD_CONNECT;
static DWORD event_count = 0;
#endif
static bool running;
static int io_compare(const io_t *a, const io_t *b) { static int io_compare(const io_t *a, const io_t *b) {
#ifndef HAVE_MINGW
return a->fd - b->fd; return a->fd - b->fd;
#else
return a->event - b->event;
#endif
} }
static int timeout_compare(const timeout_t *a, const timeout_t *b) { static int timeout_compare(const timeout_t *a, const timeout_t *b) {
@ -60,6 +71,14 @@ void io_add(io_t *io, io_cb_t cb, void *data, int fd, int flags) {
return; return;
io->fd = fd; io->fd = fd;
#ifdef HAVE_MINGW
if (io->fd != -1) {
io->event = WSACreateEvent();
if (io->event == WSA_INVALID_EVENT)
abort();
}
event_count++;
#endif
io->cb = cb; io->cb = cb;
io->data = data; io->data = data;
io->node.data = io; io->node.data = io;
@ -70,9 +89,21 @@ void io_add(io_t *io, io_cb_t cb, void *data, int fd, int flags) {
abort(); abort();
} }
void io_set(io_t *io, int flags) { #ifdef HAVE_MINGW
io->flags = flags; void io_add_event(io_t *io, io_cb_t cb, void *data, WSAEVENT event) {
io->event = event;
io_add(io, cb, data, -1, 0);
}
#endif
void io_set(io_t *io, int flags) {
if (flags == io->flags)
return;
io->flags = flags;
if (io->fd == -1)
return;
#ifndef HAVE_MINGW
if(flags & IO_READ) if(flags & IO_READ)
FD_SET(io->fd, &readfds); FD_SET(io->fd, &readfds);
else else
@ -82,6 +113,15 @@ void io_set(io_t *io, int flags) {
FD_SET(io->fd, &writefds); FD_SET(io->fd, &writefds);
else else
FD_CLR(io->fd, &writefds); FD_CLR(io->fd, &writefds);
#else
long events = 0;
if (flags & IO_WRITE)
events |= WRITE_EVENTS;
if (flags & IO_READ)
events |= READ_EVENTS;
if (WSAEventSelect(io->fd, io->event, events) != 0)
abort();
#endif
} }
void io_del(io_t *io) { void io_del(io_t *io) {
@ -89,6 +129,11 @@ void io_del(io_t *io) {
return; return;
io_set(io, 0); io_set(io, 0);
#ifdef HAVE_MINGW
if (io->fd != -1 && WSACloseEvent(io->event) == FALSE)
abort();
event_count--;
#endif
splay_unlink_node(&io_tree, &io->node); splay_unlink_node(&io_tree, &io->node);
io->cb = NULL; io->cb = NULL;
@ -182,30 +227,37 @@ void signal_del(signal_t *sig) {
} }
#endif #endif
bool event_loop(void) { static struct timeval * get_time_remaining(struct timeval *diff) {
running = true;
fd_set readable;
fd_set writable;
while(running) {
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
struct timeval diff, *tv = NULL; struct timeval *tv = NULL;
while(timeout_tree.head) { while(timeout_tree.head) {
timeout_t *timeout = timeout_tree.head->data; timeout_t *timeout = timeout_tree.head->data;
timersub(&timeout->tv, &now, &diff); timersub(&timeout->tv, &now, diff);
if(diff.tv_sec < 0) { if(diff->tv_sec < 0) {
timeout->cb(timeout->data); timeout->cb(timeout->data);
if(timercmp(&timeout->tv, &now, <)) if(timercmp(&timeout->tv, &now, <))
timeout_del(timeout); timeout_del(timeout);
} else { } else {
tv = &diff; tv = diff;
break; break;
} }
} }
return tv;
}
bool event_loop(void) {
running = true;
#ifndef HAVE_MINGW
fd_set readable;
fd_set writable;
while(running) {
struct timeval diff;
struct timeval *tv = get_time_remaining(&diff);
memcpy(&readable, &readfds, sizeof readable); memcpy(&readable, &readfds, sizeof readable);
memcpy(&writable, &writefds, sizeof writable); memcpy(&writable, &writefds, sizeof writable);
@ -216,16 +268,10 @@ bool event_loop(void) {
fds = last->fd + 1; fds = last->fd + 1;
} }
#ifdef HAVE_MINGW
LeaveCriticalSection(&mutex);
#endif
int n = select(fds, &readable, &writable, NULL, tv); int n = select(fds, &readable, &writable, NULL, tv);
#ifdef HAVE_MINGW
EnterCriticalSection(&mutex);
#endif
if(n < 0) { if(n < 0) {
if(sockwouldblock(errno)) if(sockwouldblock(sockerrno))
continue; continue;
else else
return false; return false;
@ -241,16 +287,77 @@ bool event_loop(void) {
io->cb(io->data, IO_READ); io->cb(io->data, IO_READ);
} }
} }
#else
while (running) {
struct timeval diff;
struct timeval *tv = get_time_remaining(&diff);
DWORD timeout_ms = tv ? (tv->tv_sec * 1000 + tv->tv_usec / 1000 + 1) : WSA_INFINITE;
if (!event_count) {
Sleep(timeout_ms);
continue;
}
/*
For some reason, Microsoft decided to make the FD_WRITE event edge-triggered instead of level-triggered,
which is the opposite of what select() does. In practice, that means that if a FD_WRITE event triggers,
it will never trigger again until a send() returns EWOULDBLOCK. Since the semantics of this event loop
is that write events are level-triggered (i.e. they continue firing until the socket is full), we need
to emulate these semantics by making sure we fire each IO_WRITE that is still writeable.
Note that technically FD_CLOSE has the same problem, but it's okay because user code does not rely on
this event being fired again if ignored.
*/
io_t* writeable_io = NULL;
for splay_each(io_t, io, &io_tree)
if (io->flags & IO_WRITE && send(io->fd, NULL, 0, 0) == 0) {
writeable_io = io;
break;
}
if (writeable_io) {
writeable_io->cb(writeable_io->data, IO_WRITE);
continue;
}
WSAEVENT* events = xmalloc(event_count * sizeof(*events));
DWORD event_index = 0;
for splay_each(io_t, io, &io_tree) {
events[event_index] = io->event;
event_index++;
}
DWORD result = WSAWaitForMultipleEvents(event_count, events, FALSE, timeout_ms, FALSE);
WSAEVENT event;
if (result >= WSA_WAIT_EVENT_0 && result < WSA_WAIT_EVENT_0 + event_count)
event = events[result - WSA_WAIT_EVENT_0];
free(events);
if (result == WSA_WAIT_TIMEOUT)
continue;
if (result < WSA_WAIT_EVENT_0 || result >= WSA_WAIT_EVENT_0 + event_count)
return false;
io_t *io = splay_search(&io_tree, &((io_t){.event = event}));
if (!io)
abort();
if (io->fd == -1) {
io->cb(io->data, 0);
} else {
WSANETWORKEVENTS network_events;
if (WSAEnumNetworkEvents(io->fd, io->event, &network_events) != 0)
return false;
if (network_events.lNetworkEvents & WRITE_EVENTS)
io->cb(io->data, IO_WRITE);
if (network_events.lNetworkEvents & READ_EVENTS)
io->cb(io->data, IO_READ);
}
}
#endif
return true; return true;
} }
void event_flush_output(void) {
for splay_each(io_t, io, &io_tree)
if(FD_ISSET(io->fd, &writefds))
io->cb(io->data, IO_WRITE);
}
void event_exit(void) { void event_exit(void) {
running = false; running = false;
} }

View file

@ -32,6 +32,9 @@ typedef void (*signal_cb_t)(void *data);
typedef struct io_t { typedef struct io_t {
int fd; int fd;
int flags; int flags;
#ifdef HAVE_MINGW
WSAEVENT event;
#endif
io_cb_t cb; io_cb_t cb;
void *data; void *data;
splay_node_t node; splay_node_t node;
@ -54,6 +57,9 @@ typedef struct signal_t {
extern struct timeval now; extern struct timeval now;
extern void io_add(io_t *io, io_cb_t cb, void *data, int fd, int flags); extern void io_add(io_t *io, io_cb_t cb, void *data, int fd, int flags);
#ifdef HAVE_MINGW
extern void io_add_event(io_t *io, io_cb_t cb, void* data, WSAEVENT event);
#endif
extern void io_del(io_t *io); extern void io_del(io_t *io);
extern void io_set(io_t *io, int flags); extern void io_set(io_t *io, int flags);
@ -65,7 +71,6 @@ extern void signal_add(signal_t *sig, signal_cb_t cb, void *data, int signum);
extern void signal_del(signal_t *sig); extern void signal_del(signal_t *sig);
extern bool event_loop(void); extern bool event_loop(void);
extern void event_flush_output(void);
extern void event_exit(void); extern void event_exit(void);
#endif #endif

View file

@ -176,9 +176,13 @@ static void sssp_bfs(void) {
&& (e->to->distance != n->distance + 1 || e->weight >= e->to->prevedge->weight)) && (e->to->distance != n->distance + 1 || e->weight >= e->to->prevedge->weight))
continue; continue;
// Only update nexthop if it doesn't increase the path length
if(!e->to->status.visited || (e->to->distance == n->distance + 1 && e->weight >= e->to->prevedge->weight))
e->to->nexthop = (n->nexthop == myself) ? e->to : n->nexthop;
e->to->status.visited = true; e->to->status.visited = true;
e->to->status.indirect = indirect; e->to->status.indirect = indirect;
e->to->nexthop = (n->nexthop == myself) ? e->to : n->nexthop;
e->to->prevedge = e; e->to->prevedge = e;
e->to->via = indirect ? n->via : e->to; e->to->via = indirect ? n->via : e->to;
e->to->options = e->options; e->to->options = e->options;
@ -200,6 +204,9 @@ static void sssp_bfs(void) {
static void check_reachability(void) { static void check_reachability(void) {
/* Check reachability status. */ /* Check reachability status. */
int reachable_count = 0;
int became_reachable_count = 0;
int became_unreachable_count = 0;
for splay_each(node_t, n, node_tree) { for splay_each(node_t, n, node_tree) {
if(n->status.visited != n->status.reachable) { if(n->status.visited != n->status.reachable) {
n->status.reachable = !n->status.reachable; n->status.reachable = !n->status.reachable;
@ -208,9 +215,13 @@ static void check_reachability(void) {
if(n->status.reachable) { if(n->status.reachable) {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Node %s (%s) became reachable", logger(DEBUG_TRAFFIC, LOG_DEBUG, "Node %s (%s) became reachable",
n->name, n->hostname); n->name, n->hostname);
if (n != myself)
became_reachable_count++;
} else { } else {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Node %s (%s) became unreachable", logger(DEBUG_TRAFFIC, LOG_DEBUG, "Node %s (%s) became unreachable",
n->name, n->hostname); n->name, n->hostname);
if (n != myself)
became_unreachable_count++;
} }
if(experimental && OPTION_VERSION(n->options) >= 2) if(experimental && OPTION_VERSION(n->options) >= 2)
@ -264,15 +275,18 @@ static void check_reachability(void) {
update_node_udp(n, NULL); update_node_udp(n, NULL);
memset(&n->status, 0, sizeof n->status); memset(&n->status, 0, sizeof n->status);
n->options = 0; n->options = 0;
} else if(n->connection) {
if(n->status.sptps) {
if(n->connection->outgoing)
send_req_key(n);
} else {
send_ans_key(n);
} }
} }
if(n->status.reachable && n != myself)
reachable_count++;
} }
if (device_standby) {
if (reachable_count == 0 && became_unreachable_count > 0)
device_disable();
else if (reachable_count > 0 && reachable_count == became_reachable_count)
device_enable();
} }
} }

View file

@ -91,6 +91,13 @@ void *hash_search_or_insert(hash_t *hash, const void *key, const void *value) {
return NULL; return NULL;
} }
/* Deleting */
void hash_delete(hash_t *hash, const void *key) {
uint32_t i = modulo(hash_function(key, hash->size), hash->n);
hash->values[i] = NULL;
}
/* Utility functions */ /* Utility functions */
void hash_clear(hash_t *hash) { void hash_clear(hash_t *hash) {

View file

@ -31,6 +31,7 @@ extern hash_t *hash_alloc(size_t n, size_t size) __attribute__ ((__malloc__));
extern void hash_free(hash_t *); extern void hash_free(hash_t *);
extern void hash_insert(hash_t *, const void *key, const void *value); extern void hash_insert(hash_t *, const void *key, const void *value);
extern void hash_delete(hash_t *, const void *key);
extern void *hash_search(const hash_t *, const void *key); extern void *hash_search(const hash_t *, const void *key);
extern void *hash_search_or_insert(hash_t *, const void *key, const void *value); extern void *hash_search_or_insert(hash_t *, const void *key, const void *value);

View file

@ -39,6 +39,7 @@
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <limits.h>
#ifdef HAVE_MINGW #ifdef HAVE_MINGW
#include <w32api.h> #include <w32api.h>

View file

@ -24,6 +24,7 @@
#include "subnet.h" #include "subnet.h"
#include "tincctl.h" #include "tincctl.h"
#include "info.h" #include "info.h"
#include "utils.h"
#include "xalloc.h" #include "xalloc.h"
void logger(int level, int priority, const char *format, ...) { void logger(int level, int priority, const char *format, ...) {
@ -49,6 +50,7 @@ static int info_node(int fd, const char *item) {
char line[4096]; char line[4096];
char node[4096]; char node[4096];
char id[4096];
char from[4096]; char from[4096];
char to[4096]; char to[4096];
char subnet[4096]; char subnet[4096];
@ -67,12 +69,12 @@ static int info_node(int fd, const char *item) {
long int last_state_change; long int last_state_change;
while(recvline(fd, line, sizeof line)) { while(recvline(fd, line, sizeof line)) {
int n = sscanf(line, "%d %d %s %s port %s %d %d %d %d %x %"PRIx32" %s %s %d %hd %hd %hd %ld", &code, &req, node, host, port, &cipher, &digest, &maclength, &compression, &options, &status_union.raw, nexthop, via, &distance, &pmtu, &minmtu, &maxmtu, &last_state_change); int n = sscanf(line, "%d %d %s %s %s port %s %d %d %d %d %x %"PRIx32" %s %s %d %hd %hd %hd %ld", &code, &req, node, id, host, port, &cipher, &digest, &maclength, &compression, &options, &status_union.raw, nexthop, via, &distance, &pmtu, &minmtu, &maxmtu, &last_state_change);
if(n == 2) if(n == 2)
break; break;
if(n != 18) { if(n != 19) {
fprintf(stderr, "Unable to parse node dump from tincd.\n"); fprintf(stderr, "Unable to parse node dump from tincd.\n");
return 1; return 1;
} }
@ -94,6 +96,7 @@ static int info_node(int fd, const char *item) {
} }
printf("Node: %s\n", item); printf("Node: %s\n", item);
printf("Node ID: %s\n", id);
printf("Address: %s port %s\n", host, port); printf("Address: %s port %s\n", host, port);
char timestr[32] = "never"; char timestr[32] = "never";

View file

@ -1,6 +1,6 @@
/* /*
invitation.c -- Create and accept invitations invitation.c -- Create and accept invitations
Copyright (C) 2013 Guus Sliepen <guus@tinc-vpn.org> Copyright (C) 2013-2014 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
@ -142,12 +142,19 @@ char *get_my_hostname() {
} }
} }
if(!tty) {
if(!hostname) {
fprintf(stderr, "Could not determine the external address or hostname. Please set Address manually.\n");
return NULL;
}
goto save;
}
again: again:
printf("Please enter your host's external address or hostname"); fprintf(stderr, "Please enter your host's external address or hostname");
if(hostname) if(hostname)
printf(" [%s]", hostname); fprintf(stderr, " [%s]", hostname);
printf(": "); fprintf(stderr, ": ");
fflush(stdout);
if(!fgets(line, sizeof line, stdin)) { if(!fgets(line, sizeof line, stdin)) {
fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno)); fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno));
@ -190,8 +197,10 @@ done:
else else
xasprintf(&hostport, "%s:%s", hostname, port); xasprintf(&hostport, "%s:%s", hostname, port);
} else { } else {
hostport = hostname; if(strchr(hostname, ':'))
hostname = NULL; xasprintf(&hostport, "[%s]", hostname);
else
hostport = xstrdup(hostname);
} }
free(hostname); free(hostname);
@ -241,7 +250,7 @@ int cmd_invite(int argc, char *argv[]) {
} }
free(filename); free(filename);
// If a daemon is running, ensure no other nodes now about this name // If a daemon is running, ensure no other nodes know about this name
bool found = false; bool found = false;
if(connect_tincd(false)) { if(connect_tincd(false)) {
sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES); sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);
@ -312,7 +321,7 @@ int cmd_invite(int argc, char *argv[]) {
free(filename); free(filename);
ecdsa_t *key; ecdsa_t *key;
xasprintf(&filename, "%s" SLASH "invitations" SLASH "ecdsa_key.priv", confbase); xasprintf(&filename, "%s" SLASH "invitations" SLASH "ed25519_key.priv", confbase);
// Remove the key if there are no outstanding invitations. // Remove the key if there are no outstanding invitations.
if(!count) if(!count)
@ -404,8 +413,12 @@ int cmd_invite(int argc, char *argv[]) {
char buf[1024]; char buf[1024];
while(fgets(buf, sizeof buf, tc)) { while(fgets(buf, sizeof buf, tc)) {
if((!strncasecmp(buf, "Mode", 4) && strchr(" \t=", buf[4])) if((!strncasecmp(buf, "Mode", 4) && strchr(" \t=", buf[4]))
|| (!strncasecmp(buf, "Broadcast", 9) && strchr(" \t=", buf[9]))) || (!strncasecmp(buf, "Broadcast", 9) && strchr(" \t=", buf[9]))) {
fputs(buf, f); fputs(buf, f);
// Make sure there is a newline character.
if(!strchr(buf, '\n'))
fputc('\n', f);
}
} }
fclose(tc); fclose(tc);
} }
@ -567,7 +580,7 @@ make_names:
if(!access(tinc_conf, F_OK)) { if(!access(tinc_conf, F_OK)) {
fprintf(stderr, "Configuration file %s already exists!\n", tinc_conf); fprintf(stderr, "Configuration file %s already exists!\n", tinc_conf);
if(!tty || confbasegiven) if(confbasegiven)
return false; return false;
// Generate a random netname, ask for a better one later. // Generate a random netname, ask for a better one later.
@ -600,6 +613,7 @@ make_names:
FILE *fh = fopen(filename, "w"); FILE *fh = fopen(filename, "w");
if(!fh) { if(!fh) {
fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno)); fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno));
fclose(f);
return false; return false;
} }
@ -709,7 +723,7 @@ make_names:
if(!b64key) if(!b64key)
return false; return false;
xasprintf(&filename, "%s" SLASH "ecdsa_key.priv", confbase); xasprintf(&filename, "%s" SLASH "ed25519_key.priv", confbase);
f = fopenmask(filename, "w", 0600); f = fopenmask(filename, "w", 0600);
if(!ecdsa_write_pem_private_key(key, f)) { if(!ecdsa_write_pem_private_key(key, f)) {
@ -721,7 +735,7 @@ make_names:
fclose(f); fclose(f);
fprintf(fh, "ECDSAPublicKey = %s\n", b64key); fprintf(fh, "Ed25519PublicKey = %s\n", b64key);
sptps_send_record(&sptps, 1, b64key, strlen(b64key)); sptps_send_record(&sptps, 1, b64key, strlen(b64key));
free(b64key); free(b64key);
@ -743,7 +757,7 @@ make_names:
check_port(name); check_port(name);
ask_netname: ask_netname:
if(ask_netname) { if(ask_netname && tty) {
fprintf(stderr, "Enter a new netname: "); fprintf(stderr, "Enter a new netname: ");
if(!fgets(line, sizeof line, stdin)) { if(!fgets(line, sizeof line, stdin)) {
fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno)); fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno));
@ -767,11 +781,13 @@ ask_netname:
make_names(); make_names();
} }
fprintf(stderr, "Configuration stored in: %s\n", confbase);
return true; return true;
} }
static bool invitation_send(void *handle, uint8_t type, const char *data, size_t len) { static bool invitation_send(void *handle, uint8_t type, const void *data, size_t len) {
while(len) { while(len) {
int result = send(sock, data, len, 0); int result = send(sock, data, len, 0);
if(result == -1 && errno == EINTR) if(result == -1 && errno == EINTR)
@ -784,7 +800,7 @@ static bool invitation_send(void *handle, uint8_t type, const char *data, size_t
return true; return true;
} }
static bool invitation_receive(void *handle, uint8_t type, const char *msg, uint16_t len) { static bool invitation_receive(void *handle, uint8_t type, const void *msg, uint16_t len) {
switch(type) { switch(type) {
case SPTPS_HANDSHAKE: case SPTPS_HANDSHAKE:
return sptps_send_record(&sptps, 0, cookie, sizeof cookie); return sptps_send_record(&sptps, 0, cookie, sizeof cookie);
@ -850,10 +866,8 @@ int cmd_join(int argc, char *argv[]) {
if(argc > 1) { if(argc > 1) {
invitation = argv[1]; invitation = argv[1];
} else { } else {
if(tty) { if(tty)
printf("Enter invitation URL: "); fprintf(stderr, "Enter invitation URL: ");
fflush(stdout);
}
errno = EPIPE; errno = EPIPE;
if(!fgets(line, sizeof line, stdin)) { if(!fgets(line, sizeof line, stdin)) {
fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno)); fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno));
@ -893,7 +907,7 @@ int cmd_join(int argc, char *argv[]) {
if(!port || !*port) if(!port || !*port)
port = "655"; port = "655";
if(!b64decode(slash, hash, 18) || !b64decode(slash + 24, cookie, 18)) if(!b64decode(slash, hash, 24) || !b64decode(slash + 24, cookie, 24))
goto invalid; goto invalid;
// Generate a throw-away key for the invitation. // Generate a throw-away key for the invitation.

View file

@ -1,7 +1,7 @@
/* /*
device.c -- Interaction with Linux ethertap and tun/tap device device.c -- Interaction with Linux ethertap and tun/tap device
Copyright (C) 2001-2005 Ivo Timmermans, Copyright (C) 2001-2005 Ivo Timmermans,
2001-2013 Guus Sliepen <guus@tinc-vpn.org> 2001-2014 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
@ -46,11 +46,6 @@ static char *type = NULL;
static char ifrname[IFNAMSIZ]; static char ifrname[IFNAMSIZ];
static char *device_info; static char *device_info;
uint64_t device_in_packets = 0;
uint64_t device_in_bytes = 0;
uint64_t device_out_packets = 0;
uint64_t device_out_bytes = 0;
static bool setup_device(void) { static bool setup_device(void) {
if(!get_config_string(lookup_config(config_tree, "Device"), &device)) if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = xstrdup(DEFAULT_DEVICE); device = xstrdup(DEFAULT_DEVICE);
@ -110,15 +105,25 @@ static bool setup_device(void) {
logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info); logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
if(ifr.ifr_flags & IFF_TAP) {
struct ifreq ifr_mac = {};
if(!ioctl(device_fd, SIOCGIFHWADDR, &ifr_mac))
memcpy(mymac.x, ifr_mac.ifr_hwaddr.sa_data, ETH_ALEN);
else
logger(DEBUG_ALWAYS, LOG_WARNING, "Could not get MAC address of %s: %s", device, strerror(errno));
}
return true; return true;
} }
static void close_device(void) { static void close_device(void) {
close(device_fd); close(device_fd);
device_fd = -1;
free(type); free(type); type = NULL;
free(device); free(device); device = NULL;
free(iface); free(iface); iface = NULL;
device_info = NULL;
} }
static bool read_packet(vpn_packet_t *packet) { static bool read_packet(vpn_packet_t *packet) {
@ -126,7 +131,7 @@ static bool read_packet(vpn_packet_t *packet) {
switch(device_type) { switch(device_type) {
case DEVICE_TYPE_TUN: case DEVICE_TYPE_TUN:
inlen = read(device_fd, packet->data + 10, MTU - 10); inlen = read(device_fd, DATA(packet) + 10, MTU - 10);
if(inlen <= 0) { if(inlen <= 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s",
@ -134,11 +139,11 @@ static bool read_packet(vpn_packet_t *packet) {
return false; return false;
} }
memset(packet->data, 0, 12); memset(DATA(packet), 0, 12);
packet->len = inlen + 10; packet->len = inlen + 10;
break; break;
case DEVICE_TYPE_TAP: case DEVICE_TYPE_TAP:
inlen = read(device_fd, packet->data, MTU); inlen = read(device_fd, DATA(packet), MTU);
if(inlen <= 0) { if(inlen <= 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s",
@ -152,9 +157,6 @@ static bool read_packet(vpn_packet_t *packet) {
abort(); abort();
} }
device_in_packets++;
device_in_bytes += packet->len;
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len,
device_info); device_info);
@ -167,15 +169,15 @@ static bool write_packet(vpn_packet_t *packet) {
switch(device_type) { switch(device_type) {
case DEVICE_TYPE_TUN: case DEVICE_TYPE_TUN:
packet->data[10] = packet->data[11] = 0; DATA(packet)[10] = DATA(packet)[11] = 0;
if(write(device_fd, packet->data + 10, packet->len - 10) < 0) { 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;
} }
break; break;
case DEVICE_TYPE_TAP: case DEVICE_TYPE_TAP:
if(write(device_fd, packet->data, packet->len) < 0) { if(write(device_fd, DATA(packet), packet->len) < 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;
@ -185,22 +187,12 @@ static bool write_packet(vpn_packet_t *packet) {
abort(); abort();
} }
device_out_packets++;
device_out_bytes += packet->len;
return true; return true;
} }
static void dump_device_stats(void) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "Statistics for %s %s:", device_info, device);
logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes in: %10"PRIu64, device_in_bytes);
logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes out: %10"PRIu64, device_out_bytes);
}
const devops_t os_devops = { const devops_t os_devops = {
.setup = setup_device, .setup = setup_device,
.close = close_device, .close = close_device,
.read = read_packet, .read = read_packet,
.write = write_packet, .write = write_packet,
.dump_stats = dump_device_stats,
}; };

View file

@ -65,6 +65,8 @@ enum {
#endif #endif
#endif #endif
#include <stdbool.h>
extern debug_t debug_level; extern debug_t debug_level;
extern bool logcontrol; extern bool logcontrol;
extern void openlogger(const char *, logmode_t); extern void openlogger(const char *, logmode_t);

View file

@ -1,6 +1,6 @@
/* /*
meta.c -- handle the meta communication meta.c -- handle the meta communication
Copyright (C) 2000-2013 Guus Sliepen <guus@tinc-vpn.org>, Copyright (C) 2000-2014 Guus Sliepen <guus@tinc-vpn.org>,
2000-2005 Ivo Timmermans 2000-2005 Ivo Timmermans
2006 Scott Lamb <slamb@slamb.org> 2006 Scott Lamb <slamb@slamb.org>
@ -30,7 +30,7 @@
#include "utils.h" #include "utils.h"
#include "xalloc.h" #include "xalloc.h"
bool send_meta_sptps(void *handle, uint8_t type, const char *buffer, size_t length) { bool send_meta_sptps(void *handle, uint8_t type, const void *buffer, size_t length) {
connection_t *c = handle; connection_t *c = handle;
if(!c) { if(!c) {
@ -76,11 +76,12 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
void broadcast_meta(connection_t *from, const char *buffer, int length) { void broadcast_meta(connection_t *from, const char *buffer, int length) {
for list_each(connection_t, c, connection_list) for list_each(connection_t, c, connection_list)
if(c != from && c->status.active) if(c != from && c->edge)
send_meta(c, buffer, length); send_meta(c, buffer, length);
} }
bool receive_meta_sptps(void *handle, uint8_t type, const char *data, uint16_t length) { bool receive_meta_sptps(void *handle, uint8_t type, const void *vdata, uint16_t length) {
const char *data = vdata;
connection_t *c = handle; connection_t *c = handle;
if(!c) { if(!c) {
@ -142,7 +143,7 @@ bool receive_meta(connection_t *c) {
inlen = recv(c->socket, inbuf, sizeof inbuf - c->inbuf.len, 0); inlen = recv(c->socket, inbuf, sizeof inbuf - c->inbuf.len, 0);
if(inlen <= 0) { if(inlen <= 0) {
if(!inlen || !errno) { if(!inlen || !sockerrno) {
logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection closed by %s (%s)", logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection closed by %s (%s)",
c->name, c->hostname); c->name, c->hostname);
} else if(sockwouldblock(sockerrno)) } else if(sockwouldblock(sockerrno))

View file

@ -1,6 +1,6 @@
/* /*
meta.h -- header for meta.c meta.h -- header for meta.c
Copyright (C) 2000-2012 Guus Sliepen <guus@tinc-vpn.org>, Copyright (C) 2000-2014 Guus Sliepen <guus@tinc-vpn.org>,
2000-2005 Ivo Timmermans 2000-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
@ -24,8 +24,8 @@
#include "connection.h" #include "connection.h"
extern bool send_meta(struct connection_t *, const char *, int); extern bool send_meta(struct connection_t *, const char *, int);
extern bool send_meta_sptps(void *, uint8_t, const char *, size_t); extern bool send_meta_sptps(void *, uint8_t, const void *, size_t);
extern bool receive_meta_sptps(void *, uint8_t, const char *, uint16_t); extern bool receive_meta_sptps(void *, uint8_t, const void *, uint16_t);
extern void broadcast_meta(struct connection_t *, const char *, int); extern void broadcast_meta(struct connection_t *, const char *, int);
extern bool receive_meta(struct connection_t *); extern bool receive_meta(struct connection_t *);

View file

@ -1,7 +1,7 @@
/* /*
device.c -- Interaction with Windows tap driver in a MinGW environment device.c -- Interaction with Windows tap driver in a MinGW environment
Copyright (C) 2002-2005 Ivo Timmermans, Copyright (C) 2002-2005 Ivo Timmermans,
2002-2013 Guus Sliepen <guus@tinc-vpn.org> 2002-2014 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
@ -36,55 +36,52 @@
int device_fd = -1; int device_fd = -1;
static HANDLE device_handle = INVALID_HANDLE_VALUE; static HANDLE device_handle = INVALID_HANDLE_VALUE;
static io_t device_read_io;
static OVERLAPPED device_read_overlapped;
static vpn_packet_t device_read_packet;
char *device = NULL; char *device = NULL;
char *iface = NULL; char *iface = NULL;
static char *device_info = NULL; static char *device_info = NULL;
static uint64_t device_total_in = 0;
static uint64_t device_total_out = 0;
extern char *myport; extern char *myport;
static DWORD WINAPI tapreader(void *bla) { static void device_issue_read() {
device_read_overlapped.Offset = 0;
device_read_overlapped.OffsetHigh = 0;
int status; int status;
for (;;) {
DWORD len; DWORD len;
OVERLAPPED overlapped; status = ReadFile(device_handle, (void *)device_read_packet.data, MTU, &len, &device_read_overlapped);
vpn_packet_t packet; if (!status) {
if (GetLastError() != ERROR_IO_PENDING)
logger(DEBUG_ALWAYS, LOG_DEBUG, "Tap reader running");
/* Read from tap device and send to parent */
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
for(;;) {
overlapped.Offset = 0;
overlapped.OffsetHigh = 0;
ResetEvent(overlapped.hEvent);
status = ReadFile(device_handle, (void *)packet.data, MTU, &len, &overlapped);
if(!status) {
if(GetLastError() == ERROR_IO_PENDING) {
WaitForSingleObject(overlapped.hEvent, INFINITE);
if(!GetOverlappedResult(device_handle, &overlapped, &len, FALSE))
continue;
} else {
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 -1; break;
}
} }
EnterCriticalSection(&mutex); device_read_packet.len = len;
packet.len = len; device_read_packet.priority = 0;
packet.priority = 0; route(myself, &device_read_packet);
route(myself, &packet);
event_flush_output();
LeaveCriticalSection(&mutex);
} }
} }
static void device_handle_read(void *data, int flags) {
ResetEvent(device_read_overlapped.hEvent);
DWORD len;
if (!GetOverlappedResult(device_handle, &device_read_overlapped, &len, FALSE)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error getting read result from %s %s: %s", device_info,
device, strerror(errno));
return;
}
device_read_packet.len = len;
device_read_packet.priority = 0;
route(myself, &device_read_packet);
device_issue_read();
}
static bool setup_device(void) { static bool setup_device(void) {
HKEY key, key2; HKEY key, key2;
int i; int i;
@ -94,12 +91,10 @@ static bool setup_device(void) {
char adaptername[1024]; char adaptername[1024];
char tapname[1024]; char tapname[1024];
DWORD len; DWORD len;
unsigned long status;
bool found = false; bool found = false;
int err; int err;
HANDLE thread;
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);
@ -191,20 +186,6 @@ static bool setup_device(void) {
overwrite_mac = 1; overwrite_mac = 1;
} }
/* Start the tap reader */
thread = CreateThread(NULL, 0, tapreader, NULL, 0, NULL);
if(!thread) {
logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "CreateThread", winerror(GetLastError()));
return false;
}
/* Set media status for newer TAP-Win32 devices */
status = true;
DeviceIoControl(device_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, sizeof status, &status, sizeof status, &len, NULL);
device_info = "Windows tap device"; device_info = "Windows tap device";
logger(DEBUG_ALWAYS, LOG_INFO, "%s (%s) is a %s", device, iface, device_info); logger(DEBUG_ALWAYS, LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
@ -212,11 +193,36 @@ static bool setup_device(void) {
return true; return true;
} }
static void close_device(void) { static void enable_device(void) {
CloseHandle(device_handle); logger(DEBUG_ALWAYS, LOG_INFO, "Enabling %s", device_info);
free(device); ULONG status = 1;
free(iface); DWORD len;
DeviceIoControl(device_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, sizeof status, &status, sizeof status, &len, NULL);
io_add_event(&device_read_io, device_handle_read, NULL, CreateEvent(NULL, TRUE, FALSE, NULL));
device_read_overlapped.hEvent = device_read_io.event;
device_issue_read();
}
static void disable_device(void) {
logger(DEBUG_ALWAYS, LOG_INFO, "Disabling %s", device_info);
io_del(&device_read_io);
CancelIo(device_handle);
CloseHandle(device_read_overlapped.hEvent);
ULONG status = 0;
DWORD len;
DeviceIoControl(device_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, sizeof status, &status, sizeof status, &len, NULL);
}
static void close_device(void) {
CloseHandle(device_handle); device_handle = INVALID_HANDLE_VALUE;
free(device); device = NULL;
free(iface); iface = NULL;
device_info = NULL;
} }
static bool read_packet(vpn_packet_t *packet) { static bool read_packet(vpn_packet_t *packet) {
@ -230,26 +236,19 @@ 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(!WriteFile(device_handle, packet->data, packet->len, &outlen, &overlapped)) { if(!WriteFile(device_handle, DATA(packet), packet->len, &outlen, &overlapped)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info, device, winerror(GetLastError())); logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info, device, winerror(GetLastError()));
return false; return false;
} }
device_total_out += packet->len;
return true; return true;
} }
static void dump_device_stats(void) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "Statistics for %s %s:", device_info, device);
logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
}
const devops_t os_devops = { const devops_t os_devops = {
.setup = setup_device, .setup = setup_device,
.close = close_device, .close = close_device,
.read = read_packet, .read = read_packet,
.write = write_packet, .write = write_packet,
.dump_stats = dump_device_stats, .enable = enable_device,
.disable = disable_device,
}; };

View file

@ -31,9 +31,6 @@
static char *device_info; static char *device_info;
static uint64_t device_total_in = 0;
static uint64_t device_total_out = 0;
static struct addrinfo *ai = NULL; static struct addrinfo *ai = NULL;
static mac_t ignore_src = {{0}}; static mac_t ignore_src = {{0}};
@ -132,7 +129,7 @@ static bool setup_device(void) {
#endif #endif
default: default:
logger(DEBUG_ALWAYS, LOG_ERR, "Multicast for address family %hx unsupported", ai->ai_family); logger(DEBUG_ALWAYS, LOG_ERR, "Multicast for address family %x unsupported", ai->ai_family);
goto error; goto error;
} }
@ -151,33 +148,33 @@ error:
} }
static void close_device(void) { static void close_device(void) {
close(device_fd); close(device_fd); device_fd = -1;
free(device); free(device); device = NULL;
free(iface); free(iface); iface = NULL;
if(ai) if(ai) {
freeaddrinfo(ai); freeaddrinfo(ai); ai = NULL;
}
device_info = NULL;
} }
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, (void *)packet->data, MTU, 0)) <= 0) { if((lenin = recv(device_fd, 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, strerror(errno)); device, sockstrerror(sockerrno));
return false; return false;
} }
if(!memcmp(&ignore_src, packet->data + 6, sizeof ignore_src)) { if(!memcmp(&ignore_src, DATA(packet) + 6, sizeof ignore_src)) {
logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Ignoring loopback packet of %d bytes from %s", lenin, device_info); logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Ignoring loopback packet of %d bytes from %s", lenin, device_info);
return false; return false;
} }
packet->len = lenin; packet->len = lenin;
device_total_in += packet->len;
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len,
device_info); device_info);
@ -188,45 +185,20 @@ 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, (void *)packet->data, packet->len, 0, ai->ai_addr, ai->ai_addrlen) < 0) { if(sendto(device_fd, 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,
strerror(errno)); sockstrerror(sockerrno));
return false; return false;
} }
device_total_out += packet->len; memcpy(&ignore_src, DATA(packet) + 6, sizeof ignore_src);
memcpy(&ignore_src, packet->data + 6, sizeof ignore_src);
return true; return true;
} }
static void dump_device_stats(void) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "Statistics for %s %s:", device_info, device);
logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
}
const devops_t multicast_devops = { const devops_t multicast_devops = {
.setup = setup_device, .setup = setup_device,
.close = close_device, .close = close_device,
.read = read_packet, .read = read_packet,
.write = write_packet, .write = write_packet,
.dump_stats = dump_device_stats,
}; };
#if 0
static bool not_supported(void) {
logger(DEBUG_ALWAYS, LOG_ERR, "Raw socket device not supported on this platform");
return false;
}
const devops_t multicast_devops = {
.setup = not_supported,
.close = NULL,
.read = NULL,
.write = NULL,
.dump_stats = NULL,
};
#endif

View file

@ -64,8 +64,6 @@ void make_names(void) {
else else
xasprintf(&confbase, "%s", installdir); xasprintf(&confbase, "%s", installdir);
} }
if(!pidfilename)
xasprintf(&pidfilename, "%s" SLASH "pid", confbase);
} }
RegCloseKey(key); RegCloseKey(key);
} }
@ -73,11 +71,26 @@ void make_names(void) {
if(!confdir) if(!confdir)
confdir = xstrdup(CONFDIR SLASH "tinc"); confdir = xstrdup(CONFDIR SLASH "tinc");
if(!confbase) {
if(netname)
xasprintf(&confbase, CONFDIR SLASH "tinc" SLASH "%s", netname);
else
xasprintf(&confbase, CONFDIR SLASH "tinc");
}
#ifdef HAVE_MINGW
if(!logfilename)
xasprintf(&logfilename, "%s" SLASH "log", confbase);
if(!pidfilename)
xasprintf(&pidfilename, "%s" SLASH "pid", confbase);
#else
if(!logfilename) if(!logfilename)
xasprintf(&logfilename, LOCALSTATEDIR SLASH "log" SLASH "%s.log", identname); xasprintf(&logfilename, LOCALSTATEDIR SLASH "log" SLASH "%s.log", identname);
if(!pidfilename) if(!pidfilename)
xasprintf(&pidfilename, LOCALSTATEDIR SLASH "run" SLASH "%s.pid", identname); xasprintf(&pidfilename, LOCALSTATEDIR SLASH "run" SLASH "%s.pid", identname);
#endif
if(!unixsocketname) { if(!unixsocketname) {
int len = strlen(pidfilename); int len = strlen(pidfilename);
@ -88,13 +101,6 @@ void make_names(void) {
else else
strcpy(unixsocketname + len, ".socket"); strcpy(unixsocketname + len, ".socket");
} }
if(!confbase) {
if(netname)
xasprintf(&confbase, CONFDIR SLASH "tinc" SLASH "%s", netname);
else
xasprintf(&confbase, CONFDIR SLASH "tinc");
}
} }
void free_names(void) { void free_names(void) {

View file

@ -36,6 +36,10 @@
#include "subnet.h" #include "subnet.h"
#include "xalloc.h" #include "xalloc.h"
#ifdef HAVE_RESOLV_H
#include <resolv.h>
#endif
int contradicting_add_edge = 0; int contradicting_add_edge = 0;
int contradicting_del_edge = 0; int contradicting_del_edge = 0;
static int sleeptime = 10; static int sleeptime = 10;
@ -93,8 +97,6 @@ void purge(void) {
void terminate_connection(connection_t *c, bool report) { void terminate_connection(connection_t *c, bool report) {
logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Closing connection with %s (%s)", c->name, c->hostname); logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Closing connection with %s (%s)", c->name, c->hostname);
c->status.active = false;
if(c->node && c->node->connection == c) if(c->node && c->node->connection == c)
c->node->connection = NULL; c->node->connection = NULL;
@ -129,6 +131,12 @@ void terminate_connection(connection_t *c, bool report) {
if(outgoing) if(outgoing)
do_outgoing_connection(outgoing); do_outgoing_connection(outgoing);
#ifndef HAVE_MINGW
/* Clean up dead proxy processes */
while(waitpid(-1, NULL, WNOHANG) > 0);
#endif
} }
/* /*
@ -145,7 +153,7 @@ static void timeout_handler(void *data) {
continue; continue;
if(c->last_ping_time + pingtimeout <= now.tv_sec) { if(c->last_ping_time + pingtimeout <= now.tv_sec) {
if(c->status.active) { if(c->edge) {
if(c->status.pinged) { if(c->status.pinged) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds", c->name, c->hostname, (long)now.tv_sec - c->last_ping_time); logger(DEBUG_CONNECTIONS, LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds", c->name, c->hostname, (long)now.tv_sec - c->last_ping_time);
} else if(c->last_ping_time + pinginterval <= now.tv_sec) { } else if(c->last_ping_time + pinginterval <= now.tv_sec) {
@ -160,7 +168,7 @@ static void timeout_handler(void *data) {
else else
logger(DEBUG_CONNECTIONS, LOG_WARNING, "Timeout from %s (%s) during authentication", c->name, c->hostname); logger(DEBUG_CONNECTIONS, LOG_WARNING, "Timeout from %s (%s) during authentication", c->name, c->hostname);
} }
terminate_connection(c, c->status.active); terminate_connection(c, c->edge);
} }
} }
@ -194,11 +202,11 @@ static void periodic_handler(void *data) {
/* Count number of active connections */ /* Count number of active connections */
int nc = 0; int nc = 0;
for list_each(connection_t, c, connection_list) { for list_each(connection_t, c, connection_list) {
if(c->status.active && !c->status.control) if(c->edge)
nc++; nc++;
} }
if(nc < autoconnect) { if(nc < 3) {
/* Not enough active connections, try to add one. /* Not enough active connections, try to add one.
Choose a random node, if we don't have a connection to it, Choose a random node, if we don't have a connection to it,
and we are not already trying to make one, create an and we are not already trying to make one, create an
@ -232,7 +240,7 @@ static void periodic_handler(void *data) {
} }
break; break;
} }
} else if(nc > autoconnect) { } 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
that has at least one other connection. that has at least one other connection.
@ -241,7 +249,7 @@ static void periodic_handler(void *data) {
int i = 0; int i = 0;
for list_each(connection_t, c, connection_list) { for list_each(connection_t, c, connection_list) {
if(!c->status.active || c->status.control) if(!c->edge)
continue; continue;
if(i++ != r) if(i++ != r)
@ -253,12 +261,12 @@ static void periodic_handler(void *data) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "Autodisconnecting from %s", c->name); logger(DEBUG_CONNECTIONS, LOG_INFO, "Autodisconnecting from %s", c->name);
list_delete(outgoing_list, c->outgoing); list_delete(outgoing_list, c->outgoing);
c->outgoing = NULL; c->outgoing = NULL;
terminate_connection(c, c->status.active); terminate_connection(c, c->edge);
break; break;
} }
} }
if(nc >= autoconnect) { if(nc >= 3) {
/* If we have enough active connections, /* If we have enough active connections,
remove any pending outgoing connections. remove any pending outgoing connections.
*/ */
@ -283,7 +291,7 @@ static void periodic_handler(void *data) {
void handle_meta_connection_data(connection_t *c) { void handle_meta_connection_data(connection_t *c) {
if (!receive_meta(c)) { if (!receive_meta(c)) {
terminate_connection(c, c->status.active); terminate_connection(c, c->edge);
return; return;
} }
} }
@ -303,6 +311,9 @@ static void sighup_handler(void *data) {
static void sigalrm_handler(void *data) { static void sigalrm_handler(void *data) {
logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum)); logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum));
#ifdef HAVE_DECL_RES_INIT
res_init();
#endif
retry(); retry();
} }
#endif #endif
@ -334,11 +345,14 @@ int reload_configuration(void) {
if(strictsubnets) { if(strictsubnets) {
for splay_each(subnet_t, subnet, subnet_tree) for splay_each(subnet_t, subnet, subnet_tree)
if (subnet->owner)
subnet->expires = 1; subnet->expires = 1;
load_all_subnets(); load_all_subnets();
for splay_each(subnet_t, subnet, subnet_tree) { for splay_each(subnet_t, subnet, subnet_tree) {
if (!subnet->owner)
continue;
if(subnet->expires == 1) { if(subnet->expires == 1) {
send_del_subnet(everyone, subnet); send_del_subnet(everyone, subnet);
if(subnet->owner->status.reachable) if(subnet->owner->status.reachable)
@ -402,7 +416,7 @@ int reload_configuration(void) {
struct stat s; struct stat s;
if(stat(fname, &s) || s.st_mtime > last_config_check) { if(stat(fname, &s) || s.st_mtime > last_config_check) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "Host config file of %s has been changed", c->name); logger(DEBUG_CONNECTIONS, LOG_INFO, "Host config file of %s has been changed", c->name);
terminate_connection(c, c->status.active); terminate_connection(c, c->edge);
} }
free(fname); free(fname);
} }
@ -452,7 +466,7 @@ int main_loop(void) {
#endif #endif
if(!event_loop()) { if(!event_loop()) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while waiting for input: %s", strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "Error while waiting for input: %s", sockstrerror(sockerrno));
return 1; return 1;
} }

View file

@ -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-2013 Guus Sliepen <guus@tinc-vpn.org> 2000-2014 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
@ -32,8 +32,8 @@
#define MTU 1518 /* 1500 bytes payload + 14 bytes ethernet header + 4 bytes VLAN tag */ #define MTU 1518 /* 1500 bytes payload + 14 bytes ethernet header + 4 bytes VLAN tag */
#endif #endif
/* MAXSIZE is the maximum size of an encapsulated packet: MTU + seqno + padding + HMAC + compressor overhead */ /* MAXSIZE is the maximum size of an encapsulated packet: MTU + seqno + srcid + dstid + padding + HMAC + compressor overhead */
#define MAXSIZE (MTU + 4 + CIPHER_MAX_BLOCK_SIZE + DIGEST_MAX_SIZE + MTU/64 + 20) #define MAXSIZE (MTU + 4 + sizeof(node_id_t) + sizeof(node_id_t) + CIPHER_MAX_BLOCK_SIZE + DIGEST_MAX_SIZE + MTU/64 + 20)
/* MAXBUFSIZE is the maximum size of a request: enough for a MAXSIZEd packet or a 8192 bits RSA key */ /* MAXBUFSIZE is the maximum size of a request: enough for a MAXSIZEd packet or a 8192 bits RSA key */
#define MAXBUFSIZE ((MAXSIZE > 2048 ? MAXSIZE : 2048) + 128) #define MAXBUFSIZE ((MAXSIZE > 2048 ? MAXSIZE : 2048) + 128)
@ -52,7 +52,12 @@ typedef struct ipv6_t {
uint16_t x[8]; uint16_t x[8];
} ipv6_t; } ipv6_t;
typedef struct node_id_t {
uint8_t x[6];
} node_id_t;
typedef short length_t; typedef short length_t;
typedef uint32_t seqno_t;
#define AF_UNKNOWN 255 #define AF_UNKNOWN 255
@ -80,10 +85,16 @@ typedef union sockaddr_t {
#define SALEN(s) (s.sa_family==AF_INET?sizeof(struct sockaddr_in):sizeof(struct sockaddr_in6)) #define SALEN(s) (s.sa_family==AF_INET?sizeof(struct sockaddr_in):sizeof(struct sockaddr_in6))
#endif #endif
#define SEQNO(x) ((x)->data + (x)->offset - 4)
#define SRCID(x) ((node_id_t *)((x)->data + (x)->offset - 6))
#define DSTID(x) ((node_id_t *)((x)->data + (x)->offset - 12))
#define DATA(x) ((x)->data + (x)->offset)
#define DEFAULT_PACKET_OFFSET 12
typedef struct vpn_packet_t { typedef struct vpn_packet_t {
length_t len; /* the actual number of bytes in the `data' field */ length_t len; /* The actual number of valid bytes in the `data' field (including seqno or dstid/srcid) */
length_t offset; /* Offset in the buffer where the packet data starts (righter after seqno or dstid/srcid) */
int priority; /* priority or TOS */ int priority; /* priority or TOS */
uint32_t seqno; /* 32 bits sequence number (network byte order of course) */
uint8_t data[MAXSIZE]; uint8_t data[MAXSIZE];
} vpn_packet_t; } vpn_packet_t;
@ -103,6 +114,7 @@ typedef struct listen_socket_t {
io_t tcp; io_t tcp;
io_t udp; io_t udp;
sockaddr_t sa; sockaddr_t sa;
bool bindto;
} listen_socket_t; } listen_socket_t;
#include "conf.h" #include "conf.h"
@ -125,7 +137,6 @@ extern int seconds_till_retry;
extern int addressfamily; extern int addressfamily;
extern unsigned replaywin; extern unsigned replaywin;
extern bool localdiscovery; extern bool localdiscovery;
extern sockaddr_t localdiscovery_address;
extern listen_socket_t listen_socket[MAXSOCKETS]; extern listen_socket_t listen_socket[MAXSOCKETS];
extern int listen_sockets; extern int listen_sockets;
@ -136,7 +147,8 @@ extern int udp_sndbuf;
extern int max_connection_burst; extern int max_connection_burst;
extern bool do_prune; extern bool do_prune;
extern char *myport; extern char *myport;
extern int autoconnect; extern bool device_standby;
extern bool autoconnect;
extern bool disablebuggypeers; extern bool disablebuggypeers;
extern int contradicting_add_edge; extern int contradicting_add_edge;
extern int contradicting_del_edge; extern int contradicting_del_edge;
@ -171,12 +183,14 @@ extern void handle_new_meta_connection(void *, int);
extern void handle_new_unix_connection(void *, int); extern void handle_new_unix_connection(void *, int);
extern int setup_listen_socket(const sockaddr_t *); extern int setup_listen_socket(const sockaddr_t *);
extern int setup_vpn_in_socket(const sockaddr_t *); extern int setup_vpn_in_socket(const sockaddr_t *);
extern bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len); extern bool send_sptps_data(void *handle, uint8_t type, const void *data, size_t len);
extern bool receive_sptps_record(void *handle, uint8_t type, const char *data, uint16_t len); extern bool receive_sptps_record(void *handle, uint8_t type, const void *data, uint16_t len);
extern void send_packet(struct node_t *, vpn_packet_t *); extern void send_packet(struct node_t *, vpn_packet_t *);
extern void receive_tcppacket(struct connection_t *, const char *, int); extern void receive_tcppacket(struct connection_t *, const char *, int);
extern void broadcast_packet(const struct node_t *, vpn_packet_t *); extern void broadcast_packet(const struct node_t *, vpn_packet_t *);
extern char *get_name(void); extern char *get_name(void);
extern void device_enable(void);
extern void device_disable(void);
extern bool setup_myself_reloadable(void); extern bool setup_myself_reloadable(void);
extern bool setup_network(void); extern bool setup_network(void);
extern void setup_outgoing_connection(struct outgoing_t *); extern void setup_outgoing_connection(struct outgoing_t *);
@ -199,8 +213,6 @@ extern void load_all_nodes(void);
#ifndef HAVE_MINGW #ifndef HAVE_MINGW
#define closesocket(s) close(s) #define closesocket(s) close(s)
#else
extern CRITICAL_SECTION mutex;
#endif #endif
#endif /* __TINC_NET_H__ */ #endif /* __TINC_NET_H__ */

View file

@ -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-2013 Guus Sliepen <guus@tinc-vpn.org> 2000-2014 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>
@ -54,8 +54,7 @@ static char lzo_wrkmem[LZO1X_999_MEM_COMPRESS > LZO1X_1_MEM_COMPRESS ? LZO1X_999
static void send_udppacket(node_t *, vpn_packet_t *); static void send_udppacket(node_t *, vpn_packet_t *);
unsigned replaywin = 16; unsigned replaywin = 16;
bool localdiscovery = false; bool localdiscovery = true;
sockaddr_t localdiscovery_address;
#define MAX_SEQNO 1073741824 #define MAX_SEQNO 1073741824
@ -140,19 +139,19 @@ static void send_mtu_probe_handler(void *data) {
len = 64; len = 64;
vpn_packet_t packet; vpn_packet_t packet;
memset(packet.data, 0, 14); packet.offset = DEFAULT_PACKET_OFFSET;
randomize(packet.data + 14, len - 14); memset(DATA(&packet), 0, 14);
randomize(DATA(&packet) + 14, len - 14);
packet.len = len; packet.len = len;
if(i >= 4 && n->mtuprobes <= 10)
packet.priority = -1;
else
packet.priority = 0; packet.priority = 0;
n->status.send_locally = i >= 4 && n->mtuprobes <= 10 && n->prevedge;
logger(DEBUG_TRAFFIC, LOG_INFO, "Sending MTU probe length %d to %s (%s)", len, n->name, n->hostname); logger(DEBUG_TRAFFIC, LOG_INFO, "Sending MTU probe length %d to %s (%s)", len, n->name, n->hostname);
send_udppacket(n, &packet); send_udppacket(n, &packet);
} }
n->status.send_locally = false;
n->probe_counter = 0; n->probe_counter = 0;
gettimeofday(&n->probe_time, NULL); gettimeofday(&n->probe_time, NULL);
@ -178,24 +177,24 @@ void send_mtu_probe(node_t *n) {
} }
static void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) { static void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) {
if(!packet->data[0]) { if(!DATA(packet)[0]) {
logger(DEBUG_TRAFFIC, LOG_INFO, "Got MTU probe request %d from %s (%s)", packet->len, n->name, n->hostname); logger(DEBUG_TRAFFIC, LOG_INFO, "Got MTU probe request %d from %s (%s)", packet->len, n->name, n->hostname);
/* It's a probe request, send back a reply */ /* It's a probe request, send back a reply */
/* Type 2 probe replies were introduced in protocol 17.3 */ /* Type 2 probe replies were introduced in protocol 17.3 */
if ((n->options >> 24) == 3) { if ((n->options >> 24) >= 3) {
uint8_t* data = packet->data; uint8_t *data = DATA(packet);
*data++ = 2; *data++ = 2;
uint16_t len16 = htons(len); memcpy(data, &len16, 2); data += 2; uint16_t len16 = htons(len); memcpy(data, &len16, 2); data += 2;
struct timeval now; struct timeval now;
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
uint32_t sec = htonl(now.tv_sec); memcpy(data, &sec, 4); data += 4; uint32_t sec = htonl(now.tv_sec); memcpy(data, &sec, 4); data += 4;
uint32_t usec = htonl(now.tv_usec); memcpy(data, &usec, 4); data += 4; uint32_t usec = htonl(now.tv_usec); memcpy(data, &usec, 4); data += 4;
packet->len = data - packet->data; packet->len -= 10;
} else { } else {
/* Legacy protocol: n won't understand type 2 probe replies. */ /* Legacy protocol: n won't understand type 2 probe replies. */
packet->data[0] = 1; DATA(packet)[0] = 1;
} }
/* Temporarily set udp_confirmed, so that the reply is sent /* Temporarily set udp_confirmed, so that the reply is sent
@ -207,14 +206,14 @@ static void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) {
n->status.udp_confirmed = udp_confirmed; n->status.udp_confirmed = udp_confirmed;
} else { } else {
length_t probelen = len; length_t probelen = len;
if (packet->data[0] == 2) { if (DATA(packet)[0] == 2) {
if (len < 3) if (len < 3)
logger(DEBUG_TRAFFIC, LOG_WARNING, "Received invalid (too short) MTU probe reply from %s (%s)", n->name, n->hostname); logger(DEBUG_TRAFFIC, LOG_WARNING, "Received invalid (too short) MTU probe reply from %s (%s)", n->name, n->hostname);
else { else {
uint16_t probelen16; memcpy(&probelen16, packet->data + 1, 2); probelen = ntohs(probelen16); uint16_t probelen16; memcpy(&probelen16, DATA(packet) + 1, 2); probelen = ntohs(probelen16);
} }
} }
logger(DEBUG_TRAFFIC, LOG_INFO, "Got type %d MTU probe reply %d from %s (%s)", packet->data[0], probelen, n->name, n->hostname); logger(DEBUG_TRAFFIC, LOG_INFO, "Got type %d MTU probe reply %d from %s (%s)", DATA(packet)[0], probelen, n->name, n->hostname);
/* It's a valid reply: now we know bidirectional communication /* It's a valid reply: now we know bidirectional communication
is possible using the address and socket that the reply is possible using the address and socket that the reply
@ -256,9 +255,9 @@ static void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) {
timersub(&now, &n->probe_time, &diff); timersub(&now, &n->probe_time, &diff);
struct timeval probe_timestamp = now; struct timeval probe_timestamp = now;
if (packet->data[0] == 2 && packet->len >= 11) { if (DATA(packet)[0] == 2 && packet->len >= 11) {
uint32_t sec; memcpy(&sec, packet->data + 3, 4); uint32_t sec; memcpy(&sec, DATA(packet) + 3, 4);
uint32_t usec; memcpy(&usec, packet->data + 7, 4); uint32_t usec; memcpy(&usec, DATA(packet) + 7, 4);
probe_timestamp.tv_sec = ntohl(sec); probe_timestamp.tv_sec = ntohl(sec);
probe_timestamp.tv_usec = ntohl(usec); probe_timestamp.tv_usec = ntohl(usec);
} }
@ -350,20 +349,21 @@ static void receive_packet(node_t *n, vpn_packet_t *packet) {
static bool try_mac(node_t *n, const vpn_packet_t *inpkt) { static bool try_mac(node_t *n, const vpn_packet_t *inpkt) {
if(n->status.sptps) if(n->status.sptps)
return sptps_verify_datagram(&n->sptps, (char *)&inpkt->seqno, inpkt->len); return sptps_verify_datagram(&n->sptps, DATA(inpkt), inpkt->len);
if(!digest_active(n->indigest) || inpkt->len < sizeof inpkt->seqno + digest_length(n->indigest)) if(!digest_active(n->indigest) || inpkt->len < sizeof(seqno_t) + digest_length(n->indigest))
return false; return false;
return digest_verify(n->indigest, &inpkt->seqno, inpkt->len - digest_length(n->indigest), (const char *)&inpkt->seqno + inpkt->len - digest_length(n->indigest)); return digest_verify(n->indigest, SEQNO(inpkt), inpkt->len - digest_length(n->indigest), DATA(inpkt) + inpkt->len - digest_length(n->indigest));
} }
static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) { static bool receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
vpn_packet_t pkt1, pkt2; vpn_packet_t pkt1, pkt2;
vpn_packet_t *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 }; vpn_packet_t *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 };
int nextpkt = 0; int nextpkt = 0;
vpn_packet_t *outpkt = pkt[0];
size_t outlen; size_t outlen;
pkt1.offset = DEFAULT_PACKET_OFFSET;
pkt2.offset = DEFAULT_PACKET_OFFSET;
if(n->status.sptps) { if(n->status.sptps) {
if(!n->sptps.state) { if(!n->sptps.state) {
@ -373,43 +373,51 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
} else { } else {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet", n->name, n->hostname); logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet", n->name, n->hostname);
} }
return; return false;
} }
sptps_receive_data(&n->sptps, (char *)&inpkt->seqno, inpkt->len); inpkt->offset += 2 * sizeof(node_id_t);
return; if(!sptps_receive_data(&n->sptps, DATA(inpkt), inpkt->len - 2 * sizeof(node_id_t))) {
logger(DEBUG_TRAFFIC, LOG_ERR, "Got bad packet from %s (%s)", n->name, n->hostname);
return false;
}
return true;
} }
if(!cipher_active(n->incipher)) { if(!n->status.validkey) {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet", n->name, n->hostname); logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet", n->name, n->hostname);
return; return false;
} }
/* Check packet length */ /* Check packet length */
if(inpkt->len < sizeof inpkt->seqno + digest_length(n->indigest)) { if(inpkt->len < sizeof(seqno_t) + digest_length(n->indigest)) {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got too short packet from %s (%s)", logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got too short packet from %s (%s)",
n->name, n->hostname); n->name, n->hostname);
return; return false;
} }
/* It's a legacy UDP packet, the data starts after the seqno */
inpkt->offset += sizeof(seqno_t);
/* Check the message authentication code */ /* Check the message authentication code */
if(digest_active(n->indigest)) { if(digest_active(n->indigest)) {
inpkt->len -= digest_length(n->indigest); inpkt->len -= digest_length(n->indigest);
if(!digest_verify(n->indigest, &inpkt->seqno, inpkt->len, (const char *)&inpkt->seqno + inpkt->len)) { if(!digest_verify(n->indigest, SEQNO(inpkt), inpkt->len, SEQNO(inpkt) + inpkt->len)) {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got unauthenticated packet from %s (%s)", n->name, n->hostname); logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got unauthenticated packet from %s (%s)", n->name, n->hostname);
return; return false;
} }
} }
/* Decrypt the packet */ /* Decrypt the packet */
if(cipher_active(n->incipher)) { if(cipher_active(n->incipher)) {
outpkt = pkt[nextpkt++]; vpn_packet_t *outpkt = pkt[nextpkt++];
outlen = MAXSIZE; outlen = MAXSIZE;
if(!cipher_decrypt(n->incipher, &inpkt->seqno, inpkt->len, &outpkt->seqno, &outlen, true)) { if(!cipher_decrypt(n->incipher, SEQNO(inpkt), inpkt->len, SEQNO(outpkt), &outlen, true)) {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Error decrypting packet from %s (%s)", n->name, n->hostname); logger(DEBUG_TRAFFIC, LOG_DEBUG, "Error decrypting packet from %s (%s)", n->name, n->hostname);
return; return false;
} }
outpkt->len = outlen; outpkt->len = outlen;
@ -418,38 +426,40 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
/* Check the sequence number */ /* Check the sequence number */
inpkt->len -= sizeof inpkt->seqno; seqno_t seqno;
inpkt->seqno = ntohl(inpkt->seqno); memcpy(&seqno, SEQNO(inpkt), sizeof seqno);
seqno = ntohl(seqno);
inpkt->len -= sizeof seqno;
if(replaywin) { if(replaywin) {
if(inpkt->seqno != n->received_seqno + 1) { if(seqno != n->received_seqno + 1) {
if(inpkt->seqno >= n->received_seqno + replaywin * 8) { if(seqno >= n->received_seqno + replaywin * 8) {
if(n->farfuture++ < replaywin >> 2) { if(n->farfuture++ < replaywin >> 2) {
logger(DEBUG_ALWAYS, LOG_WARNING, "Packet from %s (%s) is %d seqs in the future, dropped (%u)", logger(DEBUG_ALWAYS, LOG_WARNING, "Packet from %s (%s) is %d seqs in the future, dropped (%u)",
n->name, n->hostname, inpkt->seqno - n->received_seqno - 1, n->farfuture); n->name, n->hostname, seqno - n->received_seqno - 1, n->farfuture);
return; return false;
} }
logger(DEBUG_ALWAYS, LOG_WARNING, "Lost %d packets from %s (%s)", logger(DEBUG_ALWAYS, LOG_WARNING, "Lost %d packets from %s (%s)",
inpkt->seqno - n->received_seqno - 1, n->name, n->hostname); seqno - n->received_seqno - 1, n->name, n->hostname);
memset(n->late, 0, replaywin); memset(n->late, 0, replaywin);
} else if (inpkt->seqno <= n->received_seqno) { } else if (seqno <= n->received_seqno) {
if((n->received_seqno >= replaywin * 8 && inpkt->seqno <= n->received_seqno - replaywin * 8) || !(n->late[(inpkt->seqno / 8) % replaywin] & (1 << inpkt->seqno % 8))) { if((n->received_seqno >= replaywin * 8 && seqno <= n->received_seqno - replaywin * 8) || !(n->late[(seqno / 8) % replaywin] & (1 << seqno % 8))) {
logger(DEBUG_ALWAYS, LOG_WARNING, "Got late or replayed packet from %s (%s), seqno %d, last received %d", logger(DEBUG_ALWAYS, LOG_WARNING, "Got late or replayed packet from %s (%s), seqno %d, last received %d",
n->name, n->hostname, inpkt->seqno, n->received_seqno); n->name, n->hostname, seqno, n->received_seqno);
return; return false;
} }
} else { } else {
for(int i = n->received_seqno + 1; i < inpkt->seqno; i++) for(int i = n->received_seqno + 1; i < seqno; i++)
n->late[(i / 8) % replaywin] |= 1 << i % 8; n->late[(i / 8) % replaywin] |= 1 << i % 8;
} }
} }
n->farfuture = 0; n->farfuture = 0;
n->late[(inpkt->seqno / 8) % replaywin] &= ~(1 << inpkt->seqno % 8); n->late[(seqno / 8) % replaywin] &= ~(1 << seqno % 8);
} }
if(inpkt->seqno > n->received_seqno) if(seqno > n->received_seqno)
n->received_seqno = inpkt->seqno; n->received_seqno = seqno;
n->received++; n->received++;
@ -461,12 +471,12 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
length_t origlen = inpkt->len; length_t origlen = inpkt->len;
if(n->incompression) { if(n->incompression) {
outpkt = pkt[nextpkt++]; vpn_packet_t *outpkt = pkt[nextpkt++];
if((outpkt->len = uncompress_packet(outpkt->data, inpkt->data, inpkt->len, n->incompression)) < 0) { if((outpkt->len = uncompress_packet(DATA(outpkt), DATA(inpkt), inpkt->len, n->incompression)) < 0) {
logger(DEBUG_TRAFFIC, LOG_ERR, "Error while uncompressing packet from %s (%s)", logger(DEBUG_TRAFFIC, LOG_ERR, "Error while uncompressing packet from %s (%s)",
n->name, n->hostname); n->name, n->hostname);
return; return false;
} }
inpkt = outpkt; inpkt = outpkt;
@ -476,16 +486,18 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
inpkt->priority = 0; inpkt->priority = 0;
if(!inpkt->data[12] && !inpkt->data[13]) if(!DATA(inpkt)[12] && !DATA(inpkt)[13])
mtu_probe_h(n, inpkt, origlen); mtu_probe_h(n, inpkt, origlen);
else else
receive_packet(n, inpkt); receive_packet(n, inpkt);
return true;
} }
void receive_tcppacket(connection_t *c, const char *buffer, int len) { void receive_tcppacket(connection_t *c, const char *buffer, int len) {
vpn_packet_t outpkt; vpn_packet_t outpkt;
outpkt.offset = DEFAULT_PACKET_OFFSET;
if(len > sizeof outpkt.data) if(len > sizeof outpkt.data - outpkt.offset)
return; return;
outpkt.len = len; outpkt.len = len;
@ -493,14 +505,22 @@ void receive_tcppacket(connection_t *c, const char *buffer, int len) {
outpkt.priority = 0; outpkt.priority = 0;
else else
outpkt.priority = -1; outpkt.priority = -1;
memcpy(outpkt.data, buffer, len); memcpy(DATA(&outpkt), buffer, len);
receive_packet(c->node, &outpkt); receive_packet(c->node, &outpkt);
} }
static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) { static bool try_sptps(node_t *n) {
if(!n->status.validkey) { if(n->status.validkey)
return true;
/* If n is a TCP-only neighbor, we'll only use "cleartext" PACKET
messages anyway, so there's no need for SPTPS at all. */
if(n->connection && ((myself->options | n->options) & OPTION_TCPONLY))
return false;
logger(DEBUG_TRAFFIC, LOG_INFO, "No valid key known yet for %s (%s)", n->name, n->hostname); logger(DEBUG_TRAFFIC, LOG_INFO, "No valid key known yet for %s (%s)", n->name, n->hostname);
if(!n->status.waitingforkey) if(!n->status.waitingforkey)
send_req_key(n); send_req_key(n);
else if(n->last_req_key + 10 < now.tv_sec) { else if(n->last_req_key + 10 < now.tv_sec) {
@ -509,14 +529,22 @@ static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) {
n->status.waitingforkey = false; n->status.waitingforkey = false;
send_req_key(n); send_req_key(n);
} }
return false;
}
static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) {
/* Note: condition order is as intended - even if we have a direct
metaconnection, we want to try SPTPS anyway as it's the only way to
get UDP going */
if(!try_sptps(n) && !n->connection)
return; return;
}
uint8_t type = 0; uint8_t type = 0;
int offset = 0; int offset = 0;
if(!(origpkt->data[12] | origpkt->data[13])) { if(!(DATA(origpkt)[12] | DATA(origpkt)[13])) {
sptps_send_record(&n->sptps, PKT_PROBE, (char *)origpkt->data, origpkt->len); sptps_send_record(&n->sptps, PKT_PROBE, (char *)DATA(origpkt), origpkt->len);
return; return;
} }
@ -531,7 +559,8 @@ static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) {
vpn_packet_t outpkt; vpn_packet_t outpkt;
if(n->outcompression) { if(n->outcompression) {
int len = compress_packet(outpkt.data + offset, origpkt->data + offset, origpkt->len - offset, n->outcompression); outpkt.offset = 0;
int len = compress_packet(DATA(&outpkt) + offset, DATA(origpkt) + offset, origpkt->len - offset, n->outcompression);
if(len < 0) { if(len < 0) {
logger(DEBUG_TRAFFIC, LOG_ERR, "Error while compressing packet to %s (%s)", n->name, n->hostname); logger(DEBUG_TRAFFIC, LOG_ERR, "Error while compressing packet to %s (%s)", n->name, n->hostname);
} else if(len < origpkt->len - offset) { } else if(len < origpkt->len - offset) {
@ -541,10 +570,29 @@ static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) {
} }
} }
sptps_send_record(&n->sptps, type, (char *)origpkt->data + offset, origpkt->len - offset); /* If we have a direct metaconnection to n, and we can't use UDP, then
don't bother with SPTPS and just use a "plaintext" PACKET message.
We don't really care about end-to-end security since we're not
sending the message through any intermediate nodes. */
if(n->connection && origpkt->len > n->minmtu)
send_tcppacket(n->connection, origpkt);
else
sptps_send_record(&n->sptps, type, DATA(origpkt) + offset, origpkt->len - offset);
return; return;
} }
static void adapt_socket(const sockaddr_t *sa, int *sock) {
/* Make sure we have a suitable socket for the chosen address */
if(listen_socket[*sock].sa.sa.sa_family != sa->sa.sa_family) {
for(int i = 0; i < listen_sockets; i++) {
if(listen_socket[i].sa.sa.sa_family == sa->sa.sa_family) {
*sock = i;
break;
}
}
}
}
static void choose_udp_address(const node_t *n, const sockaddr_t **sa, int *sock) { static void choose_udp_address(const node_t *n, const sockaddr_t **sa, int *sock) {
/* Latest guess */ /* Latest guess */
*sa = &n->address; *sa = &n->address;
@ -583,53 +631,29 @@ static void choose_udp_address(const node_t *n, const sockaddr_t **sa, int *sock
*sock = rand() % listen_sockets; *sock = rand() % listen_sockets;
} }
/* Make sure we have a suitable socket for the chosen address */ adapt_socket(*sa, sock);
if(listen_socket[*sock].sa.sa.sa_family != (*sa)->sa.sa_family) { }
for(int i = 0; i < listen_sockets; i++) {
if(listen_socket[i].sa.sa.sa_family == (*sa)->sa.sa_family) { static void choose_local_address(const node_t *n, const sockaddr_t **sa, int *sock) {
*sock = i; *sa = NULL;
/* Pick one of the edges from this node at random, then use its local address. */
int i = 0;
int j = rand() % n->edge_tree->count;
edge_t *candidate = NULL;
for splay_each(edge_t, e, n->edge_tree) {
if(i++ == j) {
candidate = e;
break; break;
} }
} }
}
}
static void choose_broadcast_address(const node_t *n, const sockaddr_t **sa, int *sock) {
static sockaddr_t broadcast_ipv4 = {
.in = {
.sin_family = AF_INET,
.sin_addr.s_addr = -1,
}
};
static sockaddr_t broadcast_ipv6 = {
.in6 = {
.sin6_family = AF_INET6,
.sin6_addr.s6_addr[0x0] = 0xff,
.sin6_addr.s6_addr[0x1] = 0x02,
.sin6_addr.s6_addr[0xf] = 0x01,
}
};
if (candidate && candidate->local_address.sa.sa_family) {
*sa = &candidate->local_address;
*sock = rand() % listen_sockets; *sock = rand() % listen_sockets;
adapt_socket(*sa, sock);
if(listen_socket[*sock].sa.sa.sa_family == AF_INET6) {
if(localdiscovery_address.sa.sa_family == AF_INET6) {
localdiscovery_address.in6.sin6_port = n->prevedge->address.in.sin_port;
*sa = &localdiscovery_address;
} else {
broadcast_ipv6.in6.sin6_port = n->prevedge->address.in.sin_port;
broadcast_ipv6.in6.sin6_scope_id = listen_socket[*sock].sa.in6.sin6_scope_id;
*sa = &broadcast_ipv6;
}
} else {
if(localdiscovery_address.sa.sa_family == AF_INET) {
localdiscovery_address.in.sin_port = n->prevedge->address.in.sin_port;
*sa = &localdiscovery_address;
} else {
broadcast_ipv4.in.sin_port = n->prevedge->address.in.sin_port;
*sa = &broadcast_ipv4;
}
} }
} }
@ -643,8 +667,11 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
size_t outlen; size_t outlen;
#if defined(SOL_IP) && defined(IP_TOS) #if defined(SOL_IP) && defined(IP_TOS)
static int priority = 0; static int priority = 0;
#endif
int origpriority = origpkt->priority; int origpriority = origpkt->priority;
#endif
pkt1.offset = DEFAULT_PACKET_OFFSET;
pkt2.offset = DEFAULT_PACKET_OFFSET;
if(!n->status.reachable) { if(!n->status.reachable) {
logger(DEBUG_TRAFFIC, LOG_INFO, "Trying to send UDP packet to unreachable node %s (%s)", n->name, n->hostname); logger(DEBUG_TRAFFIC, LOG_INFO, "Trying to send UDP packet to unreachable node %s (%s)", n->name, n->hostname);
@ -671,7 +698,7 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
return; return;
} }
if(n->options & OPTION_PMTU_DISCOVERY && inpkt->len > n->minmtu && (inpkt->data[12] | inpkt->data[13])) { if(n->options & OPTION_PMTU_DISCOVERY && inpkt->len > n->minmtu && (DATA(inpkt)[12] | DATA(inpkt)[13])) {
logger(DEBUG_TRAFFIC, LOG_INFO, logger(DEBUG_TRAFFIC, LOG_INFO,
"Packet for %s (%s) larger than minimum MTU, forwarding via %s", "Packet for %s (%s) larger than minimum MTU, forwarding via %s",
n->name, n->hostname, n != n->nexthop ? n->nexthop->name : "TCP"); n->name, n->hostname, n != n->nexthop ? n->nexthop->name : "TCP");
@ -689,7 +716,7 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
if(n->outcompression) { if(n->outcompression) {
outpkt = pkt[nextpkt++]; outpkt = pkt[nextpkt++];
if((outpkt->len = compress_packet(outpkt->data, inpkt->data, inpkt->len, n->outcompression)) < 0) { if((outpkt->len = compress_packet(DATA(outpkt), DATA(inpkt), inpkt->len, n->outcompression)) < 0) {
logger(DEBUG_TRAFFIC, LOG_ERR, "Error while compressing packet to %s (%s)", logger(DEBUG_TRAFFIC, LOG_ERR, "Error while compressing packet to %s (%s)",
n->name, n->hostname); n->name, n->hostname);
return; return;
@ -700,8 +727,9 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
/* Add sequence number */ /* Add sequence number */
inpkt->seqno = htonl(++(n->sent_seqno)); seqno_t seqno = htonl(++(n->sent_seqno));
inpkt->len += sizeof inpkt->seqno; memcpy(SEQNO(inpkt), &seqno, sizeof seqno);
inpkt->len += sizeof seqno;
/* Encrypt the packet */ /* Encrypt the packet */
@ -709,7 +737,7 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
outpkt = pkt[nextpkt++]; outpkt = pkt[nextpkt++];
outlen = MAXSIZE; outlen = MAXSIZE;
if(!cipher_encrypt(n->outcipher, &inpkt->seqno, inpkt->len, &outpkt->seqno, &outlen, true)) { if(!cipher_encrypt(n->outcipher, SEQNO(inpkt), inpkt->len, SEQNO(outpkt), &outlen, true)) {
logger(DEBUG_TRAFFIC, LOG_ERR, "Error while encrypting packet to %s (%s)", n->name, n->hostname); logger(DEBUG_TRAFFIC, LOG_ERR, "Error while encrypting packet to %s (%s)", n->name, n->hostname);
goto end; goto end;
} }
@ -721,7 +749,7 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
/* Add the message authentication code */ /* Add the message authentication code */
if(digest_active(n->outdigest)) { if(digest_active(n->outdigest)) {
if(!digest_create(n->outdigest, &inpkt->seqno, inpkt->len, (char *)&inpkt->seqno + inpkt->len)) { if(!digest_create(n->outdigest, SEQNO(inpkt), inpkt->len, SEQNO(inpkt) + inpkt->len)) {
logger(DEBUG_TRAFFIC, LOG_ERR, "Error while encrypting packet to %s (%s)", n->name, n->hostname); logger(DEBUG_TRAFFIC, LOG_ERR, "Error while encrypting packet to %s (%s)", n->name, n->hostname);
goto end; goto end;
} }
@ -731,14 +759,12 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
/* Send the packet */ /* Send the packet */
const sockaddr_t *sa; const sockaddr_t *sa = NULL;
int sock; int sock;
/* Overloaded use of priority field: -1 means local broadcast */ if(n->status.send_locally)
choose_local_address(n, &sa, &sock);
if(origpriority == -1 && n->prevedge) if(!sa)
choose_broadcast_address(n, &sa, &sock);
else
choose_udp_address(n, &sa, &sock); choose_udp_address(n, &sa, &sock);
#if defined(SOL_IP) && defined(IP_TOS) #if defined(SOL_IP) && defined(IP_TOS)
@ -747,11 +773,11 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
priority = origpriority; priority = origpriority;
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Setting outgoing packet priority to %d", priority); logger(DEBUG_TRAFFIC, LOG_DEBUG, "Setting outgoing packet priority to %d", priority);
if(setsockopt(listen_socket[n->sock].udp.fd, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */ if(setsockopt(listen_socket[n->sock].udp.fd, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */
logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setsockopt", sockstrerror(sockerrno));
} }
#endif #endif
if(sendto(listen_socket[sock].udp.fd, (char *) &inpkt->seqno, inpkt->len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) { if(sendto(listen_socket[sock].udp.fd, 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;
@ -765,39 +791,67 @@ end:
origpkt->len = origlen; origpkt->len = origlen;
} }
bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len) { static bool send_sptps_data_priv(node_t *to, node_t *from, int type, const void *data, size_t len) {
node_t *to = handle; node_t *relay = (to->via != myself && (type == PKT_PROBE || (len - SPTPS_DATAGRAM_OVERHEAD) <= to->via->minmtu)) ? to->via : to->nexthop;
bool direct = from == myself && to == relay;
bool relay_supported = (relay->options >> 24) >= 4;
bool tcponly = (myself->options | relay->options) & OPTION_TCPONLY;
/* Send it via TCP if it is a handshake packet, TCPOnly is in use, or this packet is larger than the MTU. */ /* We don't really need the relay's key, but we need to establish a UDP tunnel with it and discover its MTU. */
if (!direct && relay_supported && !tcponly)
try_sptps(relay);
if(type >= SPTPS_HANDSHAKE || ((myself->options | to->options) & OPTION_TCPONLY) || (type != PKT_PROBE && len > to->minmtu)) { /* Send it via TCP if it is a handshake packet, TCPOnly is in use, this is a relay packet that the other node cannot understand, or this packet is larger than the MTU.
TODO: When relaying, the original sender does not know the end-to-end PMTU (it only knows the PMTU of the first hop).
This can lead to scenarios where large packets are sent over UDP to relay, but then relay has no choice but fall back to TCP. */
if(type == SPTPS_HANDSHAKE || tcponly || (!direct && !relay_supported) || (type != PKT_PROBE && (len - SPTPS_DATAGRAM_OVERHEAD) > relay->minmtu)) {
char buf[len * 4 / 3 + 5]; char buf[len * 4 / 3 + 5];
b64encode(data, buf, len); b64encode(data, buf, len);
/* If no valid key is known yet, send the packets using ANS_KEY requests, /* If no valid key is known yet, send the packets using ANS_KEY requests,
to ensure we get to learn the reflexive UDP address. */ to ensure we get to learn the reflexive UDP address. */
if(!to->status.validkey) { if(from == myself && !to->status.validkey) {
to->incompression = myself->incompression; to->incompression = myself->incompression;
return send_request(to->nexthop->connection, "%d %s %s %s -1 -1 -1 %d", ANS_KEY, myself->name, to->name, buf, to->incompression); return send_request(to->nexthop->connection, "%d %s %s %s -1 -1 -1 %d", ANS_KEY, from->name, to->name, buf, to->incompression);
} else { } else {
return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, to->name, REQ_SPTPS, buf); return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, from->name, to->name, REQ_SPTPS, buf);
} }
} }
/* Otherwise, send the packet via UDP */ size_t overhead = 0;
if(relay_supported) overhead += sizeof to->id + sizeof from->id;
char buf[len + overhead]; char* buf_ptr = buf;
if(relay_supported) {
if(direct) {
/* Inform the recipient that this packet was sent directly. */
node_id_t nullid = {};
memcpy(buf_ptr, &nullid, sizeof nullid); buf_ptr += sizeof nullid;
} else {
memcpy(buf_ptr, &to->id, sizeof to->id); buf_ptr += sizeof to->id;
}
memcpy(buf_ptr, &from->id, sizeof from->id); buf_ptr += sizeof from->id;
const sockaddr_t *sa; }
/* TODO: if this copy turns out to be a performance concern, change sptps_send_record() to add some "pre-padding" to the buffer and use that instead */
memcpy(buf_ptr, data, len); buf_ptr += len;
const sockaddr_t *sa = NULL;
int sock; int sock;
if(relay->status.send_locally)
choose_udp_address(to, &sa, &sock); choose_local_address(relay, &sa, &sock);
if(!sa)
if(sendto(listen_socket[sock].udp.fd, data, len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) { choose_udp_address(relay, &sa, &sock);
logger(DEBUG_TRAFFIC, LOG_INFO, "Sending packet from %s (%s) to %s (%s) via %s (%s)", from->name, from->hostname, to->name, to->hostname, relay->name, relay->hostname);
if(sendto(listen_socket[sock].udp.fd, buf, buf_ptr - buf, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) {
if(sockmsgsize(sockerrno)) { if(sockmsgsize(sockerrno)) {
if(to->maxmtu >= len) // Compensate for SPTPS overhead
to->maxmtu = len - 1; len -= SPTPS_DATAGRAM_OVERHEAD;
if(to->mtu >= len) if(relay->maxmtu >= len)
to->mtu = len - 1; relay->maxmtu = len - 1;
if(relay->mtu >= len)
relay->mtu = len - 1;
} else { } else {
logger(DEBUG_TRAFFIC, LOG_WARNING, "Error sending UDP SPTPS packet to %s (%s): %s", to->name, to->hostname, sockstrerror(sockerrno)); logger(DEBUG_TRAFFIC, LOG_WARNING, "Error sending UDP SPTPS packet to %s (%s): %s", relay->name, relay->hostname, sockstrerror(sockerrno));
return false; return false;
} }
} }
@ -805,7 +859,11 @@ bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len) {
return true; return true;
} }
bool receive_sptps_record(void *handle, uint8_t type, const char *data, uint16_t len) { bool send_sptps_data(void *handle, uint8_t type, const void *data, size_t len) {
return send_sptps_data_priv(handle, myself, type, data, len);
}
bool receive_sptps_record(void *handle, uint8_t type, const void *data, uint16_t len) {
node_t *from = handle; node_t *from = handle;
if(type == SPTPS_HANDSHAKE) { if(type == SPTPS_HANDSHAKE) {
@ -823,10 +881,11 @@ bool receive_sptps_record(void *handle, uint8_t type, const char *data, uint16_t
} }
vpn_packet_t inpkt; vpn_packet_t inpkt;
inpkt.offset = DEFAULT_PACKET_OFFSET;
if(type == PKT_PROBE) { if(type == PKT_PROBE) {
inpkt.len = len; inpkt.len = len;
memcpy(inpkt.data, data, len); memcpy(DATA(&inpkt), data, len);
mtu_probe_h(from, &inpkt, len); mtu_probe_h(from, &inpkt, len);
return true; return true;
} }
@ -846,7 +905,7 @@ bool receive_sptps_record(void *handle, uint8_t type, const char *data, uint16_t
int offset = (type & PKT_MAC) ? 0 : 14; int offset = (type & PKT_MAC) ? 0 : 14;
if(type & PKT_COMPRESSED) { if(type & PKT_COMPRESSED) {
length_t ulen = uncompress_packet(inpkt.data + offset, (const uint8_t *)data, len, from->incompression); length_t ulen = uncompress_packet(DATA(&inpkt) + offset, (const uint8_t *)data, len, from->incompression);
if(ulen < 0) { if(ulen < 0) {
return false; return false;
} else { } else {
@ -855,25 +914,25 @@ bool receive_sptps_record(void *handle, uint8_t type, const char *data, uint16_t
if(inpkt.len > MAXSIZE) if(inpkt.len > MAXSIZE)
abort(); abort();
} else { } else {
memcpy(inpkt.data + offset, data, len); memcpy(DATA(&inpkt) + offset, data, len);
inpkt.len = len + offset; inpkt.len = len + offset;
} }
/* Generate the Ethernet packet type if necessary */ /* Generate the Ethernet packet type if necessary */
if(offset) { if(offset) {
switch(inpkt.data[14] >> 4) { switch(DATA(&inpkt)[14] >> 4) {
case 4: case 4:
inpkt.data[12] = 0x08; DATA(&inpkt)[12] = 0x08;
inpkt.data[13] = 0x00; DATA(&inpkt)[13] = 0x00;
break; break;
case 6: case 6:
inpkt.data[12] = 0x86; DATA(&inpkt)[12] = 0x86;
inpkt.data[13] = 0xDD; DATA(&inpkt)[13] = 0xDD;
break; break;
default: default:
logger(DEBUG_TRAFFIC, LOG_ERR, logger(DEBUG_TRAFFIC, LOG_ERR,
"Unknown IP version %d while reading packet from %s (%s)", "Unknown IP version %d while reading packet from %s (%s)",
inpkt.data[14] >> 4, from->name, from->hostname); DATA(&inpkt)[14] >> 4, from->name, from->hostname);
return false; return false;
} }
} }
@ -890,7 +949,7 @@ void send_packet(node_t *n, vpn_packet_t *packet) {
if(n == myself) { if(n == myself) {
if(overwrite_mac) if(overwrite_mac)
memcpy(packet->data, mymac.x, ETH_ALEN); memcpy(DATA(packet), mymac.x, ETH_ALEN);
n->out_packets++; n->out_packets++;
n->out_bytes += packet->len; n->out_bytes += packet->len;
devops.write(packet); devops.write(packet);
@ -948,7 +1007,7 @@ void broadcast_packet(const node_t *from, vpn_packet_t *packet) {
// usually distributes the sending of broadcast packets over all nodes. // usually distributes the sending of broadcast packets over all nodes.
case BMODE_MST: case BMODE_MST:
for list_each(connection_t, c, connection_list) for list_each(connection_t, c, connection_list)
if(c->status.active && c->status.mst && c != from->nexthop->connection) if(c->edge && c->status.mst && c != from->nexthop->connection)
send_packet(c->node, packet); send_packet(c->node, packet);
break; break;
@ -1002,12 +1061,14 @@ void handle_incoming_vpn_data(void *data, int flags) {
listen_socket_t *ls = data; listen_socket_t *ls = data;
vpn_packet_t pkt; vpn_packet_t pkt;
char *hostname; char *hostname;
sockaddr_t from = {{0}}; node_id_t nullid = {};
socklen_t fromlen = sizeof from; sockaddr_t addr = {};
node_t *n; socklen_t addrlen = sizeof addr;
int len; node_t *from, *to;
bool direct = false;
len = recvfrom(ls->udp.fd, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen); pkt.offset = 0;
int len = recvfrom(ls->udp.fd, DATA(&pkt), MAXSIZE, 0, &addr.sa, &addrlen);
if(len <= 0 || len > MAXSIZE) { if(len <= 0 || len > MAXSIZE) {
if(!sockwouldblock(sockerrno)) if(!sockwouldblock(sockerrno))
@ -1017,32 +1078,76 @@ void handle_incoming_vpn_data(void *data, int flags) {
pkt.len = len; pkt.len = len;
sockaddrunmap(&from); /* Some braindead IPv6 implementations do stupid things. */ sockaddrunmap(&addr); /* Some braindead IPv6 implementations do stupid things. */
n = lookup_node_udp(&from); // Try to figure out who sent this packet.
node_t *n = lookup_node_udp(&addr);
if(!n) { if(!n) {
n = try_harder(&from, &pkt); // It might be from a 1.1 node, which might have a source ID in the packet.
if(n) pkt.offset = 2 * sizeof(node_id_t);
update_node_udp(n, &from); from = lookup_node_id(SRCID(&pkt));
else if(debug_level >= DEBUG_PROTOCOL) { if(from && !memcmp(DSTID(&pkt), &nullid, sizeof nullid) && from->status.sptps) {
hostname = sockaddr2hostname(&from); if(sptps_verify_datagram(&from->sptps, DATA(&pkt), pkt.len - 2 * sizeof(node_id_t)))
n = from;
else
goto skip_harder;
}
}
if(!n) {
pkt.offset = 0;
n = try_harder(&addr, &pkt);
}
skip_harder:
if(!n) {
if(debug_level >= DEBUG_PROTOCOL) {
hostname = sockaddr2hostname(&addr);
logger(DEBUG_PROTOCOL, LOG_WARNING, "Received UDP packet from unknown source %s", hostname); logger(DEBUG_PROTOCOL, LOG_WARNING, "Received UDP packet from unknown source %s", hostname);
free(hostname); free(hostname);
}
return; return;
} }
else
if(n->status.sptps) {
pkt.offset = 2 * sizeof(node_id_t);
if(!memcmp(DSTID(&pkt), &nullid, sizeof nullid)) {
direct = true;
from = n;
to = myself;
} else {
from = lookup_node_id(SRCID(&pkt));
to = lookup_node_id(DSTID(&pkt));
}
if(!from || !to) {
logger(DEBUG_PROTOCOL, LOG_WARNING, "Received UDP packet from %s (%s) with unknown source and/or destination ID", n->name, n->hostname);
return; return;
} }
if(to != myself) {
send_sptps_data_priv(to, n, 0, DATA(&pkt), pkt.len - 2 * sizeof(node_id_t));
return;
}
} else {
direct = true;
from = n;
}
pkt.offset = 0;
if(!receive_udppacket(from, &pkt))
return;
n->sock = ls - listen_socket; n->sock = ls - listen_socket;
if(direct && sockaddrcmp(&addr, &n->address))
receive_udppacket(n, &pkt); update_node_udp(n, &addr);
} }
void handle_device_data(void *data, int flags) { void handle_device_data(void *data, int flags) {
vpn_packet_t packet; vpn_packet_t packet;
packet.offset = DEFAULT_PACKET_OFFSET;
packet.priority = 0; packet.priority = 0;
if(devops.read(&packet)) { if(devops.read(&packet)) {

View file

@ -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-2013 Guus Sliepen <guus@tinc-vpn.org> 2000-2014 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>
@ -44,15 +44,17 @@
#include "xalloc.h" #include "xalloc.h"
char *myport; char *myport;
static char *myname;
static io_t device_io; static io_t device_io;
devops_t devops; devops_t devops;
bool device_standby = false;
char *proxyhost; char *proxyhost;
char *proxyport; char *proxyport;
char *proxyuser; char *proxyuser;
char *proxypass; char *proxypass;
proxytype_t proxytype; proxytype_t proxytype;
int autoconnect; bool autoconnect;
bool disablebuggypeers; bool disablebuggypeers;
char *scriptinterpreter; char *scriptinterpreter;
@ -71,25 +73,23 @@ bool node_read_ecdsa_public_key(node_t *n) {
if(!read_host_config(config_tree, n->name)) if(!read_host_config(config_tree, n->name))
goto exit; goto exit;
/* First, check for simple ECDSAPublicKey statement */ /* First, check for simple Ed25519PublicKey statement */
if(get_config_string(lookup_config(config_tree, "ECDSAPublicKey"), &p)) { if(get_config_string(lookup_config(config_tree, "Ed25519PublicKey"), &p)) {
n->ecdsa = ecdsa_set_base64_public_key(p); n->ecdsa = ecdsa_set_base64_public_key(p);
free(p); free(p);
goto exit; goto exit;
} }
/* Else, check for ECDSAPublicKeyFile statement and read it */ /* Else, check for Ed25519PublicKeyFile statement and read it */
if(!get_config_string(lookup_config(config_tree, "ECDSAPublicKeyFile"), &pubname)) if(!get_config_string(lookup_config(config_tree, "Ed25519PublicKeyFile"), &pubname))
xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, n->name); xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, n->name);
fp = fopen(pubname, "r"); fp = fopen(pubname, "r");
if(!fp) { if(!fp)
logger(DEBUG_ALWAYS, LOG_ERR, "Error reading ECDSA public key file `%s': %s", pubname, strerror(errno));
goto exit; goto exit;
}
n->ecdsa = ecdsa_read_pem_public_key(fp); n->ecdsa = ecdsa_read_pem_public_key(fp);
fclose(fp); fclose(fp);
@ -114,23 +114,23 @@ bool read_ecdsa_public_key(connection_t *c) {
return false; return false;
} }
/* First, check for simple ECDSAPublicKey statement */ /* First, check for simple Ed25519PublicKey statement */
if(get_config_string(lookup_config(c->config_tree, "ECDSAPublicKey"), &p)) { if(get_config_string(lookup_config(c->config_tree, "Ed25519PublicKey"), &p)) {
c->ecdsa = ecdsa_set_base64_public_key(p); c->ecdsa = ecdsa_set_base64_public_key(p);
free(p); free(p);
return c->ecdsa; return c->ecdsa;
} }
/* Else, check for ECDSAPublicKeyFile statement and read it */ /* Else, check for Ed25519PublicKeyFile statement and read it */
if(!get_config_string(lookup_config(c->config_tree, "ECDSAPublicKeyFile"), &fname)) if(!get_config_string(lookup_config(c->config_tree, "Ed25519PublicKeyFile"), &fname))
xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name); xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
fp = fopen(fname, "r"); fp = fopen(fname, "r");
if(!fp) { if(!fp) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error reading ECDSA public key file `%s': %s", logger(DEBUG_ALWAYS, LOG_ERR, "Error reading Ed25519 public key file `%s': %s",
fname, strerror(errno)); fname, strerror(errno));
free(fname); free(fname);
return false; return false;
@ -140,7 +140,7 @@ bool read_ecdsa_public_key(connection_t *c) {
fclose(fp); fclose(fp);
if(!c->ecdsa) if(!c->ecdsa)
logger(DEBUG_ALWAYS, LOG_ERR, "Parsing ECDSA public key file `%s' failed.", fname); logger(DEBUG_ALWAYS, LOG_ERR, "Parsing Ed25519 public key file `%s' failed.", fname);
free(fname); free(fname);
return c->ecdsa; return c->ecdsa;
} }
@ -189,15 +189,15 @@ static bool read_ecdsa_private_key(void) {
/* Check for PrivateKeyFile statement and read it */ /* Check for PrivateKeyFile statement and read it */
if(!get_config_string(lookup_config(config_tree, "ECDSAPrivateKeyFile"), &fname)) if(!get_config_string(lookup_config(config_tree, "Ed25519PrivateKeyFile"), &fname))
xasprintf(&fname, "%s" SLASH "ecdsa_key.priv", confbase); xasprintf(&fname, "%s" SLASH "ed25519_key.priv", confbase);
fp = fopen(fname, "r"); fp = fopen(fname, "r");
if(!fp) { if(!fp) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error reading ECDSA private key file `%s': %s", fname, strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "Error reading Ed25519 private key file `%s': %s", fname, strerror(errno));
if(errno == ENOENT) if(errno == ENOENT)
logger(DEBUG_ALWAYS, LOG_INFO, "Create an ECDSA keypair with `tinc -n %s generate-ecdsa-keys'.", netname ?: "."); logger(DEBUG_ALWAYS, LOG_INFO, "Create an Ed25519 keypair with `tinc -n %s generate-ed25519-keys'.", netname ?: ".");
free(fname); free(fname);
return false; return false;
} }
@ -206,20 +206,20 @@ static bool read_ecdsa_private_key(void) {
struct stat s; struct stat s;
if(fstat(fileno(fp), &s)) { if(fstat(fileno(fp), &s)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not stat ECDSA private key file `%s': %s'", fname, strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "Could not stat Ed25519 private key file `%s': %s'", fname, strerror(errno));
free(fname); free(fname);
return false; return false;
} }
if(s.st_mode & ~0100700) if(s.st_mode & ~0100700)
logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: insecure file permissions for ECDSA private key file `%s'!", fname); logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: insecure file permissions for Ed25519 private key file `%s'!", fname);
#endif #endif
myself->connection->ecdsa = ecdsa_read_pem_private_key(fp); myself->connection->ecdsa = ecdsa_read_pem_private_key(fp);
fclose(fp); fclose(fp);
if(!myself->connection->ecdsa) if(!myself->connection->ecdsa)
logger(DEBUG_ALWAYS, LOG_ERR, "Reading ECDSA private key file `%s' failed: %s", fname, strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "Reading Ed25519 private key file `%s' failed", fname);
free(fname); free(fname);
return myself->connection->ecdsa; return myself->connection->ecdsa;
} }
@ -233,7 +233,7 @@ static bool read_invitation_key(void) {
invitation_key = NULL; invitation_key = NULL;
} }
xasprintf(&fname, "%s" SLASH "invitations" SLASH "ecdsa_key.priv", confbase); xasprintf(&fname, "%s" SLASH "invitations" SLASH "ed25519_key.priv", confbase);
fp = fopen(fname, "r"); fp = fopen(fname, "r");
@ -241,7 +241,7 @@ static bool read_invitation_key(void) {
invitation_key = ecdsa_read_pem_private_key(fp); invitation_key = ecdsa_read_pem_private_key(fp);
fclose(fp); fclose(fp);
if(!invitation_key) if(!invitation_key)
logger(DEBUG_ALWAYS, LOG_ERR, "Reading ECDSA private key file `%s' failed: %s", fname, strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "Reading Ed25519 private key file `%s' failed", fname);
} }
free(fname); free(fname);
@ -277,6 +277,8 @@ static bool read_rsa_private_key(void) {
if(!fp) { if(!fp) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error reading RSA private key file `%s': %s", logger(DEBUG_ALWAYS, LOG_ERR, "Error reading RSA private key file `%s': %s",
fname, strerror(errno)); fname, strerror(errno));
if(errno == ENOENT)
logger(DEBUG_ALWAYS, LOG_INFO, "Create an RSA keypair with `tinc -n %s generate-rsa-keys'.", netname ?: ".");
free(fname); free(fname);
return false; return false;
} }
@ -403,40 +405,16 @@ void load_all_nodes(void) {
char *get_name(void) { char *get_name(void) {
char *name = NULL; char *name = NULL;
char *returned_name;
get_config_string(lookup_config(config_tree, "Name"), &name); get_config_string(lookup_config(config_tree, "Name"), &name);
if(!name) if(!name)
return NULL; return NULL;
if(*name == '$') { returned_name = replace_name(name);
char *envname = getenv(name + 1);
if(!envname) {
if(strcmp(name + 1, "HOST")) {
logger(DEBUG_ALWAYS, LOG_ERR, "Invalid Name: environment variable %s does not exist\n", name + 1);
return false;
}
char envname[32];
if(gethostname(envname, 32)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not get hostname: %s\n", strerror(errno));
return false;
}
envname[31] = 0;
}
free(name); free(name);
name = xstrdup(envname); return returned_name;
for(char *c = name; *c; c++)
if(!isalnum(*c))
*c = '_';
}
if(!check_id(name)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Invalid name for myself!");
free(name);
return false;
}
return name;
} }
bool setup_myself_reloadable(void) { bool setup_myself_reloadable(void) {
@ -445,7 +423,6 @@ bool setup_myself_reloadable(void) {
char *fmode = NULL; char *fmode = NULL;
char *bmode = NULL; char *bmode = NULL;
char *afname = NULL; char *afname = NULL;
char *address = NULL;
char *space; char *space;
bool choice; bool choice;
@ -532,16 +509,6 @@ bool setup_myself_reloadable(void) {
get_config_bool(lookup_config(config_tree, "DirectOnly"), &directonly); get_config_bool(lookup_config(config_tree, "DirectOnly"), &directonly);
get_config_bool(lookup_config(config_tree, "LocalDiscovery"), &localdiscovery); get_config_bool(lookup_config(config_tree, "LocalDiscovery"), &localdiscovery);
memset(&localdiscovery_address, 0, sizeof localdiscovery_address);
if(get_config_string(lookup_config(config_tree, "LocalDiscoveryAddress"), &address)) {
struct addrinfo *ai = str2addrinfo(address, myport, SOCK_DGRAM);
free(address);
if(!ai)
return false;
memcpy(&localdiscovery_address, ai->ai_addr, ai->ai_addrlen);
}
if(get_config_string(lookup_config(config_tree, "Mode"), &rmode)) { if(get_config_string(lookup_config(config_tree, "Mode"), &rmode)) {
if(!strcasecmp(rmode, "router")) if(!strcasecmp(rmode, "router"))
routing_mode = RMODE_ROUTER; routing_mode = RMODE_ROUTER;
@ -596,6 +563,20 @@ bool setup_myself_reloadable(void) {
free(bmode); free(bmode);
} }
const char* const DEFAULT_BROADCAST_SUBNETS[] = { "ff:ff:ff:ff:ff:ff", "255.255.255.255", "224.0.0.0/4", "ff00::/8" };
for (size_t i = 0; i < sizeof(DEFAULT_BROADCAST_SUBNETS) / sizeof(*DEFAULT_BROADCAST_SUBNETS); i++) {
subnet_t *s = new_subnet();
if (!str2net(s, DEFAULT_BROADCAST_SUBNETS[i]))
abort();
subnet_add(NULL, s);
}
for (config_t* cfg = lookup_config(config_tree, "BroadcastSubnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
subnet_t *s;
if (!get_config_subnet(cfg, &s))
continue;
subnet_add(NULL, s);
}
#if !defined(SOL_IP) || !defined(IP_TOS) #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", "PriorityInheritance");
@ -631,7 +612,15 @@ bool setup_myself_reloadable(void) {
if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime)) if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime))
keylifetime = 3600; keylifetime = 3600;
get_config_int(lookup_config(config_tree, "AutoConnect"), &autoconnect); config_t *cfg = lookup_config(config_tree, "AutoConnect");
if(cfg) {
if(!get_config_bool(cfg, &autoconnect)) {
// Some backwards compatibility with when this option was an int
int val = 0;
get_config_int(cfg, &val);
autoconnect = val;
}
}
get_config_bool(lookup_config(config_tree, "DisableBuggyPeers"), &disablebuggypeers); get_config_bool(lookup_config(config_tree, "DisableBuggyPeers"), &disablebuggypeers);
@ -640,18 +629,133 @@ bool setup_myself_reloadable(void) {
return true; return true;
} }
/*
Add listening sockets.
*/
static bool add_listen_address(char *address, bool bindto) {
char *port = myport;
if(address) {
char *space = strchr(address, ' ');
if(space) {
*space++ = 0;
port = space;
}
if(!strcmp(address, "*"))
*address = 0;
}
struct addrinfo *ai, hint = {0};
hint.ai_family = addressfamily;
hint.ai_socktype = SOCK_STREAM;
hint.ai_protocol = IPPROTO_TCP;
hint.ai_flags = AI_PASSIVE;
int err = getaddrinfo(address && *address ? address : NULL, port, &hint, &ai);
free(address);
if(err || !ai) {
logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "getaddrinfo", err == EAI_SYSTEM ? strerror(err) : gai_strerror(err));
return false;
}
for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) {
// Ignore duplicate addresses
bool found = false;
for(int i = 0; i < listen_sockets; i++)
if(!memcmp(&listen_socket[i].sa, aip->ai_addr, aip->ai_addrlen)) {
found = true;
break;
}
if(found)
continue;
if(listen_sockets >= MAXSOCKETS) {
logger(DEBUG_ALWAYS, LOG_ERR, "Too many listening sockets");
return false;
}
int tcp_fd = setup_listen_socket((sockaddr_t *) aip->ai_addr);
if(tcp_fd < 0)
continue;
int udp_fd = setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);
if(tcp_fd < 0) {
close(tcp_fd);
continue;
}
io_add(&listen_socket[listen_sockets].tcp, handle_new_meta_connection, &listen_socket[listen_sockets], tcp_fd, IO_READ);
io_add(&listen_socket[listen_sockets].udp, handle_incoming_vpn_data, &listen_socket[listen_sockets], udp_fd, IO_READ);
if(debug_level >= DEBUG_CONNECTIONS) {
char *hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr);
logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Listening on %s", hostname);
free(hostname);
}
listen_socket[listen_sockets].bindto = bindto;
memcpy(&listen_socket[listen_sockets].sa, aip->ai_addr, aip->ai_addrlen);
listen_sockets++;
}
freeaddrinfo(ai);
return true;
}
void device_enable(void) {
if (devops.enable)
devops.enable();
/* Run tinc-up script to further initialize the tap interface */
char *envp[5] = {NULL};
xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
xasprintf(&envp[1], "DEVICE=%s", device ? : "");
xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
xasprintf(&envp[3], "NAME=%s", myname);
execute_script("tinc-up", envp);
for(int i = 0; i < 4; i++)
free(envp[i]);
}
void device_disable(void) {
char *envp[5] = {NULL};
xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
xasprintf(&envp[1], "DEVICE=%s", device ? : "");
xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
xasprintf(&envp[3], "NAME=%s", myname);
execute_script("tinc-down", envp);
for(int i = 0; i < 4; i++)
free(envp[i]);
if (devops.disable)
devops.disable();
}
/* /*
Configure node_t myself and set up the local sockets (listen only) Configure node_t myself and set up the local sockets (listen only)
*/ */
static bool setup_myself(void) { static bool setup_myself(void) {
char *name, *hostname, *cipher, *digest, *type; char *name, *hostname, *cipher, *digest, *type;
char *address = NULL; char *address = NULL;
bool port_specified = false;
if(!(name = get_name())) { if(!(name = get_name())) {
logger(DEBUG_ALWAYS, LOG_ERR, "Name for tinc daemon required!"); logger(DEBUG_ALWAYS, LOG_ERR, "Name for tinc daemon required!");
return false; return false;
} }
myname = xstrdup(name);
myself = new_node(); myself = new_node();
myself->connection = new_connection(); myself->connection = new_connection();
myself->name = name; myself->name = name;
@ -660,9 +764,8 @@ static bool setup_myself(void) {
if(!get_config_string(lookup_config(config_tree, "Port"), &myport)) if(!get_config_string(lookup_config(config_tree, "Port"), &myport))
myport = xstrdup("655"); myport = xstrdup("655");
else
xasprintf(&myself->hostname, "MYSELF port %s", myport); port_specified = true;
myself->connection->hostname = xstrdup(myself->hostname);
myself->connection->options = 0; myself->connection->options = 0;
myself->connection->protocol_major = PROT_MAJOR; myself->connection->protocol_major = PROT_MAJOR;
@ -670,13 +773,25 @@ static bool setup_myself(void) {
myself->options |= PROT_MINOR << 24; myself->options |= PROT_MINOR << 24;
get_config_bool(lookup_config(config_tree, "ExperimentalProtocol"), &experimental); if(!get_config_bool(lookup_config(config_tree, "ExperimentalProtocol"), &experimental)) {
experimental = read_ecdsa_private_key();
if(!experimental)
logger(DEBUG_ALWAYS, LOG_WARNING, "Support for SPTPS disabled.");
} else {
if(experimental && !read_ecdsa_private_key()) if(experimental && !read_ecdsa_private_key())
return false; return false;
}
if(!read_rsa_private_key()) if(!read_rsa_private_key()) {
if(experimental) {
logger(DEBUG_ALWAYS, LOG_WARNING, "Support for legacy protocol disabled.");
} else {
logger(DEBUG_ALWAYS, LOG_ERR, "No private keys available, cannot start tinc!");
return false; return false;
}
}
/* Ensure myport is numeric */
if(!atoi(myport)) { if(!atoi(myport)) {
struct addrinfo *ai = str2addrinfo("localhost", myport, SOCK_DGRAM); struct addrinfo *ai = str2addrinfo("localhost", myport, SOCK_DGRAM);
@ -744,7 +859,9 @@ static bool setup_myself(void) {
if(!get_config_string(lookup_config(config_tree, "Cipher"), &cipher)) if(!get_config_string(lookup_config(config_tree, "Cipher"), &cipher))
cipher = xstrdup("blowfish"); cipher = xstrdup("blowfish");
if(!(myself->incipher = cipher_open_by_name(cipher))) { if(!strcasecmp(cipher, "none")) {
myself->incipher = NULL;
} else if(!(myself->incipher = cipher_open_by_name(cipher))) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unrecognized cipher type!"); logger(DEBUG_ALWAYS, LOG_ERR, "Unrecognized cipher type!");
return false; return false;
} }
@ -766,7 +883,9 @@ static bool setup_myself(void) {
if(!get_config_string(lookup_config(config_tree, "Digest"), &digest)) if(!get_config_string(lookup_config(config_tree, "Digest"), &digest))
digest = xstrdup("sha1"); digest = xstrdup("sha1");
if(!(myself->indigest = digest_open_by_name(digest, maclength))) { if(!strcasecmp(digest, "none")) {
myself->indigest = NULL;
} else if(!(myself->indigest = digest_open_by_name(digest, maclength))) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unrecognized digest type!"); logger(DEBUG_ALWAYS, LOG_ERR, "Unrecognized digest type!");
return false; return false;
} }
@ -822,6 +941,8 @@ static bool setup_myself(void) {
#endif #endif
} }
get_config_bool(lookup_config(config_tree, "DeviceStandby"), &device_standby);
if(!devops.setup()) if(!devops.setup())
return false; return false;
@ -847,7 +968,7 @@ static bool setup_myself(void) {
for(int i = 0; i < listen_sockets; i++) { for(int i = 0; i < listen_sockets; i++) {
salen = sizeof sa; salen = sizeof sa;
if(getsockname(i + 3, &sa.sa, &salen) < 0) { if(getsockname(i + 3, &sa.sa, &salen) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not get address of listen fd %d: %s", i + 3, sockstrerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "Could not get address of listen fd %d: %s", i + 3, sockstrerror(sockerrno));
return false; return false;
} }
@ -872,73 +993,25 @@ static bool setup_myself(void) {
} }
} else { } else {
listen_sockets = 0; listen_sockets = 0;
config_t *cfg = lookup_config(config_tree, "BindToAddress"); int cfgs = 0;
do { for(config_t *cfg = lookup_config(config_tree, "BindToAddress"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
cfgs++;
get_config_string(cfg, &address); get_config_string(cfg, &address);
if(cfg) if(!add_listen_address(address, true))
cfg = lookup_config_next(config_tree, cfg);
char *port = myport;
if(address) {
char *space = strchr(address, ' ');
if(space) {
*space++ = 0;
port = space;
}
if(!strcmp(address, "*"))
*address = 0;
}
struct addrinfo *ai, hint = {0};
hint.ai_family = addressfamily;
hint.ai_socktype = SOCK_STREAM;
hint.ai_protocol = IPPROTO_TCP;
hint.ai_flags = AI_PASSIVE;
int err = getaddrinfo(address && *address ? address : NULL, port, &hint, &ai);
free(address);
if(err || !ai) {
logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "getaddrinfo", err == EAI_SYSTEM ? strerror(err) : gai_strerror(err));
return false; return false;
} }
for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) { for(config_t *cfg = lookup_config(config_tree, "ListenAddress"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
if(listen_sockets >= MAXSOCKETS) { cfgs++;
logger(DEBUG_ALWAYS, LOG_ERR, "Too many listening sockets"); get_config_string(cfg, &address);
if(!add_listen_address(address, false))
return false; return false;
} }
int tcp_fd = setup_listen_socket((sockaddr_t *) aip->ai_addr); if(!cfgs)
if(!add_listen_address(address, NULL))
if(tcp_fd < 0) return false;
continue;
int udp_fd = setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);
if(tcp_fd < 0) {
close(tcp_fd);
continue;
}
io_add(&listen_socket[listen_sockets].tcp, handle_new_meta_connection, &listen_socket[listen_sockets], tcp_fd, IO_READ);
io_add(&listen_socket[listen_sockets].udp, handle_incoming_vpn_data, &listen_socket[listen_sockets], udp_fd, IO_READ);
if(debug_level >= DEBUG_CONNECTIONS) {
hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr);
logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Listening on %s", hostname);
free(hostname);
}
memcpy(&listen_socket[listen_sockets].sa, aip->ai_addr, aip->ai_addrlen);
listen_sockets++;
}
freeaddrinfo(ai);
} while(cfg);
} }
if(!listen_sockets) { if(!listen_sockets) {
@ -946,6 +1019,24 @@ static bool setup_myself(void) {
return false; return false;
} }
/* If no Port option was specified, set myport to the port used by the first listening socket. */
if(!port_specified || atoi(myport) == 0) {
sockaddr_t sa;
socklen_t salen = sizeof sa;
if(!getsockname(listen_socket[0].udp.fd, &sa.sa, &salen)) {
free(myport);
sockaddr2str(&sa, NULL, &myport);
if(!myport)
myport = xstrdup("655");
}
}
xasprintf(&myself->hostname, "MYSELF port %s", myport);
myself->connection->hostname = xstrdup(myself->hostname);
/* Done. */
last_config_check = now.tv_sec; last_config_check = now.tv_sec;
return true; return true;
@ -982,18 +1073,8 @@ bool setup_network(void) {
if(!init_control()) if(!init_control())
return false; return false;
/* Run tinc-up script to further initialize the tap interface */ if (!device_standby)
device_enable();
char *envp[5] = {NULL};
xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
xasprintf(&envp[1], "DEVICE=%s", device ? : "");
xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
xasprintf(&envp[3], "NAME=%s", myself->name);
execute_script("tinc-up", envp);
for(int i = 0; i < 4; i++)
free(envp[i]);
/* Run subnet-up scripts for our own subnets */ /* Run subnet-up scripts for our own subnets */
@ -1016,6 +1097,7 @@ void close_network_connections(void) {
terminate_connection(c, false); terminate_connection(c, false);
} }
if(outgoing_list)
list_delete_list(outgoing_list); list_delete_list(outgoing_list);
if(myself && myself->connection) { if(myself && myself->connection) {
@ -1031,28 +1113,27 @@ void close_network_connections(void) {
close(listen_socket[i].udp.fd); close(listen_socket[i].udp.fd);
} }
char *envp[5] = {NULL};
xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
xasprintf(&envp[1], "DEVICE=%s", device ? : "");
xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
xasprintf(&envp[3], "NAME=%s", myself->name);
exit_requests(); exit_requests();
exit_edges(); exit_edges();
exit_subnets(); exit_subnets();
exit_nodes(); exit_nodes();
exit_connections(); exit_connections();
execute_script("tinc-down", envp); if (!device_standby)
device_disable();
if(myport) free(myport); free(myport);
for(int i = 0; i < 4; i++)
free(envp[i]);
if (device_fd >= 0)
io_del(&device_io);
if (devops.close)
devops.close(); devops.close();
exit_control(); exit_control();
free(myname);
free(scriptextension);
free(scriptinterpreter);
return; return;
} }

View file

@ -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-2013 Guus Sliepen <guus@tinc-vpn.org> 2000-2014 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>
@ -103,7 +103,7 @@ static bool bind_to_interface(int sd) {
status = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)); status = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr));
if(status) { if(status) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to interface %s: %s", iface, logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to interface %s: %s", iface,
strerror(errno)); sockstrerror(sockerrno));
return false; return false;
} }
#else /* if !defined(SOL_SOCKET) || !defined(SO_BINDTODEVICE) */ #else /* if !defined(SOL_SOCKET) || !defined(SO_BINDTODEVICE) */
@ -116,7 +116,7 @@ static bool bind_to_interface(int sd) {
static bool bind_to_address(connection_t *c) { static bool bind_to_address(connection_t *c) {
int s = -1; int s = -1;
for(int i = 0; i < listen_sockets; i++) { for(int i = 0; i < listen_sockets && listen_socket[i].bindto; i++) {
if(listen_socket[i].sa.sa.sa_family != c->address.sa.sa_family) if(listen_socket[i].sa.sa.sa_family != c->address.sa.sa_family)
continue; continue;
if(s >= 0) if(s >= 0)
@ -134,7 +134,7 @@ static bool bind_to_address(connection_t *c) {
sa.in6.sin6_port = 0; sa.in6.sin6_port = 0;
if(bind(c->socket, &sa.sa, SALEN(sa.sa))) { if(bind(c->socket, &sa.sa, SALEN(sa.sa))) {
logger(DEBUG_CONNECTIONS, LOG_WARNING, "Can't bind outgoing socket: %s", strerror(errno)); logger(DEBUG_CONNECTIONS, LOG_WARNING, "Can't bind outgoing socket: %s", sockstrerror(sockerrno));
return false; return false;
} }
@ -179,7 +179,7 @@ int setup_listen_socket(const sockaddr_t *sa) {
if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof ifr)) { if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof ifr)) {
closesocket(nfd); closesocket(nfd);
logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to interface %s: %s", iface, logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to interface %s: %s", iface,
strerror(sockerrno)); sockstrerror(sockerrno));
return -1; return -1;
} }
#else #else
@ -247,10 +247,10 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
setsockopt(nfd, SOL_SOCKET, SO_BROADCAST, (void *)&option, sizeof option); setsockopt(nfd, SOL_SOCKET, SO_BROADCAST, (void *)&option, sizeof option);
if(udp_rcvbuf && setsockopt(nfd, SOL_SOCKET, SO_RCVBUF, (void *)&udp_rcvbuf, sizeof(udp_rcvbuf))) if(udp_rcvbuf && setsockopt(nfd, SOL_SOCKET, SO_RCVBUF, (void *)&udp_rcvbuf, sizeof(udp_rcvbuf)))
logger(DEBUG_ALWAYS, LOG_WARNING, "Can't set UDP SO_RCVBUF to %i: %s", udp_rcvbuf, strerror(errno)); logger(DEBUG_ALWAYS, LOG_WARNING, "Can't set UDP SO_RCVBUF to %i: %s", udp_rcvbuf, sockstrerror(sockerrno));
if(udp_sndbuf && setsockopt(nfd, SOL_SOCKET, SO_SNDBUF, (void *)&udp_sndbuf, sizeof(udp_sndbuf))) if(udp_sndbuf && setsockopt(nfd, SOL_SOCKET, SO_SNDBUF, (void *)&udp_sndbuf, sizeof(udp_sndbuf)))
logger(DEBUG_ALWAYS, LOG_WARNING, "Can't set UDP SO_SNDBUF to %i: %s", udp_sndbuf, strerror(errno)); logger(DEBUG_ALWAYS, LOG_WARNING, "Can't set UDP SO_SNDBUF to %i: %s", udp_sndbuf, sockstrerror(sockerrno));
#if defined(IPPROTO_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)
@ -271,8 +271,6 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
option = 1; option = 1;
setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, (void *)&option, sizeof(option)); setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, (void *)&option, sizeof(option));
} }
#else
#warning No way to disable IPv4 fragmentation
#endif #endif
#if defined(SOL_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) #if defined(SOL_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
@ -285,8 +283,6 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
option = 1; option = 1;
setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, (void *)&option, sizeof(option)); setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, (void *)&option, sizeof(option));
} }
#else
#warning No way to disable IPv6 fragmentation
#endif #endif
if (!bind_to_interface(nfd)) { if (!bind_to_interface(nfd)) {
@ -334,7 +330,7 @@ static void do_outgoing_pipe(connection_t *c, char *command) {
int fd[2]; int fd[2];
if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) { if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not create socketpair: %s", strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "Could not create socketpair: %s", sockstrerror(sockerrno));
return; return;
} }
@ -383,16 +379,16 @@ static void handle_meta_write(connection_t *c) {
ssize_t outlen = send(c->socket, c->outbuf.data + c->outbuf.offset, c->outbuf.len - c->outbuf.offset, 0); ssize_t outlen = send(c->socket, c->outbuf.data + c->outbuf.offset, c->outbuf.len - c->outbuf.offset, 0);
if(outlen <= 0) { if(outlen <= 0) {
if(!errno || errno == EPIPE) { if(!sockerrno || sockerrno == EPIPE) {
logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection closed by %s (%s)", c->name, c->hostname); logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection closed by %s (%s)", c->name, c->hostname);
} else if(sockwouldblock(sockerrno)) { } else if(sockwouldblock(sockerrno)) {
logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Sending %d bytes to %s (%s) would block", c->outbuf.len - c->outbuf.offset, c->name, c->hostname); logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Sending %d bytes to %s (%s) would block", c->outbuf.len - c->outbuf.offset, c->name, c->hostname);
return; return;
} else { } else {
logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not send %d bytes of data to %s (%s): %s", c->outbuf.len - c->outbuf.offset, c->name, c->hostname, strerror(errno)); logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not send %d bytes of data to %s (%s): %s", c->outbuf.len - c->outbuf.offset, c->name, c->hostname, sockstrerror(sockerrno));
} }
terminate_connection(c, c->status.active); terminate_connection(c, c->edge);
return; return;
} }
@ -405,19 +401,38 @@ static void handle_meta_io(void *data, int flags) {
connection_t *c = data; connection_t *c = data;
if(c->status.connecting) { if(c->status.connecting) {
c->status.connecting = false; /*
The event loop does not protect against spurious events. Verify that we are actually connected
by issuing an empty send() call.
int result; Note that the behavior of send() on potentially unconnected sockets differ between platforms:
socklen_t len = sizeof result; +------------+-----------+-------------+-----------+
getsockopt(c->socket, SOL_SOCKET, SO_ERROR, (void *)&result, &len); | Event | POSIX | Linux | Windows |
+------------+-----------+-------------+-----------+
if(!result) | Spurious | ENOTCONN | EWOULDBLOCK | ENOTCONN |
finish_connecting(c); | Failed | ENOTCONN | (cause) | ENOTCONN |
| Successful | (success) | (success) | (success) |
+------------+-----------+-------------+-----------+
*/
if (send(c->socket, NULL, 0, 0) != 0) {
if (sockwouldblock(sockerrno))
return;
int socket_error;
if (!socknotconn(sockerrno))
socket_error = sockerrno;
else { else {
logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Error while connecting to %s (%s): %s", c->name, c->hostname, sockstrerror(result)); socklen_t len = sizeof socket_error;
getsockopt(c->socket, SOL_SOCKET, SO_ERROR, (void *)&socket_error, &len);
}
if (socket_error) {
logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Error while connecting to %s (%s): %s", c->name, c->hostname, sockstrerror(socket_error));
terminate_connection(c, false); terminate_connection(c, false);
}
return; return;
} }
c->status.connecting = false;
finish_connecting(c);
} }
if(flags & IO_WRITE) if(flags & IO_WRITE)
@ -547,6 +562,39 @@ begin:
return true; return true;
} }
// Find edges pointing to this node, and use them to build a list of unique, known addresses.
static struct addrinfo *get_known_addresses(node_t *n) {
struct addrinfo *ai = NULL;
for splay_each(edge_t, e, n->edge_tree) {
if(!e->reverse)
continue;
bool found = false;
for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) {
if(!sockaddrcmp(&e->reverse->address, (sockaddr_t *)aip->ai_addr)) {
found = true;
break;
}
}
if(found)
continue;
struct addrinfo *nai = xzalloc(sizeof *nai);
if(ai)
ai->ai_next = nai;
ai = nai;
ai->ai_family = e->reverse->address.sa.sa_family;
ai->ai_socktype = SOCK_STREAM;
ai->ai_protocol = IPPROTO_TCP;
ai->ai_addrlen = SALEN(e->reverse->address.sa);
ai->ai_addr = xmalloc(ai->ai_addrlen);
memcpy(ai->ai_addr, &e->reverse->address, ai->ai_addrlen);
}
return ai;
}
void setup_outgoing_connection(outgoing_t *outgoing) { void setup_outgoing_connection(outgoing_t *outgoing) {
timeout_del(&outgoing->ev); timeout_del(&outgoing->ev);
@ -564,9 +612,13 @@ void setup_outgoing_connection(outgoing_t *outgoing) {
outgoing->cfg = lookup_config(outgoing->config_tree, "Address"); outgoing->cfg = lookup_config(outgoing->config_tree, "Address");
if(!outgoing->cfg) { if(!outgoing->cfg) {
logger(DEBUG_ALWAYS, LOG_ERR, "No address specified for %s", outgoing->name); if(n)
outgoing->aip = outgoing->ai = get_known_addresses(n);
if(!outgoing->ai) {
logger(DEBUG_ALWAYS, LOG_ERR, "No address known for %s", outgoing->name);
return; return;
} }
}
do_outgoing_connection(outgoing); do_outgoing_connection(outgoing);
} }
@ -594,7 +646,6 @@ void handle_new_meta_connection(void *data, int flags) {
// Check if we get many connections from the same host // Check if we get many connections from the same host
static sockaddr_t prev_sa; static sockaddr_t prev_sa;
static time_t prev_time;
static int tarpit = -1; static int tarpit = -1;
if(tarpit >= 0) { if(tarpit >= 0) {
@ -621,7 +672,6 @@ void handle_new_meta_connection(void *data, int flags) {
} }
memcpy(&prev_sa, &sa, sizeof sa); memcpy(&prev_sa, &sa, sizeof sa);
prev_time = now.tv_sec;
// Check if we get many connections from different hosts // Check if we get many connections from different hosts
@ -770,7 +820,7 @@ void try_outgoing_connections(void) {
if(c->outgoing && c->outgoing->timeout == -1) { if(c->outgoing && c->outgoing->timeout == -1) {
c->outgoing = NULL; c->outgoing = NULL;
logger(DEBUG_CONNECTIONS, LOG_INFO, "No more outgoing connection to %s", c->name); logger(DEBUG_CONNECTIONS, LOG_INFO, "No more outgoing connection to %s", c->name);
terminate_connection(c, c->status.active); terminate_connection(c, c->edge);
} }
} }

View file

@ -30,8 +30,12 @@
#include "utils.h" #include "utils.h"
#include "xalloc.h" #include "xalloc.h"
static digest_t *sha256;
splay_tree_t *node_tree; splay_tree_t *node_tree;
static splay_tree_t *node_id_tree;
static hash_t *node_udp_cache; static hash_t *node_udp_cache;
static hash_t *node_id_cache;
node_t *myself; node_t *myself;
@ -39,14 +43,26 @@ static int node_compare(const node_t *a, const node_t *b) {
return strcmp(a->name, b->name); return strcmp(a->name, b->name);
} }
static int node_id_compare(const node_t *a, const node_t *b) {
return memcmp(&a->id, &b->id, sizeof(node_id_t));
}
void init_nodes(void) { void init_nodes(void) {
sha256 = digest_open_by_name("sha256", sizeof(node_id_t));
node_tree = splay_alloc_tree((splay_compare_t) node_compare, (splay_action_t) free_node); node_tree = splay_alloc_tree((splay_compare_t) node_compare, (splay_action_t) free_node);
node_id_tree = splay_alloc_tree((splay_compare_t) node_id_compare, NULL);
node_udp_cache = hash_alloc(0x100, sizeof(sockaddr_t)); node_udp_cache = hash_alloc(0x100, sizeof(sockaddr_t));
node_id_cache = hash_alloc(0x100, sizeof(node_id_t));
} }
void exit_nodes(void) { void exit_nodes(void) {
hash_free(node_id_cache);
hash_free(node_udp_cache); hash_free(node_udp_cache);
splay_delete_tree(node_id_tree);
splay_delete_tree(node_tree); splay_delete_tree(node_tree);
digest_close(sha256);
} }
node_t *new_node(void) { node_t *new_node(void) {
@ -93,16 +109,23 @@ void free_node(node_t *n) {
} }
void node_add(node_t *n) { void node_add(node_t *n) {
digest_create(sha256, n->name, strlen(n->name), &n->id);
splay_insert(node_tree, n); splay_insert(node_tree, n);
splay_insert(node_id_tree, n);
} }
void node_del(node_t *n) { void node_del(node_t *n) {
hash_delete(node_udp_cache, &n->address);
hash_delete(node_id_cache, &n->id);
for splay_each(subnet_t, s, n->subnet_tree) for splay_each(subnet_t, s, n->subnet_tree)
subnet_del(n, s); subnet_del(n, s);
for splay_each(edge_t, e, n->edge_tree) for splay_each(edge_t, e, n->edge_tree)
edge_del(e); edge_del(e);
splay_delete(node_id_tree, n);
splay_delete(node_tree, n); splay_delete(node_tree, n);
} }
@ -114,6 +137,18 @@ node_t *lookup_node(char *name) {
return splay_search(node_tree, &n); return splay_search(node_tree, &n);
} }
node_t *lookup_node_id(const node_id_t *id) {
node_t *n = hash_search(node_id_cache, id);
if(!n) {
node_t tmp = {.id = *id};
n = splay_search(node_id_tree, &tmp);
if(n)
hash_insert(node_id_cache, id, n);
}
return n;
}
node_t *lookup_node_udp(const sockaddr_t *sa) { node_t *lookup_node_udp(const sockaddr_t *sa) {
return hash_search(node_udp_cache, sa); return hash_search(node_udp_cache, sa);
} }
@ -124,7 +159,7 @@ void update_node_udp(node_t *n, const sockaddr_t *sa) {
return; return;
} }
hash_insert(node_udp_cache, &n->address, NULL); hash_delete(node_udp_cache, &n->address);
if(sa) { if(sa) {
n->address = *sa; n->address = *sa;
@ -140,15 +175,27 @@ void update_node_udp(node_t *n, const sockaddr_t *sa) {
n->hostname = sockaddr2hostname(&n->address); n->hostname = sockaddr2hostname(&n->address);
logger(DEBUG_PROTOCOL, LOG_DEBUG, "UDP address of %s set to %s", n->name, n->hostname); logger(DEBUG_PROTOCOL, LOG_DEBUG, "UDP address of %s set to %s", n->name, n->hostname);
} }
/* invalidate UDP information - note that this is a security feature as well to make sure
we can't be tricked into flooding any random address with UDP packets */
n->status.udp_confirmed = false;
n->mtuprobes = 0;
n->minmtu = 0;
n->maxmtu = MTU;
} }
bool dump_nodes(connection_t *c) { bool dump_nodes(connection_t *c) {
for splay_each(node_t, n, node_tree) for splay_each(node_t, n, node_tree) {
send_request(c, "%d %d %s %s %d %d %d %d %x %x %s %s %d %hd %hd %hd %ld", CONTROL, REQ_DUMP_NODES, char id[2 * sizeof n->id + 1];
n->name, n->hostname ?: "unknown port unknown", cipher_get_nid(n->outcipher), for (size_t c = 0; c < sizeof n->id; ++c)
sprintf(id + 2 * c, "%02hhx", n->id.x[c]);
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,
n->name, id, n->hostname ?: "unknown port unknown", cipher_get_nid(n->outcipher),
digest_get_nid(n->outdigest), (int)digest_length(n->outdigest), n->outcompression, digest_get_nid(n->outdigest), (int)digest_length(n->outdigest), n->outcompression,
n->options, bitfield_to_int(&n->status, sizeof n->status), n->nexthop ? n->nexthop->name : "-", n->options, bitfield_to_int(&n->status, sizeof n->status), n->nexthop ? n->nexthop->name : "-",
n->via ? n->via->name ?: "-" : "-", n->distance, n->mtu, n->minmtu, n->maxmtu, (long)n->last_state_change); n->via ? n->via->name ?: "-" : "-", n->distance, n->mtu, n->minmtu, n->maxmtu, (long)n->last_state_change);
}
return send_request(c, "%d %d", CONTROL, REQ_DUMP_NODES); return send_request(c, "%d %d", CONTROL, REQ_DUMP_NODES);
} }

View file

@ -37,11 +37,13 @@ typedef struct node_status_t {
unsigned int indirect:1; /* 1 if this node is not directly reachable by us */ unsigned int indirect:1; /* 1 if this node is not directly reachable by us */
unsigned int sptps:1; /* 1 if this node supports SPTPS */ unsigned int sptps:1; /* 1 if this node supports SPTPS */
unsigned int udp_confirmed:1; /* 1 if the address is one that we received UDP traffic on */ unsigned int udp_confirmed:1; /* 1 if the address is one that we received UDP traffic on */
unsigned int unused:24; unsigned int send_locally:1; /* 1 if the next UDP packet should be sent on the local network */
unsigned int unused:23;
} node_status_t; } node_status_t;
typedef struct node_t { typedef struct node_t {
char *name; /* name of this node */ char *name; /* name of this node */
node_id_t id; /* unique node ID (name hash) */
uint32_t options; /* options turned on for this node */ uint32_t options; /* options turned on for this node */
int sock; /* Socket to use for outgoing UDP packets */ int sock; /* Socket to use for outgoing UDP packets */
@ -110,6 +112,7 @@ extern void free_node(node_t *);
extern void node_add(node_t *); extern void node_add(node_t *);
extern void node_del(node_t *); extern void node_del(node_t *);
extern node_t *lookup_node(char *); extern node_t *lookup_node(char *);
extern node_t *lookup_node_id(const node_id_t *);
extern node_t *lookup_node_udp(const sockaddr_t *); extern node_t *lookup_node_udp(const sockaddr_t *);
extern bool dump_nodes(struct connection_t *); extern bool dump_nodes(struct connection_t *);
extern bool dump_traffic(struct connection_t *); extern bool dump_traffic(struct connection_t *);

View file

@ -30,15 +30,8 @@
struct cipher { struct cipher {
EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX ctx;
const EVP_CIPHER *cipher; const EVP_CIPHER *cipher;
struct cipher_counter *counter;
}; };
typedef struct cipher_counter {
unsigned char counter[CIPHER_MAX_IV_SIZE];
unsigned char block[CIPHER_MAX_IV_SIZE];
int n;
} cipher_counter_t;
static cipher_t *cipher_open(const EVP_CIPHER *evp_cipher) { static cipher_t *cipher_open(const EVP_CIPHER *evp_cipher) {
cipher_t *cipher = xzalloc(sizeof *cipher); cipher_t *cipher = xzalloc(sizeof *cipher);
cipher->cipher = evp_cipher; cipher->cipher = evp_cipher;
@ -76,7 +69,6 @@ void cipher_close(cipher_t *cipher) {
return; return;
EVP_CIPHER_CTX_cleanup(&cipher->ctx); EVP_CIPHER_CTX_cleanup(&cipher->ctx);
free(cipher->counter);
free(cipher); free(cipher);
} }
@ -84,7 +76,7 @@ size_t cipher_keylength(const cipher_t *cipher) {
if(!cipher || !cipher->cipher) if(!cipher || !cipher->cipher)
return 0; return 0;
return cipher->cipher->key_len + cipher->cipher->block_size; return cipher->cipher->key_len + cipher->cipher->iv_len;
} }
bool cipher_set_key(cipher_t *cipher, void *key, bool encrypt) { bool cipher_set_key(cipher_t *cipher, void *key, bool encrypt) {
@ -117,70 +109,6 @@ bool cipher_set_key_from_rsa(cipher_t *cipher, void *key, size_t len, bool encry
return false; return false;
} }
bool cipher_set_counter(cipher_t *cipher, const void *counter, size_t len) {
if(len > cipher->cipher->block_size - 4) {
logger(DEBUG_ALWAYS, LOG_ERR, "Counter too long");
abort();
}
memcpy(cipher->counter->counter + cipher->cipher->block_size - len, counter, len);
memset(cipher->counter->counter, 0, 4);
cipher->counter->n = 0;
return true;
}
bool cipher_set_counter_key(cipher_t *cipher, void *key) {
int result = EVP_EncryptInit_ex(&cipher->ctx, cipher->cipher, NULL, (unsigned char *)key, NULL);
if(!result) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while setting key: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
}
if(!cipher->counter)
cipher->counter = xzalloc(sizeof *cipher->counter);
else
cipher->counter->n = 0;
memcpy(cipher->counter->counter, (unsigned char *)key + cipher->cipher->key_len, cipher->cipher->block_size);
return true;
}
bool cipher_counter_xor(cipher_t *cipher, const void *indata, size_t inlen, void *outdata) {
if(!cipher->counter) {
logger(DEBUG_ALWAYS, LOG_ERR, "Counter not initialized");
return false;
}
const unsigned char *in = indata;
unsigned char *out = outdata;
while(inlen--) {
// Encrypt the new counter value if we need it
if(!cipher->counter->n) {
int len;
if(!EVP_EncryptUpdate(&cipher->ctx, cipher->counter->block, &len, cipher->counter->counter, cipher->cipher->block_size)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while encrypting: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
}
// Increase the counter value
for(int i = 0; i < cipher->cipher->block_size; i++)
if(++cipher->counter->counter[i])
break;
}
*out++ = *in++ ^ cipher->counter->block[cipher->counter->n++];
if(cipher->counter->n >= cipher->cipher->block_size)
cipher->counter->n = 0;
}
return true;
}
bool cipher_encrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) { bool cipher_encrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) {
if(oneshot) { if(oneshot) {
int len, pad; int len, pad;

View file

@ -1,6 +1,6 @@
/* /*
crypto.c -- Cryptographic miscellaneous functions and initialisation crypto.c -- Cryptographic miscellaneous functions and initialisation
Copyright (C) 2007-2013 Guus Sliepen <guus@tinc-vpn.org> Copyright (C) 2007-2014 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,8 +25,65 @@
#include "../crypto.h" #include "../crypto.h"
#ifndef HAVE_MINGW
static int random_fd = -1;
static void random_init(void) {
random_fd = open("/dev/urandom", O_RDONLY);
if(random_fd < 0)
random_fd = open("/dev/random", O_RDONLY);
if(random_fd < 0) {
fprintf(stderr, "Could not open source of random numbers: %s\n", strerror(errno));
abort();
}
}
static void random_exit(void) {
close(random_fd);
}
void randomize(void *out, size_t outlen) {
while(outlen) {
size_t len = read(random_fd, out, outlen);
if(len <= 0) {
if(errno == EAGAIN || errno == EINTR)
continue;
fprintf(stderr, "Could not read random numbers: %s\n", strerror(errno));
abort();
}
out += len;
outlen -= len;
}
}
#else
#include <wincrypt.h>
HCRYPTPROV prov;
void random_init(void) {
if(!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
fprintf(stderr, "CryptAcquireContext() failed!\n");
abort();
}
}
void random_exit(void) {
CryptReleaseContext(prov, 0);
}
void randomize(void *out, size_t outlen) {
if(!CryptGenRandom(prov, outlen, out)) {
fprintf(stderr, "CryptGenRandom() failed\n");
abort();
}
}
#endif
void crypto_init(void) { void crypto_init(void) {
RAND_load_file("/dev/urandom", 1024); random_init();
ENGINE_load_builtin_engines(); ENGINE_load_builtin_engines();
ENGINE_register_all_complete(); ENGINE_register_all_complete();
@ -42,8 +99,7 @@ void crypto_init(void) {
void crypto_exit(void) { void crypto_exit(void) {
EVP_cleanup(); EVP_cleanup();
} ERR_free_strings();
ENGINE_cleanup();
void randomize(void *out, size_t outlen) { random_exit();
RAND_pseudo_bytes(out, outlen);
} }

Some files were not shown because too many files have changed in this diff Show more