Import Upstream version 1.0.11

This commit is contained in:
Guus Sliepen 2019-08-26 13:44:38 +02:00
parent fa871d431d
commit 23bd9e9d53
28 changed files with 343 additions and 107 deletions

139
ChangeLog
View file

@ -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
View file

@ -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
View file

@ -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
View file

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

View file

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

View file

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

View file

@ -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);

View file

@ -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`

View file

@ -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:

View file

@ -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);
}

View file

@ -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 */

View file

@ -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);
}

View file

@ -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 */

View file

@ -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;

View file

@ -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;
}

View file

@ -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) {

View file

@ -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;

View file

@ -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;
}

View file

@ -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) {

View file

@ -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,18 +522,7 @@ 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);
for(cfg = lookup_config(config_tree, "ConnectTo"); cfg; cfg = lookup_config_next(config_tree, cfg)) {

View file

@ -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 : "-",

View file

@ -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 */

View file

@ -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()));

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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 */

View file

@ -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;
if(!p || p->type != subnet.type)
continue;
return p;
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) {