Import Upstream version 1.1~pre17
This commit is contained in:
parent
bc8ca65653
commit
b511a112e6
216 changed files with 43313 additions and 18448 deletions
|
|
@ -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)
|
||||
|
|
|
|||
516
src/Makefile.in
516
src/Makefile.in
|
|
@ -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
277
src/address_cache.c
Normal 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
50
src/address_cache.h
Normal 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
|
||||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
422
src/bsd/device.c
422
src/bsd/device.c
|
|
@ -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;
|
||||
|
|
|
|||
213
src/bsd/tunemu.c
213
src/bsd/tunemu.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
18
src/buffer.c
18
src/buffer.c
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
18
src/buffer.h
18
src/buffer.h
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
31
src/cipher.h
31
src/cipher.h
|
|
@ -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
|
||||
|
||||
|
|
|
|||
186
src/conf.c
186
src/conf.c
|
|
@ -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");
|
||||
|
||||
|
|
|
|||
42
src/conf.h
42
src/conf.h
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
149
src/control.c
149
src/control.c
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
12
src/crypto.h
12
src/crypto.h
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
26
src/digest.h
26
src/digest.h
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
28
src/dropin.h
28
src/dropin.h
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
12
src/ecdh.h
12
src/ecdh.h
|
|
@ -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
|
||||
|
|
|
|||
18
src/ecdsa.h
18
src/ecdsa.h
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
2348
src/ed25519/fe.c
2348
src/ed25519/fe.c
File diff suppressed because it is too large
Load diff
|
|
@ -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) {
|
||||
|
|
|
|||
586
src/ed25519/ge.c
586
src/ed25519/ge.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
1484
src/ed25519/sc.c
1484
src/ed25519/sc.c
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
20
src/edge.c
20
src/edge.c
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
24
src/edge.h
24
src/edge.h
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
287
src/event.c
287
src/event.c
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
218
src/fsck.c
218
src/fsck.c
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
141
src/gcrypt/rsa.c
141
src/gcrypt/rsa.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
1313
src/getopt.c
1313
src/getopt.c
File diff suppressed because it is too large
Load diff
68
src/getopt.h
68
src/getopt.h
|
|
@ -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
|
||||
|
|
|
|||
180
src/getopt1.c
180
src/getopt1.c
|
|
@ -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 */
|
||||
|
|
|
|||
70
src/graph.c
70
src/graph.c
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
36
src/hash.c
36
src/hash.c
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
10
src/hash.h
10
src/hash.h
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
213
src/ifconfig.c
213
src/ifconfig.c
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
179
src/info.c
179
src/info.c
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
539
src/invitation.c
539
src/invitation.c
File diff suppressed because it is too large
Load diff
|
|
@ -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[]);
|
||||
|
||||
|
|
|
|||
20
src/ipv4.h
20
src/ipv4.h
|
|
@ -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
|
||||
|
|
|
|||
20
src/ipv6.h
20
src/ipv6.h
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
55
src/list.c
55
src/list.c
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
46
src/list.h
46
src/list.h
|
|
@ -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
|
||||
|
|
|
|||
178
src/logger.c
178
src/logger.c
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
12
src/logger.h
12
src/logger.h
|
|
@ -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
|
||||
|
|
|
|||
102
src/meta.c
102
src/meta.c
|
|
@ -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;
|
||||
|
|
|
|||
20
src/meta.h
20
src/meta.h
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
83
src/names.c
83
src/names.c
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
184
src/net.c
|
|
@ -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};
|
||||
|
|
|
|||
63
src/net.h
63
src/net.h
|
|
@ -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
|
||||
|
|
|
|||
633
src/net_packet.c
633
src/net_packet.c
File diff suppressed because it is too large
Load diff
483
src/net_setup.c
483
src/net_setup.c
File diff suppressed because it is too large
Load diff
385
src/net_socket.c
385
src/net_socket.c
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
146
src/netutl.c
146
src/netutl.c
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
28
src/netutl.h
28
src/netutl.h
|
|
@ -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
|
||||
|
|
|
|||
73
src/node.c
73
src/node.c
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
61
src/node.h
61
src/node.h
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue