Commit graph

2531 commits

Author SHA1 Message Date
Etienne Dechamps
b54fde6747 Implement sptps_verify_datagram().
Implementation of sptps_verify_datagram() was left as a TODO. This
causes problems when using SPTPS in tinc, because this function is
used in try_mac(), which itself is used in try_harder() to locate
nodes sending UDP packets from unexpected addresses. In the current
state this function always returns true, resulting in UDP addresses
of random nodes getting changed which makes UDP communication
fragile and unreliable. In addition, this makes UDP communication
impossible through port translation and local discovery.

This commit adds the missing implementation, thus fixing the issue.
2014-06-29 16:48:57 +01:00
Etienne Dechamps
498f1b1d58 Enable LocalDiscovery by default.
Recent improvements to the local discovery mechanism makes it cheaper,
more network-friendly, and now it cannot make things worse (as opposed
to the old mechanism). Thus there is no reason not to enable it by
default.
2014-06-29 11:24:36 +01:00
Etienne Dechamps
4159108971 Remove broadcast-based local discovery mechanism.
The new local address based local discovery mechanism is technically
superior to the old broadcast-based one. In fact, the old algorithm
can technically make things worse by e.g. sending broadcasts over the
VPN itself and then selecting the VPN address as the node's UDP
address. This cannot happen with the new mechanism.

Note that this means old nodes that don't send their local addresses in
ADD_EDGE messages can't be discovered, because there is no address to
send discovery packets to. Old nodes can still discover new nodes by
sending them broadcasts, though.
2014-06-29 11:24:36 +01:00
Etienne Dechamps
e16ade874d Use edge local addresses for local discovery.
This introduces a new way of doing local discovery: when tinc has
local address information for the recipient node, it will send local
discovery packets directly to the local address of that node, instead
of using broadcast packets.

This new way of doing local discovery provides numerous advantages compared to
using broadcasts:

 - No broadcast packets "polluting" the local network;

 - Reliable even if the sending host has multiple network interfaces (in
   contrast, broadcasts will only be sent through one unpredictable
   interface)

 - Works even if the two hosts are not on the same broadcast domain. One
   example is a large LAN where the two hosts might be on different local
   subnets. In fact, thanks to UDP hole punching this might even work if
   there is a NAT sitting in the middle of the LAN between the two nodes!

 - Sometimes a node is reachable through its "normal" address, and via a
   local subnet as well. One might think the local subnet is the best route
   to the node in this case, but more often than not it's actually worse -
   one example is where the local segment is a third party VPN running in
   parallel, or ironically it can be the local segment formed by the tinc
   VPN itself! Because this new algorithm only checks the addresses for
   which an edge is already established, it is less likely to fall into
   these traps.
2014-06-29 11:23:32 +01:00
Etienne Dechamps
bfce56d473 Add local address information to edges.
In addition to the remote address, each edge now stores the local address from
the point of view of the "from" node. This information is then made available
to other nodes through a backwards-compatible extension to ADD_EDGE messages.

This information can be used in future code to improve packet routing.
2014-06-29 11:23:14 +01:00
Guus Sliepen
762db91ef7 Give getsockopt() a reference to a socklen_t. 2014-06-28 21:54:34 +02:00
Guus Sliepen
e57daac63b Merge branch 'winevents-clean' of https://github.com/dechamps/tinc into 1.1 2014-06-28 21:49:55 +02:00
Etienne Dechamps
313a752cb5 Remove the TAP-Win32 reader thread.
tinc is using a separate thread to read from the TAP device on Windows.
The rationale was that the notification mechanism for packets arriving
on the virtual network device is based on Win32 events, and the event
loop did not support listening to these events.

Thanks to recent improvements, this event loop limitation has been
lifted. Therefore we can get rid of the separate thread and simply add
the Win32 "incoming packet" event to the event loop, just like a socket.
The result is cleaner code that's easier to reason about.
2014-06-28 20:00:05 +01:00
Etienne Dechamps
ffbc99558c Use a Windows event to stop tinc when running as a service.
Currently, when the tinc service handler callback (which runs in a
separate thread) receives a service shutdown request, it calls
event_exit() to request the event loop to exit.

