Import Upstream version 1.1~pre11
This commit is contained in:
parent
60cff3039b
commit
1813f3157e
128 changed files with 10991 additions and 3132 deletions
20
AUTHORS
20
AUTHORS
|
@ -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.
|
||||
|
|
2
COPYING
2
COPYING
|
@ -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
237
ChangeLog
|
@ -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
|
||||
------------------------------------------------------------------------
|
||||
|
||||
|
|
4
INSTALL
4
INSTALL
|
@ -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
|
||||
|
|
18
Makefile.in
18
Makefile.in
|
@ -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
78
NEWS
|
@ -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
17
README
|
@ -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
27
THANKS
|
@ -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
143
aclocal.m4
vendored
|
@ -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
174
config.guess
vendored
|
@ -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
|
||||
|
||||
|
|
33
config.h.in
33
config.h.in
|
@ -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
30
config.sub
vendored
|
@ -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
|
||||
;;
|
||||
|
|
43
configure.ac
43
configure.ac
|
@ -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)]) ])
|
||||
]
|
||||
|
|
|
@ -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@
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
460
doc/tinc.info
460
doc/tinc.info
|
@ -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
|
||||
|
|
169
doc/tinc.texi
169
doc/tinc.texi
|
@ -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
|
||||
|
|
|
@ -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@
|
||||
|
|
35
gui/tinc-gui
35
gui/tinc-gui
|
@ -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)
|
||||
|
|
|
@ -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@
|
||||
|
|
72
m4/ax_check_compile_flag.m4
Normal file
72
m4/ax_check_compile_flag.m4
Normal 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
71
m4/ax_check_link_flag.m4
Normal 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
|
|
@ -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
33
m4/libgcrypt.m4
Normal 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.])]
|
||||
)
|
||||
])
|
|
@ -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>]
|
||||
)
|
||||
|
|
4
missing
4
missing
|
@ -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*)
|
||||
|
|
|
@ -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
|
||||
|
|
373
src/Makefile.in
373
src/Makefile.in
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
103
src/chacha-poly1305/chacha-poly1305.c
Normal file
103
src/chacha-poly1305/chacha-poly1305.c
Normal 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;
|
||||
}
|
15
src/chacha-poly1305/chacha-poly1305.h
Normal file
15
src/chacha-poly1305/chacha-poly1305.h
Normal 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
|
215
src/chacha-poly1305/chacha.c
Normal file
215
src/chacha-poly1305/chacha.c
Normal 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;
|
||||
}
|
||||
}
|
24
src/chacha-poly1305/chacha.h
Normal file
24
src/chacha-poly1305/chacha.h
Normal 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 */
|
197
src/chacha-poly1305/poly1305.c
Normal file
197
src/chacha-poly1305/poly1305.c
Normal 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);
|
||||
}
|
16
src/chacha-poly1305/poly1305.h
Normal file
16
src/chacha-poly1305/poly1305.h
Normal 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 */
|
|
@ -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 *);
|
||||
|
||||
|
|
28
src/conf.c
28
src/conf.c
|
@ -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));
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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
56
src/ed25519/add_scalar.c
Normal 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
51
src/ed25519/ecdh.c
Normal 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
145
src/ed25519/ecdsa.c
Normal 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);
|
||||
}
|
|
@ -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
38
src/ed25519/ed25519.h
Normal 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
1491
src/ed25519/fe.c
Normal file
File diff suppressed because it is too large
Load diff
41
src/ed25519/fe.h
Normal file
41
src/ed25519/fe.h
Normal 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
70
src/ed25519/fixedint.h
Normal 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
467
src/ed25519/ge.c
Normal 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
74
src/ed25519/ge.h
Normal 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
|
79
src/ed25519/key_exchange.c
Normal file
79
src/ed25519/key_exchange.c
Normal 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
16
src/ed25519/keypair.c
Normal 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
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
809
src/ed25519/sc.c
Normal 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
12
src/ed25519/sc.h
Normal 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
275
src/ed25519/sha512.c
Normal 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
21
src/ed25519/sha512.h
Normal 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
31
src/ed25519/sign.c
Normal 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
77
src/ed25519/verify.c
Normal 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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
155
src/event.c
155
src/event.c
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
28
src/graph.c
28
src/graph.c
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef HAVE_MINGW
|
||||
#include <w32api.h>
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
11
src/meta.c
11
src/meta.c
|
@ -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))
|
||||
|
|
|
@ -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 *);
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
24
src/names.c
24
src/names.c
|
@ -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) {
|
||||
|
|
40
src/net.c
40
src/net.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
34
src/net.h
34
src/net.h
|
@ -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__ */
|
||||
|
|
439
src/net_packet.c
439
src/net_packet.c
|
@ -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)) {
|
||||
|
|
389
src/net_setup.c
389
src/net_setup.c
|
@ -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;
|
||||
}
|
||||
|
|
104
src/net_socket.c
104
src/net_socket.c
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
55
src/node.c
55
src/node.c
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue