Import Upstream version 1.1~pre11

This commit is contained in:
Guus Sliepen 2019-08-26 13:44:51 +02:00
parent 60cff3039b
commit 1813f3157e
128 changed files with 10991 additions and 3132 deletions

20
AUTHORS
View file

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

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.
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
------------------------------------------------------------------------

View file

@ -12,8 +12,8 @@ without warranty of any kind.
Basic Installation
==================
Briefly, the shell commands `./configure; make; make install' should
configure, build, and install this package. The following
Briefly, the shell command `./configure && make && make install'
should configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package. Some packages provide this
`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@
# 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
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \
$(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.ac
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_check_link_flag.m4 \
$(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) \
$(ACLOCAL_M4)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
@ -223,9 +226,6 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LN_S = @LN_S@
@ -241,7 +241,6 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
READLINE_LIBS = @READLINE_LIBS@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
@ -599,9 +598,10 @@ distcheck: dist
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
&& am__cwd=`pwd` \
&& $(am__cd) $(distdir)/_build \
&& ../configure --srcdir=.. --prefix="$$dc_install_base" \
&& ../configure \
$(AM_DISTCHECK_CONFIGURE_FLAGS) \
$(DISTCHECK_CONFIGURE_FLAGS) \
--srcdir=.. --prefix="$$dc_install_base" \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(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
* 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.
tinc is Copyright (C) 1998-2013 by:
tinc is Copyright (C) 1998-2014 by:
Ivo Timmermans,
Guus Sliepen <guus@tinc-vpn.org>,
@ -36,12 +36,11 @@ at your own risk.
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.
When the ExperimentalProtocol option is used, which is the default since
1.1pre8, tinc is still compatible with 1.0.X and 1.1pre9 itself, but not with
any other 1.1preX version.
When the ExperimentalProtocol option is used, tinc is still compatible with
1.0.X and 1.1pre11 itself, but not with any other 1.1preX version.
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:
- 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:
@ -73,8 +72,8 @@ be forwarded by intermediate nodes.
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
CTR mode*), authenticated using HMAC-SHA1 (or HMAC-SHA-256*), and is protected
against replay attacks.
GCM mode*), authenticated using HMAC-SHA1 (or GCM*), and is protected against
replay attacks.
*) 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:
* Alexander Reil and Gemeinde Berg
* Alexander Ried
* Alexis Hildebrandt
* Allesandro Gatti
* Andreas van Cranenburgh
* Anthony G. Basile
* Armijn Hemel
* Armin Fisslthaler
* Baptiste Jonglez
* Borg
* Brandon Black
* Cheng LI
* Cris van Pelt
* Darius Jahandarie
* David Pflug
* Delf Eldkraft
* Dennis Joachimsthaler
* dnk
* Enrique Zanardi
* Erik Tews
* Etienne Dechamps
* Florent Clairambault
* Flynn Marquardt
* Franz Pletz
* Gary Kessler and Claudia Gonzalez
* Grzegorz Dymarek
* Hans Bayle
* Ivo van Dong
* James Cook
* James MacLean
* Jamie Briggs
* Jason Harper
* Jason Livesay
* Jelle de Jong
* Jeroen Ubbink
* Jerome Etienne
* Jochen Voss
* Julien Muchembled
* Lavrans Laading
* Loïc Dachary
* Loïc Grenié
* Lubomír Bulej
* Mads Kiilerich
* Marc A. Lehmann
* Mark Glines
* Mark Petryk
* Markus Goetz
* Martin Kihlgren
* Martin Schobert
@ -45,16 +62,24 @@ We would like to thank the following people for their contributions to tinc:
* Philipp Babel
* Robert van der Meulen
* Rumko
* Saverio Proto
* Scott Lamb
* Steffan Karger
* Sven-Haegar Koch
* Teemu Kiviniemi
* Thomas Tsiakalakis
* Timothy Redaelli
* Tomislav Čohar
* Tommy Arnkværn
* Tonnerre Lombard
* Vil Brekin
* Vittorio Gambaletta
* Wessel Dankers
* William A. Kennington III
* William McArthur
* Wouter van Heyst
And everyone we forgot. Thank you!
And everyone we forgot (if we did, please let us know). Thank you!
Ivo Timmermans
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.
@ -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.
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.
#
# This file is free software; the Free Software Foundation
@ -159,7 +35,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.14'
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.
m4_if([$1], [1.14], [],
m4_if([$1], [1.14.1], [],
[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.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
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_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_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.
AC_DEFUN([AM_AUX_DIR_EXPAND],
[dnl Rely on autoconf to set up CDPATH properly.
AC_PREREQ([2.50])dnl
# expand $ac_aux_dir to an absolute path
am_aux_dir=`cd $ac_aux_dir && pwd`
[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
# Expand $ac_aux_dir to an absolute path.
am_aux_dir=`cd "$ac_aux_dir" && pwd`
])
# AM_CONDITIONAL -*- Autoconf -*-
@ -697,7 +572,8 @@ to "yes", and re-run configure.
END
AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
fi
fi])
fi
])
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
@ -1272,7 +1148,10 @@ AC_SUBST([am__untar])
]) # _AM_PROG_TAR
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/libgcrypt.m4])
m4_include([m4/lzo.m4])
m4_include([m4/openssl.m4])
m4_include([m4/readline.m4])

174
config.guess vendored
View file

@ -1,8 +1,8 @@
#! /bin/sh
# 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
# under the terms of the GNU General Public License as published by
@ -50,7 +50,7 @@ version="\
GNU config.guess ($timestamp)
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
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@ -149,7 +149,7 @@ Linux|GNU|GNU/*)
LIBC=gnu
#endif
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
@ -826,7 +826,7 @@ EOF
*:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32
exit ;;
i*:MSYS*:*)
*:MSYS*:*)
echo ${UNAME_MACHINE}-pc-msys
exit ;;
i*:windows32*:*)
@ -969,10 +969,10 @@ EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
;;
or1k:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
openrisc*:Linux:*:*)
echo or1k-unknown-linux-${LIBC}
exit ;;
or32:Linux:*:*)
or32:Linux:*:* | or1k*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
padre:Linux:*:*)
@ -1260,6 +1260,7 @@ EOF
if test "$UNAME_PROCESSOR" = unknown ; then
UNAME_PROCESSOR=powerpc
fi
if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
@ -1271,6 +1272,15 @@ EOF
esac
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}
exit ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
@ -1361,154 +1371,6 @@ EOF
exit ;;
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
$0: unable to guess system type

View file

@ -52,18 +52,20 @@
don't. */
#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. */
#undef HAVE_DIRENT_H
/* 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. */
#undef HAVE_EVP_ENCRYPTINIT_EX
@ -82,6 +84,9 @@
/* Define to 1 if you have the `ftime' function. */
#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. */
#undef HAVE_GETTIMEOFDAY
@ -94,6 +99,9 @@
/* Define to 1 if you have the `nsl' library (-lnsl). */
#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). */
#undef HAVE_LIBSOCKET
@ -190,12 +198,6 @@
/* 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. */
#undef HAVE_OPENSSL_ENGINE_H
@ -223,8 +225,8 @@
/* Define to 1 if you have the `random' function. */
#undef HAVE_RANDOM
/* Define to 1 if you have the `RAND_pseudo_bytes' function. */
#undef HAVE_RAND_PSEUDO_BYTES
/* Define to 1 if you have the `RAND_status' function. */
#undef HAVE_RAND_STATUS
/* have readline support */
#undef HAVE_READLINE
@ -235,6 +237,9 @@
/* Define to 1 if you have the <readline/readline.h> header file. */
#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. */
#undef HAVE_SELECT

30
config.sub vendored
View file

@ -1,8 +1,8 @@
#! /bin/sh
# 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
# 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="\
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
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@ -265,6 +265,7 @@ case $basic_machine in
| hexagon \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
| k1om \
| le32 | le64 \
| lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
@ -282,8 +283,10 @@ case $basic_machine in
| mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
| mipsisa32r6 | mipsisa32r6el \
| mipsisa64 | mipsisa64el \
| mipsisa64r2 | mipsisa64r2el \
| mipsisa64r6 | mipsisa64r6el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
| mipsr5900 | mipsr5900el \
@ -295,11 +298,11 @@ case $basic_machine in
| nds32 | nds32le | nds32be \
| nios | nios2 | nios2eb | nios2el \
| ns16k | ns32k \
| open8 \
| or1k | or32 \
| open8 | or1k | or1knd | or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
| riscv32 | riscv64 \
| rl78 | rx \
| score \
| 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)
basic_machine=tic6x-unknown
;;
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
basic_machine=$basic_machine-unknown
os=-none
;;
@ -381,6 +384,7 @@ case $basic_machine in
| hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
| k1om-* \
| le32-* | le64-* \
| lm32-* \
| m32c-* | m32r-* | m32rle-* \
@ -400,8 +404,10 @@ case $basic_machine in
| mips64vr5900-* | mips64vr5900el-* \
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
| mipsisa32r6-* | mipsisa32r6el-* \
| mipsisa64-* | mipsisa64el-* \
| mipsisa64r2-* | mipsisa64r2el-* \
| mipsisa64r6-* | mipsisa64r6el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipsr5900-* | mipsr5900el-* \
@ -413,6 +419,7 @@ case $basic_machine in
| nios-* | nios2-* | nios2eb-* | nios2el-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| open8-* \
| or1k*-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
@ -822,6 +829,10 @@ case $basic_machine in
basic_machine=powerpc-unknown
os=-morphos
;;
moxiebox)
basic_machine=moxie-unknown
os=-moxiebox
;;
msdos)
basic_machine=i386-pc
os=-msdos
@ -1367,14 +1378,14 @@ case $os in
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* \
| -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -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.
;;
-qnx*)
@ -1592,9 +1603,6 @@ case $basic_machine in
mips*-*)
os=-elf
;;
or1k-*)
os=-elf
;;
or32-*)
os=-coff
;;

1026
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.
AC_PREREQ(2.61)
AC_INIT([tinc], [1.1pre9])
AC_INIT([tinc], [1.1pre11])
AC_CONFIG_SRCDIR([src/tincd.c])
AC_GNU_SOURCE
AM_INIT_AUTOMAKE([check-news std-options subdir-objects -Wall])
@ -18,7 +18,6 @@ AC_PROG_CC_C99
AC_PROG_CPP
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_RANLIB
AM_PROG_CC_C_O
@ -109,7 +108,7 @@ AC_ARG_ENABLE(tunemu,
)
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"],
[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"
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 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],
[], [], [#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"]
)
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"]
)
AC_CHECK_DECLS([res_init], [AC_CHECK_LIB(resolv, res_init)], [], [
#include <netinet/in.h>
#include <resolv.h>
])
AC_CACHE_SAVE
dnl These are defined in files in m4/
@ -193,20 +220,20 @@ tinc_READLINE
tinc_ZLIB
tinc_LZO
if test "$with_libgcrypt" = yes; then
if test -n "$with_libgcrypt"; then
gcrypt=true
AM_PATH_LIBGCRYPT([1.4.0], [], [])
tinc_LIBGCRYPT
else
openssl=true
tinc_OPENSSL
fi
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
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"],
[ AC_DEFINE(ENABLE_JUMBOGRAMS, 1, [Support for jumbograms (packets up to 9000 bytes)]) ])
]

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

View file

@ -1,4 +1,4 @@
.Dd 2013-01-15
.Dd 2014-01-16
.Dt TINCCTL 8
.\" Manual page created by:
.\" Scott Lamb
@ -13,14 +13,36 @@
.Op Fl -pidfile Ns = Ns Ar FILENAME
.Op Fl -help
.Op Fl -version
.Ar COMMAND
.Op Ar COMMAND
.Sh DESCRIPTION
This is the control program of tinc, a secure virtual private network (VPN)
project.
.Nm
communicates with
.Xr tincd 8
to alter and inspect the running VPN's state.
can start and stop
.Xr tincd 8 ,
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
.Bl -tag -width indent
.It Fl n, -net Ns = Ns Ar NETNAME
@ -47,7 +69,7 @@ option, the value of this environment variable is used.
.Sh COMMANDS
.Bl -tag -width indent
.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
.Ar name
for this node is given, it will be asked for.
@ -120,9 +142,9 @@ will be made.
Shows the PID of the currently running
.Xr tincd 8 .
.It generate-keys Op bits
Generate both RSA and ECDSA keypairs (see below) and exit.
.It generate-ecdsa-keys
Generate public/private ECDSA keypair and exit.
Generate both RSA and Ed25519 keypairs (see below) and exit.
.It generate-ed25519-keys
Generate public/private Ed25519 keypair and exit.
.It generate-rsa-keys Op bits
Generate public/private RSA keypair and exit.
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,
such as
.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
.Sh EXAMPLES
Examples of some commands:
@ -197,7 +224,7 @@ tinc -n vpn pcap | tcpdump -r -
tinc -n vpn top
.Pp
.Ed
Example of configuring tinc using
Examples of changing the configuration using
.Nm :
.Bd -literal -offset indent
tinc -n vpn init foo

View file

@ -1,4 +1,4 @@
.Dd 2013-01-14
.Dd 2014-01-29
.Dt TINC.CONF 5
.\" Manual page created by:
.\" Ivo Timmermans
@ -64,20 +64,20 @@ or by using
.Sh PUBLIC/PRIVATE KEYS
The
.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
.Pa rsa_key.priv
and
.Pa ecdsa_key.priv
.Pa ed25519_key.priv
in the directory
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /
The public keys should be stored in the host configuration file
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Va NAME .
The RSA keys are used for backwards compatibility with tinc version 1.0.
If you are upgrading from version 1.0 to 1.1, you can keep the old configuration files,
but you will need to create ECDSA keys using the following command:
but you will need to create Ed25519 keys using the following command:
.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
.Sh SERVER CONFIGURATION
The server configuration of the daemon is done in the file
@ -114,33 +114,24 @@ If
.Qq any
is selected, then depending on the operating system both IPv4 and IPv6 or just
IPv6 listening sockets will be created.
.It Va AutoConnect Li = Ar count Po 0 Pc Bq experimental
If set to a non-zero value,
.Nm
will try to only have
.Ar count
meta connections to other nodes,
by automatically making or breaking connections to known nodes.
Higher values increase redundancy but also increase meta data overhead.
When using this option, a good value is 3.
.It Va BindToAddress Li = Ar address Op Ar port
If your computer has more than one IPv4 or IPv6 address,
.It Va AutoConnect Li = yes | no Po no Pc Bq experimental
If set to yes,
.Nm tinc
will by default listen on all of them for incoming connections.
Multiple
.Va BindToAddress
variables may be specified,
in which case listening sockets for each specified address are made.
will automatically set up meta connections to other nodes,
without requiring
.Va ConnectTo
variables.
.Pp
If no
.Ar port
is specified, the socket will be bound to the port specified by the
.Va Port
option, or to port 655 if neither is given.
To only bind to a specific port but not to a specific address, use
.Li *
for the
.Ar address .
Note: it is not possible to connect to nodes using zero (system-assigned) ports in this way.
.It Va BindToAddress Li = Ar address Op Ar port
This is the same as
.Va ListenAddress ,
however the address given with the
.Va BindToAddress
option will also be used for outgoing connections. This is useful if your
computer has more than one IPv4 or IPv6 address, and you want
.Nm tinc
to only use a specific one for outgoing packets.
.It Va BindToInterface Li = Ar interface Bq experimental
If your computer has more than one network interface,
.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.
If the IndirectData option is also set, broadcast packets will only be sent to nodes which we have a meta connection to.
.El
.It Va 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
Specifies which other tinc daemon to connect to on startup.
Multiple
@ -178,7 +176,9 @@ The names should be known to this tinc daemon
line).
.Pp
If you don't specify a host with
.Va ConnectTo ,
.Va ConnectTo
and don't enable
.Va AutoConnect ,
.Nm tinc
won't try to connect to other daemons at all,
and will instead just listen for incoming connections.
@ -202,6 +202,13 @@ instead of
.Va Device .
The info pages of the tinc package contain more information
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
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.
@ -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.
When combined with the IndirectData option,
packets for nodes for which we do not have a meta connection with are also dropped.
.It Va ECDSAPrivateKeyFile Li = Ar filename Po Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /ecdsa_key.priv Pc
The file in which the private ECDSA key of this tinc daemon resides.
.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 Ed25519 key of this tinc daemon resides.
This is only used if
.Va ExperimentalProtocol
is enabled.
.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.
Ephemeral ECDH will be used for key exchanges,
and ECDSA will be used instead of RSA for authentication.
When enabled, an ECDSA key must have been generated before with
.Nm tinc generate-ecdsa-keys .
and Ed25519 will be used instead of RSA for authentication.
When enabled, an Ed25519 key must have been generated before with
.Nm tinc generate-ed25519-keys .
.It Va Forwarding Li = off | internal | kernel Po internal Pc Bq experimental
This option selects the way indirect packets are forwarded.
.Bl -tag -width indent
@ -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.
It is common practice to change keys at regular intervals to make it even harder for crackers,
even though it is thought to be nearly impossible to crack a single key.
.It Va LocalDiscovery Li = yes | no Pq no
.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,
.Nm tinc
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,
which normally would prevent the peers from learning each other's LAN address.
.Pp
Currently, local discovery is implemented by sending broadcast packets to the LAN during path MTU discovery.
This feature may not work in all possible situations.
.It Va LocalDiscoveryAddress Li = Ar address
If this variable is specified, local discovery packets are sent to the given
.Ar address .
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.
.It Va MACExpire Li = Ar seconds Pq 600
This option controls the amount of time MAC addresses are kept before they are removed.
This only has effect when
@ -367,7 +397,8 @@ while no routing table is managed.
.It Va Name Li = Ar name Bq required
This is the name which identifies this tinc daemon.
It must be unique for the virtual private network this daemon will connect to.
The Name may only consist of alphanumeric and underscore characters (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
.Va Name
starts with a
@ -446,7 +477,8 @@ traffic.
When this option is enabled tinc will only use Subnet statements which are
present in the host config files in the local
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/
directory.
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
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
@ -507,8 +539,8 @@ will turn off packet authentication.
This option has no effect for connections between nodes using
.Va ExperimentalProtocol .
.It Va IndirectData Li = yes | no Pq no
When set to yes, other nodes which do not already have a meta connection to you
will not try to establish direct communication with you.
When set to yes, only nodes which already have a meta connection to you
will try to establish direct communication with you.
It is best to leave this option out or set it to no.
.It Va MACLength Li = Ar length Pq 4
The length of the message authentication code used to authenticate UDP packets.
@ -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
.Va Address
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
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.
@ -575,6 +615,12 @@ Setting this options also implicitly sets IndirectData.
.Pp
Since version 1.0.10, tinc will automatically detect whether communication via
UDP is possible or not.
.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
.Sh SCRIPTS
Apart from reading the server and host configuration files,
@ -586,12 +632,16 @@ or
.Bl -tag -width indent
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up
This is the most important script.
If it is present it will be executed right after the tinc daemon has been started and has connected to the virtual network device.
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,
but can also be used to start other things.
Under Windows you can use the Network Connections control panel instead of creating this script.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-down
This script is started right before the tinc daemon quits.
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
This script is started when the tinc daemon with name
.Ar HOST
@ -668,6 +718,8 @@ The top directory for configuration files.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf
The default name of the server configuration file for net
.Ar NETNAME .
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /conf.d/
Optional directory from which any .conf file will be loaded
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/
Host configuration files are kept in this directory.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up

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
START-INFO-DIR-ENTRY
* tinc: (tinc). The tinc Manual.
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.
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>.
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,
zlib and lzo libraries installed on your system. If you try to
configure tinc without having them installed, configure will give you an
error message, and stop.
zlib, lzo, curses and readline libraries installed on your system. If
you try to configure tinc without having them installed, configure will
give you an error message, and stop.
* 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
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
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
created.
AutoConnect = <count> (0) [experimental]
If set to a non-zero value, tinc will try to only have count meta
connections to other nodes, by automatically making or breaking
connections to known nodes. Higher values increase redundancy but
also increase meta data overhead. When using this option, a good
value is 3.
AutoConnect = <yes|no> (no) [experimental]
If set to yes, tinc will automatically set up meta connections to
other nodes, without requiring CONNECTTO variables.
BindToAddress = <ADDRESS> [<PORT>]
If your computer has more than one IPv4 or IPv6 address, tinc will
by default listen on all of them for incoming connections.
Multiple BindToAddress variables may be specified, in which case
listening sockets for each specified address are made.
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.
This is the same as ListenAddress, however the address given with
the BindToAddress option will also be used for outgoing
connections. This is useful if your computer has more than one
IPv4 or IPv6 address, and you want tinc to only use a specific one
for outgoing packets.
BindToInterface = <INTERFACE> [experimental]
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
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>
Specifies which other tinc daemon to connect to on startup.
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
host configuration file for the name on the ConnectTo line).
If you don't specify a host with ConnectTo, tinc won't try to
connect to other daemons at all, and will instead just listen for
incoming connections.
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, and
will instead just listen for incoming connections.
DecrementTTL = <yes | no> (no) [experimental]
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
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)
The type of the virtual network device. Tinc will normally
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
meta connection with are also dropped.
ECDSAPrivateKeyFile = <PATH> ('/etc/tinc/NETNAME/ecdsa_key.priv')
The file in which the private ECDSA key of this tinc daemon
Ed25519PrivateKeyFile = <PATH> ('/etc/tinc/NETNAME/ed25519_key.priv')
The file in which the private Ed25519 key of this tinc daemon
resides. This is only used if ExperimentalProtocol is enabled.
ExperimentalProtocol = <yes|no> (yes)
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, and ECDSA will be used instead of RSA for
authentication. When enabled, an ECDSA key must have been
generated before with 'tinc generate-ecdsa-keys'.
used for key exchanges, and Ed25519 will be used instead of RSA for
authentication. When enabled, an Ed25519 key must have been
generated before with 'tinc generate-ed25519-keys'.
Forwarding = <off|internal|kernel> (internal) [experimental]
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
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)
When enabled, tinc will try to detect peers that are on the same
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
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
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
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
USERNAME and PASSWORD are given, basic username/password
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
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
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]
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.
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
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)
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
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
@ -1353,10 +1390,10 @@ contents:
Name = NAME
It will also create private RSA and ECDSA keys, which will be stored in
the files 'rsa_key.priv' and 'ecdsa_key.priv'. It will also create a
host configuration file 'hosts/NAME', which will contain the
corresponding public RSA and ECDSA keys.
It will also create private RSA and Ed25519 keys, which will be stored
in the files 'rsa_key.priv' and 'ed25519_key.priv'. It will also create
a host configuration file 'hosts/NAME', which will contain the
corresponding public RSA and Ed25519 keys.
Finally, on UNIX operating systems, it will create an executable script
'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
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
bottom:
@ -1657,9 +1694,9 @@ Key files
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
private ECDSA key is stored in '/etc/tinc/company/ecdsa_key.priv', and
the public RSA and ECDSA keys are put into the host configuration file
in the '/etc/tinc/company/hosts/' directory.
private Ed25519 key is stored in '/etc/tinc/company/ed25519_key.priv',
and the public RSA and Ed25519 keys are put into the host configuration
file in the '/etc/tinc/company/hosts/' directory.
Starting
........
@ -1997,11 +2034,17 @@ File: tinc.info, Node: Controlling tinc, Next: Technical information, Prev: R
6 Controlling tinc
******************
You can control and inspect a running tincd through the tinc command. A
quick example:
You can start, stop, control and inspect a running tincd through the
tinc command. A quick example:
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:
* tinc runtime options::
@ -2052,8 +2095,8 @@ File: tinc.info, Node: tinc commands, Next: tinc examples, Prev: tinc environ
=================
'init [NAME]'
Create initial configuration files and RSA and ECDSA keypairs with
default length. If no NAME for this node is given, it will be
Create initial configuration files and RSA and Ed25519 keypairs
with default length. If no NAME for this node is given, it will be
asked for.
'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'.
'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
configuration directory (you can use the -c or -n option).
'generate-ecdsa-keys'
Generate public/private ECDSA keypair and exit.
'generate-ed25519-keys'
Generate public/private Ed25519 keypair and exit.
'generate-rsa-keys [BITS]'
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
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
@ -2207,7 +2254,7 @@ Examples of some commands:
tinc -n vpn pcap | tcpdump -r -
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 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
encrypt messages sent to the responder.
When using 521 bits EC keys, the AES-256-CTR cipher and HMAC-SHA-256
digest algorithm, the sizes are as follows:
When using 256 bits Ed25519 keys, the AES-256-CTR cipher and
HMAC-SHA-256 digest algorithm, the sizes are as follows:
ECDH_SIZE: 67 (= ceil(521/8) + 1)
ECDSA_SIZE: 141 (= 2 * ceil(521/8) + 9)
ECDH_SIZE: 32 (= 256/8)
ECDSA_SIZE: 64 (= 2 * 256/8)
CIPHER_KEYSIZE: 48 (= 256/8 + 128/8)
DIGEST_KEYSIZE: 32 (= 256/8)
@ -3019,6 +3066,7 @@ Concept Index
* ACK: Legacy authentication protocol.
(line 6)
* add: tinc commands. (line 22)
* Address: Host configuration variables.
(line 6)
* AddressFamily: Main configuration variables.
@ -3031,83 +3079,107 @@ Concept Index
* binary package: Building and installing tinc.
(line 9)
* BindToAddress: Main configuration variables.
(line 19)
(line 16)
* BindToInterface: Main configuration variables.
(line 30)
(line 23)
* Broadcast: Main configuration variables.
(line 40)
(line 33)
* BroadcastSubnet: Main configuration variables.
(line 53)
* Cabal: Security. (line 6)
* CHALLENGE: Legacy authentication protocol.
(line 6)
* CHAL_REPLY: Legacy authentication protocol.
(line 6)
* CIDR notation: Host configuration variables.
(line 94)
(line 96)
* Cipher: Host configuration variables.
(line 12)
(line 14)
* ClampMSS: Host configuration variables.
(line 20)
(line 22)
* client: How connections work.
(line 18)
* command line: Runtime options. (line 9)
* command line interface: Controlling tinc. (line 6)
* Compression: Host configuration variables.
(line 26)
(line 28)
* connection: The connection. (line 6)
* ConnectTo: Main configuration variables.
(line 60)
(line 65)
* daemon: Running tinc. (line 11)
* data-protocol: The meta-connection. (line 18)
* debug: tinc commands. (line 121)
* debug level: Runtime options. (line 17)
* debug levels: Debug levels. (line 6)
* DecrementTTL: Main configuration variables.
(line 71)
(line 76)
* del: tinc commands. (line 26)
* DEL_EDGE: The meta-protocol. (line 46)
* DEL_SUBNET: The meta-protocol. (line 46)
* Device: Main configuration variables.
(line 80)
(line 85)
* DEVICE: Scripts. (line 60)
* device files: Device files. (line 6)
* DeviceStandby: Main configuration variables.
(line 92)
* DeviceType: Main configuration variables.
(line 87)
(line 99)
* Digest: Host configuration variables.
(line 31)
(line 33)
* DirectOnly: Main configuration variables.
(line 152)
(line 164)
* disconnect: tinc commands. (line 136)
* dummy: Main configuration variables.
(line 94)
* ECDSAPrivateKeyFile: Main configuration variables.
(line 159)
(line 106)
* dump: tinc commands. (line 94)
* Ed25519PrivateKeyFile: Main configuration variables.
(line 171)
* edit: tinc commands. (line 31)
* encapsulating: The UDP tunnel. (line 30)
* encryption: Encryption of network packets.
(line 6)
* environment variables: Scripts. (line 48)
* example: Example configuration.
(line 6)
* exchange: tinc commands. (line 47)
* exchange-all: tinc commands. (line 50)
* exec: Main configuration variables.
(line 328)
(line 352)
* ExperimentalProtocol: Main configuration variables.
(line 163)
(line 175)
* export: tinc commands. (line 35)
* export-all: tinc commands. (line 39)
* Forwarding: Main configuration variables.
(line 170)
(line 182)
* 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.
(line 190)
(line 202)
* http: Main configuration variables.
(line 325)
(line 349)
* hub: Main configuration variables.
(line 246)
(line 270)
* ID: Legacy authentication protocol.
(line 6)
* import: tinc commands. (line 42)
* IndirectData: Host configuration variables.
(line 38)
(line 40)
* info: tinc commands. (line 114)
* init: tinc commands. (line 6)
* Interface: Main configuration variables.
(line 201)
(line 213)
* INTERFACE: Scripts. (line 63)
* INVITATION_FILE: Scripts. (line 86)
* INVITATION_URL: Scripts. (line 90)
* invite: tinc commands. (line 53)
* IRC: Contact information. (line 9)
* join: tinc commands. (line 58)
* KeyExpire: Main configuration variables.
(line 251)
(line 275)
* KEY_CHANGED: The meta-protocol. (line 63)
* legacy authentication protocol: Legacy authentication protocol.
(line 6)
@ -3115,27 +3187,30 @@ Concept Index
* libraries: Libraries. (line 6)
* libreadline: libreadline. (line 6)
* license: OpenSSL. (line 35)
* ListenAddress: Main configuration variables.
(line 221)
* LocalDiscovery: Main configuration variables.
(line 209)
(line 233)
* LocalDiscoveryAddress: Main configuration variables.
(line 220)
(line 244)
* log: tinc commands. (line 124)
* lzo: lzo. (line 6)
* MACExpire: Main configuration variables.
(line 257)
(line 281)
* MACLength: Host configuration variables.
(line 43)
(line 45)
* MaxConnectionBurst: Main configuration variables.
(line 262)
(line 286)
* meta-protocol: The meta-connection. (line 18)
* META_KEY: Legacy authentication protocol.
(line 6)
* Mode: Main configuration variables.
(line 224)
(line 248)
* multicast: Main configuration variables.
(line 106)
(line 118)
* multiple networks: Multiple networks. (line 6)
* Name: Main configuration variables.
(line 268)
(line 292)
* NAME: Scripts. (line 57)
* netmask: Network interfaces. (line 39)
* netname: Multiple networks. (line 6)
@ -3144,101 +3219,114 @@ Concept Index
(line 6)
* Network Administrators Guide: Configuration introduction.
(line 15)
* network [NETNAME]: tinc commands. (line 150)
* NODE: Scripts. (line 67)
* OpenSSL: OpenSSL. (line 6)
* options: Runtime options. (line 9)
* pcap: tinc commands. (line 144)
* PEM format: Host configuration variables.
(line 70)
(line 72)
* pid: tinc commands. (line 77)
* PING: The meta-protocol. (line 88)
* PingInterval: Main configuration variables.
(line 279)
(line 303)
* PingTimeout: Main configuration variables.
(line 283)
(line 307)
* platforms: Supported platforms. (line 6)
* PMTU: Host configuration variables.
(line 50)
(line 52)
* PMTUDiscovery: Host configuration variables.
(line 53)
(line 55)
* PONG: The meta-protocol. (line 88)
* Port: Host configuration variables.
(line 58)
(line 60)
* port numbers: Other files. (line 17)
* PriorityInheritance: Main configuration variables.
(line 289)
(line 313)
* private: Virtual Private Networks.
(line 10)
* PrivateKey: Main configuration variables.
(line 294)
(line 318)
* PrivateKeyFile: Main configuration variables.
(line 300)
(line 324)
* ProcessPriority: Main configuration variables.
(line 305)
(line 329)
* Proxy: Main configuration variables.
(line 310)
(line 334)
* PublicKey: Host configuration variables.
(line 62)
(line 64)
* PublicKeyFile: Host configuration variables.
(line 65)
(line 67)
* purge: tinc commands. (line 118)
* raw_socket: Main configuration variables.
(line 99)
(line 111)
* release: Supported platforms. (line 14)
* reload: tinc commands. (line 72)
* REMOTEADDRESS: Scripts. (line 72)
* REMOTEPORT: Scripts. (line 75)
* ReplayWindow: Main configuration variables.
(line 333)
(line 357)
* requirements: Libraries. (line 6)
* REQ_KEY: The meta-protocol. (line 63)
* restart: tinc commands. (line 69)
* retry: tinc commands. (line 129)
* router: Main configuration variables.
(line 227)
(line 251)
* runtime options: Runtime options. (line 9)
* scalability: tinc. (line 19)
* scripts: Scripts. (line 6)
* server: How connections work.
(line 18)
* set: tinc commands. (line 16)
* shell: Controlling tinc. (line 11)
* signals: Signals. (line 6)
* socks4: Main configuration variables.
(line 314)
(line 338)
* socks5: Main configuration variables.
(line 319)
(line 343)
* SPTPS: Simple Peer-to-Peer Security.
(line 6)
* start: tinc commands. (line 63)
* stop: tinc commands. (line 66)
* StrictSubnets: Main configuration variables.
(line 344)
(line 368)
* Subnet: Host configuration variables.
(line 77)
(line 79)
* SUBNET: Scripts. (line 79)
* SVPN: Security. (line 11)
* switch: Main configuration variables.
(line 235)
(line 259)
* TCP: The meta-connection. (line 10)
* TCPonly: Host configuration variables.
(line 106)
(line 108)
* tinc: Introduction. (line 6)
* TINC: Security. (line 6)
* tinc-down: Scripts. (line 18)
* tinc-up: Scripts. (line 10)
* tinc-up <1>: Network interfaces. (line 19)
* tincd: tinc. (line 14)
* top: tinc commands. (line 139)
* top <1>: tinc top. (line 6)
* traditional VPNs: tinc. (line 19)
* tunifhead: Main configuration variables.
(line 141)
(line 153)
* TunnelServer: Main configuration variables.
(line 349)
(line 375)
* tunnohead: Main configuration variables.
(line 135)
(line 147)
* UDP: The UDP tunnel. (line 30)
* UDP <1>: Encryption of network packets.
(line 11)
* UDPRcvBuf: Main configuration variables.
(line 356)
(line 382)
* UDPSndBuf: Main configuration variables.
(line 361)
(line 387)
* UML: Main configuration variables.
(line 117)
(line 129)
* Universal tun/tap: Configuration of Linux kernels.
(line 6)
* VDE: Main configuration variables.
(line 122)
(line 134)
* virtual: Virtual Private Networks.
(line 18)
* virtual network device: The UDP tunnel. (line 6)
@ -3246,80 +3334,82 @@ Concept Index
(line 6)
* vpnd: tinc. (line 6)
* website: Contact information. (line 6)
* Weight: Host configuration variables.
(line 115)
* WEIGHT: Scripts. (line 82)
* zlib: zlib. (line 6)

