Import Upstream version 1.1~pre15

This commit is contained in:
Guus Sliepen 2019-08-26 13:44:52 +02:00
parent 87cef22421
commit bc8ca65653
85 changed files with 1687 additions and 971 deletions

View file

@ -1,6 +1,8 @@
## Produce this file with automake to get Makefile.in
sbin_PROGRAMS = tincd tinc sptps_test sptps_keypair
sbin_PROGRAMS = tincd tinc
check_PROGRAMS = sptps_test sptps_keypair
EXTRA_PROGRAMS = sptps_test sptps_keypair
CLEANFILES = version_git.h
@ -18,11 +20,10 @@ version.c: ${srcdir}/version.c
endif
if LINUX
sbin_PROGRAMS += sptps_speed
EXTRA_PROGRAMS += sptps_speed
endif
ed25519_SOURCES = \
ed25519/add_scalar.c \
ed25519/ed25519.h \
ed25519/fe.c ed25519/fe.h \
ed25519/fixedint.h \
@ -41,6 +42,7 @@ chacha_poly1305_SOURCES = \
chacha-poly1305/poly1305.c chacha-poly1305/poly1305.h
tincd_SOURCES = \
autoconnect.c autoconnect.h \
buffer.c buffer.h \
cipher.h \
conf.c conf.h \
@ -58,6 +60,7 @@ tincd_SOURCES = \
edge.c edge.h \
ethernet.h \
event.c event.h \
fd_device.c \
graph.c graph.h \
hash.c hash.h \
have.h \

View file

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.15 from Makefile.am.
# Makefile.in generated by automake 1.15.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
# Copyright (C) 1994-2017 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -88,8 +88,10 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
sbin_PROGRAMS = tincd$(EXEEXT) tinc$(EXEEXT) sptps_test$(EXEEXT) \
sptps_keypair$(EXEEXT) $(am__EXEEXT_1)
sbin_PROGRAMS = tincd$(EXEEXT) tinc$(EXEEXT)
check_PROGRAMS = sptps_test$(EXEEXT) sptps_keypair$(EXEEXT)
EXTRA_PROGRAMS = sptps_test$(EXEEXT) sptps_keypair$(EXEEXT) \
$(am__EXEEXT_1)
@LINUX_TRUE@am__append_1 = sptps_speed
@GETOPT_FALSE@am__append_2 = \
@GETOPT_FALSE@ getopt.c getopt.h \
@ -216,19 +218,18 @@ CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(sbindir)"
PROGRAMS = $(sbin_PROGRAMS)
am__sptps_keypair_SOURCES_DIST = sptps_keypair.c utils.c utils.h \
ed25519/ecdsagen.c 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/ecdsagen.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 getopt.c getopt.h getopt1.c openssl/crypto.c \
nolegacy/crypto.c
am__dirstamp = $(am__leading_dot)dirstamp
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)
am__objects_1 = 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)
@GETOPT_FALSE@am__objects_2 = getopt.$(OBJEXT) getopt1.$(OBJEXT)
@OPENSSL_TRUE@am__objects_3 = openssl/crypto.$(OBJEXT)
@GCRYPT_TRUE@@OPENSSL_FALSE@am__objects_4 = openssl/crypto.$(OBJEXT)
@ -241,9 +242,9 @@ 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/ecdh.c ed25519/ecdsa.c \
ed25519/ecdsagen.c 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/ecdsagen.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 \
@ -272,11 +273,10 @@ 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/ecdh.c ed25519/ecdsa.c \
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/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 \
@ -300,11 +300,11 @@ am__tinc_SOURCES_DIST = dropin.c dropin.h fsck.c fsck.h ifconfig.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 version.c version.h ed25519/ecdh.c \
ed25519/ecdsa.c ed25519/ecdsagen.c 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/ecdsa.c ed25519/ecdsagen.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 \
@ -336,23 +336,23 @@ am_tinc_OBJECTS = dropin.$(OBJEXT) fsck.$(OBJEXT) ifconfig.$(OBJEXT) \
tinc_OBJECTS = $(am_tinc_OBJECTS)
am__DEPENDENCIES_1 =
tinc_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
am__tincd_SOURCES_DIST = 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 ecdsa.h ecdsagen.h edge.c edge.h ethernet.h event.c \
event.h graph.c graph.h hash.c hash.h have.h ipv4.h ipv6.h \
list.c list.h logger.c logger.h meta.c meta.h \
multicast_device.c names.c names.h net.c net.h net_packet.c \
net_setup.c net_socket.c netutl.c netutl.h node.c node.h prf.h \
process.c process.h protocol.c protocol.h protocol_auth.c \
protocol_edge.c protocol_key.c protocol_misc.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 version.c version.h ed25519/ecdh.c \
ed25519/ecdsa.c 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 \
am__tincd_SOURCES_DIST = autoconnect.c autoconnect.h 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 ecdsa.h ecdsagen.h edge.c \
edge.h ethernet.h event.c event.h fd_device.c graph.c graph.h \
hash.c hash.h have.h ipv4.h ipv6.h list.c list.h logger.c \
logger.h meta.c meta.h multicast_device.c names.c names.h \
net.c net.h net_packet.c net_setup.c net_socket.c netutl.c \
netutl.h node.c node.h prf.h process.c process.h protocol.c \
protocol.h protocol_auth.c protocol_edge.c protocol_key.c \
protocol_misc.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 version.c version.h \
ed25519/ecdh.c ed25519/ecdsa.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 \
@ -384,14 +384,15 @@ am__tincd_SOURCES_DIST = buffer.c buffer.h cipher.h conf.c conf.h \
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/prf.$(OBJEXT) \
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/rsa.$(OBJEXT)
@MINIUPNPC_TRUE@am__objects_23 = upnp.$(OBJEXT)
am_tincd_OBJECTS = buffer.$(OBJEXT) conf.$(OBJEXT) \
connection.$(OBJEXT) control.$(OBJEXT) dropin.$(OBJEXT) \
dummy_device.$(OBJEXT) edge.$(OBJEXT) event.$(OBJEXT) \
graph.$(OBJEXT) hash.$(OBJEXT) list.$(OBJEXT) logger.$(OBJEXT) \
meta.$(OBJEXT) multicast_device.$(OBJEXT) names.$(OBJEXT) \
net.$(OBJEXT) net_packet.$(OBJEXT) net_setup.$(OBJEXT) \
net_socket.$(OBJEXT) netutl.$(OBJEXT) node.$(OBJEXT) \
process.$(OBJEXT) protocol.$(OBJEXT) protocol_auth.$(OBJEXT) \
am_tincd_OBJECTS = autoconnect.$(OBJEXT) buffer.$(OBJEXT) \
conf.$(OBJEXT) connection.$(OBJEXT) control.$(OBJEXT) \
dropin.$(OBJEXT) dummy_device.$(OBJEXT) edge.$(OBJEXT) \
event.$(OBJEXT) fd_device.$(OBJEXT) graph.$(OBJEXT) \
hash.$(OBJEXT) list.$(OBJEXT) logger.$(OBJEXT) meta.$(OBJEXT) \
multicast_device.$(OBJEXT) names.$(OBJEXT) net.$(OBJEXT) \
net_packet.$(OBJEXT) net_setup.$(OBJEXT) net_socket.$(OBJEXT) \
netutl.$(OBJEXT) node.$(OBJEXT) process.$(OBJEXT) \
protocol.$(OBJEXT) protocol_auth.$(OBJEXT) \
protocol_edge.$(OBJEXT) protocol_key.$(OBJEXT) \
protocol_misc.$(OBJEXT) protocol_subnet.$(OBJEXT) \
raw_socket_device.$(OBJEXT) route.$(OBJEXT) script.$(OBJEXT) \
@ -570,7 +571,6 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
CLEANFILES = version_git.h
ed25519_SOURCES = \
ed25519/add_scalar.c \
ed25519/ed25519.h \
ed25519/fe.c ed25519/fe.h \
ed25519/fixedint.h \
@ -588,16 +588,16 @@ chacha_poly1305_SOURCES = \
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 \
ecdsa.h ecdsagen.h edge.c edge.h ethernet.h event.c event.h \
graph.c graph.h hash.c hash.h have.h ipv4.h ipv6.h list.c \
list.h logger.c logger.h meta.c meta.h multicast_device.c \
names.c names.h net.c net.h net_packet.c net_setup.c \
net_socket.c netutl.c netutl.h node.c node.h prf.h process.c \
process.h protocol.c protocol.h protocol_auth.c \
protocol_edge.c protocol_key.c protocol_misc.c \
tincd_SOURCES = autoconnect.c autoconnect.h 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 ecdsa.h ecdsagen.h edge.c edge.h \
ethernet.h event.c event.h fd_device.c graph.c graph.h hash.c \
hash.h have.h ipv4.h ipv6.h list.c list.h logger.c logger.h \
meta.c meta.h multicast_device.c names.c names.h net.c net.h \
net_packet.c net_setup.c net_socket.c netutl.c netutl.h node.c \
node.h prf.h process.c process.h protocol.c protocol.h \
protocol_auth.c protocol_edge.c protocol_key.c protocol_misc.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 \
@ -666,6 +666,9 @@ $(top_srcdir)/configure: $(am__configure_deps)
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
clean-checkPROGRAMS:
-test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS)
install-sbinPROGRAMS: $(sbin_PROGRAMS)
@$(NORMAL_INSTALL)
@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
@ -732,8 +735,6 @@ ed25519/$(DEPDIR)/$(am__dirstamp):
@: > ed25519/$(DEPDIR)/$(am__dirstamp)
ed25519/ecdsagen.$(OBJEXT): ed25519/$(am__dirstamp) \
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) \
@ -892,6 +893,7 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/autoconnect.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connection.Po@am__quote@
@ -900,6 +902,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dummy_device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edge.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fd_device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsck.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@
@ -950,7 +953,6 @@ distclean-compile:
@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@
@ -1079,6 +1081,7 @@ distdir: $(DISTFILES)
fi; \
done
check-am: all-am
$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
check: check-am
all-am: Makefile $(PROGRAMS)
installdirs:
@ -1138,7 +1141,8 @@ maintainer-clean-generic:
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am
clean-am: clean-checkPROGRAMS clean-generic clean-sbinPROGRAMS \
mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR) bsd/$(DEPDIR) chacha-poly1305/$(DEPDIR) cygwin/$(DEPDIR) ed25519/$(DEPDIR) gcrypt/$(DEPDIR) linux/$(DEPDIR) mingw/$(DEPDIR) nolegacy/$(DEPDIR) openssl/$(DEPDIR) solaris/$(DEPDIR)
@ -1205,21 +1209,22 @@ ps-am:
uninstall-am: uninstall-sbinPROGRAMS
.MAKE: install-am install-strip
.MAKE: check-am install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
clean-sbinPROGRAMS cscopelist-am ctags ctags-am distclean \
distclean-compile distclean-generic distclean-tags distdir dvi \
dvi-am html html-am info info-am install install-am \
install-data install-data-am install-dvi install-dvi-am \
install-exec install-exec-am install-html install-html-am \
install-info install-info-am install-man install-pdf \
install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \
install-strip installcheck installcheck-am \
installcheck-sbinPROGRAMS installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
uninstall-am uninstall-sbinPROGRAMS
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
clean-checkPROGRAMS clean-generic clean-sbinPROGRAMS \
cscopelist-am ctags ctags-am distclean distclean-compile \
distclean-generic distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-pdf install-pdf-am \
install-ps install-ps-am install-sbinPROGRAMS install-strip \
installcheck installcheck-am installcheck-sbinPROGRAMS \
installdirs maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \
ps ps-am tags tags-am uninstall uninstall-am \
uninstall-sbinPROGRAMS
.PRECIOUS: Makefile