This approach has a few issues:

 - The event loop will only notice the exit request when the next event
   fires. This slows down tinc service shutdown. In some extreme cases
   (DeviceStandby enabled, long PingTimeout and no connections),
   shutdown can take ages.

 - Strictly speaking, because of the absence of memory barriers, there
   is no guarantee that the event loop will even notice an exit request
   coming from another thread. I suppose marking the "running" variable
   as "volatile" is supposed to alleviate that, but it's unclear whether
   that provides any guarantees with modern systems and compilers.

This commit fixes the issue by leveraging the new event loop Windows
interface, using a custom Windows event that is manually set when
shutdown is requested.
2014-06-28 20:00:05 +01:00
Etienne Dechamps
2f9a1d4ab5 Make the event loop expose a Windows event interface.
This allows event loop users to specify Win32 events to wait on,
thus making the event loop more flexible.
2014-06-28 20:00:01 +01:00
Etienne Dechamps
611217c96e Use native Windows events for the event loop.
This commit changes the event loop to use WSAEventSelect() and
WSAWaitForMultipleEvents() on Windows. This paves the way for making the
event loop more flexible on Windows by introducing the required
infrastructure to make the event loop wait on any Win32 event.

This commit only affects the internal implementation of the event
module. Externally visible behavior remains strictly unchanged (for
now).
2014-06-28 18:45:13 +01:00
Etienne Dechamps
cc284e7c5d Fix connection event error handling.
Commit 86a99c6b99 changed the way we
handle connection events to protect against spurious event loop
callbacks. Unfortunately, it turns out that calling connect() twice on
the same socket results in different behaviors depending on the platform
(even though it seems well defined in POSIX). On Windows this resulted
in the connection handling code being unable to react to connection
errors (such as connection refused), always hitting the timeout; on
Linux this resulted in spurious error messages about connect() returning
success.

In POSIX and on Linux, using connect() on a socket where the previous
attempt failed will attempt to connect again, resulting in unnecessary
network activity. Using getsockopt(SO_ERROR) before connect() solves
that, but introduces a race condition if a connection failure happens
between the two calls.

For this reason, this commit switches from connect() to a zero-sized
send() call, which is more consistent (though not completely, see the
truth table in the comments) and simpler to use for that purpose. Note
that Windows explictly support empty send() calls; POSIX says nothing
on the subject, but testing shows it works at least on Linux.

(Surprisingly enough, Windows seems more POSIX-compliant than Linux on
this one!)
2014-06-28 14:04:43 +01:00
Etienne Dechamps
86a99c6b99 Protect against spurious connection events.
The event loop does not guarantee that spurious write I/O events do not
happen; in fact, they are guaranteed to happen on Windows when
event_flush_output() is called. Because handle_meta_io() does not check
for spurious events, a metaconnection socket might appear connected even
though it's not, and will fail immediately when sending the ID request.

This commit fixes this issue by making handle_meta_io() check the
connection status before assuming the socket is connected. It seems that
the only reliable way to do that is to try to call connect() again and
look at the error code, which will be EISCONN if the socket is
connected, or EALREADY if it's not.
2014-06-27 19:39:30 +01:00
Etienne Dechamps
0c026f3c6d Fix errno references when handling socket errors.
When using socket functions, "sockerrno" is supposed to be used to
retrieve the error code as opposed to "errno", so that it is translated
to the correct call on Windows (WSAGetLastError() - Windows does not
update errno on socket errors). Unfortunately, the use of sockerrno is
inconsistent throughout the tinc codebase, as errno is often used
incorrectly on socket-related calls.