Tag Table:
Node: Top807
Node: Introduction1127
Node: Virtual Private Networks1931
Node: tinc3643
Node: Supported platforms5155
Node: Preparations5851
Node: Configuring the kernel6107
Node: Configuration of Linux kernels6516
Node: Configuration of FreeBSD kernels7365
Node: Configuration of OpenBSD kernels7830
Node: Configuration of NetBSD kernels8438
Node: Configuration of Solaris kernels8840
Node: Configuration of Darwin (MacOS/X) kernels9501
Node: Configuration of Windows10190
Node: Libraries10703
Node: OpenSSL11121
Node: zlib13393
Node: lzo14411
Node: libcurses15401
Node: libreadline16311
Node: Installation17248
Node: Building and installing tinc18257
Node: Darwin (MacOS/X) build environment18913
Node: Cygwin (Windows) build environment19477
Node: MinGW (Windows) build environment20061
Node: System files20579
Node: Device files20844
Node: Other files21257
Node: Configuration21870
Node: Configuration introduction22157
Node: Multiple networks23678
Node: How connections work25046
Node: Configuration files27607
Node: Main configuration variables29135
Node: Host configuration variables45893
Node: Scripts51364
Node: How to configure54765
Node: Network interfaces59241
Node: Example configuration61620
Node: Running tinc66713
Node: Runtime options67300
Node: Signals70160
Node: Debug levels71009
Node: Solving problems71945
Node: Error messages73371
Node: Sending bug reports77688
Node: Controlling tinc78635
Node: tinc runtime options79012
Node: tinc environment variables79699
Node: tinc commands80028
Node: tinc examples85138
Node: tinc top85701
Node: Technical information87286
Node: The connection87521
Node: The UDP tunnel87833
Node: The meta-connection90878
Node: The meta-protocol92336
Node: Security97319
Node: Legacy authentication protocol98656
Node: Simple Peer-to-Peer Security103273
Node: Encryption of network packets108933
Node: Security issues111562
Node: Platform specific information113297
Node: Interface configuration113525
Node: Routes115966
Node: About us117877
Node: Contact information118052
Node: Authors118454
Node: Concept Index118856
Node: Top808
Node: Introduction1128
Node: Virtual Private Networks1932
Node: tinc3644
Node: Supported platforms5156
Node: Preparations5852
Node: Configuring the kernel6108
Node: Configuration of Linux kernels6517
Node: Configuration of FreeBSD kernels7366
Node: Configuration of OpenBSD kernels7831
Node: Configuration of NetBSD kernels8439
Node: Configuration of Solaris kernels8841
Node: Configuration of Darwin (MacOS/X) kernels9502
Node: Configuration of Windows10191
Node: Libraries10704
Node: OpenSSL11140
Node: zlib13412
Node: lzo14430
Node: libcurses15420
Node: libreadline16330
Node: Installation17267
Node: Building and installing tinc18276
Node: Darwin (MacOS/X) build environment18932
Node: Cygwin (Windows) build environment19496
Node: MinGW (Windows) build environment20080
Node: System files20598
Node: Device files20863
Node: Other files21276
Node: Configuration21889
Node: Configuration introduction22176
Node: Multiple networks23697
Node: How connections work25065
Node: Configuration files27626
Node: Main configuration variables29258
Node: Host configuration variables47397
Node: Scripts53256
Node: How to configure56657
Node: Network interfaces61141
Node: Example configuration63520
Node: Running tinc68619
Node: Runtime options69206
Node: Signals72066
Node: Debug levels72915
Node: Solving problems73851
Node: Error messages75277
Node: Sending bug reports79594
Node: Controlling tinc80541
Node: tinc runtime options81287
Node: tinc environment variables81974
Node: tinc commands82303
Node: tinc examples87567
Node: tinc top88129
Node: Technical information89714
Node: The connection89949
Node: The UDP tunnel90261
Node: The meta-connection93306
Node: The meta-protocol94764
Node: Security99747
Node: Legacy authentication protocol101084
Node: Simple Peer-to-Peer Security105701
Node: Encryption of network packets111346
Node: Security issues113975
Node: Platform specific information115710
Node: Interface configuration115938
Node: Routes118379
Node: About us120290
Node: Contact information120465
Node: Authors120867
Node: Concept Index121269

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.
Copyright @copyright{} 1998-2013 Ivo Timmermans,
Copyright @copyright{} 1998-2014 Ivo Timmermans,
Guus Sliepen <guus@@tinc-vpn.org> and
Wessel Dankers <wsl@@tinc-vpn.org>.
@ -43,7 +43,7 @@ permission notice identical to this one.
@vskip 0pt plus 1filll
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
Wessel Dankers <wsl@@tinc-vpn.org>.
@ -335,9 +335,10 @@ as explained in the rest of the documentation.
@cindex requirements
@cindex libraries
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 configure tinc without
having them installed, configure will give you an error message, and stop.
Before you can configure or build tinc, you need to have the OpenSSL, zlib,
lzo, curses and readline libraries installed on your system. If you try to
configure tinc without having them installed, configure will give you an error
message, and stop.
@menu
* 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}/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
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.
@cindex AutoConnect
@item AutoConnect = <count> (0) [experimental]
If set to a non-zero value,
tinc will try to only have count meta connections to other nodes,
by automatically making or breaking connections to known nodes.
Higher values increase redundancy but also increase meta data overhead.
When using this option, a good value is 3.
@item AutoConnect = <yes|no> (no) [experimental]
If set to yes, tinc will automatically set up meta connections to other nodes,
without requiring @var{ConnectTo} variables.
@cindex BindToAddress
@item BindToAddress = <@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.
Multiple BindToAddress variables may be specified,
in which case listening sockets for each specified address are made.
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}.
This is the same as ListenAddress, however the address given with the BindToAddress option
will also be used for outgoing connections.
This is useful if your computer has more than one IPv4 or IPv6 address,
and you want tinc to only use a specific one for outgoing packets.
@cindex BindToInterface
@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.
@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
@item ConnectTo = <@var{name}>
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
(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,
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.
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
@item DeviceType = <@var{type}> (platform dependent)
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,
packets for nodes for which we do not have a meta connection with are also dropped.
@cindex ECDSAPrivateKeyFile
@item ECDSAPrivateKeyFile = <@var{path}> (@file{@value{sysconfdir}/tinc/@var{netname}/ecdsa_key.priv})
The file in which the private ECDSA key of this tinc daemon resides.
@cindex Ed25519PrivateKeyFile
@item Ed25519PrivateKeyFile = <@var{path}> (@file{@value{sysconfdir}/tinc/@var{netname}/ed25519_key.priv})
The file in which the private Ed25519 key of this tinc daemon resides.
This is only used if ExperimentalProtocol is enabled.
@cindex ExperimentalProtocol
@item ExperimentalProtocol = <yes|no> (yes)
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,
and ECDSA will be used instead of RSA for authentication.
When enabled, an ECDSA key must have been generated before with
@samp{tinc generate-ecdsa-keys}.
and Ed25519 will be used instead of RSA for authentication.
When enabled, an Ed25519 key must have been generated before with
@samp{tinc generate-ed25519-keys}.
@cindex Forwarding
@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.
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
@item LocalDiscovery = <yes | no> (no)
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.
@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.
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.
@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.
If a @var{username} and @var{password} are given, basic username/password 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.
@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
present in the host config files in the local
@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
@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,
not the one that is internal to the VPN.
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
@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
firewall, or if UDP packet routing is disabled somehow.
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
@ -1471,9 +1509,9 @@ In the configuration directory, it will create the file @file{tinc.conf} with th
Name = @var{name}
@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}},
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},
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.
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:
@example
@ -1803,8 +1841,8 @@ Address = 4.5.6.7
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 ECDSA key is stored in @file{@value{sysconfdir}/tinc/company/ecdsa_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.
the private Ed25519 key is stored in @file{@value{sysconfdir}/tinc/company/ed25519_key.priv},
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
@ -2146,13 +2184,21 @@ Be sure to include the following information in your bugreport:
@node 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:
@example
tinc -n @var{netname} reload
@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
* tinc runtime options::
* tinc environment variables::
@ -2206,85 +2252,107 @@ the value of this environment variable is used.
@c from the manpage
@table @code
@cindex init
@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.
@cindex get
@item get @var{variable}
Print the current value of configuration variable @var{variable}.
If more than one variable with the same name exists,
the value of each of them will be printed on a separate line.
@cindex set
@item set @var{variable} @var{value}
Set configuration variable @var{variable} to the given @var{value}.
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}.
@cindex add
@item add @var{variable} @var{value}
As above, but without removing any previously existing configuration variables.
@cindex del
@item del @var{variable} [@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.
@cindex edit
@item edit @var{filename}
Start an editor for the given configuration file.
You do not need to specify the full path to the file.
@cindex export
@item export
Export the host configuration file of the local node to standard output.
@cindex export-all
@item export-all
Export all host configuration files to standard output.
@cindex import
@item import [--force]
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.
@cindex exchange
@item exchange [--force]
The same as export followed by import.
@cindex exchange-all
@item exchange-all [--force]
The same as export-all followed by import.
@cindex invite
@item invite @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.
@cindex join
@item join [@var{URL}]
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.
@cindex start
@item start [tincd options]
Start @samp{tincd}, optionally with the given extra options.
@cindex stop
@item stop
Stop @samp{tincd}.
@cindex restart
@item restart [tincd options]
Restart @samp{tincd}, optionally with the given extra options.
@cindex reload
@item reload
Partially rereads configuration files. Connections to hosts whose host
config files are removed are closed. New outgoing connections specified
in @file{tinc.conf} will be made.
@cindex pid
@item pid
Shows the PID of the currently running @samp{tincd}.
@cindex generate-keys
@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
configuration directory (you can use the -c or -n option).
@item generate-ecdsa-keys
Generate public/private ECDSA keypair and exit.
@cindex generate-ed25519-keys
@item generate-ed25519-keys
Generate public/private Ed25519 keypair and exit.
@cindex generate-rsa-keys
@item generate-rsa-keys [@var{bits}]
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
will not delete the old keys; you have to remove them manually.
@cindex dump
@item dump [reachable] nodes
Dump a list of all known nodes in the VPN.
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
Dump a list of all meta connections with ourself.
@cindex graph
@item dump graph | digraph
Dump a graph of the VPN in dotty format.
Nodes are colored according to their reachability:
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.
@cindex info
@item info @var{node} | @var{subnet} | @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.
@cindex purge
@item purge
Purges all information remembered about unreachable nodes.
@cindex debug
@item debug @var{level}
Sets debug level to @var{level}.
@cindex log
@item log [@var{level}]
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.
@cindex retry
@item retry
Forces tinc to try to connect to all uplinks immediately.
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,
it defaults to the maximum time of 15 minutes.
@cindex disconnect
@item disconnect @var{node}
Closes the meta connection with the given @var{node}.
@cindex top
@item top
If tinc is compiled with libcurses support, this will display live traffic statistics for all the known nodes,
similar to the UNIX top command.
See below for more information.
@cindex pcap
@item pcap
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,
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
@c ==================================================================
@ -2352,7 +2434,7 @@ tinc -n vpn pcap | tcpdump -r -
tinc -n vpn top
@end example
Example of configuring tinc using the tinc command:
Examples of changing the configuration using tinc:
@example
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
@section tinc top
@cindex top
The top command connects to a running tinc daemon and repeatedly queries its per-node traffic counters.
It displays a list of all the known nodes in the left-most column,
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
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:
@example
ECDH_SIZE: 67 (= ceil(521/8) + 1)
ECDSA_SIZE: 141 (= 2 * ceil(521/8) + 9)
ECDH_SIZE: 32 (= 256/8)
ECDSA_SIZE: 64 (= 2 * 256/8)
CIPHER_KEYSIZE: 48 (= 256/8 + 128/8)
DIGEST_KEYSIZE: 32 (= 256/8)
@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@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@ -83,9 +83,12 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(dist_bin_SCRIPTS)
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \
$(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.ac
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_check_link_flag.m4 \
$(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) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
@ -170,9 +173,6 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LN_S = @LN_S@
@ -188,7 +188,6 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
READLINE_LIBS = @READLINE_LIBS@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@

View file

@ -1,7 +1,8 @@
#!/usr/bin/python
#!/usr/bin/env python
# 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
# 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 ListCtrlAutoWidthMixin
if platform.system == 'Windows':
if platform.system() == 'Windows':
import _winreg
# Classes to interface with a running tinc daemon
@ -77,8 +78,8 @@ class Edge:
self.to = args[1]
self.address = args[2]
self.port = args[4]
self.options = int(args[5], 16)
self.weight = int(args[6])
self.options = int(args[-2], 16)
self.weight = int(args[-1])
class Subnet:
def parse(self, args):
@ -130,7 +131,11 @@ class VPN:
else:
# otherwise connect via TCP
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])))
self.sf = s.makefile()
@ -187,6 +192,8 @@ class VPN:
subnet.parse(resp[2:])
subnet.visited = True
self.subnets[(resp[2], resp[3])] = subnet
if subnet.owner == "(broadcast)":
continue
self.nodes[subnet.owner].subnets[resp[2]] = subnet
elif resp[1] == '6':
if len(resp) < 9:
@ -233,10 +240,16 @@ class VPN:
return int(resp[2])
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:
reg = _winreg.ConnectRegistry(None, HKEY_LOCAL_MACHINE)
key = _winreg.OpenKey(reg, "SOFTWARE\\tinc")
reg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
try:
key = _winreg.OpenKey(reg, "SOFTWARE\\tinc", 0, sam)
except WindowsError:
key = _winreg.OpenKey(reg, "SOFTWARE\\Wow6432Node\\tinc", 0, sam)
VPN.confdir = _winreg.QueryValue(key, None)
except WindowsError:
pass
@ -252,7 +265,7 @@ class VPN:
if pidfile != None:
self.pidfile = pidfile
else:
if platform.system == 'Windows':
if platform.system() == 'Windows':
self.pidfile = os.path.join(self.confbase, 'pid')
else:
if netname:
@ -524,7 +537,7 @@ class SubnetsPage(wx.Panel):
self.list.InsertStringItem(i, subnet.address + '/' + subnet.prefixlen)
else:
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.itemDataMap[i] = (subnet.address + '/' + subnet.prefixlen, subnet.weight, subnet.owner)
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@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@ -81,9 +81,12 @@ subdir = m4
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am README
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \
$(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.ac
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_check_link_flag.m4 \
$(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) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
@ -139,9 +142,6 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LN_S = @LN_S@
@ -157,7 +157,6 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
READLINE_LIBS = @READLINE_LIBS@
SET_MAKE = @SET_MAKE@
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_CHECK_LIB(curses, initscr,
AC_CHECK_LIB(ncurses, initscr,
[CURSES_LIBS="-lncurses"],
[AC_CHECK_LIB(curses, initscr,
[CURSES_LIBS="-lcurses"],
[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"]
)
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]
)
@ -45,11 +45,11 @@ AC_DEFUN([tinc_OPENSSL],
[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_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],
[#include <openssl/evp.h>]
)

View file

@ -1,7 +1,7 @@
#! /bin/sh
# 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.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
@ -160,7 +160,7 @@ give_advice ()
;;
autom4te*)
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'
;;
bison*|yacc*)

View file

@ -1,9 +1,36 @@
## 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 =
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 \
@ -63,7 +90,10 @@ tincd_SOURCES = \
system.h \
tincd.c \
utils.c utils.h \
xalloc.h
xalloc.h \
version.c version.h \
$(ed25519_SOURCES) \
$(chacha_poly1305_SOURCES)
tinc_SOURCES = \
dropin.c dropin.h \
@ -79,13 +109,31 @@ tinc_SOURCES = \
subnet_parse.c subnet.h \
tincctl.c tincctl.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 = \
logger.c logger.h \
sptps.c sptps.h \
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
@ -125,26 +173,35 @@ tincd_SOURCES += \
openssl/cipher.c \
openssl/crypto.c \
openssl/digest.c openssl/digest.h \
openssl/ecdh.c \
openssl/ecdsa.c \
ed25519/ecdh.c \
ed25519/ecdsa.c \
openssl/prf.c \
openssl/rsa.c
tinc_SOURCES += \
openssl/cipher.c \
openssl/crypto.c \
openssl/digest.c openssl/digest.h \
openssl/ecdh.c \
openssl/ecdsa.c \
openssl/ecdsagen.c \
ed25519/ecdh.c \
ed25519/ecdsa.c \
ed25519/ecdsagen.c \
openssl/prf.c \
openssl/rsa.c \
openssl/rsagen.c
sptps_test_SOURCES += \
openssl/cipher.c \
openssl/crypto.c \
openssl/digest.c openssl/digest.h \
openssl/ecdh.c \
openssl/ecdsa.c \
ed25519/ecdh.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
endif
@ -177,8 +234,9 @@ sptps_test_SOURCES += \
endif
tinc_LDADD = $(READLINE_LIBS) $(CURSES_LIBS)
sptps_speed_LDADD = -lrt
LIBS = @LIBS@ @LIBGCRYPT_LIBS@
LIBS = @LIBS@
if TUNEMU
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@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@ -78,44 +78,57 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
sbin_PROGRAMS = tincd$(EXEEXT) tinc$(EXEEXT) sptps_test$(EXEEXT)
@LINUX_TRUE@am__append_1 = linux/device.c
@BSD_TRUE@am__append_2 = bsd/device.c
@BSD_TRUE@@TUNEMU_TRUE@am__append_3 = bsd/tunemu.c bsd/tunemu.h
@SOLARIS_TRUE@am__append_4 = solaris/device.c
@MINGW_TRUE@am__append_5 = mingw/device.c mingw/common.h
@CYGWIN_TRUE@am__append_6 = cygwin/device.c
@UML_TRUE@am__append_7 = uml_device.c
@VDE_TRUE@am__append_8 = vde_device.c
@OPENSSL_TRUE@am__append_9 = \
@OPENSSL_TRUE@ openssl/cipher.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
sbin_PROGRAMS = tincd$(EXEEXT) tinc$(EXEEXT) sptps_test$(EXEEXT) \
sptps_keypair$(EXEEXT) $(am__EXEEXT_1)
@LINUX_TRUE@am__append_1 = sptps_speed
@LINUX_TRUE@am__append_2 = linux/device.c
@BSD_TRUE@am__append_3 = bsd/device.c
@BSD_TRUE@@TUNEMU_TRUE@am__append_4 = bsd/tunemu.c bsd/tunemu.h
@SOLARIS_TRUE@am__append_5 = solaris/device.c
@MINGW_TRUE@am__append_6 = mingw/device.c mingw/common.h
@CYGWIN_TRUE@am__append_7 = cygwin/device.c
@UML_TRUE@am__append_8 = uml_device.c
@VDE_TRUE@am__append_9 = vde_device.c
@OPENSSL_TRUE@am__append_10 = \
@OPENSSL_TRUE@ openssl/cipher.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/ecdsagen.c \
@OPENSSL_TRUE@ ed25519/ecdh.c \
@OPENSSL_TRUE@ ed25519/ecdsa.c \
@OPENSSL_TRUE@ openssl/prf.c \
@OPENSSL_TRUE@ openssl/rsa.c \
@OPENSSL_TRUE@ openssl/rsagen.c
@OPENSSL_TRUE@ openssl/rsa.c
@OPENSSL_TRUE@am__append_11 = \
@OPENSSL_TRUE@ openssl/cipher.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@ ed25519/ecdh.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
@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/crypto.c \
@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/rsa.c
@GCRYPT_TRUE@am__append_13 = \
@GCRYPT_TRUE@am__append_16 = \
@GCRYPT_TRUE@ gcrypt/cipher.c \
@GCRYPT_TRUE@ gcrypt/crypto.c \
@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/rsagen.c
@GCRYPT_TRUE@am__append_14 = \
@GCRYPT_TRUE@am__append_17 = \
@GCRYPT_TRUE@ gcrypt/cipher.c \
@GCRYPT_TRUE@ gcrypt/crypto.c \
@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/prf.c
@TUNEMU_TRUE@am__append_15 = -lpcap
@TUNEMU_TRUE@am__append_18 = -lpcap
subdir = src
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/depcomp
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \
$(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.ac
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_check_link_flag.m4 \
$(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) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
@LINUX_TRUE@am__EXEEXT_1 = sptps_speed$(EXEEXT)
am__installdirs = "$(DESTDIR)$(sbindir)"
PROGRAMS = $(sbin_PROGRAMS)
am__sptps_test_SOURCES_DIST = logger.c logger.h sptps.c sptps.h \
sptps_test.c utils.c utils.h openssl/cipher.c openssl/crypto.c \
openssl/digest.c openssl/digest.h openssl/ecdh.c \
openssl/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
am__sptps_keypair_SOURCES_DIST = sptps_keypair.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 openssl/crypto.c ed25519/ecdsagen.c
am__dirstamp = $(am__leading_dot)dirstamp
@OPENSSL_TRUE@am__objects_1 = openssl/cipher.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/crypto.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/digest.$(OBJEXT) openssl/ecdh.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/ecdsa.$(OBJEXT) openssl/prf.$(OBJEXT)
@GCRYPT_TRUE@am__objects_2 = gcrypt/cipher.$(OBJEXT) \
am__objects_1 = ed25519/add_scalar.$(OBJEXT) ed25519/fe.$(OBJEXT) \
ed25519/ge.$(OBJEXT) ed25519/key_exchange.$(OBJEXT) \
ed25519/keypair.$(OBJEXT) ed25519/sc.$(OBJEXT) \
ed25519/sha512.$(OBJEXT) ed25519/sign.$(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/ecdh.$(OBJEXT) gcrypt/ecdsa.$(OBJEXT) \
@GCRYPT_TRUE@ gcrypt/prf.$(OBJEXT)
am_sptps_test_OBJECTS = logger.$(OBJEXT) sptps.$(OBJEXT) \
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_LDADD = $(LDADD)
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 \
names.h netutl.c netutl.h script.c script.h sptps.c sptps.h \
subnet_parse.c subnet.h tincctl.c tincctl.h top.c top.h \
utils.c utils.h openssl/cipher.c openssl/crypto.c \
openssl/digest.c openssl/digest.h openssl/ecdh.c \
openssl/ecdsa.c openssl/ecdsagen.c openssl/prf.c openssl/rsa.c \
utils.c utils.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 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 \
gcrypt/digest.c gcrypt/digest.h gcrypt/ecdh.c gcrypt/ecdsa.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/digest.$(OBJEXT) openssl/ecdh.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/ecdsa.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/ecdsagen.$(OBJEXT) openssl/prf.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/digest.$(OBJEXT) ed25519/ecdh.$(OBJEXT) \
@OPENSSL_TRUE@ ed25519/ecdsa.$(OBJEXT) \
@OPENSSL_TRUE@ ed25519/ecdsagen.$(OBJEXT) openssl/prf.$(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/ecdh.$(OBJEXT) gcrypt/ecdsa.$(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) \
names.$(OBJEXT) netutl.$(OBJEXT) script.$(OBJEXT) \
sptps.$(OBJEXT) subnet_parse.$(OBJEXT) tincctl.$(OBJEXT) \
top.$(OBJEXT) utils.$(OBJEXT) $(am__objects_3) \
$(am__objects_4)
top.$(OBJEXT) utils.$(OBJEXT) version.$(OBJEXT) \
$(am__objects_1) $(am__objects_3) $(am__objects_7) \
$(am__objects_8)
tinc_OBJECTS = $(am_tinc_OBJECTS)
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 \
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 \
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 \
mingw/common.h cygwin/device.c uml_device.c vde_device.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 \
gcrypt/digest.h gcrypt/ecdh.c gcrypt/ecdsa.c gcrypt/prf.c \
gcrypt/rsa.c
@LINUX_TRUE@am__objects_5 = linux/device.$(OBJEXT)
@BSD_TRUE@am__objects_6 = bsd/device.$(OBJEXT)
@BSD_TRUE@@TUNEMU_TRUE@am__objects_7 = bsd/tunemu.$(OBJEXT)
@SOLARIS_TRUE@am__objects_8 = solaris/device.$(OBJEXT)
@MINGW_TRUE@am__objects_9 = mingw/device.$(OBJEXT)
@CYGWIN_TRUE@am__objects_10 = cygwin/device.$(OBJEXT)
@UML_TRUE@am__objects_11 = uml_device.$(OBJEXT)
@VDE_TRUE@am__objects_12 = vde_device.$(OBJEXT)
@OPENSSL_TRUE@am__objects_13 = openssl/cipher.$(OBJEXT) \
@LINUX_TRUE@am__objects_9 = linux/device.$(OBJEXT)
@BSD_TRUE@am__objects_10 = bsd/device.$(OBJEXT)
@BSD_TRUE@@TUNEMU_TRUE@am__objects_11 = bsd/tunemu.$(OBJEXT)
@SOLARIS_TRUE@am__objects_12 = solaris/device.$(OBJEXT)
@MINGW_TRUE@am__objects_13 = mingw/device.$(OBJEXT)
@CYGWIN_TRUE@am__objects_14 = cygwin/device.$(OBJEXT)
@UML_TRUE@am__objects_15 = uml_device.$(OBJEXT)
@VDE_TRUE@am__objects_16 = vde_device.$(OBJEXT)
@OPENSSL_TRUE@am__objects_17 = openssl/cipher.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/crypto.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/digest.$(OBJEXT) openssl/ecdh.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/ecdsa.$(OBJEXT) openssl/prf.$(OBJEXT) \
@OPENSSL_TRUE@ openssl/digest.$(OBJEXT) ed25519/ecdh.$(OBJEXT) \
@OPENSSL_TRUE@ ed25519/ecdsa.$(OBJEXT) openssl/prf.$(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/ecdh.$(OBJEXT) gcrypt/ecdsa.$(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) \
splay_tree.$(OBJEXT) sptps.$(OBJEXT) subnet.$(OBJEXT) \
subnet_parse.$(OBJEXT) tincd.$(OBJEXT) utils.$(OBJEXT) \
$(am__objects_5) $(am__objects_6) $(am__objects_7) \
$(am__objects_8) $(am__objects_9) $(am__objects_10) \
$(am__objects_11) $(am__objects_12) $(am__objects_13) \
$(am__objects_14)
version.$(OBJEXT) $(am__objects_1) $(am__objects_3) \
$(am__objects_9) $(am__objects_10) $(am__objects_11) \
$(am__objects_12) $(am__objects_13) $(am__objects_14) \
$(am__objects_15) $(am__objects_16) $(am__objects_17) \
$(am__objects_18)
tincd_OBJECTS = $(am_tincd_OBJECTS)
tincd_LDADD = $(LDADD)
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_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(sptps_test_SOURCES) $(tinc_SOURCES) $(tincd_SOURCES)
DIST_SOURCES = $(am__sptps_test_SOURCES_DIST) $(am__tinc_SOURCES_DIST) \
$(am__tincd_SOURCES_DIST)
SOURCES = $(sptps_keypair_SOURCES) $(sptps_speed_SOURCES) \
$(sptps_test_SOURCES) $(tinc_SOURCES) $(tincd_SOURCES)
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 = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@ -354,11 +440,8 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@ @LIBGCRYPT_LIBS@ $(am__append_15)
LIBS = @LIBS@ $(am__append_18)
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
@ -372,7 +455,6 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
READLINE_LIBS = @READLINE_LIBS@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
@ -429,6 +511,25 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
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 \
connection.h control.c control.h control_common.h crypto.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 \
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 \
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_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 \
info.h invitation.c invitation.h list.c list.h names.c names.h \
netutl.c netutl.h script.c script.h sptps.c sptps.h \
subnet_parse.c subnet.h tincctl.c tincctl.h top.c top.h \
utils.c utils.h $(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 \
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)
sptps_speed_LDADD = -lrt
AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\"
all: all-am
@ -549,24 +659,69 @@ installcheck-sbinPROGRAMS: $(sbin_PROGRAMS)
else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \
done; \
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):
@$(MKDIR_P) openssl
@: > openssl/$(am__dirstamp)
openssl/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) openssl/$(DEPDIR)
@: > openssl/$(DEPDIR)/$(am__dirstamp)
openssl/cipher.$(OBJEXT): openssl/$(am__dirstamp) \
openssl/$(DEPDIR)/$(am__dirstamp)
openssl/crypto.$(OBJEXT): openssl/$(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/$(DEPDIR)/$(am__dirstamp)
openssl/ecdh.$(OBJEXT): openssl/$(am__dirstamp) \
openssl/$(DEPDIR)/$(am__dirstamp)
openssl/ecdsa.$(OBJEXT): openssl/$(am__dirstamp) \
openssl/$(DEPDIR)/$(am__dirstamp)
ed25519/ecdh.$(OBJEXT): ed25519/$(am__dirstamp) \
ed25519/$(DEPDIR)/$(am__dirstamp)
ed25519/ecdsa.$(OBJEXT): ed25519/$(am__dirstamp) \
ed25519/$(DEPDIR)/$(am__dirstamp)
openssl/prf.$(OBJEXT): openssl/$(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):
@$(MKDIR_P) gcrypt
@: > 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)
@rm -f sptps_test$(EXEEXT)
$(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/rsa.$(OBJEXT): openssl/$(am__dirstamp) \
openssl/$(DEPDIR)/$(am__dirstamp)
@ -655,7 +810,9 @@ tincd$(EXEEXT): $(tincd_OBJECTS) $(tincd_DEPENDENCIES) $(EXTRA_tincd_DEPENDENCIE
mostlyclean-compile:
-rm -f *.$(OBJEXT)
-rm -f bsd/*.$(OBJEXT)
-rm -f chacha-poly1305/*.$(OBJEXT)
-rm -f cygwin/*.$(OBJEXT)
-rm -f ed25519/*.$(OBJEXT)
-rm -f gcrypt/*.$(OBJEXT)
-rm -f linux/*.$(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)/splay_tree.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)/subnet.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)/utils.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)/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@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)/crypto.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)/crypto.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)/rsa.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)
-rm -f bsd/$(DEPDIR)/$(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/$(am__dirstamp)
-rm -f ed25519/$(DEPDIR)/$(am__dirstamp)
-rm -f ed25519/$(am__dirstamp)
-rm -f gcrypt/$(DEPDIR)/$(am__dirstamp)
-rm -f gcrypt/$(am__dirstamp)
-rm -f linux/$(DEPDIR)/$(am__dirstamp)
@ -892,7 +1068,7 @@ clean: clean-am
clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-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
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
@ -938,7 +1114,7 @@ install-ps-am:
installcheck-am: installcheck-sbinPROGRAMS
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
maintainer-clean-am: distclean-am maintainer-clean-generic
@ -973,6 +1149,9 @@ 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.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View file

@ -1,7 +1,7 @@
/*
device.c -- Interaction BSD tun/tap device
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>
This program is free software; you can redistribute it and/or modify
@ -35,7 +35,7 @@
#endif
#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"
#else
#define DEFAULT_TAP_DEVICE "/dev/tun0"
@ -54,8 +54,6 @@ int device_fd = -1;
char *device = NULL;
char *iface = NULL;
static char *device_info = NULL;
static uint64_t device_total_in = 0;
static uint64_t device_total_out = 0;
#if defined(ENABLE_TUNEMU)
static device_type_t device_type = DEVICE_TYPE_TUNEMU;
#elif defined(HAVE_OPENBSD) || defined(HAVE_FREEBSD) || defined(HAVE_DRAGONFLY)
@ -65,18 +63,9 @@ static device_type_t device_type = DEVICE_TYPE_TUN;
#endif
static bool setup_device(void) {
get_config_string(lookup_config(config_tree, "Device"), &device);
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(!strcasecmp(type, "tun"))
/* use default */;
@ -95,10 +84,29 @@ static bool setup_device(void) {
return false;
}
} else {
if(strstr(device, "tap") || routing_mode != RMODE_ROUTER)
if((device && strstr(device, "tap")) || routing_mode != RMODE_ROUTER)
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) {
#ifdef ENABLE_TUNEMU
case DEVICE_TYPE_TUNEMU: {
@ -199,9 +207,11 @@ static void close_device(void) {
default:
close(device_fd);
}
device_fd = -1;
free(device);
free(iface);
free(device); device = NULL;
free(iface); iface = NULL;
device_info = NULL;
}
static bool read_packet(vpn_packet_t *packet) {
@ -212,10 +222,10 @@ static bool read_packet(vpn_packet_t *packet) {
#ifdef ENABLE_TUNEMU
case 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
#endif
inlen = read(device_fd, packet->data + 14, MTU - 14);
inlen = read(device_fd, DATA(packet) + 14, MTU - 14);
if(inlen <= 0) {
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;
}
switch(packet->data[14] >> 4) {
switch(DATA(packet)[14] >> 4) {
case 4:
packet->data[12] = 0x08;
packet->data[13] = 0x00;
DATA(packet)[12] = 0x08;
DATA(packet)[13] = 0x00;
break;
case 6:
packet->data[12] = 0x86;
packet->data[13] = 0xDD;
DATA(packet)[12] = 0x86;
DATA(packet)[13] = 0xDD;
break;
default:
logger(DEBUG_TRAFFIC, LOG_ERR,
"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;
}
memset(packet->data, 0, 12);
memset(DATA(packet), 0, 12);
packet->len = inlen + 14;
break;
case DEVICE_TYPE_TUNIFHEAD: {
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) {
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)) {
case AF_INET:
packet->data[12] = 0x08;
packet->data[13] = 0x00;
DATA(packet)[12] = 0x08;
DATA(packet)[13] = 0x00;
break;
case AF_INET6:
packet->data[12] = 0x86;
packet->data[13] = 0xDD;
DATA(packet)[12] = 0x86;
DATA(packet)[13] = 0xDD;
break;
default:
@ -271,13 +281,13 @@ static bool read_packet(vpn_packet_t *packet) {
return false;
}
memset(packet->data, 0, 12);
memset(DATA(packet), 0, 12);
packet->len = inlen + 10;
break;
}
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,
device, strerror(errno));
return false;
@ -290,8 +300,6 @@ static bool read_packet(vpn_packet_t *packet) {
return false;
}
device_total_in += packet->len;
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s",
packet->len, device_info);
@ -304,7 +312,7 @@ static bool write_packet(vpn_packet_t *packet) {
switch(device_type) {
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,
device, strerror(errno));
return false;
@ -313,10 +321,10 @@ static bool write_packet(vpn_packet_t *packet) {
case DEVICE_TYPE_TUNIFHEAD: {
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;
af = (packet->data[12] << 8) + packet->data[13];
af = (DATA(packet)[12] << 8) + DATA(packet)[13];
switch (af) {
case 0x0800:
@ -341,7 +349,7 @@ static bool write_packet(vpn_packet_t *packet) {
}
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,
device, strerror(errno));
return false;
@ -350,7 +358,7 @@ static bool write_packet(vpn_packet_t *packet) {
#ifdef ENABLE_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,
device, strerror(errno));
return false;
@ -362,21 +370,12 @@ static bool write_packet(vpn_packet_t *packet) {
return false;
}
device_total_out += packet->len;
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 = {
.setup = setup_device,
.close = close_device,
.read = read_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 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_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_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 bool cipher_active(const cipher_t *);

View file

@ -2,9 +2,10 @@
conf.c -- configuration code
Copyright (C) 1998 Robert van der Meulen
1998-2005 Ivo Timmermans
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
2010-2011 Julien Muchembled <jm@jmuchemb.eu>
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
it under the terms of the GNU General Public License as published by
@ -376,6 +377,29 @@ bool read_server_config(void) {
errno = 0;
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)
logger(DEBUG_ALWAYS, LOG_ERR, "Failed to read `%s': %s", fname, strerror(errno));

View file

@ -36,7 +36,7 @@
typedef struct connection_status_t {
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 unused_termreq:1; /* the termination of this connection was requested */
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 invitation:1; /* 1 if this is an invitation */
unsigned int invitation_used:1; /* 1 if the invitation has been consumed */
unsigned int unused:19;
unsigned int unused:18;
} connection_status_t;
#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) {
if(strcmp(other->name, name))
continue;
terminate_connection(other, other->status.active);
terminate_connection(other, other->edge);
found = true;
}
@ -178,15 +178,15 @@ bool init_control(void) {
#ifndef HAVE_MINGW
int unix_fd = socket(AF_UNIX, SOCK_STREAM, 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;
}
struct sockaddr_un sun;
sun.sun_family = AF_UNIX;
strncpy(sun.sun_path, unixsocketname, sizeof sun.sun_path);
struct sockaddr_un sa_un;
sa_un.sun_family = AF_UNIX;
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);
return false;
}
@ -194,16 +194,16 @@ bool init_control(void) {
unlink(unixsocketname);
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);
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;
}
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;
}

View file

@ -1,7 +1,7 @@
/*
device.c -- Interaction with Windows tap driver in a Cygwin environment
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
it under the terms of the GNU General Public License as published by
@ -40,9 +40,6 @@ char *device = NULL;
char *iface = 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 int sp[2];
@ -218,18 +215,19 @@ static bool setup_device(void) {
static void close_device(void) {
close(sp[0]);
close(sp[1]);
CloseHandle(device_handle);
CloseHandle(device_handle); device_handle = INVALID_HANDLE_VALUE;
kill(reader_pid, SIGKILL);
free(device);
free(iface);
free(device); device = NULL;
free(iface); iface = NULL;
device_info = NULL;
}
static bool read_packet(vpn_packet_t *packet) {
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,
device, strerror(errno));
return false;
@ -237,8 +235,6 @@ static bool read_packet(vpn_packet_t *packet) {
packet->len = inlen;
device_total_in += packet->len;
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len,
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",
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()));
return false;
}
device_total_out += packet->len;
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 = {
.setup = setup_device,
.close = close_device,
.read = read_packet,
.write = write_packet,
.dump_stats = dump_device_stats,
};

View file

@ -27,17 +27,13 @@ extern int device_fd;
extern char *device;
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 {
bool (*setup)(void);
void (*close)(void);
bool (*read)(struct vpn_packet_t *);
bool (*write)(struct vpn_packet_t *);
void (*dump_stats)(void);
void (*enable)(void); /* optional */
void (*disable)(void); /* optional */
} devops_t;
extern const devops_t os_devops;

View file

@ -25,9 +25,6 @@
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) {
device = "dummy";
iface = "dummy";
@ -43,20 +40,12 @@ static bool read_packet(vpn_packet_t *packet) {
}
static bool write_packet(vpn_packet_t *packet) {
device_total_out += packet->len;
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 = {
.setup = setup_device,
.close = close_device,
.read = read_packet,
.write = write_packet,
.dump_stats = dump_device_stats,
};

View file

@ -20,8 +20,8 @@
#ifndef __TINC_ECDH_H__
#define __TINC_ECDH_H__
#define ECDH_SIZE 67
#define ECDH_SHARED_SIZE 66
#define ECDH_SIZE 32
#define ECDH_SHARED_SIZE 32
#ifndef __TINC_ECDH_INTERNAL__
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 <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/obj_mac.h>
#include "ed25519.h"
#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 "../utils.h"
#include "../xalloc.h"
@ -33,38 +35,37 @@ typedef EC_KEY ecdsa_t;
// Generate ECDSA key
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)) {
fprintf(stderr, "Generating EC key failed: %s", ERR_error_string(ERR_get_error(), NULL));
ecdsa_free(ecdsa);
return false;
}
EC_KEY_set_asn1_flag(ecdsa, OPENSSL_EC_NAMED_CURVE);
EC_KEY_set_conv_form(ecdsa, POINT_CONVERSION_COMPRESSED);
uint8_t seed[32];
randomize(seed, sizeof seed);
ed25519_create_keypair(ecdsa->public, ecdsa->private, seed);
return ecdsa;
}
// 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) {
BIO *out = BIO_new(BIO_s_file());
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;
return write_pem(fp, "ED25519 PUBLIC KEY", ecdsa->public, sizeof ecdsa->public);
}
bool ecdsa_write_pem_private_key(ecdsa_t *ecdsa, FILE *fp) {
BIO *out = BIO_new(BIO_s_file());
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;
return write_pem(fp, "ED25519 PRIVATE KEY", ecdsa->private, sizeof *ecdsa);
}

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(edge_t, e, n->edge_tree) {
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,
e->from->name, e->to->name, address,
e->options, e->weight);
local_address, e->options, e->weight);
free(address);
free(local_address);
}
}

View file

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

View file

@ -23,15 +23,26 @@
#include "event.h"
#include "net.h"
#include "utils.h"
#include "xalloc.h"
struct timeval now;
#ifndef HAVE_MINGW
static fd_set readfds;
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) {
#ifndef HAVE_MINGW
return a->fd - b->fd;
#else
return a->event - b->event;
#endif
}
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;
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->data = data;
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();
}
void io_set(io_t *io, int flags) {
io->flags = flags;
#ifdef HAVE_MINGW
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)
FD_SET(io->fd, &readfds);
else
@ -82,6 +113,15 @@ void io_set(io_t *io, int flags) {
FD_SET(io->fd, &writefds);
else
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) {
@ -89,6 +129,11 @@ void io_del(io_t *io) {
return;
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);
io->cb = NULL;
@ -182,30 +227,37 @@ void signal_del(signal_t *sig) {
}
#endif
bool event_loop(void) {
running = true;
fd_set readable;
fd_set writable;
while(running) {
static struct timeval * get_time_remaining(struct timeval *diff) {
gettimeofday(&now, NULL);
struct timeval diff, *tv = NULL;
struct timeval *tv = NULL;
while(timeout_tree.head) {
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);
if(timercmp(&timeout->tv, &now, <))
timeout_del(timeout);
} else {
tv = &diff;
tv = diff;
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(&writable, &writefds, sizeof writable);
@ -216,16 +268,10 @@ bool event_loop(void) {
fds = last->fd + 1;
}
#ifdef HAVE_MINGW
LeaveCriticalSection(&mutex);
#endif
int n = select(fds, &readable, &writable, NULL, tv);
#ifdef HAVE_MINGW
EnterCriticalSection(&mutex);
#endif
if(n < 0) {
if(sockwouldblock(errno))
if(sockwouldblock(sockerrno))
continue;
else
return false;
@ -241,14 +287,75 @@ bool event_loop(void) {
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;
return true;
if (!event_count) {
Sleep(timeout_ms);
continue;
}
void event_flush_output(void) {
/*
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(FD_ISSET(io->fd, &writefds))
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;
}
void event_exit(void) {

View file

@ -32,6 +32,9 @@ typedef void (*signal_cb_t)(void *data);
typedef struct io_t {
int fd;
int flags;
#ifdef HAVE_MINGW
WSAEVENT event;
#endif
io_cb_t cb;
void *data;
splay_node_t node;
@ -54,6 +57,9 @@ typedef struct signal_t {
extern struct timeval now;
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_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 bool event_loop(void);
extern void event_flush_output(void);
extern void event_exit(void);
#endif

View file

@ -176,9 +176,13 @@ static void sssp_bfs(void) {
&& (e->to->distance != n->distance + 1 || e->weight >= e->to->prevedge->weight))
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.indirect = indirect;
e->to->nexthop = (n->nexthop == myself) ? e->to : n->nexthop;
e->to->prevedge = e;
e->to->via = indirect ? n->via : e->to;
e->to->options = e->options;
@ -200,6 +204,9 @@ static void sssp_bfs(void) {
static void check_reachability(void) {
/* 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) {
if(n->status.visited != n->status.reachable) {
n->status.reachable = !n->status.reachable;
@ -208,9 +215,13 @@ static void check_reachability(void) {
if(n->status.reachable) {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Node %s (%s) became reachable",
n->name, n->hostname);
if (n != myself)
became_reachable_count++;
} else {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Node %s (%s) became unreachable",
n->name, n->hostname);
if (n != myself)
became_unreachable_count++;
}
if(experimental && OPTION_VERSION(n->options) >= 2)
@ -264,15 +275,18 @@ static void check_reachability(void) {
update_node_udp(n, NULL);
memset(&n->status, 0, sizeof n->status);
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;
}
/* 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 */
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_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_or_insert(hash_t *, const void *key, const void *value);

View file

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

View file

@ -24,6 +24,7 @@
#include "subnet.h"
#include "tincctl.h"
#include "info.h"
#include "utils.h"
#include "xalloc.h"
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 node[4096];
char id[4096];
char from[4096];
char to[4096];
char subnet[4096];
@ -67,12 +69,12 @@ static int info_node(int fd, const char *item) {
long int last_state_change;
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)
break;
if(n != 18) {
if(n != 19) {
fprintf(stderr, "Unable to parse node dump from tincd.\n");
return 1;
}
@ -94,6 +96,7 @@ static int info_node(int fd, const char *item) {
}
printf("Node: %s\n", item);
printf("Node ID: %s\n", id);
printf("Address: %s port %s\n", host, port);
char timestr[32] = "never";

View file

@ -1,6 +1,6 @@
/*
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
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:
printf("Please enter your host's external address or hostname");
fprintf(stderr, "Please enter your host's external address or hostname");
if(hostname)
printf(" [%s]", hostname);
printf(": ");
fflush(stdout);
fprintf(stderr, " [%s]", hostname);
fprintf(stderr, ": ");
if(!fgets(line, sizeof line, stdin)) {
fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno));
@ -190,8 +197,10 @@ done:
else
xasprintf(&hostport, "%s:%s", hostname, port);
} else {
hostport = hostname;
hostname = NULL;
if(strchr(hostname, ':'))
xasprintf(&hostport, "[%s]", hostname);
else
hostport = xstrdup(hostname);
}
free(hostname);
@ -241,7 +250,7 @@ int cmd_invite(int argc, char *argv[]) {
}
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;
if(connect_tincd(false)) {
sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);
@ -312,7 +321,7 @@ int cmd_invite(int argc, char *argv[]) {
free(filename);
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.
if(!count)
@ -404,8 +413,12 @@ int cmd_invite(int argc, char *argv[]) {
char buf[1024];
while(fgets(buf, sizeof buf, tc)) {
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);
// Make sure there is a newline character.
if(!strchr(buf, '\n'))
fputc('\n', f);
}
}
fclose(tc);
}
@ -567,7 +580,7 @@ make_names:
if(!access(tinc_conf, F_OK)) {
fprintf(stderr, "Configuration file %s already exists!\n", tinc_conf);
if(!tty || confbasegiven)
if(confbasegiven)
return false;
// Generate a random netname, ask for a better one later.
@ -600,6 +613,7 @@ make_names:
FILE *fh = fopen(filename, "w");
if(!fh) {
fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno));
fclose(f);
return false;
}
@ -709,7 +723,7 @@ make_names:
if(!b64key)
return false;
xasprintf(&filename, "%s" SLASH "ecdsa_key.priv", confbase);
xasprintf(&filename, "%s" SLASH "ed25519_key.priv", confbase);
f = fopenmask(filename, "w", 0600);
if(!ecdsa_write_pem_private_key(key, f)) {
@ -721,7 +735,7 @@ make_names:
fclose(f);
fprintf(fh, "ECDSAPublicKey = %s\n", b64key);
fprintf(fh, "Ed25519PublicKey = %s\n", b64key);
sptps_send_record(&sptps, 1, b64key, strlen(b64key));
free(b64key);
@ -743,7 +757,7 @@ make_names:
check_port(name);
ask_netname:
if(ask_netname) {
if(ask_netname && tty) {
fprintf(stderr, "Enter a new netname: ");
if(!fgets(line, sizeof line, stdin)) {
fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno));
@ -767,11 +781,13 @@ ask_netname:
make_names();
}
fprintf(stderr, "Configuration stored in: %s\n", confbase);
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) {
int result = send(sock, data, len, 0);
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;
}
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) {
case SPTPS_HANDSHAKE:
return sptps_send_record(&sptps, 0, cookie, sizeof cookie);
@ -850,10 +866,8 @@ int cmd_join(int argc, char *argv[]) {
if(argc > 1) {
invitation = argv[1];
} else {
if(tty) {
printf("Enter invitation URL: ");
fflush(stdout);
}
if(tty)
fprintf(stderr, "Enter invitation URL: ");
errno = EPIPE;
if(!fgets(line, sizeof line, stdin)) {
fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno));
@ -893,7 +907,7 @@ int cmd_join(int argc, char *argv[]) {
if(!port || !*port)
port = "655";
if(!b64decode(slash, hash, 18) || !b64decode(slash + 24, cookie, 18))
if(!b64decode(slash, hash, 24) || !b64decode(slash + 24, cookie, 24))
goto invalid;
// Generate a throw-away key for the invitation.

View file

@ -1,7 +1,7 @@
/*
device.c -- Interaction with Linux ethertap and tun/tap device
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
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 *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) {
if(!get_config_string(lookup_config(config_tree, "Device"), &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);
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;
}
static void close_device(void) {
close(device_fd);
device_fd = -1;
free(type);
free(device);
free(iface);
free(type); type = NULL;
free(device); device = NULL;
free(iface); iface = NULL;
device_info = NULL;
}
static bool read_packet(vpn_packet_t *packet) {
@ -126,7 +131,7 @@ static bool read_packet(vpn_packet_t *packet) {
switch(device_type) {
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) {
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;
}
memset(packet->data, 0, 12);
memset(DATA(packet), 0, 12);
packet->len = inlen + 10;
break;
case DEVICE_TYPE_TAP:
inlen = read(device_fd, packet->data, MTU);
inlen = read(device_fd, DATA(packet), MTU);
if(inlen <= 0) {
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();
}
device_in_packets++;
device_in_bytes += packet->len;
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len,
device_info);
@ -167,15 +169,15 @@ static bool write_packet(vpn_packet_t *packet) {
switch(device_type) {
case DEVICE_TYPE_TUN:
packet->data[10] = packet->data[11] = 0;
if(write(device_fd, packet->data + 10, packet->len - 10) < 0) {
DATA(packet)[10] = DATA(packet)[11] = 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,
strerror(errno));
return false;
}
break;
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,
strerror(errno));
return false;
@ -185,22 +187,12 @@ static bool write_packet(vpn_packet_t *packet) {
abort();
}
device_out_packets++;
device_out_bytes += packet->len;
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 = {
.setup = setup_device,
.close = close_device,
.read = read_packet,
.write = write_packet,
.dump_stats = dump_device_stats,
};

View file

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

View file

@ -1,6 +1,6 @@
/*
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
2006 Scott Lamb <slamb@slamb.org>
@ -30,7 +30,7 @@
#include "utils.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;
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) {
for list_each(connection_t, c, connection_list)
if(c != from && c->status.active)
if(c != from && c->edge)
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;
if(!c) {
@ -142,7 +143,7 @@ bool receive_meta(connection_t *c) {
inlen = recv(c->socket, inbuf, sizeof inbuf - c->inbuf.len, 0);
if(inlen <= 0) {
if(!inlen || !errno) {
if(!inlen || !sockerrno) {
logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection closed by %s (%s)",
c->name, c->hostname);
} else if(sockwouldblock(sockerrno))

View file

@ -1,6 +1,6 @@
/*
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
This program is free software; you can redistribute it and/or modify
@ -24,8 +24,8 @@
#include "connection.h"
extern bool send_meta(struct connection_t *, const char *, int);
extern bool send_meta_sptps(void *, uint8_t, const char *, size_t);
extern bool receive_meta_sptps(void *, uint8_t, const char *, uint16_t);
extern bool send_meta_sptps(void *, uint8_t, const void *, size_t);
extern bool receive_meta_sptps(void *, uint8_t, const void *, uint16_t);
extern void broadcast_meta(struct connection_t *, const char *, int);
extern bool receive_meta(struct connection_t *);

View file

@ -1,7 +1,7 @@
/*
device.c -- Interaction with Windows tap driver in a MinGW environment
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
it under the terms of the GNU General Public License as published by
@ -36,53 +36,50 @@
int device_fd = -1;
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 *iface = NULL;
static char *device_info = NULL;
static uint64_t device_total_in = 0;
static uint64_t device_total_out = 0;
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;
DWORD len;
OVERLAPPED overlapped;
vpn_packet_t packet;
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);
DWORD len;
status = ReadFile(device_handle, (void *)device_read_packet.data, MTU, &len, &device_read_overlapped);
if (!status) {
if(GetLastError() == ERROR_IO_PENDING) {
WaitForSingleObject(overlapped.hEvent, INFINITE);
if(!GetOverlappedResult(device_handle, &overlapped, &len, FALSE))
continue;
} else {
if (GetLastError() != ERROR_IO_PENDING)
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno));
return -1;
break;
}
device_read_packet.len = len;
device_read_packet.priority = 0;
route(myself, &device_read_packet);
}
}
EnterCriticalSection(&mutex);
packet.len = len;
packet.priority = 0;
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) {
@ -94,12 +91,10 @@ static bool setup_device(void) {
char adaptername[1024];
char tapname[1024];
DWORD len;
unsigned long status;
bool found = false;
int err;
HANDLE thread;
get_config_string(lookup_config(config_tree, "Device"), &device);
get_config_string(lookup_config(config_tree, "Interface"), &iface);
@ -191,20 +186,6 @@ static bool setup_device(void) {
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";
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;
}
static void close_device(void) {
CloseHandle(device_handle);
static void enable_device(void) {
logger(DEBUG_ALWAYS, LOG_INFO, "Enabling %s", device_info);
free(device);
free(iface);
ULONG status = 1;
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) {
@ -230,26 +236,19 @@ static bool write_packet(vpn_packet_t *packet) {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s",
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()));
return false;
}
device_total_out += packet->len;
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 = {
.setup = setup_device,
.close = close_device,
.read = read_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 uint64_t device_total_in = 0;
static uint64_t device_total_out = 0;
static struct addrinfo *ai = NULL;
static mac_t ignore_src = {{0}};
@ -132,7 +129,7 @@ static bool setup_device(void) {
#endif
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;
}
@ -151,33 +148,33 @@ error:
}
static void close_device(void) {
close(device_fd);
close(device_fd); device_fd = -1;
free(device);
free(iface);
free(device); device = NULL;
free(iface); iface = NULL;
if(ai)
freeaddrinfo(ai);
if(ai) {
freeaddrinfo(ai); ai = NULL;
}
device_info = NULL;
}
static bool read_packet(vpn_packet_t *packet) {
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,
device, strerror(errno));
device, sockstrerror(sockerrno));
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);
return false;
}
packet->len = lenin;
device_total_in += packet->len;
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len,
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",
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,
strerror(errno));
sockstrerror(sockerrno));
return false;
}
device_total_out += packet->len;
memcpy(&ignore_src, packet->data + 6, sizeof ignore_src);
memcpy(&ignore_src, DATA(packet) + 6, sizeof ignore_src);
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 = {
.setup = setup_device,
.close = close_device,
.read = read_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
xasprintf(&confbase, "%s", installdir);
}
if(!pidfilename)
xasprintf(&pidfilename, "%s" SLASH "pid", confbase);
}
RegCloseKey(key);
}
@ -73,11 +71,26 @@ void make_names(void) {
if(!confdir)
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)
xasprintf(&logfilename, LOCALSTATEDIR SLASH "log" SLASH "%s.log", identname);
if(!pidfilename)
xasprintf(&pidfilename, LOCALSTATEDIR SLASH "run" SLASH "%s.pid", identname);
#endif
if(!unixsocketname) {
int len = strlen(pidfilename);
@ -88,13 +101,6 @@ void make_names(void) {
else
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) {

View file

@ -36,6 +36,10 @@
#include "subnet.h"
#include "xalloc.h"
#ifdef HAVE_RESOLV_H
#include <resolv.h>
#endif
int contradicting_add_edge = 0;
int contradicting_del_edge = 0;
static int sleeptime = 10;
@ -93,8 +97,6 @@ void purge(void) {
void terminate_connection(connection_t *c, bool report) {
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)
c->node->connection = NULL;
@ -129,6 +131,12 @@ void terminate_connection(connection_t *c, bool report) {
if(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;
if(c->last_ping_time + pingtimeout <= now.tv_sec) {
if(c->status.active) {
if(c->edge) {
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);
} else if(c->last_ping_time + pinginterval <= now.tv_sec) {
@ -160,7 +168,7 @@ static void timeout_handler(void *data) {
else
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 */
int nc = 0;
for list_each(connection_t, c, connection_list) {
if(c->status.active && !c->status.control)
if(c->edge)
nc++;
}
if(nc < autoconnect) {
if(nc < 3) {
/* Not enough active connections, try to add one.
Choose a random node, if we don't have a connection to it,
and we are not already trying to make one, create an
@ -232,7 +240,7 @@ static void periodic_handler(void *data) {
}
break;
}
} else if(nc > autoconnect) {
} else if(nc > 3) {
/* Too many active connections, try to remove one.
Choose a random outgoing connection to a node
that has at least one other connection.
@ -241,7 +249,7 @@ static void periodic_handler(void *data) {
int i = 0;
for list_each(connection_t, c, connection_list) {
if(!c->status.active || c->status.control)
if(!c->edge)
continue;
if(i++ != r)
@ -253,12 +261,12 @@ static void periodic_handler(void *data) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "Autodisconnecting from %s", c->name);
list_delete(outgoing_list, c->outgoing);
c->outgoing = NULL;
terminate_connection(c, c->status.active);
terminate_connection(c, c->edge);
break;
}
}
if(nc >= autoconnect) {
if(nc >= 3) {
/* If we have enough active connections,
remove any pending outgoing connections.
*/
@ -283,7 +291,7 @@ static void periodic_handler(void *data) {
void handle_meta_connection_data(connection_t *c) {
if (!receive_meta(c)) {
terminate_connection(c, c->status.active);
terminate_connection(c, c->edge);
return;
}
}
@ -303,6 +311,9 @@ static void sighup_handler(void *data) {
static void sigalrm_handler(void *data) {
logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum));
#ifdef HAVE_DECL_RES_INIT
res_init();
#endif
retry();
}
#endif
@ -334,11 +345,14 @@ int reload_configuration(void) {
if(strictsubnets) {
for splay_each(subnet_t, subnet, subnet_tree)
if (subnet->owner)
subnet->expires = 1;
load_all_subnets();
for splay_each(subnet_t, subnet, subnet_tree) {
if (!subnet->owner)
continue;
if(subnet->expires == 1) {
send_del_subnet(everyone, subnet);
if(subnet->owner->status.reachable)
@ -402,7 +416,7 @@ int reload_configuration(void) {
struct stat s;
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);
terminate_connection(c, c->status.active);
terminate_connection(c, c->edge);
}
free(fname);
}
@ -452,7 +466,7 @@ int main_loop(void) {
#endif
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;
}

View file

@ -1,7 +1,7 @@
/*
net.h -- header for net.c
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
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 */
#endif
/* MAXSIZE is the maximum size of an encapsulated packet: MTU + seqno + padding + HMAC + compressor overhead */
#define MAXSIZE (MTU + 4 + CIPHER_MAX_BLOCK_SIZE + DIGEST_MAX_SIZE + MTU/64 + 20)
/* MAXSIZE is the maximum size of an encapsulated packet: MTU + seqno + srcid + dstid + padding + HMAC + compressor overhead */
#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 */
#define MAXBUFSIZE ((MAXSIZE > 2048 ? MAXSIZE : 2048) + 128)
@ -52,7 +52,12 @@ typedef struct ipv6_t {
uint16_t x[8];
} ipv6_t;
typedef struct node_id_t {
uint8_t x[6];
} node_id_t;
typedef short length_t;
typedef uint32_t seqno_t;
#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))
#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 {
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 */
uint32_t seqno; /* 32 bits sequence number (network byte order of course) */
uint8_t data[MAXSIZE];
} vpn_packet_t;
@ -103,6 +114,7 @@ typedef struct listen_socket_t {
io_t tcp;
io_t udp;
sockaddr_t sa;
bool bindto;
} listen_socket_t;
#include "conf.h"
@ -125,7 +137,6 @@ extern int seconds_till_retry;
extern int addressfamily;
extern unsigned replaywin;
extern bool localdiscovery;
extern sockaddr_t localdiscovery_address;
extern listen_socket_t listen_socket[MAXSOCKETS];
extern int listen_sockets;
@ -136,7 +147,8 @@ extern int udp_sndbuf;
extern int max_connection_burst;
extern bool do_prune;
extern char *myport;
extern int autoconnect;
extern bool device_standby;
extern bool autoconnect;
extern bool disablebuggypeers;
extern int contradicting_add_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 int setup_listen_socket(const sockaddr_t *);
extern int setup_vpn_in_socket(const sockaddr_t *);
extern bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len);
extern bool receive_sptps_record(void *handle, uint8_t type, const char *data, uint16_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 void *data, uint16_t len);
extern void send_packet(struct node_t *, vpn_packet_t *);
extern void receive_tcppacket(struct connection_t *, const char *, int);
extern void broadcast_packet(const struct node_t *, vpn_packet_t *);
extern char *get_name(void);
extern void device_enable(void);
extern void device_disable(void);
extern bool setup_myself_reloadable(void);
extern bool setup_network(void);
extern void setup_outgoing_connection(struct outgoing_t *);
@ -199,8 +213,6 @@ extern void load_all_nodes(void);
#ifndef HAVE_MINGW
#define closesocket(s) close(s)
#else
extern CRITICAL_SECTION mutex;
#endif
#endif /* __TINC_NET_H__ */

View file

@ -1,7 +1,7 @@
/*
net_packet.c -- Handles in- and outgoing VPN packets
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 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 *);
unsigned replaywin = 16;
bool localdiscovery = false;
sockaddr_t localdiscovery_address;
bool localdiscovery = true;
#define MAX_SEQNO 1073741824
@ -140,19 +139,19 @@ static void send_mtu_probe_handler(void *data) {
len = 64;
vpn_packet_t packet;
memset(packet.data, 0, 14);
randomize(packet.data + 14, len - 14);
packet.offset = DEFAULT_PACKET_OFFSET;
memset(DATA(&packet), 0, 14);
randomize(DATA(&packet) + 14, len - 14);
packet.len = len;
if(i >= 4 && n->mtuprobes <= 10)
packet.priority = -1;
else
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);
send_udppacket(n, &packet);
}
n->status.send_locally = false;
n->probe_counter = 0;
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) {
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);
/* It's a probe request, send back a reply */
/* Type 2 probe replies were introduced in protocol 17.3 */
if ((n->options >> 24) == 3) {
uint8_t* data = packet->data;
if ((n->options >> 24) >= 3) {
uint8_t *data = DATA(packet);
*data++ = 2;
uint16_t len16 = htons(len); memcpy(data, &len16, 2); data += 2;
struct timeval now;
gettimeofday(&now, NULL);
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;
packet->len = data - packet->data;
packet->len -= 10;
} else {
/* 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
@ -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;
} else {
length_t probelen = len;
if (packet->data[0] == 2) {
if (DATA(packet)[0] == 2) {
if (len < 3)
logger(DEBUG_TRAFFIC, LOG_WARNING, "Received invalid (too short) MTU probe reply from %s (%s)", n->name, n->hostname);
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
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);
struct timeval probe_timestamp = now;
if (packet->data[0] == 2 && packet->len >= 11) {
uint32_t sec; memcpy(&sec, packet->data + 3, 4);
uint32_t usec; memcpy(&usec, packet->data + 7, 4);
if (DATA(packet)[0] == 2 && packet->len >= 11) {
uint32_t sec; memcpy(&sec, DATA(packet) + 3, 4);
uint32_t usec; memcpy(&usec, DATA(packet) + 7, 4);
probe_timestamp.tv_sec = ntohl(sec);
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) {
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 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 *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 };
int nextpkt = 0;
vpn_packet_t *outpkt = pkt[0];
size_t outlen;
pkt1.offset = DEFAULT_PACKET_OFFSET;
pkt2.offset = DEFAULT_PACKET_OFFSET;
if(n->status.sptps) {
if(!n->sptps.state) {
@ -373,43 +373,51 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
} else {
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);
return;
inpkt->offset += 2 * sizeof(node_id_t);
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);
return;
return false;
}
/* 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)",
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 */
if(digest_active(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);
return;
return false;
}
}
/* Decrypt the packet */
if(cipher_active(n->incipher)) {
outpkt = pkt[nextpkt++];
vpn_packet_t *outpkt = pkt[nextpkt++];
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);
return;
return false;
}
outpkt->len = outlen;
@ -418,38 +426,40 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
/* Check the sequence number */
inpkt->len -= sizeof inpkt->seqno;
inpkt->seqno = ntohl(inpkt->seqno);
seqno_t seqno;
memcpy(&seqno, SEQNO(inpkt), sizeof seqno);
seqno = ntohl(seqno);
inpkt->len -= sizeof seqno;
if(replaywin) {
if(inpkt->seqno != n->received_seqno + 1) {
if(inpkt->seqno >= n->received_seqno + replaywin * 8) {
if(seqno != n->received_seqno + 1) {
if(seqno >= n->received_seqno + replaywin * 8) {
if(n->farfuture++ < replaywin >> 2) {
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);
return;
n->name, n->hostname, seqno - n->received_seqno - 1, n->farfuture);
return false;
}
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);
} else if (inpkt->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))) {
} else if (seqno <= n->received_seqno) {
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",
n->name, n->hostname, inpkt->seqno, n->received_seqno);
return;
n->name, n->hostname, seqno, n->received_seqno);
return false;
}
} 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->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)
n->received_seqno = inpkt->seqno;
if(seqno > n->received_seqno)
n->received_seqno = seqno;
n->received++;
@ -461,12 +471,12 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
length_t origlen = inpkt->len;
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)",
n->name, n->hostname);
return;
return false;
}
inpkt = outpkt;
@ -476,16 +486,18 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
inpkt->priority = 0;
if(!inpkt->data[12] && !inpkt->data[13])
if(!DATA(inpkt)[12] && !DATA(inpkt)[13])
mtu_probe_h(n, inpkt, origlen);
else
receive_packet(n, inpkt);
return true;
}
void receive_tcppacket(connection_t *c, const char *buffer, int len) {
vpn_packet_t outpkt;
outpkt.offset = DEFAULT_PACKET_OFFSET;
if(len > sizeof outpkt.data)
if(len > sizeof outpkt.data - outpkt.offset)
return;
outpkt.len = len;
@ -493,14 +505,22 @@ void receive_tcppacket(connection_t *c, const char *buffer, int len) {
outpkt.priority = 0;
else
outpkt.priority = -1;
memcpy(outpkt.data, buffer, len);
memcpy(DATA(&outpkt), buffer, len);
receive_packet(c->node, &outpkt);
}
static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) {
if(!n->status.validkey) {
static bool try_sptps(node_t *n) {
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);
if(!n->status.waitingforkey)
send_req_key(n);
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;
send_req_key(n);
}
return;
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;
uint8_t type = 0;
int offset = 0;
if(!(origpkt->data[12] | origpkt->data[13])) {
sptps_send_record(&n->sptps, PKT_PROBE, (char *)origpkt->data, origpkt->len);
if(!(DATA(origpkt)[12] | DATA(origpkt)[13])) {
sptps_send_record(&n->sptps, PKT_PROBE, (char *)DATA(origpkt), origpkt->len);
return;
}
@ -531,7 +559,8 @@ static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) {
vpn_packet_t outpkt;
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) {
logger(DEBUG_TRAFFIC, LOG_ERR, "Error while compressing packet to %s (%s)", n->name, n->hostname);
} 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;
}
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) {
/* Latest guess */
*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;
}
/* 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;
adapt_socket(*sa, sock);
}
static void choose_local_address(const node_t *n, const sockaddr_t **sa, int *sock) {
*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;
}
}
}
}
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;
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;
}
adapt_socket(*sa, sock);
}
}
@ -643,8 +667,11 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
size_t outlen;
#if defined(SOL_IP) && defined(IP_TOS)
static int priority = 0;
#endif
int origpriority = origpkt->priority;
#endif
pkt1.offset = DEFAULT_PACKET_OFFSET;
pkt2.offset = DEFAULT_PACKET_OFFSET;
if(!n->status.reachable) {
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;
}
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,
"Packet for %s (%s) larger than minimum MTU, forwarding via %s",
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) {
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)",
n->name, n->hostname);
return;
@ -700,8 +727,9 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
/* Add sequence number */
inpkt->seqno = htonl(++(n->sent_seqno));
inpkt->len += sizeof inpkt->seqno;
seqno_t seqno = htonl(++(n->sent_seqno));
memcpy(SEQNO(inpkt), &seqno, sizeof seqno);
inpkt->len += sizeof seqno;
/* Encrypt the packet */
@ -709,7 +737,7 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
outpkt = pkt[nextpkt++];
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);
goto end;
}
@ -721,7 +749,7 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
/* Add the message authentication code */
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);
goto end;
}
@ -731,14 +759,12 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
/* Send the packet */
const sockaddr_t *sa;
const sockaddr_t *sa = NULL;
int sock;
/* Overloaded use of priority field: -1 means local broadcast */
if(origpriority == -1 && n->prevedge)
choose_broadcast_address(n, &sa, &sock);
else
if(n->status.send_locally)
choose_local_address(n, &sa, &sock);
if(!sa)
choose_udp_address(n, &sa, &sock);
#if defined(SOL_IP) && defined(IP_TOS)
@ -747,11 +773,11 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
priority = origpriority;
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 */
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
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(n->maxmtu >= origlen)
n->maxmtu = origlen - 1;
@ -765,39 +791,67 @@ end:
origpkt->len = origlen;
}
bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len) {
node_t *to = handle;
static bool send_sptps_data_priv(node_t *to, node_t *from, int type, const void *data, size_t len) {
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];
b64encode(data, buf, len);
/* If no valid key is known yet, send the packets using ANS_KEY requests,
to ensure we get to learn the reflexive UDP address. */
if(!to->status.validkey) {
if(from == myself && !to->status.validkey) {
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 {
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;
choose_udp_address(to, &sa, &sock);
if(sendto(listen_socket[sock].udp.fd, data, len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) {
if(relay->status.send_locally)
choose_local_address(relay, &sa, &sock);
if(!sa)
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(to->maxmtu >= len)
to->maxmtu = len - 1;
if(to->mtu >= len)
to->mtu = len - 1;
// Compensate for SPTPS overhead
len -= SPTPS_DATAGRAM_OVERHEAD;
if(relay->maxmtu >= len)
relay->maxmtu = len - 1;
if(relay->mtu >= len)
relay->mtu = len - 1;
} 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;
}
}
@ -805,7 +859,11 @@ bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len) {
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;
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;
inpkt.offset = DEFAULT_PACKET_OFFSET;
if(type == PKT_PROBE) {
inpkt.len = len;
memcpy(inpkt.data, data, len);
memcpy(DATA(&inpkt), data, len);
mtu_probe_h(from, &inpkt, len);
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;
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) {
return false;
} else {
@ -855,25 +914,25 @@ bool receive_sptps_record(void *handle, uint8_t type, const char *data, uint16_t
if(inpkt.len > MAXSIZE)
abort();
} else {
memcpy(inpkt.data + offset, data, len);
memcpy(DATA(&inpkt) + offset, data, len);
inpkt.len = len + offset;
}
/* Generate the Ethernet packet type if necessary */
if(offset) {
switch(inpkt.data[14] >> 4) {
switch(DATA(&inpkt)[14] >> 4) {
case 4:
inpkt.data[12] = 0x08;
inpkt.data[13] = 0x00;
DATA(&inpkt)[12] = 0x08;
DATA(&inpkt)[13] = 0x00;
break;
case 6:
inpkt.data[12] = 0x86;
inpkt.data[13] = 0xDD;
DATA(&inpkt)[12] = 0x86;
DATA(&inpkt)[13] = 0xDD;
break;
default:
logger(DEBUG_TRAFFIC, LOG_ERR,
"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;
}
}
@ -890,7 +949,7 @@ void send_packet(node_t *n, vpn_packet_t *packet) {
if(n == myself) {
if(overwrite_mac)
memcpy(packet->data, mymac.x, ETH_ALEN);
memcpy(DATA(packet), mymac.x, ETH_ALEN);
n->out_packets++;
n->out_bytes += packet->len;
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.
case BMODE_MST:
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);
break;
@ -1002,12 +1061,14 @@ void handle_incoming_vpn_data(void *data, int flags) {
listen_socket_t *ls = data;
vpn_packet_t pkt;
char *hostname;
sockaddr_t from = {{0}};
socklen_t fromlen = sizeof from;
node_t *n;
int len;
node_id_t nullid = {};
sockaddr_t addr = {};
socklen_t addrlen = sizeof addr;
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(!sockwouldblock(sockerrno))
@ -1017,32 +1078,76 @@ void handle_incoming_vpn_data(void *data, int flags) {
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) {
n = try_harder(&from, &pkt);
if(n)
update_node_udp(n, &from);
else if(debug_level >= DEBUG_PROTOCOL) {
hostname = sockaddr2hostname(&from);
// It might be from a 1.1 node, which might have a source ID in the packet.
pkt.offset = 2 * sizeof(node_id_t);
from = lookup_node_id(SRCID(&pkt));
if(from && !memcmp(DSTID(&pkt), &nullid, sizeof nullid) && from->status.sptps) {
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);
free(hostname);
}
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;
}
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;
receive_udppacket(n, &pkt);
if(direct && sockaddrcmp(&addr, &n->address))
update_node_udp(n, &addr);
}
void handle_device_data(void *data, int flags) {
vpn_packet_t packet;
packet.offset = DEFAULT_PACKET_OFFSET;
packet.priority = 0;
if(devops.read(&packet)) {

View file

@ -1,7 +1,7 @@
/*
net_setup.c -- Setup.
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>
2010 Brandon Black <blblack@gmail.com>
@ -44,15 +44,17 @@
#include "xalloc.h"
char *myport;
static char *myname;
static io_t device_io;
devops_t devops;
bool device_standby = false;
char *proxyhost;
char *proxyport;
char *proxyuser;
char *proxypass;
proxytype_t proxytype;
int autoconnect;
bool autoconnect;
bool disablebuggypeers;
char *scriptinterpreter;
@ -71,25 +73,23 @@ bool node_read_ecdsa_public_key(node_t *n) {
if(!read_host_config(config_tree, n->name))
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);
free(p);
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);
fp = fopen(pubname, "r");
if(!fp) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error reading ECDSA public key file `%s': %s", pubname, strerror(errno));
if(!fp)
goto exit;
}
n->ecdsa = ecdsa_read_pem_public_key(fp);
fclose(fp);
@ -114,23 +114,23 @@ bool read_ecdsa_public_key(connection_t *c) {
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);
free(p);
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);
fp = fopen(fname, "r");
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));
free(fname);
return false;
@ -140,7 +140,7 @@ bool read_ecdsa_public_key(connection_t *c) {
fclose(fp);
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);
return c->ecdsa;
}
@ -189,15 +189,15 @@ static bool read_ecdsa_private_key(void) {
/* Check for PrivateKeyFile statement and read it */
if(!get_config_string(lookup_config(config_tree, "ECDSAPrivateKeyFile"), &fname))
xasprintf(&fname, "%s" SLASH "ecdsa_key.priv", confbase);
if(!get_config_string(lookup_config(config_tree, "Ed25519PrivateKeyFile"), &fname))
xasprintf(&fname, "%s" SLASH "ed25519_key.priv", confbase);
fp = fopen(fname, "r");
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)
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);
return false;
}
@ -206,20 +206,20 @@ static bool read_ecdsa_private_key(void) {
struct stat 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);
return false;
}
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
myself->connection->ecdsa = ecdsa_read_pem_private_key(fp);
fclose(fp);
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);
return myself->connection->ecdsa;
}
@ -233,7 +233,7 @@ static bool read_invitation_key(void) {
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");
@ -241,7 +241,7 @@ static bool read_invitation_key(void) {
invitation_key = ecdsa_read_pem_private_key(fp);
fclose(fp);
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);
@ -277,6 +277,8 @@ static bool read_rsa_private_key(void) {
if(!fp) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error reading RSA private key file `%s': %s",
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);
return false;
}
@ -403,40 +405,16 @@ void load_all_nodes(void) {
char *get_name(void) {
char *name = NULL;
char *returned_name;
get_config_string(lookup_config(config_tree, "Name"), &name);
if(!name)
return NULL;
if(*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;
}
returned_name = replace_name(name);
free(name);
name = xstrdup(envname);
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;
return returned_name;
}
bool setup_myself_reloadable(void) {
@ -445,7 +423,6 @@ bool setup_myself_reloadable(void) {
char *fmode = NULL;
char *bmode = NULL;
char *afname = NULL;
char *address = NULL;
char *space;
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, "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(!strcasecmp(rmode, "router"))
routing_mode = RMODE_ROUTER;
@ -596,6 +563,20 @@ bool setup_myself_reloadable(void) {
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(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))
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);
@ -640,18 +629,133 @@ bool setup_myself_reloadable(void) {
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)
*/
static bool setup_myself(void) {
char *name, *hostname, *cipher, *digest, *type;
char *address = NULL;
bool port_specified = false;
if(!(name = get_name())) {
logger(DEBUG_ALWAYS, LOG_ERR, "Name for tinc daemon required!");
return false;
}
myname = xstrdup(name);
myself = new_node();
myself->connection = new_connection();
myself->name = name;
@ -660,9 +764,8 @@ static bool setup_myself(void) {
if(!get_config_string(lookup_config(config_tree, "Port"), &myport))
myport = xstrdup("655");
xasprintf(&myself->hostname, "MYSELF port %s", myport);
myself->connection->hostname = xstrdup(myself->hostname);
else
port_specified = true;
myself->connection->options = 0;
myself->connection->protocol_major = PROT_MAJOR;
@ -670,13 +773,25 @@ static bool setup_myself(void) {
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())
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;
}
}
/* Ensure myport is numeric */
if(!atoi(myport)) {
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))
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!");
return false;
}
@ -766,7 +883,9 @@ static bool setup_myself(void) {
if(!get_config_string(lookup_config(config_tree, "Digest"), &digest))
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!");
return false;
}
@ -822,6 +941,8 @@ static bool setup_myself(void) {
#endif
}
get_config_bool(lookup_config(config_tree, "DeviceStandby"), &device_standby);
if(!devops.setup())
return false;
@ -847,7 +968,7 @@ static bool setup_myself(void) {
for(int i = 0; i < listen_sockets; i++) {
salen = sizeof sa;
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;
}
@ -872,73 +993,25 @@ static bool setup_myself(void) {
}
} else {
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);
if(cfg)
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));
if(!add_listen_address(address, true))
return false;
}
for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) {
if(listen_sockets >= MAXSOCKETS) {
logger(DEBUG_ALWAYS, LOG_ERR, "Too many listening sockets");
for(config_t *cfg = lookup_config(config_tree, "ListenAddress"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
cfgs++;
get_config_string(cfg, &address);
if(!add_listen_address(address, false))
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) {
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(!cfgs)
if(!add_listen_address(address, NULL))
return false;
}
if(!listen_sockets) {
@ -946,6 +1019,24 @@ static bool setup_myself(void) {
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;
return true;
@ -982,18 +1073,8 @@ bool setup_network(void) {
if(!init_control())
return false;
/* 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", myself->name);
execute_script("tinc-up", envp);
for(int i = 0; i < 4; i++)
free(envp[i]);
if (!device_standby)
device_enable();
/* Run subnet-up scripts for our own subnets */
@ -1016,6 +1097,7 @@ void close_network_connections(void) {
terminate_connection(c, false);
}
if(outgoing_list)
list_delete_list(outgoing_list);
if(myself && myself->connection) {
@ -1031,28 +1113,27 @@ void close_network_connections(void) {
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_edges();
exit_subnets();
exit_nodes();
exit_connections();
execute_script("tinc-down", envp);
if (!device_standby)
device_disable();
if(myport) free(myport);
for(int i = 0; i < 4; i++)
free(envp[i]);
free(myport);
if (device_fd >= 0)
io_del(&device_io);
if (devops.close)
devops.close();
exit_control();
free(myname);
free(scriptextension);
free(scriptinterpreter);
return;
}

View file

@ -1,7 +1,7 @@
/*
net_socket.c -- Handle various kinds of sockets.
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>
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));
if(status) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to interface %s: %s", iface,
strerror(errno));
sockstrerror(sockerrno));
return false;
}
#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) {
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)
continue;
if(s >= 0)
@ -134,7 +134,7 @@ static bool bind_to_address(connection_t *c) {
sa.in6.sin6_port = 0;
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;
}
@ -179,7 +179,7 @@ int setup_listen_socket(const sockaddr_t *sa) {
if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof ifr)) {
closesocket(nfd);
logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to interface %s: %s", iface,
strerror(sockerrno));
sockstrerror(sockerrno));
return -1;
}
#else
@ -247,10 +247,10 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
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)))
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)))
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(sa->sa.sa_family == AF_INET6)
@ -271,8 +271,6 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
option = 1;
setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, (void *)&option, sizeof(option));
}
#else
#warning No way to disable IPv4 fragmentation
#endif
#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;
setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, (void *)&option, sizeof(option));
}
#else
#warning No way to disable IPv6 fragmentation
#endif
if (!bind_to_interface(nfd)) {
@ -334,7 +330,7 @@ static void do_outgoing_pipe(connection_t *c, char *command) {
int fd[2];
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;
}
@ -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);
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);
} 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);
return;
} 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;
}
@ -405,19 +401,38 @@ static void handle_meta_io(void *data, int flags) {
connection_t *c = data;
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;
socklen_t len = sizeof result;
getsockopt(c->socket, SOL_SOCKET, SO_ERROR, (void *)&result, &len);
if(!result)
finish_connecting(c);
Note that the behavior of send() on potentially unconnected sockets differ between platforms:
+------------+-----------+-------------+-----------+
| Event | POSIX | Linux | Windows |
+------------+-----------+-------------+-----------+
| Spurious | ENOTCONN | EWOULDBLOCK | ENOTCONN |
| 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 {
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);
}
return;
}
c->status.connecting = false;
finish_connecting(c);
}
if(flags & IO_WRITE)
@ -547,6 +562,39 @@ begin:
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) {
timeout_del(&outgoing->ev);
@ -564,9 +612,13 @@ void setup_outgoing_connection(outgoing_t *outgoing) {
outgoing->cfg = lookup_config(outgoing->config_tree, "Address");
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;
}
}
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
static sockaddr_t prev_sa;
static time_t prev_time;
static int tarpit = -1;
if(tarpit >= 0) {
@ -621,7 +672,6 @@ void handle_new_meta_connection(void *data, int flags) {
}
memcpy(&prev_sa, &sa, sizeof sa);
prev_time = now.tv_sec;
// 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) {
c->outgoing = NULL;
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 "xalloc.h"
static digest_t *sha256;
splay_tree_t *node_tree;
static splay_tree_t *node_id_tree;
static hash_t *node_udp_cache;
static hash_t *node_id_cache;
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);
}
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) {
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_id_tree = splay_alloc_tree((splay_compare_t) node_id_compare, NULL);
node_udp_cache = hash_alloc(0x100, sizeof(sockaddr_t));
node_id_cache = hash_alloc(0x100, sizeof(node_id_t));
}
void exit_nodes(void) {
hash_free(node_id_cache);
hash_free(node_udp_cache);
splay_delete_tree(node_id_tree);
splay_delete_tree(node_tree);
digest_close(sha256);
}
node_t *new_node(void) {
@ -93,16 +109,23 @@ void free_node(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_id_tree, 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)
subnet_del(n, s);
for splay_each(edge_t, e, n->edge_tree)
edge_del(e);
splay_delete(node_id_tree, n);
splay_delete(node_tree, n);
}
@ -114,6 +137,18 @@ node_t *lookup_node(char *name) {
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) {
return hash_search(node_udp_cache, sa);
}
@ -124,7 +159,7 @@ void update_node_udp(node_t *n, const sockaddr_t *sa) {
return;
}
hash_insert(node_udp_cache, &n->address, NULL);
hash_delete(node_udp_cache, &n->address);
if(sa) {
n->address = *sa;
@ -140,15 +175,27 @@ void update_node_udp(node_t *n, const sockaddr_t *sa) {
n->hostname = sockaddr2hostname(&n->address);
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) {
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,
n->name, n->hostname ?: "unknown port unknown", cipher_get_nid(n->outcipher),
for splay_each(node_t, n, node_tree) {
char id[2 * sizeof n->id + 1];
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,
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);
}
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 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 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;
typedef struct node_t {
char *name; /* name of this node */
node_id_t id; /* unique node ID (name hash) */
uint32_t options; /* options turned on for this node */
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_del(node_t *);
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 bool dump_nodes(struct connection_t *);
extern bool dump_traffic(struct connection_t *);

View file

@ -30,15 +30,8 @@
struct cipher {
EVP_CIPHER_CTX ctx;
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) {
cipher_t *cipher = xzalloc(sizeof *cipher);
cipher->cipher = evp_cipher;
@ -76,7 +69,6 @@ void cipher_close(cipher_t *cipher) {
return;
EVP_CIPHER_CTX_cleanup(&cipher->ctx);
free(cipher->counter);
free(cipher);
}
@ -84,7 +76,7 @@ size_t cipher_keylength(const cipher_t *cipher) {
if(!cipher || !cipher->cipher)
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) {
@ -117,70 +109,6 @@ bool cipher_set_key_from_rsa(cipher_t *cipher, void *key, size_t len, bool encry
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) {
if(oneshot) {
int len, pad;

View file

@ -1,6 +1,6 @@
/*
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
it under the terms of the GNU General Public License as published by
@ -25,8 +25,65 @@
#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) {
RAND_load_file("/dev/urandom", 1024);
random_init();
ENGINE_load_builtin_engines();
ENGINE_register_all_complete();
@ -42,8 +99,7 @@ void crypto_init(void) {
void crypto_exit(void) {
EVP_cleanup();
}
void randomize(void *out, size_t outlen) {
RAND_pseudo_bytes(out, outlen);
ERR_free_strings();
ENGINE_cleanup();
random_exit();
}

View file

@ -1,96 +0,0 @@
/*
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 <openssl/err.h>
#include <openssl/ec.h>
#include <openssl/ecdh.h>
#include <openssl/obj_mac.h>
#define __TINC_ECDH_INTERNAL__
typedef EC_KEY ecdh_t;
#include "../ecdh.h"
#include "../logger.h"
#include "../utils.h"
#include "../xalloc.h"
ecdh_t *ecdh_generate_public(void *pubkey) {
ecdh_t *ecdh = EC_KEY_new_by_curve_name(NID_secp521r1);
if(!ecdh) {
logger(DEBUG_ALWAYS, LOG_ERR, "Generating EC key_by_curve_name failed: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
}
if(!EC_KEY_generate_key(ecdh)) {
EC_KEY_free(ecdh);
logger(DEBUG_ALWAYS, LOG_ERR, "Generating EC key failed: %s", ERR_error_string(ERR_get_error(), NULL));
return NULL;
}
const EC_POINT *point = EC_KEY_get0_public_key(ecdh);
if(!point) {
EC_KEY_free(ecdh);
logger(DEBUG_ALWAYS, LOG_ERR, "Getting public key failed: %s", ERR_error_string(ERR_get_error(), NULL));
return NULL;
}
size_t result = EC_POINT_point2oct(EC_KEY_get0_group(ecdh), point, POINT_CONVERSION_COMPRESSED, pubkey, ECDH_SIZE, NULL);
if(!result) {
EC_KEY_free(ecdh);
logger(DEBUG_ALWAYS, LOG_ERR, "Converting EC_POINT to binary failed: %s", ERR_error_string(ERR_get_error(), NULL));
return NULL;
}
return ecdh;
}
bool ecdh_compute_shared(ecdh_t *ecdh, const void *pubkey, void *shared) {
EC_POINT *point = EC_POINT_new(EC_KEY_get0_group(ecdh));
if(!point) {
logger(DEBUG_ALWAYS, LOG_ERR, "EC_POINT_new() failed: %s", ERR_error_string(ERR_get_error(), NULL));
EC_KEY_free(ecdh);
return false;
}
int result = EC_POINT_oct2point(EC_KEY_get0_group(ecdh), point, pubkey, ECDH_SIZE, NULL);
if(!result) {
EC_POINT_free(point);
EC_KEY_free(ecdh);
logger(DEBUG_ALWAYS, LOG_ERR, "Converting binary to EC_POINT failed: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
}
result = ECDH_compute_key(shared, ECDH_SIZE, point, ecdh, NULL);
EC_POINT_free(point);
EC_KEY_free(ecdh);
if(!result) {
logger(DEBUG_ALWAYS, LOG_ERR, "Computing Elliptic Curve Diffie-Hellman shared key failed: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
}
return true;
}
void ecdh_free(ecdh_t *ecdh) {
if(ecdh)
EC_KEY_free(ecdh);
}

View file

@ -1,131 +0,0 @@
/*
ecdsa.c -- ECDSA key handling
Copyright (C) 2011-2013 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "../system.h"
#include <openssl/pem.h>
#include <openssl/err.h>
#define __TINC_ECDSA_INTERNAL__
typedef EC_KEY 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) {
ecdsa_t *ecdsa = EC_KEY_new_by_curve_name(NID_secp521r1);
if(!ecdsa) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "EC_KEY_new_by_curve_name failed: %s", ERR_error_string(ERR_get_error(), NULL));
return NULL;
}
int len = strlen(p);
unsigned char pubkey[len / 4 * 3 + 3];
const unsigned char *ppubkey = pubkey;
len = b64decode(p, (char *)pubkey, len);
if(!o2i_ECPublicKey(&ecdsa, &ppubkey, len)) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "o2i_ECPublicKey failed: %s", ERR_error_string(ERR_get_error(), NULL));
EC_KEY_free(ecdsa);
return NULL;
}
return ecdsa;
}
char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa) {
unsigned char *pubkey = NULL;
int len = i2o_ECPublicKey(ecdsa, &pubkey);
char *base64 = xmalloc(len * 4 / 3 + 5);
b64encode((char *)pubkey, base64, len);
free(pubkey);
return base64;
}
// Read PEM ECDSA keys
ecdsa_t *ecdsa_read_pem_public_key(FILE *fp) {
ecdsa_t *ecdsa = PEM_read_EC_PUBKEY(fp, NULL, NULL, NULL);
if(!ecdsa)
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read ECDSA public key: %s", ERR_error_string(ERR_get_error(), NULL));
return ecdsa;
}
ecdsa_t *ecdsa_read_pem_private_key(FILE *fp) {
ecdsa_t *ecdsa = PEM_read_ECPrivateKey(fp, NULL, NULL, NULL);
if(!ecdsa)
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read ECDSA private key: %s", ERR_error_string(ERR_get_error(), NULL));
return ecdsa;
}
size_t ecdsa_size(ecdsa_t *ecdsa) {
return ECDSA_size(ecdsa);
}
// TODO: standardise output format?
bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t len, void *sig) {
unsigned int siglen = ECDSA_size(ecdsa);
unsigned char hash[SHA512_DIGEST_LENGTH];
SHA512(in, len, hash);
memset(sig, 0, siglen);
if(!ECDSA_sign(0, hash, sizeof hash, sig, &siglen, ecdsa)) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "ECDSA_sign() failed: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
}
return true;
}
bool ecdsa_verify(ecdsa_t *ecdsa, const void *in, size_t len, const void *sig) {
unsigned int siglen = ECDSA_size(ecdsa);
unsigned char hash[SHA512_DIGEST_LENGTH];
SHA512(in, len, hash);
if(!ECDSA_verify(0, hash, sizeof hash, sig, siglen, ecdsa)) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "ECDSA_verify() failed: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
}
return true;
}
bool ecdsa_active(ecdsa_t *ecdsa) {
return ecdsa;
}
void ecdsa_free(ecdsa_t *ecdsa) {
if(ecdsa)
EC_KEY_free(ecdsa);
}

View file

@ -61,8 +61,10 @@ rsa_t *rsa_set_hex_private_key(char *n, char *e, char *d) {
rsa_t *rsa_read_pem_public_key(FILE *fp) {
rsa_t *rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL);
if(!rsa)
if(!rsa) {
rewind(fp);
rsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
}
if(!rsa)
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read RSA public key: %s", ERR_error_string(ERR_get_error(), NULL));

View file

@ -34,6 +34,7 @@
#include "subnet.h"
#include "utils.h"
#include "xalloc.h"
#include "version.h"
/* If zero, don't detach from the terminal. */
bool do_detach = true;
@ -108,6 +109,8 @@ static bool install_service(void) {
return true;
}
io_t stop_io;
DWORD WINAPI controlhandler(DWORD request, DWORD type, LPVOID boe, LPVOID bah) {
switch(request) {
case SERVICE_CONTROL_INTERROGATE:
@ -124,10 +127,11 @@ DWORD WINAPI controlhandler(DWORD request, DWORD type, LPVOID boe, LPVOID bah) {
return ERROR_CALL_NOT_IMPLEMENTED;
}
event_exit();
status.dwWaitHint = 30000;
status.dwWaitHint = 1000;
status.dwCurrentState = SERVICE_STOP_PENDING;
SetServiceStatus(statushandle, &status);
if (WSASetEvent(stop_io.event) == FALSE)
abort();
return NO_ERROR;
}
@ -209,7 +213,7 @@ bool detach(void) {
openlogger(identname, use_logfile?LOGMODE_FILE:(do_detach?LOGMODE_SYSLOG:LOGMODE_STDERR));
logger(DEBUG_ALWAYS, LOG_NOTICE, "tincd %s (%s %s) starting, debug level %d",
VERSION, __DATE__, __TIME__, debug_level);
VERSION, BUILD_DATE, BUILD_TIME, debug_level);
return true;
}

View file

@ -29,6 +29,7 @@ extern bool detach(void);
extern bool kill_other(int);
#ifdef HAVE_MINGW
extern io_t stop_io;
extern bool init_service(void);
#endif

View file

@ -55,17 +55,6 @@ static char (*request_name[]) = {
static splay_tree_t *past_request_tree;
bool check_id(const char *id) {
if(!id || !*id)
return false;
for(; *id; id++)
if(!isalnum(*id) && *id != '_')
return false;
return true;
}
/* Generic request routines - takes care of logging and error
detection as well */

View file

@ -26,7 +26,7 @@
/* Protocol version. Different major versions are incompatible. */
#define PROT_MAJOR 17
#define PROT_MINOR 3 /* Should not exceed 255! */
#define PROT_MINOR 4 /* Should not exceed 255! */
/* Silly Windows */
@ -81,7 +81,6 @@ extern ecdsa_t *invitation_key;
extern bool send_request(struct connection_t *, const char *, ...) __attribute__ ((__format__(printf, 2, 3)));
extern void forward_request(struct connection_t *, const char *);
extern bool receive_request(struct connection_t *, const char *);
extern bool check_id(const char *);
extern void init_requests(void);
extern void exit_requests(void);

View file

@ -1,7 +1,7 @@
/*
protocol_auth.c -- handle the meta-protocol, authentication
Copyright (C) 1999-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
it under the terms of the GNU General Public License as published by
@ -172,7 +172,7 @@ static bool finalize_invitation(connection_t *c, const char *data, uint16_t len)
return false;
}
fprintf(f, "ECDSAPublicKey = %s\n", data);
fprintf(f, "Ed25519PublicKey = %s\n", data);
fclose(f);
logger(DEBUG_CONNECTIONS, LOG_INFO, "Key succesfully received from %s (%s)", c->name, c->hostname);
@ -198,7 +198,7 @@ static bool finalize_invitation(connection_t *c, const char *data, uint16_t len)
return true;
}
static bool receive_invitation_sptps(void *handle, uint8_t type, const char *data, uint16_t len) {
static bool receive_invitation_sptps(void *handle, uint8_t type, const void *data, uint16_t len) {
connection_t *c = handle;
if(type == 128)
@ -380,12 +380,13 @@ bool id_h(connection_t *c, const char *request) {
if(experimental)
read_ecdsa_public_key(c);
} else {
if(c->protocol_minor && !ecdsa_active(c->ecdsa))
c->protocol_minor = 1;
/* Ignore failures if no key known yet */
}
/* Forbid version rollback for nodes whose ECDSA key we know */
if(c->protocol_minor && !ecdsa_active(c->ecdsa))
c->protocol_minor = 1;
/* Forbid version rollback for nodes whose Ed25519 key we know */
if(ecdsa_active(c->ecdsa) && c->protocol_minor < 2) {
logger(DEBUG_ALWAYS, LOG_ERR, "Peer %s (%s) tries to roll back protocol version to %d.%d",
@ -411,6 +412,11 @@ bool id_h(connection_t *c, const char *request) {
}
bool send_metakey(connection_t *c) {
if(!myself->connection->rsa) {
logger(DEBUG_CONNECTIONS, LOG_ERR, "Peer %s (%s) uses legacy protocol which we don't support", c->name, c->hostname);
return false;
}
if(!read_rsa_public_key(c))
return false;
@ -420,7 +426,7 @@ bool send_metakey(connection_t *c) {
if(!(c->outdigest = digest_open_sha1(-1)))
return false;
size_t len = rsa_size(c->rsa);
const size_t len = rsa_size(c->rsa);
char key[len];
char enckey[len];
char hexkey[2 * len + 1];
@ -477,9 +483,12 @@ bool send_metakey(connection_t *c) {
}
bool metakey_h(connection_t *c, const char *request) {
if(!myself->connection->rsa)
return false;
char hexkey[MAX_STRING_SIZE];
int cipher, digest, maclength, compression;
size_t len = rsa_size(myself->connection->rsa);
const size_t len = rsa_size(myself->connection->rsa);
char enckey[len];
char key[len];
@ -513,15 +522,23 @@ bool metakey_h(connection_t *c, const char *request) {
/* Check and lookup cipher and digest algorithms */
if(cipher) {
if(!(c->incipher = cipher_open_by_nid(cipher)) || !cipher_set_key_from_rsa(c->incipher, key, len, false)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error during initialisation of cipher from %s (%s)", c->name, c->hostname);
return false;
}
} else {
c->incipher = NULL;
}
if(digest) {
if(!(c->indigest = digest_open_by_nid(digest, -1))) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error during initialisation of digest from %s (%s)", c->name, c->hostname);
return false;
}
} else {
c->indigest = NULL;
}
c->status.decryptin = true;
@ -531,7 +548,7 @@ bool metakey_h(connection_t *c, const char *request) {
}
bool send_challenge(connection_t *c) {
size_t len = rsa_size(c->rsa);
const size_t len = rsa_size(c->rsa);
char buffer[len * 2 + 1];
if(!c->hischallenge)
@ -551,8 +568,11 @@ bool send_challenge(connection_t *c) {
}
bool challenge_h(connection_t *c, const char *request) {
if(!myself->connection->rsa)
return false;
char buffer[MAX_STRING_SIZE];
size_t len = rsa_size(myself->connection->rsa);
const size_t len = rsa_size(myself->connection->rsa);
size_t digestlen = digest_length(c->indigest);
char digest[digestlen];
@ -628,7 +648,7 @@ bool chal_reply_h(connection_t *c, const char *request) {
}
static bool send_upgrade(connection_t *c) {
/* Special case when protocol_minor is 1: the other end is ECDSA capable,
/* Special case when protocol_minor is 1: the other end is Ed25519 capable,
* but doesn't know our key yet. So send it now. */
char *pubkey = ecdsa_get_base64_public_key(myself->connection->ecdsa);
@ -672,7 +692,8 @@ bool send_ack(connection_t *c) {
if(choice)
c->options |= OPTION_CLAMP_MSS;
get_config_int(lookup_config(c->config_tree, "Weight"), &c->estimated_weight);
if(!get_config_int(lookup_config(c->config_tree, "Weight"), &c->estimated_weight))
get_config_int(lookup_config(config_tree, "Weight"), &c->estimated_weight);
return send_request(c, "%d %s %d %x", ACK, myport, c->estimated_weight, (c->options & 0xffffff) | (experimental ? (PROT_MINOR << 24) : 0));
}
@ -716,12 +737,26 @@ static bool upgrade_h(connection_t *c, const char *request) {
}
if(ecdsa_active(c->ecdsa) || read_ecdsa_public_key(c)) {
logger(DEBUG_ALWAYS, LOG_INFO, "Already have ECDSA public key from %s (%s), not upgrading.", c->name, c->hostname);
char *knownkey = ecdsa_get_base64_public_key(c->ecdsa);
bool different = strcmp(knownkey, pubkey);
free(knownkey);
if(different) {
logger(DEBUG_ALWAYS, LOG_ERR, "Already have an Ed25519 public key from %s (%s) which is different from the one presented now!", c->name, c->hostname);
return false;
}
logger(DEBUG_ALWAYS, LOG_INFO, "Already have Ed25519 public key from %s (%s), ignoring.", c->name, c->hostname);
c->allow_request = TERMREQ;
return send_termreq(c);
}
c->ecdsa = ecdsa_set_base64_public_key(pubkey);
if(!c->ecdsa) {
logger(DEBUG_ALWAYS, LOG_INFO, "Got bad Ed25519 public key from %s (%s), not upgrading.", c->name, c->hostname);
return false;
}
logger(DEBUG_ALWAYS, LOG_INFO, "Got ECDSA public key from %s (%s), upgrading!", c->name, c->hostname);
append_config_file(c->name, "ECDSAPublicKey", pubkey);
logger(DEBUG_ALWAYS, LOG_INFO, "Got Ed25519 public key from %s (%s), upgrading!", c->name, c->hostname);
append_config_file(c->name, "Ed25519PublicKey", pubkey);
c->allow_request = TERMREQ;
return send_termreq(c);
}
@ -795,7 +830,6 @@ bool ack_h(connection_t *c, const char *request) {
/* Activate this connection */
c->allow_request = ALL;
c->status.active = true;
logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection with %s (%s) activated", c->name,
c->hostname);
@ -812,6 +846,16 @@ bool ack_h(connection_t *c, const char *request) {
sockaddr2str(&c->address, &hisaddress, NULL);
c->edge->address = str2sockaddr(hisaddress, hisport);
free(hisaddress);
sockaddr_t local_sa;
socklen_t local_salen = sizeof local_sa;
if (getsockname(c->socket, &local_sa.sa, &local_salen) < 0)
logger(DEBUG_ALWAYS, LOG_WARNING, "Could not get local socket address for connection with %s", c->name);
else {
char *local_address;
sockaddr2str(&local_sa, &local_address, NULL);
c->edge->local_address = str2sockaddr(local_address, myport);
free(local_address);
}
c->edge->weight = (weight + c->estimated_weight) / 2;
c->edge->connection = c;
c->edge->options = c->options;

View file

@ -37,14 +37,19 @@
bool send_add_edge(connection_t *c, const edge_t *e) {
bool x;
char *address, *port;
char *local_address, *local_port;
sockaddr2str(&e->address, &address, &port);
sockaddr2str(&e->local_address, &local_address, &local_port);
x = send_request(c, "%d %x %s %s %s %s %x %d", ADD_EDGE, rand(),
x = send_request(c, "%d %x %s %s %s %s %x %d %s %s", ADD_EDGE, rand(),
e->from->name, e->to->name, address, port,
e->options, e->weight);
e->options, e->weight, local_address, local_port);
free(address);
free(port);
free(local_address);
free(local_port);
return x;
}
@ -56,12 +61,15 @@ bool add_edge_h(connection_t *c, const char *request) {
char to_name[MAX_STRING_SIZE];
char to_address[MAX_STRING_SIZE];
char to_port[MAX_STRING_SIZE];
sockaddr_t address;
char address_local[MAX_STRING_SIZE] = "unknown";
char port_local[MAX_STRING_SIZE] = "unknown";
sockaddr_t address, local_address;
uint32_t options;
int weight;
if(sscanf(request, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %x %d",
from_name, to_name, to_address, to_port, &options, &weight) != 6) {
int parameter_count = sscanf(request, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %x %d "MAX_STRING" "MAX_STRING,
from_name, to_name, to_address, to_port, &options, &weight, address_local, port_local);
if (parameter_count != 6 && parameter_count != 8) {
logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ADD_EDGE", c->name,
c->hostname);
return false;
@ -109,13 +117,14 @@ bool add_edge_h(connection_t *c, const char *request) {
/* Convert addresses */
address = str2sockaddr(to_address, to_port);
local_address = str2sockaddr(address_local, port_local);
/* Check if edge already exists */
e = lookup_edge(from, to);
if(e) {
if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address)) {
if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address) || sockaddrcmp(&e->local_address, &local_address)) {
if(from == myself) {
logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself which does not match existing entry",
"ADD_EDGE", c->name, c->hostname);
@ -145,6 +154,7 @@ bool add_edge_h(connection_t *c, const char *request) {
e->from = from;
e->to = to;
e->address = address;
e->local_address = local_address;
e->options = options;
e->weight = weight;
edge_add(e);

View file

@ -1,7 +1,7 @@
/*
protocol_key.c -- handle the meta-protocol, key exchange
Copyright (C) 1999-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
it under the terms of the GNU General Public License as published by
@ -41,7 +41,7 @@ void send_key_changed(void) {
/* Immediately send new keys to directly connected nodes to keep UDP mappings alive */
for list_each(connection_t, c, connection_list)
if(c->status.active && c->node && c->node->status.reachable && !c->node->status.sptps)
if(c->edge && c->node && c->node->status.reachable && !c->node->status.sptps)
send_ans_key(c->node);
/* Force key exchange for connections using SPTPS */
@ -87,7 +87,7 @@ bool key_changed_h(connection_t *c, const char *request) {
return true;
}
static bool send_initial_sptps_data(void *handle, uint8_t type, const char *data, size_t len) {
static bool send_initial_sptps_data(void *handle, uint8_t type, const void *data, size_t len) {
node_t *to = handle;
to->sptps.send_data = send_sptps_data;
char buf[len * 4 / 3 + 5];
@ -98,7 +98,7 @@ static bool send_initial_sptps_data(void *handle, uint8_t type, const char *data
bool send_req_key(node_t *to) {
if(to->status.sptps) {
if(!node_read_ecdsa_public_key(to)) {
logger(DEBUG_PROTOCOL, LOG_DEBUG, "No ECDSA key known for %s (%s)", to->name, to->hostname);
logger(DEBUG_PROTOCOL, LOG_DEBUG, "No Ed25519 key known for %s (%s)", to->name, to->hostname);
send_request(to->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, to->name, REQ_PUBKEY);
return true;
}
@ -124,6 +124,11 @@ bool send_req_key(node_t *to) {
static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, int reqno) {
switch(reqno) {
case REQ_PUBKEY: {
if(!node_read_ecdsa_public_key(from)) {
/* Request their key *before* we send our key back. Otherwise the first SPTPS packet from them will get dropped. */
logger(DEBUG_PROTOCOL, LOG_DEBUG, "Preemptively requesting Ed25519 key for %s (%s)", from->name, from->hostname);
send_request(from->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, from->name, REQ_PUBKEY);
}
char *pubkey = ecdsa_get_base64_public_key(myself->connection->ecdsa);
send_request(from->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, from->name, ANS_PUBKEY, pubkey);
free(pubkey);
@ -142,14 +147,14 @@ static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, in
return true;
}
logger(DEBUG_PROTOCOL, LOG_INFO, "Learned ECDSA public key from %s (%s)", from->name, from->hostname);
append_config_file(from->name, "ECDSAPublicKey", pubkey);
logger(DEBUG_PROTOCOL, LOG_INFO, "Learned Ed25519 public key from %s (%s)", from->name, from->hostname);
append_config_file(from->name, "Ed25519PublicKey", pubkey);
return true;
}
case REQ_KEY: {
if(!node_read_ecdsa_public_key(from)) {
logger(DEBUG_PROTOCOL, LOG_DEBUG, "No ECDSA key known for %s (%s)", from->name, from->hostname);
logger(DEBUG_PROTOCOL, LOG_DEBUG, "No Ed25519 key known for %s (%s)", from->name, from->hostname);
send_request(from->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, from->name, REQ_PUBKEY);
return true;
}
@ -250,6 +255,7 @@ bool req_key_h(connection_t *c, const char *request) {
return true;
}
/* TODO: forwarding SPTPS packets in this way is inefficient because we send them over TCP without checking for UDP connectivity */
send_request(to->nexthop->connection, "%s", request);
}
@ -260,24 +266,31 @@ bool send_ans_key(node_t *to) {
if(to->status.sptps)
abort();
size_t keylen = cipher_keylength(myself->incipher);
size_t keylen = myself->incipher ? cipher_keylength(myself->incipher) : 1;
char key[keylen * 2 + 1];
randomize(key, keylen);
cipher_close(to->incipher);
digest_close(to->indigest);
if(myself->incipher) {
to->incipher = cipher_open_by_nid(cipher_get_nid(myself->incipher));
to->indigest = digest_open_by_nid(digest_get_nid(myself->indigest), digest_length(myself->indigest));
to->incompression = myself->incompression;
if(!to->incipher || !to->indigest)
if(!to->incipher)
abort();
randomize(key, keylen);
if(!cipher_set_key(to->incipher, key, false))
abort();
}
if(myself->indigest) {
to->indigest = digest_open_by_nid(digest_get_nid(myself->indigest), digest_length(myself->indigest));
if(!to->indigest)
abort();
if(!digest_set_key(to->indigest, key, keylen))
abort();
}
to->incompression = myself->incompression;
bin2hex(key, key, keylen);
@ -386,7 +399,9 @@ bool ans_key_h(connection_t *c, const char *request) {
update_node_udp(from, &sa);
}
if(from->options & OPTION_PMTU_DISCOVERY && !(from->options & OPTION_TCPONLY))
/* Don't send probes if we can't send UDP packets directly to that node.
TODO: the indirect (via) condition can change at any time as edges are added and removed, so this should probably be moved to graph.c. */
if((from->via == myself || from->via == from) && from->options & OPTION_PMTU_DISCOVERY && !(from->options & OPTION_TCPONLY))
send_mtu_probe(from);
}
@ -395,15 +410,23 @@ bool ans_key_h(connection_t *c, const char *request) {
/* Check and lookup cipher and digest algorithms */
if(cipher) {
if(!(from->outcipher = cipher_open_by_nid(cipher))) {
logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown cipher!", from->name, from->hostname);
return false;
}
} else {
from->outcipher = NULL;
}
if(digest) {
if(!(from->outdigest = digest_open_by_nid(digest, maclength))) {
logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown digest!", from->name, from->hostname);
return false;
}
} else {
from->outdigest = NULL;
}
if(maclength != digest_length(from->outdigest)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus MAC length!", from->name, from->hostname);
@ -414,16 +437,16 @@ bool ans_key_h(connection_t *c, const char *request) {
keylen = hex2bin(key, key, sizeof key);
if(keylen != cipher_keylength(from->outcipher)) {
if(keylen != (from->outcipher ? cipher_keylength(from->outcipher) : 1)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name, from->hostname);
return true;
}
/* Update our copy of the origin's packet key */
if(!cipher_set_key(from->outcipher, key, true))
if(from->outcipher && !cipher_set_key(from->outcipher, key, true))
return false;
if(!digest_set_key(from->outdigest, key, keylen))
if(from->outdigest && !digest_set_key(from->outdigest, key, keylen))
return false;
from->status.validkey = true;

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