174
src/autoconnect.c Normal file
View file

@ -0,0 +1,174 @@
/*
autoconnect.c -- automatic connection establishment
Copyright (C) 2017 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 "connection.h"
#include "logger.h"
#include "node.h"
#include "xalloc.h"
static void make_new_connection() {
/* Select a random node we haven't connected to yet. */
int count = 0;
for splay_each(node_t, n, node_tree) {
if(n == myself || n->connection || !(n->status.has_address || n->status.reachable))
continue;
count++;
}
if(!count)
return;
int r = rand() % count;
for splay_each(node_t, n, node_tree) {
if(n == myself || n->connection || !(n->status.has_address || n->status.reachable))
continue;
if(r--)
continue;
bool found = false;
for list_each(outgoing_t, outgoing, outgoing_list) {
if(!strcmp(outgoing->name, n->name)) {
found = true;
break;
}
}
if(!found) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "Autoconnecting to %s", n->name);
outgoing_t *outgoing = xzalloc(sizeof *outgoing);
outgoing->name = xstrdup(n->name);
list_insert_tail(outgoing_list, outgoing);
setup_outgoing_connection(outgoing);
}
break;
}
}
static void connect_to_unreachable() {
/* Select a random known node. The rationale is that if there are many
* reachable nodes, and only a few unreachable nodes, we don't want all
* reachable nodes to try to connect to the unreachable ones at the
* same time. This way, we back off automatically. Conversely, if there
* are only a few reachable nodes, and many unreachable ones, we're
* going to try harder to connect to them. */
int r = rand() % node_tree->count;
for splay_each(node_t, n, node_tree) {
if(r--)
continue;
/* Is it unreachable and do we know an address for it? If not, return. */
if(n == myself || n->connection || n->status.reachable || !n->status.has_address)
return;
/* Are we already trying to make an outgoing connection to it? If not, return. */
for list_each(outgoing_t, outgoing, outgoing_list)
if(!strcmp(outgoing->name, n->name))
return;
logger(DEBUG_CONNECTIONS, LOG_INFO, "Autoconnecting to %s", n->name);
outgoing_t *outgoing = xzalloc(sizeof *outgoing);
outgoing->name = xstrdup(n->name);
list_insert_tail(outgoing_list, outgoing);
setup_outgoing_connection(outgoing);
return;
}
}
static void drop_superfluous_outgoing_connection() {
/* Choose a random outgoing connection to a node that has at least one other connection. */
int count = 0;
for list_each(connection_t, c, connection_list) {
if(!c->edge || !c->outgoing || !c->node || c->node->edge_tree->count < 2)
continue;
count++;
}
if(!count)
return;
int r = rand() % count;
for list_each(connection_t, c, connection_list) {
if(!c->edge || !c->outgoing || !c->node || c->node->edge_tree->count < 2)
continue;
if(r--)
continue;
logger(DEBUG_CONNECTIONS, LOG_INFO, "Autodisconnecting from %s", c->name);
list_delete(outgoing_list, c->outgoing);
c->outgoing = NULL;
terminate_connection(c, c->edge);
break;
}
}
static void drop_superfluous_pending_connections() {
for list_each(outgoing_t, o, outgoing_list) {
/* Only look for connections that are waiting to be retried later. */
bool found = false;
for list_each(connection_t, c, connection_list) {
if(c->outgoing == o) {
found = true;
break;
}
}
if(found)
continue;
logger(DEBUG_CONNECTIONS, LOG_INFO, "Cancelled outgoing connection to %s", o->name);
list_delete_node(outgoing_list, node);
}
}
void do_autoconnect() {
/* Count number of active connections. */
int nc = 0;
for list_each(connection_t, c, connection_list) {
if(c->edge)
nc++;
}
/* Less than 3 connections? Eagerly try to make a new one. */
if(nc < 3) {
make_new_connection();
return;
}
/* More than 3 connections? See if we can get rid of a superfluous one. */
if(nc > 3)
drop_superfluous_outgoing_connection();
/* Check if there are unreachable nodes that we should try to connect to. */
connect_to_unreachable();
/* Drop pending outgoing connections from the outgoing list. */
drop_superfluous_pending_connections();
}

25
src/autoconnect.h Normal file
View file

@ -0,0 +1,25 @@
/*
autoconnect.h -- header for autoconnect.c
Copyright (C) 2017 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.
*/
#ifndef __TINC_AUTOCONNECT_H__
#define __TINC_AUTOCONNECT_H__
extern void do_autoconnect(void);
#endif

View file

@ -1,7 +1,7 @@
/*
device.c -- Interaction BSD tun/tap device
Copyright (C) 2001-2005 Ivo Timmermans,
2001-2016 Guus Sliepen <guus@tinc-vpn.org>
2001-2017 Guus Sliepen <guus@tinc-vpn.org>
2009 Grzegorz Dymarek <gregd72002@googlemail.com>
This program is free software; you can redistribute it and/or modify
@ -198,18 +198,19 @@ static bool setup_device(void) {
// Guess what the corresponding interface is called
char *realname;
char *realname = NULL;
#if defined(HAVE_FDEVNAME)
realname = fdevname(device_fd) ? : device;
realname = fdevname(device_fd);
#elif defined(HAVE_DEVNAME)
struct stat buf;
if(!fstat(device_fd, &buf))
realname = devname(buf.st_rdev, S_IFCHR) ? : device;
#else
realname = device;
realname = devname(buf.st_rdev, S_IFCHR);
#endif
if(!realname)
realname = device;
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
iface = xstrdup(strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname);
else if(strcmp(iface, strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname))

View file

@ -1,6 +1,6 @@
/*
cipher.h -- header file cipher.c
Copyright (C) 2007-2013 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2007-2016 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
@ -30,10 +30,10 @@ typedef struct cipher cipher_t;
extern cipher_t *cipher_open_by_name(const char *) __attribute__ ((__malloc__));
extern cipher_t *cipher_open_by_nid(int) __attribute__ ((__malloc__));
extern cipher_t *cipher_open_blowfish_ofb(void) __attribute__ ((__malloc__));
extern void cipher_close(cipher_t *);
extern size_t cipher_keylength(const cipher_t *);
extern size_t cipher_blocksize(const cipher_t *);
extern uint64_t cipher_budget(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__));

View file

@ -81,6 +81,8 @@ typedef struct connection_t {
cipher_t *outcipher; /* Cipher we will use to send data to him */
digest_t *indigest;
digest_t *outdigest;
uint64_t inbudget;
uint64_t outbudget;
#endif
ecdsa_t *ecdsa; /* his public ECDSA key */

View file

@ -40,6 +40,7 @@ extern const devops_t os_devops;
extern const devops_t dummy_devops;
extern const devops_t raw_socket_devops;
extern const devops_t multicast_devops;
extern const devops_t fd_devops;
extern const devops_t uml_devops;
extern const devops_t vde_devops;
extern devops_t devops;

View file

@ -1,6 +1,6 @@
/*
digest.h -- header file digest.c
Copyright (C) 2007-2013 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2007-2016 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
@ -28,7 +28,6 @@ typedef struct digest digest_t;
extern digest_t *digest_open_by_name(const char *name, int maclength) __attribute__ ((__malloc__));
extern digest_t *digest_open_by_nid(int nid, int maclength) __attribute__ ((__malloc__));
extern digest_t *digest_open_sha1(int maclength) __attribute__ ((__malloc__));
extern void digest_close(digest_t *);
extern bool digest_create(digest_t *, const void *indata, size_t inlen, void *outdata) __attribute__ ((__warn_unused_result__));
extern bool digest_verify(digest_t *, const void *indata, size_t inlen, const void *digestdata) __attribute__ ((__warn_unused_result__));

View file

@ -106,14 +106,13 @@ int vasprintf(char **buf, const char *fmt, va_list ap) {
va_copy(aq, ap);
status = vsnprintf(*buf, len, fmt, aq);
buf[len - 1] = 0;
va_end(aq);
if(status >= 0)
*buf = xrealloc(*buf, status + 1);
if(status > len - 1) {
len = status;
len = status + 1;
va_copy(aq, ap);
status = vsnprintf(*buf, len, fmt, aq);
va_end(aq);

View file

@ -1,56 +0,0 @@
#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);
}
}

View file

@ -27,7 +27,6 @@ int ED25519_DECLSPEC ed25519_create_seed(unsigned char *seed);
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);

View file

@ -81,42 +81,36 @@ void sc_reduce(unsigned char *s) {
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 -= shl64(carry6, 21);
@ -156,35 +150,30 @@ void sc_reduce(unsigned char *s) {
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;
@ -277,7 +266,6 @@ void sc_reduce(unsigned char *s) {
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = s0 >> 21;
s1 += carry0;
s0 -= shl64(carry0, 21);
@ -543,42 +531,36 @@ void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b,
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 -= shl64(carry6, 21);
@ -618,35 +600,30 @@ void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b,
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;
@ -739,7 +716,6 @@ void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b,
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = s0 >> 21;
s1 += carry0;
s0 -= shl64(carry0, 21);

View file

@ -25,6 +25,15 @@
#define ETH_ALEN 6
#endif
#ifndef ETH_HLEN
#define ETH_HLEN 14
#endif
#ifndef ETHER_TYPE_LEN
#define ETHER_TYPE_LEN 2
#endif
#ifndef ARPHRD_ETHER
#define ARPHRD_ETHER 1
#endif
@ -45,6 +54,10 @@
#define ETH_P_8021Q 0x8100
#endif
#ifndef ETH_P_MAX
#define ETH_P_MAX 0xFFFF
#endif
#ifndef HAVE_STRUCT_ETHER_HEADER
struct ether_header {
uint8_t ether_dhost[ETH_ALEN];

View file

@ -357,10 +357,13 @@ bool event_loop(void) {
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);
/*
The fd might be available for write too. However, if we already fired the read callback, that
callback might have deleted the io (e.g. through terminate_connection()), so we can't fire the
write callback here. Instead, we loop back and let the writable io loop above handle it.
*/
}
}
#endif

123
src/fd_device.c Normal file
View file

@ -0,0 +1,123 @@
/*
fd_device.c -- Interaction with Android tun fd
Copyright (C) 2001-2005 Ivo Timmermans,
2001-2016 Guus Sliepen <guus@tinc-vpn.org>
2009 Grzegorz Dymarek <gregd72002@googlemail.com>
2016 Pacien TRAN-GIRARD <pacien@pacien.net>
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 "conf.h"
#include "device.h"
#include "ethernet.h"
#include "logger.h"
#include "net.h"
#include "route.h"
#include "utils.h"
static inline bool check_config(void) {
if(routing_mode == RMODE_SWITCH) {
logger(DEBUG_ALWAYS, LOG_ERR, "Switch mode not supported (requires unsupported TAP device)!");
return false;
}
if(!get_config_int(lookup_config(config_tree, "Device"), &device_fd)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not read fd from configuration!");
return false;
}
return true;
}
static bool setup_device(void) {
if(!check_config()) {
return false;
}
if(device_fd < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s!", device, strerror(errno));
return false;
}
logger(DEBUG_ALWAYS, LOG_INFO, "fd/%d adapter set up.", device_fd);
return true;
}
static void close_device(void) {
close(device_fd);
device_fd = -1;
}
static inline uint16_t get_ip_ethertype(vpn_packet_t *packet) {
switch (DATA(packet)[ETH_HLEN] >> 4) {
case 4:
return ETH_P_IP;
case 6:
return ETH_P_IPV6;
default:
return ETH_P_MAX;
}
}
static inline void set_etherheader(vpn_packet_t *packet, uint16_t ethertype) {
memset(DATA(packet), 0, ETH_HLEN - ETHER_TYPE_LEN);
DATA(packet)[ETH_HLEN - ETHER_TYPE_LEN] = (ethertype >> 8) & 0xFF;
DATA(packet)[ETH_HLEN - ETHER_TYPE_LEN + 1] = ethertype & 0xFF;
}
static bool read_packet(vpn_packet_t *packet) {
int lenin = read(device_fd, DATA(packet) + ETH_HLEN, MTU - ETH_HLEN);
if(lenin <= 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from fd/%d: %s!", device_fd, strerror(errno));
return false;
}
uint16_t ethertype = get_ip_ethertype(packet);
if(ethertype == ETH_P_MAX) {
logger(DEBUG_TRAFFIC, LOG_ERR, "Unknown IP version while reading packet from fd/%d!", device_fd);
return false;
}
set_etherheader(packet, ethertype);
packet->len = lenin + ETH_HLEN;
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from fd/%d.", packet->len, device_fd);
return true;
}
static bool write_packet(vpn_packet_t *packet) {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to fd/%d.", packet->len, device_fd);
if(write(device_fd, DATA(packet) + ETH_HLEN, packet->len - ETH_HLEN) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to fd/%d: %s!", device_fd, strerror(errno));
return false;
}
return true;
}
const devops_t fd_devops = {
.setup = setup_device,
.close = close_device,
.read = read_packet,
.write = write_packet,
};

View file

@ -297,9 +297,10 @@ int fsck(const char *argv0) {
rsa_t *rsa_pub = NULL;
f = fopen(fname, "r");
if(f)
if(f) {
rsa_pub = rsa_read_pem_public_key(f);
fclose(f);
fclose(f);
}
if(rsa_priv) {
if(!rsa_pub) {
@ -352,12 +353,12 @@ int fsck(const char *argv0) {
f = fopen(fname, "r");
if(f) {
ecdsa_pub = get_pubkey(f);
if(!f) {
if(!ecdsa_pub) {
rewind(f);
ecdsa_pub = ecdsa_read_pem_public_key(f);
}
fclose(f);
}
fclose(f);
if(ecdsa_priv) {
if(!ecdsa_pub) {

View file

@ -1,6 +1,6 @@
/*
graph.c -- graph algorithms
Copyright (C) 2001-2013 Guus Sliepen <guus@tinc-vpn.org>,
Copyright (C) 2001-2017 Guus Sliepen <guus@tinc-vpn.org>,
2001-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify
@ -247,28 +247,23 @@ static void check_reachability(void) {
char *name;
char *address;
char *port;
char *envp[8] = {NULL};
xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
xasprintf(&envp[1], "DEVICE=%s", device ? : "");
xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
xasprintf(&envp[3], "NODE=%s", n->name);
environment_t env;
environment_init(&env);
environment_add(&env, "NODE=%s", n->name);
sockaddr2str(&n->address, &address, &port);
xasprintf(&envp[4], "REMOTEADDRESS=%s", address);
xasprintf(&envp[5], "REMOTEPORT=%s", port);
xasprintf(&envp[6], "NAME=%s", myself->name);
environment_add(&env, "REMOTEADDRESS=%s", address);
environment_add(&env, "REMOTEPORT=%s", port);
execute_script(n->status.reachable ? "host-up" : "host-down", envp);
execute_script(n->status.reachable ? "host-up" : "host-down", &env);
xasprintf(&name, n->status.reachable ? "hosts/%s-up" : "hosts/%s-down", n->name);
execute_script(name, envp);
execute_script(name, &env);
free(name);
free(address);
free(port);
for(int i = 0; i < 7; i++)
free(envp[i]);
environment_exit(&env);
subnet_update(n, NULL, n->status.reachable);

View file

@ -1,6 +1,6 @@
/*
ifconfig.c -- Generate platform specific interface configuration commands
Copyright (C) 2016 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2016-2017 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
@ -104,13 +104,6 @@ void ifconfig_address(FILE *out, const char *value) {
case SUBNET_IPV6: fprintf(out, "ip addr replace %s dev \"$INTERFACE\"\n", address_str); break;
default: return;
}
#elif defined(HAVE_BSD)
switch(address.type) {
case SUBNET_MAC: fprintf(out, "ifconfig \"$INTERFACE\" link %s\n", address_str); break;
case SUBNET_IPV4: fprintf(out, "ifconfig \"$INTERFACE\" %s\n", address_str); break;
case SUBNET_IPV6: fprintf(out, "ifconfig \"$INTERFACE\" inet6 %s\n", address_str); break;
default: return;
}
#elif defined(HAVE_MINGW) || defined(HAVE_CYGWIN)
switch(address.type) {
case SUBNET_MAC: fprintf(out, "ip link set \"$INTERFACE\" address %s\n", address_str); break;
@ -118,6 +111,13 @@ void ifconfig_address(FILE *out, const char *value) {
case SUBNET_IPV6: fprintf(out, "netsh inetface ipv6 set address \"$INTERFACE\" static %s\n", address_str); break;
default: return;
}
#else // assume BSD
switch(address.type) {
case SUBNET_MAC: fprintf(out, "ifconfig \"$INTERFACE\" link %s\n", address_str); break;
case SUBNET_IPV4: fprintf(out, "ifconfig \"$INTERFACE\" %s\n", address_str); break;
case SUBNET_IPV6: fprintf(out, "ifconfig \"$INTERFACE\" inet6 %s\n", address_str); break;
default: return;
}
#endif
}
@ -152,8 +152,21 @@ void ifconfig_route(FILE *out, const char *value) {
default: return;
}
}
#elif defined(HAVE_BSD)
// BSD route command is silly and doesn't accept an interface name as a destination.
#elif defined(HAVE_MINGW) || defined(HAVE_CYGWIN)
if(*gateway_str) {
switch(subnet.type) {
case SUBNET_IPV4: fprintf(out, "netsh inetface ipv4 add route %s \"%%INTERFACE%%\" %s\n", subnet_str, gateway_str); break;
case SUBNET_IPV6: fprintf(out, "netsh inetface ipv6 add route %s \"%%INTERFACE%%\" %s\n", subnet_str, gateway_str); break;
default: return;
}
} else {
switch(subnet.type) {
case SUBNET_IPV4: fprintf(out, "netsh inetface ipv4 add route %s \"%%INTERFACE%%\"\n", subnet_str); break;
case SUBNET_IPV6: fprintf(out, "netsh inetface ipv6 add route %s \"%%INTERFACE%%\"\n", subnet_str); break;
default: return;
}
}
#else // assume BSD
if(!*gateway_str) {
switch(subnet.type) {
case SUBNET_IPV4:
@ -180,19 +193,5 @@ void ifconfig_route(FILE *out, const char *value) {
case SUBNET_IPV6: fprintf(out, "route add -inet6 %s %s\n", subnet_str, gateway_str); break;
default: return;
}
#elif defined(HAVE_MINGW) || defined(HAVE_CYGWIN)
if(*gateway_str) {
switch(subnet.type) {
case SUBNET_IPV4: fprintf(out, "netsh inetface ipv4 add route %s \"%%INTERFACE%%\" %s\n", subnet_str, gateway_str); break;
case SUBNET_IPV6: fprintf(out, "netsh inetface ipv6 add route %s \"%%INTERFACE%%\" %s\n", subnet_str, gateway_str); break;
default: return;
}
} else {
switch(subnet.type) {
case SUBNET_IPV4: fprintf(out, "netsh inetface ipv4 add route %s \"%%INTERFACE%%\"\n", subnet_str); break;
case SUBNET_IPV6: fprintf(out, "netsh inetface ipv6 add route %s \"%%INTERFACE%%\"\n", subnet_str); break;
default: return;
}
}
#endif
}

View file

@ -1,6 +1,6 @@
/*
info.c -- Show information about a node, subnet or address
Copyright (C) 2012-2013 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2012-2017 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
@ -69,7 +69,7 @@ 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 %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);
int n = sscanf(line, "%d %d %4095s %4095s %4095s port %4095s %d %d %d %d %x %"PRIx32" %4095s %4095s %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;
@ -91,7 +91,7 @@ static int info_node(int fd, const char *item) {
}
while(recvline(fd, line, sizeof line)) {
if(sscanf(line, "%d %d %s", &code, &req, node) == 2)
if(sscanf(line, "%d %d %4095s", &code, &req, node) == 2)
break;
}
@ -158,7 +158,7 @@ static int info_node(int fd, const char *item) {
printf("Edges: ");
sendline(fd, "%d %d %s", CONTROL, REQ_DUMP_EDGES, item);
while(recvline(fd, line, sizeof line)) {
int n = sscanf(line, "%d %d %s %s", &code, &req, from, to);
int n = sscanf(line, "%d %d %4095s %4095s", &code, &req, from, to);
if(n == 2)
break;
if(n != 4) {
@ -174,7 +174,7 @@ static int info_node(int fd, const char *item) {
printf("Subnets: ");
sendline(fd, "%d %d %s", CONTROL, REQ_DUMP_SUBNETS, item);
while(recvline(fd, line, sizeof line)) {
int n = sscanf(line, "%d %d %s %s", &code, &req, subnet, from);
int n = sscanf(line, "%d %d %4095s %4095s", &code, &req, subnet, from);
if(n == 2)
break;
if(n != 4) {
@ -209,7 +209,7 @@ static int info_subnet(int fd, const char *item) {
sendline(fd, "%d %d %s", CONTROL, REQ_DUMP_SUBNETS, item);
while(recvline(fd, line, sizeof line)) {
int n = sscanf(line, "%d %d %s %s", &code, &req, netstr, owner);
int n = sscanf(line, "%d %d %4095s %4095s", &code, &req, netstr, owner);
if(n == 2)
break;

View file

@ -1,6 +1,6 @@
/*
invitation.c -- Create and accept invitations
Copyright (C) 2013-2015 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2013-2017 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
@ -239,7 +239,7 @@ int cmd_invite(int argc, char *argv[]) {
return 1;
}
char *myname = get_my_name(true);
myname = get_my_name(true);
if(!myname)
return 1;
@ -252,14 +252,14 @@ int cmd_invite(int argc, char *argv[]) {
}
// If a daemon is running, ensure no other nodes know about this name
bool found = false;
if(connect_tincd(false)) {
bool found = false;
sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);
while(recvline(fd, line, sizeof line)) {
char node[4096];
int code, req;
if(sscanf(line, "%d %d %s", &code, &req, node) != 3)
if(sscanf(line, "%d %d %4095s", &code, &req, node) != 3)
break;
if(!strcmp(node, argv[1]))
found = true;
@ -425,15 +425,13 @@ int cmd_invite(int argc, char *argv[]) {
xasprintf(&url, "%s/%s%s", address, hash, cookie);
// Call the inviation-created script
char *envp[6] = {};
xasprintf(&envp[0], "NAME=%s", myname);
xasprintf(&envp[1], "NETNAME=%s", netname);
xasprintf(&envp[2], "NODE=%s", argv[1]);
xasprintf(&envp[3], "INVITATION_FILE=%s", filename);
xasprintf(&envp[4], "INVITATION_URL=%s", url);
execute_script("invitation-created", envp);
for(int i = 0; i < 6 && envp[i]; i++)
free(envp[i]);
environment_t env;
environment_init(&env);
environment_add(&env, "NODE=%s", argv[1]);
environment_add(&env, "INVITATION_FILE=%s", filename);
environment_add(&env, "INVITATION_URL=%s", url);
execute_script("invitation-created", &env);
environment_exit(&env);
puts(url);
free(url);
@ -609,6 +607,17 @@ make_names:
return false;
}
snprintf(filename, sizeof filename, "%s" SLASH "invitation-data", confbase);
FILE *finv = fopen(filename, "w");
if(!finv || fwrite(data, datalen, 1, finv) != 1) {
fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno));
fclose(fh);
fclose(f);
fclose(finv);
return false;
}
fclose(finv);
snprintf(filename, sizeof filename, "%s" SLASH "tinc-up.invitation", confbase);
FILE *fup = fopen(filename, "w");
if(!fup) {
@ -688,7 +697,7 @@ make_names:
}
// Copy the safe variable to the right config file
fprintf(variables[i].type & VAR_HOST ? fh : f, "%s = %s\n", l, value);
fprintf((variables[i].type & VAR_HOST) ? fh : f, "%s = %s\n", l, value);
}
fclose(f);
@ -1046,7 +1055,7 @@ next:
char hisname[4096] = "";
int code, hismajor, hisminor = 0;
if(!recvline(sock, line, sizeof line) || sscanf(line, "%d %s %d.%d", &code, hisname, &hismajor, &hisminor) < 3 || code != 0 || hismajor != PROT_MAJOR || !check_id(hisname) || !recvline(sock, line, sizeof line) || !rstrip(line) || sscanf(line, "%d ", &code) != 1 || code != ACK || strlen(line) < 3) {
if(!recvline(sock, line, sizeof line) || sscanf(line, "%d %4095s %d.%d", &code, hisname, &hismajor, &hisminor) < 3 || code != 0 || hismajor != PROT_MAJOR || !check_id(hisname) || !recvline(sock, line, sizeof line) || !rstrip(line) || sscanf(line, "%d ", &code) != 1 || code != ACK || strlen(line) < 3) {
fprintf(stderr, "Cannot read greeting from peer\n");
closesocket(sock);
goto next;

View file

@ -139,6 +139,9 @@ static bool read_packet(vpn_packet_t *packet) {
if(inlen <= 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s",
device_info, device, strerror(errno));
if (errno == EBADFD) { /* File descriptor in bad state */
event_exit();
}
return false;
}

View file

@ -1,6 +1,6 @@
/*
logger.c -- logging code
Copyright (C) 2004-2015 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2004-2017 Guus Sliepen <guus@tinc-vpn.org>
2004-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify
@ -29,7 +29,7 @@
#include "process.h"
#include "sptps.h"
debug_t debug_level = DEBUG_NOTHING;
int debug_level = DEBUG_NOTHING;
static logmode_t logmode = LOGMODE_STDERR;
static pid_t logpid;
static FILE *logfile = NULL;

View file

@ -1,7 +1,7 @@
/*
logger.h -- header file for logger.c
Copyright (C) 1998-2005 Ivo Timmermans
2000-2012 Guus Sliepen <guus@tinc-vpn.org>
2000-2017 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
@ -67,7 +67,7 @@ enum {
#include <stdbool.h>
extern debug_t debug_level;
extern int debug_level;
extern bool logcontrol;
extern int umbilical;
extern void openlogger(const char *, logmode_t);

View file

@ -65,6 +65,13 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
#ifdef DISABLE_LEGACY
return false;
#else
if(length > c->outbudget) {
logger(DEBUG_META, LOG_ERR, "Byte limit exceeded for encryption to %s (%s)", c->name, c->hostname);
return false;
} else {
c->outbudget -= length;
}
size_t outlen = length;
if(!cipher_encrypt(c->outcipher, buffer, length, buffer_prepare(&c->outbuf, length), &outlen, false) || outlen != length) {
@ -220,6 +227,13 @@ bool receive_meta(connection_t *c) {
#ifdef DISABLE_LEGACY
return false;
#else
if(inlen > c->inbudget) {
logger(DEBUG_META, LOG_ERR, "yte limit exceeded for decryption from %s (%s)", c->name, c->hostname);
return false;
} else {
c->inbudget -= inlen;
}
size_t outlen = inlen;
if(!cipher_decrypt(c->incipher, bufp, inlen, buffer_prepare(&c->inbuf, inlen), &outlen, false) || inlen != outlen) {

View file

@ -214,6 +214,9 @@ static bool setup_device(void) {
logger(DEBUG_ALWAYS, LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
device_read_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
device_write_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
return true;
}
@ -226,9 +229,6 @@ static void enable_device(void) {
/* We don't use the write event directly, but GetOverlappedResult() does, internally. */
device_read_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
device_write_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
io_add_event(&device_read_io, device_handle_read, NULL, device_read_overlapped.hEvent);
device_issue_read();
}
@ -237,6 +237,19 @@ static void disable_device(void) {
logger(DEBUG_ALWAYS, LOG_INFO, "Disabling %s", device_info);
io_del(&device_read_io);
ULONG status = 0;
DWORD len;
DeviceIoControl(device_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, sizeof status, &status, sizeof status, &len, NULL);
/* Note that we don't try to cancel ongoing I/O here - we just stop listening.
This is because some TAP-Win32 drivers don't seem to handle cancellation very well,
especially when combined with other events such as the computer going to sleep - cases
were observed where the GetOverlappedResult() would just block indefinitely and never
return in that case. */
}
static void close_device(void) {
CancelIo(device_handle);
/* According to MSDN, CancelIo() does not necessarily wait for the operation to complete.
@ -253,11 +266,6 @@ static void disable_device(void) {
CloseHandle(device_read_overlapped.hEvent);
CloseHandle(device_write_overlapped.hEvent);
ULONG status = 0;
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;

View file

@ -1,7 +1,7 @@
/*
names.c -- generate commonly used (file)names
Copyright (C) 1998-2005 Ivo Timmermans
2000-2015 Guus Sliepen <guus@tinc-vpn.org>
2000-2017 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,6 +25,7 @@
#include "xalloc.h"
char *netname = NULL;
char *myname = NULL;
char *confdir = NULL; /* base configuration directory */
char *confbase = NULL; /* base configuration directory for this instance of tinc */
bool confbase_given;
@ -137,6 +138,7 @@ void free_names(void) {
free(logfilename);
free(confbase);
free(confdir);
free(myname);
identname = NULL;
netname = NULL;
@ -145,4 +147,5 @@ void free_names(void) {
logfilename = NULL;
confbase = NULL;
confdir = NULL;
myname = NULL;
}

View file

@ -1,7 +1,7 @@
/*
names.h -- header for names.c
Copyright (C) 1998-2005 Ivo Timmermans
2000-2015 Guus Sliepen <guus@tinc-vpn.org>
2000-2017 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,6 +25,7 @@ extern char *confdir;
extern char *confbase;
extern bool confbase_given;
extern char *netname;
extern char *myname;
extern char *identname;
extern char *unixsocketname;
extern char *logfilename;

107
src/net.c
View file

@ -1,7 +1,7 @@
/*
net.c -- most of the network code
Copyright (C) 1998-2005 Ivo Timmermans,
2000-2015 Guus Sliepen <guus@tinc-vpn.org>
2000-2017 Guus Sliepen <guus@tinc-vpn.org>
2006 Scott Lamb <slamb@slamb.org>
2011 Loïc Grenié <loic.grenie@gmail.com>
@ -22,7 +22,7 @@
#include "system.h"
#include "utils.h"
#include "autoconnect.h"
#include "conf.h"
#include "connection.h"
#include "device.h"
@ -34,6 +34,7 @@
#include "netutl.h"
#include "protocol.h"
#include "subnet.h"
#include "utils.h"
#include "xalloc.h"
int contradicting_add_edge = 0;
@ -209,7 +210,7 @@ static void timeout_handler(void *data) {
// timeout during ping
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);
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));
terminate_connection(c, c->edge);
continue;
}
@ -245,105 +246,9 @@ static void periodic_handler(void *data) {
/* If AutoConnect is set, check if we need to make or break connections. */
if(autoconnect && node_tree->count > 1) {
/* Count number of active connections */
int nc = 0;
for list_each(connection_t, c, connection_list) {
if(c->edge)
nc++;
}
if(autoconnect && node_tree->count > 1)
do_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
outgoing connection to this node.
*/
int count = 0;
for splay_each(node_t, n, node_tree) {
if(n == myself || n->connection || !(n->status.has_address || n->status.reachable))
continue;
count++;
}
if(!count)
goto end;
int r = rand() % count;
for splay_each(node_t, n, node_tree) {
if(n == myself || n->connection || !(n->status.has_address || n->status.reachable))
continue;
if(r--)
continue;
bool found = false;
for list_each(outgoing_t, outgoing, outgoing_list) {
if(!strcmp(outgoing->name, n->name)) {
found = true;
break;
}
}
if(!found) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "Autoconnecting to %s", n->name);
outgoing_t *outgoing = xzalloc(sizeof *outgoing);
outgoing->name = xstrdup(n->name);
list_insert_tail(outgoing_list, outgoing);
setup_outgoing_connection(outgoing);
}
break;
}
} 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.
*/
int r = rand() % nc;
int i = 0;
for list_each(connection_t, c, connection_list) {
if(!c->edge)
continue;
if(i++ != r)
continue;
if(!c->outgoing || !c->node || c->node->edge_tree->count < 2)
break;
logger(DEBUG_CONNECTIONS, LOG_INFO, "Autodisconnecting from %s", c->name);
list_delete(outgoing_list, c->outgoing);
c->outgoing = NULL;
terminate_connection(c, c->edge);
break;
}
}
if(nc >= 3) {
/* If we have enough active connections,
remove any pending outgoing connections.
*/
for list_each(outgoing_t, o, outgoing_list) {
bool found = false;
for list_each(connection_t, c, connection_list) {
if(c->outgoing == o) {
found = true;
break;
}
}
if(!found) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "Cancelled outgoing connection to %s", o->name);
list_delete_node(outgoing_list, node);
}
}
}
}
end:
timeout_set(data, &(struct timeval){5, rand() % 100000});
}

View file

@ -126,8 +126,9 @@ typedef struct outgoing_t {
int timeout;
splay_tree_t *config_tree;
struct config_t *cfg;
struct addrinfo *ai;
struct addrinfo *ai; // addresses from config files
struct addrinfo *aip;
struct addrinfo *kai; // addresses known via other online nodes (use free_known_addresses())
timeout_t ev;
} outgoing_t;

View file

