Import Upstream version 1.1~pre17

This commit is contained in:
Guus Sliepen 2019-08-26 13:44:53 +02:00
parent bc8ca65653
commit b511a112e6
216 changed files with 43313 additions and 18448 deletions

View file

@ -42,6 +42,7 @@ chacha_poly1305_SOURCES = \
chacha-poly1305/poly1305.c chacha-poly1305/poly1305.h
tincd_SOURCES = \
address_cache.c address_cache.h \
autoconnect.c autoconnect.h \
buffer.c buffer.h \
cipher.h \
@ -278,10 +279,11 @@ endif
tinc_LDADD = $(READLINE_LIBS) $(CURSES_LIBS)
sptps_speed_LDADD = -lrt
LIBS = @LIBS@ -lm
LIBS = @LIBS@ -lm $(CODE_COVERAGE_LIBS)
if TUNEMU
LIBS += -lpcap
endif
AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\" -iquote.
AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DRUNSTATEDIR=\"$(runstatedir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\" -iquote. $(CODE_COVERAGE_CFLAGS)
AM_CPPFLAGS = $(CODE_COVERAGE_CPPFLAGS)

View file

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.15.1 from Makefile.am.
# Makefile.in generated by automake 1.16.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2017 Free Software Foundation, Inc.
# Copyright (C) 1994-2018 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -202,6 +202,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/ax_cflags_warn_all.m4 \
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_check_link_flag.m4 \
$(top_srcdir)/m4/ax_code_coverage.m4 \
$(top_srcdir)/m4/ax_require_defined.m4 \
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/libgcrypt.m4 \
$(top_srcdir)/m4/lzo.m4 $(top_srcdir)/m4/miniupnpc.m4 \
@ -336,22 +337,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 = 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 \
am__tincd_SOURCES_DIST = address_cache.c address_cache.h 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 \
@ -384,15 +386,15 @@ am__tincd_SOURCES_DIST = autoconnect.c autoconnect.h buffer.c buffer.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 = 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) \
am_tincd_OBJECTS = address_cache.$(OBJEXT) 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) \
@ -423,7 +425,54 @@ am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES =
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/address_cache.Po \
./$(DEPDIR)/autoconnect.Po ./$(DEPDIR)/buffer.Po \
./$(DEPDIR)/conf.Po ./$(DEPDIR)/connection.Po \
./$(DEPDIR)/control.Po ./$(DEPDIR)/dropin.Po \
./$(DEPDIR)/dummy_device.Po ./$(DEPDIR)/edge.Po \
./$(DEPDIR)/event.Po ./$(DEPDIR)/fd_device.Po \
./$(DEPDIR)/fsck.Po ./$(DEPDIR)/getopt.Po \
./$(DEPDIR)/getopt1.Po ./$(DEPDIR)/graph.Po \
./$(DEPDIR)/hash.Po ./$(DEPDIR)/ifconfig.Po \
./$(DEPDIR)/info.Po ./$(DEPDIR)/invitation.Po \
./$(DEPDIR)/list.Po ./$(DEPDIR)/logger.Po ./$(DEPDIR)/meta.Po \
./$(DEPDIR)/multicast_device.Po ./$(DEPDIR)/names.Po \
./$(DEPDIR)/net.Po ./$(DEPDIR)/net_packet.Po \
./$(DEPDIR)/net_setup.Po ./$(DEPDIR)/net_socket.Po \
./$(DEPDIR)/netutl.Po ./$(DEPDIR)/node.Po \
./$(DEPDIR)/process.Po ./$(DEPDIR)/protocol.Po \
./$(DEPDIR)/protocol_auth.Po ./$(DEPDIR)/protocol_edge.Po \
./$(DEPDIR)/protocol_key.Po ./$(DEPDIR)/protocol_misc.Po \
./$(DEPDIR)/protocol_subnet.Po \
./$(DEPDIR)/raw_socket_device.Po ./$(DEPDIR)/route.Po \
./$(DEPDIR)/script.Po ./$(DEPDIR)/splay_tree.Po \
./$(DEPDIR)/sptps.Po ./$(DEPDIR)/sptps_keypair.Po \
./$(DEPDIR)/sptps_speed.Po ./$(DEPDIR)/sptps_test.Po \
./$(DEPDIR)/subnet.Po ./$(DEPDIR)/subnet_parse.Po \
./$(DEPDIR)/tincctl.Po ./$(DEPDIR)/tincd.Po ./$(DEPDIR)/top.Po \
./$(DEPDIR)/uml_device.Po ./$(DEPDIR)/upnp.Po \
./$(DEPDIR)/utils.Po ./$(DEPDIR)/vde_device.Po \
./$(DEPDIR)/version.Po bsd/$(DEPDIR)/device.Po \
bsd/$(DEPDIR)/tunemu.Po \
chacha-poly1305/$(DEPDIR)/chacha-poly1305.Po \
chacha-poly1305/$(DEPDIR)/chacha.Po \
chacha-poly1305/$(DEPDIR)/poly1305.Po \
cygwin/$(DEPDIR)/device.Po ed25519/$(DEPDIR)/ecdh.Po \
ed25519/$(DEPDIR)/ecdsa.Po ed25519/$(DEPDIR)/ecdsagen.Po \
ed25519/$(DEPDIR)/fe.Po ed25519/$(DEPDIR)/ge.Po \
ed25519/$(DEPDIR)/key_exchange.Po ed25519/$(DEPDIR)/keypair.Po \
ed25519/$(DEPDIR)/sc.Po ed25519/$(DEPDIR)/sha512.Po \
ed25519/$(DEPDIR)/sign.Po ed25519/$(DEPDIR)/verify.Po \
gcrypt/$(DEPDIR)/cipher.Po gcrypt/$(DEPDIR)/crypto.Po \
gcrypt/$(DEPDIR)/digest.Po gcrypt/$(DEPDIR)/prf.Po \
gcrypt/$(DEPDIR)/rsa.Po gcrypt/$(DEPDIR)/rsagen.Po \
linux/$(DEPDIR)/device.Po mingw/$(DEPDIR)/device.Po \
nolegacy/$(DEPDIR)/crypto.Po nolegacy/$(DEPDIR)/prf.Po \
openssl/$(DEPDIR)/cipher.Po openssl/$(DEPDIR)/crypto.Po \
openssl/$(DEPDIR)/digest.Po openssl/$(DEPDIR)/prf.Po \
openssl/$(DEPDIR)/rsa.Po openssl/$(DEPDIR)/rsagen.Po \
solaris/$(DEPDIR)/device.Po
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@ -478,6 +527,12 @@ AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@
CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@
CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
CODE_COVERAGE_LIBS = @CODE_COVERAGE_LIBS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CURSES_LIBS = @CURSES_LIBS@
@ -489,16 +544,18 @@ ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
GCOV = @GCOV@
GENHTML = @GENHTML@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LCOV = @LCOV@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@ -lm $(am__append_30)
LN_S = @LN_S@
LIBS = @LIBS@ -lm $(CODE_COVERAGE_LIBS) $(am__append_30)
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MINIUPNPC_LIBS = @MINIUPNPC_LIBS@
@ -513,6 +570,7 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
READLINE_LIBS = @READLINE_LIBS@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
@ -588,16 +646,17 @@ chacha_poly1305_SOURCES = \
chacha-poly1305/chacha-poly1305.c chacha-poly1305/chacha-poly1305.h \
chacha-poly1305/poly1305.c chacha-poly1305/poly1305.h
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 \
tincd_SOURCES = address_cache.c address_cache.h 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 \
@ -632,7 +691,8 @@ sptps_speed_SOURCES = logger.c logger.h sptps.c sptps.h sptps_speed.c \
@MINIUPNPC_TRUE@tincd_LDFLAGS = -pthread
tinc_LDADD = $(READLINE_LIBS) $(CURSES_LIBS)
sptps_speed_LDADD = -lrt
AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\" -iquote.
AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DRUNSTATEDIR=\"$(runstatedir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\" -iquote. $(CODE_COVERAGE_CFLAGS)
AM_CPPFLAGS = $(CODE_COVERAGE_CPPFLAGS)
all: all-am
.SUFFIXES:
@ -654,8 +714,8 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
@ -893,94 +953,101 @@ 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@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/control.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dropin.Po@am__quote@
@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@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/graph.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ifconfig.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/info.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/invitation.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logger.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/meta.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multicast_device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/names.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_packet.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_setup.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_socket.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netutl.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_auth.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_edge.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_key.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_misc.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_subnet.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/raw_socket_device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/route.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/splay_tree.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sptps.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sptps_keypair.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sptps_speed.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sptps_test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnet.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnet_parse.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tincctl.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tincd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/top.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uml_device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upnp.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vde_device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@bsd/$(DEPDIR)/device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@bsd/$(DEPDIR)/tunemu.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@chacha-poly1305/$(DEPDIR)/chacha-poly1305.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@chacha-poly1305/$(DEPDIR)/chacha.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@chacha-poly1305/$(DEPDIR)/poly1305.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@cygwin/$(DEPDIR)/device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/ecdh.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/ecdsa.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/ecdsagen.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/fe.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/ge.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/key_exchange.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/keypair.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/sc.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/sha512.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/sign.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/verify.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/cipher.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/crypto.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/digest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/prf.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/rsa.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/rsagen.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@linux/$(DEPDIR)/device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@mingw/$(DEPDIR)/device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@nolegacy/$(DEPDIR)/crypto.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@nolegacy/$(DEPDIR)/prf.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/cipher.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/crypto.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/digest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/prf.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/rsa.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/rsagen.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@solaris/$(DEPDIR)/device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/address_cache.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/autoconnect.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connection.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/control.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dropin.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dummy_device.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edge.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fd_device.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsck.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/graph.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ifconfig.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/info.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/invitation.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logger.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/meta.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multicast_device.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/names.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_packet.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_setup.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_socket.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netutl.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_auth.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_edge.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_key.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_misc.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_subnet.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/raw_socket_device.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/route.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/splay_tree.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sptps.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sptps_keypair.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sptps_speed.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sptps_test.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnet.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnet_parse.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tincctl.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tincd.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/top.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uml_device.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upnp.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vde_device.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@bsd/$(DEPDIR)/device.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@bsd/$(DEPDIR)/tunemu.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@chacha-poly1305/$(DEPDIR)/chacha-poly1305.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@chacha-poly1305/$(DEPDIR)/chacha.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@chacha-poly1305/$(DEPDIR)/poly1305.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@cygwin/$(DEPDIR)/device.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/ecdh.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/ecdsa.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/ecdsagen.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/fe.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/ge.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/key_exchange.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/keypair.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/sc.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/sha512.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/sign.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@ed25519/$(DEPDIR)/verify.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/cipher.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/crypto.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/digest.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/prf.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/rsa.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/rsagen.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@linux/$(DEPDIR)/device.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@mingw/$(DEPDIR)/device.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@nolegacy/$(DEPDIR)/crypto.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@nolegacy/$(DEPDIR)/prf.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/cipher.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/crypto.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/digest.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/prf.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/rsa.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/rsagen.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@solaris/$(DEPDIR)/device.Po@am__quote@ # am--include-marker
$(am__depfiles_remade):
@$(MKDIR_P) $(@D)
@echo '# dummy' >$@-t && $(am__mv) $@-t $@
am--depfiles: $(am__depfiles_remade)
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@ -1050,7 +1117,10 @@ cscopelist-am: $(am__tagged_files)
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
@ -1145,7 +1215,95 @@ 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)
-rm -f ./$(DEPDIR)/address_cache.Po
-rm -f ./$(DEPDIR)/autoconnect.Po
-rm -f ./$(DEPDIR)/buffer.Po
-rm -f ./$(DEPDIR)/conf.Po
-rm -f ./$(DEPDIR)/connection.Po
-rm -f ./$(DEPDIR)/control.Po
-rm -f ./$(DEPDIR)/dropin.Po
-rm -f ./$(DEPDIR)/dummy_device.Po
-rm -f ./$(DEPDIR)/edge.Po
-rm -f ./$(DEPDIR)/event.Po
-rm -f ./$(DEPDIR)/fd_device.Po
-rm -f ./$(DEPDIR)/fsck.Po
-rm -f ./$(DEPDIR)/getopt.Po
-rm -f ./$(DEPDIR)/getopt1.Po
-rm -f ./$(DEPDIR)/graph.Po
-rm -f ./$(DEPDIR)/hash.Po
-rm -f ./$(DEPDIR)/ifconfig.Po
-rm -f ./$(DEPDIR)/info.Po
-rm -f ./$(DEPDIR)/invitation.Po
-rm -f ./$(DEPDIR)/list.Po
-rm -f ./$(DEPDIR)/logger.Po
-rm -f ./$(DEPDIR)/meta.Po
-rm -f ./$(DEPDIR)/multicast_device.Po
-rm -f ./$(DEPDIR)/names.Po
-rm -f ./$(DEPDIR)/net.Po
-rm -f ./$(DEPDIR)/net_packet.Po
-rm -f ./$(DEPDIR)/net_setup.Po
-rm -f ./$(DEPDIR)/net_socket.Po
-rm -f ./$(DEPDIR)/netutl.Po
-rm -f ./$(DEPDIR)/node.Po
-rm -f ./$(DEPDIR)/process.Po
-rm -f ./$(DEPDIR)/protocol.Po
-rm -f ./$(DEPDIR)/protocol_auth.Po
-rm -f ./$(DEPDIR)/protocol_edge.Po
-rm -f ./$(DEPDIR)/protocol_key.Po
-rm -f ./$(DEPDIR)/protocol_misc.Po
-rm -f ./$(DEPDIR)/protocol_subnet.Po
-rm -f ./$(DEPDIR)/raw_socket_device.Po
-rm -f ./$(DEPDIR)/route.Po
-rm -f ./$(DEPDIR)/script.Po
-rm -f ./$(DEPDIR)/splay_tree.Po
-rm -f ./$(DEPDIR)/sptps.Po
-rm -f ./$(DEPDIR)/sptps_keypair.Po
-rm -f ./$(DEPDIR)/sptps_speed.Po
-rm -f ./$(DEPDIR)/sptps_test.Po
-rm -f ./$(DEPDIR)/subnet.Po
-rm -f ./$(DEPDIR)/subnet_parse.Po
-rm -f ./$(DEPDIR)/tincctl.Po
-rm -f ./$(DEPDIR)/tincd.Po
-rm -f ./$(DEPDIR)/top.Po
-rm -f ./$(DEPDIR)/uml_device.Po
-rm -f ./$(DEPDIR)/upnp.Po
-rm -f ./$(DEPDIR)/utils.Po
-rm -f ./$(DEPDIR)/vde_device.Po
-rm -f ./$(DEPDIR)/version.Po
-rm -f bsd/$(DEPDIR)/device.Po
-rm -f bsd/$(DEPDIR)/tunemu.Po
-rm -f chacha-poly1305/$(DEPDIR)/chacha-poly1305.Po
-rm -f chacha-poly1305/$(DEPDIR)/chacha.Po
-rm -f chacha-poly1305/$(DEPDIR)/poly1305.Po
-rm -f cygwin/$(DEPDIR)/device.Po
-rm -f ed25519/$(DEPDIR)/ecdh.Po
-rm -f ed25519/$(DEPDIR)/ecdsa.Po
-rm -f ed25519/$(DEPDIR)/ecdsagen.Po
-rm -f ed25519/$(DEPDIR)/fe.Po
-rm -f ed25519/$(DEPDIR)/ge.Po
-rm -f ed25519/$(DEPDIR)/key_exchange.Po
-rm -f ed25519/$(DEPDIR)/keypair.Po
-rm -f ed25519/$(DEPDIR)/sc.Po
-rm -f ed25519/$(DEPDIR)/sha512.Po
-rm -f ed25519/$(DEPDIR)/sign.Po
-rm -f ed25519/$(DEPDIR)/verify.Po
-rm -f gcrypt/$(DEPDIR)/cipher.Po
-rm -f gcrypt/$(DEPDIR)/crypto.Po
-rm -f gcrypt/$(DEPDIR)/digest.Po
-rm -f gcrypt/$(DEPDIR)/prf.Po
-rm -f gcrypt/$(DEPDIR)/rsa.Po
-rm -f gcrypt/$(DEPDIR)/rsagen.Po
-rm -f linux/$(DEPDIR)/device.Po
-rm -f mingw/$(DEPDIR)/device.Po
-rm -f nolegacy/$(DEPDIR)/crypto.Po
-rm -f nolegacy/$(DEPDIR)/prf.Po
-rm -f openssl/$(DEPDIR)/cipher.Po
-rm -f openssl/$(DEPDIR)/crypto.Po
-rm -f openssl/$(DEPDIR)/digest.Po
-rm -f openssl/$(DEPDIR)/prf.Po
-rm -f openssl/$(DEPDIR)/rsa.Po
-rm -f openssl/$(DEPDIR)/rsagen.Po
-rm -f solaris/$(DEPDIR)/device.Po
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
@ -1191,7 +1349,95 @@ install-ps-am:
installcheck-am: installcheck-sbinPROGRAMS
maintainer-clean: maintainer-clean-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)
-rm -f ./$(DEPDIR)/address_cache.Po
-rm -f ./$(DEPDIR)/autoconnect.Po
-rm -f ./$(DEPDIR)/buffer.Po
-rm -f ./$(DEPDIR)/conf.Po
-rm -f ./$(DEPDIR)/connection.Po
-rm -f ./$(DEPDIR)/control.Po
-rm -f ./$(DEPDIR)/dropin.Po
-rm -f ./$(DEPDIR)/dummy_device.Po
-rm -f ./$(DEPDIR)/edge.Po
-rm -f ./$(DEPDIR)/event.Po
-rm -f ./$(DEPDIR)/fd_device.Po
-rm -f ./$(DEPDIR)/fsck.Po
-rm -f ./$(DEPDIR)/getopt.Po
-rm -f ./$(DEPDIR)/getopt1.Po
-rm -f ./$(DEPDIR)/graph.Po
-rm -f ./$(DEPDIR)/hash.Po
-rm -f ./$(DEPDIR)/ifconfig.Po
-rm -f ./$(DEPDIR)/info.Po
-rm -f ./$(DEPDIR)/invitation.Po
-rm -f ./$(DEPDIR)/list.Po
-rm -f ./$(DEPDIR)/logger.Po
-rm -f ./$(DEPDIR)/meta.Po
-rm -f ./$(DEPDIR)/multicast_device.Po
-rm -f ./$(DEPDIR)/names.Po
-rm -f ./$(DEPDIR)/net.Po
-rm -f ./$(DEPDIR)/net_packet.Po
-rm -f ./$(DEPDIR)/net_setup.Po
-rm -f ./$(DEPDIR)/net_socket.Po
-rm -f ./$(DEPDIR)/netutl.Po
-rm -f ./$(DEPDIR)/node.Po
-rm -f ./$(DEPDIR)/process.Po
-rm -f ./$(DEPDIR)/protocol.Po
-rm -f ./$(DEPDIR)/protocol_auth.Po
-rm -f ./$(DEPDIR)/protocol_edge.Po
-rm -f ./$(DEPDIR)/protocol_key.Po
-rm -f ./$(DEPDIR)/protocol_misc.Po
-rm -f ./$(DEPDIR)/protocol_subnet.Po
-rm -f ./$(DEPDIR)/raw_socket_device.Po
-rm -f ./$(DEPDIR)/route.Po
-rm -f ./$(DEPDIR)/script.Po
-rm -f ./$(DEPDIR)/splay_tree.Po
-rm -f ./$(DEPDIR)/sptps.Po
-rm -f ./$(DEPDIR)/sptps_keypair.Po
-rm -f ./$(DEPDIR)/sptps_speed.Po
-rm -f ./$(DEPDIR)/sptps_test.Po
-rm -f ./$(DEPDIR)/subnet.Po
-rm -f ./$(DEPDIR)/subnet_parse.Po
-rm -f ./$(DEPDIR)/tincctl.Po
-rm -f ./$(DEPDIR)/tincd.Po
-rm -f ./$(DEPDIR)/top.Po
-rm -f ./$(DEPDIR)/uml_device.Po
-rm -f ./$(DEPDIR)/upnp.Po
-rm -f ./$(DEPDIR)/utils.Po
-rm -f ./$(DEPDIR)/vde_device.Po
-rm -f ./$(DEPDIR)/version.Po
-rm -f bsd/$(DEPDIR)/device.Po
-rm -f bsd/$(DEPDIR)/tunemu.Po
-rm -f chacha-poly1305/$(DEPDIR)/chacha-poly1305.Po
-rm -f chacha-poly1305/$(DEPDIR)/chacha.Po
-rm -f chacha-poly1305/$(DEPDIR)/poly1305.Po
-rm -f cygwin/$(DEPDIR)/device.Po
-rm -f ed25519/$(DEPDIR)/ecdh.Po
-rm -f ed25519/$(DEPDIR)/ecdsa.Po
-rm -f ed25519/$(DEPDIR)/ecdsagen.Po
-rm -f ed25519/$(DEPDIR)/fe.Po
-rm -f ed25519/$(DEPDIR)/ge.Po
-rm -f ed25519/$(DEPDIR)/key_exchange.Po
-rm -f ed25519/$(DEPDIR)/keypair.Po
-rm -f ed25519/$(DEPDIR)/sc.Po
-rm -f ed25519/$(DEPDIR)/sha512.Po
-rm -f ed25519/$(DEPDIR)/sign.Po
-rm -f ed25519/$(DEPDIR)/verify.Po
-rm -f gcrypt/$(DEPDIR)/cipher.Po
-rm -f gcrypt/$(DEPDIR)/crypto.Po
-rm -f gcrypt/$(DEPDIR)/digest.Po
-rm -f gcrypt/$(DEPDIR)/prf.Po
-rm -f gcrypt/$(DEPDIR)/rsa.Po
-rm -f gcrypt/$(DEPDIR)/rsagen.Po
-rm -f linux/$(DEPDIR)/device.Po
-rm -f mingw/$(DEPDIR)/device.Po
-rm -f nolegacy/$(DEPDIR)/crypto.Po
-rm -f nolegacy/$(DEPDIR)/prf.Po
-rm -f openssl/$(DEPDIR)/cipher.Po
-rm -f openssl/$(DEPDIR)/crypto.Po
-rm -f openssl/$(DEPDIR)/digest.Po
-rm -f openssl/$(DEPDIR)/prf.Po
-rm -f openssl/$(DEPDIR)/rsa.Po
-rm -f openssl/$(DEPDIR)/rsagen.Po
-rm -f solaris/$(DEPDIR)/device.Po
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
@ -1211,7 +1457,7 @@ uninstall-am: uninstall-sbinPROGRAMS
.MAKE: check-am install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles 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 \

277
src/address_cache.c Normal file
View file

@ -0,0 +1,277 @@
/*
address_cache.c -- Manage cache of recently seen addresses
Copyright (C) 2018 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 "address_cache.h"
#include "conf.h"
#include "names.h"
#include "netutl.h"
#include "xalloc.h"
static const unsigned int NOT_CACHED = -1;
// 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) {
continue;
}
bool found = false;
for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) {
if(!sockaddrcmp(&e->reverse->address, (sockaddr_t *)aip->ai_addr)) {
found = true;
break;
}
}
if(found) {
continue;
}
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;
}
static void free_known_addresses(struct addrinfo *ai) {
for(struct addrinfo *aip = ai, *next; aip; aip = next) {
next = aip->ai_next;
free(aip);
}
}
static unsigned int find_cached(address_cache_t *cache, const sockaddr_t *sa) {
for(unsigned int i = 0; i < cache->data.used; i++)
if(!sockaddrcmp(&cache->data.address[i], sa)) {
return i;
}
return NOT_CACHED;
}
void add_recent_address(address_cache_t *cache, const sockaddr_t *sa) {
// Check if it's already cached
unsigned int pos = find_cached(cache, sa);
// It's in the first spot, so nothing to do
if(pos == 0) {
return;
}
// Shift everything, move/add the address to the first slot
if(pos == NOT_CACHED) {
if(cache->data.used < MAX_CACHED_ADDRESSES) {
cache->data.used++;
}
pos = cache->data.used - 1;
}
memmove(&cache->data.address[1], &cache->data.address[0], pos * sizeof(cache->data.address[0]));
cache->data.address[0] = *sa;
// Write the cache
char fname[PATH_MAX];
snprintf(fname, sizeof(fname), "%s" SLASH "cache" SLASH "%s", confbase, cache->node->name);
FILE *fp = fopen(fname, "wb");
if(fp) {
fwrite(&cache->data, sizeof(cache->data), 1, fp);
fclose(fp);
}
}
const sockaddr_t *get_recent_address(address_cache_t *cache) {
// Check if there is an address in our cache of recently seen addresses
if(cache->tried < cache->data.used) {
return &cache->data.address[cache->tried++];
}
// Next, check any recently seen addresses not in our cache
while(cache->tried == cache->data.used) {
if(!cache->ai) {
cache->aip = cache->ai = get_known_addresses(cache->node);
}
if(cache->ai) {
if(cache->aip) {
sockaddr_t *sa = (sockaddr_t *)cache->aip->ai_addr;
cache->aip = cache->aip->ai_next;
if(find_cached(cache, sa) != NOT_CACHED) {
continue;
}
return sa;
} else {
free_known_addresses(cache->ai);
cache->ai = NULL;
}
}
cache->tried++;
}
// Otherwise, check if there are any known Address statements
if(!cache->config_tree) {
init_configuration(&cache->config_tree);
read_host_config(cache->config_tree, cache->node->name, false);
cache->cfg = lookup_config(cache->config_tree, "Address");
}
while(cache->cfg && !cache->ai) {
char *address, *port;
get_config_string(cache->cfg, &address);
char *space = strchr(address, ' ');
if(space) {
port = xstrdup(space + 1);
*space = 0;
} else {
if(!get_config_string(lookup_config(cache->config_tree, "Port"), &port)) {
port = xstrdup("655");
}
}
cache->aip = cache->ai = str2addrinfo(address, port, SOCK_STREAM);
if(cache->ai) {
struct addrinfo *ai = NULL;
for(; cache->aip; cache->aip = cache->aip->ai_next) {
struct addrinfo *oai = ai;
ai = xzalloc(sizeof(*ai));
ai->ai_family = cache->aip->ai_family;
ai->ai_socktype = cache->aip->ai_socktype;
ai->ai_protocol = cache->aip->ai_protocol;
ai->ai_addrlen = cache->aip->ai_addrlen;
ai->ai_addr = xmalloc(ai->ai_addrlen);
memcpy(ai->ai_addr, cache->aip->ai_addr, ai->ai_addrlen);
ai->ai_next = oai;
}
freeaddrinfo(cache->ai);
cache->aip = cache->ai = ai;
}
free(address);
free(port);
cache->cfg = lookup_config_next(cache->config_tree, cache->cfg);
}
if(cache->ai) {
if(cache->aip) {
sockaddr_t *sa = (sockaddr_t *)cache->aip->ai_addr;
cache->aip = cache->aip->ai_next;
return sa;
} else {
free_known_addresses(cache->ai);
cache->ai = NULL;
}
}
// We're all out of addresses.
exit_configuration(&cache->config_tree);
return false;
}
address_cache_t *open_address_cache(node_t *node) {
address_cache_t *cache = xmalloc(sizeof(*cache));
cache->node = node;
// Try to open an existing address cache
char fname[PATH_MAX];
snprintf(fname, sizeof(fname), "%s" SLASH "cache" SLASH "%s", confbase, node->name);
FILE *fp = fopen(fname, "rb");
if(!fp || fread(&cache->data, sizeof(cache->data), 1, fp) != 1 || cache->data.version != ADDRESS_CACHE_VERSION) {
memset(&cache->data, 0, sizeof(cache->data));
}
if(fp) {
fclose(fp);
}
// Ensure we have a valid state
cache->config_tree = NULL;
cache->cfg = NULL;
cache->ai = NULL;
cache->aip = NULL;
cache->tried = 0;
cache->data.version = ADDRESS_CACHE_VERSION;
if(cache->data.used > MAX_CACHED_ADDRESSES) {
cache->data.used = 0;
}
return cache;
}
void reset_address_cache(address_cache_t *cache, const sockaddr_t *sa) {
if(sa) {
add_recent_address(cache, sa);
}
if(cache->config_tree) {
exit_configuration(&cache->config_tree);
}
if(cache->ai) {
free_known_addresses(cache->ai);
}
cache->config_tree = NULL;
cache->cfg = NULL;
cache->ai = NULL;
cache->aip = NULL;
cache->tried = 0;
}
void close_address_cache(address_cache_t *cache) {
if(cache->config_tree) {
exit_configuration(&cache->config_tree);
}
if(cache->ai) {
free_known_addresses(cache->ai);
}
free(cache);
}

50
src/address_cache.h Normal file
View file

@ -0,0 +1,50 @@
#ifndef TINC_ADDRESS_CACHE_H
#define TINC_ADDRESS_CACHE_H
/*
address_cache.h -- header for address_cache.c
Copyright (C) 2018 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 "net.h"
#define MAX_CACHED_ADDRESSES 8
#define ADDRESS_CACHE_VERSION 1
typedef struct address_cache_t {
struct node_t *node;
struct splay_tree_t *config_tree;
struct config_t *cfg;
struct addrinfo *ai;
struct addrinfo *aip;
unsigned int tried;
struct {
unsigned int version;
unsigned int used;
sockaddr_t address[MAX_CACHED_ADDRESSES];
} data;
} address_cache_t;
void add_recent_address(address_cache_t *cache, const sockaddr_t *sa);
const sockaddr_t *get_recent_address(address_cache_t *cache);
address_cache_t *open_address_cache(struct node_t *node);
void reset_address_cache(address_cache_t *cache, const sockaddr_t *sa);
void close_address_cache(address_cache_t *cache);
#endif

View file

@ -27,28 +27,34 @@
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))
if(n == myself || n->connection || !(n->status.has_address || n->status.reachable)) {
continue;
}
count++;
}
if(!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))
if(n == myself || n->connection || !(n->status.has_address || n->status.reachable)) {
continue;
}
if(r--)
if(r--) {
continue;
}
bool found = false;
for list_each(outgoing_t, outgoing, outgoing_list) {
if(!strcmp(outgoing->name, n->name)) {
if(outgoing->node == n) {
found = true;
break;
}
@ -56,10 +62,10 @@ static void make_new_connection() {
if(!found) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "Autoconnecting to %s", n->name);
outgoing_t *outgoing = xzalloc(sizeof *outgoing);
outgoing->name = xstrdup(n->name);
outgoing_t *outgoing = xzalloc(sizeof(*outgoing));
outgoing->node = n;
list_insert_tail(outgoing_list, outgoing);
setup_outgoing_connection(outgoing);
setup_outgoing_connection(outgoing, false);
}
break;
@ -77,23 +83,27 @@ static void connect_to_unreachable() {
int r = rand() % node_tree->count;
for splay_each(node_t, n, node_tree) {
if(r--)
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)
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))
/* Are we already trying to make an outgoing connection to it? If so, return. */
for list_each(outgoing_t, outgoing, outgoing_list) {
if(outgoing->node == n) {
return;
}
}
logger(DEBUG_CONNECTIONS, LOG_INFO, "Autoconnecting to %s", n->name);
outgoing_t *outgoing = xzalloc(sizeof *outgoing);
outgoing->name = xstrdup(n->name);
outgoing_t *outgoing = xzalloc(sizeof(*outgoing));
outgoing->node = n;
list_insert_tail(outgoing_list, outgoing);
setup_outgoing_connection(outgoing);
setup_outgoing_connection(outgoing, false);
return;
}
@ -102,23 +112,29 @@ static void connect_to_unreachable() {
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)
if(!c->edge || !c->outgoing || !c->node || c->node->edge_tree->count < 2) {
continue;
}
count++;
}
if(!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)
if(!c->edge || !c->outgoing || !c->node || c->node->edge_tree->count < 2) {
continue;
if(r--)
}
if(r--) {
continue;
}
logger(DEBUG_CONNECTIONS, LOG_INFO, "Autodisconnecting from %s", c->name);
list_delete(outgoing_list, c->outgoing);
@ -132,6 +148,7 @@ 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;
@ -139,10 +156,11 @@ static void drop_superfluous_pending_connections() {
}
}
if(found)
if(found) {
continue;
}
logger(DEBUG_CONNECTIONS, LOG_INFO, "Cancelled outgoing connection to %s", o->name);
logger(DEBUG_CONNECTIONS, LOG_INFO, "Cancelled outgoing connection to %s", o->node->name);
list_delete_node(outgoing_list, node);
}
}
@ -150,9 +168,11 @@ static void drop_superfluous_pending_connections() {
void do_autoconnect() {
/* Count number of active connections. */
int nc = 0;
for list_each(connection_t, c, connection_list) {
if(c->edge)
if(c->edge) {
nc++;
}
}
/* Less than 3 connections? Eagerly try to make a new one. */
@ -160,10 +180,11 @@ void do_autoconnect() {
make_new_connection();
return;
}
/* More than 3 connections? See if we can get rid of a superfluous one. */
if(nc > 3)
if(nc > 3) {
drop_superfluous_outgoing_connection();
}
/* Check if there are unreachable nodes that we should try to connect to. */

View file

@ -1,3 +1,6 @@
#ifndef TINC_AUTOCONNECT_H
#define TINC_AUTOCONNECT_H
/*
autoconnect.h -- header for autoconnect.c
Copyright (C) 2017 Guus Sliepen <guus@tinc-vpn.org>
@ -17,9 +20,6 @@
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

@ -56,7 +56,7 @@ typedef enum device_type {
int device_fd = -1;
char *device = NULL;
char *iface = NULL;
static char *device_info = NULL;
static const char *device_info = "OS X utun device";
#if defined(ENABLE_TUNEMU)
static device_type_t device_type = DEVICE_TYPE_TUNEMU;
#elif defined(HAVE_OPENBSD) || defined(HAVE_FREEBSD) || defined(HAVE_DRAGONFLY)
@ -68,13 +68,15 @@ static device_type_t device_type = DEVICE_TYPE_TUN;
#ifdef HAVE_NET_IF_UTUN_H
static bool setup_utun(void) {
device_fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
if(device_fd == -1) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not open PF_SYSTEM socket: %s\n", strerror(errno));
return false;
}
struct ctl_info info = {};
strlcpy(info.ctl_name, UTUN_CONTROL_NAME, sizeof info.ctl_name);
strlcpy(info.ctl_name, UTUN_CONTROL_NAME, sizeof(info.ctl_name));
if(ioctl(device_fd, CTLIOCGINFO, &info) == -1) {
logger(DEBUG_ALWAYS, LOG_ERR, "ioctl(CTLIOCGINFO) failed: %s", strerror(errno));
@ -83,15 +85,18 @@ static bool setup_utun(void) {
int unit = -1;
char *p = strstr(device, "utun"), *e = NULL;
if(p) {
unit = strtol(p + 4, &e, 10);
if(!e)
if(!e) {
unit = -1;
}
}
struct sockaddr_ctl sc = {
.sc_id = info.ctl_id,
.sc_len = sizeof sc,
.sc_len = sizeof(sc),
.sc_family = AF_SYSTEM,
.ss_sysaddr = AF_SYS_CONTROL,
.sc_unit = unit + 1,
@ -103,15 +108,14 @@ static bool setup_utun(void) {
}
char name[64] = "";
socklen_t len = sizeof name;
socklen_t len = sizeof(name);
if(getsockopt(device_fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, name, &len)) {
iface = xstrdup(device);
} else {
iface = xstrdup(name);
}
device_info = "OS X utun device";
logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
return true;
@ -124,35 +128,43 @@ static bool setup_device(void) {
// Find out if it's supposed to be a tun or a tap device
char *type;
if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
if(!strcasecmp(type, "tun"))
/* use default */;
#ifdef ENABLE_TUNEMU
else if(!strcasecmp(type, "tunemu"))
else if(!strcasecmp(type, "tunemu")) {
device_type = DEVICE_TYPE_TUNEMU;
}
#endif
#ifdef HAVE_NET_IF_UTUN_H
else if(!strcasecmp(type, "utun"))
else if(!strcasecmp(type, "utun")) {
device_type = DEVICE_TYPE_UTUN;
}
#endif
else if(!strcasecmp(type, "tunnohead"))
else if(!strcasecmp(type, "tunnohead")) {
device_type = DEVICE_TYPE_TUN;
else if(!strcasecmp(type, "tunifhead"))
} else if(!strcasecmp(type, "tunifhead")) {
device_type = DEVICE_TYPE_TUNIFHEAD;
else if(!strcasecmp(type, "tap"))
} else if(!strcasecmp(type, "tap")) {
device_type = DEVICE_TYPE_TAP;
else {
} else {
logger(DEBUG_ALWAYS, LOG_ERR, "Unknown device type %s!", type);
return false;
}
} else {
#ifdef HAVE_NET_IF_UTUN_H
if(device && (strncmp(device, "utun", 4) == 0 || strncmp(device, "/dev/utun", 9) == 0))
if(device && (strncmp(device, "utun", 4) == 0 || strncmp(device, "/dev/utun", 9) == 0)) {
device_type = DEVICE_TYPE_UTUN;
else
} else
#endif
if((device && strstr(device, "tap")) || routing_mode != RMODE_ROUTER)
device_type = DEVICE_TYPE_TAP;
if((device && strstr(device, "tap")) || routing_mode != RMODE_ROUTER) {
device_type = DEVICE_TYPE_TAP;
}
}
if(routing_mode == RMODE_SWITCH && device_type != DEVICE_TYPE_TAP) {
@ -163,28 +175,32 @@ static bool setup_device(void) {
// Find out which device file to open
if(!device) {
if(device_type == DEVICE_TYPE_TAP)
if(device_type == DEVICE_TYPE_TAP) {
device = xstrdup(DEFAULT_TAP_DEVICE);
else
} else {
device = xstrdup(DEFAULT_TUN_DEVICE);
}
}
// Open the device
switch(device_type) {
#ifdef ENABLE_TUNEMU
case DEVICE_TYPE_TUNEMU: {
char dynamic_name[256] = "";
device_fd = tunemu_open(dynamic_name);
}
break;
case DEVICE_TYPE_TUNEMU: {
char dynamic_name[256] = "";
device_fd = tunemu_open(dynamic_name);
}
break;
#endif
#ifdef HAVE_NET_IF_UTUN_H
case DEVICE_TYPE_UTUN:
return setup_utun();
case DEVICE_TYPE_UTUN:
return setup_utun();
#endif
default:
device_fd = open(device, O_RDWR | O_NONBLOCK);
default:
device_fd = open(device, O_RDWR | O_NONBLOCK);
}
if(device_fd < 0) {
@ -204,87 +220,105 @@ static bool setup_device(void) {
realname = fdevname(device_fd);
#elif defined(HAVE_DEVNAME)
struct stat buf;
if(!fstat(device_fd, &buf))
if(!fstat(device_fd, &buf)) {
realname = devname(buf.st_rdev, S_IFCHR);
}
#endif
if(!realname)
if(!realname) {
realname = device;
}
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
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))
} else if(strcmp(iface, strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname)) {
logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: Interface does not match Device. $INTERFACE might be set incorrectly.");
}
// Configure the device as best as we can
switch(device_type) {
default:
device_type = DEVICE_TYPE_TUN;
case DEVICE_TYPE_TUN:
default:
device_type = DEVICE_TYPE_TUN;
case DEVICE_TYPE_TUN:
#ifdef TUNSIFHEAD
{
const int zero = 0;
if(ioctl(device_fd, TUNSIFHEAD, &zero, sizeof zero) == -1) {
if(ioctl(device_fd, TUNSIFHEAD, &zero, sizeof(zero)) == -1) {
logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "ioctl", strerror(errno));
return false;
}
}
#endif
#if defined(TUNSIFMODE) && defined(IFF_BROADCAST) && defined(IFF_MULTICAST)
{
const int mode = IFF_BROADCAST | IFF_MULTICAST;
ioctl(device_fd, TUNSIFMODE, &mode, sizeof mode);
ioctl(device_fd, TUNSIFMODE, &mode, sizeof(mode));
}
#endif
device_info = "Generic BSD tun device";
break;
case DEVICE_TYPE_TUNIFHEAD:
device_info = "Generic BSD tun device";
break;
case DEVICE_TYPE_TUNIFHEAD:
#ifdef TUNSIFHEAD
{
const int one = 1;
if(ioctl(device_fd, TUNSIFHEAD, &one, sizeof one) == -1) {
if(ioctl(device_fd, TUNSIFHEAD, &one, sizeof(one)) == -1) {
logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "ioctl", strerror(errno));
return false;
}
}
#endif
#if defined(TUNSIFMODE) && defined(IFF_BROADCAST) && defined(IFF_MULTICAST)
{
const int mode = IFF_BROADCAST | IFF_MULTICAST;
ioctl(device_fd, TUNSIFMODE, &mode, sizeof mode);
const int mode = IFF_BROADCAST | IFF_MULTICAST;
ioctl(device_fd, TUNSIFMODE, &mode, sizeof(mode));
}
#endif
device_info = "Generic BSD tun device";
break;
case DEVICE_TYPE_TAP:
if(routing_mode == RMODE_ROUTER)
overwrite_mac = true;
device_info = "Generic BSD tap device";
device_info = "Generic BSD tun device";
break;
case DEVICE_TYPE_TAP:
if(routing_mode == RMODE_ROUTER) {
overwrite_mac = true;
}
device_info = "Generic BSD tap device";
#ifdef TAPGIFNAME
{
struct ifreq ifr;
if(ioctl(device_fd, TAPGIFNAME, (void*)&ifr) == 0) {
if(iface)
free(iface);
iface = xstrdup(ifr.ifr_name);
}
{
struct ifreq ifr;
if(ioctl(device_fd, TAPGIFNAME, (void *)&ifr) == 0) {
free(iface);
iface = xstrdup(ifr.ifr_name);
}
}
#endif
break;
break;
#ifdef ENABLE_TUNEMU
case DEVICE_TYPE_TUNEMU:
device_info = "BSD tunemu device";
break;
case DEVICE_TYPE_TUNEMU:
device_info = "BSD tunemu device";
break;
#endif
}
#ifdef SIOCGIFADDR
if(overwrite_mac)
if(overwrite_mac) {
ioctl(device_fd, SIOCGIFADDR, mymac.x);
}
#endif
logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
@ -295,17 +329,22 @@ static bool setup_device(void) {
static void close_device(void) {
switch(device_type) {
#ifdef ENABLE_TUNEMU
case DEVICE_TYPE_TUNEMU:
tunemu_close(device_fd);
break;
case DEVICE_TYPE_TUNEMU:
tunemu_close(device_fd);
break;
#endif
default:
close(device_fd);
default:
close(device_fd);
}
device_fd = -1;
free(device); device = NULL;
free(iface); iface = NULL;
free(device);
device = NULL;
free(iface);
iface = NULL;
device_info = NULL;
}
@ -313,154 +352,163 @@ static bool read_packet(vpn_packet_t *packet) {
int inlen;
switch(device_type) {
case DEVICE_TYPE_TUN:
case DEVICE_TYPE_TUN:
#ifdef ENABLE_TUNEMU
case DEVICE_TYPE_TUNEMU:
if(device_type == DEVICE_TYPE_TUNEMU)
inlen = tunemu_read(device_fd, DATA(packet) + 14, MTU - 14);
else
case DEVICE_TYPE_TUNEMU:
if(device_type == DEVICE_TYPE_TUNEMU) {
inlen = tunemu_read(device_fd, DATA(packet) + 14, MTU - 14);
} else
#endif
inlen = read(device_fd, DATA(packet) + 14, MTU - 14);
inlen = read(device_fd, DATA(packet) + 14, MTU - 14);
if(inlen <= 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno));
return false;
}
switch(DATA(packet)[14] >> 4) {
case 4:
DATA(packet)[12] = 0x08;
DATA(packet)[13] = 0x00;
break;
case 6:
DATA(packet)[12] = 0x86;
DATA(packet)[13] = 0xDD;
break;
default:
logger(DEBUG_TRAFFIC, LOG_ERR,
"Unknown IP version %d while reading packet from %s %s",
DATA(packet)[14] >> 4, device_info, device);
return false;
}
memset(DATA(packet), 0, 12);
packet->len = inlen + 14;
break;
case DEVICE_TYPE_UTUN:
case DEVICE_TYPE_TUNIFHEAD: {
if((inlen = read(device_fd, DATA(packet) + 10, MTU - 10)) <= 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno));
return false;
}
switch (DATA(packet)[14] >> 4) {
case 4:
DATA(packet)[12] = 0x08;
DATA(packet)[13] = 0x00;
break;
case 6:
DATA(packet)[12] = 0x86;
DATA(packet)[13] = 0xDD;
break;
default:
logger(DEBUG_TRAFFIC, LOG_ERR,
"Unknown IP version %d while reading packet from %s %s",
DATA(packet)[14] >> 4, device_info, device);
return false;
}
memset(DATA(packet), 0, 12);
packet->len = inlen + 10;
break;
if(inlen <= 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno));
return false;
}
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));
return false;
}
switch(DATA(packet)[14] >> 4) {
case 4:
DATA(packet)[12] = 0x08;
DATA(packet)[13] = 0x00;
break;
packet->len = inlen;
case 6:
DATA(packet)[12] = 0x86;
DATA(packet)[13] = 0xDD;
break;
default:
logger(DEBUG_TRAFFIC, LOG_ERR,
"Unknown IP version %d while reading packet from %s %s",
DATA(packet)[14] >> 4, device_info, device);
return false;
}
memset(DATA(packet), 0, 12);
packet->len = inlen + 14;
break;
case DEVICE_TYPE_UTUN:
case DEVICE_TYPE_TUNIFHEAD: {
if((inlen = read(device_fd, DATA(packet) + 10, MTU - 10)) <= 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno));
return false;
}
switch(DATA(packet)[14] >> 4) {
case 4:
DATA(packet)[12] = 0x08;
DATA(packet)[13] = 0x00;
break;
case 6:
DATA(packet)[12] = 0x86;
DATA(packet)[13] = 0xDD;
break;
default:
logger(DEBUG_TRAFFIC, LOG_ERR,
"Unknown IP version %d while reading packet from %s %s",
DATA(packet)[14] >> 4, device_info, device);
return false;
}
memset(DATA(packet), 0, 12);
packet->len = inlen + 10;
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));
return false;
}
packet->len = inlen;
break;
default:
return false;
}
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s",
packet->len, device_info);
packet->len, device_info);
return true;
}
static bool write_packet(vpn_packet_t *packet) {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s",
packet->len, device_info);
packet->len, device_info);
switch(device_type) {
case DEVICE_TYPE_TUN:
if(write(device_fd, DATA(packet) + 14, packet->len - 14) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info,
device, strerror(errno));
return false;
}
break;
case DEVICE_TYPE_UTUN:
case DEVICE_TYPE_TUNIFHEAD: {
int af = (DATA(packet)[12] << 8) + DATA(packet)[13];
uint32_t type;
switch (af) {
case 0x0800:
type = htonl(AF_INET);
break;
case 0x86DD:
type = htonl(AF_INET6);
break;
default:
logger(DEBUG_TRAFFIC, LOG_ERR,
"Unknown address family %x while writing packet to %s %s",
af, device_info, device);
return false;
}
memcpy(DATA(packet) + 10, &type, sizeof type);
if(write(device_fd, DATA(packet) + 10, packet->len - 10) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
strerror(errno));
return false;
}
break;
case DEVICE_TYPE_TUN:
if(write(device_fd, DATA(packet) + 14, packet->len - 14) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info,
device, strerror(errno));
return false;
}
case DEVICE_TYPE_TAP:
if(write(device_fd, DATA(packet), packet->len) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info,
device, strerror(errno));
return false;
}
break;
case DEVICE_TYPE_UTUN:
case DEVICE_TYPE_TUNIFHEAD: {
int af = (DATA(packet)[12] << 8) + DATA(packet)[13];
uint32_t type;
switch(af) {
case 0x0800:
type = htonl(AF_INET);
break;
#ifdef ENABLE_TUNEMU
case DEVICE_TYPE_TUNEMU:
if(tunemu_write(device_fd, DATA(packet) + 14, packet->len - 14) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info,
device, strerror(errno));
return false;
}
case 0x86DD:
type = htonl(AF_INET6);
break;
#endif
default:
logger(DEBUG_TRAFFIC, LOG_ERR,
"Unknown address family %x while writing packet to %s %s",
af, device_info, device);
return false;
}
memcpy(DATA(packet) + 10, &type, sizeof(type));
if(write(device_fd, DATA(packet) + 10, packet->len - 10) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
strerror(errno));
return false;
}
break;
}
case DEVICE_TYPE_TAP:
if(write(device_fd, DATA(packet), packet->len) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info,
device, strerror(errno));
return false;
}
break;
#ifdef ENABLE_TUNEMU
case DEVICE_TYPE_TUNEMU:
if(tunemu_write(device_fd, DATA(packet) + 14, packet->len - 14) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info,
device, strerror(errno));
return false;
}
break;
#endif
default:
return false;
}
return true;

View file

@ -49,24 +49,21 @@
#define PPPIOCCONNECT _IOW('t', 58, int)
#define PPPIOCGUNIT _IOR('t', 86, int)
struct sockaddr_ppp
{
struct sockaddr_ppp {
u_int8_t ppp_len;
u_int8_t ppp_family;
u_int16_t ppp_proto;
u_int32_t ppp_cookie;
};
enum NPmode
{
enum NPmode {
NPMODE_PASS,
NPMODE_DROP,
NPMODE_ERROR,
NPMODE_QUEUE
NPMODE_DROP,
NPMODE_ERROR,
NPMODE_QUEUE
};
struct npioctl
{
struct npioctl {
int protocol;
enum NPmode mode;
};
@ -83,58 +80,55 @@ static pcap_t *pcap = NULL;
static int data_buffer_length = 0;
static char *data_buffer = NULL;
static void tun_error(char *format, ...)
{
static void tun_error(char *format, ...) {
va_list vl;
va_start(vl, format);
vsnprintf(tunemu_error, sizeof tunemu_error, format, vl);
vsnprintf(tunemu_error, sizeof(tunemu_error), format, vl);
va_end(vl);
}
static void tun_noerror()
{
static void tun_noerror() {
*tunemu_error = 0;
}
static void closeall()
{
int fd = getdtablesize();
while (fd--)
close(fd);
static void closeall() {
int fd = getdtablesize();
open("/dev/null", O_RDWR, 0);
dup(0);
dup(0);
while(fd--) {
close(fd);
}
open("/dev/null", O_RDWR, 0);
dup(0);
dup(0);
}
static int ppp_load_kext()
{
static int ppp_load_kext() {
int pid = fork();
if (pid < 0)
{
if(pid < 0) {
tun_error("fork for ppp kext: %s", strerror(errno));
return -1;
}
if (pid == 0)
{
if(pid == 0) {
closeall();
execle("/sbin/kextload", "kextload", PPP_KEXT_PATH, NULL, NULL);
exit(1);
}
int status;
while (waitpid(pid, &status, 0) < 0)
{
if (errno == EINTR)
while(waitpid(pid, &status, 0) < 0) {
if(errno == EINTR) {
continue;
}
tun_error("waitpid for ppp kext: %s", strerror(errno));
return -1;
}
if (WEXITSTATUS(status) != 0)
{
if(WEXITSTATUS(status) != 0) {
tun_error("could not load ppp kext \"%s\"", PPP_KEXT_PATH);
return -1;
}
@ -143,74 +137,73 @@ static int ppp_load_kext()
return 0;
}
static int ppp_new_instance()
{
static int ppp_new_instance() {
// create ppp socket
int ppp_sockfd = socket(PF_PPP, SOCK_RAW, PPPPROTO_CTL);
if (ppp_sockfd < 0)
{
if (ppp_load_kext() < 0)
int ppp_sockfd = socket(PF_PPP, SOCK_RAW, PPPPROTO_CTL);
if(ppp_sockfd < 0) {
if(ppp_load_kext() < 0) {
return -1;
}
ppp_sockfd = socket(PF_PPP, SOCK_RAW, PPPPROTO_CTL);
if (ppp_sockfd < 0)
{
if(ppp_sockfd < 0) {
tun_error("creating ppp socket: %s", strerror(errno));
return -1;
}
}
// connect to ppp procotol
struct sockaddr_ppp pppaddr;
pppaddr.ppp_len = sizeof(struct sockaddr_ppp);
pppaddr.ppp_family = AF_PPP;
pppaddr.ppp_proto = PPPPROTO_CTL;
pppaddr.ppp_cookie = 0;
if (connect(ppp_sockfd, (struct sockaddr *)&pppaddr, sizeof(struct sockaddr_ppp)) < 0)
{
struct sockaddr_ppp pppaddr;
pppaddr.ppp_len = sizeof(struct sockaddr_ppp);
pppaddr.ppp_family = AF_PPP;
pppaddr.ppp_proto = PPPPROTO_CTL;
pppaddr.ppp_cookie = 0;
if(connect(ppp_sockfd, (struct sockaddr *)&pppaddr, sizeof(struct sockaddr_ppp)) < 0) {
tun_error("connecting ppp socket: %s", strerror(errno));
close(ppp_sockfd);
return -1;
}
}
tun_noerror();
return ppp_sockfd;
}
static int ppp_new_unit(int *unit_number)
{
static int ppp_new_unit(int *unit_number) {
int fd = ppp_new_instance();
if (fd < 0)
if(fd < 0) {
return -1;
}
// create ppp unit
if (ioctl(fd, PPPIOCNEWUNIT, unit_number) < 0)
{
if(ioctl(fd, PPPIOCNEWUNIT, unit_number) < 0) {
tun_error("creating ppp unit: %s", strerror(errno));
close(fd);
return -1;
}
}
tun_noerror();
return fd;
}
static int ppp_setup_unit(int unit_fd)
{
static int ppp_setup_unit(int unit_fd) {
// send traffic to program
int flags = SC_LOOP_TRAFFIC;
if (ioctl(unit_fd, PPPIOCSFLAGS, &flags) < 0)
{
if(ioctl(unit_fd, PPPIOCSFLAGS, &flags) < 0) {
tun_error("setting ppp loopback mode: %s", strerror(errno));
return -1;
}
}
// allow packets
struct npioctl npi;
npi.protocol = PPP_IP;
npi.mode = NPMODE_PASS;
if (ioctl(unit_fd, PPPIOCSNPMODE, &npi) < 0)
{
if(ioctl(unit_fd, PPPIOCSNPMODE, &npi) < 0) {
tun_error("starting ppp unit: %s", strerror(errno));
return -1;
}
@ -219,10 +212,8 @@ static int ppp_setup_unit(int unit_fd)
return 0;
}
static int open_pcap()
{
if (pcap != NULL)
{
static int open_pcap() {
if(pcap != NULL) {
pcap_use_count++;
return 0;
}
@ -231,8 +222,7 @@ static int open_pcap()
pcap = pcap_open_live("lo0", BUFSIZ, 0, 1, errbuf);
pcap_use_count = 1;
if (pcap == NULL)
{
if(pcap == NULL) {
tun_error("opening pcap: %s", errbuf);
return -1;
}
@ -241,59 +231,57 @@ static int open_pcap()
return 0;
}
static void close_pcap()
{
if (pcap == NULL)
static void close_pcap() {
if(pcap == NULL) {
return;
}
pcap_use_count--;
if (pcap_use_count == 0)
{
if(pcap_use_count == 0) {
pcap_close(pcap);
pcap = NULL;
}
}
static void allocate_data_buffer(int size)
{
if (data_buffer_length < size)
{
static void allocate_data_buffer(int size) {
if(data_buffer_length < size) {
free(data_buffer);
data_buffer_length = size;
data_buffer = malloc(data_buffer_length);
}
}
static void make_device_name(tunemu_device device, int unit_number)
{
static void make_device_name(tunemu_device device, int unit_number) {
snprintf(device, sizeof(tunemu_device), "ppp%d", unit_number);
}
static int check_device_name(tunemu_device device)
{
if (strlen(device) < 4)
static int check_device_name(tunemu_device device) {
if(strlen(device) < 4) {
return -1;
}
int unit_number = atoi(device + 3);
if (unit_number < 0 || unit_number > 999)
if(unit_number < 0 || unit_number > 999) {
return -1;
}
tunemu_device compare;
make_device_name(compare, unit_number);
if (strcmp(device, compare) != 0)
if(strcmp(device, compare) != 0) {
return -1;
}
return 0;
}
int tunemu_open(tunemu_device device)
{
int tunemu_open(tunemu_device device) {
int ppp_unit_number = -1;
if (device[0] != 0)
{
if (check_device_name(device) < 0)
{
if(device[0] != 0) {
if(check_device_name(device) < 0) {
tun_error("invalid device name \"%s\"", device);
return -1;
}
@ -302,17 +290,17 @@ int tunemu_open(tunemu_device device)
}
int ppp_unit_fd = ppp_new_unit(&ppp_unit_number);
if (ppp_unit_fd < 0)
return -1;
if (ppp_setup_unit(ppp_unit_fd) < 0)
{
if(ppp_unit_fd < 0) {
return -1;
}
if(ppp_setup_unit(ppp_unit_fd) < 0) {
close(ppp_unit_fd);
return -1;
}
if (open_pcap() < 0)
{
if(open_pcap() < 0) {
close(ppp_unit_fd);
return -1;
}
@ -322,39 +310,40 @@ int tunemu_open(tunemu_device device)
return ppp_unit_fd;
}
int tunemu_close(int ppp_sockfd)
{
int tunemu_close(int ppp_sockfd) {
int ret = close(ppp_sockfd);
if (ret == 0)
if(ret == 0) {
close_pcap();
}
return ret;
}
int tunemu_read(int ppp_sockfd, char *buffer, int length)
{
int tunemu_read(int ppp_sockfd, char *buffer, int length) {
allocate_data_buffer(length + 2);
length = read(ppp_sockfd, data_buffer, length + 2);
if (length < 0)
{
if(length < 0) {
tun_error("reading packet: %s", strerror(errno));
return length;
}
tun_noerror();
length -= 2;
if (length < 0)
if(length < 0) {
return 0;
}
memcpy(buffer, data_buffer + 2, length);
return length;
}
int tunemu_write(int ppp_sockfd, char *buffer, int length)
{
int tunemu_write(int ppp_sockfd, char *buffer, int length) {
allocate_data_buffer(length + 4);
data_buffer[0] = 0x02;
@ -364,23 +353,25 @@ int tunemu_write(int ppp_sockfd, char *buffer, int length)
memcpy(data_buffer + 4, buffer, length);
if (pcap == NULL)
{
if(pcap == NULL) {
tun_error("pcap not open");
return -1;
}
length = pcap_inject(pcap, data_buffer, length + 4);
if (length < 0)
{
if(length < 0) {
tun_error("injecting packet: %s", pcap_geterr(pcap));
return length;
}
tun_noerror();
length -= 4;
if (length < 0)
if(length < 0) {
return 0;
}
return length;
}

View file

@ -22,7 +22,7 @@
#include "buffer.h"
#include "xalloc.h"
void buffer_compact(buffer_t *buffer, int maxsize) {
void buffer_compact(buffer_t *buffer, uint32_t maxsize) {
if(buffer->len >= maxsize || buffer->offset / 7 > buffer->len / 8) {
memmove(buffer->data, buffer->data + buffer->offset, buffer->len - buffer->offset);
buffer->len -= buffer->offset;
@ -32,7 +32,7 @@ void buffer_compact(buffer_t *buffer, int maxsize) {
// Make sure we can add size bytes to the buffer, and return a pointer to the start of those bytes.
char *buffer_prepare(buffer_t *buffer, int size) {
char *buffer_prepare(buffer_t *buffer, uint32_t size) {
if(!buffer->data) {
buffer->maxlen = size;
buffer->data = xmalloc(size);
@ -58,13 +58,13 @@ char *buffer_prepare(buffer_t *buffer, int size) {
// Copy data into the buffer.
void buffer_add(buffer_t *buffer, const char *data, int size) {
void buffer_add(buffer_t *buffer, const char *data, uint32_t size) {
memcpy(buffer_prepare(buffer, size), data, size);
}
// Remove given number of bytes from the buffer, return a pointer to the start of them.
static char *buffer_consume(buffer_t *buffer, int size) {
static char *buffer_consume(buffer_t *buffer, uint32_t size) {
char *start = buffer->data + buffer->offset;
buffer->offset += size;
@ -82,19 +82,21 @@ static char *buffer_consume(buffer_t *buffer, int size) {
char *buffer_readline(buffer_t *buffer) {
char *newline = memchr(buffer->data + buffer->offset, '\n', buffer->len - buffer->offset);
if(!newline)
if(!newline) {
return NULL;
}
int len = newline + 1 - (buffer->data + buffer->offset);
uint32_t len = newline + 1 - (buffer->data + buffer->offset);
*newline = 0;
return buffer_consume(buffer, len);
}
// Check if we have enough bytes in the buffer, and if so, return a pointer to the start of them.
char *buffer_read(buffer_t *buffer, int size) {
if(buffer->len - buffer->offset < size)
char *buffer_read(buffer_t *buffer, uint32_t size) {
if(buffer->len - buffer->offset < size) {
return NULL;
}
return buffer_consume(buffer, size);
}

View file

@ -1,18 +1,18 @@
#ifndef __TINC_BUFFER_H__
#define __TINC_BUFFER_H__
#ifndef TINC_BUFFER_H
#define TINC_BUFFER_H
typedef struct buffer_t {
char *data;
int maxlen;
int len;
int offset;
uint32_t maxlen;
uint32_t len;
uint32_t offset;
} buffer_t;
extern void buffer_compact(buffer_t *buffer, int maxsize);
extern char *buffer_prepare(buffer_t *buffer, int size);
extern void buffer_add(buffer_t *buffer, const char *data, int size);
extern void buffer_compact(buffer_t *buffer, uint32_t maxsize);
extern char *buffer_prepare(buffer_t *buffer, uint32_t size);
extern void buffer_add(buffer_t *buffer, const char *data, uint32_t size);
extern char *buffer_readline(buffer_t *buffer);
extern char *buffer_read(buffer_t *buffer, int size);
extern char *buffer_read(buffer_t *buffer, uint32_t size);
extern void buffer_clear(buffer_t *buffer);
#endif

View file

@ -11,42 +11,40 @@ struct chacha_poly1305_ctx {
struct chacha_ctx main_ctx, header_ctx;
};
chacha_poly1305_ctx_t *chacha_poly1305_init(void)
{
chacha_poly1305_ctx_t *ctx = xzalloc(sizeof *ctx);
chacha_poly1305_ctx_t *chacha_poly1305_init(void) {
chacha_poly1305_ctx_t *ctx = xzalloc(sizeof(*ctx));
return ctx;
}
void chacha_poly1305_exit(chacha_poly1305_ctx_t *ctx)
{
void chacha_poly1305_exit(chacha_poly1305_ctx_t *ctx) {
free(ctx);
}
bool chacha_poly1305_set_key(chacha_poly1305_ctx_t *ctx, const void *key)
{
bool chacha_poly1305_set_key(chacha_poly1305_ctx_t *ctx, const void *vkey) {
const uint8_t *key = vkey;
chacha_keysetup(&ctx->main_ctx, key, 256);
chacha_keysetup(&ctx->header_ctx, key + 32, 256);
return true;
}
static void put_u64(void *vp, uint64_t v)
{
static void put_u64(void *vp, uint64_t v) {
uint8_t *p = (uint8_t *) vp;
p[0] = (uint8_t) (v >> 56) & 0xff;
p[1] = (uint8_t) (v >> 48) & 0xff;
p[2] = (uint8_t) (v >> 40) & 0xff;
p[3] = (uint8_t) (v >> 32) & 0xff;
p[4] = (uint8_t) (v >> 24) & 0xff;
p[5] = (uint8_t) (v >> 16) & 0xff;
p[6] = (uint8_t) (v >> 8) & 0xff;
p[0] = (uint8_t)(v >> 56) & 0xff;
p[1] = (uint8_t)(v >> 48) & 0xff;
p[2] = (uint8_t)(v >> 40) & 0xff;
p[3] = (uint8_t)(v >> 32) & 0xff;
p[4] = (uint8_t)(v >> 24) & 0xff;
p[5] = (uint8_t)(v >> 16) & 0xff;
p[6] = (uint8_t)(v >> 8) & 0xff;
p[7] = (uint8_t) v & 0xff;
}
bool chacha_poly1305_encrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen, void *outdata, size_t *outlen) {
bool chacha_poly1305_encrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen, void *voutdata, size_t *outlen) {
uint8_t seqbuf[8];
const uint8_t one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */
const uint8_t one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */
uint8_t poly_key[POLY1305_KEYLEN];
uint8_t *outdata = voutdata;
/*
* Run ChaCha20 once to generate the Poly1305 key. The IV is the
@ -63,16 +61,18 @@ bool chacha_poly1305_encrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const v
chacha_encrypt_bytes(&ctx->main_ctx, indata, outdata, inlen);
poly1305_auth(outdata + inlen, outdata, inlen, poly_key);
if (outlen)
if(outlen) {
*outlen = inlen + POLY1305_TAGLEN;
}
return true;
}
bool chacha_poly1305_decrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen, void *outdata, size_t *outlen) {
bool chacha_poly1305_decrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *vindata, size_t inlen, void *outdata, size_t *outlen) {
uint8_t seqbuf[8];
const uint8_t one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */
const uint8_t one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */
uint8_t expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN];
const uint8_t *indata = vindata;
/*
* Run ChaCha20 once to generate the Poly1305 key. The IV is the
@ -91,13 +91,16 @@ bool chacha_poly1305_decrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const v
const uint8_t *tag = indata + inlen;
poly1305_auth(expected_tag, indata, inlen, poly_key);
if (memcmp(expected_tag, tag, POLY1305_TAGLEN))
if(memcmp(expected_tag, tag, POLY1305_TAGLEN)) {
return false;
}
chacha_encrypt_bytes(&ctx->main_ctx, indata, outdata, inlen);
if (outlen)
if(outlen) {
*outlen = inlen;
}
return true;
}

View file

@ -47,20 +47,21 @@ typedef struct chacha_ctx chacha_ctx;
static const char sigma[16] = "expand 32-byte k";
static const char tau[16] = "expand 16-byte k";
void chacha_keysetup(chacha_ctx *x, const uint8_t *k, uint32_t kbits)
{
void chacha_keysetup(chacha_ctx *x, const uint8_t *k, uint32_t kbits) {
const char *constants;
x->input[4] = U8TO32_LITTLE(k + 0);
x->input[5] = U8TO32_LITTLE(k + 4);
x->input[6] = U8TO32_LITTLE(k + 8);
x->input[7] = U8TO32_LITTLE(k + 12);
if (kbits == 256) { /* recommended */
if(kbits == 256) { /* recommended */
k += 16;
constants = sigma;
} else { /* kbits == 128 */
} else { /* kbits == 128 */
constants = tau;
}
x->input[8] = U8TO32_LITTLE(k + 0);
x->input[9] = U8TO32_LITTLE(k + 4);
x->input[10] = U8TO32_LITTLE(k + 8);
@ -71,8 +72,7 @@ void chacha_keysetup(chacha_ctx *x, const uint8_t *k, uint32_t kbits)
x->input[3] = U8TO32_LITTLE(constants + 12);
}
void chacha_ivsetup(chacha_ctx *x, const uint8_t *iv, const uint8_t *counter)
{
void chacha_ivsetup(chacha_ctx *x, const uint8_t *iv, const uint8_t *counter) {
x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0);
x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4);
x->input[14] = U8TO32_LITTLE(iv + 0);
@ -80,16 +80,16 @@ void chacha_ivsetup(chacha_ctx *x, const uint8_t *iv, const uint8_t *counter)
}
void
chacha_encrypt_bytes(chacha_ctx *x, const uint8_t *m, uint8_t *c, uint32_t bytes)
{
chacha_encrypt_bytes(chacha_ctx *x, const uint8_t *m, uint8_t *c, uint32_t bytes) {
uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
uint8_t *ctarget = NULL;
uint8_t tmp[64];
uint32_t i;
if (!bytes)
if(!bytes) {
return;
}
j0 = x->input[0];
j1 = x->input[1];
@ -108,14 +108,17 @@ chacha_encrypt_bytes(chacha_ctx *x, const uint8_t *m, uint8_t *c, uint32_t bytes
j14 = x->input[14];
j15 = x->input[15];
for (;;) {
if (bytes < 64) {
for (i = 0; i < bytes; ++i)
for(;;) {
if(bytes < 64) {
for(i = 0; i < bytes; ++i) {
tmp[i] = m[i];
}
m = tmp;
ctarget = c;
c = tmp;
}
x0 = j0;
x1 = j1;
x2 = j2;
@ -132,7 +135,8 @@ chacha_encrypt_bytes(chacha_ctx *x, const uint8_t *m, uint8_t *c, uint32_t bytes
x13 = j13;
x14 = j14;
x15 = j15;
for (i = 20; i > 0; i -= 2) {
for(i = 20; i > 0; i -= 2) {
QUARTERROUND(x0, x4, x8, x12)
QUARTERROUND(x1, x5, x9, x13)
QUARTERROUND(x2, x6, x10, x14)
@ -142,6 +146,7 @@ chacha_encrypt_bytes(chacha_ctx *x, const uint8_t *m, uint8_t *c, uint32_t bytes
QUARTERROUND(x2, x7, x8, x13)
QUARTERROUND(x3, x4, x9, x14)
}
x0 = PLUS(x0, j0);
x1 = PLUS(x1, j1);
x2 = PLUS(x2, j2);
@ -177,7 +182,8 @@ chacha_encrypt_bytes(chacha_ctx *x, const uint8_t *m, uint8_t *c, uint32_t bytes
x15 = XOR(x15, U8TO32_LITTLE(m + 60));
j12 = PLUSONE(j12);
if (!j12) {
if(!j12) {
j13 = PLUSONE(j13);
/* stopping at 2^70 bytes per nonce is user's responsibility */
}
@ -199,15 +205,18 @@ chacha_encrypt_bytes(chacha_ctx *x, const uint8_t *m, uint8_t *c, uint32_t bytes
U32TO8_LITTLE(c + 56, x14);
U32TO8_LITTLE(c + 60, x15);
if (bytes <= 64) {
if (bytes < 64) {
for (i = 0; i < bytes; ++i)
if(bytes <= 64) {
if(bytes < 64) {
for(i = 0; i < bytes; ++i) {
ctarget[i] = c[i];
}
}
x->input[12] = j12;
x->input[13] = j13;
return;
}
bytes -= 64;
c += 64;
m += 64;

View file

@ -11,14 +11,14 @@ struct chacha_ctx {
uint32_t input[16];
};
#define CHACHA_MINKEYLEN 16
#define CHACHA_NONCELEN 8
#define CHACHA_CTRLEN 8
#define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN)
#define CHACHA_BLOCKLEN 64
#define CHACHA_MINKEYLEN 16
#define CHACHA_NONCELEN 8
#define CHACHA_CTRLEN 8
#define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN)
#define CHACHA_BLOCKLEN 64
void chacha_keysetup(struct chacha_ctx *x, const uint8_t *k, uint32_t kbits);
void chacha_ivsetup(struct chacha_ctx *x, const uint8_t *iv, const uint8_t *ctr);
void chacha_encrypt_bytes(struct chacha_ctx *x, const uint8_t *m, uint8_t * c, uint32_t bytes);
void chacha_encrypt_bytes(struct chacha_ctx *x, const uint8_t *m, uint8_t *c, uint32_t bytes);
#endif /* CHACHA_H */

View file

@ -1,4 +1,4 @@
/*
/*
* Public Domain poly1305 from Andrew Moon
* poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna
*/
@ -24,8 +24,7 @@
} while (0)
void
poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen, const unsigned char key[POLY1305_KEYLEN])
{
poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen, const unsigned char key[POLY1305_KEYLEN]) {
uint32_t t0, t1, t2, t3;
uint32_t h0, h1, h2, h3, h4;
uint32_t r0, r1, r2, r3, r4;
@ -71,10 +70,11 @@ poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t
h4 = 0;
/* full blocks */
if (inlen < 16)
if(inlen < 16) {
goto poly1305_donna_atmost15bytes;
}
poly1305_donna_16bytes:
poly1305_donna_16bytes:
m += 16;
inlen -= 16;
@ -89,7 +89,7 @@ poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t
h3 += ((((uint64_t) t3 << 32) | t2) >> 14) & 0x3ffffff;
h4 += (t3 >> 8) | (1 << 24);
poly1305_donna_mul:
poly1305_donna_mul:
t[0] = mul32x32_64(h0, r0) + mul32x32_64(h1, s4) + mul32x32_64(h2, s3) + mul32x32_64(h3, s2) + mul32x32_64(h4, s1);
t[1] = mul32x32_64(h0, r1) + mul32x32_64(h1, r0) + mul32x32_64(h2, s4) + mul32x32_64(h3, s3) + mul32x32_64(h4, s2);
t[2] = mul32x32_64(h0, r2) + mul32x32_64(h1, r1) + mul32x32_64(h2, r0) + mul32x32_64(h3, s4) + mul32x32_64(h4, s3);
@ -100,31 +100,39 @@ poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t
c = (t[0] >> 26);
t[1] += c;
h1 = (uint32_t) t[1] & 0x3ffffff;
b = (uint32_t) (t[1] >> 26);
b = (uint32_t)(t[1] >> 26);
t[2] += b;
h2 = (uint32_t) t[2] & 0x3ffffff;
b = (uint32_t) (t[2] >> 26);
b = (uint32_t)(t[2] >> 26);
t[3] += b;
h3 = (uint32_t) t[3] & 0x3ffffff;
b = (uint32_t) (t[3] >> 26);
b = (uint32_t)(t[3] >> 26);
t[4] += b;
h4 = (uint32_t) t[4] & 0x3ffffff;
b = (uint32_t) (t[4] >> 26);
b = (uint32_t)(t[4] >> 26);
h0 += b * 5;
if (inlen >= 16)
if(inlen >= 16) {
goto poly1305_donna_16bytes;
}
/* final bytes */
poly1305_donna_atmost15bytes:
if (!inlen)
goto poly1305_donna_finish;
poly1305_donna_atmost15bytes:
for (j = 0; j < inlen; j++)
if(!inlen) {
goto poly1305_donna_finish;
}
for(j = 0; j < inlen; j++) {
mp[j] = m[j];
}
mp[j++] = 1;
for (; j < 16; j++)
for(; j < 16; j++) {
mp[j] = 0;
}
inlen = 0;
t0 = U8TO32_LE(mp + 0);
@ -140,7 +148,7 @@ poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t
goto poly1305_donna_mul;
poly1305_donna_finish:
poly1305_donna_finish:
b = h0 >> 26;
h0 = h0 & 0x3ffffff;
h1 += b;

View file

@ -1,6 +1,6 @@
/* $OpenBSD: poly1305.h,v 1.2 2013/12/19 22:57:13 djm Exp $ */
/*
/*
* Public Domain poly1305 from Andrew Moon
* poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna
*/
@ -8,9 +8,9 @@
#ifndef POLY1305_H
#define POLY1305_H
#define POLY1305_KEYLEN 32
#define POLY1305_TAGLEN 16
#define POLY1305_KEYLEN 32
#define POLY1305_TAGLEN 16
void poly1305_auth(uint8_t out[POLY1305_TAGLEN], const uint8_t *m, size_t inlen, const uint8_t key[POLY1305_KEYLEN]);
#endif /* POLY1305_H */
#endif /* POLY1305_H */

View file

@ -1,3 +1,6 @@
#ifndef TINC_CIPHER_H
#define TINC_CIPHER_H
/*
cipher.h -- header file cipher.c
Copyright (C) 2007-2016 Guus Sliepen <guus@tinc-vpn.org>
@ -17,9 +20,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_CIPHER_H__
#define __TINC_CIPHER_H__
#define CIPHER_MAX_BLOCK_SIZE 32
#define CIPHER_MAX_IV_SIZE 16
#define CIPHER_MAX_KEY_SIZE 32
@ -28,19 +28,18 @@
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 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__));
extern bool cipher_encrypt(cipher_t *, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) __attribute__ ((__warn_unused_result__));
extern bool cipher_decrypt(cipher_t *, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) __attribute__ ((__warn_unused_result__));
extern int cipher_get_nid(const cipher_t *);
extern bool cipher_active(const cipher_t *);
extern cipher_t *cipher_open_by_name(const char *name) __attribute__((__malloc__));
extern cipher_t *cipher_open_by_nid(int nid) __attribute__((__malloc__));
extern void cipher_close(cipher_t *cipher);
extern size_t cipher_keylength(const cipher_t *cipher);
extern size_t cipher_blocksize(const cipher_t *cipher);
extern uint64_t cipher_budget(const cipher_t *cipher);
extern bool cipher_set_key(cipher_t *cipher, void *key, bool encrypt) __attribute__((__warn_unused_result__));
extern bool cipher_set_key_from_rsa(cipher_t *cipher, void *rsa, size_t len, bool encrypt) __attribute__((__warn_unused_result__));
extern bool cipher_encrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) __attribute__((__warn_unused_result__));
extern bool cipher_decrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) __attribute__((__warn_unused_result__));
extern int cipher_get_nid(const cipher_t *cipher);
extern bool cipher_active(const cipher_t *cipher);
#endif

View file

@ -46,27 +46,31 @@ static int config_compare(const config_t *a, const config_t *b) {
result = strcasecmp(a->variable, b->variable);
if(result)
if(result) {
return result;
}
/* give priority to command line options */
result = !b->file - !a->file;
if (result)
if(result) {
return result;
}
result = a->line - b->line;
if(result)
if(result) {
return result;
else
} else {
return a->file ? strcmp(a->file, b->file) : 0;
}
}
void init_configuration(splay_tree_t ** config_tree) {
void init_configuration(splay_tree_t **config_tree) {
*config_tree = splay_alloc_tree((splay_compare_t) config_compare, (splay_action_t) free_config);
}
void exit_configuration(splay_tree_t ** config_tree) {
void exit_configuration(splay_tree_t **config_tree) {
splay_delete_tree(*config_tree);
*config_tree = NULL;
}
@ -76,15 +80,9 @@ config_t *new_config(void) {
}
void free_config(config_t *cfg) {
if(cfg->variable)
free(cfg->variable);
if(cfg->value)
free(cfg->value);
if(cfg->file)
free(cfg->file);
free(cfg->variable);
free(cfg->value);
free(cfg->file);
free(cfg);
}
@ -101,11 +99,13 @@ config_t *lookup_config(splay_tree_t *config_tree, char *variable) {
found = splay_search_closest_greater(config_tree, &cfg);
if(!found)
if(!found) {
return NULL;
}
if(strcasecmp(found->variable, variable))
if(strcasecmp(found->variable, variable)) {
return NULL;
}
return found;
}
@ -120,8 +120,9 @@ config_t *lookup_config_next(splay_tree_t *config_tree, const config_t *cfg) {
if(node->next) {
found = node->next->data;
if(!strcasecmp(found->variable, cfg->variable))
if(!strcasecmp(found->variable, cfg->variable)) {
return found;
}
}
}
@ -129,8 +130,9 @@ config_t *lookup_config_next(splay_tree_t *config_tree, const config_t *cfg) {
}
bool get_config_bool(const config_t *cfg, bool *result) {
if(!cfg)
if(!cfg) {
return false;
}
if(!strcasecmp(cfg->value, "yes")) {
*result = true;
@ -141,27 +143,30 @@ bool get_config_bool(const config_t *cfg, bool *result) {
}
logger(DEBUG_ALWAYS, LOG_ERR, "\"yes\" or \"no\" expected for configuration variable %s in %s line %d",
cfg->variable, cfg->file, cfg->line);
cfg->variable, cfg->file, cfg->line);
return false;
}
bool get_config_int(const config_t *cfg, int *result) {
if(!cfg)
if(!cfg) {
return false;
}
if(sscanf(cfg->value, "%d", result) == 1)
if(sscanf(cfg->value, "%d", result) == 1) {
return true;
}
logger(DEBUG_ALWAYS, LOG_ERR, "Integer expected for configuration variable %s in %s line %d",
cfg->variable, cfg->file, cfg->line);
cfg->variable, cfg->file, cfg->line);
return false;
}
bool get_config_string(const config_t *cfg, char **result) {
if(!cfg)
if(!cfg) {
return false;
}
*result = xstrdup(cfg->value);
@ -171,8 +176,9 @@ bool get_config_string(const config_t *cfg, char **result) {
bool get_config_address(const config_t *cfg, struct addrinfo **result) {
struct addrinfo *ai;
if(!cfg)
if(!cfg) {
return false;
}
ai = str2addrinfo(cfg->value, NULL, 0);
@ -182,31 +188,32 @@ bool get_config_address(const config_t *cfg, struct addrinfo **result) {
}
logger(DEBUG_ALWAYS, LOG_ERR, "Hostname or IP address expected for configuration variable %s in %s line %d",
cfg->variable, cfg->file, cfg->line);
cfg->variable, cfg->file, cfg->line);
return false;
}
bool get_config_subnet(const config_t *cfg, subnet_t ** result) {
subnet_t subnet = {NULL};
bool get_config_subnet(const config_t *cfg, subnet_t **result) {
subnet_t subnet = {0};
if(!cfg)
if(!cfg) {
return false;
}
if(!str2net(&subnet, cfg->value)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Subnet expected for configuration variable %s in %s line %d",
cfg->variable, cfg->file, cfg->line);
cfg->variable, cfg->file, cfg->line);
return false;
}
/* Teach newbies what subnets are... */
if(((subnet.type == SUBNET_IPV4)
&& !maskcheck(&subnet.net.ipv4.address, subnet.net.ipv4.prefixlength, sizeof subnet.net.ipv4.address))
|| ((subnet.type == SUBNET_IPV6)
&& !maskcheck(&subnet.net.ipv6.address, subnet.net.ipv6.prefixlength, sizeof subnet.net.ipv6.address))) {
&& !maskcheck(&subnet.net.ipv4.address, subnet.net.ipv4.prefixlength, sizeof(subnet.net.ipv4.address)))
|| ((subnet.type == SUBNET_IPV6)
&& !maskcheck(&subnet.net.ipv6.address, subnet.net.ipv6.prefixlength, sizeof(subnet.net.ipv6.address)))) {
logger(DEBUG_ALWAYS, LOG_ERR, "Network address and prefix length do not match for configuration variable %s in %s line %d",
cfg->variable, cfg->file, cfg->line);
cfg->variable, cfg->file, cfg->line);
return false;
}
@ -218,27 +225,32 @@ bool get_config_subnet(const config_t *cfg, subnet_t ** result) {
/*
Read exactly one line and strip the trailing newline if any.
*/
static char *readline(FILE * fp, char *buf, size_t buflen) {
static char *readline(FILE *fp, char *buf, size_t buflen) {
char *newline = NULL;
char *p;
if(feof(fp))
if(feof(fp)) {
return NULL;
}
p = fgets(buf, buflen, fp);
if(!p)
if(!p) {
return NULL;
}
newline = strchr(p, '\n');
if(!newline)
if(!newline) {
return buf;
}
/* kill newline and carriage return if necessary */
*newline = '\0';
if(newline > p && newline[-1] == '\r')
if(newline > p && newline[-1] == '\r') {
newline[-1] = '\0';
}
return buf;
}
@ -250,26 +262,32 @@ config_t *parse_config_line(char *line, const char *fname, int lineno) {
variable = value = line;
eol = line + strlen(line);
while(strchr("\t ", *--eol))
while(strchr("\t ", *--eol)) {
*eol = '\0';
}
len = strcspn(value, "\t =");
value += len;
value += strspn(value, "\t ");
if(*value == '=') {
value++;
value += strspn(value, "\t ");
}
variable[len] = '\0';
if(!*value) {
const char err[] = "No value for variable";
if (fname)
if(fname)
logger(DEBUG_ALWAYS, LOG_ERR, "%s `%s' on line %d while reading config file %s",
err, variable, lineno, fname);
err, variable, lineno, fname);
else
logger(DEBUG_ALWAYS, LOG_ERR, "%s `%s' in command line option %d",
err, variable, lineno);
err, variable, lineno);
return NULL;
}
@ -286,7 +304,7 @@ config_t *parse_config_line(char *line, const char *fname, int lineno) {
Parse a configuration file and put the results in the configuration tree
starting at *base.
*/
bool read_config_file(splay_tree_t *config_tree, const char *fname) {
bool read_config_file(splay_tree_t *config_tree, const char *fname, bool verbose) {
FILE *fp;
char buffer[MAX_STRING_SIZE];
char *line;
@ -298,27 +316,32 @@ bool read_config_file(splay_tree_t *config_tree, const char *fname) {
fp = fopen(fname, "r");
if(!fp) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "Cannot open config file %s: %s", fname, strerror(errno));
logger(verbose ? DEBUG_ALWAYS : DEBUG_CONNECTIONS, LOG_ERR, "Cannot open config file %s: %s", fname, strerror(errno));
return false;
}
for(;;) {
line = readline(fp, buffer, sizeof buffer);
line = readline(fp, buffer, sizeof(buffer));
if(!line) {
if(feof(fp))
if(feof(fp)) {
result = true;
}
break;
}
lineno++;
if(!*line || *line == '#')
if(!*line || *line == '#') {
continue;
}
if(ignore) {
if(!strncmp(line, "-----END", 8))
if(!strncmp(line, "-----END", 8)) {
ignore = false;
}
continue;
}
@ -328,8 +351,11 @@ bool read_config_file(splay_tree_t *config_tree, const char *fname) {
}
cfg = parse_config_line(line, fname, lineno);
if (!cfg)
if(!cfg) {
break;
}
config_add(config_tree, cfg);
}
@ -346,19 +372,24 @@ void read_config_options(splay_tree_t *config_tree, const char *prefix) {
config_t *new;
if(!prefix) {
if(strchr(cfg->variable, '.'))
if(strchr(cfg->variable, '.')) {
continue;
}
} else {
if(strncmp(prefix, cfg->variable, prefix_len) ||
cfg->variable[prefix_len] != '.')
cfg->variable[prefix_len] != '.') {
continue;
}
}
new = new_config();
if(prefix)
if(prefix) {
new->variable = xstrdup(cfg->variable + prefix_len + 1);
else
} else {
new->variable = xstrdup(cfg->variable);
}
new->value = xstrdup(cfg->value);
new->file = NULL;
new->line = cfg->line;
@ -373,52 +404,57 @@ bool read_server_config(void) {
read_config_options(config_tree, NULL);
snprintf(fname, sizeof fname, "%s" SLASH "tinc.conf", confbase);
snprintf(fname, sizeof(fname), "%s" SLASH "tinc.conf", confbase);
errno = 0;
x = read_config_file(config_tree, fname);
x = read_config_file(config_tree, fname, true);
// We will try to read the conf files in the "conf.d" dir
if (x) {
if(x) {
char dname[PATH_MAX];
snprintf(dname, sizeof dname, "%s" SLASH "conf.d", confbase);
DIR *dir = opendir (dname);
snprintf(dname, sizeof(dname), "%s" SLASH "conf.d", confbase);
DIR *dir = opendir(dname);
// If we can find this dir
if (dir) {
if(dir) {
struct dirent *ep;
// We list all the files in it
while (x && (ep = readdir (dir))) {
while(x && (ep = readdir(dir))) {
size_t l = strlen(ep->d_name);
// And we try to read the ones that end with ".conf"
if (l > 5 && !strcmp(".conf", & ep->d_name[ l - 5 ])) {
snprintf(fname, sizeof fname, "%s" SLASH "%s", dname, ep->d_name);
x = read_config_file(config_tree, fname);
if(l > 5 && !strcmp(".conf", & ep->d_name[ l - 5 ])) {
if((size_t)snprintf(fname, sizeof(fname), "%s" SLASH "%s", dname, ep->d_name) >= sizeof(fname)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Pathname too long: %s/%s", dname, ep->d_name);
return false;
}
x = read_config_file(config_tree, fname, true);
}
}
closedir (dir);
closedir(dir);
}
}
if(!x && errno)
if(!x && errno) {
logger(DEBUG_ALWAYS, LOG_ERR, "Failed to read `%s': %s", fname, strerror(errno));
}
return x;
}
bool read_host_config(splay_tree_t *config_tree, const char *name) {
char fname[PATH_MAX];
bool x;
bool read_host_config(splay_tree_t *config_tree, const char *name, bool verbose) {
read_config_options(config_tree, name);
snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
x = read_config_file(config_tree, fname);
return x;
char fname[PATH_MAX];
snprintf(fname, sizeof(fname), "%s" SLASH "hosts" SLASH "%s", confbase, name);
return read_config_file(config_tree, fname, verbose);
}
bool append_config_file(const char *name, const char *key, const char *value) {
char fname[PATH_MAX];
snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
snprintf(fname, sizeof(fname), "%s" SLASH "hosts" SLASH "%s", confbase, name);
FILE *fp = fopen(fname, "a");

View file

@ -1,3 +1,6 @@
#ifndef TINC_CONF_H
#define TINC_CONF_H
/*
conf.h -- header for conf.c
Copyright (C) 1998-2005 Ivo Timmermans
@ -18,9 +21,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_CONF_H__
#define __TINC_CONF_H__
#include "list.h"
#include "splay_tree.h"
#include "subnet.h"
@ -41,24 +41,24 @@ extern int maxtimeout;
extern bool bypass_security;
extern list_t *cmdline_conf;
extern void init_configuration(splay_tree_t **);
extern void exit_configuration(splay_tree_t **);
extern config_t *new_config(void) __attribute__ ((__malloc__));
extern void free_config(config_t *);
extern void config_add(splay_tree_t *, config_t *);
extern config_t *lookup_config(splay_tree_t *, char *);
extern config_t *lookup_config_next(splay_tree_t *, const config_t *);
extern bool get_config_bool(const config_t *, bool *);
extern bool get_config_int(const config_t *, int *);
extern bool get_config_string(const config_t *, char **);
extern bool get_config_address(const config_t *, struct addrinfo **);
extern bool get_config_subnet(const config_t *, struct subnet_t **);
extern void init_configuration(splay_tree_t **config_tree);
extern void exit_configuration(splay_tree_t **config_tree);
extern config_t *new_config(void) __attribute__((__malloc__));
extern void free_config(config_t *config);
extern void config_add(splay_tree_t *config_tree, config_t *config);
extern config_t *lookup_config(splay_tree_t *config_tree, char *variable);
extern config_t *lookup_config_next(splay_tree_t *config_tree, const config_t *config);
extern bool get_config_bool(const config_t *config, bool *result);
extern bool get_config_int(const config_t *config, int *result);
extern bool get_config_string(const config_t *config, char **result);
extern bool get_config_address(const config_t *config, struct addrinfo **result);
extern bool get_config_subnet(const config_t *config, struct subnet_t **result);
extern config_t *parse_config_line(char *, const char *, int);
extern bool read_config_file(splay_tree_t *, const char *);
extern void read_config_options(splay_tree_t *, const char *);
extern config_t *parse_config_line(char *line, const char *fname, int lineno);
extern bool read_config_file(splay_tree_t *config_tree, const char *filename, bool verbose);
extern void read_config_options(splay_tree_t *config_tree, const char *prefix);
extern bool read_server_config(void);
extern bool read_host_config(splay_tree_t *, const char *);
extern bool append_config_file(const char *, const char *, const char *);
extern bool read_host_config(splay_tree_t *config_tree, const char *name, bool verbose);
extern bool append_config_file(const char *name, const char *key, const char *value);
#endif /* __TINC_CONF_H__ */
#endif

View file

@ -27,6 +27,7 @@
#include "control_common.h"
#include "list.h"
#include "logger.h"
#include "net.h"
#include "rsa.h"
#include "subnet.h"
#include "utils.h"
@ -52,8 +53,9 @@ connection_t *new_connection(void) {
}
void free_connection(connection_t *c) {
if(!c)
if(!c) {
return;
}
#ifndef DISABLE_LEGACY
cipher_close(c->incipher);
@ -67,20 +69,27 @@ void free_connection(connection_t *c) {
ecdsa_free(c->ecdsa);
free(c->hischallenge);
free(c->mychallenge);
buffer_clear(&c->inbuf);
buffer_clear(&c->outbuf);
io_del(&c->io);
if(c->socket > 0)
closesocket(c->socket);
if(c->socket > 0) {
if(c->status.tarpit) {
tarpit(c->socket);
} else {
closesocket(c->socket);
}
}
free(c->name);
free(c->hostname);
if(c->config_tree)
if(c->config_tree) {
exit_configuration(&c->config_tree);
}
free(c);
}
@ -96,9 +105,9 @@ void connection_del(connection_t *c) {
bool dump_connections(connection_t *cdump) {
for list_each(connection_t, c, connection_list) {
send_request(cdump, "%d %d %s %s %x %d %x",
CONTROL, REQ_DUMP_CONNECTIONS,
c->name, c->hostname, c->options, c->socket,
bitfield_to_int(&c->status, sizeof c->status));
CONTROL, REQ_DUMP_CONNECTIONS,
c->name, c->hostname, c->options, c->socket,
bitfield_to_int(&c->status, sizeof(c->status)));
}
return send_request(cdump, "%d %d", CONTROL, REQ_DUMP_CONNECTIONS);

View file

@ -1,3 +1,6 @@
#ifndef TINC_CONNECTION_H
#define TINC_CONNECTION_H
/*
connection.h -- header for connection.c
Copyright (C) 2000-2013 Guus Sliepen <guus@tinc-vpn.org>,
@ -18,9 +21,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_CONNECTION_H__
#define __TINC_CONNECTION_H__
#include "buffer.h"
#include "cipher.h"
#include "digest.h"
@ -35,21 +35,22 @@
#define OPTION_VERSION(x) ((x) >> 24) /* Top 8 bits are for protocol minor version */
typedef struct connection_status_t {
unsigned int pinged:1; /* sent ping */
unsigned int unused_active:1;
unsigned int connecting:1; /* 1 if we are waiting for a non-blocking connect() to finish */
unsigned int unused_termreq:1; /* the termination of this connection was requested */
unsigned int remove_unused:1; /* Set to 1 if you want this connection removed */
unsigned int timeout_unused:1; /* 1 if gotten timeout */
unsigned int encryptout:1; /* 1 if we can encrypt outgoing traffic */
unsigned int decryptin:1; /* 1 if we have to decrypt incoming traffic */
unsigned int mst:1; /* 1 if this connection is part of a minimum spanning tree */
unsigned int control:1; /* 1 if this is a control connection */
unsigned int pcap:1; /* 1 if this is a control connection requesting packet capture */
unsigned int log:1; /* 1 if this is a control connection requesting log dump */
unsigned int invitation:1; /* 1 if this is an invitation */
unsigned int invitation_used:1; /* 1 if the invitation has been consumed */
unsigned int unused:18;
unsigned int pinged: 1; /* sent ping */
unsigned int unused_active: 1;
unsigned int connecting: 1; /* 1 if we are waiting for a non-blocking connect() to finish */
unsigned int unused_termreq: 1; /* the termination of this connection was requested */
unsigned int remove_unused: 1; /* Set to 1 if you want this connection removed */
unsigned int timeout_unused: 1; /* 1 if gotten timeout */
unsigned int encryptout: 1; /* 1 if we can encrypt outgoing traffic */
unsigned int decryptin: 1; /* 1 if we have to decrypt incoming traffic */
unsigned int mst: 1; /* 1 if this connection is part of a minimum spanning tree */
unsigned int control: 1; /* 1 if this is a control connection */
unsigned int pcap: 1; /* 1 if this is a control connection requesting packet capture */
unsigned int log: 1; /* 1 if this is a control connection requesting log dump */
unsigned int invitation: 1; /* 1 if this is an invitation */
unsigned int invitation_used: 1; /* 1 if the invitation has been consumed */
unsigned int tarpit: 1; /* 1 if the connection should be added to the tarpit */
unsigned int unused: 17;
} connection_status_t;
#include "ecdsa.h"
@ -94,12 +95,13 @@ typedef struct connection_t {
int outcompression;
char *hischallenge; /* The challenge we sent to him */
char *mychallenge; /* The challenge we received */
struct buffer_t inbuf;
struct buffer_t outbuf;
io_t io; /* input/output event on this metadata connection */
int tcplen; /* length of incoming TCPpacket */
int sptpslen; /* length of incoming SPTPS packet */
int sptpslen; /* length of incoming SPTPS packet */
int allow_request; /* defined if there's only one request possible */
time_t last_ping_time; /* last time we saw some activity from the other end or pinged them */
@ -112,10 +114,10 @@ extern connection_t *everyone;
extern void init_connections(void);
extern void exit_connections(void);
extern connection_t *new_connection(void) __attribute__ ((__malloc__));
extern void free_connection(connection_t *);
extern void connection_add(connection_t *);
extern void connection_del(connection_t *);
extern bool dump_connections(struct connection_t *);
extern connection_t *new_connection(void) __attribute__((__malloc__));
extern void free_connection(connection_t *c);
extern void connection_add(connection_t *c);
extern void connection_del(connection_t *c);
extern bool dump_connections(struct connection_t *c);
#endif /* __TINC_CONNECTION_H__ */
#endif

View file

@ -56,86 +56,95 @@ bool control_h(connection_t *c, const char *request) {
return false;
}
switch (type) {
case REQ_STOP:
event_exit();
return control_ok(c, REQ_STOP);
switch(type) {
case REQ_STOP:
event_exit();
return control_ok(c, REQ_STOP);
case REQ_DUMP_NODES:
return dump_nodes(c);
case REQ_DUMP_NODES:
return dump_nodes(c);
case REQ_DUMP_EDGES:
return dump_edges(c);
case REQ_DUMP_EDGES:
return dump_edges(c);
case REQ_DUMP_SUBNETS:
return dump_subnets(c);
case REQ_DUMP_SUBNETS:
return dump_subnets(c);
case REQ_DUMP_CONNECTIONS:
return dump_connections(c);
case REQ_DUMP_CONNECTIONS:
return dump_connections(c);
case REQ_PURGE:
purge();
return control_ok(c, REQ_PURGE);
case REQ_PURGE:
purge();
return control_ok(c, REQ_PURGE);
case REQ_SET_DEBUG: {
int new_level;
if(sscanf(request, "%*d %*d %d", &new_level) != 1)
return false;
send_request(c, "%d %d %d", CONTROL, REQ_SET_DEBUG, debug_level);
if(new_level >= 0)
debug_level = new_level;
return true;
case REQ_SET_DEBUG: {
int new_level;
if(sscanf(request, "%*d %*d %d", &new_level) != 1) {
return false;
}
case REQ_RETRY:
retry();
return control_ok(c, REQ_RETRY);
send_request(c, "%d %d %d", CONTROL, REQ_SET_DEBUG, debug_level);
case REQ_RELOAD:
logger(DEBUG_ALWAYS, LOG_NOTICE, "Got '%s' command", "reload");
int result = reload_configuration();
return control_return(c, REQ_RELOAD, result);
if(new_level >= 0) {
debug_level = new_level;
}
case REQ_DISCONNECT: {
char name[MAX_STRING_SIZE];
bool found = false;
return true;
}
if(sscanf(request, "%*d %*d " MAX_STRING, name) != 1)
return control_return(c, REQ_DISCONNECT, -1);
case REQ_RETRY:
retry();
return control_ok(c, REQ_RETRY);
for list_each(connection_t, other, connection_list) {
if(strcmp(other->name, name))
continue;
terminate_connection(other, other->edge);
found = true;
case REQ_RELOAD:
logger(DEBUG_ALWAYS, LOG_NOTICE, "Got '%s' command", "reload");
int result = reload_configuration();
return control_return(c, REQ_RELOAD, result);
case REQ_DISCONNECT: {
char name[MAX_STRING_SIZE];
bool found = false;
if(sscanf(request, "%*d %*d " MAX_STRING, name) != 1) {
return control_return(c, REQ_DISCONNECT, -1);
}
for list_each(connection_t, other, connection_list) {
if(strcmp(other->name, name)) {
continue;
}
return control_return(c, REQ_DISCONNECT, found ? 0 : -2);
terminate_connection(other, other->edge);
found = true;
}
case REQ_DUMP_TRAFFIC:
return dump_traffic(c);
return control_return(c, REQ_DISCONNECT, found ? 0 : -2);
}
case REQ_PCAP:
sscanf(request, "%*d %*d %d", &c->outmaclength);
c->status.pcap = true;
pcap = true;
return true;
case REQ_DUMP_TRAFFIC:
return dump_traffic(c);
case REQ_LOG:
sscanf(request, "%*d %*d %d", &c->outcompression);
c->status.log = true;
logcontrol = true;
return true;
case REQ_PCAP:
sscanf(request, "%*d %*d %d", &c->outmaclength);
c->status.pcap = true;
pcap = true;
return true;
default:
return send_request(c, "%d %d", CONTROL, REQ_INVALID);
case REQ_LOG:
sscanf(request, "%*d %*d %d", &c->outcompression);
c->status.log = true;
logcontrol = true;
return true;
default:
return send_request(c, "%d %d", CONTROL, REQ_INVALID);
}
}
bool init_control(void) {
randomize(controlcookie, sizeof controlcookie / 2);
bin2hex(controlcookie, controlcookie, sizeof controlcookie / 2);
randomize(controlcookie, sizeof(controlcookie) / 2);
bin2hex(controlcookie, controlcookie, sizeof(controlcookie) / 2);
mode_t mask = umask(0);
umask(mask | 077);
@ -150,21 +159,24 @@ bool init_control(void) {
// Get the address and port of the first listening socket
char *localhost = NULL;
sockaddr_t sa;
socklen_t len = sizeof sa;
sockaddr_t sa = {0};
socklen_t len = sizeof(sa);
// Make sure we have a valid address, and map 0.0.0.0 and :: to 127.0.0.1 and ::1.
if(getsockname(listen_socket[0].tcp.fd, (struct sockaddr *)&sa, &len)) {
if(getsockname(listen_socket[0].tcp.fd, &sa.sa, &len)) {
xasprintf(&localhost, "127.0.0.1 port %s", myport);
} else {
if(sa.sa.sa_family == AF_INET) {
if(sa.in.sin_addr.s_addr == 0)
if(sa.in.sin_addr.s_addr == 0) {
sa.in.sin_addr.s_addr = htonl(0x7f000001);
}
} else if(sa.sa.sa_family == AF_INET6) {
static const uint8_t zero[16] = {0};
if(!memcmp(sa.in6.sin6_addr.s6_addr, zero, sizeof zero))
if(!memcmp(sa.in6.sin6_addr.s6_addr, zero, sizeof(zero))) {
sa.in6.sin6_addr.s6_addr[15] = 1;
}
}
localhost = sockaddr2hostname(&sa);
@ -177,16 +189,21 @@ bool init_control(void) {
#ifndef HAVE_MINGW
int unix_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if(unix_fd < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not create UNIX socket: %s", sockstrerror(sockerrno));
return false;
}
struct sockaddr_un sa_un;
sa_un.sun_family = AF_UNIX;
strncpy(sa_un.sun_path, unixsocketname, sizeof sa_un.sun_path);
if(connect(unix_fd, (struct sockaddr *)&sa_un, sizeof sa_un) >= 0) {
sa_un.sun_family = AF_UNIX;
strncpy(sa_un.sun_path, unixsocketname, sizeof(sa_un.sun_path));
sa_un.sun_path[sizeof(sa_un.sun_path) - 1] = 0;
if(connect(unix_fd, (struct sockaddr *)&sa_un, sizeof(sa_un)) >= 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "UNIX socket %s is still in use!", unixsocketname);
return false;
}
@ -194,7 +211,7 @@ bool init_control(void) {
unlink(unixsocketname);
umask(mask | 077);
int result = bind(unix_fd, (struct sockaddr *)&sa_un, sizeof sa_un);
int result = bind(unix_fd, (struct sockaddr *)&sa_un, sizeof(sa_un));
umask(mask);
if(result < 0) {

View file

@ -1,3 +1,6 @@
#ifndef TINC_CONTROL_H
#define TINC_CONTROL_H
/*
control.h -- header for control.c.
Copyright (C) 2007 Guus Sliepen <guus@tinc-vpn.org>
@ -17,11 +20,8 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_CONTROL_H__
#define __TINC_CONTROL_H__
extern bool init_control();
extern void exit_control();
extern bool init_control(void);
extern void exit_control(void);
extern char controlcookie[];
#endif

View file

@ -1,3 +1,6 @@
#ifndef TINC_CONTROL_COMMON_H
#define TINC_CONTROL_COMMON_H
/*
control_protocol.h -- control socket protocol.
Copyright (C) 2007 Scott Lamb <slamb@slamb.org>
@ -18,9 +21,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_CONTROL_PROTOCOL_H__
#define __TINC_CONTROL_PROTOCOL_H__
#include "protocol.h"
enum request_type {

View file

@ -1,3 +1,6 @@
#ifndef TINC_CRYPTO_H
#define TINC_CRYPTO_H
/*
crypto.h -- header for crypto.c
Copyright (C) 2007-2013 Guus Sliepen <guus@tinc-vpn.org>
@ -17,11 +20,8 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_CRYPTO_H__
#define __TINC_CRYPTO_H__
extern void crypto_init();
extern void crypto_exit();
extern void randomize(void *, size_t);
extern void crypto_init(void);
extern void crypto_exit(void);
extern void randomize(void *buf, size_t buflen);
#endif

View file

@ -38,7 +38,7 @@ int device_fd = -1;
static HANDLE device_handle = INVALID_HANDLE_VALUE;
char *device = NULL;
char *iface = NULL;
static char *device_info = NULL;
static const char *device_info = "Windows tap device";
static pid_t reader_pid;
static int sp[2];
@ -59,8 +59,9 @@ static bool setup_device(void) {
get_config_string(lookup_config(config_tree, "Device"), &device);
get_config_string(lookup_config(config_tree, "Interface"), &iface);
if(device && iface)
if(device && iface) {
logger(LOG_WARNING, "Warning: both Device and Interface specified, results may not be as expected");
}
/* Open registry and look for network adapters */
@ -69,44 +70,51 @@ static bool setup_device(void) {
return false;
}
for (i = 0; ; i++) {
len = sizeof adapterid;
if(RegEnumKeyEx(key, i, adapterid, &len, 0, 0, 0, NULL))
for(i = 0; ; i++) {
len = sizeof(adapterid);
if(RegEnumKeyEx(key, i, adapterid, &len, 0, 0, 0, NULL)) {
break;
}
/* Find out more about this adapter */
snprintf(regpath, sizeof regpath, "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapterid);
snprintf(regpath, sizeof(regpath), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapterid);
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2))
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2)) {
continue;
}
len = sizeof adaptername;
len = sizeof(adaptername);
err = RegQueryValueEx(key2, "Name", 0, 0, adaptername, &len);
RegCloseKey(key2);
if(err)
if(err) {
continue;
}
if(device) {
if(!strcmp(device, adapterid)) {
found = true;
break;
} else
} else {
continue;
}
}
if(iface) {
if(!strcmp(iface, adaptername)) {
found = true;
break;
} else
} else {
continue;
}
}
snprintf(tapname, sizeof tapname, USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
if(device_handle != INVALID_HANDLE_VALUE) {
CloseHandle(device_handle);
found = true;
@ -121,13 +129,15 @@ static bool setup_device(void) {
return false;
}
if(!device)
if(!device) {
device = xstrdup(adapterid);
}
if(!iface)
if(!iface) {
iface = xstrdup(adaptername);
}
snprintf(tapname, sizeof tapname, USERMODEDEVICEDIR "%s" TAPSUFFIX, device);
snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, device);
/* Now we are going to open this device twice: once for reading and once for writing.
We do this because apparently it isn't possible to check for activity in the select() loop.
@ -140,7 +150,7 @@ static bool setup_device(void) {
/* The parent opens the tap device for writing. */
device_handle = CreateFile(tapname, GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM , 0);
device_handle = CreateFile(tapname, GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
if(device_handle == INVALID_HANDLE_VALUE) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not open Windows tap device %s (%s) for writing: %s", device, iface, winerror(GetLastError()));
@ -151,7 +161,7 @@ static bool setup_device(void) {
/* Get MAC address from tap device */
if(!DeviceIoControl(device_handle, TAP_IOCTL_GET_MAC, mymac.x, sizeof mymac.x, mymac.x, sizeof mymac.x, &len, 0)) {
if(!DeviceIoControl(device_handle, TAP_IOCTL_GET_MAC, mymac.x, sizeof(mymac.x), mymac.x, sizeof(mymac.x), &len, 0)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not get MAC address from Windows tap device %s (%s): %s", device, iface, winerror(GetLastError()));
return false;
}
@ -203,13 +213,12 @@ static bool setup_device(void) {
}
read(device_fd, &gelukt, 1);
if(gelukt != 1) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "Tap reader failed!");
return false;
}
device_info = "Windows tap device";
logger(DEBUG_ALWAYS, LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
return true;
@ -218,12 +227,15 @@ static bool setup_device(void) {
static void close_device(void) {
close(sp[0]);
close(sp[1]);
CloseHandle(device_handle); device_handle = INVALID_HANDLE_VALUE;
CloseHandle(device_handle);
device_handle = INVALID_HANDLE_VALUE;
kill(reader_pid, SIGKILL);
free(device); device = NULL;
free(iface); iface = NULL;
free(device);
device = NULL;
free(iface);
iface = NULL;
device_info = NULL;
}
@ -232,14 +244,14 @@ static bool read_packet(vpn_packet_t *packet) {
if((inlen = read(sp[0], DATA(packet), MTU)) <= 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno));
device, strerror(errno));
return false;
}
packet->len = inlen;
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len,
device_info);
device_info);
return true;
}
@ -248,9 +260,9 @@ static bool write_packet(vpn_packet_t *packet) {
long outlen;
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s",
packet->len, device_info);
packet->len, device_info);
if(!WriteFile (device_handle, DATA(packet), packet->len, &outlen, NULL)) {
if(!WriteFile(device_handle, DATA(packet), packet->len, &outlen, NULL)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info, device, winerror(GetLastError()));
return false;
}

View file

@ -1,3 +1,6 @@
#ifndef TINC_DEVICE_H
#define TINC_DEVICE_H
/*
device.h -- generic header for device.c
Copyright (C) 2001-2005 Ivo Timmermans
@ -18,9 +21,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_DEVICE_H__
#define __TINC_DEVICE_H__
#include "net.h"
extern int device_fd;
@ -45,4 +45,4 @@ extern const devops_t uml_devops;
extern const devops_t vde_devops;
extern devops_t devops;
#endif /* __TINC_DEVICE_H__ */
#endif

View file

@ -1,3 +1,6 @@
#ifndef TINC_DIGEST_H
#define TINC_DIGEST_H
/*
digest.h -- header file digest.c
Copyright (C) 2007-2016 Guus Sliepen <guus@tinc-vpn.org>
@ -17,25 +20,22 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_DIGEST_H__
#define __TINC_DIGEST_H__
#define DIGEST_MAX_SIZE 64
#ifndef DISABLE_LEGACY
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 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__));
extern bool digest_set_key(digest_t *, const void *key, size_t len) __attribute__ ((__warn_unused_result__));
extern int digest_get_nid(const digest_t *);
extern size_t digest_keylength(const digest_t *);
extern size_t digest_length(const digest_t *);
extern bool digest_active(const 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 void digest_close(digest_t *digest);
extern bool digest_create(digest_t *digest, const void *indata, size_t inlen, void *outdata) __attribute__((__warn_unused_result__));
extern bool digest_verify(digest_t *digest, const void *indata, size_t inlen, const void *digestdata) __attribute__((__warn_unused_result__));
extern bool digest_set_key(digest_t *digest, const void *key, size_t len) __attribute__((__warn_unused_result__));
extern int digest_get_nid(const digest_t *digest);
extern size_t digest_keylength(const digest_t *digest);
extern size_t digest_length(const digest_t *digest);
extern bool digest_active(const digest_t *digest);
#endif

View file

@ -50,8 +50,9 @@ int daemon(int nochdir, int noclose) {
}
/* If we are the parent, terminate */
if(pid)
if(pid) {
exit(0);
}
/* Detach by becoming the new process group leader */
if(setsid() < 0) {
@ -108,8 +109,9 @@ int vasprintf(char **buf, const char *fmt, va_list ap) {
status = vsnprintf(*buf, len, fmt, aq);
va_end(aq);
if(status >= 0)
if(status >= 0) {
*buf = xrealloc(*buf, status + 1);
}
if(status > len - 1) {
len = status + 1;

View file

@ -1,3 +1,6 @@
#ifndef TINC_DROPIN_H
#define TINC_DROPIN_H
/*
dropin.h -- header file for dropin.c
Copyright (C) 2000-2005 Ivo Timmermans,
@ -18,9 +21,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __DROPIN_H__
#define __DROPIN_H__
#ifndef HAVE_DAEMON
extern int daemon(int, int);
#endif
@ -40,20 +40,20 @@ extern int nanosleep(const struct timespec *req, struct timespec *rem);
#ifndef timeradd
#define timeradd(a, b, r) do {\
(r)->tv_sec = (a)->tv_sec + (b)->tv_sec;\
(r)->tv_usec = (a)->tv_usec + (b)->tv_usec;\
if((r)->tv_usec >= 1000000)\
(r)->tv_sec++, (r)->tv_usec -= 1000000;\
} while (0)
(r)->tv_sec = (a)->tv_sec + (b)->tv_sec;\
(r)->tv_usec = (a)->tv_usec + (b)->tv_usec;\
if((r)->tv_usec >= 1000000)\
(r)->tv_sec++, (r)->tv_usec -= 1000000;\
} while (0)
#endif
#ifndef timersub
#define timersub(a, b, r) do {\
(r)->tv_sec = (a)->tv_sec - (b)->tv_sec;\
(r)->tv_usec = (a)->tv_usec - (b)->tv_usec;\
if((r)->tv_usec < 0)\
(r)->tv_sec--, (r)->tv_usec += 1000000;\
} while (0)
(r)->tv_sec = (a)->tv_sec - (b)->tv_sec;\
(r)->tv_usec = (a)->tv_usec - (b)->tv_usec;\
if((r)->tv_usec < 0)\
(r)->tv_sec--, (r)->tv_usec += 1000000;\
} while (0)
#endif
#ifdef HAVE_MINGW
@ -67,4 +67,4 @@ extern int nanosleep(const struct timespec *req, struct timespec *rem);
#define EAI_SYSTEM 0
#endif
#endif /* __DROPIN_H__ */
#endif

View file

@ -22,12 +22,13 @@
#include "device.h"
#include "logger.h"
#include "net.h"
#include "xalloc.h"
static char *device_info = "dummy device";
static const char *device_info = "dummy device";
static bool setup_device(void) {
device = "dummy";
iface = "dummy";
device = xstrdup("dummy");
iface = xstrdup("dummy");
logger(DEBUG_ALWAYS, LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
return true;
}
@ -36,10 +37,12 @@ static void close_device(void) {
}
static bool read_packet(vpn_packet_t *packet) {
(void)packet;
return false;
}
static bool write_packet(vpn_packet_t *packet) {
(void)packet;
return true;
}

View file

@ -1,3 +1,6 @@
#ifndef TINC_ECDH_H
#define TINC_ECDH_H
/*
ecdh.h -- header file for ecdh.c
Copyright (C) 2011-2013 Guus Sliepen <guus@tinc-vpn.org>
@ -17,18 +20,15 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_ECDH_H__
#define __TINC_ECDH_H__
#define ECDH_SIZE 32
#define ECDH_SHARED_SIZE 32
#ifndef __TINC_ECDH_INTERNAL__
#ifndef TINC_ECDH_INTERNAL
typedef struct ecdh ecdh_t;
#endif
extern ecdh_t *ecdh_generate_public(void *pubkey) __attribute__ ((__malloc__));
extern bool ecdh_compute_shared(ecdh_t *ecdh, const void *pubkey, void *shared) __attribute__ ((__warn_unused_result__));
extern ecdh_t *ecdh_generate_public(void *pubkey) __attribute__((__malloc__));
extern bool ecdh_compute_shared(ecdh_t *ecdh, const void *pubkey, void *shared) __attribute__((__warn_unused_result__));
extern void ecdh_free(ecdh_t *ecdh);
#endif

View file

@ -1,3 +1,6 @@
#ifndef TINC_ECDSA_H
#define TINC_ECDSA_H
/*
ecdsa.h -- ECDSA key handling
Copyright (C) 2011-2013 Guus Sliepen <guus@tinc-vpn.org>
@ -17,20 +20,17 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_ECDSA_H__
#define __TINC_ECDSA_H__
#ifndef __TINC_ECDSA_INTERNAL__
#ifndef TINC_ECDSA_INTERNAL
typedef struct ecdsa ecdsa_t;
#endif
extern ecdsa_t *ecdsa_set_base64_public_key(const char *p) __attribute__ ((__malloc__));
extern ecdsa_t *ecdsa_set_base64_public_key(const char *p) __attribute__((__malloc__));
extern char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa);
extern ecdsa_t *ecdsa_read_pem_public_key(FILE *fp) __attribute__ ((__malloc__));
extern ecdsa_t *ecdsa_read_pem_private_key(FILE *fp) __attribute__ ((__malloc__));
extern ecdsa_t *ecdsa_read_pem_public_key(FILE *fp) __attribute__((__malloc__));
extern ecdsa_t *ecdsa_read_pem_private_key(FILE *fp) __attribute__((__malloc__));
extern size_t ecdsa_size(ecdsa_t *ecdsa);
extern bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t inlen, void *out) __attribute__ ((__warn_unused_result__));
extern bool ecdsa_verify(ecdsa_t *ecdsa, const void *in, size_t inlen, const void *out) __attribute__ ((__warn_unused_result__));
extern bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t inlen, void *out) __attribute__((__warn_unused_result__));
extern bool ecdsa_verify(ecdsa_t *ecdsa, const void *in, size_t inlen, const void *out) __attribute__((__warn_unused_result__));
extern bool ecdsa_active(ecdsa_t *ecdsa);
extern void ecdsa_free(ecdsa_t *ecdsa);

View file

@ -1,3 +1,6 @@
#ifndef TINC_ECDSAGEN_H
#define TINC_ECDSAGEN_H
/*
ecdsagen.h -- ECDSA key generation and export
Copyright (C) 2011-2013 Guus Sliepen <guus@tinc-vpn.org>
@ -17,13 +20,10 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_ECDSAGEN_H__
#define __TINC_ECDSAGEN_H__
#include "ecdsa.h"
extern ecdsa_t *ecdsa_generate(void) __attribute__ ((__malloc__));
extern bool ecdsa_write_pem_public_key(ecdsa_t *ecdsa, FILE *fp) __attribute__ ((__warn_unused_result__));
extern bool ecdsa_write_pem_private_key(ecdsa_t *ecdsa, FILE *fp) __attribute__ ((__warn_unused_result__));
extern ecdsa_t *ecdsa_generate(void) __attribute__((__malloc__));
extern bool ecdsa_write_pem_public_key(ecdsa_t *ecdsa, FILE *fp) __attribute__((__warn_unused_result__));
extern bool ecdsa_write_pem_private_key(ecdsa_t *ecdsa, FILE *fp) __attribute__((__warn_unused_result__));
#endif

View file

@ -21,7 +21,7 @@
#include "ed25519.h"
#define __TINC_ECDH_INTERNAL__
#define TINC_ECDH_INTERNAL
typedef struct ecdh_t {
uint8_t private[64];
} ecdh_t;
@ -31,10 +31,10 @@ typedef struct ecdh_t {
#include "../xalloc.h"
ecdh_t *ecdh_generate_public(void *pubkey) {
ecdh_t *ecdh = xzalloc(sizeof *ecdh);
ecdh_t *ecdh = xzalloc(sizeof(*ecdh));
uint8_t seed[32];
randomize(seed, sizeof seed);
randomize(seed, sizeof(seed));
ed25519_create_keypair(pubkey, ecdh->private, seed);
return ecdh;

View file

@ -21,7 +21,7 @@
#include "ed25519.h"
#define __TINC_ECDSA_INTERNAL__
#define TINC_ECDSA_INTERNAL
typedef struct {
uint8_t private[64];
uint8_t public[32];
@ -42,8 +42,9 @@ ecdsa_t *ecdsa_set_base64_public_key(const char *p) {
return 0;
}
ecdsa_t *ecdsa = xzalloc(sizeof *ecdsa);
ecdsa_t *ecdsa = xzalloc(sizeof(*ecdsa));
len = b64decode(p, ecdsa->public, len);
if(len != 32) {
logger(DEBUG_ALWAYS, LOG_ERR, "Invalid format of public key! len = %d", len);
free(ecdsa);
@ -55,33 +56,40 @@ ecdsa_t *ecdsa_set_base64_public_key(const char *p) {
char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa) {
char *base64 = xmalloc(44);
b64encode(ecdsa->public, base64, sizeof ecdsa->public);
b64encode(ecdsa->public, base64, sizeof(ecdsa->public));
return base64;
}
// Read PEM ECDSA keys
static bool read_pem(FILE *fp, const char *type, void *buf, size_t size) {
static bool read_pem(FILE *fp, const char *type, void *vbuf, size_t size) {
char line[1024];
bool data = false;
size_t typelen = strlen(type);
char *buf = vbuf;
while(fgets(line, sizeof line, fp)) {
while(fgets(line, sizeof(line), fp)) {
if(!data) {
if(strncmp(line, "-----BEGIN ", 11))
if(strncmp(line, "-----BEGIN ", 11)) {
continue;
if(strncmp(line + 11, type, typelen))
}
if(strncmp(line + 11, type, typelen)) {
continue;
}
data = true;
continue;
}
if(!strncmp(line, "-----END ", 9))
if(!strncmp(line, "-----END ", 9)) {
break;
}
size_t linelen = strcspn(line, "\r\n");
size_t len = b64decode(line, line, linelen);
if(!len) {
logger(DEBUG_ALWAYS, LOG_ERR, "Invalid base64 data in PEM file\n");
errno = EINVAL;
@ -106,6 +114,7 @@ static bool read_pem(FILE *fp, const char *type, void *buf, size_t size) {
} else {
errno = ENOENT;
}
return false;
}
@ -113,22 +122,29 @@ static bool read_pem(FILE *fp, const char *type, void *buf, size_t size) {
}
ecdsa_t *ecdsa_read_pem_public_key(FILE *fp) {
ecdsa_t *ecdsa = xzalloc(sizeof *ecdsa);
if(read_pem(fp, "ED25519 PUBLIC KEY", ecdsa->public, sizeof ecdsa->public))
ecdsa_t *ecdsa = xzalloc(sizeof(*ecdsa));
if(read_pem(fp, "ED25519 PUBLIC KEY", ecdsa->public, sizeof(ecdsa->public))) {
return ecdsa;
}
free(ecdsa);
return 0;
}
ecdsa_t *ecdsa_read_pem_private_key(FILE *fp) {
ecdsa_t *ecdsa = xmalloc(sizeof *ecdsa);
if(read_pem(fp, "ED25519 PRIVATE KEY", ecdsa->private, sizeof *ecdsa))
ecdsa_t *ecdsa = xmalloc(sizeof(*ecdsa));
if(read_pem(fp, "ED25519 PRIVATE KEY", ecdsa->private, sizeof(*ecdsa))) {
return ecdsa;
}
free(ecdsa);
return 0;
}
size_t ecdsa_size(ecdsa_t *ecdsa) {
(void)ecdsa;
return 64;
}

View file

@ -21,7 +21,7 @@
#include "ed25519.h"
#define __TINC_ECDSA_INTERNAL__
#define TINC_ECDSA_INTERNAL
typedef struct {
uint8_t private[64];
uint8_t public[32];
@ -35,10 +35,10 @@ typedef struct {
// Generate ECDSA key
ecdsa_t *ecdsa_generate(void) {
ecdsa_t *ecdsa = xzalloc(sizeof *ecdsa);
ecdsa_t *ecdsa = xzalloc(sizeof(*ecdsa));
uint8_t seed[32];
randomize(seed, sizeof seed);
randomize(seed, sizeof(seed));
ed25519_create_keypair(ecdsa->public, ecdsa->private, seed);
return ecdsa;
@ -46,10 +46,12 @@ ecdsa_t *ecdsa_generate(void) {
// Write PEM ECDSA keys
static bool write_pem(FILE *fp, const char *type, void *buf, size_t size) {
static bool write_pem(FILE *fp, const char *type, void *vbuf, size_t size) {
fprintf(fp, "-----BEGIN %s-----\n", type);
char *buf = vbuf;
char base64[65];
while(size) {
size_t todo = size > 48 ? 48 : size;
b64encode(buf, base64, todo);
@ -63,9 +65,9 @@ static bool write_pem(FILE *fp, const char *type, void *buf, size_t size) {
}
bool ecdsa_write_pem_public_key(ecdsa_t *ecdsa, FILE *fp) {
return write_pem(fp, "ED25519 PUBLIC KEY", ecdsa->public, sizeof ecdsa->public);
return write_pem(fp, "ED25519 PUBLIC KEY", ecdsa->public, sizeof(ecdsa->public));
}
bool ecdsa_write_pem_private_key(ecdsa_t *ecdsa, FILE *fp) {
return write_pem(fp, "ED25519 PRIVATE KEY", ecdsa->private, sizeof *ecdsa);
return write_pem(fp, "ED25519 PRIVATE KEY", ecdsa->private, sizeof(*ecdsa));
}

View file

@ -4,15 +4,15 @@
#include <stddef.h>
#if defined(_WIN32)
#if defined(ED25519_BUILD_DLL)
#define ED25519_DECLSPEC __declspec(dllexport)
#elif defined(ED25519_DLL)
#define ED25519_DECLSPEC __declspec(dllimport)
#else
#define ED25519_DECLSPEC
#endif
#if defined(ED25519_BUILD_DLL)
#define ED25519_DECLSPEC __declspec(dllexport)
#elif defined(ED25519_DLL)
#define ED25519_DECLSPEC __declspec(dllimport)
#else
#define ED25519_DECLSPEC
#define ED25519_DECLSPEC
#endif
#else
#define ED25519_DECLSPEC
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,75 +1,75 @@
#ifndef TINC_FIXEDINT_H
#define TINC_FIXEDINT_H
/*
Portable header to provide the 32 and 64 bits type.
Not a compatible replacement for <stdint.h>, do not blindly use it as such.
*/
#ifndef __TINC_FIXEDINT_H__
#define __TINC_FIXEDINT_H__
#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined(__WATCOMC__) && (defined(_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_) || defined(__UINT_FAST64_TYPE__)) )) && !defined(FIXEDINT_H_INCLUDED)
#include <stdint.h>
#define FIXEDINT_H_INCLUDED
#include <stdint.h>
#define FIXEDINT_H_INCLUDED
#if defined(__WATCOMC__) && __WATCOMC__ >= 1250 && !defined(UINT64_C)
#include <limits.h>
#define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX))
#endif
#if defined(__WATCOMC__) && __WATCOMC__ >= 1250 && !defined(UINT64_C)
#include <limits.h>
#define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX))
#endif
#endif
#ifndef FIXEDINT_H_INCLUDED
#define FIXEDINT_H_INCLUDED
#define FIXEDINT_H_INCLUDED
/* (u)int32_t */
#ifndef uint32_t
#if (ULONG_MAX == 0xffffffffUL)
typedef unsigned long uint32_t;
#elif (UINT_MAX == 0xffffffffUL)
typedef unsigned int uint32_t;
#elif (USHRT_MAX == 0xffffffffUL)
typedef unsigned short uint32_t;
#endif
#endif
/* (u)int32_t */
#ifndef uint32_t
#if (ULONG_MAX == 0xffffffffUL)
typedef unsigned long uint32_t;
#elif (UINT_MAX == 0xffffffffUL)
typedef unsigned int uint32_t;
#elif (USHRT_MAX == 0xffffffffUL)
typedef unsigned short uint32_t;
#endif
#endif
#ifndef int32_t
#if (LONG_MAX == 0x7fffffffL)
typedef signed long int32_t;
#elif (INT_MAX == 0x7fffffffL)
typedef signed int int32_t;
#elif (SHRT_MAX == 0x7fffffffL)
typedef signed short int32_t;
#endif
#endif
#ifndef int32_t
#if (LONG_MAX == 0x7fffffffL)
typedef signed long int32_t;
#elif (INT_MAX == 0x7fffffffL)
typedef signed int int32_t;
#elif (SHRT_MAX == 0x7fffffffL)
typedef signed short int32_t;
#endif
#endif
/* (u)int64_t */
#if (defined(__STDC__) && defined(__STDC_VERSION__) && __STDC__ && __STDC_VERSION__ >= 199901L)
typedef long long int64_t;
typedef unsigned long long uint64_t;
/* (u)int64_t */
#if (defined(__STDC__) && defined(__STDC_VERSION__) && __STDC__ && __STDC_VERSION__ >= 199901L)
typedef long long int64_t;
typedef unsigned long long uint64_t;
#define UINT64_C(v) v ##ULL
#define INT64_C(v) v ##LL
#elif defined(__GNUC__)
__extension__ typedef long long int64_t;
__extension__ typedef unsigned long long uint64_t;
#define UINT64_C(v) v ##ULL
#define INT64_C(v) v ##LL
#elif defined(__GNUC__)
__extension__ typedef long long int64_t;
__extension__ typedef unsigned long long uint64_t;
#define UINT64_C(v) v ##ULL
#define INT64_C(v) v ##LL
#elif defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) || defined(__APPLE_CC__) || defined(_LONG_LONG) || defined(_CRAYC)
typedef long long int64_t;
typedef unsigned long long uint64_t;
#define UINT64_C(v) v ##ULL
#define INT64_C(v) v ##LL
#elif defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) || defined(__APPLE_CC__) || defined(_LONG_LONG) || defined(_CRAYC)
typedef long long int64_t;
typedef unsigned long long uint64_t;
#define UINT64_C(v) v ##ULL
#define INT64_C(v) v ##LL
#elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined(__BORLANDC__) && __BORLANDC__ > 0x460) || defined(__alpha) || defined(__DECC)
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#define UINT64_C(v) v ##ULL
#define INT64_C(v) v ##LL
#elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined(__BORLANDC__) && __BORLANDC__ > 0x460) || defined(__alpha) || defined(__DECC)
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#define UINT64_C(v) v ##UI64
#define INT64_C(v) v ##I64
#endif
#define UINT64_C(v) v ##UI64
#define INT64_C(v) v ##I64
#endif
#endif
static inline unsigned char shlu8(unsigned char a, uint32_t b) {

View file

@ -7,54 +7,54 @@ r = p + q
*/
void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->YplusX);
fe_mul(r->Y, r->Y, q->YminusX);
fe_mul(r->T, q->T2d, p->T);
fe_mul(r->X, p->Z, q->Z);
fe_add(t0, r->X, r->X);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_add(r->Z, t0, r->T);
fe_sub(r->T, t0, r->T);
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->YplusX);
fe_mul(r->Y, r->Y, q->YminusX);
fe_mul(r->T, q->T2d, p->T);
fe_mul(r->X, p->Z, q->Z);
fe_add(t0, r->X, r->X);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_add(r->Z, t0, r->T);
fe_sub(r->T, t0, r->T);
}
static void slide(signed char *r, const unsigned char *a) {
int i;
int b;
int k;
int i;
int b;
int k;
for (i = 0; i < 256; ++i) {
r[i] = 1 & (a[i >> 3] >> (i & 7));
}
for(i = 0; i < 256; ++i) {
r[i] = 1 & (a[i >> 3] >> (i & 7));
}
for (i = 0; i < 256; ++i)
if (r[i]) {
for (b = 1; b <= 6 && i + b < 256; ++b) {
if (r[i + b]) {
if (r[i] + (r[i + b] << b) <= 15) {
r[i] += r[i + b] << b;
r[i + b] = 0;
} else if (r[i] - (r[i + b] << b) >= -15) {
r[i] -= r[i + b] << b;
for(i = 0; i < 256; ++i)
if(r[i]) {
for(b = 1; b <= 6 && i + b < 256; ++b) {
if(r[i + b]) {
if(r[i] + (r[i + b] << b) <= 15) {
r[i] += r[i + b] << b;
r[i + b] = 0;
} else if(r[i] - (r[i + b] << b) >= -15) {
r[i] -= r[i + b] << b;
for (k = i + b; k < 256; ++k) {
if (!r[k]) {
r[k] = 1;
break;
}
for(k = i + b; k < 256; ++k) {
if(!r[k]) {
r[k] = 1;
break;
}
r[k] = 0;
}
} else {
break;
}
}
}
}
r[k] = 0;
}
} else {
break;
}
}
}
}
}
/*
@ -65,119 +65,119 @@ B is the Ed25519 base point (x,4/5) with x positive.
*/
void ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b) {
signed char aslide[256];
signed char bslide[256];
ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
ge_p1p1 t;
ge_p3 u;
ge_p3 A2;
int i;
slide(aslide, a);
slide(bslide, b);
ge_p3_to_cached(&Ai[0], A);
ge_p3_dbl(&t, A);
ge_p1p1_to_p3(&A2, &t);
ge_add(&t, &A2, &Ai[0]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[1], &u);
ge_add(&t, &A2, &Ai[1]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[2], &u);
ge_add(&t, &A2, &Ai[2]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[3], &u);
ge_add(&t, &A2, &Ai[3]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[4], &u);
ge_add(&t, &A2, &Ai[4]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[5], &u);
ge_add(&t, &A2, &Ai[5]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[6], &u);
ge_add(&t, &A2, &Ai[6]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[7], &u);
ge_p2_0(r);
signed char aslide[256];
signed char bslide[256];
ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
ge_p1p1 t;
ge_p3 u;
ge_p3 A2;
int i;
slide(aslide, a);
slide(bslide, b);
ge_p3_to_cached(&Ai[0], A);
ge_p3_dbl(&t, A);
ge_p1p1_to_p3(&A2, &t);
ge_add(&t, &A2, &Ai[0]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[1], &u);
ge_add(&t, &A2, &Ai[1]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[2], &u);
ge_add(&t, &A2, &Ai[2]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[3], &u);
ge_add(&t, &A2, &Ai[3]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[4], &u);
ge_add(&t, &A2, &Ai[4]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[5], &u);
ge_add(&t, &A2, &Ai[5]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[6], &u);
ge_add(&t, &A2, &Ai[6]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[7], &u);
ge_p2_0(r);
for (i = 255; i >= 0; --i) {
if (aslide[i] || bslide[i]) {
break;
}
}
for(i = 255; i >= 0; --i) {
if(aslide[i] || bslide[i]) {
break;
}
}
for (; i >= 0; --i) {
ge_p2_dbl(&t, r);
for(; i >= 0; --i) {
ge_p2_dbl(&t, r);
if (aslide[i] > 0) {
ge_p1p1_to_p3(&u, &t);
ge_add(&t, &u, &Ai[aslide[i] / 2]);
} else if (aslide[i] < 0) {
ge_p1p1_to_p3(&u, &t);
ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
}
if(aslide[i] > 0) {
ge_p1p1_to_p3(&u, &t);
ge_add(&t, &u, &Ai[aslide[i] / 2]);
} else if(aslide[i] < 0) {
ge_p1p1_to_p3(&u, &t);
ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
}
if (bslide[i] > 0) {
ge_p1p1_to_p3(&u, &t);
ge_madd(&t, &u, &Bi[bslide[i] / 2]);
} else if (bslide[i] < 0) {
ge_p1p1_to_p3(&u, &t);
ge_msub(&t, &u, &Bi[(-bslide[i]) / 2]);
}
if(bslide[i] > 0) {
ge_p1p1_to_p3(&u, &t);
ge_madd(&t, &u, &Bi[bslide[i] / 2]);
} else if(bslide[i] < 0) {
ge_p1p1_to_p3(&u, &t);
ge_msub(&t, &u, &Bi[(-bslide[i]) / 2]);
}
ge_p1p1_to_p2(r, &t);
}
ge_p1p1_to_p2(r, &t);
}
}
static const fe d = {
-10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116
};
-10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116
};
static const fe sqrtm1 = {
-32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482
};
-32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482
};
int ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s) {
fe u;
fe v;
fe v3;
fe vxx;
fe check;
fe_frombytes(h->Y, s);
fe_1(h->Z);
fe_sq(u, h->Y);
fe_mul(v, u, d);
fe_sub(u, u, h->Z); /* u = y^2-1 */
fe_add(v, v, h->Z); /* v = dy^2+1 */
fe_sq(v3, v);
fe_mul(v3, v3, v); /* v3 = v^3 */
fe_sq(h->X, v3);
fe_mul(h->X, h->X, v);
fe_mul(h->X, h->X, u); /* x = uv^7 */
fe_pow22523(h->X, h->X); /* x = (uv^7)^((q-5)/8) */
fe_mul(h->X, h->X, v3);
fe_mul(h->X, h->X, u); /* x = uv^3(uv^7)^((q-5)/8) */
fe_sq(vxx, h->X);
fe_mul(vxx, vxx, v);
fe_sub(check, vxx, u); /* vx^2-u */
fe u;
fe v;
fe v3;
fe vxx;
fe check;
fe_frombytes(h->Y, s);
fe_1(h->Z);
fe_sq(u, h->Y);
fe_mul(v, u, d);
fe_sub(u, u, h->Z); /* u = y^2-1 */
fe_add(v, v, h->Z); /* v = dy^2+1 */
fe_sq(v3, v);
fe_mul(v3, v3, v); /* v3 = v^3 */
fe_sq(h->X, v3);
fe_mul(h->X, h->X, v);
fe_mul(h->X, h->X, u); /* x = uv^7 */
fe_pow22523(h->X, h->X); /* x = (uv^7)^((q-5)/8) */
fe_mul(h->X, h->X, v3);
fe_mul(h->X, h->X, u); /* x = uv^3(uv^7)^((q-5)/8) */
fe_sq(vxx, h->X);
fe_mul(vxx, vxx, v);
fe_sub(check, vxx, u); /* vx^2-u */
if (fe_isnonzero(check)) {
fe_add(check, vxx, u); /* vx^2+u */
if(fe_isnonzero(check)) {
fe_add(check, vxx, u); /* vx^2+u */
if (fe_isnonzero(check)) {
return -1;
}
if(fe_isnonzero(check)) {
return -1;
}
fe_mul(h->X, h->X, sqrtm1);
}
fe_mul(h->X, h->X, sqrtm1);
}
if (fe_isnegative(h->X) == (s[31] >> 7)) {
fe_neg(h->X, h->X);
}
if(fe_isnegative(h->X) == (s[31] >> 7)) {
fe_neg(h->X, h->X);
}
fe_mul(h->T, h->X, h->Y);
return 0;
fe_mul(h->T, h->X, h->Y);
return 0;
}
@ -186,17 +186,17 @@ r = p + q
*/
void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->yplusx);
fe_mul(r->Y, r->Y, q->yminusx);
fe_mul(r->T, q->xy2d, p->T);
fe_add(t0, p->Z, p->Z);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_add(r->Z, t0, r->T);
fe_sub(r->T, t0, r->T);
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->yplusx);
fe_mul(r->Y, r->Y, q->yminusx);
fe_mul(r->T, q->xy2d, p->T);
fe_add(t0, p->Z, p->Z);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_add(r->Z, t0, r->T);
fe_sub(r->T, t0, r->T);
}
@ -205,18 +205,18 @@ r = p - q
*/
void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
fe t0;
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->yminusx);
fe_mul(r->Y, r->Y, q->yplusx);
fe_mul(r->T, q->xy2d, p->T);
fe_add(t0, p->Z, p->Z);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_sub(r->Z, t0, r->T);
fe_add(r->T, t0, r->T);
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->yminusx);
fe_mul(r->Y, r->Y, q->yplusx);
fe_mul(r->T, q->xy2d, p->T);
fe_add(t0, p->Z, p->Z);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_sub(r->Z, t0, r->T);
fe_add(r->T, t0, r->T);
}
@ -225,9 +225,9 @@ r = p
*/
void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) {
fe_mul(r->X, p->X, p->T);
fe_mul(r->Y, p->Y, p->Z);
fe_mul(r->Z, p->Z, p->T);
fe_mul(r->X, p->X, p->T);
fe_mul(r->Y, p->Y, p->Z);
fe_mul(r->Z, p->Z, p->T);
}
@ -237,17 +237,17 @@ r = p
*/
void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) {
fe_mul(r->X, p->X, p->T);
fe_mul(r->Y, p->Y, p->Z);
fe_mul(r->Z, p->Z, p->T);
fe_mul(r->T, p->X, p->Y);
fe_mul(r->X, p->X, p->T);
fe_mul(r->Y, p->Y, p->Z);
fe_mul(r->Z, p->Z, p->T);
fe_mul(r->T, p->X, p->Y);
}
void ge_p2_0(ge_p2 *h) {
fe_0(h->X);
fe_1(h->Y);
fe_1(h->Z);
fe_0(h->X);
fe_1(h->Y);
fe_1(h->Z);
}
@ -257,25 +257,25 @@ r = 2 * p
*/
void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p) {
fe t0;
fe t0;
fe_sq(r->X, p->X);
fe_sq(r->Z, p->Y);
fe_sq2(r->T, p->Z);
fe_add(r->Y, p->X, p->Y);
fe_sq(t0, r->Y);
fe_add(r->Y, r->Z, r->X);
fe_sub(r->Z, r->Z, r->X);
fe_sub(r->X, t0, r->Y);
fe_sub(r->T, r->T, r->Z);
fe_sq(r->X, p->X);
fe_sq(r->Z, p->Y);
fe_sq2(r->T, p->Z);
fe_add(r->Y, p->X, p->Y);
fe_sq(t0, r->Y);
fe_add(r->Y, r->Z, r->X);
fe_sub(r->Z, r->Z, r->X);
fe_sub(r->X, t0, r->Y);
fe_sub(r->T, r->T, r->Z);
}
void ge_p3_0(ge_p3 *h) {
fe_0(h->X);
fe_1(h->Y);
fe_1(h->Z);
fe_0(h->T);
fe_0(h->X);
fe_1(h->Y);
fe_1(h->Z);
fe_0(h->T);
}
@ -284,9 +284,9 @@ r = 2 * p
*/
void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p) {
ge_p2 q;
ge_p3_to_p2(&q, p);
ge_p2_dbl(r, &q);
ge_p2 q;
ge_p3_to_p2(&q, p);
ge_p2_dbl(r, &q);
}
@ -296,14 +296,14 @@ r = p
*/
static const fe d2 = {
-21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199
};
-21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199
};
void ge_p3_to_cached(ge_cached *r, const ge_p3 *p) {
fe_add(r->YplusX, p->Y, p->X);
fe_sub(r->YminusX, p->Y, p->X);
fe_copy(r->Z, p->Z);
fe_mul(r->T2d, p->T, d2);
fe_add(r->YplusX, p->Y, p->X);
fe_sub(r->YminusX, p->Y, p->X);
fe_copy(r->Z, p->Z);
fe_mul(r->T2d, p->T, d2);
}
@ -312,66 +312,66 @@ r = p
*/
void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p) {
fe_copy(r->X, p->X);
fe_copy(r->Y, p->Y);
fe_copy(r->Z, p->Z);
fe_copy(r->X, p->X);
fe_copy(r->Y, p->Y);
fe_copy(r->Z, p->Z);
}
void ge_p3_tobytes(unsigned char *s, const ge_p3 *h) {
fe recip;
fe x;
fe y;
fe_invert(recip, h->Z);
fe_mul(x, h->X, recip);
fe_mul(y, h->Y, recip);
fe_tobytes(s, y);
s[31] ^= fe_isnegative(x) << 7;
fe recip;
fe x;
fe y;
fe_invert(recip, h->Z);
fe_mul(x, h->X, recip);
fe_mul(y, h->Y, recip);
fe_tobytes(s, y);
s[31] ^= fe_isnegative(x) << 7;
}
static unsigned char equal(signed char b, signed char c) {
unsigned char ub = b;
unsigned char uc = c;
unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */
uint64_t y = x; /* 0: yes; 1..255: no */
y -= 1; /* large: yes; 0..254: no */
y >>= 63; /* 1: yes; 0: no */
return (unsigned char) y;
unsigned char ub = b;
unsigned char uc = c;
unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */
uint64_t y = x; /* 0: yes; 1..255: no */
y -= 1; /* large: yes; 0..254: no */
y >>= 63; /* 1: yes; 0: no */
return (unsigned char) y;
}
static unsigned char negative(signed char b) {
uint64_t x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */
x >>= 63; /* 1: yes; 0: no */
return (unsigned char) x;
uint64_t x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */
x >>= 63; /* 1: yes; 0: no */
return (unsigned char) x;
}
static void cmov(ge_precomp *t, ge_precomp *u, unsigned char b) {
fe_cmov(t->yplusx, u->yplusx, b);
fe_cmov(t->yminusx, u->yminusx, b);
fe_cmov(t->xy2d, u->xy2d, b);
fe_cmov(t->yplusx, u->yplusx, b);
fe_cmov(t->yminusx, u->yminusx, b);
fe_cmov(t->xy2d, u->xy2d, b);
}
static void select(ge_precomp *t, int pos, signed char b) {
ge_precomp minust;
unsigned char bnegative = negative(b);
unsigned char babs = b - shlu8(((-bnegative) & b), 1);
fe_1(t->yplusx);
fe_1(t->yminusx);
fe_0(t->xy2d);
cmov(t, &base[pos][0], equal(babs, 1));
cmov(t, &base[pos][1], equal(babs, 2));
cmov(t, &base[pos][2], equal(babs, 3));
cmov(t, &base[pos][3], equal(babs, 4));
cmov(t, &base[pos][4], equal(babs, 5));
cmov(t, &base[pos][5], equal(babs, 6));
cmov(t, &base[pos][6], equal(babs, 7));
cmov(t, &base[pos][7], equal(babs, 8));
fe_copy(minust.yplusx, t->yminusx);
fe_copy(minust.yminusx, t->yplusx);
fe_neg(minust.xy2d, t->xy2d);
cmov(t, &minust, bnegative);
ge_precomp minust;
unsigned char bnegative = negative(b);
unsigned char babs = b - shlu8(((-bnegative) & b), 1);
fe_1(t->yplusx);
fe_1(t->yminusx);
fe_0(t->xy2d);
cmov(t, &base[pos][0], equal(babs, 1));
cmov(t, &base[pos][1], equal(babs, 2));
cmov(t, &base[pos][2], equal(babs, 3));
cmov(t, &base[pos][3], equal(babs, 4));
cmov(t, &base[pos][4], equal(babs, 5));
cmov(t, &base[pos][5], equal(babs, 6));
cmov(t, &base[pos][6], equal(babs, 7));
cmov(t, &base[pos][7], equal(babs, 8));
fe_copy(minust.yplusx, t->yminusx);
fe_copy(minust.yminusx, t->yplusx);
fe_neg(minust.xy2d, t->xy2d);
cmov(t, &minust, bnegative);
}
/*
@ -384,53 +384,53 @@ Preconditions:
*/
void ge_scalarmult_base(ge_p3 *h, const unsigned char *a) {
signed char e[64];
signed char carry;
ge_p1p1 r;
ge_p2 s;
ge_precomp t;
int i;
signed char e[64];
signed char carry;
ge_p1p1 r;
ge_p2 s;
ge_precomp t;
int i;
for (i = 0; i < 32; ++i) {
e[2 * i + 0] = (a[i] >> 0) & 15;
e[2 * i + 1] = (a[i] >> 4) & 15;
}
for(i = 0; i < 32; ++i) {
e[2 * i + 0] = (a[i] >> 0) & 15;
e[2 * i + 1] = (a[i] >> 4) & 15;
}
/* each e[i] is between 0 and 15 */
/* e[63] is between 0 and 7 */
carry = 0;
/* each e[i] is between 0 and 15 */
/* e[63] is between 0 and 7 */
carry = 0;
for (i = 0; i < 63; ++i) {
e[i] += carry;
carry = e[i] + 8;
carry >>= 4;
e[i] -= shl32(carry, 4);
}
for(i = 0; i < 63; ++i) {
e[i] += carry;
carry = e[i] + 8;
carry >>= 4;
e[i] -= shl32(carry, 4);
}
e[63] += carry;
/* each e[i] is between -8 and 8 */
ge_p3_0(h);
e[63] += carry;
/* each e[i] is between -8 and 8 */
ge_p3_0(h);
for (i = 1; i < 64; i += 2) {
select(&t, i / 2, e[i]);
ge_madd(&r, h, &t);
ge_p1p1_to_p3(h, &r);
}
for(i = 1; i < 64; i += 2) {
select(&t, i / 2, e[i]);
ge_madd(&r, h, &t);
ge_p1p1_to_p3(h, &r);
}
ge_p3_dbl(&r, h);
ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
ge_p1p1_to_p3(h, &r);
ge_p3_dbl(&r, h);
ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
ge_p1p1_to_p3(h, &r);
for (i = 0; i < 64; i += 2) {
select(&t, i / 2, e[i]);
ge_madd(&r, h, &t);
ge_p1p1_to_p3(h, &r);
}
for(i = 0; i < 64; i += 2) {
select(&t, i / 2, e[i]);
ge_madd(&r, h, &t);
ge_p1p1_to_p3(h, &r);
}
}
@ -439,29 +439,29 @@ r = p - q
*/
void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->YminusX);
fe_mul(r->Y, r->Y, q->YplusX);
fe_mul(r->T, q->T2d, p->T);
fe_mul(r->X, p->Z, q->Z);
fe_add(t0, r->X, r->X);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_sub(r->Z, t0, r->T);
fe_add(r->T, t0, r->T);
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->YminusX);
fe_mul(r->Y, r->Y, q->YplusX);
fe_mul(r->T, q->T2d, p->T);
fe_mul(r->X, p->Z, q->Z);
fe_add(t0, r->X, r->X);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_sub(r->Z, t0, r->T);
fe_add(r->T, t0, r->T);
}
void ge_tobytes(unsigned char *s, const ge_p2 *h) {
fe recip;
fe x;
fe y;
fe_invert(recip, h->Z);
fe_mul(x, h->X, recip);
fe_mul(y, h->Y, recip);
fe_tobytes(s, y);
s[31] ^= fe_isnegative(x) << 7;
fe recip;
fe x;
fe y;
fe_invert(recip, h->Z);
fe_mul(x, h->X, recip);
fe_mul(y, h->Y, recip);
fe_tobytes(s, y);
s[31] ^= fe_isnegative(x) << 7;
}

View file

@ -19,36 +19,36 @@ Representations:
*/
typedef struct {
fe X;
fe Y;
fe Z;
fe X;
fe Y;
fe Z;
} ge_p2;
typedef struct {
fe X;
fe Y;
fe Z;
fe T;
fe X;
fe Y;
fe Z;
fe T;
} ge_p3;
typedef struct {
fe X;
fe Y;
fe Z;
fe T;
fe X;
fe Y;
fe Z;
fe T;
} ge_p1p1;
typedef struct {
fe yplusx;
fe yminusx;
fe xy2d;
fe yplusx;
fe yminusx;
fe xy2d;
} ge_precomp;
typedef struct {
fe YplusX;
fe YminusX;
fe Z;
fe T2d;
fe YplusX;
fe YminusX;
fe Z;
fe T2d;
} ge_cached;
void ge_p3_tobytes(unsigned char *s, const ge_p3 *h);

View file

@ -2,78 +2,79 @@
#include "fe.h"
void ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key) {
unsigned char e[32];
unsigned int i;
fe x1;
fe x2;
fe z2;
fe x3;
fe z3;
fe tmp0;
fe tmp1;
unsigned char e[32];
unsigned int i;
int pos;
unsigned int swap;
unsigned int b;
fe x1;
fe x2;
fe z2;
fe x3;
fe z3;
fe tmp0;
fe tmp1;
/* copy the private key and make sure it's valid */
for (i = 0; i < 32; ++i) {
e[i] = private_key[i];
}
int pos;
unsigned int swap;
unsigned int b;
e[0] &= 248;
e[31] &= 63;
e[31] |= 64;
/* copy the private key and make sure it's valid */
for(i = 0; i < 32; ++i) {
e[i] = private_key[i];
}
/* unpack the public key and convert edwards to montgomery */
/* due to CodesInChaos: montgomeryX = (edwardsY + 1)*inverse(1 - edwardsY) mod p */
fe_frombytes(x1, public_key);
fe_1(tmp1);
fe_add(tmp0, x1, tmp1);
fe_sub(tmp1, tmp1, x1);
fe_invert(tmp1, tmp1);
fe_mul(x1, tmp0, tmp1);
e[0] &= 248;
e[31] &= 63;
e[31] |= 64;
fe_1(x2);
fe_0(z2);
fe_copy(x3, x1);
fe_1(z3);
/* unpack the public key and convert edwards to montgomery */
/* due to CodesInChaos: montgomeryX = (edwardsY + 1)*inverse(1 - edwardsY) mod p */
fe_frombytes(x1, public_key);
fe_1(tmp1);
fe_add(tmp0, x1, tmp1);
fe_sub(tmp1, tmp1, x1);
fe_invert(tmp1, tmp1);
fe_mul(x1, tmp0, tmp1);
swap = 0;
for (pos = 254; pos >= 0; --pos) {
b = e[pos / 8] >> (pos & 7);
b &= 1;
swap ^= b;
fe_cswap(x2, x3, swap);
fe_cswap(z2, z3, swap);
swap = b;
fe_1(x2);
fe_0(z2);
fe_copy(x3, x1);
fe_1(z3);
/* from montgomery.h */
fe_sub(tmp0, x3, z3);
fe_sub(tmp1, x2, z2);
fe_add(x2, x2, z2);
fe_add(z2, x3, z3);
fe_mul(z3, tmp0, x2);
fe_mul(z2, z2, tmp1);
fe_sq(tmp0, tmp1);
fe_sq(tmp1, x2);
fe_add(x3, z3, z2);
fe_sub(z2, z3, z2);
fe_mul(x2, tmp1, tmp0);
fe_sub(tmp1, tmp1, tmp0);
fe_sq(z2, z2);
fe_mul121666(z3, tmp1);
fe_sq(x3, x3);
fe_add(tmp0, tmp0, z3);
fe_mul(z3, x1, z2);
fe_mul(z2, tmp1, tmp0);
}
swap = 0;
fe_cswap(x2, x3, swap);
fe_cswap(z2, z3, swap);
for(pos = 254; pos >= 0; --pos) {
b = e[pos / 8] >> (pos & 7);
b &= 1;
swap ^= b;
fe_cswap(x2, x3, swap);
fe_cswap(z2, z3, swap);
swap = b;
fe_invert(z2, z2);
fe_mul(x2, x2, z2);
fe_tobytes(shared_secret, x2);
/* from montgomery.h */
fe_sub(tmp0, x3, z3);
fe_sub(tmp1, x2, z2);
fe_add(x2, x2, z2);
fe_add(z2, x3, z3);
fe_mul(z3, tmp0, x2);
fe_mul(z2, z2, tmp1);
fe_sq(tmp0, tmp1);
fe_sq(tmp1, x2);
fe_add(x3, z3, z2);
fe_sub(z2, z3, z2);
fe_mul(x2, tmp1, tmp0);
fe_sub(tmp1, tmp1, tmp0);
fe_sq(z2, z2);
fe_mul121666(z3, tmp1);
fe_sq(x3, x3);
fe_add(tmp0, tmp0, z3);
fe_mul(z3, x1, z2);
fe_mul(z2, tmp1, tmp0);
}
fe_cswap(x2, x3, swap);
fe_cswap(z2, z3, swap);
fe_invert(z2, z2);
fe_mul(x2, x2, z2);
fe_tobytes(shared_secret, x2);
}

View file

@ -4,13 +4,13 @@
void ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed) {
ge_p3 A;
ge_p3 A;
sha512(seed, 32, private_key);
private_key[0] &= 248;
private_key[31] &= 63;
private_key[31] |= 64;
sha512(seed, 32, private_key);
private_key[0] &= 248;
private_key[31] &= 63;
private_key[31] |= 64;
ge_scalarmult_base(&A, private_key);
ge_p3_tobytes(public_key, &A);
ge_scalarmult_base(&A, private_key);
ge_p3_tobytes(public_key, &A);
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -14,65 +14,65 @@
/* the K array */
static const uint64_t K[80] = {
UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd),
UINT64_C(0xb5c0fbcfec4d3b2f), UINT64_C(0xe9b5dba58189dbbc),
UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019),
UINT64_C(0x923f82a4af194f9b), UINT64_C(0xab1c5ed5da6d8118),
UINT64_C(0xd807aa98a3030242), UINT64_C(0x12835b0145706fbe),
UINT64_C(0x243185be4ee4b28c), UINT64_C(0x550c7dc3d5ffb4e2),
UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1),
UINT64_C(0x9bdc06a725c71235), UINT64_C(0xc19bf174cf692694),
UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3),
UINT64_C(0x0fc19dc68b8cd5b5), UINT64_C(0x240ca1cc77ac9c65),
UINT64_C(0x2de92c6f592b0275), UINT64_C(0x4a7484aa6ea6e483),
UINT64_C(0x5cb0a9dcbd41fbd4), UINT64_C(0x76f988da831153b5),
UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210),
UINT64_C(0xb00327c898fb213f), UINT64_C(0xbf597fc7beef0ee4),
UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725),
UINT64_C(0x06ca6351e003826f), UINT64_C(0x142929670a0e6e70),
UINT64_C(0x27b70a8546d22ffc), UINT64_C(0x2e1b21385c26c926),
UINT64_C(0x4d2c6dfc5ac42aed), UINT64_C(0x53380d139d95b3df),
UINT64_C(0x650a73548baf63de), UINT64_C(0x766a0abb3c77b2a8),
UINT64_C(0x81c2c92e47edaee6), UINT64_C(0x92722c851482353b),
UINT64_C(0xa2bfe8a14cf10364), UINT64_C(0xa81a664bbc423001),
UINT64_C(0xc24b8b70d0f89791), UINT64_C(0xc76c51a30654be30),
UINT64_C(0xd192e819d6ef5218), UINT64_C(0xd69906245565a910),
UINT64_C(0xf40e35855771202a), UINT64_C(0x106aa07032bbd1b8),
UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53),
UINT64_C(0x2748774cdf8eeb99), UINT64_C(0x34b0bcb5e19b48a8),
UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb),
UINT64_C(0x5b9cca4f7763e373), UINT64_C(0x682e6ff3d6b2b8a3),
UINT64_C(0x748f82ee5defb2fc), UINT64_C(0x78a5636f43172f60),
UINT64_C(0x84c87814a1f0ab72), UINT64_C(0x8cc702081a6439ec),
UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9),
UINT64_C(0xbef9a3f7b2c67915), UINT64_C(0xc67178f2e372532b),
UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207),
UINT64_C(0xeada7dd6cde0eb1e), UINT64_C(0xf57d4f7fee6ed178),
UINT64_C(0x06f067aa72176fba), UINT64_C(0x0a637dc5a2c898a6),
UINT64_C(0x113f9804bef90dae), UINT64_C(0x1b710b35131c471b),
UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493),
UINT64_C(0x3c9ebe0a15c9bebc), UINT64_C(0x431d67c49c100d4c),
UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a),
UINT64_C(0x5fcb6fab3ad6faec), UINT64_C(0x6c44198c4a475817)
UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd),
UINT64_C(0xb5c0fbcfec4d3b2f), UINT64_C(0xe9b5dba58189dbbc),
UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019),
UINT64_C(0x923f82a4af194f9b), UINT64_C(0xab1c5ed5da6d8118),
UINT64_C(0xd807aa98a3030242), UINT64_C(0x12835b0145706fbe),
UINT64_C(0x243185be4ee4b28c), UINT64_C(0x550c7dc3d5ffb4e2),
UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1),
UINT64_C(0x9bdc06a725c71235), UINT64_C(0xc19bf174cf692694),
UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3),
UINT64_C(0x0fc19dc68b8cd5b5), UINT64_C(0x240ca1cc77ac9c65),
UINT64_C(0x2de92c6f592b0275), UINT64_C(0x4a7484aa6ea6e483),
UINT64_C(0x5cb0a9dcbd41fbd4), UINT64_C(0x76f988da831153b5),
UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210),
UINT64_C(0xb00327c898fb213f), UINT64_C(0xbf597fc7beef0ee4),
UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725),
UINT64_C(0x06ca6351e003826f), UINT64_C(0x142929670a0e6e70),
UINT64_C(0x27b70a8546d22ffc), UINT64_C(0x2e1b21385c26c926),
UINT64_C(0x4d2c6dfc5ac42aed), UINT64_C(0x53380d139d95b3df),
UINT64_C(0x650a73548baf63de), UINT64_C(0x766a0abb3c77b2a8),
UINT64_C(0x81c2c92e47edaee6), UINT64_C(0x92722c851482353b),
UINT64_C(0xa2bfe8a14cf10364), UINT64_C(0xa81a664bbc423001),
UINT64_C(0xc24b8b70d0f89791), UINT64_C(0xc76c51a30654be30),
UINT64_C(0xd192e819d6ef5218), UINT64_C(0xd69906245565a910),
UINT64_C(0xf40e35855771202a), UINT64_C(0x106aa07032bbd1b8),
UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53),
UINT64_C(0x2748774cdf8eeb99), UINT64_C(0x34b0bcb5e19b48a8),
UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb),
UINT64_C(0x5b9cca4f7763e373), UINT64_C(0x682e6ff3d6b2b8a3),
UINT64_C(0x748f82ee5defb2fc), UINT64_C(0x78a5636f43172f60),
UINT64_C(0x84c87814a1f0ab72), UINT64_C(0x8cc702081a6439ec),
UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9),
UINT64_C(0xbef9a3f7b2c67915), UINT64_C(0xc67178f2e372532b),
UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207),
UINT64_C(0xeada7dd6cde0eb1e), UINT64_C(0xf57d4f7fee6ed178),
UINT64_C(0x06f067aa72176fba), UINT64_C(0x0a637dc5a2c898a6),
UINT64_C(0x113f9804bef90dae), UINT64_C(0x1b710b35131c471b),
UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493),
UINT64_C(0x3c9ebe0a15c9bebc), UINT64_C(0x431d67c49c100d4c),
UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a),
UINT64_C(0x5fcb6fab3ad6faec), UINT64_C(0x6c44198c4a475817)
};
/* Various logical functions */
#define ROR64c(x, y) \
( ((((x)&UINT64_C(0xFFFFFFFFFFFFFFFF))>>((uint64_t)(y)&UINT64_C(63))) | \
((x)<<((uint64_t)(64-((y)&UINT64_C(63)))))) & UINT64_C(0xFFFFFFFFFFFFFFFF))
( ((((x)&UINT64_C(0xFFFFFFFFFFFFFFFF))>>((uint64_t)(y)&UINT64_C(63))) | \
((x)<<((uint64_t)(64-((y)&UINT64_C(63)))))) & UINT64_C(0xFFFFFFFFFFFFFFFF))
#define STORE64H(x, y) \
{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
#define LOAD64H(x, y) \
{ x = (((uint64_t)((y)[0] & 255))<<56)|(((uint64_t)((y)[1] & 255))<<48) | \
(((uint64_t)((y)[2] & 255))<<40)|(((uint64_t)((y)[3] & 255))<<32) | \
(((uint64_t)((y)[4] & 255))<<24)|(((uint64_t)((y)[5] & 255))<<16) | \
(((uint64_t)((y)[6] & 255))<<8)|(((uint64_t)((y)[7] & 255))); }
{ x = (((uint64_t)((y)[0] & 255))<<56)|(((uint64_t)((y)[1] & 255))<<48) | \
(((uint64_t)((y)[2] & 255))<<40)|(((uint64_t)((y)[3] & 255))<<32) | \
(((uint64_t)((y)[4] & 255))<<24)|(((uint64_t)((y)[5] & 255))<<16) | \
(((uint64_t)((y)[6] & 255))<<8)|(((uint64_t)((y)[7] & 255))); }
#define Ch(x,y,z) (z ^ (x & (y ^ z)))
@ -84,58 +84,57 @@ static const uint64_t K[80] = {
#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7))
#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6))
#ifndef MIN
#define MIN(x, y) ( ((x)<(y))?(x):(y) )
#define MIN(x, y) ( ((x)<(y))?(x):(y) )
#endif
/* compress 1024-bits */
static int sha512_compress(sha512_context *md, const unsigned char *buf)
{
uint64_t S[8], W[80], t0, t1;
int i;
static int sha512_compress(sha512_context *md, const unsigned char *buf) {
uint64_t S[8], W[80], t0, t1;
int i;
/* copy state into S */
for (i = 0; i < 8; i++) {
S[i] = md->state[i];
}
/* copy state into S */
for(i = 0; i < 8; i++) {
S[i] = md->state[i];
}
/* copy the state into 1024-bits into W[0..15] */
for (i = 0; i < 16; i++) {
LOAD64H(W[i], buf + (8*i));
}
/* copy the state into 1024-bits into W[0..15] */
for(i = 0; i < 16; i++) {
LOAD64H(W[i], buf + (8 * i));
}
/* fill W[16..79] */
for (i = 16; i < 80; i++) {
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
}
/* fill W[16..79] */
for(i = 16; i < 80; i++) {
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
}
/* Compress */
#define RND(a,b,c,d,e,f,g,h,i) \
t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
t1 = Sigma0(a) + Maj(a, b, c);\
d += t0; \
h = t0 + t1;
/* Compress */
#define RND(a,b,c,d,e,f,g,h,i) \
t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
t1 = Sigma0(a) + Maj(a, b, c);\
d += t0; \
h = t0 + t1;
for (i = 0; i < 80; i += 8) {
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
}
for(i = 0; i < 80; i += 8) {
RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i + 0);
RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], i + 1);
RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], i + 2);
RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], i + 3);
RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], i + 4);
RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], i + 5);
RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], i + 6);
RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], i + 7);
}
#undef RND
#undef RND
/* feedback */
for (i = 0; i < 8; i++) {
md->state[i] = md->state[i] + S[i];
}
/* feedback */
for(i = 0; i < 8; i++) {
md->state[i] = md->state[i] + S[i];
}
return 0;
return 0;
}
@ -144,21 +143,23 @@ static int sha512_compress(sha512_context *md, const unsigned char *buf)
@param md The hash state you wish to initialize
@return 0 if successful
*/
int sha512_init(sha512_context * md) {
if (md == NULL) return 1;
int sha512_init(sha512_context *md) {
if(md == NULL) {
return 1;
}
md->curlen = 0;
md->length = 0;
md->state[0] = UINT64_C(0x6a09e667f3bcc908);
md->state[1] = UINT64_C(0xbb67ae8584caa73b);
md->state[2] = UINT64_C(0x3c6ef372fe94f82b);
md->state[3] = UINT64_C(0xa54ff53a5f1d36f1);
md->state[4] = UINT64_C(0x510e527fade682d1);
md->state[5] = UINT64_C(0x9b05688c2b3e6c1f);
md->state[6] = UINT64_C(0x1f83d9abfb41bd6b);
md->state[7] = UINT64_C(0x5be0cd19137e2179);
md->curlen = 0;
md->length = 0;
md->state[0] = UINT64_C(0x6a09e667f3bcc908);
md->state[1] = UINT64_C(0xbb67ae8584caa73b);
md->state[2] = UINT64_C(0x3c6ef372fe94f82b);
md->state[3] = UINT64_C(0xa54ff53a5f1d36f1);
md->state[4] = UINT64_C(0x510e527fade682d1);
md->state[5] = UINT64_C(0x9b05688c2b3e6c1f);
md->state[6] = UINT64_C(0x1f83d9abfb41bd6b);
md->state[7] = UINT64_C(0x5be0cd19137e2179);
return 0;
return 0;
}
/**
@ -168,46 +169,57 @@ int sha512_init(sha512_context * md) {
@param inlen The length of the data (octets)
@return 0 if successful
*/
int sha512_update(sha512_context *md, const void *vin, size_t inlen)
{
const unsigned char *in = vin;
size_t n;
size_t i;
int err;
if (md == NULL) return 1;
if (in == NULL) return 1;
if (md->curlen > sizeof(md->buf)) {
return 1;
}
while (inlen > 0) {
if (md->curlen == 0 && inlen >= 128) {
if ((err = sha512_compress (md, in)) != 0) {
return err;
}
md->length += 128 * 8;
in += 128;
inlen -= 128;
} else {
n = MIN(inlen, (128 - md->curlen));
int sha512_update(sha512_context *md, const void *vin, size_t inlen) {
const unsigned char *in = vin;
size_t n;
size_t i;
int err;
for (i = 0; i < n; i++) {
md->buf[i + md->curlen] = in[i];
}
if(md == NULL) {
return 1;
}
if(in == NULL) {
return 1;
}
if(md->curlen > sizeof(md->buf)) {
return 1;
}
while(inlen > 0) {
if(md->curlen == 0 && inlen >= 128) {
if((err = sha512_compress(md, in)) != 0) {
return err;
}
md->length += 128 * 8;
in += 128;
inlen -= 128;
} else {
n = MIN(inlen, (128 - md->curlen));
for(i = 0; i < n; i++) {
md->buf[i + md->curlen] = in[i];
}
md->curlen += n;
in += n;
inlen -= n;
if (md->curlen == 128) {
if ((err = sha512_compress (md, md->buf)) != 0) {
return err;
}
md->length += 8*128;
md->curlen = 0;
}
}
}
return 0;
md->curlen += n;
in += n;
inlen -= n;
if(md->curlen == 128) {
if((err = sha512_compress(md, md->buf)) != 0) {
return err;
}
md->length += 8 * 128;
md->curlen = 0;
}
}
}
return 0;
}
/**
@ -216,62 +228,76 @@ int sha512_update(sha512_context *md, const void *vin, size_t inlen)
@param out [out] The destination of the hash (64 bytes)
@return 0 if successful
*/
int sha512_final(sha512_context * md, void *vout)
{
int i;
unsigned char *out = vout;
int sha512_final(sha512_context *md, void *vout) {
int i;
unsigned char *out = vout;
if (md == NULL) return 1;
if (out == NULL) return 1;
if(md == NULL) {
return 1;
}
if (md->curlen >= sizeof(md->buf)) {
return 1;
}
if(out == NULL) {
return 1;
}
/* increase the length of the message */
md->length += md->curlen * UINT64_C(8);
if(md->curlen >= sizeof(md->buf)) {
return 1;
}
/* append the '1' bit */
md->buf[md->curlen++] = (unsigned char)0x80;
/* increase the length of the message */
md->length += md->curlen * UINT64_C(8);
/* if the length is currently above 112 bytes we append zeros
* then compress. Then we can fall back to padding zeros and length
* encoding like normal.
*/
if (md->curlen > 112) {
while (md->curlen < 128) {
md->buf[md->curlen++] = (unsigned char)0;
}
sha512_compress(md, md->buf);
md->curlen = 0;
}
/* append the '1' bit */
md->buf[md->curlen++] = (unsigned char)0x80;
/* pad upto 120 bytes of zeroes
* note: that from 112 to 120 is the 64 MSB of the length. We assume that you won't hash
* > 2^64 bits of data... :-)
*/
while (md->curlen < 120) {
md->buf[md->curlen++] = (unsigned char)0;
}
/* if the length is currently above 112 bytes we append zeros
* then compress. Then we can fall back to padding zeros and length
* encoding like normal.
*/
if(md->curlen > 112) {
while(md->curlen < 128) {
md->buf[md->curlen++] = (unsigned char)0;
}
/* store length */
STORE64H(md->length, md->buf+120);
sha512_compress(md, md->buf);
sha512_compress(md, md->buf);
md->curlen = 0;
}
/* copy output */
for (i = 0; i < 8; i++) {
STORE64H(md->state[i], out+(8*i));
}
/* pad up to 120 bytes of zeroes
* note: that from 112 to 120 is the 64 MSB of the length. We assume that you won't hash
* > 2^64 bits of data... :-)
*/
while(md->curlen < 120) {
md->buf[md->curlen++] = (unsigned char)0;
}
return 0;
/* store length */
STORE64H(md->length, md->buf + 120);
sha512_compress(md, md->buf);
/* copy output */
for(i = 0; i < 8; i++) {
STORE64H(md->state[i], out + (8 * i));
}
return 0;
}
int sha512(const void *message, size_t message_len, void *out)
{
sha512_context ctx;
int ret;
if ((ret = sha512_init(&ctx))) return ret;
if ((ret = sha512_update(&ctx, message, message_len))) return ret;
if ((ret = sha512_final(&ctx, out))) return ret;
return 0;
int sha512(const void *message, size_t message_len, void *out) {
sha512_context ctx;
int ret;
if((ret = sha512_init(&ctx))) {
return ret;
}
if((ret = sha512_update(&ctx, message, message_len))) {
return ret;
}
if((ret = sha512_final(&ctx, out))) {
return ret;
}
return 0;
}

View file

@ -7,15 +7,15 @@
/* state */
typedef struct sha512_context_ {
uint64_t length, state[8];
size_t curlen;
unsigned char buf[128];
uint64_t length, state[8];
size_t curlen;
unsigned char buf[128];
} sha512_context;
int sha512_init(sha512_context * md);
int sha512_final(sha512_context * md, void *out);
int sha512_update(sha512_context * md, const void *in, size_t inlen);
int sha512_init(sha512_context *md);
int sha512_final(sha512_context *md, void *out);
int sha512_update(sha512_context *md, const void *in, size_t inlen);
int sha512(const void *message, size_t message_len, void *out);
#endif

View file

@ -5,27 +5,27 @@
void ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key) {
sha512_context hash;
unsigned char hram[64];
unsigned char r[64];
ge_p3 R;
sha512_context hash;
unsigned char hram[64];
unsigned char r[64];
ge_p3 R;
sha512_init(&hash);
sha512_update(&hash, private_key + 32, 32);
sha512_update(&hash, message, message_len);
sha512_final(&hash, r);
sha512_init(&hash);
sha512_update(&hash, private_key + 32, 32);
sha512_update(&hash, message, message_len);
sha512_final(&hash, r);
sc_reduce(r);
ge_scalarmult_base(&R, r);
ge_p3_tobytes(signature, &R);
sc_reduce(r);
ge_scalarmult_base(&R, r);
ge_p3_tobytes(signature, &R);
sha512_init(&hash);
sha512_update(&hash, signature, 32);
sha512_update(&hash, public_key, 32);
sha512_update(&hash, message, message_len);
sha512_final(&hash, hram);
sha512_init(&hash);
sha512_update(&hash, signature, 32);
sha512_update(&hash, public_key, 32);
sha512_update(&hash, message, message_len);
sha512_final(&hash, hram);
sc_reduce(hram);
sc_muladd(signature + 32, hram, private_key, r);
sc_reduce(hram);
sc_muladd(signature + 32, hram, private_key, r);
}

View file

@ -4,74 +4,74 @@
#include "sc.h"
static int consttime_equal(const unsigned char *x, const unsigned char *y) {
unsigned char r = 0;
unsigned char r = 0;
r = x[0] ^ y[0];
#define F(i) r |= x[i] ^ y[i]
F(1);
F(2);
F(3);
F(4);
F(5);
F(6);
F(7);
F(8);
F(9);
F(10);
F(11);
F(12);
F(13);
F(14);
F(15);
F(16);
F(17);
F(18);
F(19);
F(20);
F(21);
F(22);
F(23);
F(24);
F(25);
F(26);
F(27);
F(28);
F(29);
F(30);
F(31);
#undef F
r = x[0] ^ y[0];
#define F(i) r |= x[i] ^ y[i]
F(1);
F(2);
F(3);
F(4);
F(5);
F(6);
F(7);
F(8);
F(9);
F(10);
F(11);
F(12);
F(13);
F(14);
F(15);
F(16);
F(17);
F(18);
F(19);
F(20);
F(21);
F(22);
F(23);
F(24);
F(25);
F(26);
F(27);
F(28);
F(29);
F(30);
F(31);
#undef F
return !r;
return !r;
}
int ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key) {
unsigned char h[64];
unsigned char checker[32];
sha512_context hash;
ge_p3 A;
ge_p2 R;
unsigned char h[64];
unsigned char checker[32];
sha512_context hash;
ge_p3 A;
ge_p2 R;
if (signature[63] & 224) {
return 0;
}
if(signature[63] & 224) {
return 0;
}
if (ge_frombytes_negate_vartime(&A, public_key) != 0) {
return 0;
}
if(ge_frombytes_negate_vartime(&A, public_key) != 0) {
return 0;
}
sha512_init(&hash);
sha512_update(&hash, signature, 32);
sha512_update(&hash, public_key, 32);
sha512_update(&hash, message, message_len);
sha512_final(&hash, h);
sc_reduce(h);
ge_double_scalarmult_vartime(&R, h, &A, signature + 32);
ge_tobytes(checker, &R);
sha512_init(&hash);
sha512_update(&hash, signature, 32);
sha512_update(&hash, public_key, 32);
sha512_update(&hash, message, message_len);
sha512_final(&hash, h);
if (!consttime_equal(checker, signature)) {
return 0;
}
sc_reduce(h);
ge_double_scalarmult_vartime(&R, h, &A, signature + 32);
ge_tobytes(checker, &R);
return 1;
if(!consttime_equal(checker, signature)) {
return 0;
}
return 1;
}

View file

@ -40,13 +40,15 @@ static int edge_weight_compare(const edge_t *a, const edge_t *b) {
result = a->weight - b->weight;
if(result)
if(result) {
return result;
}
result = strcmp(a->from->name, b->from->name);
if(result)
if(result) {
return result;
}
return strcmp(a->to->name, b->to->name);
}
@ -86,13 +88,15 @@ void edge_add(edge_t *e) {
e->reverse = lookup_edge(e->to, e->from);
if(e->reverse)
if(e->reverse) {
e->reverse->reverse = e;
}
}
void edge_del(edge_t *e) {
if(e->reverse)
if(e->reverse) {
e->reverse->reverse = NULL;
}
splay_delete(edge_weight_tree, e);
splay_delete(e->from->edge_tree, e);
@ -111,11 +115,11 @@ bool dump_edges(connection_t *c) {
for splay_each(node_t, n, node_tree) {
for splay_each(edge_t, e, n->edge_tree) {
char *address = sockaddr2hostname(&e->address);
char* local_address = sockaddr2hostname(&e->local_address);
char *local_address = sockaddr2hostname(&e->local_address);
send_request(c, "%d %d %s %s %s %s %x %d",
CONTROL, REQ_DUMP_EDGES,
e->from->name, e->to->name, address,
local_address, e->options, e->weight);
CONTROL, REQ_DUMP_EDGES,
e->from->name, e->to->name, address,
local_address, e->options, e->weight);
free(address);
free(local_address);
}

View file

@ -1,3 +1,6 @@
#ifndef TINC_EDGE_H
#define TINC_EDGE_H
/*
edge.h -- header for edge.c
Copyright (C) 2001-2012 Guus Sliepen <guus@tinc-vpn.org>,
@ -18,9 +21,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_EDGE_H__
#define __TINC_EDGE_H__
#include "splay_tree.h"
#include "connection.h"
#include "net.h"
@ -43,13 +43,13 @@ extern splay_tree_t *edge_weight_tree; /* Tree with all known edges sor
extern void init_edges(void);
extern void exit_edges(void);
extern edge_t *new_edge(void) __attribute__ ((__malloc__));
extern void free_edge(edge_t *);
extern splay_tree_t *new_edge_tree(void) __attribute__ ((__malloc__));
extern void free_edge_tree(splay_tree_t *);
extern void edge_add(edge_t *);
extern void edge_del(edge_t *);
extern edge_t *lookup_edge(struct node_t *, struct node_t *);
extern bool dump_edges(struct connection_t *);
extern edge_t *new_edge(void) __attribute__((__malloc__));
extern void free_edge(edge_t *e);
extern splay_tree_t *new_edge_tree(void) __attribute__((__malloc__));
extern void free_edge_tree(splay_tree_t *edge_tree);
extern void edge_add(edge_t *e);
extern void edge_del(edge_t *e);
extern edge_t *lookup_edge(struct node_t *from, struct node_t *to);
extern bool dump_edges(struct connection_t *c);
#endif /* __TINC_EDGE_H__ */
#endif

View file

@ -1,3 +1,6 @@
#ifndef TINC_ETHERNET_H
#define TINC_ETHERNET_H
/*
ethernet.h -- missing Ethernet related definitions
Copyright (C) 2005 Ivo Timmermans
@ -18,9 +21,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_ETHERNET_H__
#define __TINC_ETHERNET_H__
#ifndef ETH_ALEN
#define ETH_ALEN 6
#endif
@ -63,7 +63,7 @@ struct ether_header {
uint8_t ether_dhost[ETH_ALEN];
uint8_t ether_shost[ETH_ALEN];
uint16_t ether_type;
} __attribute__ ((__gcc_struct__, __packed__));
} __attribute__((__gcc_struct__, __packed__));
#endif
#ifndef HAVE_STRUCT_ARPHDR
@ -73,7 +73,7 @@ struct arphdr {
uint8_t ar_hln;
uint8_t ar_pln;
uint16_t ar_op;
} __attribute__ ((__gcc_struct__, __packed__));
} __attribute__((__gcc_struct__, __packed__));
#define ARPOP_REQUEST 1
#define ARPOP_REPLY 2
@ -91,7 +91,7 @@ struct ether_arp {
uint8_t arp_spa[4];
uint8_t arp_tha[ETH_ALEN];
uint8_t arp_tpa[4];
} __attribute__ ((__gcc_struct__, __packed__));
} __attribute__((__gcc_struct__, __packed__));
#define arp_hrd ea_hdr.ar_hrd
#define arp_pro ea_hdr.ar_pro
#define arp_hln ea_hdr.ar_hln
@ -99,4 +99,4 @@ struct ether_arp {
#define arp_op ea_hdr.ar_op
#endif
#endif /* __TINC_ETHERNET_H__ */
#endif

View file

@ -41,25 +41,47 @@ static int io_compare(const io_t *a, const io_t *b) {
#ifndef HAVE_MINGW
return a->fd - b->fd;
#else
return a->event - b->event;
if(a->event < b->event) {
return -1;
}
if(a->event > b->event) {
return 1;
}
return 0;
#endif
}
static int timeout_compare(const timeout_t *a, const timeout_t *b) {
struct timeval diff;
timersub(&a->tv, &b->tv, &diff);
if(diff.tv_sec < 0)
if(diff.tv_sec < 0) {
return -1;
if(diff.tv_sec > 0)
}
if(diff.tv_sec > 0) {
return 1;
if(diff.tv_usec < 0)
}
if(diff.tv_usec < 0) {
return -1;
if(diff.tv_usec > 0)
}
if(diff.tv_usec > 0) {
return 1;
if(a < b)
}
if(a < b) {
return -1;
if(a > b)
}
if(a > b) {
return 1;
}
return 0;
}
@ -67,16 +89,21 @@ static splay_tree_t io_tree = {.compare = (splay_compare_t)io_compare};
static splay_tree_t timeout_tree = {.compare = (splay_compare_t)timeout_compare};
void io_add(io_t *io, io_cb_t cb, void *data, int fd, int flags) {
if(io->cb)
if(io->cb) {
return;
}
io->fd = fd;
#ifdef HAVE_MINGW
if (io->fd != -1) {
if(io->fd != -1) {
io->event = WSACreateEvent();
if (io->event == WSA_INVALID_EVENT)
if(io->event == WSA_INVALID_EVENT) {
abort();
}
}
event_count++;
#endif
io->cb = cb;
@ -85,8 +112,9 @@ void io_add(io_t *io, io_cb_t cb, void *data, int fd, int flags) {
io_set(io, flags);
if(!splay_insert_node(&io_tree, &io->node))
if(!splay_insert_node(&io_tree, &io->node)) {
abort();
}
}
#ifdef HAVE_MINGW
@ -97,41 +125,60 @@ void io_add_event(io_t *io, io_cb_t cb, void *data, WSAEVENT event) {
#endif
void io_set(io_t *io, int flags) {
if (flags == io->flags)
if(flags == io->flags) {
return;
}
io->flags = flags;
if (io->fd == -1)
if(io->fd == -1) {
return;
}
#ifndef HAVE_MINGW
if(flags & IO_READ)
FD_SET(io->fd, &readfds);
else
FD_CLR(io->fd, &readfds);
if(flags & IO_WRITE)
if(flags & IO_READ) {
FD_SET(io->fd, &readfds);
} else {
FD_CLR(io->fd, &readfds);
}
if(flags & IO_WRITE) {
FD_SET(io->fd, &writefds);
else
} else {
FD_CLR(io->fd, &writefds);
}
#else
long events = 0;
if (flags & IO_WRITE)
if(flags & IO_WRITE) {
events |= WRITE_EVENTS;
if (flags & IO_READ)
}
if(flags & IO_READ) {
events |= READ_EVENTS;
if (WSAEventSelect(io->fd, io->event, events) != 0)
}
if(WSAEventSelect(io->fd, io->event, events) != 0) {
abort();
}
#endif
}
void io_del(io_t *io) {
if(!io->cb)
if(!io->cb) {
return;
}
io_set(io, 0);
#ifdef HAVE_MINGW
if (io->fd != -1 && WSACloseEvent(io->event) == FALSE)
if(io->fd != -1 && WSACloseEvent(io->event) == FALSE) {
abort();
}
event_count--;
#endif
@ -148,25 +195,31 @@ void timeout_add(timeout_t *timeout, timeout_cb_t cb, void *data, struct timeval
}
void timeout_set(timeout_t *timeout, struct timeval *tv) {
if(timerisset(&timeout->tv))
if(timerisset(&timeout->tv)) {
splay_unlink_node(&timeout_tree, &timeout->node);
}
if(!now.tv_sec)
if(!now.tv_sec) {
gettimeofday(&now, NULL);
}
timeradd(&now, tv, &timeout->tv);
if(!splay_insert_node(&timeout_tree, &timeout->node))
if(!splay_insert_node(&timeout_tree, &timeout->node)) {
abort();
}
}
void timeout_del(timeout_t *timeout) {
if(!timeout->cb)
if(!timeout->cb) {
return;
}
splay_unlink_node(&timeout_tree, &timeout->node);
timeout->cb = 0;
timeout->tv = (struct timeval){0, 0};
timeout->tv = (struct timeval) {
0, 0
};
}
#ifndef HAVE_MINGW
@ -184,41 +237,54 @@ static void signal_handler(int signum) {
}
static void signalio_handler(void *data, int flags) {
(void)data;
(void)flags;
unsigned char signum;
if(read(pipefd[0], &signum, 1) != 1)
return;
signal_t *sig = splay_search(&signal_tree, &((signal_t){.signum = signum}));
if(sig)
if(read(pipefd[0], &signum, 1) != 1) {
return;
}
signal_t *sig = splay_search(&signal_tree, &((signal_t) {
.signum = signum
}));
if(sig) {
sig->cb(sig->data);
}
}
static void pipe_init(void) {
if(!pipe(pipefd))
if(!pipe(pipefd)) {
io_add(&signalio, signalio_handler, NULL, pipefd[0], IO_READ);
}
}
void signal_add(signal_t *sig, signal_cb_t cb, void *data, int signum) {
if(sig->cb)
if(sig->cb) {
return;
}
sig->cb = cb;
sig->data = data;
sig->signum = signum;
sig->node.data = sig;
if(pipefd[0] == -1)
if(pipefd[0] == -1) {
pipe_init();
}
signal(sig->signum, signal_handler);
if(!splay_insert_node(&signal_tree, &sig->node))
if(!splay_insert_node(&signal_tree, &sig->node)) {
abort();
}
}
void signal_del(signal_t *sig) {
if(!sig->cb)
if(!sig->cb) {
return;
}
signal(sig->signum, SIG_DFL);
@ -227,7 +293,7 @@ void signal_del(signal_t *sig) {
}
#endif
static struct timeval * get_time_remaining(struct timeval *diff) {
static struct timeval *get_time_remaining(struct timeval *diff) {
gettimeofday(&now, NULL);
struct timeval *tv = NULL;
@ -237,8 +303,10 @@ static struct timeval * get_time_remaining(struct timeval *diff) {
if(diff->tv_sec < 0) {
timeout->cb(timeout->data);
if(timercmp(&timeout->tv, &now, <))
if(timercmp(&timeout->tv, &now, <)) {
timeout_del(timeout);
}
} else {
tv = diff;
break;
@ -258,8 +326,8 @@ bool event_loop(void) {
while(running) {
struct timeval diff;
struct timeval *tv = get_time_remaining(&diff);
memcpy(&readable, &readfds, sizeof readable);
memcpy(&writable, &writefds, sizeof writable);
memcpy(&readable, &readfds, sizeof(readable));
memcpy(&writable, &writefds, sizeof(writable));
int fds = 0;
@ -271,39 +339,48 @@ bool event_loop(void) {
int n = select(fds, &readable, &writable, NULL, tv);
if(n < 0) {
if(sockwouldblock(sockerrno))
if(sockwouldblock(sockerrno)) {
continue;
else
} else {
return false;
}
}
if(!n)
if(!n) {
continue;
}
unsigned int curgen = io_tree.generation;
for splay_each(io_t, io, &io_tree) {
if(FD_ISSET(io->fd, &writable))
if(FD_ISSET(io->fd, &writable)) {
io->cb(io->data, IO_WRITE);
else if(FD_ISSET(io->fd, &readable))
} else if(FD_ISSET(io->fd, &readable)) {
io->cb(io->data, IO_READ);
else
} else {
continue;
}
/*
There are scenarios in which the callback will remove another io_t from the tree
(e.g. closing a double connection). Since splay_each does not support that, we
need to exit the loop now. That's okay, since any remaining events will get picked
up by the next select() call.
need to exit the loop if that happens. That's okay, since any remaining events will
get picked up by the next select() call.
*/
break;
if(curgen != io_tree.generation) {
break;
}
}
}
#else
while (running) {
while(running) {
struct timeval diff;
struct timeval *tv = get_time_remaining(&diff);
DWORD timeout_ms = tv ? (tv->tv_sec * 1000 + tv->tv_usec / 1000 + 1) : WSA_INFINITE;
if (!event_count) {
if(!event_count) {
Sleep(timeout_ms);
continue;
}
@ -318,54 +395,90 @@ bool event_loop(void) {
Note that technically FD_CLOSE has the same problem, but it's okay because user code does not rely on
this event being fired again if ignored.
*/
io_t* writeable_io = NULL;
for splay_each(io_t, io, &io_tree)
if (io->flags & IO_WRITE && send(io->fd, NULL, 0, 0) == 0) {
writeable_io = io;
break;
unsigned int curgen = io_tree.generation;
for splay_each(io_t, io, &io_tree) {
if(io->flags & IO_WRITE && send(io->fd, NULL, 0, 0) == 0) {
io->cb(io->data, IO_WRITE);
if(curgen != io_tree.generation) {
break;
}
}
if (writeable_io) {
writeable_io->cb(writeable_io->data, IO_WRITE);
continue;
}
WSAEVENT* events = xmalloc(event_count * sizeof(*events));
if(event_count > WSA_MAXIMUM_WAIT_EVENTS) {
WSASetLastError(WSA_INVALID_PARAMETER);
return(false);
}
WSAEVENT events[WSA_MAXIMUM_WAIT_EVENTS];
io_t *io_map[WSA_MAXIMUM_WAIT_EVENTS];
DWORD event_index = 0;
for splay_each(io_t, io, &io_tree) {
events[event_index] = io->event;
io_map[event_index] = io;
event_index++;
}
DWORD result = WSAWaitForMultipleEvents(event_count, events, FALSE, timeout_ms, FALSE);
/*
* If the generation number changes due to event addition
* or removal by a callback we restart the loop.
*/
curgen = io_tree.generation;
WSAEVENT event;
if (result >= WSA_WAIT_EVENT_0 && result < WSA_WAIT_EVENT_0 + event_count)
event = events[result - WSA_WAIT_EVENT_0];
free(events);
if (result == WSA_WAIT_TIMEOUT)
continue;
if (result < WSA_WAIT_EVENT_0 || result >= WSA_WAIT_EVENT_0 + event_count)
return false;
for(DWORD event_offset = 0; event_offset < event_count;) {
DWORD result = WSAWaitForMultipleEvents(event_count - event_offset, &events[event_offset], FALSE, timeout_ms, FALSE);
io_t *io = splay_search(&io_tree, &((io_t){.event = event}));
if (!io)
abort();
if(result == WSA_WAIT_TIMEOUT) {
break;
}
if (io->fd == -1) {
io->cb(io->data, 0);
} else {
WSANETWORKEVENTS network_events;
if (WSAEnumNetworkEvents(io->fd, io->event, &network_events) != 0)
return false;
if (network_events.lNetworkEvents & 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.
*/
if(result < WSA_WAIT_EVENT_0 || result >= WSA_WAIT_EVENT_0 + event_count - event_offset) {
return(false);
}
/* Look up io in the map by index. */
event_index = result - WSA_WAIT_EVENT_0 + event_offset;
io_t *io = io_map[event_index];
if(io->fd == -1) {
io->cb(io->data, 0);
if(curgen != io_tree.generation) {
break;
}
} else {
WSANETWORKEVENTS network_events;
if(WSAEnumNetworkEvents(io->fd, io->event, &network_events) != 0) {
return(false);
}
if(network_events.lNetworkEvents & READ_EVENTS) {
io->cb(io->data, IO_READ);
if(curgen != io_tree.generation) {
break;
}
}
/*
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.
*/
}
/* Continue checking the rest of the events. */
event_offset = event_index + 1;
/* Just poll the next time through. */
timeout_ms = 0;
}
}
#endif
return true;

View file

@ -1,3 +1,6 @@
#ifndef TINC_EVENT_H
#define TINC_EVENT_H
/*
event.h -- I/O, timeout and signal event handling
Copyright (C) 2012-2013 Guus Sliepen <guus@tinc-vpn.org>
@ -17,9 +20,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_EVENT_H__
#define __TINC_EVENT_H__
#include "splay_tree.h"
#define IO_READ 1
@ -58,7 +58,7 @@ extern struct timeval now;
extern void io_add(io_t *io, io_cb_t cb, void *data, int fd, int flags);
#ifdef HAVE_MINGW
extern void io_add_event(io_t *io, io_cb_t cb, void* data, WSAEVENT event);
extern void io_add_event(io_t *io, io_cb_t cb, void *data, WSAEVENT event);
#endif
extern void io_del(io_t *io);
extern void io_set(io_t *io, int flags);

View file

@ -64,7 +64,7 @@ static void close_device(void) {
}
static inline uint16_t get_ip_ethertype(vpn_packet_t *packet) {
switch (DATA(packet)[ETH_HLEN] >> 4) {
switch(DATA(packet)[ETH_HLEN] >> 4) {
case 4:
return ETH_P_IP;
@ -85,12 +85,14 @@ static inline void set_etherheader(vpn_packet_t *packet, uint16_t ethertype) {
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;

View file

@ -32,31 +32,43 @@
#include "utils.h"
static bool ask_fix(void) {
if(force)
if(force) {
return true;
if(!tty)
}
if(!tty) {
return false;
}
again:
fprintf(stderr, "Fix y/n? ");
char buf[1024];
if(!fgets(buf, sizeof buf, stdin)) {
if(!fgets(buf, sizeof(buf), stdin)) {
tty = false;
return false;
}
if(buf[0] == 'y' || buf[0] == 'Y')
if(buf[0] == 'y' || buf[0] == 'Y') {
return true;
if(buf[0] == 'n' || buf[0] == 'N')
}
if(buf[0] == 'n' || buf[0] == 'N') {
return false;
}
goto again;
}
static void print_tinc_cmd(const char *argv0, const char *format, ...) {
if(confbasegiven)
if(confbasegiven) {
fprintf(stderr, "%s -c %s ", argv0, confbase);
else if(netname)
} else if(netname) {
fprintf(stderr, "%s -n %s ", argv0, netname);
else
} else {
fprintf(stderr, "%s ", argv0);
}
va_list va;
va_start(va, format);
vfprintf(stderr, format, va);
@ -67,13 +79,19 @@ static void print_tinc_cmd(const char *argv0, const char *format, ...) {
static int strtailcmp(const char *str, const char *tail) {
size_t slen = strlen(str);
size_t tlen = strlen(tail);
if(tlen > slen)
if(tlen > slen) {
return -1;
}
return memcmp(str + slen - tlen, tail, tlen);
}
static void check_conffile(const char *fname, bool server) {
(void)server;
FILE *f = fopen(fname, "r");
if(!f) {
fprintf(stderr, "ERROR: cannot read %s: %s\n", fname, strerror(errno));
return;
@ -84,12 +102,14 @@ static void check_conffile(const char *fname, bool server) {
bool skip = false;
const int maxvariables = 50;
int count[maxvariables];
memset(count, 0, sizeof count);
memset(count, 0, sizeof(count));
while(fgets(line, sizeof line, f)) {
while(fgets(line, sizeof(line), f)) {
if(skip) {
if(!strncmp(line, "-----END", 8))
if(!strncmp(line, "-----END", 8)) {
skip = false;
}
continue;
} else {
if(!strncmp(line, "-----BEGIN", 10)) {
@ -105,26 +125,32 @@ static void check_conffile(const char *fname, bool server) {
lineno++;
eol = line + strlen(line);
while(strchr("\t \r\n", *--eol))
*eol = '\0';
if(!line[0] || line[0] == '#')
while(strchr("\t \r\n", *--eol)) {
*eol = '\0';
}
if(!line[0] || line[0] == '#') {
continue;
}
len = strcspn(value, "\t =");
value += len;
value += strspn(value, "\t ");
if(*value == '=') {
value++;
value += strspn(value, "\t ");
}
variable[len] = '\0';
bool found = false;
for(int i = 0; variables[i].name; i++) {
if(strcasecmp(variables[i].name, variable))
if(strcasecmp(variables[i].name, variable)) {
continue;
}
found = true;
@ -132,24 +158,29 @@ static void check_conffile(const char *fname, bool server) {
fprintf(stderr, "WARNING: obsolete variable %s in %s line %d\n", variable, fname, lineno);
}
if(i < maxvariables)
if(i < maxvariables) {
count[i]++;
}
}
if(!found)
if(!found) {
fprintf(stderr, "WARNING: unknown variable %s in %s line %d\n", variable, fname, lineno);
}
if(!*value)
if(!*value) {
fprintf(stderr, "ERROR: no value for variable %s in %s line %d\n", variable, fname, lineno);
}
}
for(int i = 0; variables[i].name && i < maxvariables; i++) {
if(count[i] > 1 && !(variables[i].type & VAR_MULTIPLE))
if(count[i] > 1 && !(variables[i].type & VAR_MULTIPLE)) {
fprintf(stderr, "WARNING: multiple instances of variable %s in %s\n", variables[i].name, fname);
}
}
if(ferror(f))
if(ferror(f)) {
fprintf(stderr, "ERROR: while reading %s: %s\n", fname, strerror(errno));
}
fclose(f);
}
@ -165,19 +196,23 @@ int fsck(const char *argv0) {
if(access(tinc_conf, R_OK)) {
fprintf(stderr, "ERROR: cannot read %s: %s\n", tinc_conf, strerror(errno));
if(errno == ENOENT) {
fprintf(stderr, "No tinc configuration found. Create a new one with:\n\n");
print_tinc_cmd(argv0, "init");
} else if(errno == EACCES) {
if(uid != 0)
if(uid != 0) {
fprintf(stderr, "You are currently not running tinc as root. Use sudo?\n");
else
} else {
fprintf(stderr, "Check the permissions of each component of the path %s.\n", tinc_conf);
}
}
return 1;
}
char *name = get_my_name(true);
if(!name) {
fprintf(stderr, "ERROR: tinc cannot run without a valid Name.\n");
return 1;
@ -192,7 +227,7 @@ int fsck(const char *argv0) {
#ifndef DISABLE_LEGACY
rsa_t *rsa_priv = NULL;
snprintf(fname, sizeof fname, "%s/rsa_key.priv", confbase);
snprintf(fname, sizeof(fname), "%s/rsa_key.priv", confbase);
if(stat(fname, &st)) {
if(errno != ENOENT) {
@ -203,12 +238,15 @@ int fsck(const char *argv0) {
}
} else {
FILE *f = fopen(fname, "r");
if(!f) {
fprintf(stderr, "ERROR: could not open %s: %s\n", fname, strerror(errno));
return 1;
}
rsa_priv = rsa_read_pem_private_key(f);
fclose(f);
if(!rsa_priv) {
fprintf(stderr, "ERROR: No key or unusable key found in %s.\n", fname);
fprintf(stderr, "You can generate a new RSA key with:\n\n");
@ -217,23 +255,28 @@ int fsck(const char *argv0) {
}
#if !defined(HAVE_MINGW) && !defined(HAVE_CYGWIN)
if(st.st_mode & 077) {
fprintf(stderr, "WARNING: unsafe file permissions on %s.\n", fname);
if(st.st_uid != uid) {
fprintf(stderr, "You are not running %s as the same uid as %s.\n", argv0, fname);
} else if(ask_fix()) {
if(chmod(fname, st.st_mode & ~077))
if(chmod(fname, st.st_mode & ~077)) {
fprintf(stderr, "ERROR: could not change permissions of %s: %s\n", fname, strerror(errno));
else
} else {
fprintf(stderr, "Fixed permissions of %s.\n", fname);
}
}
}
#endif
}
#endif
ecdsa_t *ecdsa_priv = NULL;
snprintf(fname, sizeof fname, "%s/ed25519_key.priv", confbase);
snprintf(fname, sizeof(fname), "%s/ed25519_key.priv", confbase);
if(stat(fname, &st)) {
if(errno != ENOENT) {
@ -244,12 +287,15 @@ int fsck(const char *argv0) {
}
} else {
FILE *f = fopen(fname, "r");
if(!f) {
fprintf(stderr, "ERROR: could not open %s: %s\n", fname, strerror(errno));
return 1;
}
ecdsa_priv = ecdsa_read_pem_private_key(f);
fclose(f);
if(!ecdsa_priv) {
fprintf(stderr, "ERROR: No key or unusable key found in %s.\n", fname);
fprintf(stderr, "You can generate a new Ed25519 key with:\n\n");
@ -258,24 +304,30 @@ int fsck(const char *argv0) {
}
#if !defined(HAVE_MINGW) && !defined(HAVE_CYGWIN)
if(st.st_mode & 077) {
fprintf(stderr, "WARNING: unsafe file permissions on %s.\n", fname);
if(st.st_uid != uid) {
fprintf(stderr, "You are not running %s as the same uid as %s.\n", argv0, fname);
} else if(ask_fix()) {
if(chmod(fname, st.st_mode & ~077))
if(chmod(fname, st.st_mode & ~077)) {
fprintf(stderr, "ERROR: could not change permissions of %s: %s\n", fname, strerror(errno));
else
} else {
fprintf(stderr, "Fixed permissions of %s.\n", fname);
}
}
}
#endif
}
#ifdef DISABLE_LEGACY
if(!ecdsa_priv) {
fprintf(stderr, "ERROR: No Ed25519 private key found.\n");
#else
if(!rsa_priv && !ecdsa_priv) {
fprintf(stderr, "ERROR: Neither RSA or Ed25519 private key found.\n");
#endif
@ -287,9 +339,11 @@ int fsck(const char *argv0) {
// Check for public keys.
// TODO: use RSAPublicKeyFile variable if present.
snprintf(fname, sizeof fname, "%s/hosts/%s", confbase, name);
if(access(fname, R_OK))
snprintf(fname, sizeof(fname), "%s/hosts/%s", confbase, name);
if(access(fname, R_OK)) {
fprintf(stderr, "WARNING: cannot read %s\n", fname);
}
FILE *f;
@ -297,6 +351,7 @@ int fsck(const char *argv0) {
rsa_t *rsa_pub = NULL;
f = fopen(fname, "r");
if(f) {
rsa_pub = rsa_read_pem_public_key(f);
fclose(f);
@ -305,13 +360,17 @@ int fsck(const char *argv0) {
if(rsa_priv) {
if(!rsa_pub) {
fprintf(stderr, "WARNING: No (usable) public RSA key found.\n");
if(ask_fix()) {
FILE *f = fopen(fname, "a");
if(f) {
if(rsa_write_pem_public_key(rsa_priv, f))
if(rsa_write_pem_public_key(rsa_priv, f)) {
fprintf(stderr, "Wrote RSA public key to %s.\n", fname);
else
} else {
fprintf(stderr, "ERROR: could not write RSA public key to %s.\n", fname);
}
fclose(f);
} else {
fprintf(stderr, "ERROR: could not append to %s: %s\n", fname, strerror(errno));
@ -320,56 +379,70 @@ int fsck(const char *argv0) {
} else {
// TODO: suggest remedies
size_t len = rsa_size(rsa_priv);
if(len != rsa_size(rsa_pub)) {
fprintf(stderr, "ERROR: public and private RSA keys do not match.\n");
return 1;
}
char buf1[len], buf2[len], buf3[len];
randomize(buf1, sizeof buf1);
randomize(buf1, sizeof(buf1));
buf1[0] &= 0x7f;
memset(buf2, 0, sizeof buf2);
memset(buf3, 0, sizeof buf2);
if(!rsa_public_encrypt(rsa_pub, buf1, sizeof buf1, buf2)) {
memset(buf2, 0, sizeof(buf2));
memset(buf3, 0, sizeof(buf2));
if(!rsa_public_encrypt(rsa_pub, buf1, sizeof(buf1), buf2)) {
fprintf(stderr, "ERROR: public RSA key does not work.\n");
return 1;
}
if(!rsa_private_decrypt(rsa_priv, buf2, sizeof buf2, buf3)) {
if(!rsa_private_decrypt(rsa_priv, buf2, sizeof(buf2), buf3)) {
fprintf(stderr, "ERROR: private RSA key does not work.\n");
return 1;
}
if(memcmp(buf1, buf3, sizeof buf1)) {
if(memcmp(buf1, buf3, sizeof(buf1))) {
fprintf(stderr, "ERROR: public and private RSA keys do not match.\n");
return 1;
}
}
} else {
if(rsa_pub)
if(rsa_pub) {
fprintf(stderr, "WARNING: A public RSA key was found but no private key is known.\n");
}
}
#endif
ecdsa_t *ecdsa_pub = NULL;
f = fopen(fname, "r");
if(f) {
ecdsa_pub = get_pubkey(f);
if(!ecdsa_pub) {
rewind(f);
ecdsa_pub = ecdsa_read_pem_public_key(f);
}
fclose(f);
}
if(ecdsa_priv) {
if(!ecdsa_pub) {
fprintf(stderr, "WARNING: No (usable) public Ed25519 key found.\n");
if(ask_fix()) {
FILE *f = fopen(fname, "a");
if(f) {
if(ecdsa_write_pem_public_key(ecdsa_priv, f))
if(ecdsa_write_pem_public_key(ecdsa_priv, f)) {
fprintf(stderr, "Wrote Ed25519 public key to %s.\n", fname);
else
} else {
fprintf(stderr, "ERROR: could not write Ed25519 public key to %s.\n", fname);
}
fclose(f);
} else {
fprintf(stderr, "ERROR: could not append to %s: %s\n", fname, strerror(errno));
@ -378,119 +451,150 @@ int fsck(const char *argv0) {
} else {
// TODO: suggest remedies
char *key1 = ecdsa_get_base64_public_key(ecdsa_pub);
if(!key1) {
fprintf(stderr, "ERROR: public Ed25519 key does not work.\n");
return 1;
}
char *key2 = ecdsa_get_base64_public_key(ecdsa_priv);
if(!key2) {
free(key1);
fprintf(stderr, "ERROR: private Ed25519 key does not work.\n");
return 1;
}
int result = strcmp(key1, key2);
free(key1);
free(key2);
if(result) {
fprintf(stderr, "ERROR: public and private Ed25519 keys do not match.\n");
return 1;
}
}
} else {
if(ecdsa_pub)
if(ecdsa_pub) {
fprintf(stderr, "WARNING: A public Ed25519 key was found but no private key is known.\n");
}
}
// Check whether scripts are executable
struct dirent *ent;
DIR *dir = opendir(confbase);
if(!dir) {
fprintf(stderr, "ERROR: cannot read directory %s: %s\n", confbase, strerror(errno));
return 1;
}
while((ent = readdir(dir))) {
if(strtailcmp(ent->d_name, "-up") && strtailcmp(ent->d_name, "-down"))
if(strtailcmp(ent->d_name, "-up") && strtailcmp(ent->d_name, "-down")) {
continue;
}
strncpy(fname, ent->d_name, sizeof fname);
strncpy(fname, ent->d_name, sizeof(fname));
char *dash = strrchr(fname, '-');
if(!dash)
if(!dash) {
continue;
}
*dash = 0;
if(strcmp(fname, "tinc") && strcmp(fname, "host") && strcmp(fname, "subnet")) {
static bool explained = false;
fprintf(stderr, "WARNING: Unknown script %s" SLASH "%s found.\n", confbase, ent->d_name);
if(!explained) {
fprintf(stderr, "The only scripts in %s executed by tinc are:\n", confbase);
fprintf(stderr, "tinc-up, tinc-down, host-up, host-down, subnet-up and subnet-down.\n");
explained = true;
}
continue;
}
snprintf(fname, sizeof fname, "%s" SLASH "%s", confbase, ent->d_name);
snprintf(fname, sizeof(fname), "%s" SLASH "%s", confbase, ent->d_name);
if(access(fname, R_OK | X_OK)) {
if(errno != EACCES) {
fprintf(stderr, "ERROR: cannot access %s: %s\n", fname, strerror(errno));
continue;
}
fprintf(stderr, "WARNING: cannot read and execute %s: %s\n", fname, strerror(errno));
if(ask_fix()) {
if(chmod(fname, 0755))
if(chmod(fname, 0755)) {
fprintf(stderr, "ERROR: cannot change permissions on %s: %s\n", fname, strerror(errno));
}
}
}
}
closedir(dir);
snprintf(dname, sizeof dname, "%s" SLASH "hosts", confbase);
snprintf(dname, sizeof(dname), "%s" SLASH "hosts", confbase);
dir = opendir(dname);
if(!dir) {
fprintf(stderr, "ERROR: cannot read directory %s: %s\n", dname, strerror(errno));
return 1;
}
while((ent = readdir(dir))) {
if(strtailcmp(ent->d_name, "-up") && strtailcmp(ent->d_name, "-down"))
if(strtailcmp(ent->d_name, "-up") && strtailcmp(ent->d_name, "-down")) {
continue;
}
strncpy(fname, ent->d_name, sizeof fname);
strncpy(fname, ent->d_name, sizeof(fname));
char *dash = strrchr(fname, '-');
if(!dash)
if(!dash) {
continue;
}
*dash = 0;
snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, ent->d_name);
snprintf(fname, sizeof(fname), "%s" SLASH "hosts" SLASH "%s", confbase, ent->d_name);
if(access(fname, R_OK | X_OK)) {
if(errno != EACCES) {
fprintf(stderr, "ERROR: cannot access %s: %s\n", fname, strerror(errno));
continue;
}
fprintf(stderr, "WARNING: cannot read and execute %s: %s\n", fname, strerror(errno));
if(ask_fix()) {
if(chmod(fname, 0755))
if(chmod(fname, 0755)) {
fprintf(stderr, "ERROR: cannot change permissions on %s: %s\n", fname, strerror(errno));
}
}
}
}
closedir(dir);
// Check for obsolete / unsafe / unknown configuration variables.
check_conffile(tinc_conf, true);
dir = opendir(dname);
if(dir) {
while((ent = readdir(dir))) {
if(!check_id(ent->d_name))
if(!check_id(ent->d_name)) {
continue;
}
snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, ent->d_name);
snprintf(fname, sizeof(fname), "%s" SLASH "hosts" SLASH "%s", confbase, ent->d_name);
check_conffile(fname, false);
}
closedir(dir);
}

View file

@ -1,3 +1,6 @@
#ifndef TINC_FSCK_H
#define TINC_FSCK_H
/*
fsck.h -- header for fsck.c.
Copyright (C) 2012 Guus Sliepen <guus@tinc-vpn.org>
@ -17,10 +20,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_FSCK_H__
#define __TINC_FSCK_H__
extern int fsck(const char *argv0);
#endif

View file

@ -55,7 +55,7 @@ static struct {
static bool nametocipher(const char *name, int *algo, int *mode) {
size_t i;
for(i = 0; i < sizeof ciphertable / sizeof *ciphertable; i++) {
for(i = 0; i < sizeof(ciphertable) / sizeof(*ciphertable); i++) {
if(ciphertable[i].name && !strcasecmp(name, ciphertable[i].name)) {
*algo = ciphertable[i].algo;
*mode = ciphertable[i].mode;
@ -69,7 +69,7 @@ static bool nametocipher(const char *name, int *algo, int *mode) {
static bool nidtocipher(int nid, int *algo, int *mode) {
size_t i;
for(i = 0; i < sizeof ciphertable / sizeof *ciphertable; i++) {
for(i = 0; i < sizeof(ciphertable) / sizeof(*ciphertable); i++) {
if(nid == ciphertable[i].nid) {
*algo = ciphertable[i].algo;
*mode = ciphertable[i].mode;
@ -83,7 +83,7 @@ static bool nidtocipher(int nid, int *algo, int *mode) {
static bool ciphertonid(int algo, int mode, int *nid) {
size_t i;
for(i = 0; i < sizeof ciphertable / sizeof *ciphertable; i++) {
for(i = 0; i < sizeof(ciphertable) / sizeof(*ciphertable); i++) {
if(algo == ciphertable[i].algo && mode == ciphertable[i].mode) {
*nid = ciphertable[i].nid;
return true;
@ -102,7 +102,7 @@ static bool cipher_open(cipher_t *cipher, int algo, int mode) {
}
if((err = gcry_cipher_open(&cipher->handle, algo, mode, 0))) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "Unable to intialise cipher %d mode %d: %s", algo, mode, gcry_strerror(err));
logger(DEBUG_ALWAYS, LOG_DEBUG, "Unable to initialise cipher %d mode %d: %s", algo, mode, gcry_strerror(err));
return false;
}
@ -146,10 +146,8 @@ void cipher_close(cipher_t *cipher) {
cipher->handle = NULL;
}
if(cipher->key) {
free(cipher->key);
cipher->key = NULL;
}
free(cipher->key);
cipher->key = NULL;
}
size_t cipher_keylength(const cipher_t *cipher) {
@ -193,8 +191,9 @@ bool cipher_encrypt(cipher_t *cipher, const void *indata, size_t inlen, void *ou
uint8_t pad[cipher->blklen];
if(cipher->padding) {
if(!oneshot)
if(!oneshot) {
return false;
}
size_t reqlen = ((inlen + cipher->blklen) / cipher->blklen) * cipher->blklen;
@ -207,14 +206,16 @@ bool cipher_encrypt(cipher_t *cipher, const void *indata, size_t inlen, void *ou
inlen = reqlen - cipher->blklen;
for(int i = 0; i < cipher->blklen; i++)
if(i < cipher->blklen - padbyte)
if(i < cipher->blklen - padbyte) {
pad[i] = ((uint8_t *)indata)[inlen + i];
else
} else {
pad[i] = padbyte;
}
}
if(oneshot)
if(oneshot) {
gcry_cipher_setiv(cipher->handle, cipher->key + cipher->keylen, cipher->blklen);
}
if((err = gcry_cipher_encrypt(cipher->handle, outdata, *outlen, indata, inlen))) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while encrypting: %s", gcry_strerror(err));
@ -237,8 +238,9 @@ bool cipher_encrypt(cipher_t *cipher, const void *indata, size_t inlen, void *ou
bool cipher_decrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) {
gcry_error_t err;
if(oneshot)
if(oneshot) {
gcry_cipher_setiv(cipher->handle, cipher->key + cipher->keylen, cipher->blklen);
}
if((err = gcry_cipher_decrypt(cipher->handle, outdata, *outlen, indata, inlen))) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while decrypting: %s", gcry_strerror(err));
@ -246,8 +248,9 @@ bool cipher_decrypt(cipher_t *cipher, const void *indata, size_t inlen, void *ou
}
if(cipher->padding) {
if(!oneshot)
if(!oneshot) {
return false;
}
uint8_t padbyte = ((uint8_t *)outdata)[inlen - 1];
@ -265,8 +268,9 @@ bool cipher_decrypt(cipher_t *cipher, const void *indata, size_t inlen, void *ou
}
*outlen = origlen;
} else
} else {
*outlen = inlen;
}
return true;
}

View file

@ -37,7 +37,7 @@ static struct {
static bool nametodigest(const char *name, int *algo) {
int i;
for(i = 0; i < sizeof digesttable / sizeof *digesttable; i++) {
for(i = 0; i < sizeof(digesttable) / sizeof(*digesttable); i++) {
if(digesttable[i].name && !strcasecmp(name, digesttable[i].name)) {
*algo = digesttable[i].algo;
return true;
@ -50,7 +50,7 @@ static bool nametodigest(const char *name, int *algo) {
static bool nidtodigest(int nid, int *algo) {
int i;
for(i = 0; i < sizeof digesttable / sizeof *digesttable; i++) {
for(i = 0; i < sizeof(digesttable) / sizeof(*digesttable); i++) {
if(nid == digesttable[i].nid) {
*algo = digesttable[i].algo;
return true;
@ -63,7 +63,7 @@ static bool nidtodigest(int nid, int *algo) {
static bool digesttonid(int algo, int *nid) {
int i;
for(i = 0; i < sizeof digesttable / sizeof *digesttable; i++) {
for(i = 0; i < sizeof(digesttable) / sizeof(*digesttable); i++) {
if(algo == digesttable[i].algo) {
*nid = digesttable[i].nid;
return true;
@ -81,10 +81,11 @@ static bool digest_open(digest_t *digest, int algo, int maclength) {
unsigned int len = gcry_md_get_algo_dlen(algo);
if(maclength > len || maclength < 0)
if(maclength > len || maclength < 0) {
digest->maclength = len;
else
} else {
digest->maclength = maclength;
}
digest->algo = algo;
digest->hmac = NULL;
@ -119,16 +120,21 @@ bool digest_open_sha1(digest_t *digest, int maclength) {
}
void digest_close(digest_t *digest) {
if(digest->hmac)
if(digest->hmac) {
gcry_md_close(digest->hmac);
}
digest->hmac = NULL;
}
bool digest_set_key(digest_t *digest, const void *key, size_t len) {
if(!digest->hmac)
if(!digest->hmac) {
gcry_md_open(&digest->hmac, digest->algo, GCRY_MD_FLAG_HMAC);
if(!digest->hmac)
}
if(!digest->hmac) {
return false;
}
return !gcry_md_setkey(digest->hmac, key, len);
}
@ -141,8 +147,11 @@ bool digest_create(digest_t *digest, const void *indata, size_t inlen, void *out
gcry_md_reset(digest->hmac);
gcry_md_write(digest->hmac, indata, inlen);
tmpdata = gcry_md_read(digest->hmac, digest->algo);
if(!tmpdata)
if(!tmpdata) {
return false;
}
memcpy(outdata, tmpdata, digest->maclength);
} else {
char tmpdata[len];

View file

@ -1,3 +1,6 @@
#ifndef TINC_GCRYPT_DIGEST_H
#define TINC_GCRYPT_DIGEST_H
/*
digest.h -- header file digest.c
Copyright (C) 2007-2009 Guus Sliepen <guus@tinc-vpn.org>
@ -17,9 +20,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_DIGEST_H__
#define __TINC_DIGEST_H__
#include <gcrypt.h>
#define DIGEST_MAX_SIZE 64

View file

@ -23,8 +23,9 @@
#include "../ed25519/sha512.h"
static void memxor(char *buf, char c, size_t len) {
for(size_t i = 0; i < len; i++)
for(size_t i = 0; i < len; i++) {
buf[i] ^= c;
}
}
static const size_t mdlen = 64;
@ -38,30 +39,39 @@ static bool hmac_sha512(const char *key, size_t keylen, const char *msg, size_t
memcpy(tmp, key, keylen);
memset(tmp + keylen, 0, blklen - keylen);
} else {
if(sha512(key, keylen, tmp) != 0)
if(sha512(key, keylen, tmp) != 0) {
return false;
}
memset(tmp + mdlen, 0, blklen - mdlen);
}
if(sha512_init(&md) != 0)
if(sha512_init(&md) != 0) {
return false;
}
// ipad
memxor(tmp, 0x36, blklen);
if(sha512_update(&md, tmp, blklen) != 0)
if(sha512_update(&md, tmp, blklen) != 0) {
return false;
}
// message
if(sha512_update(&md, msg, msglen) != 0)
if(sha512_update(&md, msg, msglen) != 0) {
return false;
}
if(sha512_final(&md, tmp + blklen) != 0)
if(sha512_final(&md, tmp + blklen) != 0) {
return false;
}
// opad
memxor(tmp, 0x36 ^ 0x5c, blklen);
if(sha512(tmp, sizeof tmp, out) != 0)
if(sha512(tmp, sizeof(tmp), out) != 0) {
return false;
}
return true;
}
@ -84,18 +94,23 @@ bool prf(const char *secret, size_t secretlen, char *seed, size_t seedlen, char
while(outlen > 0) {
/* Inner HMAC */
if(!hmac_sha512(secret, secretlen, data, sizeof data, data))
if(!hmac_sha512(secret, secretlen, data, sizeof(data), data)) {
return false;
}
/* Outer HMAC */
if(outlen >= mdlen) {
if(!hmac_sha512(secret, secretlen, data, sizeof data, out))
if(!hmac_sha512(secret, secretlen, data, sizeof(data), out)) {
return false;
}
out += mdlen;
outlen -= mdlen;
} else {
if(!hmac_sha512(secret, secretlen, data, sizeof data, hash))
if(!hmac_sha512(secret, secretlen, data, sizeof(data), hash)) {
return false;
}
memcpy(out, hash, outlen);
out += outlen;
outlen = 0;

View file

@ -27,28 +27,28 @@
// Base64 decoding table
static const uint8_t b64d[128] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
0x31, 0x32, 0x33, 0xff, 0xff, 0xff,
0xff, 0xff
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
0x31, 0x32, 0x33, 0xff, 0xff, 0xff,
0xff, 0xff
};
// PEM encoding/decoding functions
@ -61,12 +61,15 @@ static bool pem_decode(FILE *fp, const char *header, uint8_t *buf, size_t size,
size_t i, j = 0;
while(!feof(fp)) {
if(!fgets(line, sizeof line, fp))
if(!fgets(line, sizeof(line), fp)) {
return false;
}
if(!decode && !strncmp(line, "-----BEGIN ", 11)) {
if(!strncmp(line + 11, header, strlen(header)))
if(!strncmp(line + 11, header, strlen(header))) {
decode = true;
}
continue;
}
@ -74,14 +77,18 @@ static bool pem_decode(FILE *fp, const char *header, uint8_t *buf, size_t size,
break;
}
if(!decode)
if(!decode) {
continue;
}
for(i = 0; line[i] >= ' '; i++) {
if((signed char)line[i] < 0 || b64d[(int)line[i]] == 0xff)
if((signed char)line[i] < 0 || b64d[(int)line[i]] == 0xff) {
break;
}
word |= b64d[(int)line[i]] << shift;
shift -= 6;
if(shift <= 2) {
if(j > size) {
errno = ENOMEM;
@ -95,8 +102,10 @@ static bool pem_decode(FILE *fp, const char *header, uint8_t *buf, size_t size,
}
}
if(outsize)
if(outsize) {
*outsize = j;
}
return true;
}
@ -104,20 +113,25 @@ static bool pem_decode(FILE *fp, const char *header, uint8_t *buf, size_t size,
// BER decoding functions
static int ber_read_id(unsigned char **p, size_t *buflen) {
if(*buflen <= 0)
if(*buflen <= 0) {
return -1;
}
if((**p & 0x1f) == 0x1f) {
int id = 0;
bool more;
while(*buflen > 0) {
id <<= 7;
id |= **p & 0x7f;
more = *(*p)++ & 0x80;
(*buflen)--;
if(!more)
if(!more) {
break;
}
}
return id;
} else {
(*buflen)--;
@ -126,15 +140,18 @@ static int ber_read_id(unsigned char **p, size_t *buflen) {
}
static size_t ber_read_len(unsigned char **p, size_t *buflen) {
if(*buflen <= 0)
if(*buflen <= 0) {
return -1;
}
if(**p & 0x80) {
size_t result = 0;
int len = *(*p)++ & 0x7f;
(*buflen)--;
if(len > *buflen)
if(len > *buflen) {
return 0;
}
while(len--) {
result <<= 8;
@ -155,8 +172,10 @@ static bool ber_read_sequence(unsigned char **p, size_t *buflen, size_t *result)
size_t len = ber_read_len(p, buflen);
if(tag == 0x10) {
if(result)
if(result) {
*result = len;
}
return true;
} else {
return false;
@ -168,11 +187,13 @@ static bool ber_read_mpi(unsigned char **p, size_t *buflen, gcry_mpi_t *mpi) {
size_t len = ber_read_len(p, buflen);
gcry_error_t err = 0;
if(tag != 0x02 || len > *buflen)
if(tag != 0x02 || len > *buflen) {
return false;
}
if(mpi)
if(mpi) {
err = gcry_mpi_scan(mpi, GCRYMPI_FMT_USG, *p, len, NULL);
}
*p += len;
*buflen -= len;
@ -184,7 +205,7 @@ bool rsa_set_hex_public_key(rsa_t *rsa, char *n, char *e) {
gcry_error_t err = 0;
err = gcry_mpi_scan(&rsa->n, GCRYMPI_FMT_HEX, n, 0, NULL)
?: gcry_mpi_scan(&rsa->e, GCRYMPI_FMT_HEX, e, 0, NULL);
? : gcry_mpi_scan(&rsa->e, GCRYMPI_FMT_HEX, e, 0, NULL);
if(err) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading RSA public key: %s", gcry_strerror(errno));
@ -198,8 +219,8 @@ bool rsa_set_hex_private_key(rsa_t *rsa, char *n, char *e, char *d) {
gcry_error_t err = 0;
err = gcry_mpi_scan(&rsa->n, GCRYMPI_FMT_HEX, n, 0, NULL)
?: gcry_mpi_scan(&rsa->e, GCRYMPI_FMT_HEX, e, 0, NULL)
?: gcry_mpi_scan(&rsa->d, GCRYMPI_FMT_HEX, d, 0, NULL);
? : gcry_mpi_scan(&rsa->e, GCRYMPI_FMT_HEX, e, 0, NULL)
? : gcry_mpi_scan(&rsa->d, GCRYMPI_FMT_HEX, d, 0, NULL);
if(err) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading RSA public key: %s", gcry_strerror(errno));
@ -215,15 +236,15 @@ bool rsa_read_pem_public_key(rsa_t *rsa, FILE *fp) {
uint8_t derbuf[8096], *derp = derbuf;
size_t derlen;
if(!pem_decode(fp, "RSA PUBLIC KEY", derbuf, sizeof derbuf, &derlen)) {
if(!pem_decode(fp, "RSA PUBLIC KEY", derbuf, sizeof(derbuf), &derlen)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read RSA public key: %s", strerror(errno));
return NULL;
}
if(!ber_read_sequence(&derp, &derlen, NULL)
|| !ber_read_mpi(&derp, &derlen, &rsa->n)
|| !ber_read_mpi(&derp, &derlen, &rsa->e)
|| derlen) {
|| !ber_read_mpi(&derp, &derlen, &rsa->n)
|| !ber_read_mpi(&derp, &derlen, &rsa->e)
|| derlen) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while decoding RSA public key");
return NULL;
}
@ -235,22 +256,22 @@ bool rsa_read_pem_private_key(rsa_t *rsa, FILE *fp) {
uint8_t derbuf[8096], *derp = derbuf;
size_t derlen;
if(!pem_decode(fp, "RSA PRIVATE KEY", derbuf, sizeof derbuf, &derlen)) {
if(!pem_decode(fp, "RSA PRIVATE KEY", derbuf, sizeof(derbuf), &derlen)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read RSA private key: %s", strerror(errno));
return NULL;
}
if(!ber_read_sequence(&derp, &derlen, NULL)
|| !ber_read_mpi(&derp, &derlen, NULL)
|| !ber_read_mpi(&derp, &derlen, &rsa->n)
|| !ber_read_mpi(&derp, &derlen, &rsa->e)
|| !ber_read_mpi(&derp, &derlen, &rsa->d)
|| !ber_read_mpi(&derp, &derlen, NULL) // p
|| !ber_read_mpi(&derp, &derlen, NULL) // q
|| !ber_read_mpi(&derp, &derlen, NULL)
|| !ber_read_mpi(&derp, &derlen, NULL)
|| !ber_read_mpi(&derp, &derlen, NULL) // u
|| derlen) {
|| !ber_read_mpi(&derp, &derlen, NULL)
|| !ber_read_mpi(&derp, &derlen, &rsa->n)
|| !ber_read_mpi(&derp, &derlen, &rsa->e)
|| !ber_read_mpi(&derp, &derlen, &rsa->d)
|| !ber_read_mpi(&derp, &derlen, NULL) // p
|| !ber_read_mpi(&derp, &derlen, NULL) // q
|| !ber_read_mpi(&derp, &derlen, NULL)
|| !ber_read_mpi(&derp, &derlen, NULL)
|| !ber_read_mpi(&derp, &derlen, NULL) // u
|| derlen) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while decoding RSA private key");
return NULL;
}
@ -277,10 +298,12 @@ bool rsa_public_encrypt(rsa_t *rsa, void *in, size_t len, void *out) {
gcry_mpi_powm(outmpi, inmpi, rsa->e, rsa->n);
int pad = len - (gcry_mpi_get_nbits(outmpi) + 7) / 8;
while(pad--)
*(char *)out++ = 0;
check(gcry_mpi_print(GCRYMPI_FMT_USG, out,len, NULL, outmpi));
while(pad--) {
*(char *)out++ = 0;
}
check(gcry_mpi_print(GCRYMPI_FMT_USG, out, len, NULL, outmpi));
return true;
}
@ -293,10 +316,12 @@ bool rsa_private_decrypt(rsa_t *rsa, void *in, size_t len, void *out) {
gcry_mpi_powm(outmpi, inmpi, rsa->d, rsa->n);
int pad = len - (gcry_mpi_get_nbits(outmpi) + 7) / 8;
while(pad--)
*(char *)out++ = 0;
check(gcry_mpi_print(GCRYMPI_FMT_USG, out,len, NULL, outmpi));
while(pad--) {
*(char *)out++ = 0;
}
check(gcry_mpi_print(GCRYMPI_FMT_USG, out, len, NULL, outmpi));
return true;
}

View file

@ -44,14 +44,16 @@ static bool pem_encode(FILE *fp, const char *header, uint8_t *buf, size_t size)
word = buf[i] << 16 | buf[i + 1] << 8 | buf[i + 2];
} else {
word = buf[i] << 16;
if(i == size - 2)
if(i == size - 2) {
word |= buf[i + 1] << 8;
}
}
line[j++] = b64e[(word >> 18) ];
line[j++] = b64e[(word >> 12) & 0x3f];
line[j++] = b64e[(word >> 6) & 0x3f];
line[j++] = b64e[(word ) & 0x3f];
line[j++] = b64e[(word) & 0x3f];
if(j >= 64) {
line[j++] = '\n';
@ -62,8 +64,10 @@ static bool pem_encode(FILE *fp, const char *header, uint8_t *buf, size_t size)
}
if(size % 3 > 0) {
if(size % 3 > 1)
if(size % 3 > 1) {
line[j++] = '=';
}
line[j++] = '=';
}
@ -82,19 +86,24 @@ static bool pem_encode(FILE *fp, const char *header, uint8_t *buf, size_t size)
// BER encoding functions
static bool ber_write_id(uint8_t **p, size_t *buflen, int id) {
if(*buflen <= 0)
if(*buflen <= 0) {
return false;
}
if(id >= 0x1f) {
while(id) {
if(*buflen <= 0)
if(*buflen <= 0) {
return false;
}
(*buflen)--;
**p = id & 0x7f;
id >>= 7;
if(id)
if(id) {
**p |= 0x80;
}
(*p)++;
}
} else {
@ -107,14 +116,18 @@ static bool ber_write_id(uint8_t **p, size_t *buflen, int id) {
static bool ber_write_len(uint8_t **p, size_t *buflen, size_t len) {
do {
if(*buflen <= 0)
if(*buflen <= 0) {
return false;
}
(*buflen)--;
**p = len & 0x7f;
len >>= 7;
if(len)
if(len) {
**p |= 0x80;
}
(*p)++;
} while(len);
@ -122,8 +135,9 @@ static bool ber_write_len(uint8_t **p, size_t *buflen, size_t len) {
}
static bool ber_write_sequence(uint8_t **p, size_t *buflen, uint8_t *seqbuf, size_t seqlen) {
if(!ber_write_id(p, buflen, 0x10) || !ber_write_len(p, buflen, seqlen) || *buflen < seqlen)
if(!ber_write_id(p, buflen, 0x10) || !ber_write_len(p, buflen, seqlen) || *buflen < seqlen) {
return false;
}
memcpy(*p, seqbuf, seqlen);
*p += seqlen;
@ -134,15 +148,18 @@ static bool ber_write_sequence(uint8_t **p, size_t *buflen, uint8_t *seqbuf, siz
static bool ber_write_mpi(uint8_t **p, size_t *buflen, gcry_mpi_t mpi) {
uint8_t tmpbuf[1024];
size_t tmplen = sizeof tmpbuf;
size_t tmplen = sizeof(tmpbuf);
gcry_error_t err;
err = gcry_mpi_aprint(GCRYMPI_FMT_USG, &tmpbuf, &tmplen, mpi);
if(err)
return false;
if(!ber_write_id(p, buflen, 0x02) || !ber_write_len(p, buflen, tmplen) || *buflen < tmplen)
if(err) {
return false;
}
if(!ber_write_id(p, buflen, 0x02) || !ber_write_len(p, buflen, tmplen) || *buflen < tmplen) {
return false;
}
memcpy(*p, tmpbuf, tmplen);
*p += tmplen;
@ -158,12 +175,12 @@ bool rsa_write_pem_public_key(rsa_t *rsa, FILE *fp) {
uint8_t derbuf2[8096];
uint8_t *derp1 = derbuf1;
uint8_t *derp2 = derbuf2;
size_t derlen1 = sizeof derbuf1;
size_t derlen2 = sizeof derbuf2;
size_t derlen1 = sizeof(derbuf1);
size_t derlen2 = sizeof(derbuf2);
if(!ber_write_mpi(&derp1, &derlen1, &rsa->n)
|| !ber_write_mpi(&derp1, &derlen1, &rsa->e)
|| !ber_write_sequence(&derp2, &derlen2, derbuf1, derlen1)) {
|| !ber_write_mpi(&derp1, &derlen1, &rsa->e)
|| !ber_write_sequence(&derp2, &derlen2, derbuf1, derlen1)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while encoding RSA public key");
return false;
}
@ -181,28 +198,30 @@ bool rsa_write_pem_private_key(rsa_t *rsa, FILE *fp) {
uint8_t derbuf2[8096];
uint8_t *derp1 = derbuf1;
uint8_t *derp2 = derbuf2;
size_t derlen1 = sizeof derbuf1;
size_t derlen2 = sizeof derbuf2;
size_t derlen1 = sizeof(derbuf1);
size_t derlen2 = sizeof(derbuf2);
if(!ber_write_mpi(&derp1, &derlen1, &bits)
|| ber_write_mpi(&derp1, &derlen1, &rsa->n) // modulus
|| ber_write_mpi(&derp1, &derlen1, &rsa->e) // public exponent
|| ber_write_mpi(&derp1, &derlen1, &rsa->d) // private exponent
|| ber_write_mpi(&derp1, &derlen1, &p)
|| ber_write_mpi(&derp1, &derlen1, &q)
|| ber_write_mpi(&derp1, &derlen1, &exp1)
|| ber_write_mpi(&derp1, &derlen1, &exp2)
|| ber_write_mpi(&derp1, &derlen1, &coeff))
|| ber_write_mpi(&derp1, &derlen1, &rsa->n) // modulus
|| ber_write_mpi(&derp1, &derlen1, &rsa->e) // public exponent
|| ber_write_mpi(&derp1, &derlen1, &rsa->d) // private exponent
|| ber_write_mpi(&derp1, &derlen1, &p)
|| ber_write_mpi(&derp1, &derlen1, &q)
|| ber_write_mpi(&derp1, &derlen1, &exp1)
|| ber_write_mpi(&derp1, &derlen1, &exp2)
|| ber_write_mpi(&derp1, &derlen1, &coeff)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while encoding RSA private key");
return false;
}
if(!pem_encode(fp, "RSA PRIVATE KEY", derbuf2, derlen2)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to write RSA private key: %s", strerror(errno));
return false;
}
return false;
}
return true;
if(!pem_encode(fp, "RSA PRIVATE KEY", derbuf2, derlen2)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to write RSA private key: %s", strerror(errno));
return false;
}
return true;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,6 @@
#ifndef TINC_GETOPT_H
#define TINC_GETOPT_H
/* Declarations for getopt.
Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc.
@ -22,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#ifndef _GETOPT_H
#define _GETOPT_H 1
#ifdef __cplusplus
#ifdef __cplusplus
extern "C" {
#endif
@ -63,9 +66,9 @@ extern int optopt;
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
@ -78,56 +81,55 @@ extern int optopt;
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
struct option {
#if defined (__STDC__) && __STDC__
const char *name;
const char *name;
#else
char *name;
char *name;
#endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#if defined (__STDC__) && __STDC__
#ifdef __GNU_LIBRARY__
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int argc, char *const *argv, const char *shortopts);
extern int getopt(int argc, char *const *argv, const char *shortopts);
#else /* not __GNU_LIBRARY__ */
extern int getopt ();
extern int getopt();
#endif /* __GNU_LIBRARY__ */
extern int getopt_long (int argc, char *const *argv, const char *shortopts,
const struct option *longopts, int *longind);
extern int getopt_long_only (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind);
extern int getopt_long(int argc, char *const *argv, const char *shortopts,
const struct option *longopts, int *longind);
extern int getopt_long_only(int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind,
int long_only);
extern int _getopt_internal(int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind,
int long_only);
#else /* not __STDC__ */
extern int getopt ();
extern int getopt_long ();
extern int getopt_long_only ();
extern int getopt();
extern int getopt_long();
extern int getopt_long_only();
extern int _getopt_internal ();
extern int _getopt_internal();
#endif /* __STDC__ */
#ifdef __cplusplus
#ifdef __cplusplus
}
#endif
#endif /* _GETOPT_H */
#endif

View file

@ -60,19 +60,19 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <stdlib.h>
#endif
#ifndef NULL
#ifndef NULL
#define NULL 0
#endif
int
getopt_long (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
getopt_long(argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
return _getopt_internal(argc, argv, options, long_options, opt_index, 0);
}
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
@ -81,109 +81,115 @@ getopt_long (argc, argv, options, long_options, opt_index)
instead. */
int
getopt_long_only (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
getopt_long_only(argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
return _getopt_internal(argc, argv, options, long_options, opt_index, 1);
}
#endif /* Not ELIDE_CODE. */
#endif /* Not ELIDE_CODE. */
#ifdef TEST
#include <stdio.h>
int
main (argc, argv)
int argc;
char **argv;
main(argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] =
{
{"add", 1, 0, 0},
{"append", 0, 0, 0},
{"delete", 1, 0, 0},
{"verbose", 0, 0, 0},
{"create", 0, 0, 0},
{"file", 1, 0, 0},
{0, 0, 0, 0}
};
while(1) {
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] = {
{"add", 1, 0, 0},
{"append", 0, 0, 0},
{"delete", 1, 0, 0},
{"verbose", 0, 0, 0},
{"create", 0, 0, 0},
{"file", 1, 0, 0},
{0, 0, 0, 0}
};
c = getopt_long (argc, argv, "abc:d:0123456789",
long_options, &option_index);
if (c == -1)
break;
c = getopt_long(argc, argv, "abc:d:0123456789",
long_options, &option_index);
switch (c)
{
case 0:
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
if(c == -1) {
break;
}
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
switch(c) {
case 0:
printf("option %s", long_options[option_index].name);
case 'a':
printf ("option a\n");
break;
if(optarg) {
printf(" with arg %s", optarg);
}
case 'b':
printf ("option b\n");
break;
printf("\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if(digit_optind != 0 && digit_optind != this_option_optind) {
printf("digits occur in two different argv-elements.\n");
}
case 'd':
printf ("option d with value `%s'\n", optarg);
break;
digit_optind = this_option_optind;
printf("option %c\n", c);
break;
case '?':
break;
case 'a':
printf("option a\n");
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
case 'b':
printf("option b\n");
break;
case 'c':
printf("option c with value `%s'\n", optarg);
break;
case 'd':
printf("option d with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf("?? getopt returned character code 0%o ??\n", c);
}
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
if(optind < argc) {
printf("non-option ARGV-elements: ");
exit (0);
while(optind < argc) {
printf("%s ", argv[optind++]);
}
printf("\n");
}
exit(0);
}
#endif /* TEST */

View file

@ -68,15 +68,17 @@
static void mst_kruskal(void) {
/* Clear MST status on connections */
for list_each(connection_t, c, connection_list)
for list_each(connection_t, c, connection_list) {
c->status.mst = false;
}
logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Running Kruskal's algorithm:");
/* Clear visited status on nodes */
for splay_each(node_t, n, node_tree)
for splay_each(node_t, n, node_tree) {
n->status.visited = false;
}
/* Starting point */
@ -100,11 +102,13 @@ static void mst_kruskal(void) {
e->from->status.visited = true;
e->to->status.visited = true;
if(e->connection)
if(e->connection) {
e->connection->status.mst = true;
}
if(e->reverse->connection)
if(e->reverse->connection) {
e->reverse->connection->status.mst = true;
}
logger(DEBUG_SCARY_THINGS, LOG_DEBUG, " Adding edge %s - %s weight %d", e->from->name, e->to->name, e->weight);
@ -145,20 +149,22 @@ static void sssp_bfs(void) {
for list_each(node_t, n, todo_list) { /* "n" is the node from which we start */
logger(DEBUG_SCARY_THINGS, LOG_DEBUG, " Examining edges from %s", n->name);
if(n->distance < 0)
if(n->distance < 0) {
abort();
}
for splay_each(edge_t, e, n->edge_tree) { /* "e" is the edge connected to "from" */
if(!e->reverse || e->to == myself)
if(!e->reverse || e->to == myself) {
continue;
}
/* Situation:
/
/
/
/
----->(n)---e-->(e->to)
\
\
\
\
Where e is an edge, (n) and (e->to) are nodes.
n->address is set to the e->address of the edge left of n to n.
@ -172,14 +178,16 @@ static void sssp_bfs(void) {
bool indirect = n->status.indirect || e->options & OPTION_INDIRECT;
if(e->to->status.visited
&& (!e->to->status.indirect || indirect)
&& (e->to->distance != n->distance + 1 || e->weight >= e->to->prevedge->weight))
&& (!e->to->status.indirect || indirect)
&& (e->to->distance != n->distance + 1 || e->weight >= e->to->prevedge->weight)) {
continue;
}
// Only update nexthop if it doesn't increase the path length
if(!e->to->status.visited || (e->to->distance == n->distance + 1 && e->weight >= e->to->prevedge->weight))
if(!e->to->status.visited || (e->to->distance == n->distance + 1 && e->weight >= e->to->prevedge->weight)) {
e->to->nexthop = (n->nexthop == myself) ? e->to : n->nexthop;
}
e->to->status.visited = true;
e->to->status.indirect = indirect;
@ -188,8 +196,9 @@ static void sssp_bfs(void) {
e->to->options = e->options;
e->to->distance = n->distance + 1;
if(!e->to->status.reachable || (e->to->address.sa.sa_family == AF_UNSPEC && e->address.sa.sa_family != AF_UNKNOWN))
if(!e->to->status.reachable || (e->to->address.sa.sa_family == AF_UNSPEC && e->address.sa.sa_family != AF_UNKNOWN)) {
update_node_udp(e->to, &e->address);
}
list_insert_tail(todo_list, e->to);
}
@ -207,6 +216,7 @@ static void check_reachability(void) {
int reachable_count = 0;
int became_reachable_count = 0;
int became_unreachable_count = 0;
for splay_each(node_t, n, node_tree) {
if(n->status.visited != n->status.reachable) {
n->status.reachable = !n->status.reachable;
@ -214,26 +224,33 @@ static void check_reachability(void) {
if(n->status.reachable) {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Node %s (%s) became reachable",
n->name, n->hostname);
if (n != myself)
n->name, n->hostname);
if(n != myself) {
became_reachable_count++;
}
} else {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Node %s (%s) became unreachable",
n->name, n->hostname);
if (n != myself)
n->name, n->hostname);
if(n != myself) {
became_unreachable_count++;
}
}
if(experimental && OPTION_VERSION(n->options) >= 2)
if(experimental && OPTION_VERSION(n->options) >= 2) {
n->status.sptps = true;
}
/* TODO: only clear status.validkey if node is unreachable? */
n->status.validkey = false;
if(n->status.sptps) {
sptps_stop(&n->sptps);
n->status.waitingforkey = false;
}
n->last_req_key = 0;
n->status.udp_confirmed = false;
@ -269,24 +286,27 @@ static void check_reachability(void) {
if(!n->status.reachable) {
update_node_udp(n, NULL);
memset(&n->status, 0, sizeof n->status);
memset(&n->status, 0, sizeof(n->status));
n->options = 0;
} else if(n->connection) {
// Speed up UDP probing by sending our key.
if(!n->status.sptps)
if(!n->status.sptps) {
send_ans_key(n);
}
}
}
if(n->status.reachable && n != myself)
if(n->status.reachable && n != myself) {
reachable_count++;
}
}
if (device_standby) {
if (reachable_count == 0 && became_unreachable_count > 0)
if(device_standby) {
if(reachable_count == 0 && became_unreachable_count > 0) {
device_disable();
else if (reachable_count > 0 && reachable_count == became_reachable_count)
} else if(reachable_count > 0 && reachable_count == became_reachable_count) {
device_enable();
}
}
}

View file

@ -1,3 +1,6 @@
#ifndef TINC_GRAPH_H
#define TINC_GRAPH_H
/*
graph.h -- header for graph.c
Copyright (C) 2001-2012 Guus Sliepen <guus@tinc-vpn.org>,
@ -18,10 +21,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_GRAPH_H__
#define __TINC_GRAPH_H__
extern void graph(void);
extern void dump_graph(void);
#endif /* __TINC_GRAPH_H__ */
#endif

View file

@ -27,36 +27,44 @@
static uint32_t hash_function(const void *p, size_t len) {
const uint8_t *q = p;
uint32_t hash = 0;
while(true) {
for(int i = len > 4 ? 4 : len; --i;)
for(int i = len > 4 ? 4 : len; --i;) {
hash += (uint32_t)q[len - i] << (8 * i);
}
hash *= 0x9e370001UL; // Golden ratio prime.
if(len <= 4)
if(len <= 4) {
break;
}
len -= 4;
}
return hash;
}
/* Map 32 bits int onto 0..n-1, without throwing away too many bits if n is 2^8 or 2^16 */
static uint32_t modulo(uint32_t hash, size_t n) {
if(n == 0x100)
if(n == 0x100) {
return (hash >> 24) ^ ((hash >> 16) & 0xff) ^ ((hash >> 8) & 0xff) ^ (hash & 0xff);
else if(n == 0x10000)
} else if(n == 0x10000) {
return (hash >> 16) ^ (hash & 0xffff);
else
} else {
return hash % n;
}
}
/* (De)allocation */
hash_t *hash_alloc(size_t n, size_t size) {
hash_t *hash = xzalloc(sizeof *hash);
hash_t *hash = xzalloc(sizeof(*hash));
hash->n = n;
hash->size = size;
hash->keys = xzalloc(hash->n * hash->size);
hash->values = xzalloc(hash->n * sizeof *hash->values);
hash->values = xzalloc(hash->n * sizeof(*hash->values));
return hash;
}
@ -76,16 +84,21 @@ void hash_insert(hash_t *hash, const void *key, const void *value) {
void *hash_search(const hash_t *hash, const void *key) {
uint32_t i = modulo(hash_function(key, hash->size), hash->n);
if(hash->values[i] && !memcmp(key, hash->keys + i * hash->size, hash->size)) {
return (void *)hash->values[i];
}
return NULL;
}
void *hash_search_or_insert(hash_t *hash, const void *key, const void *value) {
uint32_t i = modulo(hash_function(key, hash->size), hash->n);
if(hash->values[i] && !memcmp(key, hash->keys + i * hash->size, hash->size))
if(hash->values[i] && !memcmp(key, hash->keys + i * hash->size, hash->size)) {
return (void *)hash->values[i];
}
memcpy(hash->keys + i * hash->size, key, hash->size);
hash->values[i] = value;
return NULL;
@ -101,14 +114,15 @@ void hash_delete(hash_t *hash, const void *key) {
/* Utility functions */
void hash_clear(hash_t *hash) {
memset(hash->values, 0, hash->n * sizeof *hash->values);
memset(hash->values, 0, hash->n * sizeof(*hash->values));
}
void hash_resize(hash_t *hash, size_t n) {
hash->keys = xrealloc(hash->keys, n * hash->size);
hash->values = xrealloc(hash->values, n * sizeof *hash->values);
hash->values = xrealloc(hash->values, n * sizeof(*hash->values));
if(n > hash->n) {
memset(hash->keys + hash->n * hash->size, 0, (n - hash->n) * hash->size);
memset(hash->values + hash->n, 0, (n - hash->n) * sizeof *hash->values);
memset(hash->values + hash->n, 0, (n - hash->n) * sizeof(*hash->values));
}
}

View file

@ -1,3 +1,6 @@
#ifndef TINC_HASH_H
#define TINC_HASH_H
/*
hash.h -- header file for hash.c
Copyright (C) 2012 Guus Sliepen <guus@tinc-vpn.org>
@ -17,9 +20,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_HASH_H__
#define __TINC_HASH_H__
typedef struct hash_t {
size_t n;
size_t size;
@ -27,7 +27,7 @@ typedef struct hash_t {
const void **values;
} hash_t;
extern hash_t *hash_alloc(size_t n, size_t size) __attribute__ ((__malloc__));
extern hash_t *hash_alloc(size_t n, size_t size) __attribute__((__malloc__));
extern void hash_free(hash_t *);
extern void hash_insert(hash_t *, const void *key, const void *value);
@ -39,4 +39,4 @@ extern void *hash_search_or_insert(hash_t *, const void *key, const void *value)
extern void hash_clear(hash_t *);
extern void hash_resize(hash_t *, size_t n);
#endif /* __TINC_HASH_H__ */
#endif

View file

@ -1,3 +1,6 @@
#ifndef TINC_HAVE_H
#define TINC_HAVE_H
/*
have.h -- include headers which are known to exist
Copyright (C) 1998-2005 Ivo Timmermans
@ -18,9 +21,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_HAVE_H__
#define __TINC_HAVE_H__
#ifdef HAVE_MINGW
#define WINVER WindowsXP
#define WIN32_LEAN_AND_MEAN
@ -213,4 +213,4 @@
#define SLASH "/"
#endif
#endif /* __TINC_SYSTEM_H__ */
#endif

View file

@ -86,112 +86,219 @@ bool ifconfig_footer(FILE *out) {
static subnet_t ipv4, ipv6;
void ifconfig_address(FILE *out, const char *value) {
subnet_t address = {};
subnet_t address = {0};
char address_str[MAXNETSTR];
if(!str2net(&address, value) || !net2str(address_str, sizeof address_str, &address)) {
if(!str2net(&address, value) || !net2str(address_str, sizeof(address_str), &address)) {
fprintf(stderr, "Could not parse address in Ifconfig statement\n");
return;
}
switch(address.type) {
case SUBNET_IPV4: ipv4 = address; break;
case SUBNET_IPV6: ipv6 = address; break;
default: return;
case SUBNET_IPV4:
ipv4 = address;
break;
case SUBNET_IPV6:
ipv6 = address;
break;
default:
return;
}
#if defined(HAVE_LINUX)
switch(address.type) {
case SUBNET_MAC: fprintf(out, "ip link set \"$INTERFACE\" address %s\n", address_str); break;
case SUBNET_IPV4: fprintf(out, "ip addr replace %s dev \"$INTERFACE\"\n", address_str); break;
case SUBNET_IPV6: fprintf(out, "ip addr replace %s dev \"$INTERFACE\"\n", address_str); break;
default: return;
case SUBNET_MAC:
fprintf(out, "ip link set \"$INTERFACE\" address %s\n", address_str);
break;
case SUBNET_IPV4:
fprintf(out, "ip addr replace %s dev \"$INTERFACE\"\n", address_str);
break;
case SUBNET_IPV6:
fprintf(out, "ip addr replace %s dev \"$INTERFACE\"\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;
case SUBNET_IPV4: fprintf(out, "netsh inetface ipv4 set address \"$INTERFACE\" static %s\n", address_str); break;
case SUBNET_IPV6: fprintf(out, "netsh inetface ipv6 set address \"$INTERFACE\" static %s\n", address_str); break;
default: return;
case SUBNET_MAC:
fprintf(out, "ip link set \"$INTERFACE\" address %s\n", address_str);
break;
case SUBNET_IPV4:
fprintf(out, "netsh inetface ipv4 set address \"$INTERFACE\" static %s\n", address_str);
break;
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;
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
}
void ifconfig_route(FILE *out, const char *value) {
subnet_t subnet = {}, gateway = {};
subnet_t subnet = {0}, gateway = {0};
char subnet_str[MAXNETSTR] = "", gateway_str[MAXNETSTR] = "";
char *sep = strchr(value, ' ');
if(sep)
if(sep) {
*sep++ = 0;
if(!str2net(&subnet, value) || !net2str(subnet_str, sizeof subnet_str, &subnet) || subnet.type == SUBNET_MAC) {
}
if(!str2net(&subnet, value) || !net2str(subnet_str, sizeof(subnet_str), &subnet) || subnet.type == SUBNET_MAC) {
fprintf(stderr, "Could not parse subnet in Route statement\n");
return;
}
if(sep) {
if(!str2net(&gateway, sep) || !net2str(gateway_str, sizeof gateway_str, &gateway) || gateway.type != subnet.type) {
if(!str2net(&gateway, sep) || !net2str(gateway_str, sizeof(gateway_str), &gateway) || gateway.type != subnet.type) {
fprintf(stderr, "Could not parse gateway in Route statement\n");
return;
}
char *slash = strchr(gateway_str, '/'); if(slash) *slash = 0;
char *slash = strchr(gateway_str, '/');
if(slash) {
*slash = 0;
}
}
#if defined(HAVE_LINUX)
if(*gateway_str) {
switch(subnet.type) {
case SUBNET_IPV4: fprintf(out, "ip route add %s via %s dev \"$INTERFACE\"\n", subnet_str, gateway_str); break;
case SUBNET_IPV6: fprintf(out, "ip route add %s via %s dev \"$INTERFACE\"\n", subnet_str, gateway_str); break;
default: return;
case SUBNET_IPV4:
fprintf(out, "ip route add %s via %s dev \"$INTERFACE\"\n", subnet_str, gateway_str);
break;
case SUBNET_IPV6:
fprintf(out, "ip route add %s via %s dev \"$INTERFACE\"\n", subnet_str, gateway_str);
break;
default:
return;
}
} else {
switch(subnet.type) {
case SUBNET_IPV4: fprintf(out, "ip route add %s dev \"$INTERFACE\"\n", subnet_str); break;
case SUBNET_IPV6: fprintf(out, "ip route add %s dev \"$INTERFACE\"\n", subnet_str); break;
default: return;
case SUBNET_IPV4:
fprintf(out, "ip route add %s dev \"$INTERFACE\"\n", subnet_str);
break;
case SUBNET_IPV6:
fprintf(out, "ip route add %s dev \"$INTERFACE\"\n", subnet_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;
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;
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:
if(!ipv4.type) {
fprintf(stderr, "Route requested but no Ifconfig\n");
return;
}
net2str(gateway_str, sizeof gateway_str, &ipv4);
break;
case SUBNET_IPV6:
if(!ipv6.type) {
fprintf(stderr, "Route requested but no Ifconfig\n");
return;
}
net2str(gateway_str, sizeof gateway_str, &ipv6);
break;
default: return;
case SUBNET_IPV4:
if(!ipv4.type) {
fprintf(stderr, "Route requested but no Ifconfig\n");
return;
}
net2str(gateway_str, sizeof(gateway_str), &ipv4);
break;
case SUBNET_IPV6:
if(!ipv6.type) {
fprintf(stderr, "Route requested but no Ifconfig\n");
return;
}
net2str(gateway_str, sizeof(gateway_str), &ipv6);
break;
default:
return;
}
char *slash = strchr(gateway_str, '/');
if(slash) {
*slash = 0;
}
char *slash = strchr(gateway_str, '/'); if(slash) *slash = 0;
}
switch(subnet.type) {
case SUBNET_IPV4: fprintf(out, "route add %s %s\n", subnet_str, gateway_str); break;
case SUBNET_IPV6: fprintf(out, "route add -inet6 %s %s\n", subnet_str, gateway_str); break;
default: return;
case SUBNET_IPV4:
fprintf(out, "route add %s %s\n", subnet_str, gateway_str);
break;
case SUBNET_IPV6:
fprintf(out, "route add -inet6 %s %s\n", subnet_str, gateway_str);
break;
default:
return;
}
#endif
}

View file

@ -1,3 +1,6 @@
#ifndef TINC_IFCONFIG_H
#define TINC_IFCONFIG_H
/*
ifconfig.h -- header for ifconfig.c.
Copyright (C) 2016 Guus Sliepen <guus@tinc-vpn.org>
@ -17,9 +20,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_IFCONFIG_H__
#define __TINC_IFCONFIG_H__
extern void ifconfig_dhcp(FILE *out);
extern void ifconfig_dhcp6(FILE *out);
extern void ifconfig_slaac(FILE *out);

View file

@ -28,17 +28,24 @@
#include "xalloc.h"
void logger(int level, int priority, const char *format, ...) {
(void)level;
(void)priority;
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
fputc('\n', stderr);
}
char *strip_weight(char *netstr) {
int len = strlen(netstr);
if(len >= 3 && !strcmp(netstr + len - 3, "#10"))
if(len >= 3 && !strcmp(netstr + len - 3, "#10")) {
netstr[len - 3] = 0;
}
return netstr;
}
@ -67,14 +74,17 @@ static int info_node(int fd, const char *item) {
} status_union;
node_status_t status;
long int last_state_change;
int udp_ping_rtt;
uint64_t in_packets, in_bytes, out_packets, out_bytes;
while(recvline(fd, line, sizeof line)) {
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);
while(recvline(fd, line, sizeof(line))) {
int n = sscanf(line, "%d %d %4095s %4095s %4095s port %4095s %d %d %d %d %x %"PRIx32" %4095s %4095s %d %hd %hd %hd %ld %d %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64, &code, &req, node, id, host, port, &cipher, &digest, &maclength, &compression, &options, &status_union.raw, nexthop, via, &distance, &pmtu, &minmtu, &maxmtu, &last_state_change, &udp_ping_rtt, &in_packets, &in_bytes, &out_packets, &out_bytes);
if(n == 2)
if(n == 2) {
break;
}
if(n != 19) {
if(n != 24) {
fprintf(stderr, "Unable to parse node dump from tincd.\n");
return 1;
}
@ -90,9 +100,10 @@ static int info_node(int fd, const char *item) {
return 1;
}
while(recvline(fd, line, sizeof line)) {
if(sscanf(line, "%d %d %4095s", &code, &req, node) == 2)
while(recvline(fd, line, sizeof(line))) {
if(sscanf(line, "%d %d %4095s", &code, &req, node) == 2) {
break;
}
}
printf("Node: %s\n", item);
@ -102,88 +113,135 @@ static int info_node(int fd, const char *item) {
char timestr[32] = "never";
time_t lsc_time = last_state_change;
if(last_state_change)
strftime(timestr, sizeof timestr, "%Y-%m-%d %H:%M:%S", localtime(&lsc_time));
if(last_state_change) {
strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", localtime(&lsc_time));
}
status = status_union.bits;
if(status.reachable)
if(status.reachable) {
printf("Online since: %s\n", timestr);
else
} else {
printf("Last seen: %s\n", timestr);
}
printf("Status: ");
if(status.validkey)
if(status.validkey) {
printf(" validkey");
if(status.visited)
}
if(status.visited) {
printf(" visited");
if(status.reachable)
}
if(status.reachable) {
printf(" reachable");
if(status.indirect)
}
if(status.indirect) {
printf(" indirect");
if(status.sptps)
}
if(status.sptps) {
printf(" sptps");
if(status.udp_confirmed)
}
if(status.udp_confirmed) {
printf(" udp_confirmed");
}
printf("\n");
printf("Options: ");
if(options & OPTION_INDIRECT)
if(options & OPTION_INDIRECT) {
printf(" indirect");
if(options & OPTION_TCPONLY)
}
if(options & OPTION_TCPONLY) {
printf(" tcponly");
if(options & OPTION_PMTU_DISCOVERY)
}
if(options & OPTION_PMTU_DISCOVERY) {
printf(" pmtu_discovery");
if(options & OPTION_CLAMP_MSS)
}
if(options & OPTION_CLAMP_MSS) {
printf(" clamp_mss");
}
printf("\n");
printf("Protocol: %d.%d\n", PROT_MAJOR, OPTION_VERSION(options));
printf("Reachability: ");
if(!strcmp(host, "MYSELF"))
if(!strcmp(host, "MYSELF")) {
printf("can reach itself\n");
else if(!status.reachable)
} else if(!status.reachable) {
printf("unreachable\n");
else if(strcmp(via, item))
} else if(strcmp(via, item)) {
printf("indirectly via %s\n", via);
else if(!status.validkey)
} else if(!status.validkey) {
printf("unknown\n");
else if(minmtu > 0)
} else if(minmtu > 0) {
printf("directly with UDP\nPMTU: %d\n", pmtu);
else if(!strcmp(nexthop, item))
if(udp_ping_rtt != -1) {
printf("RTT: %d.%03d\n", udp_ping_rtt / 1000, udp_ping_rtt % 1000);
}
} else if(!strcmp(nexthop, item)) {
printf("directly with TCP\n");
else
} else {
printf("none, forwarded via %s\n", nexthop);
}
printf("RX: %"PRIu64" packets %"PRIu64" bytes\n", in_packets, in_bytes);
printf("TX: %"PRIu64" packets %"PRIu64" bytes\n", out_packets, out_bytes);
// List edges
printf("Edges: ");
sendline(fd, "%d %d %s", CONTROL, REQ_DUMP_EDGES, item);
while(recvline(fd, line, sizeof line)) {
while(recvline(fd, line, sizeof(line))) {
int n = sscanf(line, "%d %d %4095s %4095s", &code, &req, from, to);
if(n == 2)
if(n == 2) {
break;
}
if(n != 4) {
fprintf(stderr, "Unable to parse edge dump from tincd.\n%s\n", line);
return 1;
}
if(!strcmp(from, item))
if(!strcmp(from, item)) {
printf(" %s", to);
}
}
printf("\n");
// List subnets
printf("Subnets: ");
sendline(fd, "%d %d %s", CONTROL, REQ_DUMP_SUBNETS, item);
while(recvline(fd, line, sizeof line)) {
while(recvline(fd, line, sizeof(line))) {
int n = sscanf(line, "%d %d %4095s %4095s", &code, &req, subnet, from);
if(n == 2)
if(n == 2) {
break;
}
if(n != 4) {
fprintf(stderr, "Unable to parse subnet dump from tincd.\n");
return 1;
}
if(!strcmp(from, item))
if(!strcmp(from, item)) {
printf(" %s", strip_weight(subnet));
}
}
printf("\n");
return 0;
@ -208,47 +266,63 @@ static int info_subnet(int fd, const char *item) {
int code, req;
sendline(fd, "%d %d %s", CONTROL, REQ_DUMP_SUBNETS, item);
while(recvline(fd, line, sizeof line)) {
while(recvline(fd, line, sizeof(line))) {
int n = sscanf(line, "%d %d %4095s %4095s", &code, &req, netstr, owner);
if(n == 2)
if(n == 2) {
break;
}
if(n != 4 || !str2net(&subnet, netstr)) {
fprintf(stderr, "Unable to parse subnet dump from tincd.\n");
return 1;
}
if(find.type != subnet.type)
if(find.type != subnet.type) {
continue;
}
if(weight) {
if(find.weight != subnet.weight)
if(find.weight != subnet.weight) {
continue;
}
}
if(find.type == SUBNET_IPV4) {
if(address) {
if(maskcmp(&find.net.ipv4.address, &subnet.net.ipv4.address, subnet.net.ipv4.prefixlength))
if(maskcmp(&find.net.ipv4.address, &subnet.net.ipv4.address, subnet.net.ipv4.prefixlength)) {
continue;
}
} else {
if(find.net.ipv4.prefixlength != subnet.net.ipv4.prefixlength)
if(find.net.ipv4.prefixlength != subnet.net.ipv4.prefixlength) {
continue;
if(memcmp(&find.net.ipv4.address, &subnet.net.ipv4.address, sizeof subnet.net.ipv4))
}
if(memcmp(&find.net.ipv4.address, &subnet.net.ipv4.address, sizeof(subnet.net.ipv4))) {
continue;
}
}
} else if(find.type == SUBNET_IPV6) {
if(address) {
if(maskcmp(&find.net.ipv6.address, &subnet.net.ipv6.address, subnet.net.ipv6.prefixlength))
if(maskcmp(&find.net.ipv6.address, &subnet.net.ipv6.address, subnet.net.ipv6.prefixlength)) {
continue;
}
} else {
if(find.net.ipv6.prefixlength != subnet.net.ipv6.prefixlength)
if(find.net.ipv6.prefixlength != subnet.net.ipv6.prefixlength) {
continue;
if(memcmp(&find.net.ipv6.address, &subnet.net.ipv6.address, sizeof subnet.net.ipv6))
}
if(memcmp(&find.net.ipv6.address, &subnet.net.ipv6.address, sizeof(subnet.net.ipv6))) {
continue;
}
}
} if(find.type == SUBNET_MAC) {
if(memcmp(&find.net.mac.address, &subnet.net.mac.address, sizeof subnet.net.mac))
}
if(find.type == SUBNET_MAC) {
if(memcmp(&find.net.mac.address, &subnet.net.mac.address, sizeof(subnet.net.mac))) {
continue;
}
}
found = true;
@ -257,10 +331,12 @@ static int info_subnet(int fd, const char *item) {
}
if(!found) {
if(address)
if(address) {
fprintf(stderr, "Unknown address %s.\n", item);
else
} else {
fprintf(stderr, "Unknown subnet %s.\n", item);
}
return 1;
}
@ -268,10 +344,13 @@ static int info_subnet(int fd, const char *item) {
}
int info(int fd, const char *item) {
if(check_id(item))
if(check_id(item)) {
return info_node(fd, item);
if(strchr(item, '.') || strchr(item, ':'))
}
if(strchr(item, '.') || strchr(item, ':')) {
return info_subnet(fd, item);
}
fprintf(stderr, "Argument is not a node name, subnet or address.\n");
return 1;

View file

@ -1,3 +1,6 @@
#ifndef TINC_INFO_H
#define TINC_INFO_H
/*
info.h -- header for info.c.
Copyright (C) 2012 Guus Sliepen <guus@tinc-vpn.org>
@ -17,11 +20,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_INFO_H__
#define __TINC_INFO_H__
extern int info(int fd, const char *item);
extern char *strip_weight(char *);
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,6 @@
#ifndef TINC_INVITATION_H
#define TINC_INVITATION_H
/*
invitation.h -- header for invitation.c.
Copyright (C) 2013 Guus Sliepen <guus@tinc-vpn.org>
@ -17,10 +20,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_INVITATION_H__
#define __TINC_INVITATION_H__
bool recvdata(int fd, char *data, size_t len);
int cmd_invite(int argc, char *argv[]);
int cmd_join(int argc, char *argv[]);

View file

@ -1,3 +1,6 @@
#ifndef TINC_IPV4_H
#define TINC_IPV4_H
/*
ipv4.h -- missing IPv4 related definitions
Copyright (C) 2005 Ivo Timmermans
@ -18,9 +21,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_IPV4_H__
#define __TINC_IPV4_H__
#ifndef AF_INET
#define AF_INET 2
#endif
@ -64,11 +64,11 @@
#ifndef HAVE_STRUCT_IP
struct ip {
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int ip_hl:4;
unsigned int ip_v:4;
unsigned int ip_hl: 4;
unsigned int ip_v: 4;
#else
unsigned int ip_v:4;
unsigned int ip_hl:4;
unsigned int ip_v: 4;
unsigned int ip_hl: 4;
#endif
uint8_t ip_tos;
uint16_t ip_len;
@ -81,7 +81,7 @@ struct ip {
uint8_t ip_p;
uint16_t ip_sum;
struct in_addr ip_src, ip_dst;
} __attribute__ ((__gcc_struct__, __packed__));
} __attribute__((__gcc_struct__, __packed__));
#endif
#ifndef IP_OFFMASK
@ -143,7 +143,7 @@ struct icmp {
#define icmp_radv icmp_dun.id_radv
#define icmp_mask icmp_dun.id_mask
#define icmp_data icmp_dun.id_data
} __attribute__ ((__gcc_struct__, __packed__));
} __attribute__((__gcc_struct__, __packed__));
#endif
#endif /* __TINC_IPV4_H__ */
#endif

View file

@ -1,3 +1,6 @@
#ifndef TINC_IPV6_H
#define TINC_IPV6_H
/*
ipv6.h -- missing IPv6 related definitions
Copyright (C) 2005 Ivo Timmermans
@ -18,9 +21,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_IPV6_H__
#define __TINC_IPV6_H__
#ifndef AF_INET6
#define AF_INET6 10
#endif
@ -32,8 +32,8 @@
#ifndef IN6_IS_ADDR_V4MAPPED
#define IN6_IS_ADDR_V4MAPPED(a) \
((((__const uint32_t *) (a))[0] == 0) \
&& (((__const uint32_t *) (a))[1] == 0) \
&& (((__const uint32_t *) (a))[2] == htonl (0xffff)))
&& (((__const uint32_t *) (a))[1] == 0) \
&& (((__const uint32_t *) (a))[2] == htonl (0xffff)))
#endif
#ifndef HAVE_STRUCT_IP6_HDR
@ -49,7 +49,7 @@ struct ip6_hdr {
} ip6_ctlun;
struct in6_addr ip6_src;
struct in6_addr ip6_dst;
} __attribute__ ((__gcc_struct__, __packed__));
} __attribute__((__gcc_struct__, __packed__));
#define ip6_vfc ip6_ctlun.ip6_un2_vfc
#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow
#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen
@ -68,7 +68,7 @@ struct icmp6_hdr {
uint16_t icmp6_un_data16[2];
uint8_t icmp6_un_data8[4];
} icmp6_dataun;
} __attribute__ ((__gcc_struct__, __packed__));
} __attribute__((__gcc_struct__, __packed__));
#define ICMP6_DST_UNREACH_NOROUTE 0
#define ICMP6_DST_UNREACH 1
#define ICMP6_PACKET_TOO_BIG 2
@ -88,7 +88,7 @@ struct icmp6_hdr {
struct nd_neighbor_solicit {
struct icmp6_hdr nd_ns_hdr;
struct in6_addr nd_ns_target;
} __attribute__ ((__gcc_struct__, __packed__));
} __attribute__((__gcc_struct__, __packed__));
#define ND_OPT_SOURCE_LINKADDR 1
#define ND_OPT_TARGET_LINKADDR 2
#define nd_ns_type nd_ns_hdr.icmp6_type
@ -101,7 +101,7 @@ struct nd_neighbor_solicit {
struct nd_opt_hdr {
uint8_t nd_opt_type;
uint8_t nd_opt_len;
} __attribute__ ((__gcc_struct__, __packed__));
} __attribute__((__gcc_struct__, __packed__));
#endif
#endif /* __TINC_IPV6_H__ */
#endif

View file

@ -44,15 +44,17 @@ char *device = NULL;
char *iface = NULL;
static char *type = NULL;
static char ifrname[IFNAMSIZ];
static char *device_info;
static const char *device_info;
static bool setup_device(void) {
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
device = xstrdup(DEFAULT_DEVICE);
}
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
if(netname)
if(netname) {
iface = xstrdup(netname);
}
device_fd = open(device, O_RDWR | O_NONBLOCK);
@ -65,7 +67,7 @@ static bool setup_device(void) {
fcntl(device_fd, F_SETFD, FD_CLOEXEC);
#endif
struct ifreq ifr = {{{0}}};
struct ifreq ifr = {0};
get_config_string(lookup_config(config_tree, "DeviceType"), &type);
@ -79,8 +81,10 @@ static bool setup_device(void) {
device_type = DEVICE_TYPE_TUN;
device_info = "Linux tun/tap device (tun mode)";
} else {
if (routing_mode == RMODE_ROUTER)
if(routing_mode == RMODE_ROUTER) {
overwrite_mac = true;
}
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
device_type = DEVICE_TYPE_TAP;
device_info = "Linux tun/tap device (tap mode)";
@ -90,15 +94,21 @@ static bool setup_device(void) {
/* Set IFF_ONE_QUEUE flag... */
bool t1q = false;
if(get_config_bool(lookup_config(config_tree, "IffOneQueue"), &t1q) && t1q)
if(get_config_bool(lookup_config(config_tree, "IffOneQueue"), &t1q) && t1q) {
ifr.ifr_flags |= IFF_ONE_QUEUE;
}
#endif
if(iface)
if(iface) {
strncpy(ifr.ifr_name, iface, IFNAMSIZ);
ifr.ifr_name[IFNAMSIZ - 1] = 0;
}
if(!ioctl(device_fd, TUNSETIFF, &ifr)) {
strncpy(ifrname, ifr.ifr_name, IFNAMSIZ);
ifrname[IFNAMSIZ - 1] = 0;
free(iface);
iface = xstrdup(ifrname);
} else {
@ -109,11 +119,13 @@ static bool setup_device(void) {
logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
if(ifr.ifr_flags & IFF_TAP) {
struct ifreq ifr_mac = {};
if(!ioctl(device_fd, SIOCGIFHWADDR, &ifr_mac))
struct ifreq ifr_mac = {0};
if(!ioctl(device_fd, SIOCGIFHWADDR, &ifr_mac)) {
memcpy(mymac.x, ifr_mac.ifr_hwaddr.sa_data, ETH_ALEN);
else
} else {
logger(DEBUG_ALWAYS, LOG_WARNING, "Could not get MAC address of %s: %s", device, strerror(errno));
}
}
return true;
@ -123,9 +135,12 @@ static void close_device(void) {
close(device_fd);
device_fd = -1;
free(type); type = NULL;
free(device); device = NULL;
free(iface); iface = NULL;
free(type);
type = NULL;
free(device);
device = NULL;
free(iface);
iface = NULL;
device_info = NULL;
}
@ -133,64 +148,73 @@ static bool read_packet(vpn_packet_t *packet) {
int inlen;
switch(device_type) {
case DEVICE_TYPE_TUN:
inlen = read(device_fd, DATA(packet) + 10, MTU - 10);
case DEVICE_TYPE_TUN:
inlen = read(device_fd, DATA(packet) + 10, MTU - 10);
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;
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();
}
memset(DATA(packet), 0, 12);
packet->len = inlen + 10;
break;
case DEVICE_TYPE_TAP:
inlen = read(device_fd, DATA(packet), MTU);
return false;
}
if(inlen <= 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s",
device_info, device, strerror(errno));
return false;
}
memset(DATA(packet), 0, 12);
packet->len = inlen + 10;
break;
packet->len = inlen;
break;
default:
abort();
case DEVICE_TYPE_TAP:
inlen = read(device_fd, DATA(packet), MTU);
if(inlen <= 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s",
device_info, device, strerror(errno));
return false;
}
packet->len = inlen;
break;
default:
abort();
}
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len,
device_info);
device_info);
return true;
}
static bool write_packet(vpn_packet_t *packet) {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s",
packet->len, device_info);
packet->len, device_info);
switch(device_type) {
case DEVICE_TYPE_TUN:
DATA(packet)[10] = DATA(packet)[11] = 0;
if(write(device_fd, DATA(packet) + 10, packet->len - 10) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
strerror(errno));
return false;
}
break;
case DEVICE_TYPE_TAP:
if(write(device_fd, DATA(packet), packet->len) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
strerror(errno));
return false;
}
break;
default:
abort();
case DEVICE_TYPE_TUN:
DATA(packet)[10] = DATA(packet)[11] = 0;
if(write(device_fd, DATA(packet) + 10, packet->len - 10) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
strerror(errno));
return false;
}
break;
case DEVICE_TYPE_TAP:
if(write(device_fd, DATA(packet), packet->len) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
strerror(errno));
return false;
}
break;
default:
abort();
}
return true;

View file

@ -41,8 +41,9 @@ list_node_t *list_alloc_node(void) {
}
void list_free_node(list_t *list, list_node_t *node) {
if(node->data && list->delete)
if(node->data && list->delete) {
list->delete(node->data);
}
free(node);
}
@ -57,10 +58,11 @@ list_node_t *list_insert_head(list_t *list, void *data) {
node->next = list->head;
list->head = node;
if(node->next)
if(node->next) {
node->next->prev = node;
else
} else {
list->tail = node;
}
list->count++;
@ -75,10 +77,11 @@ list_node_t *list_insert_tail(list_t *list, void *data) {
node->prev = list->tail;
list->tail = node;
if(node->prev)
if(node->prev) {
node->prev->next = node;
else
} else {
list->head = node;
}
list->count++;
@ -93,10 +96,11 @@ list_node_t *list_insert_after(list_t *list, list_node_t *after, void *data) {
node->prev = after;
after->next = node;
if(node->next)
if(node->next) {
node->next->prev = node;
else
} else {
list->tail = node;
}
list->count++;
@ -113,10 +117,11 @@ list_node_t *list_insert_before(list_t *list, list_node_t *before, void *data) {
node->prev = before->prev;
before->prev = node;
if(node->prev)
if(node->prev) {
node->prev->next = node;
else
} else {
list->head = node;
}
list->count++;
@ -124,15 +129,17 @@ list_node_t *list_insert_before(list_t *list, list_node_t *before, void *data) {
}
void list_unlink_node(list_t *list, list_node_t *node) {
if(node->prev)
if(node->prev) {
node->prev->next = node->next;
else
} else {
list->head = node->next;
}
if(node->next)
if(node->next) {
node->next->prev = node->prev;
else
} else {
list->tail = node->prev;
}
list->count--;
}
@ -152,31 +159,35 @@ void list_delete_tail(list_t *list) {
void list_delete(list_t *list, const void *data) {
for(list_node_t *node = list->head, *next; next = node ? node->next : NULL, node; node = next)
if(node->data == data)
if(node->data == data) {
list_delete_node(list, node);
}
}
/* Head/tail lookup */
void *list_get_head(list_t *list) {
if(list->head)
if(list->head) {
return list->head->data;
else
} else {
return NULL;
}
}
void *list_get_tail(list_t *list) {
if(list->tail)
if(list->tail) {
return list->tail->data;
else
} else {
return NULL;
}
}
/* Fast list deletion */
void list_delete_list(list_t *list) {
for(list_node_t *node = list->head, *next; next = node ? node->next : NULL, node; node = next)
for(list_node_t *node = list->head, *next; next = node ? node->next : NULL, node; node = next) {
list_free_node(list, node);
}
list_free(list);
}
@ -184,12 +195,14 @@ void list_delete_list(list_t *list) {
/* Traversing */
void list_foreach_node(list_t *list, list_action_node_t action) {
for(list_node_t *node = list->head, *next; next = node ? node->next : NULL, node; node = next)
for(list_node_t *node = list->head, *next; next = node ? node->next : NULL, node; node = next) {
action(node);
}
}
void list_foreach(list_t *list, list_action_t action) {
for(list_node_t *node = list->head, *next; next = node ? node->next : NULL, node; node = next)
if(node->data)
if(node->data) {
action(node->data);
}
}

View file

@ -1,3 +1,6 @@
#ifndef TINC_LIST_H
#define TINC_LIST_H
/*
list.h -- header file for list.c
Copyright (C) 2000-2005 Ivo Timmermans
@ -18,9 +21,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_LIST_H__
#define __TINC_LIST_H__
typedef struct list_node_t {
struct list_node_t *prev;
struct list_node_t *next;
@ -30,8 +30,8 @@ typedef struct list_node_t {
void *data;
} list_node_t;
typedef void (*list_action_t)(const void *);
typedef void (*list_action_node_t)(const list_node_t *);
typedef void (*list_action_t)(const void *data);
typedef void (*list_action_node_t)(const list_node_t *node);
typedef struct list_t {
list_node_t *head;
@ -45,39 +45,39 @@ typedef struct list_t {
/* (De)constructors */
extern list_t *list_alloc(list_action_t) __attribute__ ((__malloc__));
extern void list_free(list_t *);
extern list_t *list_alloc(list_action_t delete) __attribute__((__malloc__));
extern void list_free(list_t *list);
extern list_node_t *list_alloc_node(void);
extern void list_free_node(list_t *, list_node_t *);
extern void list_free_node(list_t *list, list_node_t *node);
/* Insertion and deletion */
extern list_node_t *list_insert_head(list_t *, void *);
extern list_node_t *list_insert_tail(list_t *, void *);
extern list_node_t *list_insert_after(list_t *, list_node_t *, void *);
extern list_node_t *list_insert_before(list_t *, list_node_t *, void *);
extern list_node_t *list_insert_head(list_t *list, void *data);
extern list_node_t *list_insert_tail(list_t *list, void *data);
extern list_node_t *list_insert_after(list_t *list, list_node_t *node, void *data);
extern list_node_t *list_insert_before(list_t *list, list_node_t *node, void *data);
extern void list_delete(list_t *, const void *);
extern void list_delete(list_t *list, const void *data);
extern void list_unlink_node(list_t *, list_node_t *);
extern void list_delete_node(list_t *, list_node_t *);
extern void list_unlink_node(list_t *list, list_node_t *node);
extern void list_delete_node(list_t *list, list_node_t *node);
extern void list_delete_head(list_t *);
extern void list_delete_tail(list_t *);
extern void list_delete_head(list_t *list);
extern void list_delete_tail(list_t *list);
/* Head/tail lookup */
extern void *list_get_head(list_t *);
extern void *list_get_tail(list_t *);
extern void *list_get_head(list_t *list);
extern void *list_get_tail(list_t *list);
/* Fast list deletion */
extern void list_delete_list(list_t *);
extern void list_delete_list(list_t *list);
/* Traversing */
extern void list_foreach(list_t *, list_action_t);
extern void list_foreach_node(list_t *, list_action_node_t);
extern void list_foreach(list_t *list, list_action_t action);
extern void list_foreach_node(list_t *list, list_action_node_t action);
/*
Iterates over a list.
@ -87,4 +87,4 @@ extern void list_foreach_node(list_t *, list_action_node_t);
*/
#define list_each(type, item, list) (type *item = (type *)1; item; item = NULL) for(list_node_t *node = (list)->head, *next; item = node ? node->data : NULL, next = node ? node->next : NULL, node; node = next)
#endif /* __TINC_LIST_H__ */
#endif

View file

@ -45,40 +45,48 @@ static void real_logger(int level, int priority, const char *message) {
static bool suppress = false;
// Bail out early if there is nothing to do.
if(suppress)
if(suppress) {
return;
}
if(!logcontrol && (level > debug_level || logmode == LOGMODE_NULL))
if(!logcontrol && (level > debug_level || logmode == LOGMODE_NULL)) {
return;
}
if(level <= debug_level) {
switch(logmode) {
case LOGMODE_STDERR:
fprintf(stderr, "%s\n", message);
fflush(stderr);
break;
case LOGMODE_FILE:
if(!now.tv_sec)
gettimeofday(&now, NULL);
time_t now_sec = now.tv_sec;
strftime(timestr, sizeof timestr, "%Y-%m-%d %H:%M:%S", localtime(&now_sec));
fprintf(logfile, "%s %s[%ld]: %s\n", timestr, logident, (long)logpid, message);
fflush(logfile);
break;
case LOGMODE_SYSLOG:
case LOGMODE_STDERR:
fprintf(stderr, "%s\n", message);
fflush(stderr);
break;
case LOGMODE_FILE:
if(!now.tv_sec) {
gettimeofday(&now, NULL);
}
time_t now_sec = now.tv_sec;
strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", localtime(&now_sec));
fprintf(logfile, "%s %s[%ld]: %s\n", timestr, logident, (long)logpid, message);
fflush(logfile);
break;
case LOGMODE_SYSLOG:
#ifdef HAVE_MINGW
{
const char *messages[] = {message};
ReportEvent(loghandle, priority, 0, 0, NULL, 1, 0, messages, NULL);
}
{
const char *messages[] = {message};
ReportEvent(loghandle, priority, 0, 0, NULL, 1, 0, messages, NULL);
}
#else
#ifdef HAVE_SYSLOG_H
syslog(priority, "%s", message);
syslog(priority, "%s", message);
#endif
#endif
break;
case LOGMODE_NULL:
break;
break;
case LOGMODE_NULL:
break;
}
if(umbilical && do_detach) {
@ -90,16 +98,25 @@ static void real_logger(int level, int priority, const char *message) {
if(logcontrol) {
suppress = true;
logcontrol = false;
for list_each(connection_t, c, connection_list) {
if(!c->status.log)
if(!c->status.log) {
continue;
}
logcontrol = true;
if(level > (c->outcompression >= 0 ? c->outcompression : debug_level))
if(level > (c->outcompression >= 0 ? c->outcompression : debug_level)) {
continue;
}
int len = strlen(message);
if(send_request(c, "%d %d %d", CONTROL, REQ_LOG, len))
if(send_request(c, "%d %d %d", CONTROL, REQ_LOG, len)) {
send_meta(c, message, len);
}
}
suppress = false;
}
}
@ -109,31 +126,37 @@ void logger(int level, int priority, const char *format, ...) {
char message[1024] = "";
va_start(ap, format);
int len = vsnprintf(message, sizeof message, format, ap);
message[sizeof message - 1] = 0;
int len = vsnprintf(message, sizeof(message), format, ap);
message[sizeof(message) - 1] = 0;
va_end(ap);
if(len > 0 && len < sizeof message - 1 && message[len - 1] == '\n')
if(len > 0 && (size_t)len < sizeof(message) - 1 && message[len - 1] == '\n') {
message[len - 1] = 0;
}
real_logger(level, priority, message);
}
static void sptps_logger(sptps_t *s, int s_errno, const char *format, va_list ap) {
(void)s_errno;
char message[1024];
size_t msglen = sizeof message;
size_t msglen = sizeof(message);
int len = vsnprintf(message, msglen, format, ap);
message[sizeof message - 1] = 0;
if(len > 0 && len < sizeof message - 1) {
if(message[len - 1] == '\n')
message[sizeof(message) - 1] = 0;
if(len > 0 && (size_t)len < sizeof(message) - 1) {
if(message[len - 1] == '\n') {
message[--len] = 0;
}
// WARNING: s->handle can point to a connection_t or a node_t,
// but both types have the name and hostname fields at the same offsets.
connection_t *c = s->handle;
if(c)
snprintf(message + len, sizeof message - len, " from %s (%s)", c->name, c->hostname);
if(c) {
snprintf(message + len, sizeof(message) - len, " from %s (%s)", c->name, c->hostname);
}
}
real_logger(DEBUG_ALWAYS, LOG_ERR, message);
@ -144,51 +167,62 @@ void openlogger(const char *ident, logmode_t mode) {
logmode = mode;
switch(mode) {
case LOGMODE_STDERR:
logpid = getpid();
break;
case LOGMODE_FILE:
logpid = getpid();
logfile = fopen(logfilename, "a");
if(!logfile) {
fprintf(stderr, "Could not open log file %s: %s\n", logfilename, strerror(errno));
logmode = LOGMODE_NULL;
}
break;
case LOGMODE_SYSLOG:
case LOGMODE_STDERR:
logpid = getpid();
break;
case LOGMODE_FILE:
logpid = getpid();
logfile = fopen(logfilename, "a");
if(!logfile) {
fprintf(stderr, "Could not open log file %s: %s\n", logfilename, strerror(errno));
logmode = LOGMODE_NULL;
}
break;
case LOGMODE_SYSLOG:
#ifdef HAVE_MINGW
loghandle = RegisterEventSource(NULL, logident);
if(!loghandle) {
fprintf(stderr, "Could not open log handle!");
logmode = LOGMODE_NULL;
}
break;
loghandle = RegisterEventSource(NULL, logident);
if(!loghandle) {
fprintf(stderr, "Could not open log handle!\n");
logmode = LOGMODE_NULL;
}
break;
#else
#ifdef HAVE_SYSLOG_H
openlog(logident, LOG_CONS | LOG_PID, LOG_DAEMON);
break;
openlog(logident, LOG_CONS | LOG_PID, LOG_DAEMON);
break;
#endif
#endif
case LOGMODE_NULL:
break;
case LOGMODE_NULL:
break;
}
if(logmode != LOGMODE_NULL)
if(logmode != LOGMODE_NULL) {
sptps_log = sptps_logger;
else
} else {
sptps_log = sptps_log_quiet;
}
}
void reopenlogger() {
if(logmode != LOGMODE_FILE)
if(logmode != LOGMODE_FILE) {
return;
}
fflush(logfile);
FILE *newfile = fopen(logfilename, "a");
if(!newfile) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to reopen log file %s: %s", logfilename, strerror(errno));
return;
}
fclose(logfile);
logfile = newfile;
}
@ -196,21 +230,23 @@ void reopenlogger() {
void closelogger(void) {
switch(logmode) {
case LOGMODE_FILE:
fclose(logfile);
break;
case LOGMODE_SYSLOG:
case LOGMODE_FILE:
fclose(logfile);
break;
case LOGMODE_SYSLOG:
#ifdef HAVE_MINGW
DeregisterEventSource(loghandle);
break;
DeregisterEventSource(loghandle);
break;
#else
#ifdef HAVE_SYSLOG_H
closelog();
break;
closelog();
break;
#endif
#endif
case LOGMODE_NULL:
case LOGMODE_STDERR:
break;
case LOGMODE_NULL:
case LOGMODE_STDERR:
break;
}
}

View file

@ -1,3 +1,6 @@
#ifndef TINC_LOGGER_H
#define TINC_LOGGER_H
/*
logger.h -- header file for logger.c
Copyright (C) 1998-2005 Ivo Timmermans
@ -18,9 +21,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_LOGGER_H__
#define __TINC_LOGGER_H__
typedef enum debug_t {
DEBUG_NOTHING = 0, /* Quiet mode, only show starting/stopping of the daemon */
DEBUG_ALWAYS = 0,
@ -70,9 +70,9 @@ enum {
extern int debug_level;
extern bool logcontrol;
extern int umbilical;
extern void openlogger(const char *, logmode_t);
extern void openlogger(const char *ident, logmode_t mode);
extern void reopenlogger(void);
extern void logger(int, int, const char *, ...) __attribute__ ((__format__(printf, 3, 4)));
extern void logger(int level, int priority, const char *format, ...) __attribute__((__format__(printf, 3, 4)));
extern void closelogger(void);
#endif /* __TINC_LOGGER_H__ */
#endif

View file

@ -35,6 +35,7 @@
#endif
bool send_meta_sptps(void *handle, uint8_t type, const void *buffer, size_t length) {
(void)type;
connection_t *c = handle;
if(!c) {
@ -48,23 +49,25 @@ bool send_meta_sptps(void *handle, uint8_t type, const void *buffer, size_t leng
return true;
}
bool send_meta(connection_t *c, const char *buffer, int length) {
bool send_meta(connection_t *c, const char *buffer, size_t length) {
if(!c) {
logger(DEBUG_ALWAYS, LOG_ERR, "send_meta() called with NULL pointer!");
abort();
}
logger(DEBUG_META, LOG_DEBUG, "Sending %d bytes of metadata to %s (%s)", length,
c->name, c->hostname);
logger(DEBUG_META, LOG_DEBUG, "Sending %lu bytes of metadata to %s (%s)", (unsigned long)length,
c->name, c->hostname);
if(c->protocol_minor >= 2)
if(c->protocol_minor >= 2) {
return sptps_send_record(&c->sptps, 0, buffer, length);
}
/* Add our data to buffer */
if(c->status.encryptout) {
#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;
@ -76,9 +79,10 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
if(!cipher_encrypt(c->outcipher, buffer, length, buffer_prepare(&c->outbuf, length), &outlen, false) || outlen != length) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while encrypting metadata to %s (%s)",
c->name, c->hostname);
c->name, c->hostname);
return false;
}
#endif
} else {
buffer_add(&c->outbuf, buffer, length);
@ -89,24 +93,25 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
return true;
}
void send_meta_raw(connection_t *c, const char *buffer, int length) {
void send_meta_raw(connection_t *c, const char *buffer, size_t length) {
if(!c) {
logger(DEBUG_ALWAYS, LOG_ERR, "send_meta() called with NULL pointer!");
abort();
}
logger(DEBUG_META, LOG_DEBUG, "Sending %d bytes of raw metadata to %s (%s)", length,
c->name, c->hostname);
logger(DEBUG_META, LOG_DEBUG, "Sending %lu bytes of raw metadata to %s (%s)", (unsigned long)length,
c->name, c->hostname);
buffer_add(&c->outbuf, buffer, length);
io_set(&c->io, IO_READ | IO_WRITE);
}
void broadcast_meta(connection_t *from, const char *buffer, int length) {
void broadcast_meta(connection_t *from, const char *buffer, size_t length) {
for list_each(connection_t, c, connection_list)
if(c != from && c->edge)
if(c != from && c->edge) {
send_meta(c, buffer, length);
}
}
bool receive_meta_sptps(void *handle, uint8_t type, const void *vdata, uint16_t length) {
@ -119,20 +124,24 @@ bool receive_meta_sptps(void *handle, uint8_t type, const void *vdata, uint16_t
}
if(type == SPTPS_HANDSHAKE) {
if(c->allow_request == ACK)
if(c->allow_request == ACK) {
return send_ack(c);
else
} else {
return true;
}
}
if(!data)
if(!data) {
return true;
}
/* Are we receiving a TCPpacket? */
if(c->tcplen) {
if(length != c->tcplen)
if(length != c->tcplen) {
return false;
}
receive_tcppacket(c, data, length);
c->tcplen = 0;
return true;
@ -140,8 +149,9 @@ bool receive_meta_sptps(void *handle, uint8_t type, const void *vdata, uint16_t
/* Change newline to null byte, just like non-SPTPS requests */
if(data[length - 1] == '\n')
if(data[length - 1] == '\n') {
((char *)data)[length - 1] = 0;
}
/* Otherwise we are waiting for a request */
@ -149,7 +159,7 @@ bool receive_meta_sptps(void *handle, uint8_t type, const void *vdata, uint16_t
}
bool receive_meta(connection_t *c) {
int inlen;
ssize_t inlen;
char inbuf[MAXBUFSIZE];
char *bufp = inbuf, *endp;
@ -164,22 +174,23 @@ bool receive_meta(connection_t *c) {
buffer_compact(&c->inbuf, MAXBUFSIZE);
if(sizeof inbuf <= c->inbuf.len) {
if(sizeof(inbuf) <= c->inbuf.len) {
logger(DEBUG_ALWAYS, LOG_ERR, "Input buffer full for %s (%s)", c->name, c->hostname);
return false;
}
inlen = recv(c->socket, inbuf, sizeof inbuf - c->inbuf.len, 0);
inlen = recv(c->socket, inbuf, sizeof(inbuf) - c->inbuf.len, 0);
if(inlen <= 0) {
if(!inlen || !sockerrno) {
logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection closed by %s (%s)",
c->name, c->hostname);
} else if(sockwouldblock(sockerrno))
c->name, c->hostname);
} else if(sockwouldblock(sockerrno)) {
return true;
else
} else
logger(DEBUG_ALWAYS, LOG_ERR, "Metadata socket read error for %s (%s): %s",
c->name, c->hostname, sockstrerror(sockerrno));
c->name, c->hostname, sockstrerror(sockerrno));
return false;
}
@ -187,15 +198,19 @@ bool receive_meta(connection_t *c) {
/* Are we receiving a SPTPS packet? */
if(c->sptpslen) {
int len = MIN(inlen, c->sptpslen - c->inbuf.len);
ssize_t len = MIN(inlen, c->sptpslen - c->inbuf.len);
buffer_add(&c->inbuf, bufp, len);
char *sptpspacket = buffer_read(&c->inbuf, c->sptpslen);
if(!sptpspacket)
return true;
if(!receive_tcppacket_sptps(c, sptpspacket, c->sptpslen))
if(!sptpspacket) {
return true;
}
if(!receive_tcppacket_sptps(c, sptpspacket, c->sptpslen)) {
return false;
}
c->sptpslen = 0;
bufp += len;
@ -204,9 +219,12 @@ bool receive_meta(connection_t *c) {
}
if(c->protocol_minor >= 2) {
int len = sptps_receive_data(&c->sptps, bufp, inlen);
if(!len)
size_t len = sptps_receive_data(&c->sptps, bufp, inlen);
if(!len) {
return false;
}
bufp += len;
inlen -= len;
continue;
@ -214,10 +232,12 @@ bool receive_meta(connection_t *c) {
if(!c->status.decryptin) {
endp = memchr(bufp, '\n', inlen);
if(endp)
if(endp) {
endp++;
else
} else {
endp = bufp + inlen;
}
buffer_add(&c->inbuf, bufp, endp - bufp);
@ -227,8 +247,9 @@ 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);
if((size_t)inlen > c->inbudget) {
logger(DEBUG_META, LOG_ERR, "Byte limit exceeded for decryption from %s (%s)", c->name, c->hostname);
return false;
} else {
c->inbudget -= inlen;
@ -236,9 +257,9 @@ bool receive_meta(connection_t *c) {
size_t outlen = inlen;
if(!cipher_decrypt(c->incipher, bufp, inlen, buffer_prepare(&c->inbuf, inlen), &outlen, false) || inlen != outlen) {
if(!cipher_decrypt(c->incipher, bufp, inlen, buffer_prepare(&c->inbuf, inlen), &outlen, false) || (size_t)inlen != outlen) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while decrypting metadata from %s (%s)",
c->name, c->hostname);
c->name, c->hostname);
return false;
}
@ -251,8 +272,10 @@ bool receive_meta(connection_t *c) {
if(c->tcplen) {
char *tcpbuffer = buffer_read(&c->inbuf, c->tcplen);
if(!tcpbuffer)
if(!tcpbuffer) {
break;
}
if(!c->node) {
if(c->outgoing && proxytype == PROXY_SOCKS4 && c->allow_request == ID) {
@ -267,14 +290,17 @@ bool receive_meta(connection_t *c) {
logger(DEBUG_CONNECTIONS, LOG_ERR, "Invalid response from proxy server");
return false;
}
if(tcpbuffer[1] == (char)0xff) {
logger(DEBUG_CONNECTIONS, LOG_ERR, "Proxy request rejected: unsuitable authentication method");
return false;
}
if(tcpbuffer[2] != 5) {
logger(DEBUG_CONNECTIONS, LOG_ERR, "Invalid response from proxy server");
return false;
}
if(tcpbuffer[3] == 0) {
logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Proxy request granted");
} else {
@ -300,10 +326,14 @@ bool receive_meta(connection_t *c) {
/* Otherwise we are waiting for a request */
char *request = buffer_readline(&c->inbuf);
if(request) {
bool result = receive_request(c, request);
if(!result)
if(!result) {
return false;
}
continue;
} else {
break;

View file

@ -1,3 +1,6 @@
#ifndef TINC_META_H
#define TINC_META_H
/*
meta.h -- header for meta.c
Copyright (C) 2000-2014 Guus Sliepen <guus@tinc-vpn.org>,
@ -18,16 +21,13 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_META_H__
#define __TINC_META_H__
#include "connection.h"
extern bool send_meta(struct connection_t *, const char *, int);
extern void send_meta_raw(struct connection_t *, const char *, int);
extern bool send_meta_sptps(void *, uint8_t, const void *, size_t);
extern bool receive_meta_sptps(void *, uint8_t, const void *, uint16_t);
extern void broadcast_meta(struct connection_t *, const char *, int);
extern bool receive_meta(struct connection_t *);
extern bool send_meta(struct connection_t *c, const char *buffer, size_t length);
extern void send_meta_raw(struct connection_t *c, const char *buffer, size_t length);
extern bool send_meta_sptps(void *handle, uint8_t type, const void *data, size_t length);
extern bool receive_meta_sptps(void *handle, uint8_t type, const void *data, uint16_t length);
extern void broadcast_meta(struct connection_t *from, const char *buffer, size_t length);
extern bool receive_meta(struct connection_t *c);
#endif /* __TINC_META_H__ */
#endif

View file

@ -1,3 +1,6 @@
#ifndef TINC_MINGW_COMMON_H
#define TINC_MINGW_COMMON_H
/*
* TAP-Win32 -- A kernel driver to provide virtual tap device functionality
* on Windows. Originally derived from the CIPE-Win32
@ -37,7 +40,7 @@
//=============
#define TAP_CONTROL_CODE(request,method) \
CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED)
#define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED)
@ -73,3 +76,5 @@
//=========================================================
#define TAP_COMPONENT_ID "tap0801"
#endif

View file

@ -43,22 +43,24 @@ static vpn_packet_t device_read_packet;
static vpn_packet_t device_write_packet;
char *device = NULL;
char *iface = NULL;
static char *device_info = NULL;
static const char *device_info = "Windows tap device";
extern char *myport;
static void device_issue_read() {
device_read_overlapped.Offset = 0;
device_read_overlapped.OffsetHigh = 0;
int status;
for (;;) {
for(;;) {
ResetEvent(device_read_overlapped.hEvent);
DWORD len;
status = ReadFile(device_handle, (void *)device_read_packet.data, MTU, &len, &device_read_overlapped);
if (!status) {
if (GetLastError() != ERROR_IO_PENDING)
if(!status) {
if(GetLastError() != ERROR_IO_PENDING)
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno));
device, strerror(errno));
break;
}
@ -69,12 +71,17 @@ static void device_issue_read() {
}
static void device_handle_read(void *data, int flags) {
ResetEvent(device_read_overlapped.hEvent);
DWORD len;
if (!GetOverlappedResult(device_handle, &device_read_overlapped, &len, FALSE)) {
if(!GetOverlappedResult(device_handle, &device_read_overlapped, &len, FALSE)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error getting read result from %s %s: %s", device_info,
device, strerror(errno));
device, strerror(errno));
if(GetLastError() != ERROR_IO_INCOMPLETE) {
/* Must reset event or it will keep firing. */
ResetEvent(device_read_overlapped.hEvent);
}
return;
}
@ -101,8 +108,9 @@ static bool setup_device(void) {
get_config_string(lookup_config(config_tree, "Device"), &device);
get_config_string(lookup_config(config_tree, "Interface"), &iface);
if(device && iface)
if(device && iface) {
logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: both Device and Interface specified, results may not be as expected");
}
/* Open registry and look for network adapters */
@ -111,44 +119,51 @@ static bool setup_device(void) {
return false;
}
for (i = 0; ; i++) {
len = sizeof adapterid;
if(RegEnumKeyEx(key, i, adapterid, &len, 0, 0, 0, NULL))
for(i = 0; ; i++) {
len = sizeof(adapterid);
if(RegEnumKeyEx(key, i, adapterid, &len, 0, 0, 0, NULL)) {
break;
}
/* Find out more about this adapter */
snprintf(regpath, sizeof regpath, "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapterid);
snprintf(regpath, sizeof(regpath), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapterid);
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2))
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2)) {
continue;
}
len = sizeof adaptername;
len = sizeof(adaptername);
err = RegQueryValueEx(key2, "Name", 0, 0, (LPBYTE)adaptername, &len);
RegCloseKey(key2);
if(err)
if(err) {
continue;
}
if(device) {
if(!strcmp(device, adapterid)) {
found = true;
break;
} else
} else {
continue;
}
}
if(iface) {
if(!strcmp(iface, adaptername)) {
found = true;
break;
} else
} else {
continue;
}
}
snprintf(tapname, sizeof tapname, USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
if(device_handle != INVALID_HANDLE_VALUE) {
found = true;
break;
@ -162,16 +177,18 @@ static bool setup_device(void) {
return false;
}
if(!device)
if(!device) {
device = xstrdup(adapterid);
}
if(!iface)
if(!iface) {
iface = xstrdup(adaptername);
}
/* Try to open the corresponding tap device */
if(device_handle == INVALID_HANDLE_VALUE) {
snprintf(tapname, sizeof tapname, USERMODEDEVICEDIR "%s" TAPSUFFIX, device);
snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, device);
device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
}
@ -185,23 +202,24 @@ static bool setup_device(void) {
{
ULONG info[3] = {0};
DWORD len;
if(!DeviceIoControl(device_handle, TAP_IOCTL_GET_VERSION, &info, sizeof info, &info, sizeof info, &len, NULL))
if(!DeviceIoControl(device_handle, TAP_IOCTL_GET_VERSION, &info, sizeof(info), &info, sizeof(info), &len, NULL)) {
logger(DEBUG_ALWAYS, LOG_WARNING, "Could not get version information from Windows tap device %s (%s): %s", device, iface, winerror(GetLastError()));
else {
} else {
logger(DEBUG_ALWAYS, LOG_INFO, "TAP-Windows driver version: %lu.%lu%s", info[0], info[1], info[2] ? " (DEBUG)" : "");
/* Warn if using >=9.21. This is because starting from 9.21, TAP-Win32 seems to use a different, less efficient write path. */
if(info[0] == 9 && info[1] >= 21)
logger(DEBUG_ALWAYS, LOG_WARNING,
"You are using the newer (>= 9.0.0.21, NDIS6) series of TAP-Win32 drivers. "
"Using these drivers with tinc is not recommanded as it can result in poor performance. "
"You might want to revert back to 9.0.0.9 instead.");
"You are using the newer (>= 9.0.0.21, NDIS6) series of TAP-Win32 drivers. "
"Using these drivers with tinc is not recommended as it can result in poor performance. "
"You might want to revert back to 9.0.0.9 instead.");
}
}
/* Get MAC address from tap device */
if(!DeviceIoControl(device_handle, TAP_IOCTL_GET_MAC, mymac.x, sizeof mymac.x, mymac.x, sizeof mymac.x, &len, 0)) {
if(!DeviceIoControl(device_handle, TAP_IOCTL_GET_MAC, mymac.x, sizeof(mymac.x), mymac.x, sizeof(mymac.x), &len, 0)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not get MAC address from Windows tap device %s (%s): %s", device, iface, winerror(GetLastError()));
return false;
}
@ -225,7 +243,7 @@ static void enable_device(void) {
ULONG status = 1;
DWORD len;
DeviceIoControl(device_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, sizeof status, &status, sizeof status, &len, NULL);
DeviceIoControl(device_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, sizeof(status), &status, sizeof(status), &len, NULL);
/* We don't use the write event directly, but GetOverlappedResult() does, internally. */
@ -240,7 +258,7 @@ static void disable_device(void) {
ULONG status = 0;
DWORD len;
DeviceIoControl(device_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, sizeof status, &status, sizeof status, &len, NULL);
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,
@ -257,19 +275,27 @@ static void close_device(void) {
before we close the event it's referencing. */
DWORD len;
if(!GetOverlappedResult(device_handle, &device_read_overlapped, &len, TRUE) && GetLastError() != ERROR_OPERATION_ABORTED)
if(!GetOverlappedResult(device_handle, &device_read_overlapped, &len, TRUE) && GetLastError() != ERROR_OPERATION_ABORTED) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not wait for %s %s read to cancel: %s", device_info, device, winerror(GetLastError()));
if(device_write_packet.len > 0 && !GetOverlappedResult(device_handle, &device_write_overlapped, &len, TRUE) && GetLastError() != ERROR_OPERATION_ABORTED)
}
if(device_write_packet.len > 0 && !GetOverlappedResult(device_handle, &device_write_overlapped, &len, TRUE) && GetLastError() != ERROR_OPERATION_ABORTED) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not wait for %s %s write to cancel: %s", device_info, device, winerror(GetLastError()));
}
device_write_packet.len = 0;
CloseHandle(device_read_overlapped.hEvent);
CloseHandle(device_write_overlapped.hEvent);
CloseHandle(device_handle); device_handle = INVALID_HANDLE_VALUE;
CloseHandle(device_handle);
device_handle = INVALID_HANDLE_VALUE;
free(device); device = NULL;
free(iface); iface = NULL;
free(device);
device = NULL;
free(iface);
iface = NULL;
device_info = NULL;
}
@ -281,7 +307,7 @@ static bool write_packet(vpn_packet_t *packet) {
DWORD outlen;
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s",
packet->len, device_info);
packet->len, device_info);
if(device_write_packet.len > 0) {
/* Make sure the previous write operation is finished before we start the next one;
@ -289,20 +315,28 @@ static bool write_packet(vpn_packet_t *packet) {
which according to MSDN is a no-no. */
if(!GetOverlappedResult(device_handle, &device_write_overlapped, &outlen, FALSE)) {
int log_level = (GetLastError() == ERROR_IO_INCOMPLETE) ? DEBUG_TRAFFIC : DEBUG_ALWAYS;
logger(log_level, LOG_ERR, "Error while checking previous write to %s %s: %s", device_info, device, winerror(GetLastError()));
return false;
if(GetLastError() != ERROR_IO_INCOMPLETE) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error completing previously queued write to %s %s: %s", device_info, device, winerror(GetLastError()));
} else {
logger(DEBUG_TRAFFIC, LOG_ERR, "Previous overlapped write to %s %s still in progress", device_info, device);
// drop this packet
return true;
}
}
}
/* Copy the packet, since the write operation might still be ongoing after we return. */
memcpy(&device_write_packet, packet, sizeof *packet);
memcpy(&device_write_packet, packet, sizeof(*packet));
if(WriteFile(device_handle, DATA(&device_write_packet), device_write_packet.len, &outlen, &device_write_overlapped))
ResetEvent(device_write_overlapped.hEvent);
if(WriteFile(device_handle, DATA(&device_write_packet), device_write_packet.len, &outlen, &device_write_overlapped)) {
// Write was completed immediately.
device_write_packet.len = 0;
else if (GetLastError() != ERROR_IO_PENDING) {
} else if(GetLastError() != ERROR_IO_PENDING) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info, device, winerror(GetLastError()));
device_write_packet.len = 0;
return false;
}

View file

@ -29,10 +29,10 @@
#include "route.h"
#include "xalloc.h"
static char *device_info;
static const char *device_info = "multicast socket";
static struct addrinfo *ai = NULL;
static mac_t ignore_src = {{0}};
static mac_t ignore_src = {0};
static bool setup_device(void) {
char *host = NULL;
@ -40,8 +40,6 @@ static bool setup_device(void) {
char *space;
int ttl = 1;
device_info = "multicast socket";
get_config_string(lookup_config(config_tree, "Interface"), &iface);
if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
@ -51,6 +49,7 @@ static bool setup_device(void) {
host = xstrdup(device);
space = strchr(host, ' ');
if(!space) {
logger(DEBUG_ALWAYS, LOG_ERR, "Port number required for %s", device_info);
goto error;
@ -66,10 +65,13 @@ static bool setup_device(void) {
}
ai = str2addrinfo(host, port, SOCK_DGRAM);
if(!ai)
if(!ai) {
goto error;
}
device_fd = socket(ai->ai_family, SOCK_DGRAM, IPPROTO_UDP);
if(device_fd < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Creating socket failed: %s", sockstrerror(sockerrno));
goto error;
@ -80,7 +82,7 @@ static bool setup_device(void) {
#endif
static const int one = 1;
setsockopt(device_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof one);
setsockopt(device_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one));
if(bind(device_fd, ai->ai_addr, ai->ai_addrlen)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to %s %s: %s", host, port, sockstrerror(sockerrno));
@ -89,48 +91,56 @@ static bool setup_device(void) {
switch(ai->ai_family) {
#ifdef IP_ADD_MEMBERSHIP
case AF_INET: {
struct ip_mreq mreq;
struct sockaddr_in in;
memcpy(&in, ai->ai_addr, sizeof in);
mreq.imr_multiaddr.s_addr = in.sin_addr.s_addr;
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if(setsockopt(device_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof mreq)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Cannot join multicast group %s %s: %s", host, port, sockstrerror(sockerrno));
goto error;
}
case AF_INET: {
struct ip_mreq mreq;
struct sockaddr_in in;
memcpy(&in, ai->ai_addr, sizeof(in));
mreq.imr_multiaddr.s_addr = in.sin_addr.s_addr;
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if(setsockopt(device_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof(mreq))) {
logger(DEBUG_ALWAYS, LOG_ERR, "Cannot join multicast group %s %s: %s", host, port, sockstrerror(sockerrno));
goto error;
}
#ifdef IP_MULTICAST_LOOP
setsockopt(device_fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const void *)&one, sizeof one);
setsockopt(device_fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const void *)&one, sizeof(one));
#endif
#ifdef IP_MULTICAST_TTL
setsockopt(device_fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&ttl, sizeof ttl);
setsockopt(device_fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&ttl, sizeof(ttl));
#endif
} break;
}
break;
#endif
#ifdef IPV6_JOIN_GROUP
case AF_INET6: {
struct ipv6_mreq mreq;
struct sockaddr_in6 in6;
memcpy(&in6, ai->ai_addr, sizeof in6);
memcpy(&mreq.ipv6mr_multiaddr, &in6.sin6_addr, sizeof mreq.ipv6mr_multiaddr);
mreq.ipv6mr_interface = in6.sin6_scope_id;
if(setsockopt(device_fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, (void *)&mreq, sizeof mreq)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Cannot join multicast group %s %s: %s", host, port, sockstrerror(sockerrno));
goto error;
}
case AF_INET6: {
struct ipv6_mreq mreq;
struct sockaddr_in6 in6;
memcpy(&in6, ai->ai_addr, sizeof(in6));
memcpy(&mreq.ipv6mr_multiaddr, &in6.sin6_addr, sizeof(mreq.ipv6mr_multiaddr));
mreq.ipv6mr_interface = in6.sin6_scope_id;
if(setsockopt(device_fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, (void *)&mreq, sizeof(mreq))) {
logger(DEBUG_ALWAYS, LOG_ERR, "Cannot join multicast group %s %s: %s", host, port, sockstrerror(sockerrno));
goto error;
}
#ifdef IPV6_MULTICAST_LOOP
setsockopt(device_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (const void *)&one, sizeof one);
setsockopt(device_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (const void *)&one, sizeof(one));
#endif
#ifdef IPV6_MULTICAST_HOPS
setsockopt(device_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (void *)&ttl, sizeof ttl);
setsockopt(device_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (void *)&ttl, sizeof(ttl));
#endif
} break;
}
break;
#endif
default:
logger(DEBUG_ALWAYS, LOG_ERR, "Multicast for address family %x unsupported", ai->ai_family);
goto error;
default:
logger(DEBUG_ALWAYS, LOG_ERR, "Multicast for address family %x unsupported", ai->ai_family);
goto error;
}
logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
@ -138,24 +148,34 @@ static bool setup_device(void) {
return true;
error:
if(device_fd >= 0)
if(device_fd >= 0) {
closesocket(device_fd);
if(ai)
}
if(ai) {
freeaddrinfo(ai);
}
free(host);
return false;
}
static void close_device(void) {
close(device_fd); device_fd = -1;
close(device_fd);
device_fd = -1;
free(device); device = NULL;
free(iface); iface = NULL;
free(device);
device = NULL;
free(iface);
iface = NULL;
if(ai) {
freeaddrinfo(ai); ai = NULL;
freeaddrinfo(ai);
ai = NULL;
}
device_info = NULL;
}
@ -164,11 +184,11 @@ static bool read_packet(vpn_packet_t *packet) {
if((lenin = recv(device_fd, (void *)DATA(packet), MTU, 0)) <= 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, sockstrerror(sockerrno));
device, sockstrerror(sockerrno));
return false;
}
if(!memcmp(&ignore_src, DATA(packet) + 6, sizeof ignore_src)) {
if(!memcmp(&ignore_src, DATA(packet) + 6, sizeof(ignore_src))) {
logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Ignoring loopback packet of %d bytes from %s", lenin, device_info);
return false;
}
@ -176,22 +196,22 @@ static bool read_packet(vpn_packet_t *packet) {
packet->len = lenin;
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len,
device_info);
device_info);
return true;
}
static bool write_packet(vpn_packet_t *packet) {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s",
packet->len, device_info);
packet->len, device_info);
if(sendto(device_fd, (void *)DATA(packet), packet->len, 0, ai->ai_addr, ai->ai_addrlen) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
sockstrerror(sockerrno));
sockstrerror(sockerrno));
return false;
}
memcpy(&ignore_src, DATA(packet) + 6, sizeof ignore_src);
memcpy(&ignore_src, DATA(packet) + 6, sizeof(ignore_src));
return true;
}

View file

@ -42,91 +42,120 @@ void make_names(bool daemon) {
#ifdef HAVE_MINGW
HKEY key;
char installdir[1024] = "";
DWORD len = sizeof installdir;
DWORD len = sizeof(installdir);
#endif
confbase_given = confbase;
if(netname && confbase)
if(netname && confbase) {
logger(DEBUG_ALWAYS, LOG_INFO, "Both netname and configuration directory given, using the latter...");
}
if(netname)
if(netname) {
xasprintf(&identname, "tinc.%s", netname);
else
} else {
identname = xstrdup("tinc");
}
#ifdef HAVE_MINGW
if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\tinc", 0, KEY_READ, &key)) {
if(!RegQueryValueEx(key, NULL, 0, 0, (LPBYTE)installdir, &len)) {
confdir = xstrdup(installdir);
if(!confbase) {
if(netname)
if(netname) {
xasprintf(&confbase, "%s" SLASH "%s", installdir, netname);
else
} else {
xasprintf(&confbase, "%s", installdir);
}
}
if(!logfilename)
if(!logfilename) {
xasprintf(&logfilename, "%s" SLASH "tinc.log", confbase);
}
}
RegCloseKey(key);
}
#endif
if(!confdir)
if(!confdir) {
confdir = xstrdup(CONFDIR SLASH "tinc");
}
if(!confbase) {
if(netname)
if(netname) {
xasprintf(&confbase, CONFDIR SLASH "tinc" SLASH "%s", netname);
else
} else {
xasprintf(&confbase, CONFDIR SLASH "tinc");
}
}
#ifdef HAVE_MINGW
if(!logfilename)
xasprintf(&logfilename, "%s" SLASH "log", confbase);
if(!pidfilename)
if(!logfilename) {
xasprintf(&logfilename, "%s" SLASH "log", confbase);
}
if(!pidfilename) {
xasprintf(&pidfilename, "%s" SLASH "pid", confbase);
}
#else
bool fallback = false;
if(daemon) {
if(access(LOCALSTATEDIR, R_OK | W_OK | X_OK))
if(access(LOCALSTATEDIR, R_OK | W_OK | X_OK)) {
fallback = true;
}
} else {
char fname[PATH_MAX];
snprintf(fname, sizeof fname, LOCALSTATEDIR SLASH "run" SLASH "%s.pid", identname);
snprintf(fname, sizeof(fname), LOCALSTATEDIR SLASH "run" SLASH "%s.pid", identname);
if(access(fname, R_OK)) {
snprintf(fname, sizeof fname, "%s" SLASH "pid", confbase);
if(!access(fname, R_OK))
snprintf(fname, sizeof(fname), "%s" SLASH "pid", confbase);
if(!access(fname, R_OK)) {
fallback = true;
}
}
}
if(!fallback) {
if(!logfilename)
if(!logfilename) {
xasprintf(&logfilename, LOCALSTATEDIR SLASH "log" SLASH "%s.log", identname);
if(!pidfilename)
xasprintf(&pidfilename, LOCALSTATEDIR SLASH "run" SLASH "%s.pid", identname);
} else {
if(!logfilename)
xasprintf(&logfilename, "%s" SLASH "log", confbase);
}
if(!pidfilename) {
if(daemon)
xasprintf(&pidfilename, LOCALSTATEDIR SLASH "run" SLASH "%s.pid", identname);
}
} else {
if(!logfilename) {
xasprintf(&logfilename, "%s" SLASH "log", confbase);
}
if(!pidfilename) {
if(daemon) {
logger(DEBUG_ALWAYS, LOG_WARNING, "Could not access " LOCALSTATEDIR SLASH " (%s), storing pid and socket files in %s" SLASH, strerror(errno), confbase);
}
xasprintf(&pidfilename, "%s" SLASH "pid", confbase);
}
}
#endif
if(!unixsocketname) {
int len = strlen(pidfilename);
unixsocketname = xmalloc(len + 8);
memcpy(unixsocketname, pidfilename, len);
if(len > 4 && !strcmp(pidfilename + len - 4, ".pid"))
if(len > 4 && !strcmp(pidfilename + len - 4, ".pid")) {
strncpy(unixsocketname + len - 4, ".socket", 8);
else
} else {
strncpy(unixsocketname + len, ".socket", 8);
}
}
}

View file

@ -1,3 +1,6 @@
#ifndef TINC_NAMES_H
#define TINC_NAMES_H
/*
names.h -- header for names.c
Copyright (C) 1998-2005 Ivo Timmermans
@ -18,9 +21,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_NAMES_H__
#define __TINC_NAMES_H__
extern char *confdir;
extern char *confbase;
extern bool confbase_given;
@ -35,4 +35,4 @@ extern char *program_name;
extern void make_names(bool daemon);
extern void free_names(void);
#endif /* __TINC_NAMES_H__ */
#endif

184
src/net.c
View file

@ -58,13 +58,17 @@ void purge(void) {
for splay_each(subnet_t, s, n->subnet_tree) {
send_del_subnet(everyone, s);
if(!strictsubnets)
if(!strictsubnets) {
subnet_del(n, s);
}
}
for splay_each(edge_t, e, n->edge_tree) {
if(!tunnelserver)
if(!tunnelserver) {
send_del_edge(everyone, e);
}
edge_del(e);
}
}
@ -75,16 +79,35 @@ void purge(void) {
for splay_each(node_t, n, node_tree) {
if(!n->status.reachable) {
for splay_each(edge_t, e, edge_weight_tree)
if(e->to == n)
if(e->to == n) {
return;
}
if(!autoconnect && (!strictsubnets || !n->subnet_tree->head))
/* in strictsubnets mode do not delete nodes with subnets */
{
node_del(n);
}
}
}
}
/* Put a misbehaving connection in the tarpit */
void tarpit(int fd) {
static int pits[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
static unsigned int next_pit = 0;
if(pits[next_pit] != -1) {
closesocket(pits[next_pit]);
}
pits[next_pit++] = fd;
if(next_pit >= sizeof pits / sizeof pits[0]) {
next_pit = 0;
}
}
/*
Terminate a connection:
- Mark it as inactive
@ -96,12 +119,14 @@ void terminate_connection(connection_t *c, bool report) {
logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Closing connection with %s (%s)", c->name, c->hostname);
if(c->node) {
if(c->node->connection == c)
if(c->node->connection == c) {
c->node->connection = NULL;
}
if(c->edge) {
if(report && !tunnelserver)
if(report && !tunnelserver) {
send_del_edge(everyone, c->edge);
}
edge_del(c->edge);
c->edge = NULL;
@ -115,9 +140,12 @@ void terminate_connection(connection_t *c, bool report) {
if(report && !c->node->status.reachable) {
edge_t *e;
e = lookup_edge(c->node, myself);
if(e) {
if(!tunnelserver)
if(!tunnelserver) {
send_del_edge(everyone, e);
}
edge_del(e);
}
}
@ -129,13 +157,15 @@ void terminate_connection(connection_t *c, bool report) {
/* Check if this was our outgoing connection */
if(outgoing)
if(outgoing) {
do_outgoing_connection(outgoing);
}
#ifndef HAVE_MINGW
/* Clean up dead proxy processes */
while(waitpid(-1, NULL, WNOHANG) > 0);
#endif
}
@ -152,37 +182,40 @@ static void timeout_handler(void *data) {
bool close_all_connections = false;
/*
timeout_handler will start after 30 seconds from start of tincd
hold information about the elapsed time since last time the handler
has been run
timeout_handler will start after 30 seconds from start of tincd
hold information about the elapsed time since last time the handler
has been run
*/
long sleep_time = now.tv_sec - last_periodic_run_time.tv_sec;
/*
It seems that finding sane default value is harder than expected
Since we send every second a UDP packet to make holepunching work
And default UDP state expire on firewalls is between 15-30 seconds
we drop all connections after 60 Seconds - UDPDiscoveryTimeout=30
by default
It seems that finding sane default value is harder than expected
Since we send every second a UDP packet to make holepunching work
And default UDP state expire on firewalls is between 15-30 seconds
we drop all connections after 60 Seconds - UDPDiscoveryTimeout=30
by default
*/
if (sleep_time > 2 * udp_discovery_timeout) {
if(sleep_time > 2 * udp_discovery_timeout) {
logger(DEBUG_ALWAYS, LOG_ERR, "Awaking from dead after %ld seconds of sleep", sleep_time);
/*
Do not send any packets to tinc after we wake up.
The other node probably closed our connection but we still
are holding context information to them. This may happen on
laptops or any other hardware which can be suspended for some time.
Sending any data to node that wasn't expecting it will produce
annoying and misleading errors on the other side about failed signature
verification and or about missing sptps context
Do not send any packets to tinc after we wake up.
The other node probably closed our connection but we still
are holding context information to them. This may happen on
laptops or any other hardware which can be suspended for some time.
Sending any data to node that wasn't expecting it will produce
annoying and misleading errors on the other side about failed signature
verification and or about missing sptps context
*/
close_all_connections = true;
}
last_periodic_run_time = now;
for list_each(connection_t, c, connection_list) {
// control connections (eg. tinc ctl) do not have any timeout
if(c->status.control)
if(c->status.control) {
continue;
}
if(close_all_connections) {
logger(DEBUG_ALWAYS, LOG_ERR, "Forcing connection close after sleep time %s (%s)", c->name, c->hostname);
@ -191,15 +224,18 @@ static void timeout_handler(void *data) {
}
// Bail out early if we haven't reached the ping timeout for this node yet
if(c->last_ping_time + pingtimeout > now.tv_sec)
if(c->last_ping_time + pingtimeout > now.tv_sec) {
continue;
}
// timeout during connection establishing
if(!c->edge) {
if(c->status.connecting)
if(c->status.connecting) {
logger(DEBUG_CONNECTIONS, LOG_WARNING, "Timeout while connecting to %s (%s)", c->name, c->hostname);
else
} else {
logger(DEBUG_CONNECTIONS, LOG_WARNING, "Timeout from %s (%s) during authentication", c->name, c->hostname);
c->status.tarpit = true;
}
terminate_connection(c, c->edge);
continue;
@ -216,11 +252,14 @@ static void timeout_handler(void *data) {
}
// check whether we need to send a new ping
if(c->last_ping_time + pinginterval <= now.tv_sec)
if(c->last_ping_time + pinginterval <= now.tv_sec) {
send_ping(c);
}
}
timeout_set(data, &(struct timeval){1, rand() % 100000});
timeout_set(data, &(struct timeval) {
1, rand() % 100000
});
}
static void periodic_handler(void *data) {
@ -231,14 +270,20 @@ static void periodic_handler(void *data) {
if(contradicting_del_edge > 100 && contradicting_add_edge > 100) {
logger(DEBUG_ALWAYS, LOG_WARNING, "Possible node with same Name as us! Sleeping %d seconds.", sleeptime);
nanosleep(&(struct timespec){sleeptime, 0}, NULL);
nanosleep(&(struct timespec) {
sleeptime, 0
}, NULL);
sleeptime *= 2;
if(sleeptime < 0)
if(sleeptime < 0) {
sleeptime = 3600;
}
} else {
sleeptime /= 2;
if(sleeptime < 10)
if(sleeptime < 10) {
sleeptime = 10;
}
}
contradicting_add_edge = 0;
@ -246,14 +291,21 @@ 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)
if(autoconnect && node_tree->count > 1) {
do_autoconnect();
}
timeout_set(data, &(struct timeval){5, rand() % 100000});
timeout_set(data, &(struct timeval) {
5, rand() % 100000
});
}
void handle_meta_connection_data(connection_t *c) {
if (!receive_meta(c)) {
if(!receive_meta(c)) {
if(!c->status.control) {
c->status.tarpit = true;
}
terminate_connection(c, c->edge);
return;
}
@ -268,8 +320,10 @@ static void sigterm_handler(void *data) {
static void sighup_handler(void *data) {
logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum));
reopenlogger();
if(reload_configuration())
if(reload_configuration()) {
exit(1);
}
}
static void sigalrm_handler(void *data) {
@ -293,8 +347,8 @@ int reload_configuration(void) {
read_config_options(config_tree, NULL);
snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, myself->name);
read_config_file(config_tree, fname);
snprintf(fname, sizeof(fname), "%s" SLASH "hosts" SLASH "%s", confbase, myself->name);
read_config_file(config_tree, fname, true);
/* Parse some options that are allowed to be changed while tinc is running */
@ -304,48 +358,60 @@ int reload_configuration(void) {
if(strictsubnets) {
for splay_each(subnet_t, subnet, subnet_tree)
if (subnet->owner)
if(subnet->owner) {
subnet->expires = 1;
}
}
for splay_each(node_t, n, node_tree)
for splay_each(node_t, n, node_tree) {
n->status.has_address = false;
}
load_all_nodes();
if(strictsubnets) {
for splay_each(subnet_t, subnet, subnet_tree) {
if (!subnet->owner)
if(!subnet->owner) {
continue;
}
if(subnet->expires == 1) {
send_del_subnet(everyone, subnet);
if(subnet->owner->status.reachable)
if(subnet->owner->status.reachable) {
subnet_update(subnet->owner, subnet, false);
}
subnet_del(subnet->owner, subnet);
} else if(subnet->expires == -1) {
subnet->expires = 0;
} else {
send_add_subnet(everyone, subnet);
if(subnet->owner->status.reachable)
if(subnet->owner->status.reachable) {
subnet_update(subnet->owner, subnet, true);
}
}
}
} else { /* Only read our own subnets back in */
for splay_each(subnet_t, subnet, myself->subnet_tree)
if(!subnet->expires)
if(!subnet->expires) {
subnet->expires = 1;
}
config_t *cfg = lookup_config(config_tree, "Subnet");
while(cfg) {
subnet_t *subnet, *s2;
if(!get_config_subnet(cfg, &subnet))
if(!get_config_subnet(cfg, &subnet)) {
continue;
}
if((s2 = lookup_subnet(myself, subnet))) {
if(s2->expires == 1)
if(s2->expires == 1) {
s2->expires = 0;
}
free_subnet(subnet);
} else {
@ -373,11 +439,13 @@ int reload_configuration(void) {
/* Close connections to hosts that have a changed or deleted host config file */
for list_each(connection_t, c, connection_list) {
if(c->status.control)
if(c->status.control) {
continue;
}
snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
snprintf(fname, sizeof(fname), "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
struct stat s;
if(stat(fname, &s) || s.st_mtime > last_config_check) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "Host config file of %s has been changed", c->name);
terminate_connection(c, c->edge);
@ -393,18 +461,24 @@ void retry(void) {
/* Reset the reconnection timers for all outgoing connections */
for list_each(outgoing_t, outgoing, outgoing_list) {
outgoing->timeout = 0;
if(outgoing->ev.cb)
timeout_set(&outgoing->ev, &(struct timeval){0, 0});
timeout_set(&outgoing->ev, &(struct timeval) {
0, 0
});
}
/* Check for outgoing connections that are in progress, and reset their ping timers */
for list_each(connection_t, c, connection_list) {
if(c->outgoing && !c->node)
if(c->outgoing && !c->node) {
c->last_ping_time = 0;
}
}
/* Kick the ping timeout handler */
timeout_set(&pingtimer, &(struct timeval){0, 0});
timeout_set(&pingtimer, &(struct timeval) {
0, 0
});
}
/*
@ -412,8 +486,12 @@ void retry(void) {
*/
int main_loop(void) {
last_periodic_run_time = now;
timeout_add(&pingtimer, timeout_handler, &pingtimer, &(struct timeval){pingtimeout, rand() % 100000});
timeout_add(&periodictimer, periodic_handler, &periodictimer, &(struct timeval){0, 0});
timeout_add(&pingtimer, timeout_handler, &pingtimer, &(struct timeval) {
pingtimeout, rand() % 100000
});
timeout_add(&periodictimer, periodic_handler, &periodictimer, &(struct timeval) {
0, 0
});
#ifndef HAVE_MINGW
signal_t sighup = {0};

View file

@ -1,3 +1,6 @@
#ifndef TINC_NET_H
#define TINC_NET_H
/*
net.h -- header for net.c
Copyright (C) 1998-2005 Ivo Timmermans
@ -18,9 +21,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_NET_H__
#define __TINC_NET_H__
#include "ipv6.h"
#include "cipher.h"
#include "digest.h"
@ -56,7 +56,7 @@ typedef struct node_id_t {
uint8_t x[6];
} node_id_t;
typedef short length_t;
typedef uint16_t length_t;
typedef uint32_t seqno_t;
#define AF_UNKNOWN 255
@ -74,9 +74,6 @@ typedef union sockaddr_t {
struct sockaddr_in in;
struct sockaddr_in6 in6;
struct sockaddr_unknown unknown;
#ifdef HAVE_STRUCT_SOCKADDR_STORAGE
struct sockaddr_storage storage;
#endif
} sockaddr_t;
#ifdef SA_LEN
@ -122,13 +119,9 @@ typedef struct listen_socket_t {
#include "list.h"
typedef struct outgoing_t {
char *name;
struct node_t *node;
int timeout;
splay_tree_t *config_tree;
struct config_t *cfg;
struct addrinfo *ai; // addresses from config files
struct addrinfo *aip;
struct addrinfo *kai; // addresses known via other online nodes (use free_known_addresses())
struct address_cache_t *address_cache;
timeout_t ev;
} outgoing_t;
@ -155,6 +148,7 @@ extern int keylifetime;
extern int udp_rcvbuf;
extern int udp_sndbuf;
extern int max_connection_burst;
extern int fwmark;
extern bool do_prune;
extern char *myport;
extern bool device_standby;
@ -185,44 +179,45 @@ extern char *scriptextension;
#include "connection.h"
#include "node.h"
extern void retry_outgoing(outgoing_t *);
extern void handle_incoming_vpn_data(void *, int);
extern void finish_connecting(struct connection_t *);
extern bool do_outgoing_connection(struct outgoing_t *);
extern void handle_new_meta_connection(void *, int);
extern void handle_new_unix_connection(void *, int);
extern int setup_listen_socket(const sockaddr_t *);
extern int setup_vpn_in_socket(const sockaddr_t *);
extern void retry_outgoing(outgoing_t *outgoing);
extern void handle_incoming_vpn_data(void *data, int flags);
extern void finish_connecting(struct connection_t *c);
extern bool do_outgoing_connection(struct outgoing_t *outgoing);
extern void handle_new_meta_connection(void *data, int flags);
extern void handle_new_unix_connection(void *data, int flags);
extern int setup_listen_socket(const sockaddr_t *sa);
extern int setup_vpn_in_socket(const sockaddr_t *sa);
extern bool send_sptps_data(node_t *to, node_t *from, int type, const void *data, size_t len);
extern bool receive_sptps_record(void *handle, uint8_t type, const void *data, uint16_t len);
extern void send_packet(struct node_t *, vpn_packet_t *);
extern void receive_tcppacket(struct connection_t *, const char *, int);
extern bool receive_tcppacket_sptps(struct connection_t *, const char *, int);
extern void broadcast_packet(const struct node_t *, vpn_packet_t *);
extern void send_packet(struct node_t *n, vpn_packet_t *packet);
extern void receive_tcppacket(struct connection_t *c, const char *buffer, size_t length);
extern bool receive_tcppacket_sptps(struct connection_t *c, const char *buffer, size_t length);
extern void broadcast_packet(const struct node_t *n, vpn_packet_t *packet);
extern char *get_name(void);
extern void device_enable(void);
extern void device_disable(void);
extern bool setup_myself_reloadable(void);
extern bool setup_network(void);
extern void setup_outgoing_connection(struct outgoing_t *);
extern void setup_outgoing_connection(struct outgoing_t *outgoing, bool verbose);
extern void try_outgoing_connections(void);
extern void close_network_connections(void);
extern int main_loop(void);
extern void terminate_connection(struct connection_t *, bool);
extern bool node_read_ecdsa_public_key(struct node_t *);
extern bool read_ecdsa_public_key(struct connection_t *);
extern bool read_rsa_public_key(struct connection_t *);
extern void handle_device_data(void *, int);
extern void handle_meta_connection_data(struct connection_t *);
extern void terminate_connection(struct connection_t *c, bool report);
extern bool node_read_ecdsa_public_key(struct node_t *n);
extern bool read_ecdsa_public_key(struct connection_t *c);
extern bool read_rsa_public_key(struct connection_t *c);
extern void handle_device_data(void *data, int flags);
extern void handle_meta_connection_data(struct connection_t *c);
extern void regenerate_key(void);
extern void purge(void);
extern void retry(void);
extern int reload_configuration(void);
extern void load_all_nodes(void);
extern void try_tx(struct node_t *n, bool);
extern void try_tx(struct node_t *n, bool mtu);
extern void tarpit(int fd);
#ifndef HAVE_MINGW
#define closesocket(s) close(s)
#endif
#endif /* __TINC_NET_H__ */
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -22,6 +22,7 @@
#include "system.h"
#include "address_cache.h"
#include "conf.h"
#include "connection.h"
#include "control_common.h"
@ -40,7 +41,8 @@ int maxtimeout = 900;
int seconds_till_retry = 5;
int udp_rcvbuf = 1024 * 1024;
int udp_sndbuf = 1024 * 1024;
int max_connection_burst = 100;
int max_connection_burst = 10;
int fwmark;
listen_socket_t listen_socket[MAXSOCKETS];
int listen_sockets;
@ -58,29 +60,39 @@ static void configure_tcp(connection_t *c) {
int flags = fcntl(c->socket, F_GETFL);
if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "fcntl for %s: %s", c->hostname, strerror(errno));
logger(DEBUG_ALWAYS, LOG_ERR, "fcntl for %s fd %d: %s", c->hostname, c->socket, strerror(errno));
}
#elif defined(WIN32)
unsigned long arg = 1;
if(ioctlsocket(c->socket, FIONBIO, &arg) != 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "ioctlsocket for %s: %s", c->hostname, sockstrerror(sockerrno));
logger(DEBUG_ALWAYS, LOG_ERR, "ioctlsocket for %s fd %d: %s", c->hostname, c->socket, sockstrerror(sockerrno));
}
#endif
#if defined(IPPROTO_TCP) && defined(TCP_NODELAY)
#if defined(TCP_NODELAY)
option = 1;
setsockopt(c->socket, IPPROTO_TCP, TCP_NODELAY, (void *)&option, sizeof option);
setsockopt(c->socket, IPPROTO_TCP, TCP_NODELAY, (void *)&option, sizeof(option));
#endif
#if defined(IPPROTO_IP) && defined(IP_TOS) && defined(IPTOS_LOWDELAY)
#if defined(IP_TOS) && defined(IPTOS_LOWDELAY)
option = IPTOS_LOWDELAY;
setsockopt(c->socket, IPPROTO_IP, IP_TOS, (void *)&option, sizeof option);
setsockopt(c->socket, IPPROTO_IP, IP_TOS, (void *)&option, sizeof(option));
#endif
#if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS) && defined(IPTOS_LOWDELAY)
#if defined(IPV6_TCLASS) && defined(IPTOS_LOWDELAY)
option = IPTOS_LOWDELAY;
setsockopt(c->socket, IPPROTO_IPV6, IPV6_TCLASS, (void *)&option, sizeof option);
setsockopt(c->socket, IPPROTO_IPV6, IPV6_TCLASS, (void *)&option, sizeof(option));
#endif
#if defined(SO_MARK)
if(fwmark) {
setsockopt(c->socket, SOL_SOCKET, SO_MARK, (void *)&fwmark, sizeof(fwmark));
}
#endif
}
@ -92,8 +104,9 @@ static bool bind_to_interface(int sd) {
int status;
#endif /* defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) */
if(!get_config_string (lookup_config (config_tree, "BindToInterface"), &iface))
if(!get_config_string(lookup_config(config_tree, "BindToInterface"), &iface)) {
return true;
}
#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
memset(&ifr, 0, sizeof(ifr));
@ -101,11 +114,13 @@ static bool bind_to_interface(int sd) {
ifr.ifr_ifrn.ifrn_name[IFNAMSIZ - 1] = 0;
status = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr));
if(status) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to interface %s: %s", iface,
sockstrerror(sockerrno));
sockstrerror(sockerrno));
return false;
}
#else /* if !defined(SOL_SOCKET) || !defined(SO_BINDTODEVICE) */
logger(DEBUG_ALWAYS, LOG_WARNING, "%s not supported on this platform", "BindToInterface");
#endif
@ -117,21 +132,28 @@ static bool bind_to_address(connection_t *c) {
int s = -1;
for(int i = 0; i < listen_sockets && listen_socket[i].bindto; i++) {
if(listen_socket[i].sa.sa.sa_family != c->address.sa.sa_family)
if(listen_socket[i].sa.sa.sa_family != c->address.sa.sa_family) {
continue;
if(s >= 0)
}
if(s >= 0) {
return false;
}
s = i;
}
if(s < 0)
if(s < 0) {
return false;
}
sockaddr_t sa = listen_socket[s].sa;
if(sa.sa.sa_family == AF_INET)
if(sa.sa.sa_family == AF_INET) {
sa.in.sin_port = 0;
else if(sa.sa.sa_family == AF_INET6)
} else if(sa.sa.sa_family == AF_INET6) {
sa.in6.sin6_port = 0;
}
if(bind(c->socket, &sa.sa, SALEN(sa.sa))) {
logger(DEBUG_CONNECTIONS, LOG_WARNING, "Can't bind outgoing socket: %s", sockstrerror(sockerrno));
@ -161,27 +183,42 @@ int setup_listen_socket(const sockaddr_t *sa) {
/* Optimize TCP settings */
option = 1;
setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof option);
setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option));
#if defined(IPV6_V6ONLY)
if(sa->sa.sa_family == AF_INET6) {
setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof(option));
}
#else
#warning IPV6_V6ONLY not defined
#endif
#if defined(SO_MARK)
if(fwmark) {
setsockopt(nfd, SOL_SOCKET, SO_MARK, (void *)&fwmark, sizeof(fwmark));
}
#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
if(sa->sa.sa_family == AF_INET6)
setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
#endif
if(get_config_string
(lookup_config(config_tree, "BindToInterface"), &iface)) {
(lookup_config(config_tree, "BindToInterface"), &iface)) {
#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
struct ifreq ifr;
memset(&ifr, 0, sizeof ifr);
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ);
ifr.ifr_ifrn.ifrn_name[IFNAMSIZ - 1] = 0;
if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof ifr)) {
if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr))) {
closesocket(nfd);
logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to interface %s: %s", iface,
sockstrerror(sockerrno));
sockstrerror(sockerrno));
return -1;
}
#else
logger(DEBUG_ALWAYS, LOG_WARNING, "%s not supported on this platform", "BindToInterface");
#endif
@ -227,13 +264,14 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) {
closesocket(nfd);
logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "fcntl",
strerror(errno));
strerror(errno));
return -1;
}
}
#elif defined(WIN32)
{
unsigned long arg = 1;
if(ioctlsocket(nfd, FIONBIO, &arg) != 0) {
closesocket(nfd);
logger(DEBUG_ALWAYS, LOG_ERR, "Call to `%s' failed: %s", "ioctlsocket", sockstrerror(sockerrno));
@ -243,49 +281,70 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
#endif
option = 1;
setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof option);
setsockopt(nfd, SOL_SOCKET, SO_BROADCAST, (void *)&option, sizeof option);
setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option));
setsockopt(nfd, SOL_SOCKET, SO_BROADCAST, (void *)&option, sizeof(option));
if(udp_rcvbuf && setsockopt(nfd, SOL_SOCKET, SO_RCVBUF, (void *)&udp_rcvbuf, sizeof(udp_rcvbuf)))
if(udp_rcvbuf && setsockopt(nfd, SOL_SOCKET, SO_RCVBUF, (void *)&udp_rcvbuf, sizeof(udp_rcvbuf))) {
logger(DEBUG_ALWAYS, LOG_WARNING, "Can't set UDP SO_RCVBUF to %i: %s", udp_rcvbuf, sockstrerror(sockerrno));
}
if(udp_sndbuf && setsockopt(nfd, SOL_SOCKET, SO_SNDBUF, (void *)&udp_sndbuf, sizeof(udp_sndbuf)))
if(udp_sndbuf && setsockopt(nfd, SOL_SOCKET, SO_SNDBUF, (void *)&udp_sndbuf, sizeof(udp_sndbuf))) {
logger(DEBUG_ALWAYS, LOG_WARNING, "Can't set UDP SO_SNDBUF to %i: %s", udp_sndbuf, sockstrerror(sockerrno));
}
#if defined(IPV6_V6ONLY)
if(sa->sa.sa_family == AF_INET6) {
setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof(option));
}
#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
if(sa->sa.sa_family == AF_INET6)
setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
#endif
#if defined(IP_DONTFRAG) && !defined(IP_DONTFRAGMENT)
#define IP_DONTFRAGMENT IP_DONTFRAG
#endif
#if defined(IPPROTO_IP) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
if(myself->options & OPTION_PMTU_DISCOVERY) {
option = IP_PMTUDISC_DO;
setsockopt(nfd, IPPROTO_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option));
}
#elif defined(IPPROTO_IP) && defined(IP_DONTFRAGMENT)
#elif defined(IP_DONTFRAGMENT)
if(myself->options & OPTION_PMTU_DISCOVERY) {
option = 1;
setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, (void *)&option, sizeof(option));
}
#endif
#if defined(IPPROTO_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
if(myself->options & OPTION_PMTU_DISCOVERY) {
option = IPV6_PMTUDISC_DO;
setsockopt(nfd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option));
}
#elif defined(IPPROTO_IPV6) && defined(IPV6_DONTFRAG)
#elif defined(IPV6_DONTFRAG)
if(myself->options & OPTION_PMTU_DISCOVERY) {
option = 1;
setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, (void *)&option, sizeof(option));
}
#endif
if (!bind_to_interface(nfd)) {
#if defined(SO_MARK)
if(fwmark) {
setsockopt(nfd, SOL_SOCKET, SO_MARK, (void *)&fwmark, sizeof(fwmark));
}
#endif
if(!bind_to_interface(nfd)) {
closesocket(nfd);
return -1;
}
@ -302,16 +361,19 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
} /* int setup_vpn_in_socket */
static void retry_outgoing_handler(void *data) {
setup_outgoing_connection(data);
setup_outgoing_connection(data, true);
}
void retry_outgoing(outgoing_t *outgoing) {
outgoing->timeout += 5;
if(outgoing->timeout > maxtimeout)
if(outgoing->timeout > maxtimeout) {
outgoing->timeout = maxtimeout;
}
timeout_add(&outgoing->ev, retry_outgoing_handler, outgoing, &(struct timeval){outgoing->timeout, rand() % 100000});
timeout_add(&outgoing->ev, retry_outgoing_handler, outgoing, &(struct timeval) {
outgoing->timeout, rand() % 100000
});
logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Trying to re-establish outgoing connection in %d seconds", outgoing->timeout);
}
@ -358,14 +420,19 @@ static void do_outgoing_pipe(connection_t *c, char *command) {
setenv("REMOTEPORT", port, true);
setenv("NODE", c->name, true);
setenv("NAME", myself->name, true);
if(netname)
if(netname) {
setenv("NETNAME", netname, true);
}
int result = system(command);
if(result < 0)
if(result < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not execute %s: %s", command, strerror(errno));
else if(result)
} else if(result) {
logger(DEBUG_ALWAYS, LOG_ERR, "%s exited with non-zero status %d", command, result);
}
exit(result);
#else
logger(DEBUG_ALWAYS, LOG_ERR, "Proxy type exec not supported on this platform!");
@ -374,10 +441,12 @@ static void do_outgoing_pipe(connection_t *c, char *command) {
}
static void handle_meta_write(connection_t *c) {
if(c->outbuf.len <= c->outbuf.offset)
if(c->outbuf.len <= c->outbuf.offset) {
return;
}
ssize_t outlen = send(c->socket, c->outbuf.data + c->outbuf.offset, c->outbuf.len - c->outbuf.offset, 0);
if(outlen <= 0) {
if(!sockerrno || sockerrno == EPIPE) {
logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection closed by %s (%s)", c->name, c->hostname);
@ -393,8 +462,10 @@ static void handle_meta_write(connection_t *c) {
}
buffer_read(&c->outbuf, outlen);
if(!c->outbuf.len)
if(!c->outbuf.len) {
io_set(&c->io, IO_READ);
}
}
static void handle_meta_io(void *data, int flags) {
@ -414,20 +485,25 @@ static void handle_meta_io(void *data, int flags) {
| Successful | (success) | (success) | (success) |
+------------+-----------+-------------+-----------+
*/
if (send(c->socket, NULL, 0, 0) != 0) {
if (sockwouldblock(sockerrno))
if(send(c->socket, NULL, 0, 0) != 0) {
if(sockwouldblock(sockerrno)) {
return;
}
int socket_error;
if (!socknotconn(sockerrno))
if(!socknotconn(sockerrno)) {
socket_error = sockerrno;
else {
socklen_t len = sizeof socket_error;
} else {
socklen_t len = sizeof(socket_error);
getsockopt(c->socket, SOL_SOCKET, SO_ERROR, (void *)&socket_error, &len);
}
if (socket_error) {
if(socket_error) {
logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Error while connecting to %s (%s): %s", c->name, c->hostname, sockstrerror(socket_error));
terminate_connection(c, false);
}
return;
}
@ -435,72 +511,33 @@ static void handle_meta_io(void *data, int flags) {
finish_connecting(c);
}
if(flags & IO_WRITE)
if(flags & IO_WRITE) {
handle_meta_write(c);
else
} else {
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;
const sockaddr_t *sa;
struct addrinfo *proxyai = NULL;
int result;
begin:
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);
return false;
}
sa = get_recent_address(outgoing->address_cache);
get_config_string(outgoing->cfg, &address);
space = strchr(address, ' ');
if(space) {
port = xstrdup(space + 1);
*space = 0;
} else {
if(!get_config_string(lookup_config(outgoing->config_tree, "Port"), &port))
port = xstrdup("655");
}
outgoing->ai = str2addrinfo(address, port, SOCK_STREAM);
free(address);
free(port);
outgoing->aip = outgoing->ai;
outgoing->cfg = lookup_config_next(outgoing->config_tree, outgoing->cfg);
}
if(!outgoing->aip) {
if(outgoing->ai)
freeaddrinfo(outgoing->ai);
outgoing->ai = NULL;
if(outgoing->kai)
free_known_addresses(outgoing->kai);
outgoing->kai = NULL;
goto begin;
if(!sa) {
logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not set up a meta connection to %s", outgoing->node->name);
retry_outgoing(outgoing);
return false;
}
connection_t *c = new_connection();
c->outgoing = outgoing;
memcpy(&c->address, outgoing->aip->ai_addr, outgoing->aip->ai_addrlen);
outgoing->aip = outgoing->aip->ai_next;
memcpy(&c->address, sa, SALEN(sa->sa));
c->hostname = sockaddr2hostname(&c->address);
logger(DEBUG_CONNECTIONS, LOG_INFO, "Trying to connect to %s (%s)", outgoing->name, c->hostname);
logger(DEBUG_CONNECTIONS, LOG_INFO, "Trying to connect to %s (%s)", outgoing->node->name, c->hostname);
if(!proxytype) {
c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
@ -509,10 +546,12 @@ begin:
do_outgoing_pipe(c, proxyhost);
} else {
proxyai = str2addrinfo(proxyhost, proxyport, SOCK_STREAM);
if(!proxyai) {
free_connection(c);
goto begin;
}
logger(DEBUG_CONNECTIONS, LOG_INFO, "Using proxy at %s port %s", proxyhost, proxyport);
c->socket = socket(proxyai->ai_family, SOCK_STREAM, IPPROTO_TCP);
configure_tcp(c);
@ -529,10 +568,13 @@ begin:
#endif
if(proxytype != PROXY_EXEC) {
#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
#if defined(IPV6_V6ONLY)
int option = 1;
if(c->address.sa.sa_family == AF_INET6)
setsockopt(c->socket, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
if(c->address.sa.sa_family == AF_INET6) {
setsockopt(c->socket, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof(option));
}
#endif
bind_to_interface(c->socket);
@ -546,14 +588,16 @@ begin:
} else if(proxytype == PROXY_EXEC) {
result = 0;
} else {
if(!proxyai)
if(!proxyai) {
abort();
}
result = connect(c->socket, proxyai->ai_addr, proxyai->ai_addrlen);
freeaddrinfo(proxyai);
}
if(result == -1 && !sockinprogress(sockerrno)) {
logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not connect to %s (%s): %s", outgoing->name, c->hostname, sockstrerror(sockerrno));
logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not connect to %s (%s): %s", outgoing->node->name, c->hostname, sockstrerror(sockerrno));
free_connection(c);
goto begin;
@ -563,7 +607,7 @@ begin:
c->last_ping_time = time(NULL);
c->status.connecting = true;
c->name = xstrdup(outgoing->name);
c->name = xstrdup(outgoing->node->name);
#ifndef DISABLE_LEGACY
c->outcipher = myself->connection->outcipher;
c->outdigest = myself->connection->outdigest;
@ -574,51 +618,20 @@ begin:
connection_add(c);
io_add(&c->io, handle_meta_io, c, c->socket, IO_READ|IO_WRITE);
io_add(&c->io, handle_meta_io, c, c->socket, IO_READ | IO_WRITE);
return true;
}
// Find edges pointing to this node, and use them to build a list of unique, known addresses.
static struct addrinfo *get_known_addresses(node_t *n) {
struct addrinfo *ai = NULL;
struct addrinfo *oai = NULL;
for splay_each(edge_t, e, n->edge_tree) {
if(!e->reverse)
continue;
bool found = false;
for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) {
if(!sockaddrcmp(&e->reverse->address, (sockaddr_t *)aip->ai_addr)) {
found = true;
break;
}
}
if(found)
continue;
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;
}
void setup_outgoing_connection(outgoing_t *outgoing) {
void setup_outgoing_connection(outgoing_t *outgoing, bool verbose) {
(void)verbose;
timeout_del(&outgoing->ev);
node_t *n = lookup_node(outgoing->name);
node_t *n = outgoing->node;
if(n->connection) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "Already connected to %s", n->name);
if(n && n->connection) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "Already connected to %s", outgoing->name);
if(!n->connection->outgoing) {
n->connection->outgoing = outgoing;
return;
@ -627,17 +640,8 @@ void setup_outgoing_connection(outgoing_t *outgoing) {
}
}
init_configuration(&outgoing->config_tree);
read_host_config(outgoing->config_tree, outgoing->name);
outgoing->cfg = lookup_config(outgoing->config_tree, "Address");
if(!outgoing->cfg) {
if(n)
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;
}
if(!outgoing->address_cache) {
outgoing->address_cache = open_address_cache(n);
}
do_outgoing_connection(outgoing);
@ -652,11 +656,12 @@ remove:
new connection
*/
void handle_new_meta_connection(void *data, int flags) {
(void)flags;
listen_socket_t *l = data;
connection_t *c;
sockaddr_t sa;
int fd;
socklen_t len = sizeof sa;
socklen_t len = sizeof(sa);
fd = accept(l->tcp.fd, &sa.sa, &len);
@ -670,49 +675,45 @@ void handle_new_meta_connection(void *data, int flags) {
// Check if we get many connections from the same host
static sockaddr_t prev_sa;
static int tarpit = -1;
if(tarpit >= 0) {
closesocket(tarpit);
tarpit = -1;
}
if(!sockaddrcmp_noport(&sa, &prev_sa)) {
static int samehost_burst;
static int samehost_burst_time;
if(now.tv_sec - samehost_burst_time > samehost_burst)
if(now.tv_sec - samehost_burst_time > samehost_burst) {
samehost_burst = 0;
else
} else {
samehost_burst -= now.tv_sec - samehost_burst_time;
}
samehost_burst_time = now.tv_sec;
samehost_burst++;
if(samehost_burst > max_connection_burst) {
tarpit = fd;
tarpit(fd);
return;
}
}
memcpy(&prev_sa, &sa, sizeof sa);
memcpy(&prev_sa, &sa, sizeof(sa));
// Check if we get many connections from different hosts
static int connection_burst;
static int connection_burst_time;
if(now.tv_sec - connection_burst_time > connection_burst)
if(now.tv_sec - connection_burst_time > connection_burst) {
connection_burst = 0;
else
} else {
connection_burst -= now.tv_sec - connection_burst_time;
}
connection_burst_time = now.tv_sec;
connection_burst++;
if(connection_burst >= max_connection_burst) {
connection_burst = max_connection_burst;
tarpit = fd;
tarpit(fd);
return;
}
@ -741,7 +742,6 @@ void handle_new_meta_connection(void *data, int flags) {
connection_add(c);
c->allow_request = ID;
send_id(c);
}
#ifndef HAVE_MINGW
@ -749,11 +749,12 @@ void handle_new_meta_connection(void *data, int flags) {
accept a new UNIX socket connection
*/
void handle_new_unix_connection(void *data, int flags) {
(void)flags;
io_t *io = data;
connection_t *c;
sockaddr_t sa;
int fd;
socklen_t len = sizeof sa;
socklen_t len = sizeof(sa);
fd = accept(io->fd, &sa.sa, &len);
@ -778,25 +779,15 @@ void handle_new_unix_connection(void *data, int flags) {
connection_add(c);
c->allow_request = ID;
send_id(c);
}
#endif
static void free_outgoing(outgoing_t *outgoing) {
timeout_del(&outgoing->ev);
if(outgoing->ai)
freeaddrinfo(outgoing->ai);
if(outgoing->kai)
free_known_addresses(outgoing->kai);
if(outgoing->config_tree)
exit_configuration(&outgoing->config_tree);
if(outgoing->name)
free(outgoing->name);
if(outgoing->address_cache) {
close_address_cache(outgoing->address_cache);
}
free(outgoing);
}
@ -807,8 +798,9 @@ void try_outgoing_connections(void) {
if(!outgoing_list) {
outgoing_list = list_alloc((list_action_t)free_outgoing);
} else {
for list_each(outgoing_t, outgoing, outgoing_list)
for list_each(outgoing_t, outgoing, outgoing_list) {
outgoing->timeout = -1;
}
}
/* Make sure there is one outgoing_t in the list for each ConnectTo. */
@ -819,8 +811,8 @@ void try_outgoing_connections(void) {
if(!check_id(name)) {
logger(DEBUG_ALWAYS, LOG_ERR,
"Invalid name for outgoing connection in %s line %d",
cfg->file, cfg->line);
"Invalid name for outgoing connection in %s line %d",
cfg->file, cfg->line);
free(name);
continue;
}
@ -833,7 +825,7 @@ void try_outgoing_connections(void) {
bool found = false;
for list_each(outgoing_t, outgoing, outgoing_list) {
if(!strcmp(outgoing->name, name)) {
if(!strcmp(outgoing->node->name, name)) {
found = true;
outgoing->timeout = 0;
break;
@ -841,10 +833,18 @@ void try_outgoing_connections(void) {
}
if(!found) {
outgoing_t *outgoing = xzalloc(sizeof *outgoing);
outgoing->name = name;
outgoing_t *outgoing = xzalloc(sizeof(*outgoing));
node_t *n = lookup_node(name);
if(!n) {
n = new_node();
n->name = xstrdup(name);
node_add(n);
}
outgoing->node = n;
list_insert_tail(outgoing_list, outgoing);
setup_outgoing_connection(outgoing);
setup_outgoing_connection(outgoing, true);
}
}
@ -861,6 +861,7 @@ void try_outgoing_connections(void) {
/* Delete outgoing_ts for which there is no ConnectTo. */
for list_each(outgoing_t, outgoing, outgoing_list)
if(outgoing->timeout == -1)
if(outgoing->timeout == -1) {
list_delete_node(outgoing_list, node);
}
}

View file

@ -54,7 +54,7 @@ struct addrinfo *str2addrinfo(const char *address, const char *service, int sock
sockaddr_t str2sockaddr(const char *address, const char *port) {
struct addrinfo *ai, hint = {0};
sockaddr_t result = {{0}};
sockaddr_t result = {0};
int err;
hint.ai_family = AF_UNSPEC;
@ -84,20 +84,28 @@ void sockaddr2str(const sockaddr_t *sa, char **addrstr, char **portstr) {
int err;
if(sa->sa.sa_family == AF_UNSPEC) {
if(addrstr)
if(addrstr) {
*addrstr = xstrdup("unspec");
if(portstr)
}
if(portstr) {
*portstr = xstrdup("unspec");
}
return;
} else if(sa->sa.sa_family == AF_UNKNOWN) {
if(addrstr)
if(addrstr) {
*addrstr = xstrdup(sa->unknown.address);
if(portstr)
}
if(portstr) {
*portstr = xstrdup(sa->unknown.port);
}
return;
}
err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof address, port, sizeof port, NI_NUMERICHOST | NI_NUMERICSERV);
err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV);
if(err) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while translating addresses: %s", err == EAI_SYSTEM ? strerror(errno) : gai_strerror(err));
@ -106,13 +114,17 @@ void sockaddr2str(const sockaddr_t *sa, char **addrstr, char **portstr) {
scopeid = strchr(address, '%');
if(scopeid)
*scopeid = '\0'; /* Descope. */
if(scopeid) {
*scopeid = '\0'; /* Descope. */
}
if(addrstr)
if(addrstr) {
*addrstr = xstrdup(address);
if(portstr)
}
if(portstr) {
*portstr = xstrdup(port);
}
}
char *sockaddr2hostname(const sockaddr_t *sa) {
@ -129,8 +141,9 @@ char *sockaddr2hostname(const sockaddr_t *sa) {
return str;
}
err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof address, port, sizeof port,
hostnames ? 0 : (NI_NUMERICHOST | NI_NUMERICSERV));
err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port),
hostnames ? 0 : (NI_NUMERICHOST | NI_NUMERICSERV));
if(err) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while looking up hostname: %s", err == EAI_SYSTEM ? strerror(errno) : gai_strerror(err));
}
@ -145,26 +158,27 @@ int sockaddrcmp_noport(const sockaddr_t *a, const sockaddr_t *b) {
result = a->sa.sa_family - b->sa.sa_family;
if(result)
if(result) {
return result;
}
switch (a->sa.sa_family) {
case AF_UNSPEC:
return 0;
switch(a->sa.sa_family) {
case AF_UNSPEC:
return 0;
case AF_UNKNOWN:
return strcmp(a->unknown.address, b->unknown.address);
case AF_UNKNOWN:
return strcmp(a->unknown.address, b->unknown.address);
case AF_INET:
return memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof(a->in.sin_addr));
case AF_INET:
return memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof(a->in.sin_addr));
case AF_INET6:
return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr));
case AF_INET6:
return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr));
default:
logger(DEBUG_ALWAYS, LOG_ERR, "sockaddrcmp() was called with unknown address family %d, exitting!",
a->sa.sa_family);
abort();
default:
logger(DEBUG_ALWAYS, LOG_ERR, "sockaddrcmp() was called with unknown address family %d, exitting!",
a->sa.sa_family);
abort();
}
}
@ -173,41 +187,45 @@ int sockaddrcmp(const sockaddr_t *a, const sockaddr_t *b) {
result = a->sa.sa_family - b->sa.sa_family;
if(result)
if(result) {
return result;
}
switch (a->sa.sa_family) {
case AF_UNSPEC:
return 0;
switch(a->sa.sa_family) {
case AF_UNSPEC:
return 0;
case AF_UNKNOWN:
result = strcmp(a->unknown.address, b->unknown.address);
case AF_UNKNOWN:
result = strcmp(a->unknown.address, b->unknown.address);
if(result)
return result;
if(result) {
return result;
}
return strcmp(a->unknown.port, b->unknown.port);
return strcmp(a->unknown.port, b->unknown.port);
case AF_INET:
result = memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof a->in.sin_addr);
case AF_INET:
result = memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof(a->in.sin_addr));
if(result)
return result;
if(result) {
return result;
}
return memcmp(&a->in.sin_port, &b->in.sin_port, sizeof a->in.sin_port);
return memcmp(&a->in.sin_port, &b->in.sin_port, sizeof(a->in.sin_port));
case AF_INET6:
result = memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof a->in6.sin6_addr);
case AF_INET6:
result = memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr));
if(result)
return result;
if(result) {
return result;
}
return memcmp(&a->in6.sin6_port, &b->in6.sin6_port, sizeof a->in6.sin6_port);
return memcmp(&a->in6.sin6_port, &b->in6.sin6_port, sizeof(a->in6.sin6_port));
default:
logger(DEBUG_ALWAYS, LOG_ERR, "sockaddrcmp() was called with unknown address family %d, exitting!",
a->sa.sa_family);
abort();
default:
logger(DEBUG_ALWAYS, LOG_ERR, "sockaddrcmp() was called with unknown address family %d, exitting!",
a->sa.sa_family);
abort();
}
}
@ -237,19 +255,25 @@ void sockaddrunmap(sockaddr_t *sa) {
void sockaddr_setport(sockaddr_t *sa, const char *port) {
uint16_t portnum = htons(atoi(port));
if(!portnum)
if(!portnum) {
return;
}
switch(sa->sa.sa_family) {
case AF_INET:
sa->in.sin_port = portnum;
break;
case AF_INET6:
sa->in6.sin6_port = portnum;
break;
case AF_UNKNOWN:
free(sa->unknown.port);
sa->unknown.port = xstrdup(port);
default:
return;
case AF_INET:
sa->in.sin_port = portnum;
break;
case AF_INET6:
sa->in6.sin6_port = portnum;
break;
case AF_UNKNOWN:
free(sa->unknown.port);
sa->unknown.port = xstrdup(port);
default:
return;
}
}

View file

@ -1,3 +1,6 @@
#ifndef TINC_NETUTL_H
#define TINC_NETUTL_H
/*
netutl.h -- header file for netutl.c
Copyright (C) 1998-2005 Ivo Timmermans
@ -18,22 +21,19 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_NETUTL_H__
#define __TINC_NETUTL_H__
#include "net.h"
extern bool hostnames;
extern struct addrinfo *str2addrinfo(const char *, const char *, int) __attribute__ ((__malloc__));
extern sockaddr_t str2sockaddr(const char *, const char *);
extern void sockaddr2str(const sockaddr_t *, char **, char **);
extern char *sockaddr2hostname(const sockaddr_t *) __attribute__ ((__malloc__));
extern int sockaddrcmp(const sockaddr_t *, const sockaddr_t *);
extern int sockaddrcmp_noport(const sockaddr_t *, const sockaddr_t *);
extern void sockaddrunmap(sockaddr_t *);
extern void sockaddrfree(sockaddr_t *);
extern void sockaddrcpy(sockaddr_t *, const sockaddr_t *);
extern void sockaddr_setport(sockaddr_t *, const char *);
extern struct addrinfo *str2addrinfo(const char *address, const char *service, int socktype) __attribute__((__malloc__));
extern sockaddr_t str2sockaddr(const char *address, const char *port);
extern void sockaddr2str(const sockaddr_t *sa, char **address, char **port);
extern char *sockaddr2hostname(const sockaddr_t *sa) __attribute__((__malloc__));
extern int sockaddrcmp(const sockaddr_t *a, const sockaddr_t *b);
extern int sockaddrcmp_noport(const sockaddr_t *a, const sockaddr_t *b);
extern void sockaddrunmap(sockaddr_t *sa);
extern void sockaddrfree(sockaddr_t *sa);
extern void sockaddrcpy(sockaddr_t *dest, const sockaddr_t *src);
extern void sockaddr_setport(sockaddr_t *sa, const char *port);
#endif /* __TINC_NETUTL_H__ */
#endif

View file

@ -20,6 +20,7 @@
#include "system.h"
#include "address_cache.h"
#include "control_common.h"
#include "hash.h"
#include "logger.h"
@ -48,8 +49,11 @@ static int node_id_compare(const node_t *a, const node_t *b) {
static int node_udp_compare(const node_t *a, const node_t *b) {
int result = sockaddrcmp(&a->address, &b->address);
if (result)
if(result) {
return result;
}
return (a->name && b->name) ? strcmp(a->name, b->name) : 0;
}
@ -66,23 +70,29 @@ void exit_nodes(void) {
}
node_t *new_node(void) {
node_t *n = xzalloc(sizeof *n);
node_t *n = xzalloc(sizeof(*n));
if(replaywin) {
n->late = xzalloc(replaywin);
}
if(replaywin) n->late = xzalloc(replaywin);
n->subnet_tree = new_subnet_tree();
n->edge_tree = new_edge_tree();
n->mtu = MTU;
n->maxmtu = MTU;
n->udp_ping_rtt = -1;
return n;
}
void free_node(node_t *n) {
if(n->subnet_tree)
if(n->subnet_tree) {
free_subnet_tree(n->subnet_tree);
}
if(n->edge_tree)
if(n->edge_tree) {
free_edge_tree(n->edge_tree);
}
sockaddrfree(&n->address);
@ -98,22 +108,21 @@ void free_node(node_t *n) {
timeout_del(&n->udp_ping_timeout);
if(n->hostname)
free(n->hostname);
free(n->hostname);
free(n->name);
free(n->late);
if(n->name)
free(n->name);
if(n->late)
free(n->late);
if(n->address_cache) {
close_address_cache(n->address_cache);
}
free(n);
}
void node_add(node_t *n) {
unsigned char buf[64];
sha512(n->name, strlen(n->name),buf);
memcpy(&n->id, buf, sizeof n->id);
sha512(n->name, strlen(n->name), buf);
memcpy(&n->id, buf, sizeof(n->id));
splay_insert(node_tree, n);
splay_insert(node_id_tree, n);
@ -122,18 +131,20 @@ void node_add(node_t *n) {
void node_del(node_t *n) {
splay_delete(node_udp_tree, n);
for splay_each(subnet_t, s, n->subnet_tree)
for splay_each(subnet_t, s, n->subnet_tree) {
subnet_del(n, s);
}
for splay_each(edge_t, e, n->edge_tree)
for splay_each(edge_t, e, n->edge_tree) {
edge_del(e);
}
splay_delete(node_id_tree, n);
splay_delete(node_tree, n);
}
node_t *lookup_node(char *name) {
node_t n = {NULL};
node_t n = {0};
n.name = name;
@ -161,12 +172,14 @@ void update_node_udp(node_t *n, const sockaddr_t *sa) {
if(sa) {
n->address = *sa;
n->sock = 0;
for(int i = 0; i < listen_sockets; i++) {
if(listen_socket[i].sa.sa.sa_family == sa->sa.sa_family) {
n->sock = i;
break;
}
}
splay_insert(node_udp_tree, n);
free(n->hostname);
n->hostname = sockaddr2hostname(&n->address);
@ -184,20 +197,24 @@ void update_node_udp(node_t *n, const sockaddr_t *sa) {
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)
char id[2 * sizeof(n->id) + 1];
for(size_t c = 0; c < sizeof(n->id); ++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 %d %d %d %ld", CONTROL, REQ_DUMP_NODES,
n->name, id, n->hostname ?: "unknown port unknown",
}
id[sizeof(id) - 1] = 0;
send_request(c, "%d %d %s %s %s %d %d %d %d %x %x %s %s %d %d %d %d %ld %d %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64, CONTROL, REQ_DUMP_NODES,
n->name, id, n->hostname ? n->hostname : "unknown port unknown",
#ifdef DISABLE_LEGACY
0, 0, 0,
0, 0, 0,
#else
cipher_get_nid(n->outcipher), digest_get_nid(n->outdigest), (int)digest_length(n->outdigest),
cipher_get_nid(n->outcipher), digest_get_nid(n->outdigest), (int)digest_length(n->outdigest),
#endif
n->outcompression, n->options, bitfield_to_int(&n->status, sizeof n->status),
n->nexthop ? n->nexthop->name : "-", n->via ? n->via->name ?: "-" : "-", n->distance,
n->mtu, n->minmtu, n->maxmtu, (long)n->last_state_change);
n->outcompression, n->options, bitfield_to_int(&n->status, sizeof(n->status)),
n->nexthop ? n->nexthop->name : "-", n->via && n->via->name ? n->via->name : "-", n->distance,
n->mtu, n->minmtu, n->maxmtu, (long)n->last_state_change, n->udp_ping_rtt,
n->in_packets, n->in_bytes, n->out_packets, n->out_bytes);
}
return send_request(c, "%d %d", CONTROL, REQ_DUMP_NODES);
@ -206,7 +223,7 @@ bool dump_nodes(connection_t *c) {
bool dump_traffic(connection_t *c) {
for splay_each(node_t, n, node_tree)
send_request(c, "%d %d %s %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64, CONTROL, REQ_DUMP_TRAFFIC,
n->name, n->in_packets, n->in_bytes, n->out_packets, n->out_bytes);
n->name, n->in_packets, n->in_bytes, n->out_packets, n->out_bytes);
return send_request(c, "%d %d", CONTROL, REQ_DUMP_TRAFFIC);
}

View file

@ -1,3 +1,6 @@
#ifndef TINC_NODE_H
#define TINC_NODE_H
/*
node.h -- header for node.c
Copyright (C) 2001-2013 Guus Sliepen <guus@tinc-vpn.org>,
@ -18,9 +21,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_NODE_H__
#define __TINC_NODE_H__
#include "splay_tree.h"
#include "cipher.h"
#include "connection.h"
@ -29,19 +29,19 @@
#include "subnet.h"
typedef struct node_status_t {
unsigned int unused_active:1; /* 1 if active (not used for nodes) */
unsigned int validkey:1; /* 1 if we currently have a valid key for him */
unsigned int waitingforkey:1; /* 1 if we already sent out a request */
unsigned int visited:1; /* 1 if this node has been visited by one of the graph algorithms */
unsigned int reachable:1; /* 1 if this node is reachable in the graph */
unsigned int indirect:1; /* 1 if this node is not directly reachable by us */
unsigned int sptps:1; /* 1 if this node supports SPTPS */
unsigned int udp_confirmed:1; /* 1 if the address is one that we received UDP traffic on */
unsigned int send_locally:1; /* 1 if the next UDP packet should be sent on the local network */
unsigned int udppacket:1; /* 1 if the most recently received packet was UDP */
unsigned int validkey_in:1; /* 1 if we have sent a valid key to him */
unsigned int has_address:1; /* 1 if we know an external address for this node */
unsigned int unused:20;
unsigned int unused_active: 1; /* 1 if active (not used for nodes) */
unsigned int validkey: 1; /* 1 if we currently have a valid key for him */
unsigned int waitingforkey: 1; /* 1 if we already sent out a request */
unsigned int visited: 1; /* 1 if this node has been visited by one of the graph algorithms */
unsigned int reachable: 1; /* 1 if this node is reachable in the graph */
unsigned int indirect: 1; /* 1 if this node is not directly reachable by us */
unsigned int sptps: 1; /* 1 if this node supports SPTPS */
unsigned int udp_confirmed: 1; /* 1 if the address is one that we received UDP traffic on */
unsigned int send_locally: 1; /* 1 if the next UDP packet should be sent on the local network */
unsigned int udppacket: 1; /* 1 if the most recently received packet was UDP */
unsigned int validkey_in: 1; /* 1 if we have sent a valid key to him */
unsigned int has_address: 1; /* 1 if we know an external address for this node */
unsigned int unused: 20;
} node_status_t;
typedef struct node_t {
@ -88,10 +88,11 @@ typedef struct node_t {
uint32_t prev_received_seqno;
uint32_t prev_received;
uint32_t farfuture; /* Packets in a row that have arrived from the far future */
unsigned char* late; /* Bitfield marking late packets */
unsigned char *late; /* Bitfield marking late packets */
struct timeval udp_reply_sent; /* Last time a (gratuitous) UDP probe reply was sent */
struct timeval udp_ping_sent; /* Last time a UDP probe was sent */
int udp_ping_rtt; /* Round trip time of UDP ping (in microseconds; or -1 if !status.udp_confirmed) */
timeout_t udp_ping_timeout; /* Ping timeout event */
struct timeval mtu_ping_sent; /* Last time a MTU probe was sent */
@ -99,7 +100,7 @@ typedef struct node_t {
struct timeval mtu_info_sent; /* Last time a MTU_INFO message was sent */
struct timeval udp_info_sent; /* Last time a UDP_INFO message was sent */
length_t maxrecentlen; /* Maximum size of recently received packets */
length_t maxrecentlen; /* Maximum size of recently received packets */
length_t mtu; /* Maximum size of packets to send to this node */
length_t minmtu; /* Probed minimum MTU */
@ -110,6 +111,8 @@ typedef struct node_t {
uint64_t in_bytes;
uint64_t out_packets;
uint64_t out_bytes;
struct address_cache_t *address_cache;
} node_t;
extern struct node_t *myself;
@ -117,15 +120,15 @@ extern splay_tree_t *node_tree;
extern void init_nodes(void);
extern void exit_nodes(void);
extern node_t *new_node(void) __attribute__ ((__malloc__));
extern void free_node(node_t *);
extern void node_add(node_t *);
extern void node_del(node_t *);
extern node_t *lookup_node(char *);
extern node_t *lookup_node_id(const node_id_t *);
extern node_t *lookup_node_udp(const sockaddr_t *);
extern bool dump_nodes(struct connection_t *);
extern bool dump_traffic(struct connection_t *);
extern void update_node_udp(node_t *, const sockaddr_t *);
extern node_t *new_node(void) __attribute__((__malloc__));
extern void free_node(node_t *n);
extern void node_add(node_t *n);
extern void node_del(node_t *n);
extern node_t *lookup_node(char *name);
extern node_t *lookup_node_id(const node_id_t *id);
extern node_t *lookup_node_udp(const sockaddr_t *sa);
extern bool dump_nodes(struct connection_t *c);
extern bool dump_traffic(struct connection_t *c);
extern void update_node_udp(node_t *n, const sockaddr_t *sa);
#endif /* __TINC_NODE_H__ */
#endif

Some files were not shown because too many files have changed in this diff Show more