Import Upstream version 1.0.11
This commit is contained in:
parent
fa871d431d
commit
23bd9e9d53
28 changed files with 343 additions and 107 deletions
139
ChangeLog
139
ChangeLog
|
@ -1,3 +1,142 @@
|
|||
commit 44834d030464bbe1f7733caba8d96c678f1d6cf2
|
||||
Author: Guus Sliepen <guus@tinc-vpn.org>
|
||||
Date: Sun Nov 1 16:24:39 2009 +0100
|
||||
|
||||
Releasing 1.0.11.
|
||||
|
||||
commit d331f04e4598824afc7de33ac1228cf441ae9872
|
||||
Author: Guus Sliepen <guus@tinc-vpn.org>
|
||||
Date: Sun Nov 1 15:57:28 2009 +0100
|
||||
|
||||
Start a tinc service if it already exists.
|
||||
|
||||
commit 6f6f426b353596edca77829c0477268fc2fc1925
|
||||
Author: Guus Sliepen <guus@tinc-vpn.org>
|
||||
Date: Tue Oct 27 23:53:49 2009 +0100
|
||||
|
||||
Fast handoff of roaming MAC addresses.
|
||||
|
||||
In switch mode, if a known MAC address is claimed by a second node before it
|
||||
expired at the first node, it is likely that this is because a computer has
|
||||
roamed from the LAN of the first node to that of the second node. To ensure
|
||||
packets for that computer are routed to the second node, the first node should
|
||||
delete its corresponding Subnet as soon as possible, without waiting for the
|
||||
normal expiry timeout.
|
||||
|
||||
commit e00b44cb98e4d50a0d426048ba01dbd80bcb5941
|
||||
Author: Guus Sliepen <guus@tinc-vpn.org>
|
||||
Date: Sun Oct 25 01:40:07 2009 +0200
|
||||
|
||||
Move socket error interpretation to utils.h.
|
||||
|
||||
commit c11dc8079b60d9f8c5b1c7e8fecd90d0fac5a20c
|
||||
Author: Guus Sliepen <guus@tinc-vpn.org>
|
||||
Date: Sun Oct 25 00:50:09 2009 +0200
|
||||
|
||||
Use WSAGetLastError() to determine cause of network errors on Windows.
|
||||
|
||||
This reduces log spam and lets path MTU discovery work faster.
|
||||
|
||||
commit 1bca167b7e24a9cb00ad6130c24f0bb60e208f1f
|
||||
Author: Michael Tokarev <mjt@tls.msk.ru>
|
||||
Date: Sun Oct 18 21:27:24 2009 +0400
|
||||
|
||||
Remove localedir leftovers.
|
||||
|
||||
commit c3acae034c4da2d1c70f31b852b14ca098c0eeb9
|
||||
Author: Guus Sliepen <guus@tinc-vpn.org>
|
||||
Date: Sat Oct 24 22:32:35 2009 +0200
|
||||
|
||||
Use IP_DONTFRAGMENT instead of IP_MTU_DISCOVER on Windows.
|
||||
|
||||
This ensures the DF bit on outgoing UDP packets gets set on Windows when path
|
||||
MTU discovery is enabled, reducing fragmentation.
|
||||
|
||||
commit 242c4e2ca67d0b5c78dfe6e68a5ddcd27be1de99
|
||||
Author: Guus Sliepen <guus@tinc-vpn.org>
|
||||
Date: Sat Oct 24 21:53:01 2009 +0200
|
||||
|
||||
Forward packets to not directly reachable hosts via UDP if possible.
|
||||
|
||||
If MTU probing discovered a node was not reachable via UDP, packets for it were
|
||||
forwarded to the next hop, but always via TCP, even if the next hop was
|
||||
reachable via UDP. This is now fixed by retrying to send the packet using
|
||||
send_packet() if the destination is not the same as the nexthop.
|
||||
|
||||
commit d922db253cd098bc038449e5c591cc94c1019952
|
||||
Author: Guus Sliepen <guus@tinc-vpn.org>
|
||||
Date: Sat Oct 24 21:35:40 2009 +0200
|
||||
|
||||
Make maxmtu equal to minmtu when fixing the path MTU to a node.
|
||||
|
||||
This ensures MTU probes used to ping nodes are not too large, and prevents
|
||||
restarting MTU probing unnecessarily.
|
||||
|
||||
commit a8f7fccbc2b5f1c4c39fc2804abaa358b31a5080
|
||||
Author: Guus Sliepen <guus@tinc-vpn.org>
|
||||
Date: Sat Oct 24 21:32:06 2009 +0200
|
||||
|
||||
Always reply to MTU probes via UDP.
|
||||
|
||||
It could sometime happen that a node would return MTU probes via TCP, which
|
||||
does not make a lot of sense.
|
||||
|
||||
commit cddcdc9af34afb388a8e4bdfff6882f568b98313
|
||||
Author: Guus Sliepen <guus@tinc-vpn.org>
|
||||
Date: Sat Oct 24 20:54:44 2009 +0200
|
||||
|
||||
Allow UDP packets with an address different from the corresponding TCP connection.
|
||||
|
||||
commit 5cbddc68bade0d1f8ded1b784bb27bb44c5dc5dc
|
||||
Author: Guus Sliepen <guus@tinc-vpn.org>
|
||||
Date: Sat Oct 24 16:15:24 2009 +0200
|
||||
|
||||
Use uint32_t instead of long int for connection options.
|
||||
|
||||
Options should have a fixed width anyway, but this also fixes a possible MinGW
|
||||
compiler bug where %lx tries to print a 64 bit value, even though a long int is
|
||||
only 32 bits.
|
||||
|
||||
commit 468f393c4fabf9223a1bd15adfb3906cde90d547
|
||||
Author: Guus Sliepen <guus@tinc-vpn.org>
|
||||
Date: Sat Oct 24 16:05:12 2009 +0200
|
||||
|
||||
Add dummy device.
|
||||
|
||||
commit b6543af7626403516b5fc54c24b11d3a242a2992
|
||||
Author: Guus Sliepen <guus@tinc-vpn.org>
|
||||
Date: Tue Oct 20 22:39:07 2009 +0200
|
||||
|
||||
Clarify and increase level of log message about MTU probes to unreachable nodes.
|
||||
|
||||
commit 43a6e786648fb666a9b7be8f05c8a173031c9110
|
||||
Author: Guus Sliepen <guus@tinc-vpn.org>
|
||||
Date: Tue Oct 20 22:33:16 2009 +0200
|
||||
|
||||
Handle weighted Subnets in switch and hub modes.
|
||||
|
||||
We now handle MAC Subnets in exactly the same way as IPv4 and IPv6 Subnets.
|
||||
This also fixes a problem that causes unncessary broadcasting of unicast
|
||||
packets in VPNs where some daemons run 1.0.10 and some run other versions.
|
||||
|
||||
commit 3a925479c2883a6a9711f7b6931863d7f2a2c09b
|
||||
Author: Guus Sliepen <guus@tinc-vpn.org>
|
||||
Date: Tue Oct 20 22:22:59 2009 +0200
|
||||
|
||||
Starting to work towards 1.0.11.
|
||||
|
||||
commit 35af4051c3749cd2c2137a7eb57171a1fbb12af7
|
||||
Author: Guus Sliepen <guus@tinc-vpn.org>
|
||||
Date: Tue Oct 20 22:14:47 2009 +0200
|
||||
|
||||
Fix a possible crash when sending the HUP signal.
|
||||
|
||||
When the HUP signal is sent while some outgoing connections have not been made
|
||||
yet, or are being retried, a NULL pointer could be dereferenced resulting in
|
||||
tinc crashing. We fix this by more careful handling of outgoing_ts, and by
|
||||
deleting all connections that have not been fully activated yet at the HUP
|
||||
signal is received.
|
||||
|
||||
commit 8c267d3d558ac97a4ce7381a37abb6cc4b46b133
|
||||
Author: Guus Sliepen <guus@tinc-vpn.org>
|
||||
Date: Sun Oct 18 16:45:13 2009 +0200
|
||||
|
|
17
NEWS
17
NEWS
|
@ -1,3 +1,20 @@
|
|||
Version 1.0.11 Nov 1 2009
|
||||
|
||||
* Fixed potential crash when the HUP signal is sent.
|
||||
|
||||
* Fixes handling of weighted Subnets in switch and hub modes, preventing
|
||||
unnecessary broadcasts.
|
||||
|
||||
* Works around a MinGW bug that caused packets to Windows nodes to always be
|
||||
sent via TCP.
|
||||
|
||||
* Improvements to the PMTU discovery code, especially on Windows.
|
||||
|
||||
* Use UDP again in certain cases where 1.0.10 was too conservative and fell
|
||||
back to TCP unnecessarily.
|
||||
|
||||
* Allow fast roaming of hosts to other nodes in a switched VPN.
|
||||
|
||||
Version 1.0.10 Oct 18 2009
|
||||
|
||||
* Fixed potential crashes during shutdown and (in rare conditions) when other
|
||||
|
|
4
README
4
README
|
@ -1,4 +1,4 @@
|
|||
This is the README file for tinc version 1.0.10. Installation
|
||||
This is the README file for tinc version 1.0.11. Installation
|
||||
instructions may be found in the INSTALL file.
|
||||
|
||||
tinc is Copyright (C) 1998-2009 by:
|
||||
|
@ -55,7 +55,7 @@ should be changed into "Device", and "Device" should be changed into
|
|||
Compatibility
|
||||
-------------
|
||||
|
||||
Version 1.0.10 is compatible with 1.0pre8, 1.0 and later, but not with older
|
||||
Version 1.0.11 is compatible with 1.0pre8, 1.0 and later, but not with older
|
||||
versions of tinc.
|
||||
|
||||
|
||||
|
|
2
configure
vendored
2
configure
vendored
|
@ -2701,7 +2701,7 @@ fi
|
|||
|
||||
# Define the identity of the package.
|
||||
PACKAGE=tinc
|
||||
VERSION=1.0.10
|
||||
VERSION=1.0.11
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
|
|
|
@ -3,7 +3,7 @@ dnl Process this file with autoconf to produce a configure script.
|
|||
AC_PREREQ(2.61)
|
||||
AC_INIT
|
||||
AC_CONFIG_SRCDIR([src/tincd.c])
|
||||
AM_INIT_AUTOMAKE(tinc, 1.0.10)
|
||||
AM_INIT_AUTOMAKE(tinc, 1.0.11)
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ START-INFO-DIR-ENTRY
|
|||
* tinc: (tinc). The tinc Manual.
|
||||
END-INFO-DIR-ENTRY
|
||||
|
||||
This is the info manual for tinc version 1.0.10, a Virtual Private
|
||||
This is the info manual for tinc version 1.0.11, a Virtual Private
|
||||
Network daemon.
|
||||
|
||||
Copyright (C) 1998-2009 Ivo Timmermans, Guus Sliepen
|
||||
|
|
11
lib/utils.h
11
lib/utils.h
|
@ -27,6 +27,17 @@ extern void bin2hex(char *src, char *dst, int length);
|
|||
#ifdef HAVE_MINGW
|
||||
extern const char *winerror(int);
|
||||
#define strerror(x) ((x)>0?strerror(x):winerror(GetLastError()))
|
||||
#define sockerrno WSAGetLastError()
|
||||
#define sockstrerror(x) winerror(x)
|
||||
#define sockwouldblock(x) ((x) == WSAEWOULDBLOCK || (x) == WSAEINTR)
|
||||
#define sockmsgsize(x) ((x) == WSAEMSGSIZE)
|
||||
#define sockinprogress(x) ((x) == WSAEINPROGRESS || (x) == WSAEWOULDBLOCK)
|
||||
#else
|
||||
#define sockerrno errno
|
||||
#define sockstrerror(x) strerror(x)
|
||||
#define sockwouldblock(x) ((x) == EWOULDBLOCK || (x) == EINTR)
|
||||
#define sockmsgsize(x) ((x) == EMSGSIZE)
|
||||
#define sockinprogress(x) ((x) == EINPROGRESS)
|
||||
#endif
|
||||
|
||||
extern unsigned int bitfield_to_int(void *bitfield, size_t size);
|
||||
|
|
|
@ -30,9 +30,7 @@ endif
|
|||
tincd_LDADD = \
|
||||
$(top_builddir)/lib/libvpn.a
|
||||
|
||||
localedir = $(datadir)/locale
|
||||
|
||||
AM_CFLAGS = @CFLAGS@ -DCONFDIR=\"$(sysconfdir)\" -DLOCALEDIR=\"$(localedir)\" -DLOCALSTATEDIR=\"$(localstatedir)\"
|
||||
AM_CFLAGS = @CFLAGS@ -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\"
|
||||
|
||||
dist-hook:
|
||||
rm -f `find . -type l`
|
||||
|
|
|
@ -166,7 +166,7 @@ infodir = @infodir@
|
|||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = $(datadir)/locale
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
|
@ -197,7 +197,7 @@ noinst_HEADERS = conf.h connection.h device.h edge.h event.h graph.h logger.h me
|
|||
tincd_LDADD = \
|
||||
$(top_builddir)/lib/libvpn.a
|
||||
|
||||
AM_CFLAGS = @CFLAGS@ -DCONFDIR=\"$(sysconfdir)\" -DLOCALEDIR=\"$(localedir)\" -DLOCALSTATEDIR=\"$(localstatedir)\"
|
||||
AM_CFLAGS = @CFLAGS@ -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\"
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
|
|
|
@ -120,7 +120,7 @@ void dump_connections(void) {
|
|||
|
||||
for(node = connection_tree->head; node; node = node->next) {
|
||||
c = node->data;
|
||||
logger(LOG_DEBUG, " %s at %s options %lx socket %d status %04x outbuf %d/%d/%d",
|
||||
logger(LOG_DEBUG, " %s at %s options %x socket %d status %04x outbuf %d/%d/%d",
|
||||
c->name, c->hostname, c->options, c->socket, bitfield_to_int(&c->status, sizeof c->status),
|
||||
c->outbufsize, c->outbufstart, c->outbuflen);
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ typedef struct connection_t {
|
|||
int protocol_version; /* used protocol */
|
||||
|
||||
int socket; /* socket used for this connection */
|
||||
long int options; /* options for this connection */
|
||||
uint32_t options; /* options for this connection */
|
||||
connection_status_t status; /* status info */
|
||||
int estimated_weight; /* estimation for the weight of the edge for this connection */
|
||||
struct timeval start; /* time this connection was started, used for above estimation */
|
||||
|
|
|
@ -118,7 +118,7 @@ void dump_edges(void) {
|
|||
for(node2 = n->edge_tree->head; node2; node2 = node2->next) {
|
||||
e = node2->data;
|
||||
address = sockaddr2hostname(&e->address);
|
||||
logger(LOG_DEBUG, " %s to %s at %s options %lx weight %d",
|
||||
logger(LOG_DEBUG, " %s to %s at %s options %x weight %d",
|
||||
e->from->name, e->to->name, address, e->options, e->weight);
|
||||
free(address);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ typedef struct edge_t {
|
|||
struct node_t *to;
|
||||
sockaddr_t address;
|
||||
|
||||
long int options; /* options turned on for this edge */
|
||||
uint32_t options; /* options turned on for this edge */
|
||||
int weight; /* weight of this edge */
|
||||
|
||||
struct connection_t *connection; /* connection associated with this edge, if available */
|
||||
|
|
|
@ -27,7 +27,7 @@ extern avl_tree_t *event_tree;
|
|||
|
||||
typedef void (*event_handler_t)(void *);
|
||||
|
||||
typedef struct {
|
||||
typedef struct event {
|
||||
time_t time;
|
||||
int id;
|
||||
event_handler_t handler;
|
||||
|
|
10
src/meta.c
10
src/meta.c
|
@ -94,15 +94,13 @@ bool flush_meta(connection_t *c) {
|
|||
c->name, c->hostname);
|
||||
} else if(errno == EINTR) {
|
||||
continue;
|
||||
#ifdef EWOULDBLOCK
|
||||
} else if(errno == EWOULDBLOCK) {
|
||||
} else if(sockwouldblock(sockerrno)) {
|
||||
ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Flushing %d bytes to %s (%s) would block",
|
||||
c->outbuflen, c->name, c->hostname);
|
||||
return true;
|
||||
#endif
|
||||
} else {
|
||||
logger(LOG_ERR, "Flushing meta data to %s (%s) failed: %s", c->name,
|
||||
c->hostname, strerror(errno));
|
||||
c->hostname, sockstrerror(sockerrno));
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -149,11 +147,11 @@ bool receive_meta(connection_t *c) {
|
|||
if(!lenin || !errno) {
|
||||
ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Connection closed by %s (%s)",
|
||||
c->name, c->hostname);
|
||||
} else if(errno == EINTR)
|
||||
} else if(sockwouldblock(sockerrno))
|
||||
return true;
|
||||
else
|
||||
logger(LOG_ERR, "Metadata socket read error for %s (%s): %s",
|
||||
c->name, c->hostname, strerror(errno));
|
||||
c->name, c->hostname, sockstrerror(sockerrno));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
34
src/net.c
34
src/net.c
|
@ -303,7 +303,7 @@ static void check_network_activity(fd_set * readset, fd_set * writeset) {
|
|||
else {
|
||||
ifdebug(CONNECTIONS) logger(LOG_DEBUG,
|
||||
"Error while connecting to %s (%s): %s",
|
||||
c->name, c->hostname, strerror(result));
|
||||
c->name, c->hostname, sockstrerror(result));
|
||||
closesocket(c->socket);
|
||||
do_outgoing_connection(c);
|
||||
continue;
|
||||
|
@ -369,9 +369,8 @@ int main_loop(void) {
|
|||
#endif
|
||||
|
||||
if(r < 0) {
|
||||
if(errno != EINTR && errno != EAGAIN) {
|
||||
logger(LOG_ERR, "Error while waiting for input: %s",
|
||||
strerror(errno));
|
||||
if(!sockwouldblock(sockerrno)) {
|
||||
logger(LOG_ERR, "Error while waiting for input: %s", sockstrerror(sockerrno));
|
||||
dump_connections();
|
||||
return 1;
|
||||
}
|
||||
|
@ -431,7 +430,7 @@ int main_loop(void) {
|
|||
|
||||
if(sighup) {
|
||||
connection_t *c;
|
||||
avl_node_t *node;
|
||||
avl_node_t *node, *next;
|
||||
char *fname;
|
||||
struct stat s;
|
||||
|
||||
|
@ -447,6 +446,31 @@ int main_loop(void) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Cancel non-active outgoing connections */
|
||||
|
||||
for(node = connection_tree->head; node; node = next) {
|
||||
next = node->next;
|
||||
c = node->data;
|
||||
|
||||
c->outgoing = NULL;
|
||||
|
||||
if(c->status.connecting) {
|
||||
terminate_connection(c, false);
|
||||
connection_del(c);
|
||||
}
|
||||
}
|
||||
|
||||
/* Wipe list of outgoing connections */
|
||||
|
||||
for(list_node_t *node = outgoing_list->head; node; node = node->next) {
|
||||
outgoing_t *outgoing = node->data;
|
||||
|
||||
if(outgoing->event)
|
||||
event_del(outgoing->event);
|
||||
}
|
||||
|
||||
list_delete_list(outgoing_list);
|
||||
|
||||
/* Close connections to hosts that have a changed or deleted host config file */
|
||||
|
||||
for(node = connection_tree->head; node; node = node->next) {
|
||||
|
|
|
@ -98,6 +98,7 @@ typedef struct outgoing_t {
|
|||
struct config_t *cfg;
|
||||
struct addrinfo *ai;
|
||||
struct addrinfo *aip;
|
||||
struct event *event;
|
||||
} outgoing_t;
|
||||
|
||||
extern list_t *outgoing_list;
|
||||
|
|
|
@ -46,10 +46,6 @@
|
|||
#include "utils.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
#ifdef WSAEMSGSIZE
|
||||
#define EMSGSIZE WSAEMSGSIZE
|
||||
#endif
|
||||
|
||||
int keylifetime = 0;
|
||||
int keyexpires = 0;
|
||||
static char lzo_wrkmem[LZO1X_999_MEM_COMPRESS > LZO1X_1_MEM_COMPRESS ? LZO1X_999_MEM_COMPRESS : LZO1X_1_MEM_COMPRESS];
|
||||
|
@ -72,7 +68,7 @@ void send_mtu_probe(node_t *n) {
|
|||
n->mtuevent = NULL;
|
||||
|
||||
if(!n->status.reachable || !n->status.validkey) {
|
||||
logger(LOG_DEBUG, "Trying to send MTU probe to unreachable node %s (%s)", n->name, n->hostname);
|
||||
ifdebug(TRAFFIC) logger(LOG_INFO, "Trying to send MTU probe to unreachable or rekeying node %s (%s)", n->name, n->hostname);
|
||||
n->mtuprobes = 0;
|
||||
return;
|
||||
}
|
||||
|
@ -91,6 +87,10 @@ void send_mtu_probe(node_t *n) {
|
|||
}
|
||||
|
||||
if(n->mtuprobes == 30 || (n->mtuprobes < 30 && n->minmtu >= n->maxmtu)) {
|
||||
if(n->minmtu > n->maxmtu)
|
||||
n->minmtu = n->maxmtu;
|
||||
else
|
||||
n->maxmtu = n->minmtu;
|
||||
n->mtu = n->minmtu;
|
||||
ifdebug(TRAFFIC) logger(LOG_INFO, "Fixing MTU of %s (%s) to %d after %d probes", n->name, n->hostname, n->mtu, n->mtuprobes);
|
||||
n->mtuprobes = 31;
|
||||
|
@ -135,7 +135,7 @@ void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) {
|
|||
|
||||
if(!packet->data[0]) {
|
||||
packet->data[0] = 1;
|
||||
send_packet(n, packet);
|
||||
send_udppacket(n, packet);
|
||||
} else {
|
||||
if(len > n->maxmtu)
|
||||
len = n->maxmtu;
|
||||
|
@ -365,10 +365,13 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
|
|||
|
||||
if(n->options & OPTION_PMTU_DISCOVERY && inpkt->len > n->minmtu && (inpkt->data[12] | inpkt->data[13])) {
|
||||
ifdebug(TRAFFIC) logger(LOG_INFO,
|
||||
"Packet for %s (%s) larger than minimum MTU, forwarding via TCP",
|
||||
n->name, n->hostname);
|
||||
"Packet for %s (%s) larger than minimum MTU, forwarding via %s",
|
||||
n->name, n->hostname, n != n->nexthop ? n->nexthop->name : "TCP");
|
||||
|
||||
send_tcppacket(n->nexthop->connection, origpkt);
|
||||
if(n != n->nexthop)
|
||||
send_packet(n->nexthop, origpkt);
|
||||
else
|
||||
send_tcppacket(n->nexthop->connection, origpkt);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -442,14 +445,14 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
|
|||
}
|
||||
#endif
|
||||
|
||||
if((sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, &(n->address.sa), SALEN(n->address.sa))) < 0) {
|
||||
if(errno == EMSGSIZE) {
|
||||
if(sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, &(n->address.sa), SALEN(n->address.sa)) < 0 && !sockwouldblock(sockerrno)) {
|
||||
if(sockmsgsize(sockerrno)) {
|
||||
if(n->maxmtu >= origlen)
|
||||
n->maxmtu = origlen - 1;
|
||||
if(n->mtu >= origlen)
|
||||
n->mtu = origlen - 1;
|
||||
} else
|
||||
logger(LOG_ERR, "Error sending packet to %s (%s): %s", n->name, n->hostname, strerror(errno));
|
||||
logger(LOG_ERR, "Error sending packet to %s (%s): %s", n->name, n->hostname, sockstrerror(sockerrno));
|
||||
}
|
||||
|
||||
end:
|
||||
|
@ -521,12 +524,16 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) {
|
|||
avl_node_t *node;
|
||||
edge_t *e;
|
||||
node_t *n = NULL;
|
||||
static time_t last_hard_try = 0;
|
||||
|
||||
for(node = edge_weight_tree->head; node; node = node->next) {
|
||||
e = node->data;
|
||||
|
||||
if(sockaddrcmp_noport(from, &e->address))
|
||||
continue;
|
||||
if(sockaddrcmp_noport(from, &e->address)) {
|
||||
if(last_hard_try == now)
|
||||
continue;
|
||||
last_hard_try = now;
|
||||
}
|
||||
|
||||
if(!n)
|
||||
n = e->to;
|
||||
|
@ -551,8 +558,8 @@ void handle_incoming_vpn_data(int sock) {
|
|||
pkt.len = recvfrom(sock, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen);
|
||||
|
||||
if(pkt.len < 0) {
|
||||
if(errno != EAGAIN && errno != EINTR)
|
||||
logger(LOG_ERR, "Receiving packet failed: %s", strerror(errno));
|
||||
if(!sockwouldblock(sockerrno))
|
||||
logger(LOG_ERR, "Receiving packet failed: %s", sockstrerror(sockerrno));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -541,10 +541,17 @@ void close_network_connections(void) {
|
|||
for(node = connection_tree->head; node; node = next) {
|
||||
next = node->next;
|
||||
c = node->data;
|
||||
c->outgoing = false;
|
||||
c->outgoing = NULL;
|
||||
terminate_connection(c, false);
|
||||
}
|
||||
|
||||
for(list_node_t *node = outgoing_list->head; node; node = node->next) {
|
||||
outgoing_t *outgoing = node->data;
|
||||
|
||||
if(outgoing->event)
|
||||
event_del(outgoing->event);
|
||||
}
|
||||
|
||||
list_delete_list(outgoing_list);
|
||||
|
||||
if(myself && myself->connection) {
|
||||
|
|
|
@ -36,10 +36,6 @@
|
|||
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef WSAEINPROGRESS
|
||||
#define EINPROGRESS WSAEINPROGRESS
|
||||
#endif
|
||||
|
||||
/* Needed on Mac OS/X */
|
||||
#ifndef SOL_TCP
|
||||
#define SOL_TCP IPPROTO_TCP
|
||||
|
@ -68,7 +64,7 @@ static void configure_tcp(connection_t *c) {
|
|||
unsigned long arg = 1;
|
||||
|
||||
if(ioctlsocket(c->socket, FIONBIO, &arg) != 0) {
|
||||
logger(LOG_ERR, "ioctlsocket for %s: WSA error %d", c->hostname, WSAGetLastError());
|
||||
logger(LOG_ERR, "ioctlsocket for %s: %d", c->hostname, sockstrerror(sockerrno));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -157,8 +153,7 @@ static bool bind_to_address(connection_t *c) {
|
|||
|
||||
|
||||
if(status) {
|
||||
logger(LOG_ERR, "Can't bind to %s/tcp: %s", node,
|
||||
strerror(errno));
|
||||
logger(LOG_ERR, "Can't bind to %s/tcp: %s", node, sockstrerror(sockerrno));
|
||||
} else ifdebug(CONNECTIONS) {
|
||||
logger(LOG_DEBUG, "Successfully bound outgoing "
|
||||
"TCP socket to %s", node);
|
||||
|
@ -179,7 +174,7 @@ int setup_listen_socket(const sockaddr_t *sa) {
|
|||
nfd = socket(sa->sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
|
||||
|
||||
if(nfd < 0) {
|
||||
ifdebug(STATUS) logger(LOG_ERR, "Creating metasocket failed: %s", strerror(errno));
|
||||
ifdebug(STATUS) logger(LOG_ERR, "Creating metasocket failed: %s", sockstrerror(sockerrno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -204,7 +199,7 @@ int setup_listen_socket(const sockaddr_t *sa) {
|
|||
if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr))) {
|
||||
closesocket(nfd);
|
||||
logger(LOG_ERR, "Can't bind to interface %s: %s", iface,
|
||||
strerror(errno));
|
||||
strerror(sockerrno));
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
|
@ -215,16 +210,14 @@ int setup_listen_socket(const sockaddr_t *sa) {
|
|||
if(bind(nfd, &sa->sa, SALEN(sa->sa))) {
|
||||
closesocket(nfd);
|
||||
addrstr = sockaddr2hostname(sa);
|
||||
logger(LOG_ERR, "Can't bind to %s/tcp: %s", addrstr,
|
||||
strerror(errno));
|
||||
logger(LOG_ERR, "Can't bind to %s/tcp: %s", addrstr, sockstrerror(sockerrno));
|
||||
free(addrstr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(listen(nfd, 3)) {
|
||||
closesocket(nfd);
|
||||
logger(LOG_ERR, "System call `%s' failed: %s", "listen",
|
||||
strerror(errno));
|
||||
logger(LOG_ERR, "System call `%s' failed: %s", "listen", sockstrerror(sockerrno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -239,7 +232,7 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
|
|||
nfd = socket(sa->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP);
|
||||
|
||||
if(nfd < 0) {
|
||||
logger(LOG_ERR, "Creating UDP socket failed: %s", strerror(errno));
|
||||
logger(LOG_ERR, "Creating UDP socket failed: %s", sockstrerror(sockerrno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -259,8 +252,7 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
|
|||
unsigned long arg = 1;
|
||||
if(ioctlsocket(nfd, FIONBIO, &arg) != 0) {
|
||||
closesocket(nfd);
|
||||
logger(LOG_ERR, "Call to `%s' failed: WSA error %d", "ioctlsocket",
|
||||
WSAGetLastError());
|
||||
logger(LOG_ERR, "Call to `%s' failed: %s", "ioctlsocket", sockstrerror(sockerrno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -279,6 +271,11 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
|
|||
option = IP_PMTUDISC_DO;
|
||||
setsockopt(nfd, SOL_IP, IP_MTU_DISCOVER, &option, sizeof(option));
|
||||
}
|
||||
#elif defined(IPPROTO_IP) && defined(IP_DONTFRAGMENT)
|
||||
if(myself->options & OPTION_PMTU_DISCOVERY) {
|
||||
option = 1;
|
||||
setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, &option, sizeof(option));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SOL_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
|
||||
|
@ -296,8 +293,7 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
|
|||
if(bind(nfd, &sa->sa, SALEN(sa->sa))) {
|
||||
closesocket(nfd);
|
||||
addrstr = sockaddr2hostname(sa);
|
||||
logger(LOG_ERR, "Can't bind to %s/udp: %s", addrstr,
|
||||
strerror(errno));
|
||||
logger(LOG_ERR, "Can't bind to %s/udp: %s", addrstr, sockstrerror(sockerrno));
|
||||
free(addrstr);
|
||||
return -1;
|
||||
}
|
||||
|
@ -306,18 +302,18 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
|
|||
} /* int setup_vpn_in_socket */
|
||||
|
||||
void retry_outgoing(outgoing_t *outgoing) {
|
||||
event_t *event;
|
||||
|
||||
outgoing->timeout += 5;
|
||||
|
||||
if(outgoing->timeout > maxtimeout)
|
||||
outgoing->timeout = maxtimeout;
|
||||
|
||||
event = new_event();
|
||||
event->handler = (event_handler_t) setup_outgoing_connection;
|
||||
event->time = now + outgoing->timeout;
|
||||
event->data = outgoing;
|
||||
event_add(event);
|
||||
if(outgoing->event)
|
||||
event_del(outgoing->event);
|
||||
outgoing->event = new_event();
|
||||
outgoing->event->handler = (event_handler_t) setup_outgoing_connection;
|
||||
outgoing->event->time = now + outgoing->timeout;
|
||||
outgoing->event->data = outgoing;
|
||||
event_add(outgoing->event);
|
||||
|
||||
ifdebug(CONNECTIONS) logger(LOG_NOTICE,
|
||||
"Trying to re-establish outgoing connection in %d seconds",
|
||||
|
@ -338,6 +334,11 @@ void do_outgoing_connection(connection_t *c) {
|
|||
char *address, *port;
|
||||
int result;
|
||||
|
||||
if(!c->outgoing) {
|
||||
logger(LOG_ERR, "do_outgoing_connection() for %s called without c->outgoing", c->name);
|
||||
abort();
|
||||
}
|
||||
|
||||
begin:
|
||||
if(!c->outgoing->ai) {
|
||||
if(!c->outgoing->cfg) {
|
||||
|
@ -345,6 +346,7 @@ begin:
|
|||
c->name);
|
||||
c->status.remove = true;
|
||||
retry_outgoing(c->outgoing);
|
||||
c->outgoing = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -382,9 +384,7 @@ begin:
|
|||
c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
|
||||
|
||||
if(c->socket == -1) {
|
||||
ifdebug(CONNECTIONS) logger(LOG_ERR, "Creating socket for %s failed: %s", c->hostname,
|
||||
strerror(errno));
|
||||
|
||||
ifdebug(CONNECTIONS) logger(LOG_ERR, "Creating socket for %s failed: %s", c->hostname, sockstrerror(sockerrno));
|
||||
goto begin;
|
||||
}
|
||||
|
||||
|
@ -406,18 +406,14 @@ begin:
|
|||
result = connect(c->socket, &c->address.sa, SALEN(c->address.sa));
|
||||
|
||||
if(result == -1) {
|
||||
if(errno == EINPROGRESS
|
||||
#if defined(WIN32) && !defined(O_NONBLOCK)
|
||||
|| WSAGetLastError() == WSAEWOULDBLOCK
|
||||
#endif
|
||||
) {
|
||||
if(sockinprogress(sockerrno)) {
|
||||
c->status.connecting = true;
|
||||
return;
|
||||
}
|
||||
|
||||
closesocket(c->socket);
|
||||
|
||||
ifdebug(CONNECTIONS) logger(LOG_ERR, "%s: %s", c->hostname, strerror(errno));
|
||||
ifdebug(CONNECTIONS) logger(LOG_ERR, "%s: %s", c->hostname, sockstrerror(sockerrno));
|
||||
|
||||
goto begin;
|
||||
}
|
||||
|
@ -431,6 +427,8 @@ void setup_outgoing_connection(outgoing_t *outgoing) {
|
|||
connection_t *c;
|
||||
node_t *n;
|
||||
|
||||
outgoing->event = NULL;
|
||||
|
||||
n = lookup_node(outgoing->name);
|
||||
|
||||
if(n)
|
||||
|
@ -480,8 +478,7 @@ bool handle_new_meta_connection(int sock) {
|
|||
fd = accept(sock, &sa.sa, &len);
|
||||
|
||||
if(fd < 0) {
|
||||
logger(LOG_ERR, "Accepting a new connection failed: %s",
|
||||
strerror(errno));
|
||||
logger(LOG_ERR, "Accepting a new connection failed: %s", sockstrerror(sockerrno));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -525,17 +522,6 @@ void try_outgoing_connections(void) {
|
|||
static config_t *cfg = NULL;
|
||||
char *name;
|
||||
outgoing_t *outgoing;
|
||||
connection_t *c;
|
||||
avl_node_t *node;
|
||||
|
||||
if(outgoing_list) {
|
||||
for(node = connection_tree->head; node; node = node->next) {
|
||||
c = node->data;
|
||||
c->outgoing = NULL;
|
||||
}
|
||||
|
||||
list_delete_list(outgoing_list);
|
||||
}
|
||||
|
||||
outgoing_list = list_alloc((list_action_t)free_outgoing);
|
||||
|
||||
|
|
|
@ -162,7 +162,7 @@ void dump_nodes(void) {
|
|||
|
||||
for(node = node_tree->head; node; node = node->next) {
|
||||
n = node->data;
|
||||
logger(LOG_DEBUG, " %s at %s cipher %d digest %d maclength %d compression %d options %lx status %04x nexthop %s via %s pmtu %d (min %d max %d)",
|
||||
logger(LOG_DEBUG, " %s at %s cipher %d digest %d maclength %d compression %d options %x status %04x nexthop %s via %s pmtu %d (min %d max %d)",
|
||||
n->name, n->hostname, n->outcipher ? n->outcipher->nid : 0,
|
||||
n->outdigest ? n->outdigest->type : 0, n->outmaclength, n->outcompression,
|
||||
n->options, bitfield_to_int(&n->status, sizeof n->status), n->nexthop ? n->nexthop->name : "-",
|
||||
|
|
|
@ -39,7 +39,7 @@ typedef struct node_status_t {
|
|||
|
||||
typedef struct node_t {
|
||||
char *name; /* name of this node */
|
||||
long int options; /* options turned on for this node */
|
||||
uint32_t options; /* options turned on for this node */
|
||||
|
||||
sockaddr_t address; /* his real (internet) ip to send UDP packets to */
|
||||
char *hostname; /* the hostname of its real ip */
|
||||
|
|
|
@ -103,13 +103,18 @@ bool install_service(void) {
|
|||
command, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
if(!service) {
|
||||
logger(LOG_ERR, "Could not create %s service: %s", identname, winerror(GetLastError()));
|
||||
return false;
|
||||
DWORD lasterror = GetLastError();
|
||||
logger(LOG_ERR, "Could not create %s service: %s", identname, winerror(lasterror));
|
||||
if(lasterror != ERROR_SERVICE_EXISTS)
|
||||
return false;
|
||||
}
|
||||
|
||||
ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &description);
|
||||
|
||||
logger(LOG_INFO, "%s service installed", identname);
|
||||
if(service) {
|
||||
ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &description);
|
||||
logger(LOG_INFO, "%s service installed", identname);
|
||||
} else {
|
||||
service = OpenService(manager, identname, SERVICE_ALL_ACCESS);
|
||||
}
|
||||
|
||||
if(!StartService(service, 0, NULL))
|
||||
logger(LOG_WARNING, "Could not start %s service: %s", identname, winerror(GetLastError()));
|
||||
|
|
|
@ -455,7 +455,7 @@ bool send_ack(connection_t *c) {
|
|||
|
||||
get_config_int(lookup_config(c->config_tree, "Weight"), &c->estimated_weight);
|
||||
|
||||
return send_request(c, "%d %s %d %lx", ACK, myport, c->estimated_weight, c->options);
|
||||
return send_request(c, "%d %s %d %x", ACK, myport, c->estimated_weight, c->options);
|
||||
}
|
||||
|
||||
static void send_everything(connection_t *c) {
|
||||
|
@ -494,10 +494,10 @@ bool ack_h(connection_t *c) {
|
|||
char hisport[MAX_STRING_SIZE];
|
||||
char *hisaddress, *dummy;
|
||||
int weight, mtu;
|
||||
long int options;
|
||||
uint32_t options;
|
||||
node_t *n;
|
||||
|
||||
if(sscanf(c->buffer, "%*d " MAX_STRING " %d %lx", hisport, &weight, &options) != 3) {
|
||||
if(sscanf(c->buffer, "%*d " MAX_STRING " %d %x", hisport, &weight, &options) != 3) {
|
||||
logger(LOG_ERR, "Got bad %s from %s (%s)", "ACK", c->name,
|
||||
c->hostname);
|
||||
return false;
|
||||
|
|
|
@ -41,7 +41,7 @@ bool send_add_edge(connection_t *c, const edge_t *e) {
|
|||
|
||||
sockaddr2str(&e->address, &address, &port);
|
||||
|
||||
x = send_request(c, "%d %x %s %s %s %s %lx %d", ADD_EDGE, rand(),
|
||||
x = send_request(c, "%d %x %s %s %s %s %x %d", ADD_EDGE, rand(),
|
||||
e->from->name, e->to->name, address, port,
|
||||
e->options, e->weight);
|
||||
free(address);
|
||||
|
@ -58,10 +58,10 @@ bool add_edge_h(connection_t *c) {
|
|||
char to_address[MAX_STRING_SIZE];
|
||||
char to_port[MAX_STRING_SIZE];
|
||||
sockaddr_t address;
|
||||
long int options;
|
||||
uint32_t options;
|
||||
int weight;
|
||||
|
||||
if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %lx %d",
|
||||
if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %x %d",
|
||||
from_name, to_name, to_address, to_port, &options, &weight) != 6) {
|
||||
logger(LOG_ERR, "Got bad %s from %s (%s)", "ADD_EDGE", c->name,
|
||||
c->hostname);
|
||||
|
|
|
@ -45,7 +45,7 @@ bool add_subnet_h(connection_t *c) {
|
|||
char subnetstr[MAX_STRING_SIZE];
|
||||
char name[MAX_STRING_SIZE];
|
||||
node_t *owner;
|
||||
subnet_t s = {0}, *new;
|
||||
subnet_t s = {0}, *new, *old;
|
||||
|
||||
if(sscanf(c->buffer, "%*d %*x " MAX_STRING " " MAX_STRING, name, subnetstr) != 2) {
|
||||
logger(LOG_ERR, "Got bad %s from %s (%s)", "ADD_SUBNET", c->name,
|
||||
|
@ -142,6 +142,11 @@ bool add_subnet_h(connection_t *c) {
|
|||
if(!tunnelserver)
|
||||
forward_request(c);
|
||||
|
||||
/* Fast handoff of roaming MAC addresses */
|
||||
|
||||
if(s.type == SUBNET_MAC && owner != myself && (old = lookup_subnet(myself, &s)) && old->expires)
|
||||
old->expires = now;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -117,6 +117,7 @@ static void learn_mac(mac_t *address) {
|
|||
subnet->type = SUBNET_MAC;
|
||||
subnet->expires = now + macexpire;
|
||||
subnet->net.mac.address = *address;
|
||||
subnet->weight = 10;
|
||||
subnet_add(myself, subnet);
|
||||
|
||||
/* And tell all other tinc daemons it's our MAC */
|
||||
|
|
43
src/subnet.c
43
src/subnet.c
|
@ -47,9 +47,15 @@ static subnet_t *cache_ipv6_subnet[2];
|
|||
static bool cache_ipv6_valid[2];
|
||||
static int cache_ipv6_slot;
|
||||
|
||||
static mac_t cache_mac_address[2];
|
||||
static subnet_t *cache_mac_subnet[2];
|
||||
static bool cache_mac_valid[2];
|
||||
static int cache_mac_slot;
|
||||
|
||||
void subnet_cache_flush() {
|
||||
cache_ipv4_valid[0] = cache_ipv4_valid[1] = false;
|
||||
cache_ipv6_valid[0] = cache_ipv6_valid[1] = false;
|
||||
cache_mac_valid[0] = cache_mac_valid[1] = false;
|
||||
}
|
||||
|
||||
/* Subnet comparison */
|
||||
|
@ -324,15 +330,46 @@ subnet_t *lookup_subnet(const node_t *owner, const subnet_t *subnet) {
|
|||
}
|
||||
|
||||
subnet_t *lookup_subnet_mac(const mac_t *address) {
|
||||
subnet_t *p, subnet = {0};
|
||||
subnet_t *p, *r = NULL, subnet = {0};
|
||||
avl_node_t *n;
|
||||
int i;
|
||||
|
||||
// Check if this address is cached
|
||||
|
||||
for(i = 0; i < 2; i++) {
|
||||
if(!cache_mac_valid[i])
|
||||
continue;
|
||||
if(!memcmp(address, &cache_mac_address[i], sizeof *address))
|
||||
return cache_mac_subnet[i];
|
||||
}
|
||||
|
||||
// Search all subnets for a matching one
|
||||
|
||||
subnet.type = SUBNET_MAC;
|
||||
subnet.net.mac.address = *address;
|
||||
subnet.owner = NULL;
|
||||
|
||||
p = avl_search(subnet_tree, &subnet);
|
||||
for(n = subnet_tree->head; n; n = n->next) {
|
||||
p = n->data;
|
||||
|
||||
return p;
|
||||
if(!p || p->type != subnet.type)
|
||||
continue;
|
||||
|
||||
if(!memcmp(address, &p->net.mac.address, sizeof *address)) {
|
||||
r = p;
|
||||
if(p->owner->status.reachable)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Cache the result
|
||||
|
||||
cache_mac_slot = !cache_mac_slot;
|
||||
memcpy(&cache_mac_address[cache_mac_slot], address, sizeof *address);
|
||||
cache_mac_subnet[cache_mac_slot] = r;
|
||||
cache_mac_valid[cache_mac_slot] = true;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
subnet_t *lookup_subnet_ipv4(const ipv4_t *address) {
|
||||
|
|
Loading…
Reference in a new issue