@ -1,7 +1,7 @@
/*
net_packet.c -- Handles in- and outgoing VPN packets
Copyright (C) 1998-2005 Ivo Timmermans,
2000-2016 Guus Sliepen <guus@tinc-vpn.org>
2000-2017 Guus Sliepen <guus@tinc-vpn.org>
2010 Timothy Redaelli <timothy@redaelli.eu>
2010 Brandon Black <blblack@gmail.com>
@ -846,6 +846,7 @@ bool receive_sptps_record(void *handle, uint8_t type, const void *data, uint16_t
vpn_packet_t inpkt;
inpkt.offset = DEFAULT_PACKET_OFFSET;
inpkt.priority = 0;
if(type == PKT_PROBE) {
if(!from->status.udppacket) {
@ -1573,10 +1574,19 @@ void handle_device_data(void *data, int flags) {
vpn_packet_t packet;
packet.offset = DEFAULT_PACKET_OFFSET;
packet.priority = 0;
static int errors = 0;
if(devops.read(&packet)) {
errors = 0;
myself->in_packets++;
myself->in_bytes += packet.len;
route(myself, &packet);
} else {
usleep(errors * 50000);
errors++;
if(errors > 10) {
logger(DEBUG_ALWAYS, LOG_ERR, "Too many errors from %s, exiting!", device);
event_exit();
}
}
}

View file

@ -1,7 +1,7 @@
/*
net_setup.c -- Setup.
Copyright (C) 1998-2005 Ivo Timmermans,
2000-2016 Guus Sliepen <guus@tinc-vpn.org>
2000-2017 Guus Sliepen <guus@tinc-vpn.org>
2006 Scott Lamb <slamb@slamb.org>
2010 Brandon Black <blblack@gmail.com>
@ -48,7 +48,6 @@
#endif
char *myport;
static char *myname;
static io_t device_io;
devops_t devops;
bool device_standby = false;
@ -612,6 +611,9 @@ bool setup_myself_reloadable(void) {
get_config_bool(lookup_config(config_tree, "DisableBuggyPeers"), &disablebuggypeers);
if(!get_config_int(lookup_config(config_tree, "InvitationExpire"), &invitation_lifetime))
invitation_lifetime = 604800; // 1 week
read_invitation_key();
return true;
@ -705,29 +707,17 @@ void device_enable(void) {
/* 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]);
environment_t env;
environment_init(&env);
execute_script("tinc-up", &env);
environment_exit(&env);
}
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]);
environment_t env;
environment_init(&env);
execute_script("tinc-down", &env);
environment_exit(&env);
if (devops.disable)
devops.disable();
@ -857,7 +847,7 @@ static bool setup_myself(void) {
/* Generate packet encryption key */
if(!get_config_string(lookup_config(config_tree, "Cipher"), &cipher))
cipher = xstrdup("blowfish");
cipher = xstrdup("aes-256-cbc");
if(!strcasecmp(cipher, "none")) {
myself->incipher = NULL;
@ -881,7 +871,7 @@ static bool setup_myself(void) {
}
if(!get_config_string(lookup_config(config_tree, "Digest"), &digest))
digest = xstrdup("sha1");
digest = xstrdup("sha256");
if(!strcasecmp(digest, "none")) {
myself->indigest = NULL;
@ -929,6 +919,8 @@ static bool setup_myself(void) {
devops = raw_socket_devops;
else if(!strcasecmp(type, "multicast"))
devops = multicast_devops;
else if(!strcasecmp(type, "fd"))
devops = fd_devops;
#ifdef ENABLE_UML
else if(!strcasecmp(type, "uml"))
devops = uml_devops;
@ -1148,7 +1140,6 @@ void close_network_connections(void) {
exit_control();
free(myname);
free(scriptextension);
free(scriptinterpreter);

View file

@ -1,7 +1,7 @@
/*
net_socket.c -- Handle various kinds of sockets.
Copyright (C) 1998-2005 Ivo Timmermans,
2000-2016 Guus Sliepen <guus@tinc-vpn.org>
2000-2017 Guus Sliepen <guus@tinc-vpn.org>
2006 Scott Lamb <slamb@slamb.org>
2009 Florian Forster <octo@verplant.org>
@ -382,7 +382,7 @@ static void handle_meta_write(connection_t *c) {
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);
logger(DEBUG_META, 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, sockstrerror(sockerrno));
@ -441,13 +441,20 @@ static void handle_meta_io(void *data, int flags) {
handle_meta_connection_data(c);
}
static void free_known_addresses(struct addrinfo *ai) {
for(struct addrinfo *aip = ai, *next; aip; aip = next) {
next = aip->ai_next;
free(aip);
}
}
bool do_outgoing_connection(outgoing_t *outgoing) {
char *address, *port, *space;
struct addrinfo *proxyai = NULL;
int result;
begin:
if(!outgoing->ai) {
if(!outgoing->ai && !outgoing->kai) {
if(!outgoing->cfg) {
logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not set up a meta connection to %s", outgoing->name);
retry_outgoing(outgoing);
@ -477,6 +484,11 @@ begin:
if(outgoing->ai)
freeaddrinfo(outgoing->ai);
outgoing->ai = NULL;
if(outgoing->kai)
free_known_addresses(outgoing->kai);
outgoing->kai = NULL;
goto begin;
}
@ -570,6 +582,7 @@ begin:
// 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;
struct addrinfo *oai = NULL;
for splay_each(edge_t, e, n->edge_tree) {
if(!e->reverse)
@ -585,16 +598,15 @@ static struct addrinfo *get_known_addresses(node_t *n) {
if(found)
continue;
struct addrinfo *nai = xzalloc(sizeof *nai);
if(ai)
ai->ai_next = nai;
ai = nai;
oai = ai;
ai = xzalloc(sizeof *ai);
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);
ai->ai_next = oai;
}
return ai;
@ -621,8 +633,8 @@ void setup_outgoing_connection(outgoing_t *outgoing) {
if(!outgoing->cfg) {
if(n)
outgoing->aip = outgoing->ai = get_known_addresses(n);
if(!outgoing->ai) {
outgoing->aip = outgoing->kai = get_known_addresses(n);
if(!outgoing->kai) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "No address known for %s", outgoing->name);
goto remove;
}
@ -777,6 +789,9 @@ static void free_outgoing(outgoing_t *outgoing) {
if(outgoing->ai)
freeaddrinfo(outgoing->ai);
if(outgoing->kai)
free_known_addresses(outgoing->kai);
if(outgoing->config_tree)
exit_configuration(&outgoing->config_tree);

View file

@ -186,9 +186,9 @@ bool dump_nodes(connection_t *c) {
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)
snprintf(id + 2 * c, 3, "%02hhx", n->id.x[c]);
snprintf(id + 2 * c, 3, "%02x", 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,
send_request(c, "%d %d %s %s %s %d %d %d %d %x %x %s %s %d %d %d %d %ld", CONTROL, REQ_DUMP_NODES,
n->name, id, n->hostname ?: "unknown port unknown",
#ifdef DISABLE_LEGACY
0, 0, 0,

View file

@ -1,6 +1,6 @@
/*
cipher.c -- Symmetric block cipher handling
Copyright (C) 2007-2013 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2007-2017 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
@ -62,10 +62,6 @@ cipher_t *cipher_open_by_nid(int nid) {
return cipher_open(evp_cipher);
}
cipher_t *cipher_open_blowfish_ofb(void) {
return cipher_open(EVP_bf_ofb());
}
void cipher_close(cipher_t *cipher) {
if(!cipher)
return;
@ -81,6 +77,24 @@ size_t cipher_keylength(const cipher_t *cipher) {
return EVP_CIPHER_key_length(cipher->cipher) + EVP_CIPHER_iv_length(cipher->cipher);
}
uint64_t cipher_budget(const cipher_t *cipher) {
/* Hopefully some failsafe way to calculate the maximum amount of bytes to
send/receive with a given cipher before we might run into birthday paradox
attacks. Because we might use different modes, the block size of the mode
might be 1 byte. In that case, use the IV length. Ensure the whole thing
is limited to what can be represented with a 64 bits integer.
*/
if(!cipher || !cipher->cipher)
return UINT64_MAX; // NULL cipher
int ivlen = EVP_CIPHER_iv_length(cipher->cipher);
int blklen = EVP_CIPHER_block_size(cipher->cipher);
int len = blklen > 1 ? blklen : ivlen > 1 ? ivlen : 8;
int bits = len * 4 - 1;
return bits < 64 ? UINT64_C(1) << bits : UINT64_MAX;
}
size_t cipher_blocksize(const cipher_t *cipher) {
if(!cipher || !cipher->cipher)
return 1;
@ -123,7 +137,7 @@ bool cipher_encrypt(cipher_t *cipher, const void *indata, size_t inlen, void *ou
int len, pad;
if(EVP_EncryptInit_ex(cipher->ctx, NULL, NULL, NULL, NULL)
&& EVP_EncryptUpdate(cipher->ctx, (unsigned char *)outdata, &len, indata, inlen)
&& EVP_EncryptFinal(cipher->ctx, (unsigned char *)outdata + len, &pad)) {
&& EVP_EncryptFinal_ex(cipher->ctx, (unsigned char *)outdata + len, &pad)) {
if(outlen) *outlen = len + pad;
return true;
}
@ -144,7 +158,7 @@ bool cipher_decrypt(cipher_t *cipher, const void *indata, size_t inlen, void *ou
int len, pad;
if(EVP_DecryptInit_ex(cipher->ctx, NULL, NULL, NULL, NULL)
&& EVP_DecryptUpdate(cipher->ctx, (unsigned char *)outdata, &len, indata, inlen)
&& EVP_DecryptFinal(cipher->ctx, (unsigned char *)outdata + len, &pad)) {
&& EVP_DecryptFinal_ex(cipher->ctx, (unsigned char *)outdata + len, &pad)) {
if(outlen) *outlen = len + pad;
return true;
}

View file

@ -1,6 +1,6 @@
/*
digest.c -- Digest handling
Copyright (C) 2007-2013 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2007-2016 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
@ -64,10 +64,6 @@ digest_t *digest_open_by_nid(int nid, int maclength) {
return digest_open(evp_md, maclength);
}
digest_t *digest_open_sha1(int maclength) {
return digest_open(EVP_sha1(), maclength);
}
bool digest_set_key(digest_t *digest, const void *key, size_t len) {
digest->key = xrealloc(digest->key, len);
memcpy(digest->key, key, len);

View file

@ -1,7 +1,7 @@
/*
protocol.h -- header for protocol.c
Copyright (C) 1999-2005 Ivo Timmermans,
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
2000-2017 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
@ -62,6 +62,7 @@ extern bool tunnelserver;
extern bool strictsubnets;
extern bool experimental;
extern int invitation_lifetime;
extern ecdsa_t *invitation_key;
/* Maximum size of strings in a request.

View file

@ -1,7 +1,7 @@
/*
protocol_auth.c -- handle the meta-protocol, authentication
Copyright (C) 1999-2005 Ivo Timmermans,
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
2000-2017 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
@ -47,6 +47,7 @@
#include "ed25519/sha512.h"
int invitation_lifetime;
ecdsa_t *invitation_key = NULL;
static bool send_proxyrequest(connection_t *c) {
@ -180,21 +181,18 @@ static bool finalize_invitation(connection_t *c, const char *data, uint16_t len)
logger(DEBUG_CONNECTIONS, LOG_INFO, "Key succesfully received from %s (%s)", c->name, c->hostname);
// Call invitation-accepted script
char *envp[7] = {NULL};
environment_t env;
char *address, *port;
xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
xasprintf(&envp[1], "DEVICE=%s", device ? : "");
xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
xasprintf(&envp[3], "NODE=%s", c->name);
environment_init(&env);
environment_add(&env, "NODE=%s", c->name);
sockaddr2str(&c->address, &address, &port);
xasprintf(&envp[4], "REMOTEADDRESS=%s", address);
xasprintf(&envp[5], "NAME=%s", myself->name);
environment_add(&env, "REMOTEADDRESS=%s", address);
environment_add(&env, "NAME=%s", myself->name);
execute_script("invitation-accepted", envp);
execute_script("invitation-accepted", &env);
for(int i = 0; envp[i] && i < 7; i++)
free(envp[i]);
environment_exit(&env);
sptps_send_record(&c->sptps, 2, data, 0);
return true;
@ -235,6 +233,18 @@ static bool receive_invitation_sptps(void *handle, uint8_t type, const void *dat
return false;
}
// Check the timestamp of the invitation
struct stat st;
if(stat(usedname, &st)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not stat %s", usedname);
return false;
}
if(st.st_mtime + invitation_lifetime < now.tv_sec) {
logger(DEBUG_ALWAYS, LOG_ERR, "Peer %s tried to use expired invitation %s", c->hostname, cookie);
return false;
}
// Open the renamed file
FILE *f = fopen(usedname, "r");
if(!f) {
@ -284,7 +294,7 @@ static bool receive_invitation_sptps(void *handle, uint8_t type, const void *dat
bool id_h(connection_t *c, const char *request) {
char name[MAX_STRING_SIZE];
if(sscanf(request, "%*d " MAX_STRING " %d.%d", name, &c->protocol_major, &c->protocol_minor) < 2) {
if(sscanf(request, "%*d " MAX_STRING " %2d.%3d", name, &c->protocol_major, &c->protocol_minor) < 2) {
logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ID", c->name,
c->hostname);
return false;
@ -421,10 +431,24 @@ bool send_metakey(connection_t *c) {
if(!read_rsa_public_key(c))
return false;
if(!(c->outcipher = cipher_open_blowfish_ofb()))
/* We need to use a stream mode for the meta protocol. Use AES for this,
but try to match the key size with the one from the cipher selected
by Cipher.
*/
int keylen = cipher_keylength(myself->incipher);
if(keylen <= 16)
c->outcipher = cipher_open_by_name("aes-128-cfb");
else if(keylen <= 24)
c->outcipher = cipher_open_by_name("aes-192-cfb");
else
c->outcipher = cipher_open_by_name("aes-256-cfb");
if(!c)
return false;
if(!(c->outdigest = digest_open_sha1(-1)))
c->outbudget = cipher_budget(c->outcipher);
if(!(c->outdigest = digest_open_by_name("sha256", -1)))
return false;
const size_t len = rsa_size(c->rsa);
@ -536,6 +560,8 @@ bool metakey_h(connection_t *c, const char *request) {
c->incipher = NULL;
}
c->inbudget = cipher_budget(c->incipher);
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);
@ -872,8 +898,10 @@ bool ack_h(connection_t *c, const char *request) {
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
else {
sockaddr_setport(&local_sa, myport);
c->edge->local_address = local_sa;
}
c->edge->weight = (weight + c->estimated_weight) / 2;
c->edge->connection = c;
c->edge->options = c->options;

View file

@ -132,63 +132,52 @@ bool add_edge_h(connection_t *c, const char *request) {
e = lookup_edge(from, to);
if(e) {
if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &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);
send_add_edge(c, e);
sockaddrfree(&local_address);
return true;
} else {
logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) which does not match existing entry",
"ADD_EDGE", c->name, c->hostname);
e->options = options;
if(sockaddrcmp(&e->address, &address)) {
sockaddrfree(&e->address);
e->address = address;
}
if(e->weight != weight) {
splay_node_t *node = splay_unlink(edge_weight_tree, e);
e->weight = weight;
splay_insert_node(edge_weight_tree, node);
}
bool new_address = sockaddrcmp(&e->address, &address);
// local_address.sa.sa_family will be 0 if we got it from older tinc versions
// local_address.sa.sa_family will be 255 (AF_UNKNOWN) if we got it from newer versions
// but for edge which does not have local_address
bool new_local_address = local_address.sa.sa_family && local_address.sa.sa_family != AF_UNKNOWN &&
sockaddrcmp(&e->local_address, &local_address);
goto done;
}
} else if(sockaddrcmp(&e->local_address, &local_address)) {
if(from == myself) {
if(e->local_address.sa.sa_family && local_address.sa.sa_family) {
// Someone has the wrong local address for ourself. Correct then.
logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself which does not match existing entry",
"ADD_EDGE", c->name, c->hostname);
send_add_edge(c, e);
sockaddrfree(&local_address);
return true;
}
// Otherwise, just ignore it.
sockaddrfree(&local_address);
return true;
} else if(local_address.sa.sa_family && local_address.sa.sa_family != AF_UNKNOWN) {
// We learned a new local address for this edge.
// local_address.sa.sa_family will be 0 if we got it from older tinc versions
// local_address.sa.sa_family will be 255 (AF_UNKNOWN) if we got it from newer versions
// but for edge which does not have local_address
sockaddrfree(&e->local_address);
e->local_address = local_address;
// Tell others about it.
if(!tunnelserver)
forward_request(c, request);
return true;
} else {
sockaddrfree(&local_address);
return true;
}
} else {
if(e->weight == weight && e->options == options && !new_address && !new_local_address) {
sockaddrfree(&address);
sockaddrfree(&local_address);
return true;
}
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);
send_add_edge(c, e);
sockaddrfree(&address);
sockaddrfree(&local_address);
return true;
}
logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) which does not match existing entry",
"ADD_EDGE", c->name, c->hostname);
e->options = options;
if(new_address) {
sockaddrfree(&e->address);
e->address = address;
} else {
sockaddrfree(&address);
}
if(new_local_address) {
sockaddrfree(&e->local_address);
e->local_address = local_address;
} else {
sockaddrfree(&local_address);
}
if(e->weight != weight) {
splay_node_t *node = splay_unlink(edge_weight_tree, e);
e->weight = weight;
splay_insert_node(edge_weight_tree, node);
}
} else if(from == myself) {
logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself which does not exist",
"ADD_EDGE", c->name, c->hostname);
@ -198,20 +187,20 @@ bool add_edge_h(connection_t *c, const char *request) {
e->to = to;
send_del_edge(c, e);
free_edge(e);
sockaddrfree(&address);
sockaddrfree(&local_address);
return true;
} else {
e = new_edge();
e->from = from;
e->to = to;
e->address = address;
e->local_address = local_address;
e->options = options;
e->weight = weight;
edge_add(e);
}
e = new_edge();
e->from = from;
e->to = to;
e->address = address;
e->local_address = local_address;
e->options = options;
e->weight = weight;
edge_add(e);
done:
/* Tell the rest about the new edge */
if(!tunnelserver)