This commit fixes these oversights, which improves socket error
handling on Windows.
2014-06-26 20:42:40 +01:00
Etienne Dechamps
058473dc8d Fix Windows includes.
These Windows include lines are capitalized, which causes the build to fail
when cross-compiling from Linux to Windows using MinGW as the MinGW headers
are entirely lower case.
2014-06-22 18:45:49 +01:00
Guus Sliepen
b24faf3cbe Remove the warnings when IP_DONTFRAGMENT/IPV6-DONTFRAG is not supported.
There is nothing we can do about it, and tinc will run fine anyway.
2014-06-22 17:22:15 +02:00
Alexis Hildebrandt
b99e1a306c Add support to link against libresolv Mac OS X 2014-06-22 17:21:23 +02:00
Armin Fisslthaler
e76df30cb2 reload /etc/resolv.conf in SIGALRM handler 2014-06-22 17:20:55 +02:00
Etienne Dechamps
132bdb77a0 Make DeviceStandby control network interface link status on Windows.
Besides controlling when tinc-up and tinc-down get called, this commit makes
DeviceStandby control when the virtual network interface "cable" is "plugged"
on Windows. This is more user-friendly as the status of the tinc network can
be seen just by looking at the state of the network interface, and it makes
Windows behave better when isolated.
2014-06-22 15:04:15 +01:00
Etienne Dechamps
bd451cfe15 Add DeviceStandby option to only enable the device when nodes are reachable.
This adds a new DeviceStandby option; when it is disabled (the default),
behavior is unchanged. If it is enabled, tinc-up will not be called during
tinc initialization, but will instead be deferred until the first node is
reachable, and it will be closed as soon as no nodes are reachable.

This is useful because it means the device won't be set up until we are fairly
sure there is something listening on the other side. This is more user-friendly,
as one can check on the status of the tinc network connection just by checking
the status of the network interface. Besides, it prevents the OS from thinking
it is connected to some network when it is in fact completely isolated.
2014-06-22 15:04:15 +01:00
Etienne Dechamps
f0885b8d2f Cleanly remove the device FD from the event loop before closing it. 2014-06-22 15:03:53 +01:00
Etienne Dechamps
ed1d0878af Make device close cleaner. 2014-06-22 14:01:30 +02:00
Etienne Dechamps
6382608653 Move Solaris if_fd to local scope.
This variable is never used outside of setup_device(), therefore there is no
reason to declare it in global scope.
2014-06-22 14:01:01 +02:00
Baptiste Jonglez
9bfc228ef5 Clarify man page regarding the IndirectData option 2014-06-20 09:38:00 +02:00
Guus Sliepen
31c6899398 Unconditionally return non-zero exit code when "tinc del" does not find the requested variable. 2014-06-15 12:19:10 +02:00
Guus Sliepen
1ce0f76139 Return non-zero exit code when "tinc get" does not find the requested variable. 2014-06-15 12:14:01 +02:00
Guus Sliepen
ef5e8b6920 Fix base64 decoding of Ed25519 keys. 2014-06-03 11:02:58 +02:00
Guus Sliepen
b0d80c7f28 Allow Cipher and Digest "none".
This is for backwards compatibility with tinc 1.0, it has no effect on
the SPTPS protocol.
2014-05-18 21:51:42 +02:00
Guus Sliepen
666718998e Implement a PEM-like format for Ed25519 keys.
We don't require compatibility with any other software, but we do want Ed25519 keys to work
the same as RSA keys for now.
2014-05-18 20:49:35 +02:00
Guus Sliepen
f0e7e6b03e Rename ECDSA to Ed25519. 2014-05-18 20:47:04 +02:00
Guus Sliepen
35437a50e2 Add sanity checks when generating new RSA keys.
The key size should be a multiple of 8 bits, and it should be between 1024 and
8192 bits.
2014-05-13 20:33:20 +02:00
Guus Sliepen
66f325f467 Fix PMTU discovery via datagram SPTPS.
In send_sptps_data(), the len variable contains the length of the whole
datagram that needs to be sent to the peer, including the overhead from SPTPS
itself.
2014-05-12 15:57:40 +02:00
Guus Sliepen
c35bfa18ec Fix a crash when we have a malformed public ECDSA key of another node. 2014-05-12 15:56:29 +02:00
Guus Sliepen
c32fcdfc1d Add missing closedir(). 2014-05-12 14:35:56 +02:00
Guus Sliepen
75e5b2e906 Use void pointers to opaque buffers. 2014-05-12 14:35:12 +02:00
Guus Sliepen
332b55d472 Change AutoConnect from int to bool.
The proper value is 3, not 2 or 4, and 5 is right out. So just hardcode this value,
and only have the option to turn AutoConnect on or off.
2014-05-06 14:11:55 +02:00
Guus Sliepen
27acb5d047 Fix compiler warnings. 2014-05-06 13:01:48 +02:00
Guus Sliepen
bc33a073d8 Nexthop calculation should always use the shortest path.
When tinc runs the graph algorithms and updates the nexthop and via pointers,
it uses a breadth-first search, but it can sometimes revisit nodes that have
already been visited if the previous path is marked as being indirect, and
there is a longer path that is "direct". The via pointer should be updated in
this case, because this points to the closest hop to the destination that can
be reached directly. However, the nexthop pointer should not be updated.

This fixes a bug where there could potentially be a routing loop if a node in
the graph has an edge with the indirect flag set, and some other edge without
that flag, the indirect edge is part of the minimum spanning tree, and a
broadcast packet is being sent.
2014-05-06 12:58:25 +02:00
Saverio Proto
b6e2b416bf Fix typo in comment 2014-05-05 15:23:25 +02:00
Guus Sliepen
18698c4e12 Put brackets around IPv6 addresses in invitation URL, even if there is no port number. 2014-04-25 17:00:55 +02:00
Guus Sliepen
475088ed77 sptps_test: allow using a tun device instead of stdio. 2014-04-15 17:26:08 +02:00
Guus Sliepen
2980173ee7 Use the ChaCha-Poly1305 cipher for the SPTPS protocol.
The main reason to switch from AES-256-GCM to ChaCha-Poly1305 is to remove a
dependency on OpenSSL, whose behaviour of the AES-256-GCM decryption function
changes between versions. The source code for ChaCha-Pol1305 is small and in
the public domain, and can therefore be easily included in tinc itself.
Moreover, it is very fast even without using any optimized assembler, easily
outperforming AES-256-GCM on platforms that don't have special AES instructions
in hardware.
2014-04-14 21:43:45 +02:00
Guus Sliepen
49e3baec20 Merge branch '1.1-ed25519' into 1.1 2014-04-14 20:50:16 +02:00
Guus Sliepen
37b729d7fd Properly initialize buffers.
Valgrind complained about use of uninitialized data.
2014-04-13 12:09:48 +02:00
Guus Sliepen
2f01744f82 Use Ed25519 keys.
This uses the portable Ed25519 library made by Orson Peters, which in turn uses
the reference implementation made by Daniel J. Bernstein.

This implementation also allows Ed25519 keys to be used for key exchange, so
there is no need to add a separate implementation of Curve25519.
2014-04-06 22:47:26 +02:00
Guus Sliepen
d6734a2da4 Fix return value of b64encode(). 2014-04-06 22:46:06 +02:00
Guus Sliepen
f134bd0c9c Handle a disconnecting tincd better.
- Try to prevent SIGPIPE from being sent for errors sending to the control
  socket. We don't outright block the SIGPIPE signal because we still want the
  tinc CLI to exit when its output is actually sent to a real (broken) pipe.

- Don't call exit() from top(), and properly detect when the control socket is
  closed by the tincd.
2014-03-09 15:32:10 +01:00
Guus Sliepen
09e000ba54 Rewind the file before trying to use PEM_read_RSA_PUBKEY(). 2014-02-26 17:27:57 +01:00
Guus Sliepen
44c7f554c7 Add "network" command to list or switch networks. 2014-02-26 11:04:42 +01:00
Guus Sliepen
48ecff6ddb Add missing attribution for 1.1pre10 to the NEWS file. 2014-02-07 23:06:26 +01:00