View file

@ -1,7 +1,7 @@
/*
protocol_key.c -- handle the meta-protocol, key exchange
Copyright (C) 1999-2005 Ivo Timmermans,
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
2000-2017 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
@ -356,7 +356,7 @@ bool ans_key_h(connection_t *c, const char *request) {
char key[MAX_STRING_SIZE];
char address[MAX_STRING_SIZE] = "";
char port[MAX_STRING_SIZE] = "";
int cipher, digest, maclength, compression, keylen;
int cipher, digest, maclength, compression;
node_t *from, *to;
if(sscanf(request, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %d %d "MAX_STRING" "MAX_STRING,
@ -489,7 +489,7 @@ bool ans_key_h(connection_t *c, const char *request) {
/* Process key */
keylen = hex2bin(key, key, sizeof key);
int keylen = hex2bin(key, key, sizeof key);
if(keylen != (from->outcipher ? cipher_keylength(from->outcipher) : 1)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name, from->hostname);

View file

@ -135,7 +135,7 @@ bool send_tcppacket(connection_t *c, const vpn_packet_t *packet) {
if(2.0 * c->outbuf.len / (float)maxoutbufsize - 1 > (float)rand()/(float)RAND_MAX)
return true;
if(!send_request(c, "%d %hd", PACKET, packet->len))
if(!send_request(c, "%d %d", PACKET, packet->len))
return false;
return send_meta(c, (char *)DATA(packet), packet->len);
@ -194,6 +194,11 @@ bool send_udp_info(node_t *from, node_t *to) {
farther than the static relay. */
to = (to->via == myself) ? to->nexthop : to->via;
if (to == NULL) {
logger(DEBUG_ALWAYS, LOG_ERR, "Something went wrong when selecting relay - possible fake UDP_INFO");
return false;
}
/* Skip cases where sending UDP info messages doesn't make sense.
This is done here in order to avoid repeating the same logic in multiple callsites. */

View file

@ -510,7 +510,7 @@ static void route_broadcast(node_t *source, vpn_packet_t *packet) {
static void fragment_ipv4_packet(node_t *dest, vpn_packet_t *packet, length_t ether_size) {
struct ip ip;
vpn_packet_t fragment;
int len, maxlen, todo;
int maxlen, todo;
uint8_t *offset;
uint16_t ip_off, origf;
@ -537,7 +537,7 @@ static void fragment_ipv4_packet(node_t *dest, vpn_packet_t *packet, length_t et
ip_off &= IP_OFFMASK;
while(todo) {
len = todo > maxlen ? maxlen : todo;
int len = todo > maxlen ? maxlen : todo;
memcpy(DATA(&fragment) + ether_size + ip_size, offset, len);
todo -= len;
offset += len;
@ -683,6 +683,9 @@ static void route_ipv6(node_t *source, vpn_packet_t *packet) {
if(!do_decrement_ttl(source, packet))
return;
if(priorityinheritance)
packet->priority = ((DATA(packet)[14] & 0x0f) << 4) | (DATA(packet)[15] >> 4);
via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
if(via == source) {
@ -954,8 +957,12 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
uint16_t type = DATA(packet)[12] << 8 | DATA(packet)[13];
if(priorityinheritance && type == ETH_P_IP && packet->len >= ether_size + ip_size)
packet->priority = DATA(packet)[15];
if(priorityinheritance) {
if(type == ETH_P_IP && packet->len >= ether_size + ip_size)
packet->priority = DATA(packet)[15];
else if(type == ETH_P_IPV6 && packet->len >= ether_size + ip6_size)
packet->priority = ((DATA(packet)[14] & 0x0f) << 4) | (DATA(packet)[15] >> 4);
}
// Handle packets larger than PMTU

View file

@ -1,7 +1,7 @@
/*
script.c -- call an external script
Copyright (C) 1999-2005 Ivo Timmermans,
2000-2015 Guus Sliepen <guus@tinc-vpn.org>
2000-2017 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
@ -21,6 +21,7 @@
#include "system.h"
#include "conf.h"
#include "device.h"
#include "logger.h"
#include "names.h"
#include "script.h"
@ -63,7 +64,58 @@ static void putenv(const char *p) {}
static void unputenv(const char *p) {}
#endif
bool execute_script(const char *name, char **envp) {
static const int min_env_size = 10;
int environment_add(environment_t *env, const char *format, ...) {
if(env->n >= env->size) {
env->size = env->n ? env->n * 2 : min_env_size;
env->entries = xrealloc(env->entries, env->size * sizeof *env->entries);
}
if(format) {
va_list ap;
va_start(ap, format);
vasprintf(&env->entries[env->n], format, ap);
va_end(ap);
} else {
env->entries[env->n] = NULL;
}
return env->n++;
}
void environment_update(environment_t *env, int pos, const char *format, ...) {
free(env->entries[pos]);
va_list ap;
va_start(ap, format);
vasprintf(&env->entries[pos], format, ap);
va_end(ap);
}
void environment_init(environment_t *env) {
env->n = 0;
env->size = min_env_size;
env->entries = xzalloc(env->size * sizeof *env->entries);
if(netname)
environment_add(env, "NETNAME=%s", netname);
if(myname)
environment_add(env, "NAME=%s", myname);
if(device)
environment_add(env, "DEVICE=%s", device);
if(iface)
environment_add(env, "INTERFACE=%s", iface);
if(debug_level >= 0)
environment_add(env, "DEBUG=%d", debug_level);
}
void environment_exit(environment_t *env) {
for(int i = 0; i < env->n; i++)
free(env->entries[i]);
free(env->entries);
}
bool execute_script(const char *name, environment_t *env) {
char scriptname[PATH_MAX];
char *command;
@ -107,8 +159,8 @@ bool execute_script(const char *name, char **envp) {
/* Set environment */
for(int i = 0; envp[i]; i++)
putenv(envp[i]);
for(int i = 0; i < env->n; i++)
putenv(env->entries[i]);
if(scriptinterpreter)
xasprintf(&command, "%s \"%s\"", scriptinterpreter, scriptname);
@ -121,8 +173,8 @@ bool execute_script(const char *name, char **envp) {
/* Unset environment */
for(int i = 0; envp[i]; i++)
unputenv(envp[i]);
for(int i = 0; i < env->n; i++)
unputenv(env->entries[i]);
if(status != -1) {
#ifdef WEXITSTATUS

View file

@ -1,7 +1,7 @@
/*
script.h -- header file for script.c
Copyright (C) 1999-2005 Ivo Timmermans,
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
2000-2017 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
@ -21,6 +21,18 @@
#ifndef __TINC_SCRIPT_H__
#define __TINC_SCRIPT_H__
extern bool execute_script(const char *, char **);
typedef struct environment {
int n;
int size;
char **entries;
} environment_t;
extern int environment_add(environment_t *env, const char *format, ...);
extern int environment_placeholder(environment_t *env);
extern void environment_update(environment_t *env, int pos, const char *format, ...);
extern void environment_init(environment_t *env);
extern void environment_exit(environment_t *env);
extern bool execute_script(const char *name, environment_t *env);
#endif /* __TINC_SCRIPT_H__ */

View file

@ -24,6 +24,7 @@
#include <sys/stropts.h>
#include <sys/sockio.h>
#include <stropts.h>
#include "../conf.h"
#include "../device.h"
@ -41,6 +42,7 @@
#define DEFAULT_TUN_DEVICE "/dev/tun"
#define DEFAULT_TAP_DEVICE "/dev/tap"
#define IP_DEVICE "/dev/udp"
static enum {
DEVICE_TYPE_TUN,
@ -84,8 +86,8 @@ static bool setup_device(void) {
/* The following is black magic copied from OpenVPN. */
if((ip_fd = open("/dev/ip", O_RDWR, 0)) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s\n", "/dev/ip", strerror(errno));
if((ip_fd = open(IP_DEVICE, O_RDWR, 0)) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s\n", IP_DEVICE, strerror(errno));
return false;
}
@ -203,7 +205,7 @@ static bool setup_device(void) {
/* Push arp module to ip_fd */
if(ioctl(ip_fd, I_PUSH, "arp") < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not push ARP module onto %s!", "/dev/ip");
logger(DEBUG_ALWAYS, LOG_ERR, "Could not push ARP module onto %s!", IP_DEVICE);
return false;
}
@ -295,11 +297,16 @@ static void close_device(void) {
}
static bool read_packet(vpn_packet_t *packet) {
int inlen;
int result;
struct strbuf sbuf;
int f = 0;
switch(device_type) {
case DEVICE_TYPE_TUN:
if((inlen = read(device_fd, DATA(packet) + 14, MTU - 14)) <= 0) {
sbuf.maxlen = MTU - 14;
sbuf.buf = (char *)DATA(packet) + 14;
if((result = getmsg(device_fd, NULL, &sbuf, &f)) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info, device, strerror(errno));
return false;
}
@ -319,16 +326,19 @@ static bool read_packet(vpn_packet_t *packet) {
}
memset(DATA(packet), 0, 12);
packet->len = inlen + 14;
packet->len = sbuf.len + 14;
break;
case DEVICE_TYPE_TAP:
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));
sbuf.maxlen = MTU;
sbuf.buf = (char *)DATA(packet);
if((result = getmsg(device_fd, NULL, &sbuf, &f)) < 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, device, strerror(errno));
return false;
}
packet->len = inlen + 14;
packet->len = sbuf.len;
break;
default:
@ -343,17 +353,25 @@ static bool read_packet(vpn_packet_t *packet) {
static bool write_packet(vpn_packet_t *packet) {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s", packet->len, device_info);
struct strbuf sbuf;
switch(device_type) {
case DEVICE_TYPE_TUN:
if(write(device_fd, DATA(packet) + 14, packet->len - 14) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno));
sbuf.len = packet->len - 14;
sbuf.buf = (char *)DATA(packet) + 14;
if(putmsg(device_fd, NULL, &sbuf, 0) < 0) {
logger(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, DATA(packet), packet->len) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno));
sbuf.len = packet->len;
sbuf.buf = (char *)DATA(packet);
if(putmsg(device_fd, NULL, &sbuf, 0) < 0) {
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno));
return false;
}
break;

View file

@ -44,6 +44,7 @@ static bool readonly;
static bool writeonly;
static int in = 0;
static int out = 1;
static int addressfamily = AF_UNSPEC;
static bool send_data(void *handle, uint8_t type, const void *data, size_t len) {
char hex[len * 2 + 1];
@ -58,7 +59,7 @@ static bool send_data(void *handle, uint8_t type, const void *data, size_t len)
static bool receive_record(void *handle, uint8_t type, const void *data, uint16_t len) {
if(verbose)
fprintf(stderr, "Received type %d record of %hu bytes:\n", type, len);
fprintf(stderr, "Received type %d record of %u bytes:\n", type, len);
if(!writeonly)
write(out, data, len);
return true;
@ -93,6 +94,8 @@ static void usage() {
" -R, --replay-window N Set replay window to N bytes.\n"
" -s, --special Enable special handling of lines starting with #, ^ and $.\n"
" -v, --verbose Display debug messages.\n"
" -4 Use IPv4.\n"
" -6 Use IPv6.\n"
"\n");
fprintf(stderr, "Report bugs to tinc@tinc-vpn.org.\n");
}
@ -110,7 +113,7 @@ int main(int argc, char *argv[]) {
ecdsa_t *mykey = NULL, *hiskey = NULL;
bool quit = false;
while((r = getopt_long(argc, argv, "dqrstwL:W:v", long_options, &option_index)) != EOF) {
while((r = getopt_long(argc, argv, "dqrstwL:W:v46", long_options, &option_index)) != EOF) {
switch (r) {
case 0: /* long option */
break;
@ -161,6 +164,14 @@ int main(int argc, char *argv[]) {
usage();
return 1;
case '4': /* IPv4 */
addressfamily = AF_INET;
break;
case '6': /* IPv6 */
addressfamily = AF_INET6;
break;
case 1: /* help */
usage();
return 0;
@ -212,7 +223,7 @@ int main(int argc, char *argv[]) {
struct addrinfo *ai, hint;
memset(&hint, 0, sizeof hint);
hint.ai_family = AF_UNSPEC;
hint.ai_family = addressfamily;
hint.ai_socktype = datagram ? SOCK_DGRAM : SOCK_STREAM;
hint.ai_protocol = datagram ? IPPROTO_UDP : IPPROTO_TCP;
hint.ai_flags = initiator ? 0 : AI_PASSIVE;

View file

@ -1,6 +1,6 @@
/*
subnet.c -- handle subnet lookups and lists
Copyright (C) 2000-2013 Guus Sliepen <guus@tinc-vpn.org>,
Copyright (C) 2000-2017 Guus Sliepen <guus@tinc-vpn.org>,
2000-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify
@ -206,22 +206,20 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) {
// Prepare environment variables to be passed to the script
char *envp[10] = {NULL};
int n = 0;
xasprintf(&envp[n++], "NETNAME=%s", netname ? : "");
xasprintf(&envp[n++], "DEVICE=%s", device ? : "");
xasprintf(&envp[n++], "INTERFACE=%s", iface ? : "");
xasprintf(&envp[n++], "NODE=%s", owner->name);
environment_t env;
environment_init(&env);
environment_add(&env, "NODE=%s", owner->name);
if(owner != myself) {
sockaddr2str(&owner->address, &address, &port);
xasprintf(&envp[n++], "REMOTEADDRESS=%s", address);
xasprintf(&envp[n++], "REMOTEPORT=%s", port);
environment_add(&env, "REMOTEADDRESS=%s", address);
environment_add(&env, "REMOTEPORT=%s", port);
free(port);
free(address);
}
xasprintf(&envp[n++], "NAME=%s", myself->name);
int env_subnet = environment_add(&env, NULL);
int env_weight = environment_add(&env, NULL);
name = up ? "subnet-up" : "subnet-down";
@ -238,12 +236,10 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) {
weight = empty;
// Prepare the SUBNET and WEIGHT variables
free(envp[n]);
free(envp[n + 1]);
xasprintf(&envp[n], "SUBNET=%s", netstr);
xasprintf(&envp[n + 1], "WEIGHT=%s", weight);
environment_update(&env, env_subnet, "SUBNET=%s", netstr);
environment_update(&env, env_weight, "WEIGHT=%s", weight);
execute_script(name, envp);
execute_script(name, &env);
}
} else {
if(net2str(netstr, sizeof netstr, subnet)) {
@ -255,15 +251,14 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) {
weight = empty;
// Prepare the SUBNET and WEIGHT variables
xasprintf(&envp[n], "SUBNET=%s", netstr);
xasprintf(&envp[n + 1], "WEIGHT=%s", weight);
environment_update(&env, env_subnet, "SUBNET=%s", netstr);
environment_update(&env, env_weight, "WEIGHT=%s", weight);
execute_script(name, envp);
execute_script(name, &env);
}
}
for(int i = 0; envp[i] && i < 9; i++)
free(envp[i]);
environment_exit(&env);
}
bool dump_subnets(connection_t *c) {

View file

@ -372,7 +372,7 @@ bool net2str(char *netstr, int len, const subnet_t *subnet) {
result = snprintf(netstr, len, *format, ":::");
i += max_zero_length;
} else {
result = snprintf(netstr, len, "%hx:", ntohs(subnet->net.ipv6.address.x[i]));
result = snprintf(netstr, len, "%x:", ntohs(subnet->net.ipv6.address.x[i]));
i++;
}
netstr += result;

View file

@ -1,6 +1,6 @@
/*
tincctl.c -- Controlling a running tincd
Copyright (C) 2007-2016 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2007-2017 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
@ -74,6 +74,9 @@ bool netnamegiven = false;
char *scriptinterpreter = NULL;
char *scriptextension = "";
static char *prompt;
char *device = NULL;
char *iface = NULL;
int debug_level = -1;
static struct option const long_options[] = {
{"batch", no_argument, NULL, 'b'},
@ -89,7 +92,7 @@ static struct option const long_options[] = {
static void version(void) {
printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
BUILD_VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
printf("Copyright (C) 1998-2016 Ivo Timmermans, Guus Sliepen and others.\n"
printf("Copyright (C) 1998-2017 Ivo Timmermans, Guus Sliepen and others.\n"
"See the AUTHORS file for a complete list.\n\n"
"tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
"and you are welcome to redistribute it under certain conditions;\n"
@ -446,11 +449,13 @@ static bool rsa_keygen(int bits, bool ask) {
// Make sure the key size is a multiple of 8 bits.
bits &= ~0x7;
// Force them to be between 1024 and 8192 bits long.
if(bits < 1024)
bits = 1024;
if(bits > 8192)
bits = 8192;
// Make sure that a valid key size is used.
if(bits < 1024 || bits > 8192) {
fprintf(stderr, "Invalid key size %d specified! It should be between 1024 and 8192 bits.\n", bits);
return false;
} else if(bits < 2048) {
fprintf(stderr, "WARNING: generating a weak %d bits RSA key! 2048 or more bits are recommended.\n", bits);
}
fprintf(stderr, "Generating %d bits keys:\n", bits);
@ -508,7 +513,7 @@ bool recvline(int fd, char *line, size_t len) {
char *newline = NULL;
if(!fd)
abort();
return false;
while(!(newline = memchr(buffer, '\n', blen))) {
int result = recv(fd, buffer + blen, sizeof buffer - blen, 0);
@ -719,6 +724,8 @@ bool connect_tincd(bool verbose) {
}
fclose(f);
#ifndef HAVE_MINGW
if ((pid == 0) || (kill(pid, 0) && (errno == ESRCH))) {
fprintf(stderr, "Could not find tincd running at pid %d\n", pid);
/* clean up the stale socket and pid file */
@ -727,7 +734,6 @@ bool connect_tincd(bool verbose) {
return false;
}
#ifndef HAVE_MINGW
struct sockaddr_un sa;
sa.sun_family = AF_UNIX;
strncpy(sa.sun_path, unixsocketname, sizeof sa.sun_path);
@ -797,7 +803,7 @@ bool connect_tincd(bool verbose) {
char data[4096];
int version;
if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %s %d", &code, data, &version) != 3 || code != 0) {
if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %4095s %d", &code, data, &version) != 3 || code != 0) {
if(verbose)
fprintf(stderr, "Cannot read greeting from control socket: %s\n", sockstrerror(sockerrno));
close(fd);
@ -945,11 +951,11 @@ static int cmd_stop(int argc, char *argv[]) {
if(!connect_tincd(true)) {
if(pid) {
if(kill(pid, SIGTERM)) {
fprintf(stderr, "Could not send TERM signal to process with PID %u: %s\n", pid, strerror(errno));
fprintf(stderr, "Could not send TERM signal to process with PID %d: %s\n", pid, strerror(errno));
return 1;
}
fprintf(stderr, "Sent TERM signal to process with PID %u.\n", pid);
fprintf(stderr, "Sent TERM signal to process with PID %d.\n", pid);
waitpid(pid, NULL, 0);
return 0;
}
@ -1024,7 +1030,6 @@ static int dump_invitations(void) {
FILE *f = fopen(fname, "r");
if(!f) {
fprintf(stderr, "Cannot open %s: %s\n", fname, strerror(errno));
fclose(f);
continue;
}
@ -1113,7 +1118,7 @@ static int cmd_dump(int argc, char *argv[]) {
while(recvline(fd, line, sizeof line)) {
char node1[4096], node2[4096];
int n = sscanf(line, "%d %d %s %s", &code, &req, node1, node2);
int n = sscanf(line, "%d %d %4095s %4095s", &code, &req, node1, node2);
if(n == 2) {
if(do_graph && req == REQ_DUMP_NODES)
continue;
@ -1145,7 +1150,7 @@ static int cmd_dump(int argc, char *argv[]) {
switch(req) {
case REQ_DUMP_NODES: {
int n = sscanf(line, "%*d %*d %s %s %s port %s %d %d %d %d %x %x %s %s %d %hd %hd %hd %ld", node, id, host, port, &cipher, &digest, &maclength, &compression, &options, &status_int, nexthop, via, &distance, &pmtu, &minmtu, &maxmtu, &last_state_change);
int n = sscanf(line, "%*d %*d %4095s %4095s %4095s port %4095s %d %d %d %d %x %x %4095s %4095s %d %hd %hd %hd %ld", node, id, host, port, &cipher, &digest, &maclength, &compression, &options, &status_int, nexthop, via, &distance, &pmtu, &minmtu, &maxmtu, &last_state_change);
if(n != 17) {
fprintf(stderr, "Unable to parse node dump from tincd: %s\n", line);
return 1;
@ -1169,13 +1174,13 @@ static int cmd_dump(int argc, char *argv[]) {
} else {
if(only_reachable && !status.reachable)
continue;
printf("%s id %s at %s port %s cipher %d digest %d maclength %d compression %d options %x status %04x nexthop %s via %s distance %d pmtu %hd (min %hd max %hd)\n",
printf("%s id %s at %s port %s cipher %d digest %d maclength %d compression %d options %x status %04x nexthop %s via %s distance %d pmtu %d (min %d max %d)\n",
node, id, host, port, cipher, digest, maclength, compression, options, status_int, nexthop, via, distance, pmtu, minmtu, maxmtu);
}
} break;
case REQ_DUMP_EDGES: {
int n = sscanf(line, "%*d %*d %s %s %s port %s %s port %s %x %d", from, to, host, port, local_host, local_port, &options, &weight);
int n = sscanf(line, "%*d %*d %4095s %4095s %4095s port %4095s %4095s port %4095s %x %d", from, to, host, port, local_host, local_port, &options, &weight);
if(n != 8) {
fprintf(stderr, "Unable to parse edge dump from tincd.\n");
return 1;
@ -1193,7 +1198,7 @@ static int cmd_dump(int argc, char *argv[]) {
} break;
case REQ_DUMP_SUBNETS: {
int n = sscanf(line, "%*d %*d %s %s", subnet, node);
int n = sscanf(line, "%*d %*d %4095s %4095s", subnet, node);
if(n != 2) {
fprintf(stderr, "Unable to parse subnet dump from tincd.\n");
return 1;
@ -1202,7 +1207,7 @@ static int cmd_dump(int argc, char *argv[]) {
} break;
case REQ_DUMP_CONNECTIONS: {
int n = sscanf(line, "%*d %*d %s %s port %s %x %d %x", node, host, port, &options, &socket, &status_int);
int n = sscanf(line, "%*d %*d %4095s %4095s port %4095s %x %d %x", node, host, port, &options, &socket, &status_int);
if(n != 6) {
fprintf(stderr, "Unable to parse connection dump from tincd.\n");
return 1;
@ -1485,9 +1490,11 @@ const var_t variables[] = {
{"Hostnames", VAR_SERVER},
{"IffOneQueue", VAR_SERVER},
{"Interface", VAR_SERVER},
{"InvitationExpire", VAR_SERVER},
{"KeyExpire", VAR_SERVER},
{"ListenAddress", VAR_SERVER | VAR_MULTIPLE},
{"LocalDiscovery", VAR_SERVER},
{"LogLevel", VAR_SERVER},
{"MACExpire", VAR_SERVER},
{"MaxConnectionBurst", VAR_SERVER},
{"MaxOutputBufferSize", VAR_SERVER},
@ -2227,7 +2234,7 @@ static int cmd_import(int argc, char *argv[]) {
bool firstline = true;
while(fgets(buf, sizeof buf, in)) {
if(sscanf(buf, "Name = %s", name) == 1) {
if(sscanf(buf, "Name = %4095s", name) == 1) {
firstline = false;
if(!check_id(name)) {
@ -2719,7 +2726,7 @@ static char *complete_info(const char *text, int state) {
while(recvline(fd, line, sizeof line)) {
char item[4096];
int n = sscanf(line, "%d %d %s", &code, &req, item);
int n = sscanf(line, "%d %d %4095s", &code, &req, item);
if(n == 2) {
i++;
if(i >= 2)
@ -2820,8 +2827,6 @@ static int cmd_shell(int argc, char *argv[]) {
while(p && *p) {
if(nargc >= maxargs) {
fprintf(stderr, "next %p '%s', p %p '%s'\n", next, next, p, p);
abort();
maxargs *= 2;
nargv = xrealloc(nargv, maxargs * sizeof *nargv);
}

View file

@ -400,6 +400,9 @@ int main(int argc, char **argv) {
if(!read_server_config())
return 1;
if(!debug_level)
get_config_int(lookup_config(config_tree, "LogLevel"), &debug_level);
#ifdef HAVE_LZO
if(lzo_init() != LZO_E_OK) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error initializing LZO compressor!");

View file

@ -90,7 +90,7 @@ static bool update(int fd) {
ns->known = false;
while(recvline(fd, line, sizeof line)) {
int n = sscanf(line, "%d %d %s %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64, &code, &req, name, &in_packets, &in_bytes, &out_packets, &out_bytes);
int n = sscanf(line, "%d %d %4095s %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64, &code, &req, name, &in_packets, &in_bytes, &out_packets, &out_bytes);
if(n == 2)
return true;
@ -158,40 +158,54 @@ static int cmpu64(uint64_t a, uint64_t b) {
static int sortfunc(const void *a, const void *b) {
const nodestats_t *na = *(const nodestats_t **)a;
const nodestats_t *nb = *(const nodestats_t **)b;
int result;
switch(sortmode) {
case 1:
if(cumulative)
return -cmpu64(na->in_packets, nb->in_packets) ?: na->i - nb->i;
result = -cmpu64(na->in_packets, nb->in_packets);
else
return -cmpfloat(na->in_packets_rate, nb->in_packets_rate) ?: na->i - nb->i;
result = -cmpfloat(na->in_packets_rate, nb->in_packets_rate);
break;
case 2:
if(cumulative)
return -cmpu64(na->in_bytes, nb->in_bytes) ?: na->i - nb->i;
result = -cmpu64(na->in_bytes, nb->in_bytes);
else
return -cmpfloat(na->in_bytes_rate, nb->in_bytes_rate) ?: na->i - nb->i;
result = -cmpfloat(na->in_bytes_rate, nb->in_bytes_rate);
break;
case 3:
if(cumulative)
return -cmpu64(na->out_packets, nb->out_packets) ?: na->i - nb->i;
result = -cmpu64(na->out_packets, nb->out_packets);
else
return -cmpfloat(na->out_packets_rate, nb->out_packets_rate) ?: na->i - nb->i;
result = -cmpfloat(na->out_packets_rate, nb->out_packets_rate);
break;
case 4:
if(cumulative)
return -cmpu64(na->out_bytes, nb->out_bytes) ?: na->i - nb->i;
result = -cmpu64(na->out_bytes, nb->out_bytes);
else
return -cmpfloat(na->out_bytes_rate, nb->out_bytes_rate) ?: na->i - nb->i;
result = -cmpfloat(na->out_bytes_rate, nb->out_bytes_rate);
break;
case 5:
if(cumulative)
return -cmpu64(na->in_packets + na->out_packets, nb->in_packets + nb->out_packets) ?: na->i - nb->i;
result = -cmpu64(na->in_packets + na->out_packets, nb->in_packets + nb->out_packets);
else
return -cmpfloat(na->in_packets_rate + na->out_packets_rate, nb->in_packets_rate + nb->out_packets_rate) ?: na->i - nb->i;
result = -cmpfloat(na->in_packets_rate + na->out_packets_rate, nb->in_packets_rate + nb->out_packets_rate);
break;
case 6:
if(cumulative)
return -cmpu64(na->in_bytes + na->out_bytes, nb->in_bytes + nb->out_bytes) ?: na->i - nb->i;
result = -cmpu64(na->in_bytes + na->out_bytes, nb->in_bytes + nb->out_bytes);
else
return -cmpfloat(na->in_bytes_rate + na->out_bytes_rate, nb->in_bytes_rate + nb->out_bytes_rate) ?: na->i - nb->i;
result = -cmpfloat(na->in_bytes_rate + na->out_bytes_rate, nb->in_bytes_rate + nb->out_bytes_rate);
break;
default:
return strcmp(na->name, nb->name) ?: na->i - nb->i;
result = strcmp(na->name, nb->name);
break;
}
if(result)
return result;
else
return na->i - nb->i;
}
static void redraw(void) {

View file

@ -1,7 +1,7 @@
/*
device.c -- UML network socket
Copyright (C) 2002-2005 Ivo Timmermans,
2002-2013 Guus Sliepen <guus@tinc-vpn.org>
2002-2017 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
@ -228,7 +228,7 @@ static bool read_packet(vpn_packet_t *packet) {
return false;
}
if(connect(write_fd, &request.sock, sizeof request.sock) < 0) {
if(connect(write_fd, (struct sockkadr *)&request.sock, sizeof request.sock) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not bind write %s: %s", device_info, strerror(errno));
event_exit();
return false;

View file

@ -57,7 +57,7 @@ static struct UPNPDev *upnp_discover(int delay, int *error) {
#elif MINIUPNPC_API_VERSION <= 14
return upnpDiscover(delay, NULL NULL, false, false, 2, error);
return upnpDiscover(delay, NULL, NULL, false, false, 2, error);
#else