Import Upstream version 1.1~pre12
This commit is contained in:
parent
1813f3157e
commit
aa10d88732
134 changed files with 8673 additions and 4989 deletions
111
src/Makefile.am
111
src/Makefile.am
|
|
@ -2,16 +2,25 @@
|
|||
|
||||
sbin_PROGRAMS = tincd tinc sptps_test sptps_keypair
|
||||
|
||||
## Make sure version.c is always rebuilt
|
||||
.PHONY: version.c
|
||||
version.c:
|
||||
CLEANFILES = version_git.h
|
||||
|
||||
.PHONY: version-stamp
|
||||
version-stamp:
|
||||
|
||||
version_git.h: version-stamp
|
||||
$(AM_V_GEN)echo >$@
|
||||
@-(cd $(srcdir) && git describe 2>/dev/null >/dev/null) && echo '#define GIT_DESCRIPTION "'`(cd $(srcdir) && git describe) | sed 's/release-//'`'"' >$@ ||:
|
||||
${srcdir}/version.c: version_git.h
|
||||
|
||||
## Now a hack to appease some versions of BSD make that don't understand that "./foo" is the same as "foo".
|
||||
if BSD
|
||||
version.c: ${srcdir}/version.c
|
||||
endif
|
||||
|
||||
if LINUX
|
||||
sbin_PROGRAMS += sptps_speed
|
||||
endif
|
||||
|
||||
DEFAULT_INCLUDES =
|
||||
|
||||
ed25519_SOURCES = \
|
||||
ed25519/add_scalar.c \
|
||||
ed25519/ed25519.h \
|
||||
|
|
@ -49,11 +58,6 @@ tincd_SOURCES = \
|
|||
edge.c edge.h \
|
||||
ethernet.h \
|
||||
event.c event.h \
|
||||
fake-gai-errnos.h \
|
||||
fake-getaddrinfo.c fake-getaddrinfo.h \
|
||||
fake-getnameinfo.c fake-getnameinfo.h \
|
||||
getopt.c getopt.h \
|
||||
getopt1.c \
|
||||
graph.c graph.h \
|
||||
hash.c hash.h \
|
||||
have.h \
|
||||
|
|
@ -92,13 +96,15 @@ tincd_SOURCES = \
|
|||
utils.c utils.h \
|
||||
xalloc.h \
|
||||
version.c version.h \
|
||||
ed25519/ecdh.c \
|
||||
ed25519/ecdsa.c \
|
||||
$(ed25519_SOURCES) \
|
||||
$(chacha_poly1305_SOURCES)
|
||||
|
||||
tinc_SOURCES = \
|
||||
dropin.c dropin.h \
|
||||
getopt.c getopt.h \
|
||||
getopt1.c \
|
||||
fsck.c fsck.h \
|
||||
ifconfig.c ifconfig.h \
|
||||
info.c info.h \
|
||||
invitation.c invitation.h \
|
||||
list.c list.h \
|
||||
|
|
@ -111,6 +117,9 @@ tinc_SOURCES = \
|
|||
top.c top.h \
|
||||
utils.c utils.h \
|
||||
version.c version.h \
|
||||
ed25519/ecdh.c \
|
||||
ed25519/ecdsa.c \
|
||||
ed25519/ecdsagen.c \
|
||||
$(ed25519_SOURCES) \
|
||||
$(chacha_poly1305_SOURCES)
|
||||
|
||||
|
|
@ -119,12 +128,15 @@ sptps_test_SOURCES = \
|
|||
sptps.c sptps.h \
|
||||
sptps_test.c \
|
||||
utils.c utils.h \
|
||||
ed25519/ecdh.c \
|
||||
ed25519/ecdsa.c \
|
||||
$(ed25519_SOURCES) \
|
||||
$(chacha_poly1305_SOURCES)
|
||||
|
||||
sptps_keypair_SOURCES = \
|
||||
sptps_keypair.c \
|
||||
utils.c utils.h \
|
||||
ed25519/ecdsagen.c \
|
||||
$(ed25519_SOURCES)
|
||||
|
||||
sptps_speed_SOURCES = \
|
||||
|
|
@ -132,11 +144,29 @@ sptps_speed_SOURCES = \
|
|||
sptps.c sptps.h \
|
||||
sptps_speed.c \
|
||||
utils.c utils.h \
|
||||
ed25519/ecdh.c \
|
||||
ed25519/ecdsa.c \
|
||||
ed25519/ecdsagen.c \
|
||||
$(ed25519_SOURCES) \
|
||||
$(chacha_poly1305_SOURCES)
|
||||
|
||||
## Conditionally compile device drivers
|
||||
|
||||
|
||||
if !GETOPT
|
||||
tincd_SOURCES += \
|
||||
getopt.c getopt.h \
|
||||
getopt1.c
|
||||
tinc_SOURCES += \
|
||||
getopt.c getopt.h \
|
||||
getopt1.c
|
||||
sptps_test_SOURCES += \
|
||||
getopt.c getopt.h \
|
||||
getopt1.c
|
||||
sptps_keypair_SOURCES += \
|
||||
getopt.c getopt.h \
|
||||
getopt1.c
|
||||
endif
|
||||
|
||||
if LINUX
|
||||
tincd_SOURCES += linux/device.c
|
||||
endif
|
||||
|
|
@ -173,54 +203,37 @@ tincd_SOURCES += \
|
|||
openssl/cipher.c \
|
||||
openssl/crypto.c \
|
||||
openssl/digest.c openssl/digest.h \
|
||||
ed25519/ecdh.c \
|
||||
ed25519/ecdsa.c \
|
||||
openssl/prf.c \
|
||||
openssl/rsa.c
|
||||
tinc_SOURCES += \
|
||||
openssl/cipher.c \
|
||||
openssl/crypto.c \
|
||||
openssl/digest.c openssl/digest.h \
|
||||
ed25519/ecdh.c \
|
||||
ed25519/ecdsa.c \
|
||||
ed25519/ecdsagen.c \
|
||||
openssl/prf.c \
|
||||
openssl/rsa.c \
|
||||
openssl/rsagen.c
|
||||
sptps_test_SOURCES += \
|
||||
openssl/crypto.c \
|
||||
openssl/digest.c openssl/digest.h \
|
||||
ed25519/ecdh.c \
|
||||
ed25519/ecdsa.c \
|
||||
openssl/prf.c
|
||||
sptps_keypair_SOURCES += \
|
||||
openssl/crypto.c \
|
||||
ed25519/ecdsagen.c
|
||||
openssl/crypto.c
|
||||
sptps_speed_SOURCES += \
|
||||
openssl/crypto.c \
|
||||
openssl/digest.c openssl/digest.h \
|
||||
ed25519/ecdh.c \
|
||||
ed25519/ecdsa.c \
|
||||
ed25519/ecdsagen.c \
|
||||
openssl/prf.c
|
||||
endif
|
||||
|
||||
else
|
||||
if GCRYPT
|
||||
tincd_SOURCES += \
|
||||
gcrypt/cipher.c \
|
||||
gcrypt/crypto.c \
|
||||
gcrypt/digest.c gcrypt/digest.h \
|
||||
gcrypt/ecdh.c \
|
||||
gcrypt/ecdsa.c \
|
||||
gcrypt/prf.c \
|
||||
gcrypt/rsa.c
|
||||
tinc_SOURCES += \
|
||||
gcrypt/cipher.c \
|
||||
gcrypt/crypto.c \
|
||||
gcrypt/digest.c gcrypt/digest.h \
|
||||
gcrypt/ecdh.c \
|
||||
gcrypt/ecdsa.c \
|
||||
gcrypt/ecdsagen.c \
|
||||
gcrypt/prf.c \
|
||||
gcrypt/rsa.c \
|
||||
gcrypt/rsagen.c
|
||||
|
|
@ -228,18 +241,44 @@ sptps_test_SOURCES += \
|
|||
gcrypt/cipher.c \
|
||||
gcrypt/crypto.c \
|
||||
gcrypt/digest.c gcrypt/digest.h \
|
||||
gcrypt/ecdh.c \
|
||||
gcrypt/ecdsa.c \
|
||||
gcrypt/prf.c
|
||||
sptps_keypair_SOURCES += \
|
||||
openssl/crypto.c
|
||||
sptps_speed_SOURCES += \
|
||||
openssl/crypto.c \
|
||||
openssl/digest.c openssl/digest.h \
|
||||
openssl/prf.c
|
||||
else
|
||||
tincd_SOURCES += \
|
||||
nolegacy/crypto.c \
|
||||
nolegacy/prf.c
|
||||
tinc_SOURCES += \
|
||||
nolegacy/crypto.c \
|
||||
nolegacy/prf.c
|
||||
sptps_test_SOURCES += \
|
||||
nolegacy/crypto.c \
|
||||
nolegacy/prf.c
|
||||
sptps_keypair_SOURCES += \
|
||||
nolegacy/crypto.c
|
||||
sptps_speed_SOURCES += \
|
||||
nolegacy/crypto.c \
|
||||
nolegacy/prf.c
|
||||
endif
|
||||
endif
|
||||
|
||||
if MINIUPNPC
|
||||
tincd_SOURCES += upnp.h upnp.c
|
||||
tincd_LDADD = $(MINIUPNPC_LIBS)
|
||||
tincd_LDFLAGS = -pthread
|
||||
endif
|
||||
|
||||
tinc_LDADD = $(READLINE_LIBS) $(CURSES_LIBS)
|
||||
sptps_speed_LDADD = -lrt
|
||||
|
||||
LIBS = @LIBS@
|
||||
LIBS = @LIBS@ -lm
|
||||
|
||||
if TUNEMU
|
||||
LIBS += -lpcap
|
||||
endif
|
||||
|
||||
AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\"
|
||||
AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\" -iquote.
|
||||
|
|
|
|||
511
src/Makefile.in
511
src/Makefile.in
|
|
@ -1,7 +1,7 @@
|
|||
# Makefile.in generated by automake 1.14.1 from Makefile.am.
|
||||
# Makefile.in generated by automake 1.15 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
|
@ -15,7 +15,17 @@
|
|||
@SET_MAKE@
|
||||
|
||||
VPATH = @srcdir@
|
||||
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
|
||||
am__is_gnu_make = { \
|
||||
if test -z '$(MAKELEVEL)'; then \
|
||||
false; \
|
||||
elif test -n '$(MAKE_HOST)'; then \
|
||||
true; \
|
||||
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||
true; \
|
||||
else \
|
||||
false; \
|
||||
fi; \
|
||||
}
|
||||
am__make_running_with_option = \
|
||||
case $${target_option-} in \
|
||||
?) ;; \
|
||||
|
|
@ -81,95 +91,120 @@ host_triplet = @host@
|
|||
sbin_PROGRAMS = tincd$(EXEEXT) tinc$(EXEEXT) sptps_test$(EXEEXT) \
|
||||
sptps_keypair$(EXEEXT) $(am__EXEEXT_1)
|
||||
@LINUX_TRUE@am__append_1 = sptps_speed
|
||||
@LINUX_TRUE@am__append_2 = linux/device.c
|
||||
@BSD_TRUE@am__append_3 = bsd/device.c
|
||||
@BSD_TRUE@@TUNEMU_TRUE@am__append_4 = bsd/tunemu.c bsd/tunemu.h
|
||||
@SOLARIS_TRUE@am__append_5 = solaris/device.c
|
||||
@MINGW_TRUE@am__append_6 = mingw/device.c mingw/common.h
|
||||
@CYGWIN_TRUE@am__append_7 = cygwin/device.c
|
||||
@UML_TRUE@am__append_8 = uml_device.c
|
||||
@VDE_TRUE@am__append_9 = vde_device.c
|
||||
@OPENSSL_TRUE@am__append_10 = \
|
||||
@GETOPT_FALSE@am__append_2 = \
|
||||
@GETOPT_FALSE@ getopt.c getopt.h \
|
||||
@GETOPT_FALSE@ getopt1.c
|
||||
|
||||
@GETOPT_FALSE@am__append_3 = \
|
||||
@GETOPT_FALSE@ getopt.c getopt.h \
|
||||
@GETOPT_FALSE@ getopt1.c
|
||||
|
||||
@GETOPT_FALSE@am__append_4 = \
|
||||
@GETOPT_FALSE@ getopt.c getopt.h \
|
||||
@GETOPT_FALSE@ getopt1.c
|
||||
|
||||
@GETOPT_FALSE@am__append_5 = \
|
||||
@GETOPT_FALSE@ getopt.c getopt.h \
|
||||
@GETOPT_FALSE@ getopt1.c
|
||||
|
||||
@LINUX_TRUE@am__append_6 = linux/device.c
|
||||
@BSD_TRUE@am__append_7 = bsd/device.c
|
||||
@BSD_TRUE@@TUNEMU_TRUE@am__append_8 = bsd/tunemu.c bsd/tunemu.h
|
||||
@SOLARIS_TRUE@am__append_9 = solaris/device.c
|
||||
@MINGW_TRUE@am__append_10 = mingw/device.c mingw/common.h
|
||||
@CYGWIN_TRUE@am__append_11 = cygwin/device.c
|
||||
@UML_TRUE@am__append_12 = uml_device.c
|
||||
@VDE_TRUE@am__append_13 = vde_device.c
|
||||
@OPENSSL_TRUE@am__append_14 = \
|
||||
@OPENSSL_TRUE@ openssl/cipher.c \
|
||||
@OPENSSL_TRUE@ openssl/crypto.c \
|
||||
@OPENSSL_TRUE@ openssl/digest.c openssl/digest.h \
|
||||
@OPENSSL_TRUE@ ed25519/ecdh.c \
|
||||
@OPENSSL_TRUE@ ed25519/ecdsa.c \
|
||||
@OPENSSL_TRUE@ openssl/prf.c \
|
||||
@OPENSSL_TRUE@ openssl/rsa.c
|
||||
|
||||
@OPENSSL_TRUE@am__append_11 = \
|
||||
@OPENSSL_TRUE@am__append_15 = \
|
||||
@OPENSSL_TRUE@ openssl/cipher.c \
|
||||
@OPENSSL_TRUE@ openssl/crypto.c \
|
||||
@OPENSSL_TRUE@ openssl/digest.c openssl/digest.h \
|
||||
@OPENSSL_TRUE@ ed25519/ecdh.c \
|
||||
@OPENSSL_TRUE@ ed25519/ecdsa.c \
|
||||
@OPENSSL_TRUE@ ed25519/ecdsagen.c \
|
||||
@OPENSSL_TRUE@ openssl/prf.c \
|
||||
@OPENSSL_TRUE@ openssl/rsa.c \
|
||||
@OPENSSL_TRUE@ openssl/rsagen.c
|
||||
|
||||
@OPENSSL_TRUE@am__append_12 = \
|
||||
@OPENSSL_TRUE@am__append_16 = \
|
||||
@OPENSSL_TRUE@ openssl/crypto.c \
|
||||
@OPENSSL_TRUE@ openssl/digest.c openssl/digest.h \
|
||||
@OPENSSL_TRUE@ ed25519/ecdh.c \
|
||||
@OPENSSL_TRUE@ ed25519/ecdsa.c \
|
||||
@OPENSSL_TRUE@ openssl/prf.c
|
||||
|
||||
@OPENSSL_TRUE@am__append_13 = \
|
||||
@OPENSSL_TRUE@ openssl/crypto.c \
|
||||
@OPENSSL_TRUE@ ed25519/ecdsagen.c
|
||||
@OPENSSL_TRUE@am__append_17 = \
|
||||
@OPENSSL_TRUE@ openssl/crypto.c
|
||||
|
||||
@OPENSSL_TRUE@am__append_14 = \
|
||||
@OPENSSL_TRUE@am__append_18 = \
|
||||
@OPENSSL_TRUE@ openssl/crypto.c \
|
||||
@OPENSSL_TRUE@ openssl/digest.c openssl/digest.h \
|
||||
@OPENSSL_TRUE@ ed25519/ecdh.c \
|
||||
@OPENSSL_TRUE@ ed25519/ecdsa.c \
|
||||
@OPENSSL_TRUE@ ed25519/ecdsagen.c \
|
||||
@OPENSSL_TRUE@ openssl/prf.c
|
||||
|
||||
@GCRYPT_TRUE@am__append_15 = \
|
||||
@GCRYPT_TRUE@ gcrypt/cipher.c \
|
||||
@GCRYPT_TRUE@ gcrypt/crypto.c \
|
||||
@GCRYPT_TRUE@ gcrypt/digest.c gcrypt/digest.h \
|
||||
@GCRYPT_TRUE@ gcrypt/ecdh.c \
|
||||
@GCRYPT_TRUE@ gcrypt/ecdsa.c \
|
||||
@GCRYPT_TRUE@ gcrypt/prf.c \
|
||||
@GCRYPT_TRUE@ gcrypt/rsa.c
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@am__append_19 = \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/cipher.c \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/crypto.c \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/digest.c gcrypt/digest.h \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/prf.c \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/rsa.c
|
||||
|
||||
@GCRYPT_TRUE@am__append_16 = \
|
||||
@GCRYPT_TRUE@ gcrypt/cipher.c \
|
||||
@GCRYPT_TRUE@ gcrypt/crypto.c \
|
||||
@GCRYPT_TRUE@ gcrypt/digest.c gcrypt/digest.h \
|
||||
@GCRYPT_TRUE@ gcrypt/ecdh.c \
|
||||
@GCRYPT_TRUE@ gcrypt/ecdsa.c \
|
||||
@GCRYPT_TRUE@ gcrypt/ecdsagen.c \
|
||||
@GCRYPT_TRUE@ gcrypt/prf.c \
|
||||
@GCRYPT_TRUE@ gcrypt/rsa.c \
|
||||
@GCRYPT_TRUE@ gcrypt/rsagen.c
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@am__append_20 = \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/cipher.c \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/crypto.c \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/digest.c gcrypt/digest.h \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/prf.c \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/rsa.c \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/rsagen.c
|
||||
|
||||
@GCRYPT_TRUE@am__append_17 = \
|
||||
@GCRYPT_TRUE@ gcrypt/cipher.c \
|
||||
@GCRYPT_TRUE@ gcrypt/crypto.c \
|
||||
@GCRYPT_TRUE@ gcrypt/digest.c gcrypt/digest.h \
|
||||
@GCRYPT_TRUE@ gcrypt/ecdh.c \
|
||||
@GCRYPT_TRUE@ gcrypt/ecdsa.c \
|
||||
@GCRYPT_TRUE@ gcrypt/prf.c
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@am__append_21 = \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/cipher.c \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/crypto.c \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/digest.c gcrypt/digest.h \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/prf.c
|
||||
|
||||
@TUNEMU_TRUE@am__append_18 = -lpcap
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@am__append_22 = \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ openssl/crypto.c
|
||||
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@am__append_23 = \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ openssl/crypto.c \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ openssl/digest.c openssl/digest.h \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ openssl/prf.c
|
||||
|
||||
@GCRYPT_FALSE@@OPENSSL_FALSE@am__append_24 = \
|
||||
@GCRYPT_FALSE@@OPENSSL_FALSE@ nolegacy/crypto.c \
|
||||
@GCRYPT_FALSE@@OPENSSL_FALSE@ nolegacy/prf.c
|
||||
|
||||
@GCRYPT_FALSE@@OPENSSL_FALSE@am__append_25 = \
|
||||
@GCRYPT_FALSE@@OPENSSL_FALSE@ nolegacy/crypto.c \
|
||||
@GCRYPT_FALSE@@OPENSSL_FALSE@ nolegacy/prf.c
|
||||
|
||||
@GCRYPT_FALSE@@OPENSSL_FALSE@am__append_26 = \
|
||||
@GCRYPT_FALSE@@OPENSSL_FALSE@ nolegacy/crypto.c \
|
||||
@GCRYPT_FALSE@@OPENSSL_FALSE@ nolegacy/prf.c
|
||||
|
||||
@GCRYPT_FALSE@@OPENSSL_FALSE@am__append_27 = \
|
||||
@GCRYPT_FALSE@@OPENSSL_FALSE@ nolegacy/crypto.c
|
||||
|
||||
@GCRYPT_FALSE@@OPENSSL_FALSE@am__append_28 = \
|
||||
@GCRYPT_FALSE@@OPENSSL_FALSE@ nolegacy/crypto.c \
|
||||
@GCRYPT_FALSE@@OPENSSL_FALSE@ nolegacy/prf.c
|
||||
|
||||
@MINIUPNPC_TRUE@am__append_29 = upnp.h upnp.c
|
||||
@TUNEMU_TRUE@am__append_30 = -lpcap
|
||||
subdir = src
|
||||
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
|
||||
$(top_srcdir)/depcomp
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
|
||||
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
|
||||
$(top_srcdir)/m4/ax_check_link_flag.m4 \
|
||||
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/libgcrypt.m4 \
|
||||
$(top_srcdir)/m4/lzo.m4 $(top_srcdir)/m4/openssl.m4 \
|
||||
$(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/zlib.m4 \
|
||||
$(top_srcdir)/configure.ac
|
||||
$(top_srcdir)/m4/lzo.m4 $(top_srcdir)/m4/miniupnpc.m4 \
|
||||
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \
|
||||
$(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
|
|
@ -178,78 +213,91 @@ CONFIG_CLEAN_VPATH_FILES =
|
|||
am__installdirs = "$(DESTDIR)$(sbindir)"
|
||||
PROGRAMS = $(sbin_PROGRAMS)
|
||||
am__sptps_keypair_SOURCES_DIST = sptps_keypair.c utils.c utils.h \
|
||||
ed25519/add_scalar.c ed25519/ed25519.h ed25519/fe.c \
|
||||
ed25519/fe.h ed25519/fixedint.h ed25519/ge.c ed25519/ge.h \
|
||||
ed25519/key_exchange.c ed25519/keypair.c \
|
||||
ed25519/ecdsagen.c ed25519/add_scalar.c ed25519/ed25519.h \
|
||||
ed25519/fe.c ed25519/fe.h ed25519/fixedint.h ed25519/ge.c \
|
||||
ed25519/ge.h ed25519/key_exchange.c ed25519/keypair.c \
|
||||
ed25519/precomp_data.h ed25519/sc.c ed25519/sc.h \
|
||||
ed25519/sha512.c ed25519/sha512.h ed25519/sign.c \
|
||||
ed25519/verify.c openssl/crypto.c ed25519/ecdsagen.c
|
||||
ed25519/verify.c getopt.c getopt.h getopt1.c openssl/crypto.c \
|
||||
nolegacy/crypto.c
|
||||
am__dirstamp = $(am__leading_dot)dirstamp
|
||||
am__objects_1 = ed25519/add_scalar.$(OBJEXT) ed25519/fe.$(OBJEXT) \
|
||||
ed25519/ge.$(OBJEXT) ed25519/key_exchange.$(OBJEXT) \
|
||||
ed25519/keypair.$(OBJEXT) ed25519/sc.$(OBJEXT) \
|
||||
ed25519/sha512.$(OBJEXT) ed25519/sign.$(OBJEXT) \
|
||||
ed25519/verify.$(OBJEXT)
|
||||
@OPENSSL_TRUE@am__objects_2 = openssl/crypto.$(OBJEXT) \
|
||||
@OPENSSL_TRUE@ ed25519/ecdsagen.$(OBJEXT)
|
||||
@GETOPT_FALSE@am__objects_2 = getopt.$(OBJEXT) getopt1.$(OBJEXT)
|
||||
@OPENSSL_TRUE@am__objects_3 = openssl/crypto.$(OBJEXT)
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@am__objects_4 = openssl/crypto.$(OBJEXT)
|
||||
@GCRYPT_FALSE@@OPENSSL_FALSE@am__objects_5 = \
|
||||
@GCRYPT_FALSE@@OPENSSL_FALSE@ nolegacy/crypto.$(OBJEXT)
|
||||
am_sptps_keypair_OBJECTS = sptps_keypair.$(OBJEXT) utils.$(OBJEXT) \
|
||||
$(am__objects_1) $(am__objects_2)
|
||||
ed25519/ecdsagen.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
|
||||
$(am__objects_3) $(am__objects_4) $(am__objects_5)
|
||||
sptps_keypair_OBJECTS = $(am_sptps_keypair_OBJECTS)
|
||||
sptps_keypair_LDADD = $(LDADD)
|
||||
am__sptps_speed_SOURCES_DIST = logger.c logger.h sptps.c sptps.h \
|
||||
sptps_speed.c utils.c utils.h ed25519/add_scalar.c \
|
||||
ed25519/ed25519.h ed25519/fe.c ed25519/fe.h ed25519/fixedint.h \
|
||||
ed25519/ge.c ed25519/ge.h ed25519/key_exchange.c \
|
||||
ed25519/keypair.c ed25519/precomp_data.h ed25519/sc.c \
|
||||
ed25519/sc.h ed25519/sha512.c ed25519/sha512.h ed25519/sign.c \
|
||||
sptps_speed.c utils.c utils.h ed25519/ecdh.c ed25519/ecdsa.c \
|
||||
ed25519/ecdsagen.c ed25519/add_scalar.c ed25519/ed25519.h \
|
||||
ed25519/fe.c ed25519/fe.h ed25519/fixedint.h ed25519/ge.c \
|
||||
ed25519/ge.h ed25519/key_exchange.c ed25519/keypair.c \
|
||||
ed25519/precomp_data.h ed25519/sc.c ed25519/sc.h \
|
||||
ed25519/sha512.c ed25519/sha512.h ed25519/sign.c \
|
||||
ed25519/verify.c chacha-poly1305/chacha.c \
|
||||
chacha-poly1305/chacha.h chacha-poly1305/chacha-poly1305.c \
|
||||
chacha-poly1305/chacha-poly1305.h chacha-poly1305/poly1305.c \
|
||||
chacha-poly1305/poly1305.h openssl/crypto.c openssl/digest.c \
|
||||
openssl/digest.h ed25519/ecdh.c ed25519/ecdsa.c \
|
||||
ed25519/ecdsagen.c openssl/prf.c
|
||||
am__objects_3 = chacha-poly1305/chacha.$(OBJEXT) \
|
||||
openssl/digest.h openssl/prf.c nolegacy/crypto.c \
|
||||
nolegacy/prf.c
|
||||
am__objects_6 = chacha-poly1305/chacha.$(OBJEXT) \
|
||||
chacha-poly1305/chacha-poly1305.$(OBJEXT) \
|
||||
chacha-poly1305/poly1305.$(OBJEXT)
|
||||
@OPENSSL_TRUE@am__objects_4 = openssl/crypto.$(OBJEXT) \
|
||||
@OPENSSL_TRUE@ openssl/digest.$(OBJEXT) ed25519/ecdh.$(OBJEXT) \
|
||||
@OPENSSL_TRUE@ ed25519/ecdsa.$(OBJEXT) \
|
||||
@OPENSSL_TRUE@ ed25519/ecdsagen.$(OBJEXT) openssl/prf.$(OBJEXT)
|
||||
@OPENSSL_TRUE@am__objects_7 = openssl/crypto.$(OBJEXT) \
|
||||
@OPENSSL_TRUE@ openssl/digest.$(OBJEXT) openssl/prf.$(OBJEXT)
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@am__objects_8 = openssl/crypto.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ openssl/digest.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ openssl/prf.$(OBJEXT)
|
||||
@GCRYPT_FALSE@@OPENSSL_FALSE@am__objects_9 = \
|
||||
@GCRYPT_FALSE@@OPENSSL_FALSE@ nolegacy/crypto.$(OBJEXT) \
|
||||
@GCRYPT_FALSE@@OPENSSL_FALSE@ nolegacy/prf.$(OBJEXT)
|
||||
am_sptps_speed_OBJECTS = logger.$(OBJEXT) sptps.$(OBJEXT) \
|
||||
sptps_speed.$(OBJEXT) utils.$(OBJEXT) $(am__objects_1) \
|
||||
$(am__objects_3) $(am__objects_4)
|
||||
sptps_speed.$(OBJEXT) utils.$(OBJEXT) ed25519/ecdh.$(OBJEXT) \
|
||||
ed25519/ecdsa.$(OBJEXT) ed25519/ecdsagen.$(OBJEXT) \
|
||||
$(am__objects_1) $(am__objects_6) $(am__objects_7) \
|
||||
$(am__objects_8) $(am__objects_9)
|
||||
sptps_speed_OBJECTS = $(am_sptps_speed_OBJECTS)
|
||||
sptps_speed_DEPENDENCIES =
|
||||
am__sptps_test_SOURCES_DIST = logger.c logger.h sptps.c sptps.h \
|
||||
sptps_test.c utils.c utils.h ed25519/add_scalar.c \
|
||||
ed25519/ed25519.h ed25519/fe.c ed25519/fe.h ed25519/fixedint.h \
|
||||
ed25519/ge.c ed25519/ge.h ed25519/key_exchange.c \
|
||||
ed25519/keypair.c ed25519/precomp_data.h ed25519/sc.c \
|
||||
ed25519/sc.h ed25519/sha512.c ed25519/sha512.h ed25519/sign.c \
|
||||
sptps_test.c utils.c utils.h ed25519/ecdh.c ed25519/ecdsa.c \
|
||||
ed25519/add_scalar.c ed25519/ed25519.h ed25519/fe.c \
|
||||
ed25519/fe.h ed25519/fixedint.h ed25519/ge.c ed25519/ge.h \
|
||||
ed25519/key_exchange.c ed25519/keypair.c \
|
||||
ed25519/precomp_data.h ed25519/sc.c ed25519/sc.h \
|
||||
ed25519/sha512.c ed25519/sha512.h ed25519/sign.c \
|
||||
ed25519/verify.c chacha-poly1305/chacha.c \
|
||||
chacha-poly1305/chacha.h chacha-poly1305/chacha-poly1305.c \
|
||||
chacha-poly1305/chacha-poly1305.h chacha-poly1305/poly1305.c \
|
||||
chacha-poly1305/poly1305.h openssl/crypto.c openssl/digest.c \
|
||||
openssl/digest.h ed25519/ecdh.c ed25519/ecdsa.c openssl/prf.c \
|
||||
gcrypt/cipher.c gcrypt/crypto.c gcrypt/digest.c \
|
||||
gcrypt/digest.h gcrypt/ecdh.c gcrypt/ecdsa.c gcrypt/prf.c
|
||||
@OPENSSL_TRUE@am__objects_5 = openssl/crypto.$(OBJEXT) \
|
||||
@OPENSSL_TRUE@ openssl/digest.$(OBJEXT) ed25519/ecdh.$(OBJEXT) \
|
||||
@OPENSSL_TRUE@ ed25519/ecdsa.$(OBJEXT) openssl/prf.$(OBJEXT)
|
||||
@GCRYPT_TRUE@am__objects_6 = gcrypt/cipher.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@ gcrypt/crypto.$(OBJEXT) gcrypt/digest.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@ gcrypt/ecdh.$(OBJEXT) gcrypt/ecdsa.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@ gcrypt/prf.$(OBJEXT)
|
||||
chacha-poly1305/poly1305.h getopt.c getopt.h getopt1.c \
|
||||
openssl/crypto.c openssl/digest.c openssl/digest.h \
|
||||
openssl/prf.c gcrypt/cipher.c gcrypt/crypto.c gcrypt/digest.c \
|
||||
gcrypt/digest.h gcrypt/prf.c nolegacy/crypto.c nolegacy/prf.c
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@am__objects_10 = gcrypt/cipher.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/crypto.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/digest.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/prf.$(OBJEXT)
|
||||
am_sptps_test_OBJECTS = logger.$(OBJEXT) sptps.$(OBJEXT) \
|
||||
sptps_test.$(OBJEXT) utils.$(OBJEXT) $(am__objects_1) \
|
||||
$(am__objects_3) $(am__objects_5) $(am__objects_6)
|
||||
sptps_test.$(OBJEXT) utils.$(OBJEXT) ed25519/ecdh.$(OBJEXT) \
|
||||
ed25519/ecdsa.$(OBJEXT) $(am__objects_1) $(am__objects_6) \
|
||||
$(am__objects_2) $(am__objects_7) $(am__objects_10) \
|
||||
$(am__objects_9)
|
||||
sptps_test_OBJECTS = $(am_sptps_test_OBJECTS)
|
||||
sptps_test_LDADD = $(LDADD)
|
||||
am__tinc_SOURCES_DIST = dropin.c dropin.h getopt.c getopt.h getopt1.c \
|
||||
info.c info.h invitation.c invitation.h list.c list.h names.c \
|
||||
names.h netutl.c netutl.h script.c script.h sptps.c sptps.h \
|
||||
subnet_parse.c subnet.h tincctl.c tincctl.h top.c top.h \
|
||||
utils.c utils.h version.c version.h ed25519/add_scalar.c \
|
||||
am__tinc_SOURCES_DIST = dropin.c dropin.h fsck.c fsck.h ifconfig.c \
|
||||
ifconfig.h info.c info.h invitation.c invitation.h list.c \
|
||||
list.h names.c names.h netutl.c netutl.h script.c script.h \
|
||||
sptps.c sptps.h subnet_parse.c subnet.h tincctl.c tincctl.h \
|
||||
top.c top.h utils.c utils.h version.c version.h ed25519/ecdh.c \
|
||||
ed25519/ecdsa.c ed25519/ecdsagen.c ed25519/add_scalar.c \
|
||||
ed25519/ed25519.h ed25519/fe.c ed25519/fe.h ed25519/fixedint.h \
|
||||
ed25519/ge.c ed25519/ge.h ed25519/key_exchange.c \
|
||||
ed25519/keypair.c ed25519/precomp_data.h ed25519/sc.c \
|
||||
|
|
@ -257,30 +305,31 @@ am__tinc_SOURCES_DIST = dropin.c dropin.h getopt.c getopt.h getopt1.c \
|
|||
ed25519/verify.c chacha-poly1305/chacha.c \
|
||||
chacha-poly1305/chacha.h chacha-poly1305/chacha-poly1305.c \
|
||||
chacha-poly1305/chacha-poly1305.h chacha-poly1305/poly1305.c \
|
||||
chacha-poly1305/poly1305.h openssl/cipher.c openssl/crypto.c \
|
||||
openssl/digest.c openssl/digest.h ed25519/ecdh.c \
|
||||
ed25519/ecdsa.c ed25519/ecdsagen.c openssl/prf.c openssl/rsa.c \
|
||||
openssl/rsagen.c gcrypt/cipher.c gcrypt/crypto.c \
|
||||
gcrypt/digest.c gcrypt/digest.h gcrypt/ecdh.c gcrypt/ecdsa.c \
|
||||
gcrypt/ecdsagen.c gcrypt/prf.c gcrypt/rsa.c gcrypt/rsagen.c
|
||||
@OPENSSL_TRUE@am__objects_7 = openssl/cipher.$(OBJEXT) \
|
||||
chacha-poly1305/poly1305.h getopt.c getopt.h getopt1.c \
|
||||
openssl/cipher.c openssl/crypto.c openssl/digest.c \
|
||||
openssl/digest.h openssl/prf.c openssl/rsa.c openssl/rsagen.c \
|
||||
gcrypt/cipher.c gcrypt/crypto.c gcrypt/digest.c \
|
||||
gcrypt/digest.h gcrypt/prf.c gcrypt/rsa.c gcrypt/rsagen.c \
|
||||
nolegacy/crypto.c nolegacy/prf.c
|
||||
@OPENSSL_TRUE@am__objects_11 = openssl/cipher.$(OBJEXT) \
|
||||
@OPENSSL_TRUE@ openssl/crypto.$(OBJEXT) \
|
||||
@OPENSSL_TRUE@ openssl/digest.$(OBJEXT) ed25519/ecdh.$(OBJEXT) \
|
||||
@OPENSSL_TRUE@ ed25519/ecdsa.$(OBJEXT) \
|
||||
@OPENSSL_TRUE@ ed25519/ecdsagen.$(OBJEXT) openssl/prf.$(OBJEXT) \
|
||||
@OPENSSL_TRUE@ openssl/digest.$(OBJEXT) openssl/prf.$(OBJEXT) \
|
||||
@OPENSSL_TRUE@ openssl/rsa.$(OBJEXT) openssl/rsagen.$(OBJEXT)
|
||||
@GCRYPT_TRUE@am__objects_8 = gcrypt/cipher.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@ gcrypt/crypto.$(OBJEXT) gcrypt/digest.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@ gcrypt/ecdh.$(OBJEXT) gcrypt/ecdsa.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@ gcrypt/ecdsagen.$(OBJEXT) gcrypt/prf.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@ gcrypt/rsa.$(OBJEXT) gcrypt/rsagen.$(OBJEXT)
|
||||
am_tinc_OBJECTS = dropin.$(OBJEXT) getopt.$(OBJEXT) getopt1.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@am__objects_12 = gcrypt/cipher.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/crypto.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/digest.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/prf.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/rsa.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/rsagen.$(OBJEXT)
|
||||
am_tinc_OBJECTS = dropin.$(OBJEXT) fsck.$(OBJEXT) ifconfig.$(OBJEXT) \
|
||||
info.$(OBJEXT) invitation.$(OBJEXT) list.$(OBJEXT) \
|
||||
names.$(OBJEXT) netutl.$(OBJEXT) script.$(OBJEXT) \
|
||||
sptps.$(OBJEXT) subnet_parse.$(OBJEXT) tincctl.$(OBJEXT) \
|
||||
top.$(OBJEXT) utils.$(OBJEXT) version.$(OBJEXT) \
|
||||
$(am__objects_1) $(am__objects_3) $(am__objects_7) \
|
||||
$(am__objects_8)
|
||||
ed25519/ecdh.$(OBJEXT) ed25519/ecdsa.$(OBJEXT) \
|
||||
ed25519/ecdsagen.$(OBJEXT) $(am__objects_1) $(am__objects_6) \
|
||||
$(am__objects_2) $(am__objects_11) $(am__objects_12) \
|
||||
$(am__objects_9)
|
||||
tinc_OBJECTS = $(am_tinc_OBJECTS)
|
||||
am__DEPENDENCIES_1 =
|
||||
tinc_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
|
||||
|
|
@ -288,73 +337,74 @@ am__tincd_SOURCES_DIST = buffer.c buffer.h cipher.h conf.c conf.h \
|
|||
connection.c connection.h control.c control.h control_common.h \
|
||||
crypto.h device.h digest.h dropin.c dropin.h dummy_device.c \
|
||||
ecdh.h ecdsa.h ecdsagen.h edge.c edge.h ethernet.h event.c \
|
||||
event.h fake-gai-errnos.h fake-getaddrinfo.c \
|
||||
fake-getaddrinfo.h fake-getnameinfo.c fake-getnameinfo.h \
|
||||
getopt.c getopt.h getopt1.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 \
|
||||
event.h graph.c graph.h hash.c hash.h have.h ipv4.h ipv6.h \
|
||||
list.c list.h logger.c logger.h meta.c meta.h \
|
||||
multicast_device.c names.c names.h net.c net.h net_packet.c \
|
||||
net_setup.c net_socket.c netutl.c netutl.h node.c node.h prf.h \
|
||||
process.c process.h protocol.c protocol.h protocol_auth.c \
|
||||
protocol_edge.c protocol_key.c protocol_misc.c \
|
||||
protocol_subnet.c raw_socket_device.c route.c route.h rsa.h \
|
||||
rsagen.h script.c script.h splay_tree.c splay_tree.h sptps.c \
|
||||
sptps.h subnet.c subnet.h subnet_parse.c system.h tincd.c \
|
||||
utils.c utils.h xalloc.h version.c version.h \
|
||||
ed25519/add_scalar.c ed25519/ed25519.h ed25519/fe.c \
|
||||
ed25519/fe.h ed25519/fixedint.h ed25519/ge.c ed25519/ge.h \
|
||||
ed25519/key_exchange.c ed25519/keypair.c \
|
||||
utils.c utils.h xalloc.h version.c version.h ed25519/ecdh.c \
|
||||
ed25519/ecdsa.c ed25519/add_scalar.c ed25519/ed25519.h \
|
||||
ed25519/fe.c ed25519/fe.h ed25519/fixedint.h ed25519/ge.c \
|
||||
ed25519/ge.h ed25519/key_exchange.c ed25519/keypair.c \
|
||||
ed25519/precomp_data.h ed25519/sc.c ed25519/sc.h \
|
||||
ed25519/sha512.c ed25519/sha512.h ed25519/sign.c \
|
||||
ed25519/verify.c chacha-poly1305/chacha.c \
|
||||
chacha-poly1305/chacha.h chacha-poly1305/chacha-poly1305.c \
|
||||
chacha-poly1305/chacha-poly1305.h chacha-poly1305/poly1305.c \
|
||||
chacha-poly1305/poly1305.h linux/device.c bsd/device.c \
|
||||
bsd/tunemu.c bsd/tunemu.h solaris/device.c mingw/device.c \
|
||||
mingw/common.h cygwin/device.c uml_device.c vde_device.c \
|
||||
openssl/cipher.c openssl/crypto.c openssl/digest.c \
|
||||
openssl/digest.h ed25519/ecdh.c ed25519/ecdsa.c openssl/prf.c \
|
||||
openssl/rsa.c gcrypt/cipher.c gcrypt/crypto.c gcrypt/digest.c \
|
||||
gcrypt/digest.h gcrypt/ecdh.c gcrypt/ecdsa.c gcrypt/prf.c \
|
||||
gcrypt/rsa.c
|
||||
@LINUX_TRUE@am__objects_9 = linux/device.$(OBJEXT)
|
||||
@BSD_TRUE@am__objects_10 = bsd/device.$(OBJEXT)
|
||||
@BSD_TRUE@@TUNEMU_TRUE@am__objects_11 = bsd/tunemu.$(OBJEXT)
|
||||
@SOLARIS_TRUE@am__objects_12 = solaris/device.$(OBJEXT)
|
||||
@MINGW_TRUE@am__objects_13 = mingw/device.$(OBJEXT)
|
||||
@CYGWIN_TRUE@am__objects_14 = cygwin/device.$(OBJEXT)
|
||||
@UML_TRUE@am__objects_15 = uml_device.$(OBJEXT)
|
||||
@VDE_TRUE@am__objects_16 = vde_device.$(OBJEXT)
|
||||
@OPENSSL_TRUE@am__objects_17 = openssl/cipher.$(OBJEXT) \
|
||||
chacha-poly1305/poly1305.h getopt.c getopt.h getopt1.c \
|
||||
linux/device.c bsd/device.c bsd/tunemu.c bsd/tunemu.h \
|
||||
solaris/device.c mingw/device.c mingw/common.h cygwin/device.c \
|
||||
uml_device.c vde_device.c openssl/cipher.c openssl/crypto.c \
|
||||
openssl/digest.c openssl/digest.h openssl/prf.c openssl/rsa.c \
|
||||
gcrypt/cipher.c gcrypt/crypto.c gcrypt/digest.c \
|
||||
gcrypt/digest.h gcrypt/prf.c gcrypt/rsa.c nolegacy/crypto.c \
|
||||
nolegacy/prf.c upnp.h upnp.c
|
||||
@LINUX_TRUE@am__objects_13 = linux/device.$(OBJEXT)
|
||||
@BSD_TRUE@am__objects_14 = bsd/device.$(OBJEXT)
|
||||
@BSD_TRUE@@TUNEMU_TRUE@am__objects_15 = bsd/tunemu.$(OBJEXT)
|
||||
@SOLARIS_TRUE@am__objects_16 = solaris/device.$(OBJEXT)
|
||||
@MINGW_TRUE@am__objects_17 = mingw/device.$(OBJEXT)
|
||||
@CYGWIN_TRUE@am__objects_18 = cygwin/device.$(OBJEXT)
|
||||
@UML_TRUE@am__objects_19 = uml_device.$(OBJEXT)
|
||||
@VDE_TRUE@am__objects_20 = vde_device.$(OBJEXT)
|
||||
@OPENSSL_TRUE@am__objects_21 = openssl/cipher.$(OBJEXT) \
|
||||
@OPENSSL_TRUE@ openssl/crypto.$(OBJEXT) \
|
||||
@OPENSSL_TRUE@ openssl/digest.$(OBJEXT) ed25519/ecdh.$(OBJEXT) \
|
||||
@OPENSSL_TRUE@ ed25519/ecdsa.$(OBJEXT) openssl/prf.$(OBJEXT) \
|
||||
@OPENSSL_TRUE@ openssl/digest.$(OBJEXT) openssl/prf.$(OBJEXT) \
|
||||
@OPENSSL_TRUE@ openssl/rsa.$(OBJEXT)
|
||||
@GCRYPT_TRUE@am__objects_18 = gcrypt/cipher.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@ gcrypt/crypto.$(OBJEXT) gcrypt/digest.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@ gcrypt/ecdh.$(OBJEXT) gcrypt/ecdsa.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@ gcrypt/prf.$(OBJEXT) gcrypt/rsa.$(OBJEXT)
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@am__objects_22 = gcrypt/cipher.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/crypto.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/digest.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/prf.$(OBJEXT) \
|
||||
@GCRYPT_TRUE@@OPENSSL_FALSE@ gcrypt/rsa.$(OBJEXT)
|
||||
@MINIUPNPC_TRUE@am__objects_23 = upnp.$(OBJEXT)
|
||||
am_tincd_OBJECTS = buffer.$(OBJEXT) conf.$(OBJEXT) \
|
||||
connection.$(OBJEXT) control.$(OBJEXT) dropin.$(OBJEXT) \
|
||||
dummy_device.$(OBJEXT) edge.$(OBJEXT) event.$(OBJEXT) \
|
||||
fake-getaddrinfo.$(OBJEXT) fake-getnameinfo.$(OBJEXT) \
|
||||
getopt.$(OBJEXT) getopt1.$(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) \
|
||||
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) \
|
||||
splay_tree.$(OBJEXT) sptps.$(OBJEXT) subnet.$(OBJEXT) \
|
||||
subnet_parse.$(OBJEXT) tincd.$(OBJEXT) utils.$(OBJEXT) \
|
||||
version.$(OBJEXT) $(am__objects_1) $(am__objects_3) \
|
||||
$(am__objects_9) $(am__objects_10) $(am__objects_11) \
|
||||
$(am__objects_12) $(am__objects_13) $(am__objects_14) \
|
||||
version.$(OBJEXT) ed25519/ecdh.$(OBJEXT) \
|
||||
ed25519/ecdsa.$(OBJEXT) $(am__objects_1) $(am__objects_6) \
|
||||
$(am__objects_2) $(am__objects_13) $(am__objects_14) \
|
||||
$(am__objects_15) $(am__objects_16) $(am__objects_17) \
|
||||
$(am__objects_18)
|
||||
$(am__objects_18) $(am__objects_19) $(am__objects_20) \
|
||||
$(am__objects_21) $(am__objects_22) $(am__objects_9) \
|
||||
$(am__objects_23)
|
||||
tincd_OBJECTS = $(am_tincd_OBJECTS)
|
||||
tincd_LDADD = $(LDADD)
|
||||
@MINIUPNPC_TRUE@tincd_DEPENDENCIES = $(am__DEPENDENCIES_1)
|
||||
tincd_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(tincd_LDFLAGS) \
|
||||
$(LDFLAGS) -o $@
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
|
|
@ -367,6 +417,7 @@ AM_V_at = $(am__v_at_@AM_V@)
|
|||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||
am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
DEFAULT_INCLUDES =
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
am__mv = mv -f
|
||||
|
|
@ -411,6 +462,7 @@ am__define_uniq_tagged_files = \
|
|||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
|
|
@ -441,10 +493,11 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
|||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@ $(am__append_18)
|
||||
LIBS = @LIBS@ -lm $(am__append_30)
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MINIUPNPC_LIBS = @MINIUPNPC_LIBS@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
|
|
@ -502,15 +555,17 @@ pdfdir = @pdfdir@
|
|||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
runstatedir = @runstatedir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
systemd_path = @systemd_path@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
DEFAULT_INCLUDES =
|
||||
CLEANFILES = version_git.h
|
||||
ed25519_SOURCES = \
|
||||
ed25519/add_scalar.c \
|
||||
ed25519/ed25519.h \
|
||||
|
|
@ -534,39 +589,47 @@ tincd_SOURCES = buffer.c buffer.h cipher.h conf.c conf.h connection.c \
|
|||
connection.h control.c control.h control_common.h crypto.h \
|
||||
device.h digest.h dropin.c dropin.h dummy_device.c ecdh.h \
|
||||
ecdsa.h ecdsagen.h edge.c edge.h ethernet.h event.c event.h \
|
||||
fake-gai-errnos.h fake-getaddrinfo.c fake-getaddrinfo.h \
|
||||
fake-getnameinfo.c fake-getnameinfo.h getopt.c getopt.h \
|
||||
getopt1.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 \
|
||||
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_SOURCES) $(chacha_poly1305_SOURCES) $(am__append_2) \
|
||||
$(am__append_3) $(am__append_4) $(am__append_5) \
|
||||
$(am__append_6) $(am__append_7) $(am__append_8) \
|
||||
$(am__append_9) $(am__append_10) $(am__append_15)
|
||||
tinc_SOURCES = dropin.c dropin.h getopt.c getopt.h getopt1.c info.c \
|
||||
info.h invitation.c invitation.h list.c list.h names.c names.h \
|
||||
netutl.c netutl.h script.c script.h sptps.c sptps.h \
|
||||
utils.c utils.h xalloc.h version.c version.h ed25519/ecdh.c \
|
||||
ed25519/ecdsa.c $(ed25519_SOURCES) $(chacha_poly1305_SOURCES) \
|
||||
$(am__append_2) $(am__append_6) $(am__append_7) \
|
||||
$(am__append_8) $(am__append_9) $(am__append_10) \
|
||||
$(am__append_11) $(am__append_12) $(am__append_13) \
|
||||
$(am__append_14) $(am__append_19) $(am__append_24) \
|
||||
$(am__append_29)
|
||||
tinc_SOURCES = dropin.c dropin.h fsck.c fsck.h ifconfig.c ifconfig.h \
|
||||
info.c info.h invitation.c invitation.h list.c list.h names.c \
|
||||
names.h netutl.c netutl.h script.c script.h sptps.c sptps.h \
|
||||
subnet_parse.c subnet.h tincctl.c tincctl.h top.c top.h \
|
||||
utils.c utils.h version.c version.h $(ed25519_SOURCES) \
|
||||
$(chacha_poly1305_SOURCES) $(am__append_11) $(am__append_16)
|
||||
utils.c utils.h version.c version.h ed25519/ecdh.c \
|
||||
ed25519/ecdsa.c ed25519/ecdsagen.c $(ed25519_SOURCES) \
|
||||
$(chacha_poly1305_SOURCES) $(am__append_3) $(am__append_15) \
|
||||
$(am__append_20) $(am__append_25)
|
||||
sptps_test_SOURCES = logger.c logger.h sptps.c sptps.h sptps_test.c \
|
||||
utils.c utils.h $(ed25519_SOURCES) $(chacha_poly1305_SOURCES) \
|
||||
$(am__append_12) $(am__append_17)
|
||||
utils.c utils.h ed25519/ecdh.c ed25519/ecdsa.c \
|
||||
$(ed25519_SOURCES) $(chacha_poly1305_SOURCES) $(am__append_4) \
|
||||
$(am__append_16) $(am__append_21) $(am__append_26)
|
||||
sptps_keypair_SOURCES = sptps_keypair.c utils.c utils.h \
|
||||
$(ed25519_SOURCES) $(am__append_13)
|
||||
ed25519/ecdsagen.c $(ed25519_SOURCES) $(am__append_5) \
|
||||
$(am__append_17) $(am__append_22) $(am__append_27)
|
||||
sptps_speed_SOURCES = logger.c logger.h sptps.c sptps.h sptps_speed.c \
|
||||
utils.c utils.h $(ed25519_SOURCES) $(chacha_poly1305_SOURCES) \
|
||||
$(am__append_14)
|
||||
utils.c utils.h ed25519/ecdh.c ed25519/ecdsa.c \
|
||||
ed25519/ecdsagen.c $(ed25519_SOURCES) \
|
||||
$(chacha_poly1305_SOURCES) $(am__append_18) $(am__append_23) \
|
||||
$(am__append_28)
|
||||
@MINIUPNPC_TRUE@tincd_LDADD = $(MINIUPNPC_LIBS)
|
||||
@MINIUPNPC_TRUE@tincd_LDFLAGS = -pthread
|
||||
tinc_LDADD = $(READLINE_LIBS) $(CURSES_LIBS)
|
||||
sptps_speed_LDADD = -lrt
|
||||
AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\"
|
||||
AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\" -iquote.
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
|
|
@ -583,7 +646,6 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
|||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu src/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
|
|
@ -665,6 +727,8 @@ ed25519/$(am__dirstamp):
|
|||
ed25519/$(DEPDIR)/$(am__dirstamp):
|
||||
@$(MKDIR_P) ed25519/$(DEPDIR)
|
||||
@: > ed25519/$(DEPDIR)/$(am__dirstamp)
|
||||
ed25519/ecdsagen.$(OBJEXT): ed25519/$(am__dirstamp) \
|
||||
ed25519/$(DEPDIR)/$(am__dirstamp)
|
||||
ed25519/add_scalar.$(OBJEXT): ed25519/$(am__dirstamp) \
|
||||
ed25519/$(DEPDIR)/$(am__dirstamp)
|
||||
ed25519/fe.$(OBJEXT): ed25519/$(am__dirstamp) \
|
||||
|
|
@ -691,12 +755,22 @@ openssl/$(DEPDIR)/$(am__dirstamp):
|
|||
@: > openssl/$(DEPDIR)/$(am__dirstamp)
|
||||
openssl/crypto.$(OBJEXT): openssl/$(am__dirstamp) \
|
||||
openssl/$(DEPDIR)/$(am__dirstamp)
|
||||
ed25519/ecdsagen.$(OBJEXT): ed25519/$(am__dirstamp) \
|
||||
ed25519/$(DEPDIR)/$(am__dirstamp)
|
||||
nolegacy/$(am__dirstamp):
|
||||
@$(MKDIR_P) nolegacy
|
||||
@: > nolegacy/$(am__dirstamp)
|
||||
nolegacy/$(DEPDIR)/$(am__dirstamp):
|
||||
@$(MKDIR_P) nolegacy/$(DEPDIR)
|
||||
@: > nolegacy/$(DEPDIR)/$(am__dirstamp)
|
||||
nolegacy/crypto.$(OBJEXT): nolegacy/$(am__dirstamp) \
|
||||
nolegacy/$(DEPDIR)/$(am__dirstamp)
|
||||
|
||||
sptps_keypair$(EXEEXT): $(sptps_keypair_OBJECTS) $(sptps_keypair_DEPENDENCIES) $(EXTRA_sptps_keypair_DEPENDENCIES)
|
||||
@rm -f sptps_keypair$(EXEEXT)
|
||||
$(AM_V_CCLD)$(LINK) $(sptps_keypair_OBJECTS) $(sptps_keypair_LDADD) $(LIBS)
|
||||
ed25519/ecdh.$(OBJEXT): ed25519/$(am__dirstamp) \
|
||||
ed25519/$(DEPDIR)/$(am__dirstamp)
|
||||
ed25519/ecdsa.$(OBJEXT): ed25519/$(am__dirstamp) \
|
||||
ed25519/$(DEPDIR)/$(am__dirstamp)
|
||||
chacha-poly1305/$(am__dirstamp):
|
||||
@$(MKDIR_P) chacha-poly1305
|
||||
@: > chacha-poly1305/$(am__dirstamp)
|
||||
|
|
@ -712,12 +786,10 @@ chacha-poly1305/poly1305.$(OBJEXT): chacha-poly1305/$(am__dirstamp) \
|
|||
chacha-poly1305/$(DEPDIR)/$(am__dirstamp)
|
||||
openssl/digest.$(OBJEXT): openssl/$(am__dirstamp) \
|
||||
openssl/$(DEPDIR)/$(am__dirstamp)
|
||||
ed25519/ecdh.$(OBJEXT): ed25519/$(am__dirstamp) \
|
||||
ed25519/$(DEPDIR)/$(am__dirstamp)
|
||||
ed25519/ecdsa.$(OBJEXT): ed25519/$(am__dirstamp) \
|
||||
ed25519/$(DEPDIR)/$(am__dirstamp)
|
||||
openssl/prf.$(OBJEXT): openssl/$(am__dirstamp) \
|
||||
openssl/$(DEPDIR)/$(am__dirstamp)
|
||||
nolegacy/prf.$(OBJEXT): nolegacy/$(am__dirstamp) \
|
||||
nolegacy/$(DEPDIR)/$(am__dirstamp)
|
||||
|
||||
sptps_speed$(EXEEXT): $(sptps_speed_OBJECTS) $(sptps_speed_DEPENDENCIES) $(EXTRA_sptps_speed_DEPENDENCIES)
|
||||
@rm -f sptps_speed$(EXEEXT)
|
||||
|
|
@ -734,10 +806,6 @@ gcrypt/crypto.$(OBJEXT): gcrypt/$(am__dirstamp) \
|
|||
gcrypt/$(DEPDIR)/$(am__dirstamp)
|
||||
gcrypt/digest.$(OBJEXT): gcrypt/$(am__dirstamp) \
|
||||
gcrypt/$(DEPDIR)/$(am__dirstamp)
|
||||
gcrypt/ecdh.$(OBJEXT): gcrypt/$(am__dirstamp) \
|
||||
gcrypt/$(DEPDIR)/$(am__dirstamp)
|
||||
gcrypt/ecdsa.$(OBJEXT): gcrypt/$(am__dirstamp) \
|
||||
gcrypt/$(DEPDIR)/$(am__dirstamp)
|
||||
gcrypt/prf.$(OBJEXT): gcrypt/$(am__dirstamp) \
|
||||
gcrypt/$(DEPDIR)/$(am__dirstamp)
|
||||
|
||||
|
|
@ -750,8 +818,6 @@ openssl/rsa.$(OBJEXT): openssl/$(am__dirstamp) \
|
|||
openssl/$(DEPDIR)/$(am__dirstamp)
|
||||
openssl/rsagen.$(OBJEXT): openssl/$(am__dirstamp) \
|
||||
openssl/$(DEPDIR)/$(am__dirstamp)
|
||||
gcrypt/ecdsagen.$(OBJEXT): gcrypt/$(am__dirstamp) \
|
||||
gcrypt/$(DEPDIR)/$(am__dirstamp)
|
||||
gcrypt/rsa.$(OBJEXT): gcrypt/$(am__dirstamp) \
|
||||
gcrypt/$(DEPDIR)/$(am__dirstamp)
|
||||
gcrypt/rsagen.$(OBJEXT): gcrypt/$(am__dirstamp) \
|
||||
|
|
@ -805,7 +871,7 @@ cygwin/device.$(OBJEXT): cygwin/$(am__dirstamp) \
|
|||
|
||||
tincd$(EXEEXT): $(tincd_OBJECTS) $(tincd_DEPENDENCIES) $(EXTRA_tincd_DEPENDENCIES)
|
||||
@rm -f tincd$(EXEEXT)
|
||||
$(AM_V_CCLD)$(LINK) $(tincd_OBJECTS) $(tincd_LDADD) $(LIBS)
|
||||
$(AM_V_CCLD)$(tincd_LINK) $(tincd_OBJECTS) $(tincd_LDADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
|
@ -816,6 +882,7 @@ mostlyclean-compile:
|
|||
-rm -f gcrypt/*.$(OBJEXT)
|
||||
-rm -f linux/*.$(OBJEXT)
|
||||
-rm -f mingw/*.$(OBJEXT)
|
||||
-rm -f nolegacy/*.$(OBJEXT)
|
||||
-rm -f openssl/*.$(OBJEXT)
|
||||
-rm -f solaris/*.$(OBJEXT)
|
||||
|
||||
|
|
@ -830,12 +897,12 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dummy_device.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edge.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fake-getaddrinfo.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fake-getnameinfo.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@
|
||||
|
|
@ -870,6 +937,7 @@ distclean-compile:
|
|||
@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@
|
||||
|
|
@ -894,14 +962,13 @@ distclean-compile:
|
|||
@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)/ecdh.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/ecdsa.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/ecdsagen.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@
|
||||
|
|
@ -1037,6 +1104,7 @@ install-strip:
|
|||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
|
|
@ -1055,6 +1123,8 @@ distclean-generic:
|
|||
-rm -f linux/$(am__dirstamp)
|
||||
-rm -f mingw/$(DEPDIR)/$(am__dirstamp)
|
||||
-rm -f mingw/$(am__dirstamp)
|
||||
-rm -f nolegacy/$(DEPDIR)/$(am__dirstamp)
|
||||
-rm -f nolegacy/$(am__dirstamp)
|
||||
-rm -f openssl/$(DEPDIR)/$(am__dirstamp)
|
||||
-rm -f openssl/$(am__dirstamp)
|
||||
-rm -f solaris/$(DEPDIR)/$(am__dirstamp)
|
||||
|
|
@ -1068,7 +1138,7 @@ clean: clean-am
|
|||
clean-am: 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) openssl/$(DEPDIR) solaris/$(DEPDIR)
|
||||
-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 Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
|
@ -1114,7 +1184,7 @@ 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) openssl/$(DEPDIR) solaris/$(DEPDIR)
|
||||
-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 Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
|
|
@ -1148,9 +1218,18 @@ uninstall-am: uninstall-sbinPROGRAMS
|
|||
mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
|
||||
uninstall-am uninstall-sbinPROGRAMS
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
.PHONY: version.c
|
||||
version.c:
|
||||
|
||||
.PHONY: version-stamp
|
||||
version-stamp:
|
||||
|
||||
version_git.h: version-stamp
|
||||
$(AM_V_GEN)echo >$@
|
||||
@-(cd $(srcdir) && git describe 2>/dev/null >/dev/null) && echo '#define GIT_DESCRIPTION "'`(cd $(srcdir) && git describe) | sed 's/release-//'`'"' >$@ ||:
|
||||
${srcdir}/version.c: version_git.h
|
||||
|
||||
@BSD_TRUE@version.c: ${srcdir}/version.c
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
|
|
|
|||
156
src/bsd/device.c
156
src/bsd/device.c
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
device.c -- Interaction BSD tun/tap device
|
||||
Copyright (C) 2001-2005 Ivo Timmermans,
|
||||
2001-2014 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2001-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2009 Grzegorz Dymarek <gregd72002@googlemail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
|
@ -34,13 +34,15 @@
|
|||
#include "bsd/tunemu.h"
|
||||
#endif
|
||||
|
||||
#define DEFAULT_TUN_DEVICE "/dev/tun0"
|
||||
#if defined(HAVE_DARWIN) || defined(HAVE_FREEBSD) || defined(HAVE_NETBSD)
|
||||
#define DEFAULT_TAP_DEVICE "/dev/tap0"
|
||||
#else
|
||||
#define DEFAULT_TAP_DEVICE "/dev/tun0"
|
||||
#ifdef HAVE_NET_IF_UTUN_H
|
||||
#include <sys/sys_domain.h>
|
||||
#include <sys/kern_control.h>
|
||||
#include <net/if_utun.h>
|
||||
#endif
|
||||
|
||||
#define DEFAULT_TUN_DEVICE "/dev/tun0"
|
||||
#define DEFAULT_TAP_DEVICE "/dev/tap0"
|
||||
|
||||
typedef enum device_type {
|
||||
DEVICE_TYPE_TUN,
|
||||
DEVICE_TYPE_TUNIFHEAD,
|
||||
|
|
@ -48,6 +50,7 @@ typedef enum device_type {
|
|||
#ifdef ENABLE_TUNEMU
|
||||
DEVICE_TYPE_TUNEMU,
|
||||
#endif
|
||||
DEVICE_TYPE_UTUN,
|
||||
} device_type_t;
|
||||
|
||||
int device_fd = -1;
|
||||
|
|
@ -62,9 +65,64 @@ static device_type_t device_type = DEVICE_TYPE_TUNIFHEAD;
|
|||
static device_type_t device_type = DEVICE_TYPE_TUN;
|
||||
#endif
|
||||
|
||||
#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);
|
||||
|
||||
if(ioctl(device_fd, CTLIOCGINFO, &info) == -1) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "ioctl(CTLIOCGINFO) failed: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
int unit = -1;
|
||||
char *p = strstr(device, "utun"), *e = NULL;
|
||||
if(p) {
|
||||
unit = strtol(p + 4, &e, 10);
|
||||
if(!e)
|
||||
unit = -1;
|
||||
}
|
||||
|
||||
struct sockaddr_ctl sc = {
|
||||
.sc_id = info.ctl_id,
|
||||
.sc_len = sizeof sc,
|
||||
.sc_family = AF_SYSTEM,
|
||||
.ss_sysaddr = AF_SYS_CONTROL,
|
||||
.sc_unit = unit + 1,
|
||||
};
|
||||
|
||||
if(connect(device_fd, (struct sockaddr *)&sc, sizeof(sc)) == -1) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Could not connect utun socket: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
char name[64] = "";
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool setup_device(void) {
|
||||
get_config_string(lookup_config(config_tree, "Device"), &device);
|
||||
|
||||
// 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"))
|
||||
|
|
@ -72,6 +130,10 @@ static bool setup_device(void) {
|
|||
#ifdef ENABLE_TUNEMU
|
||||
else if(!strcasecmp(type, "tunemu"))
|
||||
device_type = DEVICE_TYPE_TUNEMU;
|
||||
#endif
|
||||
#ifdef HAVE_NET_IF_UTUN_H
|
||||
else if(!strcasecmp(type, "utun"))
|
||||
device_type = DEVICE_TYPE_UTUN;
|
||||
#endif
|
||||
else if(!strcasecmp(type, "tunnohead"))
|
||||
device_type = DEVICE_TYPE_TUN;
|
||||
|
|
@ -84,10 +146,22 @@ static bool setup_device(void) {
|
|||
return false;
|
||||
}
|
||||
} else {
|
||||
#ifdef HAVE_NET_IF_UTUN_H
|
||||
if(device && (strncmp(device, "utun", 4) == 0 || strncmp(device, "/dev/utun", 9) == 0))
|
||||
device_type = DEVICE_TYPE_UTUN;
|
||||
else
|
||||
#endif
|
||||
if((device && strstr(device, "tap")) || routing_mode != RMODE_ROUTER)
|
||||
device_type = DEVICE_TYPE_TAP;
|
||||
}
|
||||
|
||||
if(routing_mode == RMODE_SWITCH && device_type != DEVICE_TYPE_TAP) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Only tap devices support switch mode!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find out which device file to open
|
||||
|
||||
if(!device) {
|
||||
if(device_type == DEVICE_TYPE_TAP)
|
||||
device = xstrdup(DEFAULT_TAP_DEVICE);
|
||||
|
|
@ -95,17 +169,7 @@ static bool setup_device(void) {
|
|||
device = xstrdup(DEFAULT_TUN_DEVICE);
|
||||
}
|
||||
|
||||
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
|
||||
iface = NULL;
|
||||
#ifndef TAPGIFNAME
|
||||
if (iface) {
|
||||
logger(DEBUG_ALWAYS, LOG_WARNING, "Ignoring specified interface name '%s' as device rename is not supported on this platform", iface);
|
||||
free(iface);
|
||||
iface = NULL;
|
||||
}
|
||||
#endif
|
||||
if (!iface)
|
||||
iface = xstrdup(strrchr(device, '/') ? strrchr(device, '/') + 1 : device);
|
||||
// Open the device
|
||||
|
||||
switch(device_type) {
|
||||
#ifdef ENABLE_TUNEMU
|
||||
|
|
@ -114,6 +178,10 @@ static bool setup_device(void) {
|
|||
device_fd = tunemu_open(dynamic_name);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_NET_IF_UTUN_H
|
||||
case DEVICE_TYPE_UTUN:
|
||||
return setup_utun();
|
||||
#endif
|
||||
default:
|
||||
device_fd = open(device, O_RDWR | O_NONBLOCK);
|
||||
|
|
@ -128,6 +196,27 @@ static bool setup_device(void) {
|
|||
fcntl(device_fd, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
// Guess what the corresponding interface is called
|
||||
|
||||
char *realname;
|
||||
|
||||
#if defined(HAVE_FDEVNAME)
|
||||
realname = fdevname(device_fd) ? : device;
|
||||
#elif defined(HAVE_DEVNAME)
|
||||
struct stat buf;
|
||||
if(!fstat(device_fd, &buf))
|
||||
realname = devname(buf.st_rdev, S_IFCHR) ? : device;
|
||||
#else
|
||||
realname = device;
|
||||
#endif
|
||||
|
||||
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))
|
||||
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;
|
||||
|
|
@ -192,6 +281,11 @@ static bool setup_device(void) {
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef SIOCGIFADDR
|
||||
if(overwrite_mac)
|
||||
ioctl(device_fd, SIOCGIFADDR, mymac.x);
|
||||
#endif
|
||||
|
||||
logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
|
||||
|
||||
return true;
|
||||
|
|
@ -253,31 +347,29 @@ static bool read_packet(vpn_packet_t *packet) {
|
|||
packet->len = inlen + 14;
|
||||
break;
|
||||
|
||||
case DEVICE_TYPE_UTUN:
|
||||
case DEVICE_TYPE_TUNIFHEAD: {
|
||||
u_int32_t type;
|
||||
struct iovec vector[2] = {{&type, sizeof type}, {DATA(packet) + 14, MTU - 14}};
|
||||
|
||||
if((inlen = readv(device_fd, vector, 2)) <= 0) {
|
||||
if((inlen = read(device_fd, packet->data + 10, MTU - 10)) <= 0) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
|
||||
device, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (ntohl(type)) {
|
||||
case AF_INET:
|
||||
switch (packet->data[14] >> 4) {
|
||||
case 4:
|
||||
DATA(packet)[12] = 0x08;
|
||||
DATA(packet)[13] = 0x00;
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
case 6:
|
||||
DATA(packet)[12] = 0x86;
|
||||
DATA(packet)[13] = 0xDD;
|
||||
break;
|
||||
|
||||
default:
|
||||
logger(DEBUG_TRAFFIC, LOG_ERR,
|
||||
"Unknown address family %x while reading packet from %s %s",
|
||||
ntohl(type), device_info, device);
|
||||
"Unknown IP version %d while reading packet from %s %s",
|
||||
packet->data[14] >> 4, device_info, device);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -319,12 +411,10 @@ static bool write_packet(vpn_packet_t *packet) {
|
|||
}
|
||||
break;
|
||||
|
||||
case DEVICE_TYPE_UTUN:
|
||||
case DEVICE_TYPE_TUNIFHEAD: {
|
||||
u_int32_t type;
|
||||
struct iovec vector[2] = {{&type, sizeof type}, {DATA(packet) + 14, packet->len - 14}};
|
||||
int af;
|
||||
|
||||
af = (DATA(packet)[12] << 8) + DATA(packet)[13];
|
||||
int af = (DATA(packet)[12] << 8) + DATA(packet)[13];
|
||||
uint32_t type;
|
||||
|
||||
switch (af) {
|
||||
case 0x0800:
|
||||
|
|
@ -340,7 +430,9 @@ static bool write_packet(vpn_packet_t *packet) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if(writev(device_fd, vector, 2) < 0) {
|
||||
memcpy(packet->data + 10, &type, sizeof type);
|
||||
|
||||
if(write(device_fd, packet->data + 10, packet->len - 10) < 0) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
|
||||
strerror(errno));
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
#define CIPHER_MAX_IV_SIZE 16
|
||||
#define CIPHER_MAX_KEY_SIZE 32
|
||||
|
||||
#ifndef DISABLE_LEGACY
|
||||
|
||||
typedef struct cipher cipher_t;
|
||||
|
||||
extern cipher_t *cipher_open_by_name(const char *) __attribute__ ((__malloc__));
|
||||
|
|
@ -31,6 +33,7 @@ extern cipher_t *cipher_open_by_nid(int) __attribute__ ((__malloc__));
|
|||
extern cipher_t *cipher_open_blowfish_ofb(void) __attribute__ ((__malloc__));
|
||||
extern void cipher_close(cipher_t *);
|
||||
extern size_t cipher_keylength(const cipher_t *);
|
||||
extern size_t cipher_blocksize(const cipher_t *);
|
||||
extern 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__));
|
||||
|
|
@ -40,3 +43,5 @@ extern int cipher_get_nid(const cipher_t *);
|
|||
extern bool cipher_active(const cipher_t *);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
39
src/conf.c
39
src/conf.c
|
|
@ -4,7 +4,7 @@
|
|||
1998-2005 Ivo Timmermans
|
||||
2000 Cris van Pelt
|
||||
2010-2011 Julien Muchembled <jm@jmuchemb.eu>
|
||||
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2015 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2013 Florent Clairambault <florent@clairambault.fr>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
|
@ -298,7 +298,7 @@ bool read_config_file(splay_tree_t *config_tree, const char *fname) {
|
|||
fp = fopen(fname, "r");
|
||||
|
||||
if(!fp) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Cannot open config file %s: %s", fname, strerror(errno));
|
||||
logger(DEBUG_ALWAYS, LOG_DEBUG, "Cannot open config file %s: %s", fname, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -368,19 +368,19 @@ void read_config_options(splay_tree_t *config_tree, const char *prefix) {
|
|||
}
|
||||
|
||||
bool read_server_config(void) {
|
||||
char *fname;
|
||||
char fname[PATH_MAX];
|
||||
bool x;
|
||||
|
||||
read_config_options(config_tree, NULL);
|
||||
|
||||
xasprintf(&fname, "%s" SLASH "tinc.conf", confbase);
|
||||
snprintf(fname, sizeof fname, "%s" SLASH "tinc.conf", confbase);
|
||||
errno = 0;
|
||||
x = read_config_file(config_tree, fname);
|
||||
|
||||
// We will try to read the conf files in the "conf.d" dir
|
||||
if (x) {
|
||||
char * dname;
|
||||
xasprintf(&dname, "%s" SLASH "conf.d", confbase);
|
||||
char dname[PATH_MAX];
|
||||
snprintf(dname, sizeof dname, "%s" SLASH "conf.d", confbase);
|
||||
DIR *dir = opendir (dname);
|
||||
// If we can find this dir
|
||||
if (dir) {
|
||||
|
|
@ -390,51 +390,44 @@ bool read_server_config(void) {
|
|||
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 ])) {
|
||||
free(fname);
|
||||
xasprintf(&fname, "%s" SLASH "%s", dname, ep->d_name);
|
||||
snprintf(fname, sizeof fname, "%s" SLASH "%s", dname, ep->d_name);
|
||||
x = read_config_file(config_tree, fname);
|
||||
}
|
||||
}
|
||||
closedir (dir);
|
||||
}
|
||||
free(dname);
|
||||
}
|
||||
|
||||
if(!x && errno)
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Failed to read `%s': %s", fname, strerror(errno));
|
||||
|
||||
free(fname);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
bool read_host_config(splay_tree_t *config_tree, const char *name) {
|
||||
char *fname;
|
||||
char fname[PATH_MAX];
|
||||
bool x;
|
||||
|
||||
read_config_options(config_tree, name);
|
||||
|
||||
xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
|
||||
snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
|
||||
x = read_config_file(config_tree, fname);
|
||||
free(fname);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
bool append_config_file(const char *name, const char *key, const char *value) {
|
||||
char *fname;
|
||||
xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
|
||||
char fname[PATH_MAX];
|
||||
snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
|
||||
|
||||
FILE *fp = fopen(fname, "a");
|
||||
|
||||
if(!fp) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Cannot open config file %s: %s", fname, strerror(errno));
|
||||
} else {
|
||||
fprintf(fp, "\n# The following line was automatically added by tinc\n%s = %s\n", key, value);
|
||||
fclose(fp);
|
||||
logger(DEBUG_ALWAYS, LOG_DEBUG, "Cannot open config file %s: %s", fname, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
free(fname);
|
||||
|
||||
return fp != NULL;
|
||||
fprintf(fp, "\n# The following line was automatically added by tinc\n%s = %s\n", key, value);
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,9 @@
|
|||
#ifndef __TINC_CONF_H__
|
||||
#define __TINC_CONF_H__
|
||||
|
||||
#include "splay_tree.h"
|
||||
#include "list.h"
|
||||
#include "splay_tree.h"
|
||||
#include "subnet.h"
|
||||
|
||||
typedef struct config_t {
|
||||
char *variable;
|
||||
|
|
@ -31,7 +32,6 @@ typedef struct config_t {
|
|||
int line;
|
||||
} config_t;
|
||||
|
||||
#include "subnet.h"
|
||||
|
||||
extern splay_tree_t *config_tree;
|
||||
|
||||
|
|
|
|||
|
|
@ -55,14 +55,16 @@ void free_connection(connection_t *c) {
|
|||
if(!c)
|
||||
return;
|
||||
|
||||
#ifndef DISABLE_LEGACY
|
||||
cipher_close(c->incipher);
|
||||
digest_close(c->indigest);
|
||||
cipher_close(c->outcipher);
|
||||
digest_close(c->outdigest);
|
||||
rsa_free(c->rsa);
|
||||
#endif
|
||||
|
||||
sptps_stop(&c->sptps);
|
||||
ecdsa_free(c->ecdsa);
|
||||
rsa_free(c->rsa);
|
||||
|
||||
free(c->hischallenge);
|
||||
|
||||
|
|
|
|||
|
|
@ -59,9 +59,9 @@ typedef struct connection_status_t {
|
|||
|
||||
typedef struct connection_t {
|
||||
char *name; /* name he claims to have */
|
||||
char *hostname; /* the hostname of its real ip */
|
||||
|
||||
union sockaddr_t address; /* his real (internet) ip */
|
||||
char *hostname; /* the hostname of its real ip */
|
||||
int protocol_major; /* used protocol */
|
||||
int protocol_minor; /* used protocol */
|
||||
|
||||
|
|
@ -75,12 +75,15 @@ typedef struct connection_t {
|
|||
struct node_t *node; /* node associated with the other end */
|
||||
struct edge_t *edge; /* edge associated with this connection */
|
||||
|
||||
#ifndef DISABLE_LEGACY
|
||||
rsa_t *rsa; /* his public RSA key */
|
||||
ecdsa_t *ecdsa; /* his public ECDSA key */
|
||||
cipher_t *incipher; /* Cipher he will use to send data to us */
|
||||
cipher_t *outcipher; /* Cipher we will use to send data to him */
|
||||
digest_t *indigest;
|
||||
digest_t *outdigest;
|
||||
#endif
|
||||
|
||||
ecdsa_t *ecdsa; /* his public ECDSA key */
|
||||
sptps_t sptps;
|
||||
|
||||
int inmaclength;
|
||||
|
|
@ -94,6 +97,7 @@ typedef struct connection_t {
|
|||
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 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 */
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#include "../system.h"
|
||||
#include "../net.h"
|
||||
|
||||
#include <w32api/windows.h>
|
||||
#include <w32api/winioctl.h>
|
||||
|
|
@ -27,7 +28,6 @@
|
|||
#include "../device.h"
|
||||
#include "../logger.h"
|
||||
#include "../names.h"
|
||||
#include "../net.h"
|
||||
#include "../route.h"
|
||||
#include "../utils.h"
|
||||
#include "../xalloc.h"
|
||||
|
|
@ -59,6 +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)
|
||||
logger(LOG_WARNING, "Warning: both Device and Interface specified, results may not be as expected");
|
||||
|
||||
/* Open registry and look for network adapters */
|
||||
|
||||
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &key)) {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
#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__));
|
||||
|
|
@ -37,3 +39,5 @@ extern size_t digest_length(const digest_t *);
|
|||
extern bool digest_active(const digest_t *);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
45
src/dropin.c
45
src/dropin.c
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
dropin.c -- a set of drop-in replacements for libc functions
|
||||
Copyright (C) 2000-2005 Ivo Timmermans,
|
||||
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -86,40 +86,6 @@ int daemon(int nochdir, int noclose) {
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GET_CURRENT_DIR_NAME
|
||||
/*
|
||||
Replacement for the GNU get_current_dir_name function:
|
||||
|
||||
get_current_dir_name will malloc(3) an array big enough to hold the
|
||||
current directory name. If the environment variable PWD is set, and
|
||||
its value is correct, then that value will be returned.
|
||||
*/
|
||||
char *get_current_dir_name(void) {
|
||||
size_t size;
|
||||
char *buf;
|
||||
char *r;
|
||||
|
||||
/* Start with 100 bytes. If this turns out to be insufficient to
|
||||
contain the working directory, double the size. */
|
||||
size = 100;
|
||||
buf = xmalloc(size);
|
||||
|
||||
errno = 0; /* Success */
|
||||
r = getcwd(buf, size);
|
||||
|
||||
/* getcwd returns NULL and sets errno to ERANGE if the bufferspace
|
||||
is insufficient to contain the entire working directory. */
|
||||
while(r == NULL && errno == ERANGE) {
|
||||
free(buf);
|
||||
size <<= 1; /* double the size */
|
||||
buf = xmalloc(size);
|
||||
r = getcwd(buf, size);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ASPRINTF
|
||||
int asprintf(char **buf, const char *fmt, ...) {
|
||||
int result;
|
||||
|
|
@ -174,10 +140,9 @@ int gettimeofday(struct timeval *tv, void *tz) {
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_USLEEP
|
||||
int usleep(long long usec) {
|
||||
struct timeval tv = {usec / 1000000, (usec / 1000) % 1000};
|
||||
select(0, NULL, NULL, NULL, &tv);
|
||||
return 0;
|
||||
#ifndef HAVE_NANOSLEEP
|
||||
int nanosleep(const struct timespec *req, struct timespec *rem) {
|
||||
struct timeval tv = {req->tv_sec, req->tv_nsec / 1000};
|
||||
return select(0, NULL, NULL, NULL, &tv);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
17
src/dropin.h
17
src/dropin.h
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
dropin.h -- header file for dropin.c
|
||||
Copyright (C) 2000-2005 Ivo Timmermans,
|
||||
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -21,17 +21,10 @@
|
|||
#ifndef __DROPIN_H__
|
||||
#define __DROPIN_H__
|
||||
|
||||
#include "fake-getaddrinfo.h"
|
||||
#include "fake-getnameinfo.h"
|
||||
|
||||
#ifndef HAVE_DAEMON
|
||||
extern int daemon(int, int);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GET_CURRENT_DIR_NAME
|
||||
extern char *get_current_dir_name(void);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ASPRINTF
|
||||
extern int asprintf(char **, const char *, ...);
|
||||
extern int vasprintf(char **, const char *, va_list ap);
|
||||
|
|
@ -41,8 +34,8 @@ extern int vasprintf(char **, const char *, va_list ap);
|
|||
extern int gettimeofday(struct timeval *, void *);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_USLEEP
|
||||
extern int usleep(long long usec);
|
||||
#ifndef HAVE_NANOSLEEP
|
||||
extern int nanosleep(const struct timespec *req, struct timespec *rem);
|
||||
#endif
|
||||
|
||||
#ifndef timeradd
|
||||
|
|
@ -70,4 +63,8 @@ extern int usleep(long long usec);
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef EAI_SYSTEM
|
||||
#define EAI_SYSTEM 0
|
||||
#endif
|
||||
|
||||
#endif /* __DROPIN_H__ */
|
||||
|
|
|
|||
|
|
@ -84,11 +84,13 @@ static bool read_pem(FILE *fp, const char *type, void *buf, size_t size) {
|
|||
size_t len = b64decode(line, line, linelen);
|
||||
if(!len) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Invalid base64 data in PEM file\n");
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(len > size) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Too much base64 data in PEM file\n");
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -98,7 +100,12 @@ static bool read_pem(FILE *fp, const char *type, void *buf, size_t size) {
|
|||
}
|
||||
|
||||
if(size) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Too little base64 data in PEM file\n");
|
||||
if(data) {
|
||||
errno = EINVAL;
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Too little base64 data in PEM file\n");
|
||||
} else {
|
||||
errno = ENOENT;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
274
src/ed25519/fe.c
274
src/ed25519/fe.c
|
|
@ -8,9 +8,9 @@
|
|||
static uint64_t load_3(const unsigned char *in) {
|
||||
uint64_t result;
|
||||
|
||||
result = (uint64_t) in[0];
|
||||
result |= ((uint64_t) in[1]) << 8;
|
||||
result |= ((uint64_t) in[2]) << 16;
|
||||
result = in[0];
|
||||
result |= shlu64(in[1], 8);
|
||||
result |= shlu64(in[2], 16);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -18,10 +18,10 @@ static uint64_t load_3(const unsigned char *in) {
|
|||
static uint64_t load_4(const unsigned char *in) {
|
||||
uint64_t result;
|
||||
|
||||
result = (uint64_t) in[0];
|
||||
result |= ((uint64_t) in[1]) << 8;
|
||||
result |= ((uint64_t) in[2]) << 16;
|
||||
result |= ((uint64_t) in[3]) << 24;
|
||||
result = in[0];
|
||||
result |= shlu64(in[1], 8);
|
||||
result |= shlu64(in[2], 16);
|
||||
result |= shlu64(in[3], 24);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -316,47 +316,47 @@ void fe_frombytes(fe h, const unsigned char *s) {
|
|||
int64_t carry8;
|
||||
int64_t carry9;
|
||||
|
||||
carry9 = (h9 + (int64_t) (1 << 24)) >> 25;
|
||||
carry9 = (h9 + (1L << 24)) >> 25;
|
||||
h0 += carry9 * 19;
|
||||
h9 -= carry9 << 25;
|
||||
carry1 = (h1 + (int64_t) (1 << 24)) >> 25;
|
||||
h9 -= shl64(carry9, 25);
|
||||
carry1 = (h1 + (1L << 24)) >> 25;
|
||||
h2 += carry1;
|
||||
h1 -= carry1 << 25;
|
||||
carry3 = (h3 + (int64_t) (1 << 24)) >> 25;
|
||||
h1 -= shl64(carry1, 25);
|
||||
carry3 = (h3 + (1L << 24)) >> 25;
|
||||
h4 += carry3;
|
||||
h3 -= carry3 << 25;
|
||||
carry5 = (h5 + (int64_t) (1 << 24)) >> 25;
|
||||
h3 -= shl64(carry3, 25);
|
||||
carry5 = (h5 + (1L << 24)) >> 25;
|
||||
h6 += carry5;
|
||||
h5 -= carry5 << 25;
|
||||
carry7 = (h7 + (int64_t) (1 << 24)) >> 25;
|
||||
h5 -= shl64(carry5, 25);
|
||||
carry7 = (h7 + (1L << 24)) >> 25;
|
||||
h8 += carry7;
|
||||
h7 -= carry7 << 25;
|
||||
carry0 = (h0 + (int64_t) (1 << 25)) >> 26;
|
||||
h7 -= shl64(carry7, 25);
|
||||
carry0 = (h0 + (1L << 25)) >> 26;
|
||||
h1 += carry0;
|
||||
h0 -= carry0 << 26;
|
||||
carry2 = (h2 + (int64_t) (1 << 25)) >> 26;
|
||||
h0 -= shl64(carry0, 26);
|
||||
carry2 = (h2 + (1L << 25)) >> 26;
|
||||
h3 += carry2;
|
||||
h2 -= carry2 << 26;
|
||||
carry4 = (h4 + (int64_t) (1 << 25)) >> 26;
|
||||
h2 -= shl64(carry2, 26);
|
||||
carry4 = (h4 + (1L << 25)) >> 26;
|
||||
h5 += carry4;
|
||||
h4 -= carry4 << 26;
|
||||
carry6 = (h6 + (int64_t) (1 << 25)) >> 26;
|
||||
h4 -= shl64(carry4, 26);
|
||||
carry6 = (h6 + (1L << 25)) >> 26;
|
||||
h7 += carry6;
|
||||
h6 -= carry6 << 26;
|
||||
carry8 = (h8 + (int64_t) (1 << 25)) >> 26;
|
||||
h6 -= shl64(carry6, 26);
|
||||
carry8 = (h8 + (1L << 25)) >> 26;
|
||||
h9 += carry8;
|
||||
h8 -= carry8 << 26;
|
||||
h8 -= shl64(carry8, 26);
|
||||
|
||||
h[0] = (int32_t) h0;
|
||||
h[1] = (int32_t) h1;
|
||||
h[2] = (int32_t) h2;
|
||||
h[3] = (int32_t) h3;
|
||||
h[4] = (int32_t) h4;
|
||||
h[5] = (int32_t) h5;
|
||||
h[6] = (int32_t) h6;
|
||||
h[7] = (int32_t) h7;
|
||||
h[8] = (int32_t) h8;
|
||||
h[9] = (int32_t) h9;
|
||||
h[0] = h0;
|
||||
h[1] = h1;
|
||||
h[2] = h2;
|
||||
h[3] = h3;
|
||||
h[4] = h4;
|
||||
h[5] = h5;
|
||||
h[6] = h6;
|
||||
h[7] = h7;
|
||||
h[8] = h8;
|
||||
h[9] = h9;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -709,48 +709,48 @@ void fe_mul(fe h, const fe f, const fe g) {
|
|||
int64_t carry8;
|
||||
int64_t carry9;
|
||||
|
||||
carry0 = (h0 + (int64_t) (1 << 25)) >> 26;
|
||||
carry0 = (h0 + (1L << 25)) >> 26;
|
||||
h1 += carry0;
|
||||
h0 -= carry0 << 26;
|
||||
carry4 = (h4 + (int64_t) (1 << 25)) >> 26;
|
||||
h0 -= shl64(carry0, 26);
|
||||
carry4 = (h4 + (1L << 25)) >> 26;
|
||||
h5 += carry4;
|
||||
h4 -= carry4 << 26;
|
||||
h4 -= shl64(carry4, 26);
|
||||
|
||||
carry1 = (h1 + (int64_t) (1 << 24)) >> 25;
|
||||
carry1 = (h1 + (1L << 24)) >> 25;
|
||||
h2 += carry1;
|
||||
h1 -= carry1 << 25;
|
||||
carry5 = (h5 + (int64_t) (1 << 24)) >> 25;
|
||||
h1 -= shl64(carry1, 25);
|
||||
carry5 = (h5 + (1L << 24)) >> 25;
|
||||
h6 += carry5;
|
||||
h5 -= carry5 << 25;
|
||||
h5 -= shl64(carry5, 25);
|
||||
|
||||
carry2 = (h2 + (int64_t) (1 << 25)) >> 26;
|
||||
carry2 = (h2 + (1L << 25)) >> 26;
|
||||
h3 += carry2;
|
||||
h2 -= carry2 << 26;
|
||||
carry6 = (h6 + (int64_t) (1 << 25)) >> 26;
|
||||
h2 -= shl64(carry2, 26);
|
||||
carry6 = (h6 + (1L << 25)) >> 26;
|
||||
h7 += carry6;
|
||||
h6 -= carry6 << 26;
|
||||
h6 -= shl64(carry6, 26);
|
||||
|
||||
carry3 = (h3 + (int64_t) (1 << 24)) >> 25;
|
||||
carry3 = (h3 + (1L << 24)) >> 25;
|
||||
h4 += carry3;
|
||||
h3 -= carry3 << 25;
|
||||
carry7 = (h7 + (int64_t) (1 << 24)) >> 25;
|
||||
h3 -= shl64(carry3, 25);
|
||||
carry7 = (h7 + (1L << 24)) >> 25;
|
||||
h8 += carry7;
|
||||
h7 -= carry7 << 25;
|
||||
h7 -= shl64(carry7, 25);
|
||||
|
||||
carry4 = (h4 + (int64_t) (1 << 25)) >> 26;
|
||||
carry4 = (h4 + (1L << 25)) >> 26;
|
||||
h5 += carry4;
|
||||
h4 -= carry4 << 26;
|
||||
carry8 = (h8 + (int64_t) (1 << 25)) >> 26;
|
||||
h4 -= shl64(carry4, 26);
|
||||
carry8 = (h8 + (1L << 25)) >> 26;
|
||||
h9 += carry8;
|
||||
h8 -= carry8 << 26;
|
||||
h8 -= shl64(carry8, 26);
|
||||
|
||||
carry9 = (h9 + (int64_t) (1 << 24)) >> 25;
|
||||
carry9 = (h9 + (1L << 24)) >> 25;
|
||||
h0 += carry9 * 19;
|
||||
h9 -= carry9 << 25;
|
||||
h9 -= shl64(carry9, 25);
|
||||
|
||||
carry0 = (h0 + (int64_t) (1 << 25)) >> 26;
|
||||
carry0 = (h0 + (1L << 25)) >> 26;
|
||||
h1 += carry0;
|
||||
h0 -= carry0 << 26;
|
||||
h0 -= shl64(carry0, 26);
|
||||
|
||||
h[0] = (int32_t) h0;
|
||||
h[1] = (int32_t) h1;
|
||||
|
|
@ -808,17 +808,17 @@ void fe_mul121666(fe h, fe f) {
|
|||
int64_t carry8;
|
||||
int64_t carry9;
|
||||
|
||||
carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
|
||||
carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
|
||||
carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
|
||||
carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
|
||||
carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
|
||||
carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= shl64(carry9, 25);
|
||||
carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= shl64(carry1, 25);
|
||||
carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= shl64(carry3, 25);
|
||||
carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= shl64(carry5, 25);
|
||||
carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= shl64(carry7, 25);
|
||||
|
||||
carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
|
||||
carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
|
||||
carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
|
||||
carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
|
||||
carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
|
||||
carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= shl64(carry0, 26);
|
||||
carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= shl64(carry2, 26);
|
||||
carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= shl64(carry4, 26);
|
||||
carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= shl64(carry6, 26);
|
||||
carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= shl64(carry8, 26);
|
||||
|
||||
h[0] = h0;
|
||||
h[1] = h1;
|
||||
|
|
@ -1078,42 +1078,42 @@ void fe_sq(fe h, const fe f) {
|
|||
int64_t carry7;
|
||||
int64_t carry8;
|
||||
int64_t carry9;
|
||||
carry0 = (h0 + (int64_t) (1 << 25)) >> 26;
|
||||
carry0 = (h0 + (1L << 25)) >> 26;
|
||||
h1 += carry0;
|
||||
h0 -= carry0 << 26;
|
||||
carry4 = (h4 + (int64_t) (1 << 25)) >> 26;
|
||||
h0 -= shl64(carry0, 26);
|
||||
carry4 = (h4 + (1L << 25)) >> 26;
|
||||
h5 += carry4;
|
||||
h4 -= carry4 << 26;
|
||||
carry1 = (h1 + (int64_t) (1 << 24)) >> 25;
|
||||
h4 -= shl64(carry4, 26);
|
||||
carry1 = (h1 + (1L << 24)) >> 25;
|
||||
h2 += carry1;
|
||||
h1 -= carry1 << 25;
|
||||
carry5 = (h5 + (int64_t) (1 << 24)) >> 25;
|
||||
h1 -= shl64(carry1, 25);
|
||||
carry5 = (h5 + (1L << 24)) >> 25;
|
||||
h6 += carry5;
|
||||
h5 -= carry5 << 25;
|
||||
carry2 = (h2 + (int64_t) (1 << 25)) >> 26;
|
||||
h5 -= shl64(carry5, 25);
|
||||
carry2 = (h2 + (1L << 25)) >> 26;
|
||||
h3 += carry2;
|
||||
h2 -= carry2 << 26;
|
||||
carry6 = (h6 + (int64_t) (1 << 25)) >> 26;
|
||||
h2 -= shl64(carry2, 26);
|
||||
carry6 = (h6 + (1L << 25)) >> 26;
|
||||
h7 += carry6;
|
||||
h6 -= carry6 << 26;
|
||||
carry3 = (h3 + (int64_t) (1 << 24)) >> 25;
|
||||
h6 -= shl64(carry6, 26);
|
||||
carry3 = (h3 + (1L << 24)) >> 25;
|
||||
h4 += carry3;
|
||||
h3 -= carry3 << 25;
|
||||
carry7 = (h7 + (int64_t) (1 << 24)) >> 25;
|
||||
h3 -= shl64(carry3, 25);
|
||||
carry7 = (h7 + (1L << 24)) >> 25;
|
||||
h8 += carry7;
|
||||
h7 -= carry7 << 25;
|
||||
carry4 = (h4 + (int64_t) (1 << 25)) >> 26;
|
||||
h7 -= shl64(carry7, 25);
|
||||
carry4 = (h4 + (1L << 25)) >> 26;
|
||||
h5 += carry4;
|
||||
h4 -= carry4 << 26;
|
||||
carry8 = (h8 + (int64_t) (1 << 25)) >> 26;
|
||||
h4 -= shl64(carry4, 26);
|
||||
carry8 = (h8 + (1L << 25)) >> 26;
|
||||
h9 += carry8;
|
||||
h8 -= carry8 << 26;
|
||||
carry9 = (h9 + (int64_t) (1 << 24)) >> 25;
|
||||
h8 -= shl64(carry8, 26);
|
||||
carry9 = (h9 + (1L << 24)) >> 25;
|
||||
h0 += carry9 * 19;
|
||||
h9 -= carry9 << 25;
|
||||
carry0 = (h0 + (int64_t) (1 << 25)) >> 26;
|
||||
h9 -= shl64(carry9, 25);
|
||||
carry0 = (h0 + (1L << 25)) >> 26;
|
||||
h1 += carry0;
|
||||
h0 -= carry0 << 26;
|
||||
h0 -= shl64(carry0, 26);
|
||||
h[0] = (int32_t) h0;
|
||||
h[1] = (int32_t) h1;
|
||||
h[2] = (int32_t) h2;
|
||||
|
|
@ -1251,42 +1251,42 @@ void fe_sq2(fe h, const fe f) {
|
|||
h7 += h7;
|
||||
h8 += h8;
|
||||
h9 += h9;
|
||||
carry0 = (h0 + (int64_t) (1 << 25)) >> 26;
|
||||
carry0 = (h0 + (1L << 25)) >> 26;
|
||||
h1 += carry0;
|
||||
h0 -= carry0 << 26;
|
||||
carry4 = (h4 + (int64_t) (1 << 25)) >> 26;
|
||||
h0 -= shl64(carry0, 26);
|
||||
carry4 = (h4 + (1L << 25)) >> 26;
|
||||
h5 += carry4;
|
||||
h4 -= carry4 << 26;
|
||||
carry1 = (h1 + (int64_t) (1 << 24)) >> 25;
|
||||
h4 -= shl64(carry4, 26);
|
||||
carry1 = (h1 + (1L << 24)) >> 25;
|
||||
h2 += carry1;
|
||||
h1 -= carry1 << 25;
|
||||
carry5 = (h5 + (int64_t) (1 << 24)) >> 25;
|
||||
h1 -= shl64(carry1, 25);
|
||||
carry5 = (h5 + (1L << 24)) >> 25;
|
||||
h6 += carry5;
|
||||
h5 -= carry5 << 25;
|
||||
carry2 = (h2 + (int64_t) (1 << 25)) >> 26;
|
||||
h5 -= shl64(carry5, 25);
|
||||
carry2 = (h2 + (1L << 25)) >> 26;
|
||||
h3 += carry2;
|
||||
h2 -= carry2 << 26;
|
||||
carry6 = (h6 + (int64_t) (1 << 25)) >> 26;
|
||||
h2 -= shl64(carry2, 26);
|
||||
carry6 = (h6 + (1L << 25)) >> 26;
|
||||
h7 += carry6;
|
||||
h6 -= carry6 << 26;
|
||||
carry3 = (h3 + (int64_t) (1 << 24)) >> 25;
|
||||
h6 -= shl64(carry6, 26);
|
||||
carry3 = (h3 + (1L << 24)) >> 25;
|
||||
h4 += carry3;
|
||||
h3 -= carry3 << 25;
|
||||
carry7 = (h7 + (int64_t) (1 << 24)) >> 25;
|
||||
h3 -= shl64(carry3, 25);
|
||||
carry7 = (h7 + (1L << 24)) >> 25;
|
||||
h8 += carry7;
|
||||
h7 -= carry7 << 25;
|
||||
carry4 = (h4 + (int64_t) (1 << 25)) >> 26;
|
||||
h7 -= shl64(carry7, 25);
|
||||
carry4 = (h4 + (1L << 25)) >> 26;
|
||||
h5 += carry4;
|
||||
h4 -= carry4 << 26;
|
||||
carry8 = (h8 + (int64_t) (1 << 25)) >> 26;
|
||||
h4 -= shl64(carry4, 26);
|
||||
carry8 = (h8 + (1L << 25)) >> 26;
|
||||
h9 += carry8;
|
||||
h8 -= carry8 << 26;
|
||||
carry9 = (h9 + (int64_t) (1 << 24)) >> 25;
|
||||
h8 -= shl64(carry8, 26);
|
||||
carry9 = (h9 + (1L << 24)) >> 25;
|
||||
h0 += carry9 * 19;
|
||||
h9 -= carry9 << 25;
|
||||
carry0 = (h0 + (int64_t) (1 << 25)) >> 26;
|
||||
h9 -= shl64(carry9, 25);
|
||||
carry0 = (h0 + (1L << 25)) >> 26;
|
||||
h1 += carry0;
|
||||
h0 -= carry0 << 26;
|
||||
h0 -= shl64(carry0, 26);
|
||||
h[0] = (int32_t) h0;
|
||||
h[1] = (int32_t) h1;
|
||||
h[2] = (int32_t) h2;
|
||||
|
|
@ -1421,33 +1421,33 @@ void fe_tobytes(unsigned char *s, const fe h) {
|
|||
/* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */
|
||||
carry0 = h0 >> 26;
|
||||
h1 += carry0;
|
||||
h0 -= carry0 << 26;
|
||||
h0 -= shl32(carry0, 26);
|
||||
carry1 = h1 >> 25;
|
||||
h2 += carry1;
|
||||
h1 -= carry1 << 25;
|
||||
h1 -= shl32(carry1, 25);
|
||||
carry2 = h2 >> 26;
|
||||
h3 += carry2;
|
||||
h2 -= carry2 << 26;
|
||||
h2 -= shl32(carry2, 26);
|
||||
carry3 = h3 >> 25;
|
||||
h4 += carry3;
|
||||
h3 -= carry3 << 25;
|
||||
h3 -= shl32(carry3, 25);
|
||||
carry4 = h4 >> 26;
|
||||
h5 += carry4;
|
||||
h4 -= carry4 << 26;
|
||||
h4 -= shl32(carry4, 26);
|
||||
carry5 = h5 >> 25;
|
||||
h6 += carry5;
|
||||
h5 -= carry5 << 25;
|
||||
h5 -= shl32(carry5, 25);
|
||||
carry6 = h6 >> 26;
|
||||
h7 += carry6;
|
||||
h6 -= carry6 << 26;
|
||||
h6 -= shl32(carry6, 26);
|
||||
carry7 = h7 >> 25;
|
||||
h8 += carry7;
|
||||
h7 -= carry7 << 25;
|
||||
h7 -= shl32(carry7, 25);
|
||||
carry8 = h8 >> 26;
|
||||
h9 += carry8;
|
||||
h8 -= carry8 << 26;
|
||||
h8 -= shl32(carry8, 26);
|
||||
carry9 = h9 >> 25;
|
||||
h9 -= carry9 << 25;
|
||||
h9 -= shl32(carry9, 25);
|
||||
|
||||
/* h10 = carry9 */
|
||||
/*
|
||||
|
|
@ -1459,32 +1459,32 @@ void fe_tobytes(unsigned char *s, const fe h) {
|
|||
s[0] = (unsigned char) (h0 >> 0);
|
||||
s[1] = (unsigned char) (h0 >> 8);
|
||||
s[2] = (unsigned char) (h0 >> 16);
|
||||
s[3] = (unsigned char) ((h0 >> 24) | (h1 << 2));
|
||||
s[3] = (unsigned char) ((h0 >> 24) | shl32(h1, 2));
|
||||
s[4] = (unsigned char) (h1 >> 6);
|
||||
s[5] = (unsigned char) (h1 >> 14);
|
||||
s[6] = (unsigned char) ((h1 >> 22) | (h2 << 3));
|
||||
s[6] = (unsigned char) ((h1 >> 22) | shl32(h2, 3));
|
||||
s[7] = (unsigned char) (h2 >> 5);
|
||||
s[8] = (unsigned char) (h2 >> 13);
|
||||
s[9] = (unsigned char) ((h2 >> 21) | (h3 << 5));
|
||||
s[9] = (unsigned char) ((h2 >> 21) | shl32(h3, 5));
|
||||
s[10] = (unsigned char) (h3 >> 3);
|
||||
s[11] = (unsigned char) (h3 >> 11);
|
||||
s[12] = (unsigned char) ((h3 >> 19) | (h4 << 6));
|
||||
s[12] = (unsigned char) ((h3 >> 19) | shl32(h4, 6));
|
||||
s[13] = (unsigned char) (h4 >> 2);
|
||||
s[14] = (unsigned char) (h4 >> 10);
|
||||
s[15] = (unsigned char) (h4 >> 18);
|
||||
s[16] = (unsigned char) (h5 >> 0);
|
||||
s[17] = (unsigned char) (h5 >> 8);
|
||||
s[18] = (unsigned char) (h5 >> 16);
|
||||
s[19] = (unsigned char) ((h5 >> 24) | (h6 << 1));
|
||||
s[19] = (unsigned char) ((h5 >> 24) | shl32(h6, 1));
|
||||
s[20] = (unsigned char) (h6 >> 7);
|
||||
s[21] = (unsigned char) (h6 >> 15);
|
||||
s[22] = (unsigned char) ((h6 >> 23) | (h7 << 3));
|
||||
s[22] = (unsigned char) ((h6 >> 23) | shl32(h7, 3));
|
||||
s[23] = (unsigned char) (h7 >> 5);
|
||||
s[24] = (unsigned char) (h7 >> 13);
|
||||
s[25] = (unsigned char) ((h7 >> 21) | (h8 << 4));
|
||||
s[25] = (unsigned char) ((h7 >> 21) | shl32(h8, 4));
|
||||
s[26] = (unsigned char) (h8 >> 4);
|
||||
s[27] = (unsigned char) (h8 >> 12);
|
||||
s[28] = (unsigned char) ((h8 >> 20) | (h9 << 6));
|
||||
s[28] = (unsigned char) ((h8 >> 20) | shl32(h9, 6));
|
||||
s[29] = (unsigned char) (h9 >> 2);
|
||||
s[30] = (unsigned char) (h9 >> 10);
|
||||
s[31] = (unsigned char) (h9 >> 18);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@
|
|||
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
|
||||
|
|
@ -68,3 +71,21 @@
|
|||
#define INT64_C(v) v ##I64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static inline unsigned char shlu8(unsigned char a, uint32_t b) {
|
||||
return a << b;
|
||||
}
|
||||
|
||||
static inline int32_t shl32(uint32_t a, uint32_t b) {
|
||||
return a << b;
|
||||
}
|
||||
|
||||
static inline int64_t shl64(uint64_t a, uint32_t b) {
|
||||
return a << b;
|
||||
}
|
||||
|
||||
static inline uint64_t shlu64(uint64_t a, uint32_t b) {
|
||||
return a << b;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -356,7 +356,7 @@ static void cmov(ge_precomp *t, ge_precomp *u, unsigned char b) {
|
|||
static void select(ge_precomp *t, int pos, signed char b) {
|
||||
ge_precomp minust;
|
||||
unsigned char bnegative = negative(b);
|
||||
unsigned char babs = b - (((-bnegative) & b) << 1);
|
||||
unsigned char babs = b - shlu8(((-bnegative) & b), 1);
|
||||
fe_1(t->yplusx);
|
||||
fe_1(t->yminusx);
|
||||
fe_0(t->xy2d);
|
||||
|
|
@ -404,7 +404,7 @@ void ge_scalarmult_base(ge_p3 *h, const unsigned char *a) {
|
|||
e[i] += carry;
|
||||
carry = e[i] + 8;
|
||||
carry >>= 4;
|
||||
e[i] -= carry << 4;
|
||||
e[i] -= shl32(carry, 4);
|
||||
}
|
||||
|
||||
e[63] += carry;
|
||||
|
|
|
|||
|
|
@ -1388,4 +1388,4 @@ static ge_precomp base[32][8] = {
|
|||
{ -20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476 },
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
|
|||
284
src/ed25519/sc.c
284
src/ed25519/sc.c
|
|
@ -4,9 +4,9 @@
|
|||
static uint64_t load_3(const unsigned char *in) {
|
||||
uint64_t result;
|
||||
|
||||
result = (uint64_t) in[0];
|
||||
result |= ((uint64_t) in[1]) << 8;
|
||||
result |= ((uint64_t) in[2]) << 16;
|
||||
result = in[0];
|
||||
result |= shlu64(in[1], 8);
|
||||
result |= shlu64(in[2], 16);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -14,10 +14,10 @@ static uint64_t load_3(const unsigned char *in) {
|
|||
static uint64_t load_4(const unsigned char *in) {
|
||||
uint64_t result;
|
||||
|
||||
result = (uint64_t) in[0];
|
||||
result |= ((uint64_t) in[1]) << 8;
|
||||
result |= ((uint64_t) in[2]) << 16;
|
||||
result |= ((uint64_t) in[3]) << 24;
|
||||
result = in[0];
|
||||
result |= shlu64(in[1], 8);
|
||||
result |= shlu64(in[2], 16);
|
||||
result |= shlu64(in[3], 24);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -119,37 +119,37 @@ void sc_reduce(unsigned char *s) {
|
|||
s18 = 0;
|
||||
carry6 = (s6 + (1 << 20)) >> 21;
|
||||
s7 += carry6;
|
||||
s6 -= carry6 << 21;
|
||||
s6 -= shl64(carry6, 21);
|
||||
carry8 = (s8 + (1 << 20)) >> 21;
|
||||
s9 += carry8;
|
||||
s8 -= carry8 << 21;
|
||||
s8 -= shl64(carry8, 21);
|
||||
carry10 = (s10 + (1 << 20)) >> 21;
|
||||
s11 += carry10;
|
||||
s10 -= carry10 << 21;
|
||||
s10 -= shl64(carry10, 21);
|
||||
carry12 = (s12 + (1 << 20)) >> 21;
|
||||
s13 += carry12;
|
||||
s12 -= carry12 << 21;
|
||||
s12 -= shl64(carry12, 21);
|
||||
carry14 = (s14 + (1 << 20)) >> 21;
|
||||
s15 += carry14;
|
||||
s14 -= carry14 << 21;
|
||||
s14 -= shl64(carry14, 21);
|
||||
carry16 = (s16 + (1 << 20)) >> 21;
|
||||
s17 += carry16;
|
||||
s16 -= carry16 << 21;
|
||||
s16 -= shl64(carry16, 21);
|
||||
carry7 = (s7 + (1 << 20)) >> 21;
|
||||
s8 += carry7;
|
||||
s7 -= carry7 << 21;
|
||||
s7 -= shl64(carry7, 21);
|
||||
carry9 = (s9 + (1 << 20)) >> 21;
|
||||
s10 += carry9;
|
||||
s9 -= carry9 << 21;
|
||||
s9 -= shl64(carry9, 21);
|
||||
carry11 = (s11 + (1 << 20)) >> 21;
|
||||
s12 += carry11;
|
||||
s11 -= carry11 << 21;
|
||||
s11 -= shl64(carry11, 21);
|
||||
carry13 = (s13 + (1 << 20)) >> 21;
|
||||
s14 += carry13;
|
||||
s13 -= carry13 << 21;
|
||||
s13 -= shl64(carry13, 21);
|
||||
carry15 = (s15 + (1 << 20)) >> 21;
|
||||
s16 += carry15;
|
||||
s15 -= carry15 << 21;
|
||||
s15 -= shl64(carry15, 21);
|
||||
s5 += s17 * 666643;
|
||||
s6 += s17 * 470296;
|
||||
s7 += s17 * 654183;
|
||||
|
|
@ -194,40 +194,40 @@ void sc_reduce(unsigned char *s) {
|
|||
s12 = 0;
|
||||
carry0 = (s0 + (1 << 20)) >> 21;
|
||||
s1 += carry0;
|
||||
s0 -= carry0 << 21;
|
||||
s0 -= shl64(carry0, 21);
|
||||
carry2 = (s2 + (1 << 20)) >> 21;
|
||||
s3 += carry2;
|
||||
s2 -= carry2 << 21;
|
||||
s2 -= shl64(carry2, 21);
|
||||
carry4 = (s4 + (1 << 20)) >> 21;
|
||||
s5 += carry4;
|
||||
s4 -= carry4 << 21;
|
||||
s4 -= shl64(carry4, 21);
|
||||
carry6 = (s6 + (1 << 20)) >> 21;
|
||||
s7 += carry6;
|
||||
s6 -= carry6 << 21;
|
||||
s6 -= shl64(carry6, 21);
|
||||
carry8 = (s8 + (1 << 20)) >> 21;
|
||||
s9 += carry8;
|
||||
s8 -= carry8 << 21;
|
||||
s8 -= shl64(carry8, 21);
|
||||
carry10 = (s10 + (1 << 20)) >> 21;
|
||||
s11 += carry10;
|
||||
s10 -= carry10 << 21;
|
||||
s10 -= shl64(carry10, 21);
|
||||
carry1 = (s1 + (1 << 20)) >> 21;
|
||||
s2 += carry1;
|
||||
s1 -= carry1 << 21;
|
||||
s1 -= shl64(carry1, 21);
|
||||
carry3 = (s3 + (1 << 20)) >> 21;
|
||||
s4 += carry3;
|
||||
s3 -= carry3 << 21;
|
||||
s3 -= shl64(carry3, 21);
|
||||
carry5 = (s5 + (1 << 20)) >> 21;
|
||||
s6 += carry5;
|
||||
s5 -= carry5 << 21;
|
||||
s5 -= shl64(carry5, 21);
|
||||
carry7 = (s7 + (1 << 20)) >> 21;
|
||||
s8 += carry7;
|
||||
s7 -= carry7 << 21;
|
||||
s7 -= shl64(carry7, 21);
|
||||
carry9 = (s9 + (1 << 20)) >> 21;
|
||||
s10 += carry9;
|
||||
s9 -= carry9 << 21;
|
||||
s9 -= shl64(carry9, 21);
|
||||
carry11 = (s11 + (1 << 20)) >> 21;
|
||||
s12 += carry11;
|
||||
s11 -= carry11 << 21;
|
||||
s11 -= shl64(carry11, 21);
|
||||
s0 += s12 * 666643;
|
||||
s1 += s12 * 470296;
|
||||
s2 += s12 * 654183;
|
||||
|
|
@ -237,40 +237,40 @@ void sc_reduce(unsigned char *s) {
|
|||
s12 = 0;
|
||||
carry0 = s0 >> 21;
|
||||
s1 += carry0;
|
||||
s0 -= carry0 << 21;
|
||||
s0 -= shl64(carry0, 21);
|
||||
carry1 = s1 >> 21;
|
||||
s2 += carry1;
|
||||
s1 -= carry1 << 21;
|
||||
s1 -= shl64(carry1, 21);
|
||||
carry2 = s2 >> 21;
|
||||
s3 += carry2;
|
||||
s2 -= carry2 << 21;
|
||||
s2 -= shl64(carry2, 21);
|
||||
carry3 = s3 >> 21;
|
||||
s4 += carry3;
|
||||
s3 -= carry3 << 21;
|
||||
s3 -= shl64(carry3, 21);
|
||||
carry4 = s4 >> 21;
|
||||
s5 += carry4;
|
||||
s4 -= carry4 << 21;
|
||||
s4 -= shl64(carry4, 21);
|
||||
carry5 = s5 >> 21;
|
||||
s6 += carry5;
|
||||
s5 -= carry5 << 21;
|
||||
s5 -= shl64(carry5, 21);
|
||||
carry6 = s6 >> 21;
|
||||
s7 += carry6;
|
||||
s6 -= carry6 << 21;
|
||||
s6 -= shl64(carry6, 21);
|
||||
carry7 = s7 >> 21;
|
||||
s8 += carry7;
|
||||
s7 -= carry7 << 21;
|
||||
s7 -= shl64(carry7, 21);
|
||||
carry8 = s8 >> 21;
|
||||
s9 += carry8;
|
||||
s8 -= carry8 << 21;
|
||||
s8 -= shl64(carry8, 21);
|
||||
carry9 = s9 >> 21;
|
||||
s10 += carry9;
|
||||
s9 -= carry9 << 21;
|
||||
s9 -= shl64(carry9, 21);
|
||||
carry10 = s10 >> 21;
|
||||
s11 += carry10;
|
||||
s10 -= carry10 << 21;
|
||||
s10 -= shl64(carry10, 21);
|
||||
carry11 = s11 >> 21;
|
||||
s12 += carry11;
|
||||
s11 -= carry11 << 21;
|
||||
s11 -= shl64(carry11, 21);
|
||||
s0 += s12 * 666643;
|
||||
s1 += s12 * 470296;
|
||||
s2 += s12 * 654183;
|
||||
|
|
@ -280,67 +280,67 @@ void sc_reduce(unsigned char *s) {
|
|||
s12 = 0;
|
||||
carry0 = s0 >> 21;
|
||||
s1 += carry0;
|
||||
s0 -= carry0 << 21;
|
||||
s0 -= shl64(carry0, 21);
|
||||
carry1 = s1 >> 21;
|
||||
s2 += carry1;
|
||||
s1 -= carry1 << 21;
|
||||
s1 -= shl64(carry1, 21);
|
||||
carry2 = s2 >> 21;
|
||||
s3 += carry2;
|
||||
s2 -= carry2 << 21;
|
||||
s2 -= shl64(carry2, 21);
|
||||
carry3 = s3 >> 21;
|
||||
s4 += carry3;
|
||||
s3 -= carry3 << 21;
|
||||
s3 -= shl64(carry3, 21);
|
||||
carry4 = s4 >> 21;
|
||||
s5 += carry4;
|
||||
s4 -= carry4 << 21;
|
||||
s4 -= shl64(carry4, 21);
|
||||
carry5 = s5 >> 21;
|
||||
s6 += carry5;
|
||||
s5 -= carry5 << 21;
|
||||
s5 -= shl64(carry5, 21);
|
||||
carry6 = s6 >> 21;
|
||||
s7 += carry6;
|
||||
s6 -= carry6 << 21;
|
||||
s6 -= shl64(carry6, 21);
|
||||
carry7 = s7 >> 21;
|
||||
s8 += carry7;
|
||||
s7 -= carry7 << 21;
|
||||
s7 -= shl64(carry7, 21);
|
||||
carry8 = s8 >> 21;
|
||||
s9 += carry8;
|
||||
s8 -= carry8 << 21;
|
||||
s8 -= shl64(carry8, 21);
|
||||
carry9 = s9 >> 21;
|
||||
s10 += carry9;
|
||||
s9 -= carry9 << 21;
|
||||
s9 -= shl64(carry9, 21);
|
||||
carry10 = s10 >> 21;
|
||||
s11 += carry10;
|
||||
s10 -= carry10 << 21;
|
||||
s10 -= shl64(carry10, 21);
|
||||
|
||||
s[0] = (unsigned char) (s0 >> 0);
|
||||
s[1] = (unsigned char) (s0 >> 8);
|
||||
s[2] = (unsigned char) ((s0 >> 16) | (s1 << 5));
|
||||
s[2] = (unsigned char) ((s0 >> 16) | shl64(s1, 5));
|
||||
s[3] = (unsigned char) (s1 >> 3);
|
||||
s[4] = (unsigned char) (s1 >> 11);
|
||||
s[5] = (unsigned char) ((s1 >> 19) | (s2 << 2));
|
||||
s[5] = (unsigned char) ((s1 >> 19) | shl64(s2, 2));
|
||||
s[6] = (unsigned char) (s2 >> 6);
|
||||
s[7] = (unsigned char) ((s2 >> 14) | (s3 << 7));
|
||||
s[7] = (unsigned char) ((s2 >> 14) | shl64(s3, 7));
|
||||
s[8] = (unsigned char) (s3 >> 1);
|
||||
s[9] = (unsigned char) (s3 >> 9);
|
||||
s[10] = (unsigned char) ((s3 >> 17) | (s4 << 4));
|
||||
s[10] = (unsigned char) ((s3 >> 17) | shl64(s4, 4));
|
||||
s[11] = (unsigned char) (s4 >> 4);
|
||||
s[12] = (unsigned char) (s4 >> 12);
|
||||
s[13] = (unsigned char) ((s4 >> 20) | (s5 << 1));
|
||||
s[13] = (unsigned char) ((s4 >> 20) | shl64(s5, 1));
|
||||
s[14] = (unsigned char) (s5 >> 7);
|
||||
s[15] = (unsigned char) ((s5 >> 15) | (s6 << 6));
|
||||
s[15] = (unsigned char) ((s5 >> 15) | shl64(s6, 6));
|
||||
s[16] = (unsigned char) (s6 >> 2);
|
||||
s[17] = (unsigned char) (s6 >> 10);
|
||||
s[18] = (unsigned char) ((s6 >> 18) | (s7 << 3));
|
||||
s[18] = (unsigned char) ((s6 >> 18) | shl64(s7, 3));
|
||||
s[19] = (unsigned char) (s7 >> 5);
|
||||
s[20] = (unsigned char) (s7 >> 13);
|
||||
s[21] = (unsigned char) (s8 >> 0);
|
||||
s[22] = (unsigned char) (s8 >> 8);
|
||||
s[23] = (unsigned char) ((s8 >> 16) | (s9 << 5));
|
||||
s[23] = (unsigned char) ((s8 >> 16) | shl64(s9, 5));
|
||||
s[24] = (unsigned char) (s9 >> 3);
|
||||
s[25] = (unsigned char) (s9 >> 11);
|
||||
s[26] = (unsigned char) ((s9 >> 19) | (s10 << 2));
|
||||
s[26] = (unsigned char) ((s9 >> 19) | shl64(s10, 2));
|
||||
s[27] = (unsigned char) (s10 >> 6);
|
||||
s[28] = (unsigned char) ((s10 >> 14) | (s11 << 7));
|
||||
s[28] = (unsigned char) ((s10 >> 14) | shl64(s11, 7));
|
||||
s[29] = (unsigned char) (s11 >> 1);
|
||||
s[30] = (unsigned char) (s11 >> 9);
|
||||
s[31] = (unsigned char) (s11 >> 17);
|
||||
|
|
@ -470,73 +470,73 @@ void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b,
|
|||
s23 = 0;
|
||||
carry0 = (s0 + (1 << 20)) >> 21;
|
||||
s1 += carry0;
|
||||
s0 -= carry0 << 21;
|
||||
s0 -= shl64(carry0, 21);
|
||||
carry2 = (s2 + (1 << 20)) >> 21;
|
||||
s3 += carry2;
|
||||
s2 -= carry2 << 21;
|
||||
s2 -= shl64(carry2, 21);
|
||||
carry4 = (s4 + (1 << 20)) >> 21;
|
||||
s5 += carry4;
|
||||
s4 -= carry4 << 21;
|
||||
s4 -= shl64(carry4, 21);
|
||||
carry6 = (s6 + (1 << 20)) >> 21;
|
||||
s7 += carry6;
|
||||
s6 -= carry6 << 21;
|
||||
s6 -= shl64(carry6, 21);
|
||||
carry8 = (s8 + (1 << 20)) >> 21;
|
||||
s9 += carry8;
|
||||
s8 -= carry8 << 21;
|
||||
s8 -= shl64(carry8, 21);
|
||||
carry10 = (s10 + (1 << 20)) >> 21;
|
||||
s11 += carry10;
|
||||
s10 -= carry10 << 21;
|
||||
s10 -= shl64(carry10, 21);
|
||||
carry12 = (s12 + (1 << 20)) >> 21;
|
||||
s13 += carry12;
|
||||
s12 -= carry12 << 21;
|
||||
s12 -= shl64(carry12, 21);
|
||||
carry14 = (s14 + (1 << 20)) >> 21;
|
||||
s15 += carry14;
|
||||
s14 -= carry14 << 21;
|
||||
s14 -= shl64(carry14, 21);
|
||||
carry16 = (s16 + (1 << 20)) >> 21;
|
||||
s17 += carry16;
|
||||
s16 -= carry16 << 21;
|
||||
s16 -= shl64(carry16, 21);
|
||||
carry18 = (s18 + (1 << 20)) >> 21;
|
||||
s19 += carry18;
|
||||
s18 -= carry18 << 21;
|
||||
s18 -= shl64(carry18, 21);
|
||||
carry20 = (s20 + (1 << 20)) >> 21;
|
||||
s21 += carry20;
|
||||
s20 -= carry20 << 21;
|
||||
s20 -= shl64(carry20, 21);
|
||||
carry22 = (s22 + (1 << 20)) >> 21;
|
||||
s23 += carry22;
|
||||
s22 -= carry22 << 21;
|
||||
s22 -= shl64(carry22, 21);
|
||||
carry1 = (s1 + (1 << 20)) >> 21;
|
||||
s2 += carry1;
|
||||
s1 -= carry1 << 21;
|
||||
s1 -= shl64(carry1, 21);
|
||||
carry3 = (s3 + (1 << 20)) >> 21;
|
||||
s4 += carry3;
|
||||
s3 -= carry3 << 21;
|
||||
s3 -= shl64(carry3, 21);
|
||||
carry5 = (s5 + (1 << 20)) >> 21;
|
||||
s6 += carry5;
|
||||
s5 -= carry5 << 21;
|
||||
s5 -= shl64(carry5, 21);
|
||||
carry7 = (s7 + (1 << 20)) >> 21;
|
||||
s8 += carry7;
|
||||
s7 -= carry7 << 21;
|
||||
s7 -= shl64(carry7, 21);
|
||||
carry9 = (s9 + (1 << 20)) >> 21;
|
||||
s10 += carry9;
|
||||
s9 -= carry9 << 21;
|
||||
s9 -= shl64(carry9, 21);
|
||||
carry11 = (s11 + (1 << 20)) >> 21;
|
||||
s12 += carry11;
|
||||
s11 -= carry11 << 21;
|
||||
s11 -= shl64(carry11, 21);
|
||||
carry13 = (s13 + (1 << 20)) >> 21;
|
||||
s14 += carry13;
|
||||
s13 -= carry13 << 21;
|
||||
s13 -= shl64(carry13, 21);
|
||||
carry15 = (s15 + (1 << 20)) >> 21;
|
||||
s16 += carry15;
|
||||
s15 -= carry15 << 21;
|
||||
s15 -= shl64(carry15, 21);
|
||||
carry17 = (s17 + (1 << 20)) >> 21;
|
||||
s18 += carry17;
|
||||
s17 -= carry17 << 21;
|
||||
s17 -= shl64(carry17, 21);
|
||||
carry19 = (s19 + (1 << 20)) >> 21;
|
||||
s20 += carry19;
|
||||
s19 -= carry19 << 21;
|
||||
s19 -= shl64(carry19, 21);
|
||||
carry21 = (s21 + (1 << 20)) >> 21;
|
||||
s22 += carry21;
|
||||
s21 -= carry21 << 21;
|
||||
s21 -= shl64(carry21, 21);
|
||||
s11 += s23 * 666643;
|
||||
s12 += s23 * 470296;
|
||||
s13 += s23 * 654183;
|
||||
|
|
@ -581,37 +581,37 @@ void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b,
|
|||
s18 = 0;
|
||||
carry6 = (s6 + (1 << 20)) >> 21;
|
||||
s7 += carry6;
|
||||
s6 -= carry6 << 21;
|
||||
s6 -= shl64(carry6, 21);
|
||||
carry8 = (s8 + (1 << 20)) >> 21;
|
||||
s9 += carry8;
|
||||
s8 -= carry8 << 21;
|
||||
s8 -= shl64(carry8, 21);
|
||||
carry10 = (s10 + (1 << 20)) >> 21;
|
||||
s11 += carry10;
|
||||
s10 -= carry10 << 21;
|
||||
s10 -= shl64(carry10, 21);
|
||||
carry12 = (s12 + (1 << 20)) >> 21;
|
||||
s13 += carry12;
|
||||
s12 -= carry12 << 21;
|
||||
s12 -= shl64(carry12, 21);
|
||||
carry14 = (s14 + (1 << 20)) >> 21;
|
||||
s15 += carry14;
|
||||
s14 -= carry14 << 21;
|
||||
s14 -= shl64(carry14, 21);
|
||||
carry16 = (s16 + (1 << 20)) >> 21;
|
||||
s17 += carry16;
|
||||
s16 -= carry16 << 21;
|
||||
s16 -= shl64(carry16, 21);
|
||||
carry7 = (s7 + (1 << 20)) >> 21;
|
||||
s8 += carry7;
|
||||
s7 -= carry7 << 21;
|
||||
s7 -= shl64(carry7, 21);
|
||||
carry9 = (s9 + (1 << 20)) >> 21;
|
||||
s10 += carry9;
|
||||
s9 -= carry9 << 21;
|
||||
s9 -= shl64(carry9, 21);
|
||||
carry11 = (s11 + (1 << 20)) >> 21;
|
||||
s12 += carry11;
|
||||
s11 -= carry11 << 21;
|
||||
s11 -= shl64(carry11, 21);
|
||||
carry13 = (s13 + (1 << 20)) >> 21;
|
||||
s14 += carry13;
|
||||
s13 -= carry13 << 21;
|
||||
s13 -= shl64(carry13, 21);
|
||||
carry15 = (s15 + (1 << 20)) >> 21;
|
||||
s16 += carry15;
|
||||
s15 -= carry15 << 21;
|
||||
s15 -= shl64(carry15, 21);
|
||||
s5 += s17 * 666643;
|
||||
s6 += s17 * 470296;
|
||||
s7 += s17 * 654183;
|
||||
|
|
@ -656,40 +656,40 @@ void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b,
|
|||
s12 = 0;
|
||||
carry0 = (s0 + (1 << 20)) >> 21;
|
||||
s1 += carry0;
|
||||
s0 -= carry0 << 21;
|
||||
s0 -= shl64(carry0, 21);
|
||||
carry2 = (s2 + (1 << 20)) >> 21;
|
||||
s3 += carry2;
|
||||
s2 -= carry2 << 21;
|
||||
s2 -= shl64(carry2, 21);
|
||||
carry4 = (s4 + (1 << 20)) >> 21;
|
||||
s5 += carry4;
|
||||
s4 -= carry4 << 21;
|
||||
s4 -= shl64(carry4, 21);
|
||||
carry6 = (s6 + (1 << 20)) >> 21;
|
||||
s7 += carry6;
|
||||
s6 -= carry6 << 21;
|
||||
s6 -= shl64(carry6, 21);
|
||||
carry8 = (s8 + (1 << 20)) >> 21;
|
||||
s9 += carry8;
|
||||
s8 -= carry8 << 21;
|
||||
s8 -= shl64(carry8, 21);
|
||||
carry10 = (s10 + (1 << 20)) >> 21;
|
||||
s11 += carry10;
|
||||
s10 -= carry10 << 21;
|
||||
s10 -= shl64(carry10, 21);
|
||||
carry1 = (s1 + (1 << 20)) >> 21;
|
||||
s2 += carry1;
|
||||
s1 -= carry1 << 21;
|
||||
s1 -= shl64(carry1, 21);
|
||||
carry3 = (s3 + (1 << 20)) >> 21;
|
||||
s4 += carry3;
|
||||
s3 -= carry3 << 21;
|
||||
s3 -= shl64(carry3, 21);
|
||||
carry5 = (s5 + (1 << 20)) >> 21;
|
||||
s6 += carry5;
|
||||
s5 -= carry5 << 21;
|
||||
s5 -= shl64(carry5, 21);
|
||||
carry7 = (s7 + (1 << 20)) >> 21;
|
||||
s8 += carry7;
|
||||
s7 -= carry7 << 21;
|
||||
s7 -= shl64(carry7, 21);
|
||||
carry9 = (s9 + (1 << 20)) >> 21;
|
||||
s10 += carry9;
|
||||
s9 -= carry9 << 21;
|
||||
s9 -= shl64(carry9, 21);
|
||||
carry11 = (s11 + (1 << 20)) >> 21;
|
||||
s12 += carry11;
|
||||
s11 -= carry11 << 21;
|
||||
s11 -= shl64(carry11, 21);
|
||||
s0 += s12 * 666643;
|
||||
s1 += s12 * 470296;
|
||||
s2 += s12 * 654183;
|
||||
|
|
@ -699,40 +699,40 @@ void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b,
|
|||
s12 = 0;
|
||||
carry0 = s0 >> 21;
|
||||
s1 += carry0;
|
||||
s0 -= carry0 << 21;
|
||||
s0 -= shl64(carry0, 21);
|
||||
carry1 = s1 >> 21;
|
||||
s2 += carry1;
|
||||
s1 -= carry1 << 21;
|
||||
s1 -= shl64(carry1, 21);
|
||||
carry2 = s2 >> 21;
|
||||
s3 += carry2;
|
||||
s2 -= carry2 << 21;
|
||||
s2 -= shl64(carry2, 21);
|
||||
carry3 = s3 >> 21;
|
||||
s4 += carry3;
|
||||
s3 -= carry3 << 21;
|
||||
s3 -= shl64(carry3, 21);
|
||||
carry4 = s4 >> 21;
|
||||
s5 += carry4;
|
||||
s4 -= carry4 << 21;
|
||||
s4 -= shl64(carry4, 21);
|
||||
carry5 = s5 >> 21;
|
||||
s6 += carry5;
|
||||
s5 -= carry5 << 21;
|
||||
s5 -= shl64(carry5, 21);
|
||||
carry6 = s6 >> 21;
|
||||
s7 += carry6;
|
||||
s6 -= carry6 << 21;
|
||||
s6 -= shl64(carry6, 21);
|
||||
carry7 = s7 >> 21;
|
||||
s8 += carry7;
|
||||
s7 -= carry7 << 21;
|
||||
s7 -= shl64(carry7, 21);
|
||||
carry8 = s8 >> 21;
|
||||
s9 += carry8;
|
||||
s8 -= carry8 << 21;
|
||||
s8 -= shl64(carry8, 21);
|
||||
carry9 = s9 >> 21;
|
||||
s10 += carry9;
|
||||
s9 -= carry9 << 21;
|
||||
s9 -= shl64(carry9, 21);
|
||||
carry10 = s10 >> 21;
|
||||
s11 += carry10;
|
||||
s10 -= carry10 << 21;
|
||||
s10 -= shl64(carry10, 21);
|
||||
carry11 = s11 >> 21;
|
||||
s12 += carry11;
|
||||
s11 -= carry11 << 21;
|
||||
s11 -= shl64(carry11, 21);
|
||||
s0 += s12 * 666643;
|
||||
s1 += s12 * 470296;
|
||||
s2 += s12 * 654183;
|
||||
|
|
@ -742,67 +742,67 @@ void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b,
|
|||
s12 = 0;
|
||||
carry0 = s0 >> 21;
|
||||
s1 += carry0;
|
||||
s0 -= carry0 << 21;
|
||||
s0 -= shl64(carry0, 21);
|
||||
carry1 = s1 >> 21;
|
||||
s2 += carry1;
|
||||
s1 -= carry1 << 21;
|
||||
s1 -= shl64(carry1, 21);
|
||||
carry2 = s2 >> 21;
|
||||
s3 += carry2;
|
||||
s2 -= carry2 << 21;
|
||||
s2 -= shl64(carry2, 21);
|
||||
carry3 = s3 >> 21;
|
||||
s4 += carry3;
|
||||
s3 -= carry3 << 21;
|
||||
s3 -= shl64(carry3, 21);
|
||||
carry4 = s4 >> 21;
|
||||
s5 += carry4;
|
||||
s4 -= carry4 << 21;
|
||||
s4 -= shl64(carry4, 21);
|
||||
carry5 = s5 >> 21;
|
||||
s6 += carry5;
|
||||
s5 -= carry5 << 21;
|
||||
s5 -= shl64(carry5, 21);
|
||||
carry6 = s6 >> 21;
|
||||
s7 += carry6;
|
||||
s6 -= carry6 << 21;
|
||||
s6 -= shl64(carry6, 21);
|
||||
carry7 = s7 >> 21;
|
||||
s8 += carry7;
|
||||
s7 -= carry7 << 21;
|
||||
s7 -= shl64(carry7, 21);
|
||||
carry8 = s8 >> 21;
|
||||
s9 += carry8;
|
||||
s8 -= carry8 << 21;
|
||||
s8 -= shl64(carry8, 21);
|
||||
carry9 = s9 >> 21;
|
||||
s10 += carry9;
|
||||
s9 -= carry9 << 21;
|
||||
s9 -= shl64(carry9, 21);
|
||||
carry10 = s10 >> 21;
|
||||
s11 += carry10;
|
||||
s10 -= carry10 << 21;
|
||||
s10 -= shl64(carry10, 21);
|
||||
|
||||
s[0] = (unsigned char) (s0 >> 0);
|
||||
s[1] = (unsigned char) (s0 >> 8);
|
||||
s[2] = (unsigned char) ((s0 >> 16) | (s1 << 5));
|
||||
s[2] = (unsigned char) ((s0 >> 16) | shl64(s1, 5));
|
||||
s[3] = (unsigned char) (s1 >> 3);
|
||||
s[4] = (unsigned char) (s1 >> 11);
|
||||
s[5] = (unsigned char) ((s1 >> 19) | (s2 << 2));
|
||||
s[5] = (unsigned char) ((s1 >> 19) | shl64(s2, 2));
|
||||
s[6] = (unsigned char) (s2 >> 6);
|
||||
s[7] = (unsigned char) ((s2 >> 14) | (s3 << 7));
|
||||
s[7] = (unsigned char) ((s2 >> 14) | shl64(s3, 7));
|
||||
s[8] = (unsigned char) (s3 >> 1);
|
||||
s[9] = (unsigned char) (s3 >> 9);
|
||||
s[10] = (unsigned char) ((s3 >> 17) | (s4 << 4));
|
||||
s[10] = (unsigned char) ((s3 >> 17) | shl64(s4, 4));
|
||||
s[11] = (unsigned char) (s4 >> 4);
|
||||
s[12] = (unsigned char) (s4 >> 12);
|
||||
s[13] = (unsigned char) ((s4 >> 20) | (s5 << 1));
|
||||
s[13] = (unsigned char) ((s4 >> 20) | shl64(s5, 1));
|
||||
s[14] = (unsigned char) (s5 >> 7);
|
||||
s[15] = (unsigned char) ((s5 >> 15) | (s6 << 6));
|
||||
s[15] = (unsigned char) ((s5 >> 15) | shl64(s6, 6));
|
||||
s[16] = (unsigned char) (s6 >> 2);
|
||||
s[17] = (unsigned char) (s6 >> 10);
|
||||
s[18] = (unsigned char) ((s6 >> 18) | (s7 << 3));
|
||||
s[18] = (unsigned char) ((s6 >> 18) | shl64(s7, 3));
|
||||
s[19] = (unsigned char) (s7 >> 5);
|
||||
s[20] = (unsigned char) (s7 >> 13);
|
||||
s[21] = (unsigned char) (s8 >> 0);
|
||||
s[22] = (unsigned char) (s8 >> 8);
|
||||
s[23] = (unsigned char) ((s8 >> 16) | (s9 << 5));
|
||||
s[23] = (unsigned char) ((s8 >> 16) | shl64(s9, 5));
|
||||
s[24] = (unsigned char) (s9 >> 3);
|
||||
s[25] = (unsigned char) (s9 >> 11);
|
||||
s[26] = (unsigned char) ((s9 >> 19) | (s10 << 2));
|
||||
s[26] = (unsigned char) ((s9 >> 19) | shl64(s10, 2));
|
||||
s[27] = (unsigned char) (s10 >> 6);
|
||||
s[28] = (unsigned char) ((s10 >> 14) | (s11 << 7));
|
||||
s[28] = (unsigned char) ((s10 >> 14) | shl64(s11, 7));
|
||||
s[29] = (unsigned char) (s11 >> 1);
|
||||
s[30] = (unsigned char) (s11 >> 9);
|
||||
s[31] = (unsigned char) (s11 >> 17);
|
||||
|
|
|
|||
|
|
@ -9,4 +9,4 @@ where l = 2^252 + 27742317777372353535851937790883648493.
|
|||
void sc_reduce(unsigned char *s);
|
||||
void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -14,45 +14,45 @@
|
|||
|
||||
/* the K array */
|
||||
static const uint64_t K[80] = {
|
||||
UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd),
|
||||
UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd),
|
||||
UINT64_C(0xb5c0fbcfec4d3b2f), UINT64_C(0xe9b5dba58189dbbc),
|
||||
UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019),
|
||||
UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019),
|
||||
UINT64_C(0x923f82a4af194f9b), UINT64_C(0xab1c5ed5da6d8118),
|
||||
UINT64_C(0xd807aa98a3030242), UINT64_C(0x12835b0145706fbe),
|
||||
UINT64_C(0xd807aa98a3030242), UINT64_C(0x12835b0145706fbe),
|
||||
UINT64_C(0x243185be4ee4b28c), UINT64_C(0x550c7dc3d5ffb4e2),
|
||||
UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1),
|
||||
UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1),
|
||||
UINT64_C(0x9bdc06a725c71235), UINT64_C(0xc19bf174cf692694),
|
||||
UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3),
|
||||
UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3),
|
||||
UINT64_C(0x0fc19dc68b8cd5b5), UINT64_C(0x240ca1cc77ac9c65),
|
||||
UINT64_C(0x2de92c6f592b0275), UINT64_C(0x4a7484aa6ea6e483),
|
||||
UINT64_C(0x2de92c6f592b0275), UINT64_C(0x4a7484aa6ea6e483),
|
||||
UINT64_C(0x5cb0a9dcbd41fbd4), UINT64_C(0x76f988da831153b5),
|
||||
UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210),
|
||||
UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210),
|
||||
UINT64_C(0xb00327c898fb213f), UINT64_C(0xbf597fc7beef0ee4),
|
||||
UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725),
|
||||
UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725),
|
||||
UINT64_C(0x06ca6351e003826f), UINT64_C(0x142929670a0e6e70),
|
||||
UINT64_C(0x27b70a8546d22ffc), UINT64_C(0x2e1b21385c26c926),
|
||||
UINT64_C(0x27b70a8546d22ffc), UINT64_C(0x2e1b21385c26c926),
|
||||
UINT64_C(0x4d2c6dfc5ac42aed), UINT64_C(0x53380d139d95b3df),
|
||||
UINT64_C(0x650a73548baf63de), UINT64_C(0x766a0abb3c77b2a8),
|
||||
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(0xd192e819d6ef5218), UINT64_C(0xd69906245565a910),
|
||||
UINT64_C(0xf40e35855771202a), UINT64_C(0x106aa07032bbd1b8),
|
||||
UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53),
|
||||
UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53),
|
||||
UINT64_C(0x2748774cdf8eeb99), UINT64_C(0x34b0bcb5e19b48a8),
|
||||
UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb),
|
||||
UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb),
|
||||
UINT64_C(0x5b9cca4f7763e373), UINT64_C(0x682e6ff3d6b2b8a3),
|
||||
UINT64_C(0x748f82ee5defb2fc), UINT64_C(0x78a5636f43172f60),
|
||||
UINT64_C(0x748f82ee5defb2fc), UINT64_C(0x78a5636f43172f60),
|
||||
UINT64_C(0x84c87814a1f0ab72), UINT64_C(0x8cc702081a6439ec),
|
||||
UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9),
|
||||
UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9),
|
||||
UINT64_C(0xbef9a3f7b2c67915), UINT64_C(0xc67178f2e372532b),
|
||||
UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207),
|
||||
UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207),
|
||||
UINT64_C(0xeada7dd6cde0eb1e), UINT64_C(0xf57d4f7fee6ed178),
|
||||
UINT64_C(0x06f067aa72176fba), UINT64_C(0x0a637dc5a2c898a6),
|
||||
UINT64_C(0x06f067aa72176fba), UINT64_C(0x0a637dc5a2c898a6),
|
||||
UINT64_C(0x113f9804bef90dae), UINT64_C(0x1b710b35131c471b),
|
||||
UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493),
|
||||
UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493),
|
||||
UINT64_C(0x3c9ebe0a15c9bebc), UINT64_C(0x431d67c49c100d4c),
|
||||
UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a),
|
||||
UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a),
|
||||
UINT64_C(0x5fcb6fab3ad6faec), UINT64_C(0x6c44198c4a475817)
|
||||
};
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ static const uint64_t K[80] = {
|
|||
|
||||
|
||||
#define Ch(x,y,z) (z ^ (x & (y ^ z)))
|
||||
#define Maj(x,y,z) (((x | y) & z) | (x & y))
|
||||
#define Maj(x,y,z) (((x | y) & z) | (x & y))
|
||||
#define S(x, n) ROR64c(x, n)
|
||||
#define R(x, n) (((x) &UINT64_C(0xFFFFFFFFFFFFFFFF))>>((uint64_t)n))
|
||||
#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39))
|
||||
|
|
@ -88,7 +88,7 @@ static const uint64_t K[80] = {
|
|||
#endif
|
||||
|
||||
/* compress 1024-bits */
|
||||
static int sha512_compress(sha512_context *md, unsigned char *buf)
|
||||
static int sha512_compress(sha512_context *md, const unsigned char *buf)
|
||||
{
|
||||
uint64_t S[8], W[80], t0, t1;
|
||||
int i;
|
||||
|
|
@ -106,7 +106,7 @@ static int sha512_compress(sha512_context *md, unsigned char *buf)
|
|||
/* 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) \
|
||||
|
|
@ -168,25 +168,26 @@ 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 unsigned char *in, size_t inlen)
|
||||
{
|
||||
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, (unsigned char *)in)) != 0) {
|
||||
return err;
|
||||
}
|
||||
md->length += 128 * 8;
|
||||
in += 128;
|
||||
inlen -= 128;
|
||||
} else {
|
||||
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));
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
|
|
@ -194,19 +195,19 @@ int sha512_update (sha512_context * md, const unsigned char *in, size_t inlen)
|
|||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -215,22 +216,23 @@ int sha512_update (sha512_context * md, const unsigned char *in, size_t inlen)
|
|||
@param out [out] The destination of the hash (64 bytes)
|
||||
@return 0 if successful
|
||||
*/
|
||||
int sha512_final(sha512_context * md, unsigned char *out)
|
||||
{
|
||||
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->curlen >= sizeof(md->buf)) {
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* increase the length of the message */
|
||||
md->length += md->curlen * UINT64_C(8);
|
||||
md->length += md->curlen * UINT64_C(8);
|
||||
|
||||
/* append the '1' bit */
|
||||
md->buf[md->curlen++] = (unsigned char)0x80;
|
||||
md->buf[md->curlen++] = (unsigned char)0x80;
|
||||
|
||||
/* if the length is currently above 112 bytes we append zeros
|
||||
* then compress. Then we can fall back to padding zeros and length
|
||||
|
|
@ -244,27 +246,27 @@ int sha512_update (sha512_context * md, const unsigned char *in, size_t inlen)
|
|||
md->curlen = 0;
|
||||
}
|
||||
|
||||
/* pad upto 120 bytes of zeroes
|
||||
/* 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;
|
||||
}
|
||||
while (md->curlen < 120) {
|
||||
md->buf[md->curlen++] = (unsigned char)0;
|
||||
}
|
||||
|
||||
/* store length */
|
||||
STORE64H(md->length, md->buf+120);
|
||||
sha512_compress(md, md->buf);
|
||||
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));
|
||||
for (i = 0; i < 8; i++) {
|
||||
STORE64H(md->state[i], out+(8*i));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sha512(const unsigned char *message, size_t message_len, unsigned char *out)
|
||||
int sha512(const void *message, size_t message_len, void *out)
|
||||
{
|
||||
sha512_context ctx;
|
||||
int ret;
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ typedef struct sha512_context_ {
|
|||
|
||||
|
||||
int sha512_init(sha512_context * md);
|
||||
int sha512_final(sha512_context * md, unsigned char *out);
|
||||
int sha512_update(sha512_context * md, const unsigned char *in, size_t inlen);
|
||||
int sha512(const unsigned char *message, size_t message_len, unsigned char *out);
|
||||
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
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ edge_t *new_edge(void) {
|
|||
|
||||
void free_edge(edge_t *e) {
|
||||
sockaddrfree(&e->address);
|
||||
sockaddrfree(&e->local_address);
|
||||
|
||||
free(e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ struct ether_header {
|
|||
uint8_t ether_dhost[ETH_ALEN];
|
||||
uint8_t ether_shost[ETH_ALEN];
|
||||
uint16_t ether_type;
|
||||
} __attribute__ ((__packed__));
|
||||
} __attribute__ ((__gcc_struct__, __packed__));
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRUCT_ARPHDR
|
||||
|
|
@ -60,7 +60,7 @@ struct arphdr {
|
|||
uint8_t ar_hln;
|
||||
uint8_t ar_pln;
|
||||
uint16_t ar_op;
|
||||
} __attribute__ ((__packed__));
|
||||
} __attribute__ ((__gcc_struct__, __packed__));
|
||||
|
||||
#define ARPOP_REQUEST 1
|
||||
#define ARPOP_REPLY 2
|
||||
|
|
@ -78,7 +78,7 @@ struct ether_arp {
|
|||
uint8_t arp_spa[4];
|
||||
uint8_t arp_tha[ETH_ALEN];
|
||||
uint8_t arp_tpa[4];
|
||||
} __attribute__ ((__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
|
||||
|
|
|
|||
10
src/event.c
10
src/event.c
|
|
@ -285,6 +285,16 @@ bool event_loop(void) {
|
|||
io->cb(io->data, IO_WRITE);
|
||||
else if(FD_ISSET(io->fd, &readable))
|
||||
io->cb(io->data, IO_READ);
|
||||
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.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
/*
|
||||
* fake library for ssh
|
||||
*
|
||||
* This file is included in getaddrinfo.c and getnameinfo.c.
|
||||
* See getaddrinfo.c and getnameinfo.c.
|
||||
*/
|
||||
|
||||
/* for old netdb.h */
|
||||
#ifndef EAI_NODATA
|
||||
#define EAI_NODATA 1
|
||||
#endif
|
||||
|
||||
#ifndef EAI_MEMORY
|
||||
#define EAI_MEMORY 2
|
||||
#endif
|
||||
|
||||
#ifndef EAI_FAMILY
|
||||
#define EAI_FAMILY 3
|
||||
#endif
|
||||
|
||||
#ifndef EAI_SYSTEM
|
||||
#define EAI_SYSTEM 4
|
||||
#endif
|
||||
|
|
@ -1,102 +0,0 @@
|
|||
/*
|
||||
* fake library for ssh
|
||||
*
|
||||
* This file includes getaddrinfo(), freeaddrinfo() and gai_strerror().
|
||||
* These funtions are defined in rfc2133.
|
||||
*
|
||||
* But these functions are not implemented correctly. The minimum subset
|
||||
* is implemented for ssh use only. For exapmle, this routine assumes
|
||||
* that ai_family is AF_INET. Don't use it for another purpose.
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
||||
#include "ipv4.h"
|
||||
#include "ipv6.h"
|
||||
#include "fake-getaddrinfo.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
|
||||
#if !HAVE_DECL_GAI_STRERROR
|
||||
char *gai_strerror(int ecode) {
|
||||
switch (ecode) {
|
||||
case EAI_NODATA:
|
||||
return "No address associated with hostname";
|
||||
case EAI_MEMORY:
|
||||
return "Memory allocation failure";
|
||||
case EAI_FAMILY:
|
||||
return "Address family not supported";
|
||||
default:
|
||||
return "Unknown error";
|
||||
}
|
||||
}
|
||||
#endif /* !HAVE_GAI_STRERROR */
|
||||
|
||||
#if !HAVE_DECL_FREEADDRINFO
|
||||
void freeaddrinfo(struct addrinfo *ai) {
|
||||
struct addrinfo *next;
|
||||
|
||||
while(ai) {
|
||||
next = ai->ai_next;
|
||||
free(ai);
|
||||
ai = next;
|
||||
}
|
||||
}
|
||||
#endif /* !HAVE_FREEADDRINFO */
|
||||
|
||||
#if !HAVE_DECL_GETADDRINFO
|
||||
static struct addrinfo *malloc_ai(uint16_t port, uint32_t addr) {
|
||||
struct addrinfo *ai;
|
||||
|
||||
ai = xzalloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
|
||||
|
||||
ai->ai_addr = (struct sockaddr *)(ai + 1);
|
||||
ai->ai_addrlen = sizeof(struct sockaddr_in);
|
||||
ai->ai_addr->sa_family = ai->ai_family = AF_INET;
|
||||
|
||||
((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
|
||||
((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
|
||||
|
||||
return ai;
|
||||
}
|
||||
|
||||
int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res) {
|
||||
struct addrinfo *prev = NULL;
|
||||
struct hostent *hp;
|
||||
struct in_addr in = {0};
|
||||
int i;
|
||||
uint16_t port = 0;
|
||||
|
||||
if(hints && hints->ai_family != AF_INET && hints->ai_family != AF_UNSPEC)
|
||||
return EAI_FAMILY;
|
||||
|
||||
if (servname)
|
||||
port = htons(atoi(servname));
|
||||
|
||||
if (hints && hints->ai_flags & AI_PASSIVE) {
|
||||
*res = malloc_ai(port, htonl(0x00000000));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!hostname) {
|
||||
*res = malloc_ai(port, htonl(0x7f000001));
|
||||
return 0;
|
||||
}
|
||||
|
||||
hp = gethostbyname(hostname);
|
||||
|
||||
if(!hp || !hp->h_addr_list || !hp->h_addr_list[0])
|
||||
return EAI_NODATA;
|
||||
|
||||
for (i = 0; hp->h_addr_list[i]; i++) {
|
||||
*res = malloc_ai(port, ((struct in_addr *)hp->h_addr_list[i])->s_addr);
|
||||
|
||||
if(prev)
|
||||
prev->ai_next = *res;
|
||||
|
||||
prev = *res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* !HAVE_GETADDRINFO */
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
#ifndef _FAKE_GETADDRINFO_H
|
||||
#define _FAKE_GETADDRINFO_H
|
||||
|
||||
#include "fake-gai-errnos.h"
|
||||
|
||||
#ifndef AI_PASSIVE
|
||||
# define AI_PASSIVE 1
|
||||
# define AI_CANONNAME 2
|
||||
#endif
|
||||
|
||||
#ifndef NI_NUMERICHOST
|
||||
# define NI_NUMERICHOST 2
|
||||
# define NI_NAMEREQD 4
|
||||
# define NI_NUMERICSERV 8
|
||||
#endif
|
||||
|
||||
#ifndef AI_NUMERICHOST
|
||||
#define AI_NUMERICHOST 4
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRUCT_ADDRINFO
|
||||
struct addrinfo {
|
||||
int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
|
||||
int ai_family; /* PF_xxx */
|
||||
int ai_socktype; /* SOCK_xxx */
|
||||
int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
|
||||
size_t ai_addrlen; /* length of ai_addr */
|
||||
char *ai_canonname; /* canonical name for hostname */
|
||||
struct sockaddr *ai_addr; /* binary address */
|
||||
struct addrinfo *ai_next; /* next structure in linked list */
|
||||
};
|
||||
#endif /* !HAVE_STRUCT_ADDRINFO */
|
||||
|
||||
#if !HAVE_DECL_GETADDRINFO
|
||||
int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res);
|
||||
#endif /* !HAVE_GETADDRINFO */
|
||||
|
||||
#if !HAVE_DECL_GAI_STRERROR
|
||||
char *gai_strerror(int ecode);
|
||||
#endif /* !HAVE_GAI_STRERROR */
|
||||
|
||||
#if !HAVE_DECL_FREEADDRINFO
|
||||
void freeaddrinfo(struct addrinfo *ai);
|
||||
#endif /* !HAVE_FREEADDRINFO */
|
||||
|
||||
#endif /* _FAKE_GETADDRINFO_H */
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* fake library for ssh
|
||||
*
|
||||
* This file includes getnameinfo().
|
||||
* These funtions are defined in rfc2133.
|
||||
*
|
||||
* But these functions are not implemented correctly. The minimum subset
|
||||
* is implemented for ssh use only. For exapmle, this routine assumes
|
||||
* that ai_family is AF_INET. Don't use it for another purpose.
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
||||
#include "fake-getnameinfo.h"
|
||||
#include "fake-getaddrinfo.h"
|
||||
|
||||
#if !HAVE_DECL_GETNAMEINFO
|
||||
|
||||
int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) {
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
|
||||
struct hostent *hp;
|
||||
int len;
|
||||
|
||||
if(sa->sa_family != AF_INET)
|
||||
return EAI_FAMILY;
|
||||
|
||||
if(serv && servlen) {
|
||||
len = snprintf(serv, servlen, "%d", ntohs(sin->sin_port));
|
||||
if(len < 0 || len >= servlen)
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
|
||||
if(!host || !hostlen)
|
||||
return 0;
|
||||
|
||||
if(flags & NI_NUMERICHOST) {
|
||||
len = snprintf(host, hostlen, "%s", inet_ntoa(sin->sin_addr));
|
||||
if(len < 0 || len >= hostlen)
|
||||
return EAI_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
hp = gethostbyaddr((char *)&sin->sin_addr, sizeof(struct in_addr), AF_INET);
|
||||
|
||||
if(!hp || !hp->h_name || !hp->h_name[0])
|
||||
return EAI_NODATA;
|
||||
|
||||
len = snprintf(host, hostlen, "%s", hp->h_name);
|
||||
if(len < 0 || len >= hostlen)
|
||||
return EAI_MEMORY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* !HAVE_GETNAMEINFO */
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
#ifndef _FAKE_GETNAMEINFO_H
|
||||
#define _FAKE_GETNAMEINFO_H
|
||||
|
||||
#if !HAVE_DECL_GETNAMEINFO
|
||||
int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags);
|
||||
#endif /* !HAVE_GETNAMEINFO */
|
||||
|
||||
#ifndef NI_MAXSERV
|
||||
# define NI_MAXSERV 32
|
||||
#endif /* !NI_MAXSERV */
|
||||
#ifndef NI_MAXHOST
|
||||
# define NI_MAXHOST 1025
|
||||
#endif /* !NI_MAXHOST */
|
||||
|
||||
#endif /* _FAKE_GETNAMEINFO_H */
|
||||
498
src/fsck.c
Normal file
498
src/fsck.c
Normal file
|
|
@ -0,0 +1,498 @@
|
|||
/*
|
||||
fsck.c -- Check the configuration files for problems
|
||||
Copyright (C) 2014 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 "crypto.h"
|
||||
#include "ecdsa.h"
|
||||
#include "ecdsagen.h"
|
||||
#include "fsck.h"
|
||||
#include "names.h"
|
||||
#ifndef DISABLE_LEGACY
|
||||
#include "rsa.h"
|
||||
#include "rsagen.h"
|
||||
#endif
|
||||
#include "tincctl.h"
|
||||
#include "utils.h"
|
||||
|
||||
static bool ask_fix(void) {
|
||||
if(force)
|
||||
return true;
|
||||
if(!tty)
|
||||
return false;
|
||||
again:
|
||||
fprintf(stderr, "Fix y/n? ");
|
||||
char buf[1024];
|
||||
if(!fgets(buf, sizeof buf, stdin)) {
|
||||
tty = false;
|
||||
return false;
|
||||
}
|
||||
if(buf[0] == 'y' || buf[0] == 'Y')
|
||||
return true;
|
||||
if(buf[0] == 'n' || buf[0] == 'N')
|
||||
return false;
|
||||
goto again;
|
||||
}
|
||||
|
||||
static void print_tinc_cmd(const char *argv0, const char *format, ...) {
|
||||
if(confbasegiven)
|
||||
fprintf(stderr, "%s -c %s ", argv0, confbase);
|
||||
else if(netname)
|
||||
fprintf(stderr, "%s -n %s ", argv0, netname);
|
||||
else
|
||||
fprintf(stderr, "%s ", argv0);
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
vfprintf(stderr, format, va);
|
||||
va_end(va);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
||||
static int strtailcmp(const char *str, const char *tail) {
|
||||
size_t slen = strlen(str);
|
||||
size_t tlen = strlen(tail);
|
||||
if(tlen > slen)
|
||||
return -1;
|
||||
return memcmp(str + slen - tlen, tail, tlen);
|
||||
}
|
||||
|
||||
static void check_conffile(const char *fname, bool server) {
|
||||
FILE *f = fopen(fname, "r");
|
||||
if(!f) {
|
||||
fprintf(stderr, "ERROR: cannot read %s: %s\n", fname, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
char line[2048];
|
||||
int lineno = 0;
|
||||
bool skip = false;
|
||||
const int maxvariables = 50;
|
||||
int count[maxvariables];
|
||||
memset(count, 0, sizeof count);
|
||||
|
||||
while(fgets(line, sizeof line, f)) {
|
||||
if(skip) {
|
||||
if(!strncmp(line, "-----END", 8))
|
||||
skip = false;
|
||||
continue;
|
||||
} else {
|
||||
if(!strncmp(line, "-----BEGIN", 10)) {
|
||||
skip = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
int len;
|
||||
char *variable, *value, *eol;
|
||||
variable = value = line;
|
||||
|
||||
lineno++;
|
||||
|
||||
eol = line + strlen(line);
|
||||
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))
|
||||
continue;
|
||||
|
||||
found = true;
|
||||
|
||||
if(variables[i].type & VAR_OBSOLETE) {
|
||||
fprintf(stderr, "WARNING: obsolete variable %s in %s line %d\n", variable, fname, lineno);
|
||||
}
|
||||
|
||||
if(i < maxvariables)
|
||||
count[i]++;
|
||||
}
|
||||
|
||||
if(!found)
|
||||
fprintf(stderr, "WARNING: unknown variable %s in %s line %d\n", variable, fname, lineno);
|
||||
|
||||
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))
|
||||
fprintf(stderr, "WARNING: multiple instances of variable %s in %s\n", variables[i].name, fname);
|
||||
}
|
||||
|
||||
if(ferror(f))
|
||||
fprintf(stderr, "ERROR: while reading %s: %s\n", fname, strerror(errno));
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
int fsck(const char *argv0) {
|
||||
#ifdef HAVE_MINGW
|
||||
int uid = 0;
|
||||
#else
|
||||
uid_t uid = getuid();
|
||||
#endif
|
||||
|
||||
// Check that tinc.conf is readable.
|
||||
|
||||
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)
|
||||
fprintf(stderr, "You are currently not running tinc as root. Use sudo?\n");
|
||||
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;
|
||||
}
|
||||
|
||||
// Check for private keys.
|
||||
// TODO: use RSAPrivateKeyFile and Ed25519PrivateKeyFile variables if present.
|
||||
|
||||
struct stat st;
|
||||
char fname[PATH_MAX];
|
||||
char dname[PATH_MAX];
|
||||
|
||||
#ifndef DISABLE_LEGACY
|
||||
rsa_t *rsa_priv = NULL;
|
||||
snprintf(fname, sizeof fname, "%s/rsa_key.priv", confbase);
|
||||
|
||||
if(stat(fname, &st)) {
|
||||
if(errno != ENOENT) {
|
||||
// Something is seriously wrong here. If we can access the directory with tinc.conf in it, we should certainly be able to stat() an existing file.
|
||||
fprintf(stderr, "ERROR: cannot read %s: %s\n", fname, strerror(errno));
|
||||
fprintf(stderr, "Please correct this error.\n");
|
||||
return 1;
|
||||
}
|
||||
} 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");
|
||||
print_tinc_cmd(argv0, "generate-rsa-keys");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#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))
|
||||
fprintf(stderr, "ERROR: could not change permissions of %s: %s\n", fname, strerror(errno));
|
||||
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);
|
||||
|
||||
if(stat(fname, &st)) {
|
||||
if(errno != ENOENT) {
|
||||
// Something is seriously wrong here. If we can access the directory with tinc.conf in it, we should certainly be able to stat() an existing file.
|
||||
fprintf(stderr, "ERROR: cannot read %s: %s\n", fname, strerror(errno));
|
||||
fprintf(stderr, "Please correct this error.\n");
|
||||
return 1;
|
||||
}
|
||||
} 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");
|
||||
print_tinc_cmd(argv0, "generate-ed25519-keys");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#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))
|
||||
fprintf(stderr, "ERROR: could not change permissions of %s: %s\n", fname, strerror(errno));
|
||||
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
|
||||
fprintf(stderr, "You can generate new keys with:\n\n");
|
||||
print_tinc_cmd(argv0, "generate-keys");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Check for public keys.
|
||||
// TODO: use RSAPublicKeyFile variable if present.
|
||||
|
||||
snprintf(fname, sizeof fname, "%s/hosts/%s", confbase, name);
|
||||
if(access(fname, R_OK))
|
||||
fprintf(stderr, "WARNING: cannot read %s\n", fname);
|
||||
|
||||
FILE *f;
|
||||
|
||||
#ifndef DISABLE_LEGACY
|
||||
rsa_t *rsa_pub = NULL;
|
||||
|
||||
f = fopen(fname, "r");
|
||||
if(f)
|
||||
rsa_pub = rsa_read_pem_public_key(f);
|
||||
fclose(f);
|
||||
|
||||
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))
|
||||
fprintf(stderr, "Wrote RSA public key to %s.\n", fname);
|
||||
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));
|
||||
}
|
||||
}
|
||||
} 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);
|
||||
buf1[0] &= 0x7f;
|
||||
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)) {
|
||||
fprintf(stderr, "ERROR: private RSA key does not work.\n");
|
||||
return 1;
|
||||
}
|
||||
if(memcmp(buf1, buf3, sizeof buf1)) {
|
||||
fprintf(stderr, "ERROR: public and private RSA keys do not match.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
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(!f) {
|
||||
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))
|
||||
fprintf(stderr, "Wrote Ed25519 public key to %s.\n", fname);
|
||||
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));
|
||||
}
|
||||
}
|
||||
} 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)
|
||||
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"))
|
||||
continue;
|
||||
|
||||
strncpy(fname, ent->d_name, sizeof fname);
|
||||
char *dash = strrchr(fname, '-');
|
||||
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);
|
||||
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))
|
||||
fprintf(stderr, "ERROR: cannot change permissions on %s: %s\n", fname, strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
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"))
|
||||
continue;
|
||||
|
||||
strncpy(fname, ent->d_name, sizeof fname);
|
||||
char *dash = strrchr(fname, '-');
|
||||
if(!dash)
|
||||
continue;
|
||||
*dash = 0;
|
||||
|
||||
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))
|
||||
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))
|
||||
continue;
|
||||
|
||||
snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, ent->d_name);
|
||||
check_conffile(fname, false);
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
ecdh.c -- Diffie-Hellman key exchange handling
|
||||
Copyright (C) 2011-2013 Guus Sliepen <guus@tinc-vpn.org>
|
||||
fsck.h -- header for fsck.c.
|
||||
Copyright (C) 2012 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
|
||||
|
|
@ -17,21 +17,10 @@
|
|||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
#ifndef __TINC_FSCK_H__
|
||||
#define __TINC_FSCK_H__
|
||||
|
||||
#include "../ecdh.h"
|
||||
#include "../logger.h"
|
||||
#include "../utils.h"
|
||||
#include "../xalloc.h"
|
||||
extern int fsck(const char *argv0);
|
||||
|
||||
ecdh_t *ecdh_generate_public(void *pubkey) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "EC support using libgcrypt not implemented");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ecdh_compute_shared(ecdh_t *ecdh, const void *pubkey, void *shared) {
|
||||
return false
|
||||
}
|
||||
|
||||
void ecdh_free(ecdh_t *ecdh) {
|
||||
}
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
ecdsa.c -- ECDSA key handling
|
||||
Copyright (C) 2011-2013 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 "../logger.h"
|
||||
#include "../ecdsa.h"
|
||||
#include "../utils.h"
|
||||
#include "../xalloc.h"
|
||||
|
||||
// Get and set ECDSA keys
|
||||
//
|
||||
ecdsa_t *ecdsa_set_base64_public_key(const char *p) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "EC support using libgcrypt not implemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read PEM ECDSA keys
|
||||
|
||||
ecdsa_t *ecdsa_read_pem_public_key(FILE *fp) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "EC support using libgcrypt not implemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ecdsa_t *ecdsa_read_pem_private_key(FILE *fp) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "EC support using libgcrypt not implemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t ecdsa_size(ecdsa_t *ecdsa) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t len, void *sig) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ecdsa_verify(ecdsa_t *ecdsa, const void *in, size_t len, const void *sig) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ecdsa_active(ecdsa_t *ecdsa) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void ecdsa_free(ecdsa_t *ecdsa) {
|
||||
}
|
||||
|
|
@ -19,11 +19,88 @@
|
|||
|
||||
#include "../system.h"
|
||||
|
||||
#include "digest.h"
|
||||
#include "../digest.h"
|
||||
#include "../prf.h"
|
||||
#include "../ed25519/sha512.h"
|
||||
|
||||
static void memxor(char *buf, char c, size_t len) {
|
||||
for(size_t i = 0; i < len; i++)
|
||||
buf[i] ^= c;
|
||||
}
|
||||
|
||||
static const size_t mdlen = 64;
|
||||
static const size_t blklen = 128;
|
||||
|
||||
static bool hmac_sha512(const char *key, size_t keylen, const char *msg, size_t msglen, char *out) {
|
||||
char tmp[blklen + mdlen];
|
||||
sha512_context md;
|
||||
|
||||
if(keylen <= blklen) {
|
||||
memcpy(tmp, key, keylen);
|
||||
memset(tmp + keylen, 0, blklen - keylen);
|
||||
} else {
|
||||
if(sha512(key, keylen, tmp) != 0)
|
||||
return false;
|
||||
memset(tmp + mdlen, 0, blklen - mdlen);
|
||||
}
|
||||
|
||||
if(sha512_init(&md) != 0)
|
||||
return false;
|
||||
|
||||
// ipad
|
||||
memxor(tmp, 0x36, blklen);
|
||||
if(sha512_update(&md, tmp, blklen) != 0)
|
||||
return false;
|
||||
|
||||
// message
|
||||
if(sha512_update(&md, msg, msglen) != 0)
|
||||
return false;
|
||||
|
||||
if(sha512_final(&md, tmp + blklen) != 0)
|
||||
return false;
|
||||
|
||||
// opad
|
||||
memxor(tmp, 0x36 ^ 0x5c, blklen);
|
||||
if(sha512(tmp, sizeof tmp, out) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Generate key material from a master secret and a seed, based on RFC 4346 section 5.
|
||||
We use SHA512 instead of MD5 and SHA1.
|
||||
*/
|
||||
|
||||
bool prf(const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, size_t outlen) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "PRF support using libgcrypt not implemented");
|
||||
return false;
|
||||
/* Data is what the "inner" HMAC function processes.
|
||||
It consists of the previous HMAC result plus the seed.
|
||||
*/
|
||||
|
||||
char data[mdlen + seedlen];
|
||||
memset(data, 0, mdlen);
|
||||
memcpy(data + mdlen, seed, seedlen);
|
||||
|
||||
char hash[mdlen];
|
||||
|
||||
while(outlen > 0) {
|
||||
/* Inner HMAC */
|
||||
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))
|
||||
return false;
|
||||
out += mdlen;
|
||||
outlen -= mdlen;
|
||||
} else {
|
||||
if(!hmac_sha512(secret, secretlen, data, sizeof data, hash))
|
||||
return false;
|
||||
memcpy(out, hash, outlen);
|
||||
out += outlen;
|
||||
outlen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ static void sssp_bfs(void) {
|
|||
abort();
|
||||
|
||||
for splay_each(edge_t, e, n->edge_tree) { /* "e" is the edge connected to "from" */
|
||||
if(!e->reverse)
|
||||
if(!e->reverse || e->to == myself)
|
||||
continue;
|
||||
|
||||
/* Situation:
|
||||
|
|
@ -238,10 +238,11 @@ static void check_reachability(void) {
|
|||
|
||||
n->status.udp_confirmed = false;
|
||||
n->maxmtu = MTU;
|
||||
n->maxrecentlen = 0;
|
||||
n->minmtu = 0;
|
||||
n->mtuprobes = 0;
|
||||
|
||||
timeout_del(&n->mtutimeout);
|
||||
timeout_del(&n->udp_ping_timeout);
|
||||
|
||||
char *name;
|
||||
char *address;
|
||||
|
|
@ -275,6 +276,10 @@ static void check_reachability(void) {
|
|||
update_node_udp(n, NULL);
|
||||
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)
|
||||
send_ans_key(n);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ static uint32_t hash_function(const void *p, size_t len) {
|
|||
uint32_t hash = 0;
|
||||
while(true) {
|
||||
for(int i = len > 4 ? 4 : len; --i;)
|
||||
hash += q[len - i] << (8 * i);
|
||||
hash += (uint32_t)q[len - i] << (8 * i);
|
||||
hash *= 0x9e370001UL; // Golden ratio prime.
|
||||
if(len <= 4)
|
||||
break;
|
||||
|
|
|
|||
42
src/have.h
42
src/have.h
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
have.h -- include headers which are known to exist
|
||||
Copyright (C) 1998-2005 Ivo Timmermans
|
||||
2003-2013 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2003-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -22,17 +22,14 @@
|
|||
#define __TINC_HAVE_H__
|
||||
|
||||
#ifdef HAVE_MINGW
|
||||
#ifdef WITH_WINDOWS2000
|
||||
#define WINVER Windows2000
|
||||
#else
|
||||
#define WINVER WindowsXP
|
||||
#endif
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <signal.h>
|
||||
|
|
@ -40,6 +37,8 @@
|
|||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef HAVE_MINGW
|
||||
#include <w32api.h>
|
||||
|
|
@ -48,10 +47,6 @@
|
|||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDBOOL_H
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TERMIOS_H
|
||||
#include <termios.h>
|
||||
#endif
|
||||
|
|
@ -70,9 +65,6 @@
|
|||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TIME_H
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
|
|
@ -102,10 +94,6 @@
|
|||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_UIO_H
|
||||
#include <sys/uio.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
|
|
@ -197,6 +185,28 @@
|
|||
#include <netinet/if_ether.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ARPA_NAMESER_H
|
||||
#include <arpa/nameser.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_RESOLV_H
|
||||
#include <resolv.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LINUX_IF_TUN_H
|
||||
#include <linux/if_tun.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#else
|
||||
#include "getopt.h"
|
||||
#endif
|
||||
|
||||
#ifdef STATUS
|
||||
#undef STATUS
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MINGW
|
||||
#define SLASH "\\"
|
||||
#else
|
||||
|
|
|
|||
198
src/ifconfig.c
Normal file
198
src/ifconfig.c
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
ifconfig.c -- Generate platform specific interface configuration commands
|
||||
Copyright (C) 2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
||||
#include "conf.h"
|
||||
#include "ifconfig.h"
|
||||
#include "subnet.h"
|
||||
|
||||
static long start;
|
||||
|
||||
#ifndef HAVE_MINGW
|
||||
void ifconfig_header(FILE *out) {
|
||||
fprintf(out, "#!/bin/sh\n");
|
||||
start = ftell(out);
|
||||
}
|
||||
|
||||
void ifconfig_dhcp(FILE *out) {
|
||||
fprintf(out, "dhclient -nw \"$INTERFACE\"\n");
|
||||
}
|
||||
|
||||
void ifconfig_dhcp6(FILE *out) {
|
||||
fprintf(out, "dhclient -6 -nw \"$INTERFACE\"\n");
|
||||
}
|
||||
|
||||
void ifconfig_slaac(FILE *out) {
|
||||
#ifdef HAVE_LINUX
|
||||
fprintf(out, "echo 1 >\"/proc/sys/net/ipv6/conf/$INTERFACE/accept_ra\"\n");
|
||||
fprintf(out, "echo 1 >\"/proc/sys/net/ipv6/conf/$INTERFACE/autoconf\"\n");
|
||||
#else
|
||||
fprintf(out, "rtsol \"$INTERFACE\" &\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ifconfig_footer(FILE *out) {
|
||||
if(ftell(out) == start) {
|
||||
fprintf(out, "echo 'Unconfigured tinc-up script, please edit '$0'!'\n\n#ifconfig $INTERFACE <your vpn IP address> netmask <netmask of whole VPN>\n");
|
||||
return false;
|
||||
} else {
|
||||
#ifdef HAVE_LINUX
|
||||
fprintf(out, "ip link set \"$INTERFACE\" up\n");
|
||||
#else
|
||||
fprintf(out, "ifconfig \"$INTERFACE\" up\n");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#else
|
||||
void ifconfig_header(FILE *out) {
|
||||
start = ftell(out);
|
||||
}
|
||||
|
||||
void ifconfig_dhcp(FILE *out) {
|
||||
fprintf(out, "netsh interface ipv4 set address \"%%INTERFACE%%\" dhcp\n");
|
||||
}
|
||||
|
||||
void ifconfig_dhcp6(FILE *out) {
|
||||
fprintf(stderr, "DHCPv6 requested, but not supported by tinc on this platform\n");
|
||||
}
|
||||
|
||||
void ifconfig_slaac(FILE *out) {
|
||||
// It's the default?
|
||||
}
|
||||
|
||||
bool ifconfig_footer(FILE *out) {
|
||||
return ftell(out) != start;
|
||||
}
|
||||
#endif
|
||||
|
||||
static subnet_t ipv4, ipv6;
|
||||
|
||||
void ifconfig_address(FILE *out, const char *value) {
|
||||
subnet_t address = {};
|
||||
char address_str[MAXNETSTR];
|
||||
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;
|
||||
}
|
||||
#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;
|
||||
}
|
||||
#elif defined(HAVE_BSD)
|
||||
switch(address.type) {
|
||||
case SUBNET_MAC: fprintf(out, "ifconfig \"$INTERFACE\" link %s\n", address_str); break;
|
||||
case SUBNET_IPV4: fprintf(out, "ifconfig \"$INTERFACE\" %s\n", address_str); break;
|
||||
case SUBNET_IPV6: fprintf(out, "ifconfig \"$INTERFACE\" inet6 %s\n", address_str); break;
|
||||
default: return;
|
||||
}
|
||||
#elif defined(HAVE_MINGW) || defined(HAVE_CYGWIN)
|
||||
switch(address.type) {
|
||||
case SUBNET_MAC: fprintf(out, "ip link set \"$INTERFACE\" address %s\n", address_str); break;
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ifconfig_route(FILE *out, const char *value) {
|
||||
subnet_t subnet = {}, gateway = {};
|
||||
char subnet_str[MAXNETSTR] = "", gateway_str[MAXNETSTR] = "";
|
||||
char *sep = strchr(value, ' ');
|
||||
if(sep)
|
||||
*sep++ = 0;
|
||||
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) {
|
||||
fprintf(stderr, "Could not parse gateway in Route statement\n");
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
#elif defined(HAVE_BSD)
|
||||
// BSD route command is silly and doesn't accept an interface name as a destination.
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
#elif defined(HAVE_MINGW) || defined(HAVE_CYGWIN)
|
||||
if(*gateway_str) {
|
||||
switch(subnet.type) {
|
||||
case SUBNET_IPV4: fprintf(out, "netsh inetface ipv4 add route %s \"%%INTERFACE%%\" %s\n", subnet_str, gateway_str); break;
|
||||
case SUBNET_IPV6: fprintf(out, "netsh inetface ipv6 add route %s \"%%INTERFACE%%\" %s\n", subnet_str, gateway_str); break;
|
||||
default: return;
|
||||
}
|
||||
} else {
|
||||
switch(subnet.type) {
|
||||
case SUBNET_IPV4: fprintf(out, "netsh inetface ipv4 add route %s \"%%INTERFACE%%\"\n", subnet_str); break;
|
||||
case SUBNET_IPV6: fprintf(out, "netsh inetface ipv6 add route %s \"%%INTERFACE%%\"\n", subnet_str); break;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
31
src/ifconfig.h
Normal file
31
src/ifconfig.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
ifconfig.h -- header for ifconfig.c.
|
||||
Copyright (C) 2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef __TINC_IFCONFIG_H__
|
||||
#define __TINC_IFCONFIG_H__
|
||||
|
||||
extern void ifconfig_dhcp(FILE *out);
|
||||
extern void ifconfig_dhcp6(FILE *out);
|
||||
extern void ifconfig_slaac(FILE *out);
|
||||
extern void ifconfig_address(FILE *out, const char *value);
|
||||
extern void ifconfig_route(FILE *out, const char *value);
|
||||
extern void ifconfig_header(FILE *out);
|
||||
extern bool ifconfig_footer(FILE *out);
|
||||
|
||||
#endif
|
||||
255
src/invitation.c
255
src/invitation.c
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
invitation.c -- Create and accept invitations
|
||||
Copyright (C) 2013-2014 Guus Sliepen <guus@tinc-vpn.org>
|
||||
Copyright (C) 2013-2015 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
|
||||
|
|
@ -23,16 +23,20 @@
|
|||
#include "crypto.h"
|
||||
#include "ecdsa.h"
|
||||
#include "ecdsagen.h"
|
||||
#include "ifconfig.h"
|
||||
#include "invitation.h"
|
||||
#include "names.h"
|
||||
#include "netutl.h"
|
||||
#include "rsagen.h"
|
||||
#include "script.h"
|
||||
#include "sptps.h"
|
||||
#include "subnet.h"
|
||||
#include "tincctl.h"
|
||||
#include "utils.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
#include "ed25519/sha512.h"
|
||||
|
||||
int addressfamily = AF_UNSPEC;
|
||||
|
||||
static void scan_for_hostname(const char *filename, char **hostname, char **port) {
|
||||
|
|
@ -82,11 +86,11 @@ char *get_my_hostname() {
|
|||
char *port = NULL;
|
||||
char *hostport = NULL;
|
||||
char *name = get_my_name(false);
|
||||
char *filename = NULL;
|
||||
char filename[PATH_MAX] = {0};
|
||||
|
||||
// Use first Address statement in own host config file
|
||||
if(check_id(name)) {
|
||||
xasprintf(&filename, "%s" SLASH "hosts" SLASH "%s", confbase, name);
|
||||
snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", confbase, name);
|
||||
scan_for_hostname(filename, &hostname, &port);
|
||||
scan_for_hostname(tinc_conf, &hostname, &port);
|
||||
}
|
||||
|
|
@ -180,7 +184,7 @@ again:
|
|||
hostname = xstrdup(line);
|
||||
|
||||
save:
|
||||
if(filename) {
|
||||
if(*filename) {
|
||||
FILE *f = fopen(filename, "a");
|
||||
if(f) {
|
||||
fprintf(f, "\nAddress = %s\n", hostname);
|
||||
|
|
@ -205,7 +209,6 @@ done:
|
|||
|
||||
free(hostname);
|
||||
free(port);
|
||||
free(filename);
|
||||
return hostport;
|
||||
}
|
||||
|
||||
|
|
@ -241,14 +244,12 @@ int cmd_invite(int argc, char *argv[]) {
|
|||
return 1;
|
||||
|
||||
// Ensure no host configuration file with that name exists
|
||||
char *filename = NULL;
|
||||
xasprintf(&filename, "%s" SLASH "hosts" SLASH "%s", confbase, argv[1]);
|
||||
char filename[PATH_MAX];
|
||||
snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", confbase, argv[1]);
|
||||
if(!access(filename, F_OK)) {
|
||||
free(filename);
|
||||
fprintf(stderr, "A host config file for %s already exists!\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
free(filename);
|
||||
|
||||
// If a daemon is running, ensure no other nodes know about this name
|
||||
bool found = false;
|
||||
|
|
@ -270,12 +271,9 @@ int cmd_invite(int argc, char *argv[]) {
|
|||
}
|
||||
}
|
||||
|
||||
char hash[25];
|
||||
|
||||
xasprintf(&filename, "%s" SLASH "invitations", confbase);
|
||||
snprintf(filename, sizeof filename, "%s" SLASH "invitations", confbase);
|
||||
if(mkdir(filename, 0700) && errno != EEXIST) {
|
||||
fprintf(stderr, "Could not create directory %s: %s\n", filename, strerror(errno));
|
||||
free(filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -283,7 +281,6 @@ int cmd_invite(int argc, char *argv[]) {
|
|||
DIR *dir = opendir(filename);
|
||||
if(!dir) {
|
||||
fprintf(stderr, "Could not read directory %s: %s\n", filename, strerror(errno));
|
||||
free(filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -295,9 +292,9 @@ int cmd_invite(int argc, char *argv[]) {
|
|||
while((ent = readdir(dir))) {
|
||||
if(strlen(ent->d_name) != 24)
|
||||
continue;
|
||||
char *invname;
|
||||
char invname[PATH_MAX];
|
||||
struct stat st;
|
||||
xasprintf(&invname, "%s" SLASH "%s", filename, ent->d_name);
|
||||
snprintf(invname, sizeof invname, "%s" SLASH "%s", filename, ent->d_name);
|
||||
if(!stat(invname, &st)) {
|
||||
if(deadline < st.st_mtime)
|
||||
count++;
|
||||
|
|
@ -307,21 +304,17 @@ int cmd_invite(int argc, char *argv[]) {
|
|||
fprintf(stderr, "Could not stat %s: %s\n", invname, strerror(errno));
|
||||
errno = 0;
|
||||
}
|
||||
free(invname);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
|
||||
if(errno) {
|
||||
fprintf(stderr, "Error while reading directory %s: %s\n", filename, strerror(errno));
|
||||
closedir(dir);
|
||||
free(filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
free(filename);
|
||||
|
||||
ecdsa_t *key;
|
||||
xasprintf(&filename, "%s" SLASH "invitations" SLASH "ed25519_key.priv", confbase);
|
||||
snprintf(filename, sizeof filename, "%s" SLASH "invitations" SLASH "ed25519_key.priv", confbase);
|
||||
|
||||
// Remove the key if there are no outstanding invitations.
|
||||
if(!count)
|
||||
|
|
@ -332,23 +325,23 @@ int cmd_invite(int argc, char *argv[]) {
|
|||
if(!f) {
|
||||
if(errno != ENOENT) {
|
||||
fprintf(stderr, "Could not read %s: %s\n", filename, strerror(errno));
|
||||
free(filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
key = ecdsa_generate();
|
||||
if(!key) {
|
||||
free(filename);
|
||||
if(!key)
|
||||
return 1;
|
||||
}
|
||||
f = fopen(filename, "w");
|
||||
if(!f) {
|
||||
fprintf(stderr, "Could not write %s: %s\n", filename, strerror(errno));
|
||||
free(filename);
|
||||
return 1;
|
||||
}
|
||||
chmod(filename, 0600);
|
||||
ecdsa_write_pem_private_key(key, f);
|
||||
if(!ecdsa_write_pem_private_key(key, f)) {
|
||||
fprintf(stderr, "Could not write ECDSA private key\n");
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
if(connect_tincd(false))
|
||||
|
|
@ -360,16 +353,13 @@ int cmd_invite(int argc, char *argv[]) {
|
|||
fprintf(stderr, "Could not read private key from %s\n", filename);
|
||||
}
|
||||
|
||||
free(filename);
|
||||
if(!key)
|
||||
return 1;
|
||||
|
||||
// Create a hash of the key.
|
||||
char hash[64];
|
||||
char *fingerprint = ecdsa_get_base64_public_key(key);
|
||||
digest_t *digest = digest_open_by_name("sha256", 18);
|
||||
if(!digest)
|
||||
abort();
|
||||
digest_create(digest, fingerprint, strlen(fingerprint), hash);
|
||||
sha512(fingerprint, strlen(fingerprint), hash);
|
||||
b64encode_urlsafe(hash, hash, 18);
|
||||
|
||||
// Create a random cookie for this invitation.
|
||||
|
|
@ -378,20 +368,19 @@ int cmd_invite(int argc, char *argv[]) {
|
|||
|
||||
// Create a filename that doesn't reveal the cookie itself
|
||||
char buf[18 + strlen(fingerprint)];
|
||||
char cookiehash[25];
|
||||
char cookiehash[64];
|
||||
memcpy(buf, cookie, 18);
|
||||
memcpy(buf + 18, fingerprint, sizeof buf - 18);
|
||||
digest_create(digest, buf, sizeof buf, cookiehash);
|
||||
sha512(buf, sizeof buf, cookiehash);
|
||||
b64encode_urlsafe(cookiehash, cookiehash, 18);
|
||||
|
||||
b64encode_urlsafe(cookie, cookie, 18);
|
||||
|
||||
// Create a file containing the details of the invitation.
|
||||
xasprintf(&filename, "%s" SLASH "invitations" SLASH "%s", confbase, cookiehash);
|
||||
snprintf(filename, sizeof filename, "%s" SLASH "invitations" SLASH "%s", confbase, cookiehash);
|
||||
int ifd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||
if(!ifd) {
|
||||
fprintf(stderr, "Could not create invitation file %s: %s\n", filename, strerror(errno));
|
||||
free(filename);
|
||||
return 1;
|
||||
}
|
||||
f = fdopen(ifd, "w");
|
||||
|
|
@ -403,7 +392,7 @@ int cmd_invite(int argc, char *argv[]) {
|
|||
|
||||
// Fill in the details.
|
||||
fprintf(f, "Name = %s\n", argv[1]);
|
||||
if(netname)
|
||||
if(check_netname(netname, true))
|
||||
fprintf(f, "NetName = %s\n", netname);
|
||||
fprintf(f, "ConnectTo = %s\n", myname);
|
||||
|
||||
|
|
@ -426,11 +415,10 @@ int cmd_invite(int argc, char *argv[]) {
|
|||
fprintf(f, "#---------------------------------------------------------------#\n");
|
||||
fprintf(f, "Name = %s\n", myname);
|
||||
|
||||
char *filename2;
|
||||
xasprintf(&filename2, "%s" SLASH "hosts" SLASH "%s", confbase, myname);
|
||||
char filename2[PATH_MAX];
|
||||
snprintf(filename2, sizeof filename2, "%s" SLASH "hosts" SLASH "%s", confbase, myname);
|
||||
fcopy(f, filename2);
|
||||
fclose(f);
|
||||
free(filename2);
|
||||
|
||||
// Create an URL from the local address, key hash and cookie
|
||||
char *url;
|
||||
|
|
@ -449,7 +437,6 @@ int cmd_invite(int argc, char *argv[]) {
|
|||
|
||||
puts(url);
|
||||
free(url);
|
||||
free(filename);
|
||||
free(address);
|
||||
|
||||
return 0;
|
||||
|
|
@ -554,12 +541,17 @@ static bool finalize_join(void) {
|
|||
}
|
||||
|
||||
if(!check_id(name)) {
|
||||
fprintf(stderr, "Invalid Name found in invitation: %s!\n", name);
|
||||
fprintf(stderr, "Invalid Name found in invitation!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!netname)
|
||||
if(!netname) {
|
||||
netname = grep(data, "NetName");
|
||||
if(netname && !check_netname(netname, true)) {
|
||||
fprintf(stderr, "Unsafe NetName found in invitation!\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ask_netname = false;
|
||||
char temp_netname[32];
|
||||
|
|
@ -570,7 +562,7 @@ make_names:
|
|||
confbase = NULL;
|
||||
}
|
||||
|
||||
make_names();
|
||||
make_names(false);
|
||||
|
||||
free(tinc_conf);
|
||||
free(hosts_dir);
|
||||
|
|
@ -608,8 +600,8 @@ make_names:
|
|||
|
||||
fprintf(f, "Name = %s\n", name);
|
||||
|
||||
char *filename;
|
||||
xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name);
|
||||
char filename[PATH_MAX];
|
||||
snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, name);
|
||||
FILE *fh = fopen(filename, "w");
|
||||
if(!fh) {
|
||||
fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno));
|
||||
|
|
@ -617,7 +609,19 @@ make_names:
|
|||
return false;
|
||||
}
|
||||
|
||||
snprintf(filename, sizeof filename, "%s" SLASH "tinc-up.invitation", confbase);
|
||||
FILE *fup = fopen(filename, "w");
|
||||
if(!fup) {
|
||||
fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno));
|
||||
fclose(f);
|
||||
fclose(fh);
|
||||
return false;
|
||||
}
|
||||
|
||||
ifconfig_header(fup);
|
||||
|
||||
// Filter first chunk on approved keywords, split between tinc.conf and hosts/Name
|
||||
// Generate a tinc-up script from Ifconfig and Route keywords.
|
||||
// Other chunks go unfiltered to their respective host config files
|
||||
const char *p = data;
|
||||
char *l, *value;
|
||||
|
|
@ -656,6 +660,24 @@ make_names:
|
|||
break;
|
||||
}
|
||||
|
||||
// Handle Ifconfig and Route statements
|
||||
if(!found) {
|
||||
if(!strcasecmp(l, "Ifconfig")) {
|
||||
if(!strcasecmp(value, "dhcp"))
|
||||
ifconfig_dhcp(fup);
|
||||
else if(!strcasecmp(value, "dhcp6"))
|
||||
ifconfig_dhcp6(fup);
|
||||
else if(!strcasecmp(value, "slaac"))
|
||||
ifconfig_slaac(fup);
|
||||
else
|
||||
ifconfig_address(fup, value);
|
||||
continue;
|
||||
} else if(!strcasecmp(l, "Route")) {
|
||||
ifconfig_route(fup, value);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore unknown and unsafe variables
|
||||
if(!found) {
|
||||
fprintf(stderr, "Ignoring unknown variable '%s' in invitation.\n", l);
|
||||
|
|
@ -670,7 +692,8 @@ make_names:
|
|||
}
|
||||
|
||||
fclose(f);
|
||||
free(filename);
|
||||
bool valid_tinc_up = ifconfig_footer(fup);
|
||||
fclose(fup);
|
||||
|
||||
while(l && !strcasecmp(l, "Name")) {
|
||||
if(!check_id(value)) {
|
||||
|
|
@ -683,7 +706,7 @@ make_names:
|
|||
return false;
|
||||
}
|
||||
|
||||
xasprintf(&filename, "%s" SLASH "%s", hosts_dir, value);
|
||||
snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, value);
|
||||
f = fopen(filename, "w");
|
||||
|
||||
if(!f) {
|
||||
|
|
@ -711,7 +734,6 @@ make_names:
|
|||
}
|
||||
|
||||
fclose(f);
|
||||
free(filename);
|
||||
}
|
||||
|
||||
// Generate our key and send a copy to the server
|
||||
|
|
@ -723,8 +745,10 @@ make_names:
|
|||
if(!b64key)
|
||||
return false;
|
||||
|
||||
xasprintf(&filename, "%s" SLASH "ed25519_key.priv", confbase);
|
||||
snprintf(filename, sizeof filename, "%s" SLASH "ed25519_key.priv", confbase);
|
||||
f = fopenmask(filename, "w", 0600);
|
||||
if(!f)
|
||||
return false;
|
||||
|
||||
if(!ecdsa_write_pem_private_key(key, f)) {
|
||||
fprintf(stderr, "Error writing private key!\n");
|
||||
|
|
@ -739,20 +763,25 @@ make_names:
|
|||
|
||||
sptps_send_record(&sptps, 1, b64key, strlen(b64key));
|
||||
free(b64key);
|
||||
ecdsa_free(key);
|
||||
|
||||
|
||||
#ifndef DISABLE_LEGACY
|
||||
rsa_t *rsa = rsa_generate(2048, 0x1001);
|
||||
xasprintf(&filename, "%s" SLASH "rsa_key.priv", confbase);
|
||||
snprintf(filename, sizeof filename, "%s" SLASH "rsa_key.priv", confbase);
|
||||
f = fopenmask(filename, "w", 0600);
|
||||
|
||||
rsa_write_pem_private_key(rsa, f);
|
||||
if(!f || !rsa_write_pem_private_key(rsa, f)) {
|
||||
fprintf(stderr, "Could not write private RSA key\n");
|
||||
} else if(!rsa_write_pem_public_key(rsa, fh)) {
|
||||
fprintf(stderr, "Could not write public RSA key\n");
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
rsa_write_pem_public_key(rsa, fh);
|
||||
fclose(fh);
|
||||
|
||||
ecdsa_free(key);
|
||||
rsa_free(rsa);
|
||||
#endif
|
||||
|
||||
check_port(name);
|
||||
|
||||
|
|
@ -768,17 +797,69 @@ ask_netname:
|
|||
|
||||
line[strlen(line) - 1] = 0;
|
||||
|
||||
char *newbase;
|
||||
xasprintf(&newbase, CONFDIR SLASH "tinc" SLASH "%s", line);
|
||||
char newbase[PATH_MAX];
|
||||
snprintf(newbase, sizeof newbase, CONFDIR SLASH "tinc" SLASH "%s", line);
|
||||
if(rename(confbase, newbase)) {
|
||||
fprintf(stderr, "Error trying to rename %s to %s: %s\n", confbase, newbase, strerror(errno));
|
||||
free(newbase);
|
||||
goto ask_netname;
|
||||
}
|
||||
|
||||
free(newbase);
|
||||
netname = line;
|
||||
make_names();
|
||||
make_names(false);
|
||||
}
|
||||
|
||||
char filename2[PATH_MAX];
|
||||
snprintf(filename, sizeof filename, "%s" SLASH "tinc-up.invitation", confbase);
|
||||
snprintf(filename2, sizeof filename2, "%s" SLASH "tinc-up", confbase);
|
||||
|
||||
if(valid_tinc_up) {
|
||||
if(tty) {
|
||||
FILE *fup = fopen(filename, "r");
|
||||
if(fup) {
|
||||
fprintf(stderr, "\nPlease review the following tinc-up script:\n\n");
|
||||
|
||||
char buf[MAXSIZE];
|
||||
while(fgets(buf, sizeof buf, fup))
|
||||
fputs(buf, stderr);
|
||||
fclose(fup);
|
||||
|
||||
int response = 0;
|
||||
do {
|
||||
fprintf(stderr, "\nDo you want to use this script [y]es/[n]o/[e]dit? ");
|
||||
response = tolower(getchar());
|
||||
} while(!strchr("yne", response));
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
if(response == 'e') {
|
||||
char *command;
|
||||
#ifndef HAVE_MINGW
|
||||
xasprintf(&command, "\"%s\" \"%s\"", getenv("VISUAL") ?: getenv("EDITOR") ?: "vi", filename);
|
||||
#else
|
||||
xasprintf(&command, "edit \"%s\"", filename);
|
||||
#endif
|
||||
if(system(command))
|
||||
response = 'n';
|
||||
else
|
||||
response = 'y';
|
||||
free(command);
|
||||
}
|
||||
|
||||
if(response == 'y') {
|
||||
rename(filename, filename2);
|
||||
chmod(filename2, 0755);
|
||||
fprintf(stderr, "tinc-up enabled.\n");
|
||||
} else {
|
||||
fprintf(stderr, "tinc-up has been left disabled.\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "A tinc-up script was generated, but has been left disabled.\n");
|
||||
}
|
||||
} else {
|
||||
// A placeholder was generated.
|
||||
rename(filename, filename2);
|
||||
chmod(filename2, 0755);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Configuration stored in: %s\n", confbase);
|
||||
|
|
@ -922,16 +1003,31 @@ int cmd_join(int argc, char *argv[]) {
|
|||
if(!ai)
|
||||
return 1;
|
||||
|
||||
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||
if(sock <= 0) {
|
||||
fprintf(stderr, "Could not open socket: %s\n", strerror(errno));
|
||||
return 1;
|
||||
struct addrinfo *aip = NULL;
|
||||
|
||||
next:
|
||||
if(!aip)
|
||||
aip = ai;
|
||||
else {
|
||||
aip = aip->ai_next;
|
||||
if(!aip)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(connect(sock, ai->ai_addr, ai->ai_addrlen)) {
|
||||
fprintf(stderr, "Could not connect to %s port %s: %s\n", address, port, strerror(errno));
|
||||
sock = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
|
||||
if(sock <= 0) {
|
||||
fprintf(stderr, "Could not open socket: %s\n", strerror(errno));
|
||||
goto next;
|
||||
}
|
||||
|
||||
if(connect(sock, aip->ai_addr, aip->ai_addrlen)) {
|
||||
char *addrstr, *portstr;
|
||||
sockaddr2str((sockaddr_t *)aip->ai_addr, &addrstr, &portstr);
|
||||
fprintf(stderr, "Could not connect to %s port %s: %s\n", addrstr, portstr, strerror(errno));
|
||||
free(addrstr);
|
||||
free(portstr);
|
||||
closesocket(sock);
|
||||
return 1;
|
||||
goto next;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Connected to %s port %s...\n", address, port);
|
||||
|
|
@ -944,7 +1040,7 @@ int cmd_join(int argc, char *argv[]) {
|
|||
if(!sendline(sock, "0 ?%s %d.%d", b64key, PROT_MAJOR, 1)) {
|
||||
fprintf(stderr, "Error sending request to %s port %s: %s\n", address, port, strerror(errno));
|
||||
closesocket(sock);
|
||||
return 1;
|
||||
goto next;
|
||||
}
|
||||
|
||||
char hisname[4096] = "";
|
||||
|
|
@ -953,16 +1049,13 @@ int cmd_join(int argc, char *argv[]) {
|
|||
if(!recvline(sock, line, sizeof line) || sscanf(line, "%d %s %d.%d", &code, hisname, &hismajor, &hisminor) < 3 || code != 0 || hismajor != PROT_MAJOR || !check_id(hisname) || !recvline(sock, line, sizeof line) || !rstrip(line) || sscanf(line, "%d ", &code) != 1 || code != ACK || strlen(line) < 3) {
|
||||
fprintf(stderr, "Cannot read greeting from peer\n");
|
||||
closesocket(sock);
|
||||
return 1;
|
||||
goto next;
|
||||
}
|
||||
|
||||
// Check if the hash of the key he gave us matches the hash in the URL.
|
||||
char *fingerprint = line + 2;
|
||||
digest_t *digest = digest_open_by_name("sha256", 18);
|
||||
if(!digest)
|
||||
abort();
|
||||
char hishash[18];
|
||||
if(!digest_create(digest, fingerprint, strlen(fingerprint), hishash)) {
|
||||
char hishash[64];
|
||||
if(sha512(fingerprint, strlen(fingerprint), hishash)) {
|
||||
fprintf(stderr, "Could not create digest\n%s\n", line + 2);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -992,8 +1085,14 @@ int cmd_join(int argc, char *argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
if(!sptps_receive_data(&sptps, line, len))
|
||||
return 1;
|
||||
char *p = line;
|
||||
while(len) {
|
||||
int done = sptps_receive_data(&sptps, p, len);
|
||||
if(!done)
|
||||
return 1;
|
||||
len -= done;
|
||||
p += done;
|
||||
}
|
||||
}
|
||||
|
||||
sptps_stop(&sptps);
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ struct ip {
|
|||
uint8_t ip_p;
|
||||
uint16_t ip_sum;
|
||||
struct in_addr ip_src, ip_dst;
|
||||
} __attribute__ ((__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__ ((__packed__));
|
||||
} __attribute__ ((__gcc_struct__, __packed__));
|
||||
#endif
|
||||
|
||||
#endif /* __TINC_IPV4_H__ */
|
||||
|
|
|
|||
33
src/ipv6.h
33
src/ipv6.h
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
ipv6.h -- missing IPv6 related definitions
|
||||
Copyright (C) 2005 Ivo Timmermans
|
||||
2006-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2006-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -29,29 +29,6 @@
|
|||
#define IPPROTO_ICMPV6 58
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRUCT_IN6_ADDR
|
||||
struct in6_addr {
|
||||
union {
|
||||
uint8_t u6_addr8[16];
|
||||
uint16_t u6_addr16[8];
|
||||
uint32_t u6_addr32[4];
|
||||
} in6_u;
|
||||
} __attribute__ ((__packed__));
|
||||
#define s6_addr in6_u.u6_addr8
|
||||
#define s6_addr16 in6_u.u6_addr16
|
||||
#define s6_addr32 in6_u.u6_addr32
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRUCT_SOCKADDR_IN6
|
||||
struct sockaddr_in6 {
|
||||
uint16_t sin6_family;
|
||||
uint16_t sin6_port;
|
||||
uint32_t sin6_flowinfo;
|
||||
struct in6_addr sin6_addr;
|
||||
uint32_t sin6_scope_id;
|
||||
} __attribute__ ((__packed__));
|
||||
#endif
|
||||
|
||||
#ifndef IN6_IS_ADDR_V4MAPPED
|
||||
#define IN6_IS_ADDR_V4MAPPED(a) \
|
||||
((((__const uint32_t *) (a))[0] == 0) \
|
||||
|
|
@ -72,7 +49,7 @@ struct ip6_hdr {
|
|||
} ip6_ctlun;
|
||||
struct in6_addr ip6_src;
|
||||
struct in6_addr ip6_dst;
|
||||
} __attribute__ ((__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
|
||||
|
|
@ -91,7 +68,7 @@ struct icmp6_hdr {
|
|||
uint16_t icmp6_un_data16[2];
|
||||
uint8_t icmp6_un_data8[4];
|
||||
} icmp6_dataun;
|
||||
} __attribute__ ((__packed__));
|
||||
} __attribute__ ((__gcc_struct__, __packed__));
|
||||
#define ICMP6_DST_UNREACH_NOROUTE 0
|
||||
#define ICMP6_DST_UNREACH 1
|
||||
#define ICMP6_PACKET_TOO_BIG 2
|
||||
|
|
@ -111,7 +88,7 @@ struct icmp6_hdr {
|
|||
struct nd_neighbor_solicit {
|
||||
struct icmp6_hdr nd_ns_hdr;
|
||||
struct in6_addr nd_ns_target;
|
||||
} __attribute__ ((__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
|
||||
|
|
@ -124,7 +101,7 @@ struct nd_neighbor_solicit {
|
|||
struct nd_opt_hdr {
|
||||
uint8_t nd_opt_type;
|
||||
uint8_t nd_opt_len;
|
||||
} __attribute__ ((__packed__));
|
||||
} __attribute__ ((__gcc_struct__, __packed__));
|
||||
#endif
|
||||
|
||||
#endif /* __TINC_IPV6_H__ */
|
||||
|
|
|
|||
|
|
@ -101,6 +101,9 @@ static bool setup_device(void) {
|
|||
strncpy(ifrname, ifr.ifr_name, IFNAMSIZ);
|
||||
free(iface);
|
||||
iface = xstrdup(ifrname);
|
||||
} else {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Could not create a tun/tap interface from %s: %s", device, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
|
||||
|
|
|
|||
|
|
@ -79,6 +79,12 @@ extern void list_delete_list(list_t *);
|
|||
extern void list_foreach(list_t *, list_action_t);
|
||||
extern void list_foreach_node(list_t *, list_action_node_t);
|
||||
|
||||
/*
|
||||
Iterates over a list.
|
||||
|
||||
CAUTION: while this construct supports deleting the current item,
|
||||
it does *not* support deleting *other* nodes while iterating on the list.
|
||||
*/
|
||||
#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__ */
|
||||
|
|
|
|||
27
src/logger.c
27
src/logger.c
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
logger.c -- logging code
|
||||
Copyright (C) 2004-2013 Guus Sliepen <guus@tinc-vpn.org>
|
||||
Copyright (C) 2004-2015 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2004-2005 Ivo Timmermans
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
|
@ -26,6 +26,7 @@
|
|||
#include "logger.h"
|
||||
#include "connection.h"
|
||||
#include "control_common.h"
|
||||
#include "process.h"
|
||||
#include "sptps.h"
|
||||
|
||||
debug_t debug_level = DEBUG_NOTHING;
|
||||
|
|
@ -37,7 +38,7 @@ static HANDLE loghandle = NULL;
|
|||
#endif
|
||||
static const char *logident = NULL;
|
||||
bool logcontrol = false;
|
||||
|
||||
int umbilical = 0;
|
||||
|
||||
static void real_logger(int level, int priority, const char *message) {
|
||||
char timestr[32] = "";
|
||||
|
|
@ -79,6 +80,11 @@ static void real_logger(int level, int priority, const char *message) {
|
|||
case LOGMODE_NULL:
|
||||
break;
|
||||
}
|
||||
|
||||
if(umbilical && do_detach) {
|
||||
write(umbilical, message, strlen(message));
|
||||
write(umbilical, "\n", 1);
|
||||
}
|
||||
}
|
||||
|
||||
if(logcontrol) {
|
||||
|
|
@ -114,9 +120,19 @@ void logger(int level, int priority, const char *format, ...) {
|
|||
|
||||
static void sptps_logger(sptps_t *s, int s_errno, const char *format, va_list ap) {
|
||||
char message[1024] = "";
|
||||
int len = vsnprintf(message, sizeof message, format, ap);
|
||||
if(len > 0 && len < sizeof message && message[len - 1] == '\n')
|
||||
message[len - 1] = 0;
|
||||
size_t msglen = sizeof message;
|
||||
|
||||
int len = vsnprintf(message, msglen, format, ap);
|
||||
if(len > 0 && len < sizeof message) {
|
||||
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);
|
||||
}
|
||||
|
||||
real_logger(DEBUG_ALWAYS, LOG_ERR, message);
|
||||
}
|
||||
|
|
@ -194,6 +210,5 @@ void closelogger(void) {
|
|||
case LOGMODE_NULL:
|
||||
case LOGMODE_STDERR:
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ enum {
|
|||
|
||||
extern debug_t debug_level;
|
||||
extern bool logcontrol;
|
||||
extern int umbilical;
|
||||
extern void openlogger(const char *, logmode_t);
|
||||
extern void reopenlogger(void);
|
||||
extern void logger(int, int, const char *, ...) __attribute__ ((__format__(printf, 3, 4)));
|
||||
|
|
|
|||
55
src/meta.c
55
src/meta.c
|
|
@ -30,6 +30,10 @@
|
|||
#include "utils.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(x, y) (((x)<(y))?(x):(y))
|
||||
#endif
|
||||
|
||||
bool send_meta_sptps(void *handle, uint8_t type, const void *buffer, size_t length) {
|
||||
connection_t *c = handle;
|
||||
|
||||
|
|
@ -58,6 +62,9 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
|
|||
|
||||
/* Add our data to buffer */
|
||||
if(c->status.encryptout) {
|
||||
#ifdef DISABLE_LEGACY
|
||||
return false;
|
||||
#else
|
||||
size_t outlen = length;
|
||||
|
||||
if(!cipher_encrypt(c->outcipher, buffer, length, buffer_prepare(&c->outbuf, length), &outlen, false) || outlen != length) {
|
||||
|
|
@ -65,6 +72,7 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
|
|||
c->name, c->hostname);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
buffer_add(&c->outbuf, buffer, length);
|
||||
}
|
||||
|
|
@ -74,6 +82,20 @@ 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) {
|
||||
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);
|
||||
|
||||
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) {
|
||||
for list_each(connection_t, c, connection_list)
|
||||
if(c != from && c->edge)
|
||||
|
|
@ -155,8 +177,33 @@ bool receive_meta(connection_t *c) {
|
|||
}
|
||||
|
||||
do {
|
||||
if(c->protocol_minor >= 2)
|
||||
return sptps_receive_data(&c->sptps, bufp, inlen);
|
||||
/* Are we receiving a SPTPS packet? */
|
||||
|
||||
if(c->sptpslen) {
|
||||
int 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))
|
||||
return false;
|
||||
c->sptpslen = 0;
|
||||
|
||||
bufp += len;
|
||||
inlen -= len;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(c->protocol_minor >= 2) {
|
||||
int len = sptps_receive_data(&c->sptps, bufp, inlen);
|
||||
if(!len)
|
||||
return false;
|
||||
bufp += len;
|
||||
inlen -= len;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!c->status.decryptin) {
|
||||
endp = memchr(bufp, '\n', inlen);
|
||||
|
|
@ -170,6 +217,9 @@ bool receive_meta(connection_t *c) {
|
|||
inlen -= endp - bufp;
|
||||
bufp = endp;
|
||||
} else {
|
||||
#ifdef DISABLE_LEGACY
|
||||
return false;
|
||||
#else
|
||||
size_t outlen = inlen;
|
||||
|
||||
if(!cipher_decrypt(c->incipher, bufp, inlen, buffer_prepare(&c->inbuf, inlen), &outlen, false) || inlen != outlen) {
|
||||
|
|
@ -179,6 +229,7 @@ bool receive_meta(connection_t *c) {
|
|||
}
|
||||
|
||||
inlen = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
while(c->inbuf.len) {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#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);
|
||||
|
|
|
|||
|
|
@ -38,7 +38,9 @@ int device_fd = -1;
|
|||
static HANDLE device_handle = INVALID_HANDLE_VALUE;
|
||||
static io_t device_read_io;
|
||||
static OVERLAPPED device_read_overlapped;
|
||||
static OVERLAPPED device_write_overlapped;
|
||||
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;
|
||||
|
|
@ -99,6 +101,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)
|
||||
logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: both Device and Interface specified, results may not be as expected");
|
||||
|
||||
/* Open registry and look for network adapters */
|
||||
|
||||
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &key)) {
|
||||
|
|
@ -175,6 +180,25 @@ static bool setup_device(void) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Get version information from tap device */
|
||||
|
||||
{
|
||||
ULONG info[3] = {0};
|
||||
DWORD len;
|
||||
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 {
|
||||
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.");
|
||||
}
|
||||
}
|
||||
|
||||
/* 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)) {
|
||||
|
|
@ -200,8 +224,12 @@ static void enable_device(void) {
|
|||
DWORD len;
|
||||
DeviceIoControl(device_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, sizeof status, &status, sizeof status, &len, NULL);
|
||||
|
||||
io_add_event(&device_read_io, device_handle_read, NULL, CreateEvent(NULL, TRUE, FALSE, NULL));
|
||||
device_read_overlapped.hEvent = device_read_io.event;
|
||||
/* We don't use the write event directly, but GetOverlappedResult() does, internally. */
|
||||
|
||||
device_read_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
device_write_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
io_add_event(&device_read_io, device_handle_read, NULL, device_read_overlapped.hEvent);
|
||||
device_issue_read();
|
||||
}
|
||||
|
||||
|
|
@ -210,10 +238,22 @@ static void disable_device(void) {
|
|||
|
||||
io_del(&device_read_io);
|
||||
CancelIo(device_handle);
|
||||
|
||||
/* According to MSDN, CancelIo() does not necessarily wait for the operation to complete.
|
||||
To prevent race conditions, make sure the operation is complete
|
||||
before we close the event it's referencing. */
|
||||
|
||||
DWORD len;
|
||||
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)
|
||||
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);
|
||||
|
||||
ULONG status = 0;
|
||||
DWORD len;
|
||||
DeviceIoControl(device_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, sizeof status, &status, sizeof status, &len, NULL);
|
||||
}
|
||||
|
||||
|
|
@ -231,12 +271,29 @@ static bool read_packet(vpn_packet_t *packet) {
|
|||
|
||||
static bool write_packet(vpn_packet_t *packet) {
|
||||
DWORD outlen;
|
||||
OVERLAPPED overlapped = {0};
|
||||
|
||||
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s",
|
||||
packet->len, device_info);
|
||||
|
||||
if(!WriteFile(device_handle, DATA(packet), packet->len, &outlen, &overlapped)) {
|
||||
if(device_write_packet.len > 0) {
|
||||
/* Make sure the previous write operation is finished before we start the next one;
|
||||
otherwise we end up with multiple write ops referencing the same OVERLAPPED structure,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy the packet, since the write operation might still be ongoing after we return. */
|
||||
|
||||
memcpy(&device_write_packet, packet, sizeof *packet);
|
||||
|
||||
if(WriteFile(device_handle, DATA(&device_write_packet), device_write_packet.len, &outlen, &device_write_overlapped))
|
||||
device_write_packet.len = 0;
|
||||
else if (GetLastError() != ERROR_IO_PENDING) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info, device, winerror(GetLastError()));
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ static void close_device(void) {
|
|||
static bool read_packet(vpn_packet_t *packet) {
|
||||
int lenin;
|
||||
|
||||
if((lenin = recv(device_fd, DATA(packet), MTU, 0)) <= 0) {
|
||||
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));
|
||||
return false;
|
||||
|
|
@ -185,7 +185,7 @@ static bool write_packet(vpn_packet_t *packet) {
|
|||
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s",
|
||||
packet->len, device_info);
|
||||
|
||||
if(sendto(device_fd, DATA(packet), packet->len, 0, ai->ai_addr, ai->ai_addrlen) < 0) {
|
||||
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));
|
||||
return false;
|
||||
|
|
|
|||
56
src/names.c
56
src/names.c
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
names.c -- generate commonly used (file)names
|
||||
Copyright (C) 1998-2005 Ivo Timmermans
|
||||
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2015 Guus Sliepen <guus@tinc-vpn.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -21,6 +21,7 @@
|
|||
#include "system.h"
|
||||
|
||||
#include "logger.h"
|
||||
#include "names.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
char *netname = NULL;
|
||||
|
|
@ -36,7 +37,7 @@ char *program_name = NULL;
|
|||
/*
|
||||
Set all files and paths according to netname
|
||||
*/
|
||||
void make_names(void) {
|
||||
void make_names(bool daemon) {
|
||||
#ifdef HAVE_MINGW
|
||||
HKEY key;
|
||||
char installdir[1024] = "";
|
||||
|
|
@ -56,14 +57,14 @@ void make_names(void) {
|
|||
if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\tinc", 0, KEY_READ, &key)) {
|
||||
if(!RegQueryValueEx(key, NULL, 0, 0, (LPBYTE)installdir, &len)) {
|
||||
confdir = xstrdup(installdir);
|
||||
if(!logfilename)
|
||||
xasprintf(&logfilename, "%s" SLASH "log" SLASH "%s.log", installdir, identname);
|
||||
if(!confbase) {
|
||||
if(netname)
|
||||
xasprintf(&confbase, "%s" SLASH "%s", installdir, netname);
|
||||
else
|
||||
xasprintf(&confbase, "%s", installdir);
|
||||
}
|
||||
if(!logfilename)
|
||||
xasprintf(&logfilename, "%s" SLASH "tinc.log", confbase);
|
||||
}
|
||||
RegCloseKey(key);
|
||||
}
|
||||
|
|
@ -85,21 +86,46 @@ void make_names(void) {
|
|||
if(!pidfilename)
|
||||
xasprintf(&pidfilename, "%s" SLASH "pid", confbase);
|
||||
#else
|
||||
if(!logfilename)
|
||||
xasprintf(&logfilename, LOCALSTATEDIR SLASH "log" SLASH "%s.log", identname);
|
||||
bool fallback = false;
|
||||
if(daemon) {
|
||||
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);
|
||||
if(access(fname, R_OK)) {
|
||||
snprintf(fname, sizeof fname, "%s" SLASH "pid", confbase);
|
||||
if(!access(fname, R_OK))
|
||||
fallback = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!pidfilename)
|
||||
xasprintf(&pidfilename, LOCALSTATEDIR SLASH "run" SLASH "%s.pid", identname);
|
||||
if(!fallback) {
|
||||
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)
|
||||
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);
|
||||
strcpy(unixsocketname, pidfilename);
|
||||
memcpy(unixsocketname, pidfilename, len);
|
||||
if(len > 4 && !strcmp(pidfilename + len - 4, ".pid"))
|
||||
strcpy(unixsocketname + len - 4, ".socket");
|
||||
strncpy(unixsocketname + len - 4, ".socket", 8);
|
||||
else
|
||||
strcpy(unixsocketname + len, ".socket");
|
||||
strncpy(unixsocketname + len, ".socket", 8);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -111,4 +137,12 @@ void free_names(void) {
|
|||
free(logfilename);
|
||||
free(confbase);
|
||||
free(confdir);
|
||||
|
||||
identname = NULL;
|
||||
netname = NULL;
|
||||
unixsocketname = NULL;
|
||||
pidfilename = NULL;
|
||||
logfilename = NULL;
|
||||
confbase = NULL;
|
||||
confdir = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
names.h -- header for names.c
|
||||
Copyright (C) 1998-2005 Ivo Timmermans
|
||||
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2015 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
|
||||
|
|
@ -31,7 +31,7 @@ extern char *logfilename;
|
|||
extern char *pidfilename;
|
||||
extern char *program_name;
|
||||
|
||||
extern void make_names(void);
|
||||
extern void make_names(bool daemon);
|
||||
extern void free_names(void);
|
||||
|
||||
#endif /* __TINC_NAMES_H__ */
|
||||
|
|
|
|||
32
src/net.c
32
src/net.c
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
net.c -- most of the network code
|
||||
Copyright (C) 1998-2005 Ivo Timmermans,
|
||||
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2015 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2006 Scott Lamb <slamb@slamb.org>
|
||||
2011 Loïc Grenié <loic.grenie@gmail.com>
|
||||
|
||||
|
|
@ -36,10 +36,6 @@
|
|||
#include "subnet.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
#ifdef HAVE_RESOLV_H
|
||||
#include <resolv.h>
|
||||
#endif
|
||||
|
||||
int contradicting_add_edge = 0;
|
||||
int contradicting_del_edge = 0;
|
||||
static int sleeptime = 10;
|
||||
|
|
@ -154,8 +150,9 @@ static void timeout_handler(void *data) {
|
|||
|
||||
if(c->last_ping_time + pingtimeout <= now.tv_sec) {
|
||||
if(c->edge) {
|
||||
try_tx(c->node, false);
|
||||
if(c->status.pinged) {
|
||||
logger(DEBUG_CONNECTIONS, LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds", c->name, c->hostname, (long)now.tv_sec - c->last_ping_time);
|
||||
logger(DEBUG_CONNECTIONS, LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds", c->name, c->hostname, (long)(now.tv_sec - c->last_ping_time));
|
||||
} else if(c->last_ping_time + pinginterval <= now.tv_sec) {
|
||||
send_ping(c);
|
||||
continue;
|
||||
|
|
@ -170,9 +167,10 @@ static void timeout_handler(void *data) {
|
|||
}
|
||||
terminate_connection(c, c->edge);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
timeout_set(data, &(struct timeval){pingtimeout, rand() % 100000});
|
||||
timeout_set(data, &(struct timeval){1, rand() % 100000});
|
||||
}
|
||||
|
||||
static void periodic_handler(void *data) {
|
||||
|
|
@ -183,7 +181,7 @@ 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);
|
||||
usleep(sleeptime * 1000000LL);
|
||||
nanosleep(&(struct timespec){sleeptime, 0}, NULL);
|
||||
sleeptime *= 2;
|
||||
if(sleeptime < 0)
|
||||
sleeptime = 3600;
|
||||
|
|
@ -212,10 +210,13 @@ static void periodic_handler(void *data) {
|
|||
and we are not already trying to make one, create an
|
||||
outgoing connection to this node.
|
||||
*/
|
||||
int r = rand() % node_tree->count;
|
||||
int r = rand() % (node_tree->count - 1);
|
||||
int i = 0;
|
||||
|
||||
for splay_each(node_t, n, node_tree) {
|
||||
if(n == myself)
|
||||
continue;
|
||||
|
||||
if(i++ != r)
|
||||
continue;
|
||||
|
||||
|
|
@ -311,15 +312,12 @@ static void sighup_handler(void *data) {
|
|||
|
||||
static void sigalrm_handler(void *data) {
|
||||
logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum));
|
||||
#ifdef HAVE_DECL_RES_INIT
|
||||
res_init();
|
||||
#endif
|
||||
retry();
|
||||
}
|
||||
#endif
|
||||
|
||||
int reload_configuration(void) {
|
||||
char *fname = NULL;
|
||||
char fname[PATH_MAX];
|
||||
|
||||
/* Reread our own configuration file */
|
||||
|
||||
|
|
@ -333,9 +331,8 @@ int reload_configuration(void) {
|
|||
|
||||
read_config_options(config_tree, NULL);
|
||||
|
||||
xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, myself->name);
|
||||
snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, myself->name);
|
||||
read_config_file(config_tree, fname);
|
||||
free(fname);
|
||||
|
||||
/* Parse some options that are allowed to be changed while tinc is running */
|
||||
|
||||
|
|
@ -412,13 +409,12 @@ int reload_configuration(void) {
|
|||
if(c->status.control)
|
||||
continue;
|
||||
|
||||
xasprintf(&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);
|
||||
}
|
||||
free(fname);
|
||||
}
|
||||
|
||||
last_config_check = now.tv_sec;
|
||||
|
|
@ -449,7 +445,7 @@ void retry(void) {
|
|||
*/
|
||||
int main_loop(void) {
|
||||
timeout_add(&pingtimer, timeout_handler, &pingtimer, &(struct timeval){pingtimeout, rand() % 100000});
|
||||
timeout_add(&periodictimer, periodic_handler, &periodictimer, &(struct timeval){pingtimeout, rand() % 100000});
|
||||
timeout_add(&periodictimer, periodic_handler, &periodictimer, &(struct timeval){0, 0});
|
||||
|
||||
#ifndef HAVE_MINGW
|
||||
signal_t sighup = {0};
|
||||
|
|
|
|||
16
src/net.h
16
src/net.h
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
net.h -- header for net.c
|
||||
Copyright (C) 1998-2005 Ivo Timmermans
|
||||
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -115,6 +115,7 @@ typedef struct listen_socket_t {
|
|||
io_t udp;
|
||||
sockaddr_t sa;
|
||||
bool bindto;
|
||||
int priority;
|
||||
} listen_socket_t;
|
||||
|
||||
#include "conf.h"
|
||||
|
|
@ -138,6 +139,14 @@ extern int addressfamily;
|
|||
extern unsigned replaywin;
|
||||
extern bool localdiscovery;
|
||||
|
||||
extern bool udp_discovery;
|
||||
extern int udp_discovery_keepalive_interval;
|
||||
extern int udp_discovery_interval;
|
||||
extern int udp_discovery_timeout;
|
||||
|
||||
extern int mtu_info_interval;
|
||||
extern int udp_info_interval;
|
||||
|
||||
extern listen_socket_t listen_socket[MAXSOCKETS];
|
||||
extern int listen_sockets;
|
||||
extern io_t unix_socket;
|
||||
|
|
@ -183,10 +192,11 @@ 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 bool send_sptps_data(void *handle, uint8_t type, const void *data, size_t len);
|
||||
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 char *get_name(void);
|
||||
extern void device_enable(void);
|
||||
|
|
@ -201,7 +211,6 @@ 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 send_mtu_probe(struct node_t *);
|
||||
extern void handle_device_data(void *, int);
|
||||
extern void handle_meta_connection_data(struct connection_t *);
|
||||
extern void regenerate_key(void);
|
||||
|
|
@ -210,6 +219,7 @@ extern void retry(void);
|
|||
extern int reload_configuration(void);
|
||||
extern void load_all_subnets(void);
|
||||
extern void load_all_nodes(void);
|
||||
extern void try_tx(struct node_t *n, bool);
|
||||
|
||||
#ifndef HAVE_MINGW
|
||||
#define closesocket(s) close(s)
|
||||
|
|
|
|||
1122
src/net_packet.c
1122
src/net_packet.c
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
net_setup.c -- Setup.
|
||||
Copyright (C) 1998-2005 Ivo Timmermans,
|
||||
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2006 Scott Lamb <slamb@slamb.org>
|
||||
2010 Brandon Black <blblack@gmail.com>
|
||||
|
||||
|
|
@ -43,6 +43,10 @@
|
|||
#include "utils.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
#ifdef HAVE_MINIUPNPC
|
||||
#include "upnp.h"
|
||||
#endif
|
||||
|
||||
char *myport;
|
||||
static char *myname;
|
||||
static io_t device_io;
|
||||
|
|
@ -137,18 +141,17 @@ bool read_ecdsa_public_key(connection_t *c) {
|
|||
}
|
||||
|
||||
c->ecdsa = ecdsa_read_pem_public_key(fp);
|
||||
fclose(fp);
|
||||
|
||||
if(!c->ecdsa)
|
||||
if(!c->ecdsa && errno != ENOENT)
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Parsing Ed25519 public key file `%s' failed.", fname);
|
||||
|
||||
fclose(fp);
|
||||
free(fname);
|
||||
return c->ecdsa;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_LEGACY
|
||||
bool read_rsa_public_key(connection_t *c) {
|
||||
if(ecdsa_active(c->ecdsa))
|
||||
return true;
|
||||
|
||||
FILE *fp;
|
||||
char *fname;
|
||||
char *n;
|
||||
|
|
@ -182,6 +185,7 @@ bool read_rsa_public_key(connection_t *c) {
|
|||
free(fname);
|
||||
return c->rsa;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool read_ecdsa_private_key(void) {
|
||||
FILE *fp;
|
||||
|
|
@ -226,14 +230,14 @@ static bool read_ecdsa_private_key(void) {
|
|||
|
||||
static bool read_invitation_key(void) {
|
||||
FILE *fp;
|
||||
char *fname;
|
||||
char fname[PATH_MAX];
|
||||
|
||||
if(invitation_key) {
|
||||
ecdsa_free(invitation_key);
|
||||
invitation_key = NULL;
|
||||
}
|
||||
|
||||
xasprintf(&fname, "%s" SLASH "invitations" SLASH "ed25519_key.priv", confbase);
|
||||
snprintf(fname, sizeof fname, "%s" SLASH "invitations" SLASH "ed25519_key.priv", confbase);
|
||||
|
||||
fp = fopen(fname, "r");
|
||||
|
||||
|
|
@ -244,10 +248,10 @@ static bool read_invitation_key(void) {
|
|||
logger(DEBUG_ALWAYS, LOG_ERR, "Reading Ed25519 private key file `%s' failed", fname);
|
||||
}
|
||||
|
||||
free(fname);
|
||||
return invitation_key;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_LEGACY
|
||||
static bool read_rsa_private_key(void) {
|
||||
FILE *fp;
|
||||
char *fname;
|
||||
|
|
@ -304,6 +308,7 @@ static bool read_rsa_private_key(void) {
|
|||
free(fname);
|
||||
return myself->connection->rsa;
|
||||
}
|
||||
#endif
|
||||
|
||||
static timeout_t keyexpire_timeout;
|
||||
|
||||
|
|
@ -315,6 +320,8 @@ static void keyexpire_handler(void *data) {
|
|||
void regenerate_key(void) {
|
||||
logger(DEBUG_STATUS, LOG_INFO, "Expiring symmetric keys");
|
||||
send_key_changed();
|
||||
for splay_each(node_t, n, node_tree)
|
||||
n->status.validkey_in = false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -323,13 +330,12 @@ void regenerate_key(void) {
|
|||
void load_all_subnets(void) {
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
char *dname;
|
||||
char dname[PATH_MAX];
|
||||
|
||||
xasprintf(&dname, "%s" SLASH "hosts", confbase);
|
||||
snprintf(dname, sizeof dname, "%s" SLASH "hosts", confbase);
|
||||
dir = opendir(dname);
|
||||
if(!dir) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", dname, strerror(errno));
|
||||
free(dname);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -362,6 +368,7 @@ void load_all_subnets(void) {
|
|||
|
||||
if((s2 = lookup_subnet(n, s))) {
|
||||
s2->expires = -1;
|
||||
free(s);
|
||||
} else {
|
||||
subnet_add(n, s);
|
||||
}
|
||||
|
|
@ -376,13 +383,12 @@ void load_all_subnets(void) {
|
|||
void load_all_nodes(void) {
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
char *dname;
|
||||
char dname[PATH_MAX];
|
||||
|
||||
xasprintf(&dname, "%s" SLASH "hosts", confbase);
|
||||
snprintf(dname, sizeof dname, "%s" SLASH "hosts", confbase);
|
||||
dir = opendir(dname);
|
||||
if(!dir) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", dname, strerror(errno));
|
||||
free(dname);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -506,6 +512,14 @@ bool setup_myself_reloadable(void) {
|
|||
if(myself->options & OPTION_TCPONLY)
|
||||
myself->options |= OPTION_INDIRECT;
|
||||
|
||||
get_config_bool(lookup_config(config_tree, "UDPDiscovery"), &udp_discovery);
|
||||
get_config_int(lookup_config(config_tree, "UDPDiscoveryKeepaliveInterval"), &udp_discovery_keepalive_interval);
|
||||
get_config_int(lookup_config(config_tree, "UDPDiscoveryInterval"), &udp_discovery_interval);
|
||||
get_config_int(lookup_config(config_tree, "UDPDiscoveryTimeout"), &udp_discovery_timeout);
|
||||
|
||||
get_config_int(lookup_config(config_tree, "MTUInfoInterval"), &mtu_info_interval);
|
||||
get_config_int(lookup_config(config_tree, "UDPInfoInterval"), &udp_info_interval);
|
||||
|
||||
get_config_bool(lookup_config(config_tree, "DirectOnly"), &directonly);
|
||||
get_config_bool(lookup_config(config_tree, "LocalDiscovery"), &localdiscovery);
|
||||
|
||||
|
|
@ -577,9 +591,14 @@ bool setup_myself_reloadable(void) {
|
|||
subnet_add(NULL, s);
|
||||
}
|
||||
|
||||
#if !defined(SOL_IP) || !defined(IP_TOS)
|
||||
#if !defined(IPPROTO_IP) || !defined(IP_TOS)
|
||||
if(priorityinheritance)
|
||||
logger(DEBUG_ALWAYS, LOG_WARNING, "%s not supported on this platform", "PriorityInheritance");
|
||||
logger(DEBUG_ALWAYS, LOG_WARNING, "%s not supported on this platform for IPv4 connections", "PriorityInheritance");
|
||||
#endif
|
||||
|
||||
#if !defined(IPPROTO_IPV6) || !defined(IPV6_TCLASS)
|
||||
if(priorityinheritance)
|
||||
logger(DEBUG_ALWAYS, LOG_WARNING, "%s not supported on this platform for IPv6 connections", "PriorityInheritance");
|
||||
#endif
|
||||
|
||||
if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire))
|
||||
|
|
@ -652,6 +671,9 @@ static bool add_listen_address(char *address, bool bindto) {
|
|||
hint.ai_protocol = IPPROTO_TCP;
|
||||
hint.ai_flags = AI_PASSIVE;
|
||||
|
||||
#if HAVE_DECL_RES_INIT
|
||||
res_init();
|
||||
#endif
|
||||
int err = getaddrinfo(address && *address ? address : NULL, port, &hint, &ai);
|
||||
free(address);
|
||||
|
||||
|
|
@ -773,6 +795,13 @@ static bool setup_myself(void) {
|
|||
|
||||
myself->options |= PROT_MINOR << 24;
|
||||
|
||||
#ifdef DISABLE_LEGACY
|
||||
experimental = read_ecdsa_private_key();
|
||||
if(!experimental) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "No private key available, cannot start tinc!");
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if(!get_config_bool(lookup_config(config_tree, "ExperimentalProtocol"), &experimental)) {
|
||||
experimental = read_ecdsa_private_key();
|
||||
if(!experimental)
|
||||
|
|
@ -790,6 +819,7 @@ static bool setup_myself(void) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Ensure myport is numeric */
|
||||
|
||||
|
|
@ -831,14 +861,14 @@ static bool setup_myself(void) {
|
|||
}
|
||||
|
||||
if(get_config_int(lookup_config(config_tree, "UDPRcvBuf"), &udp_rcvbuf)) {
|
||||
if(udp_rcvbuf <= 0) {
|
||||
if(udp_rcvbuf < 0) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "UDPRcvBuf cannot be negative!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(get_config_int(lookup_config(config_tree, "UDPSndBuf"), &udp_sndbuf)) {
|
||||
if(udp_sndbuf <= 0) {
|
||||
if(udp_sndbuf < 0) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "UDPSndBuf cannot be negative!");
|
||||
return false;
|
||||
}
|
||||
|
|
@ -854,6 +884,7 @@ static bool setup_myself(void) {
|
|||
sptps_replaywin = replaywin;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_LEGACY
|
||||
/* Generate packet encryption key */
|
||||
|
||||
if(!get_config_string(lookup_config(config_tree, "Cipher"), &cipher))
|
||||
|
|
@ -891,6 +922,7 @@ static bool setup_myself(void) {
|
|||
}
|
||||
|
||||
free(digest);
|
||||
#endif
|
||||
|
||||
/* Compression */
|
||||
|
||||
|
|
@ -939,6 +971,7 @@ static bool setup_myself(void) {
|
|||
else if(!strcasecmp(type, "vde"))
|
||||
devops = vde_devops;
|
||||
#endif
|
||||
free(type);
|
||||
}
|
||||
|
||||
get_config_bool(lookup_config(config_tree, "DeviceStandby"), &device_standby);
|
||||
|
|
@ -1035,6 +1068,25 @@ static bool setup_myself(void) {
|
|||
xasprintf(&myself->hostname, "MYSELF port %s", myport);
|
||||
myself->connection->hostname = xstrdup(myself->hostname);
|
||||
|
||||
char *upnp = NULL;
|
||||
get_config_string(lookup_config(config_tree, "UPnP"), &upnp);
|
||||
bool upnp_tcp = false;
|
||||
bool upnp_udp = false;
|
||||
if (upnp) {
|
||||
if (!strcasecmp(upnp, "yes"))
|
||||
upnp_tcp = upnp_udp = true;
|
||||
else if (!strcasecmp(upnp, "udponly"))
|
||||
upnp_udp = true;
|
||||
free(upnp);
|
||||
}
|
||||
if (upnp_tcp || upnp_udp) {
|
||||
#ifdef HAVE_MINIUPNPC
|
||||
upnp_init(upnp_tcp, upnp_udp);
|
||||
#else
|
||||
logger(DEBUG_ALWAYS, LOG_WARNING, "UPnP was requested, but tinc isn't built with miniupnpc support!");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Done. */
|
||||
|
||||
last_config_check = now.tv_sec;
|
||||
|
|
@ -1102,8 +1154,7 @@ void close_network_connections(void) {
|
|||
|
||||
if(myself && myself->connection) {
|
||||
subnet_update(myself, NULL, false);
|
||||
terminate_connection(myself->connection, false);
|
||||
free_connection(myself->connection);
|
||||
connection_del(myself->connection);
|
||||
}
|
||||
|
||||
for(int i = 0; i < listen_sockets; i++) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
net_socket.c -- Handle various kinds of sockets.
|
||||
Copyright (C) 1998-2005 Ivo Timmermans,
|
||||
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2006 Scott Lamb <slamb@slamb.org>
|
||||
2009 Florian Forster <octo@verplant.org>
|
||||
|
||||
|
|
@ -35,16 +35,11 @@
|
|||
#include "utils.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
/* Needed on Mac OS/X */
|
||||
#ifndef SOL_TCP
|
||||
#define SOL_TCP IPPROTO_TCP
|
||||
#endif
|
||||
|
||||
int addressfamily = AF_UNSPEC;
|
||||
int maxtimeout = 900;
|
||||
int seconds_till_retry = 5;
|
||||
int udp_rcvbuf = 0;
|
||||
int udp_sndbuf = 0;
|
||||
int udp_rcvbuf = 1024 * 1024;
|
||||
int udp_sndbuf = 1024 * 1024;
|
||||
int max_connection_burst = 100;
|
||||
|
||||
listen_socket_t listen_socket[MAXSOCKETS];
|
||||
|
|
@ -73,14 +68,19 @@ static void configure_tcp(connection_t *c) {
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(SOL_TCP) && defined(TCP_NODELAY)
|
||||
#if defined(IPPROTO_TCP) && defined(TCP_NODELAY)
|
||||
option = 1;
|
||||
setsockopt(c->socket, SOL_TCP, TCP_NODELAY, (void *)&option, sizeof option);
|
||||
setsockopt(c->socket, IPPROTO_TCP, TCP_NODELAY, (void *)&option, sizeof option);
|
||||
#endif
|
||||
|
||||
#if defined(SOL_IP) && defined(IP_TOS) && defined(IPTOS_LOWDELAY)
|
||||
#if defined(IPPROTO_IP) && defined(IP_TOS) && defined(IPTOS_LOWDELAY)
|
||||
option = IPTOS_LOWDELAY;
|
||||
setsockopt(c->socket, SOL_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)
|
||||
option = IPTOS_LOWDELAY;
|
||||
setsockopt(c->socket, IPPROTO_IPV6, IPV6_TCLASS, (void *)&option, sizeof option);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -163,9 +163,9 @@ int setup_listen_socket(const sockaddr_t *sa) {
|
|||
option = 1;
|
||||
setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof option);
|
||||
|
||||
#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
|
||||
#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
|
||||
if(sa->sa.sa_family == AF_INET6)
|
||||
setsockopt(nfd, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
|
||||
setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
|
||||
#endif
|
||||
|
||||
if(get_config_string
|
||||
|
|
@ -261,10 +261,10 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
|
|||
#define IP_DONTFRAGMENT IP_DONTFRAG
|
||||
#endif
|
||||
|
||||
#if defined(SOL_IP) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
|
||||
#if defined(IPPROTO_IP) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
|
||||
if(myself->options & OPTION_PMTU_DISCOVERY) {
|
||||
option = IP_PMTUDISC_DO;
|
||||
setsockopt(nfd, SOL_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option));
|
||||
setsockopt(nfd, IPPROTO_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option));
|
||||
}
|
||||
#elif defined(IPPROTO_IP) && defined(IP_DONTFRAGMENT)
|
||||
if(myself->options & OPTION_PMTU_DISCOVERY) {
|
||||
|
|
@ -273,10 +273,10 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(SOL_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
|
||||
#if defined(IPPROTO_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
|
||||
if(myself->options & OPTION_PMTU_DISCOVERY) {
|
||||
option = IPV6_PMTUDISC_DO;
|
||||
setsockopt(nfd, SOL_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option));
|
||||
setsockopt(nfd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option));
|
||||
}
|
||||
#elif defined(IPPROTO_IPV6) && defined(IPV6_DONTFRAG)
|
||||
if(myself->options & OPTION_PMTU_DISCOVERY) {
|
||||
|
|
@ -517,10 +517,10 @@ begin:
|
|||
#endif
|
||||
|
||||
if(proxytype != PROXY_EXEC) {
|
||||
#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
|
||||
#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
|
||||
int option = 1;
|
||||
if(c->address.sa.sa_family == AF_INET6)
|
||||
setsockopt(c->socket, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
|
||||
setsockopt(c->socket, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
|
||||
#endif
|
||||
|
||||
bind_to_interface(c->socket);
|
||||
|
|
@ -547,10 +547,13 @@ begin:
|
|||
|
||||
/* Now that there is a working socket, fill in the rest and register this connection. */
|
||||
|
||||
c->last_ping_time = time(NULL);
|
||||
c->status.connecting = true;
|
||||
c->name = xstrdup(outgoing->name);
|
||||
#ifndef DISABLE_LEGACY
|
||||
c->outcipher = myself->connection->outcipher;
|
||||
c->outdigest = myself->connection->outdigest;
|
||||
#endif
|
||||
c->outmaclength = myself->connection->outmaclength;
|
||||
c->outcompression = myself->connection->outcompression;
|
||||
c->last_ping_time = now.tv_sec;
|
||||
|
|
@ -602,9 +605,12 @@ void setup_outgoing_connection(outgoing_t *outgoing) {
|
|||
|
||||
if(n && n->connection) {
|
||||
logger(DEBUG_CONNECTIONS, LOG_INFO, "Already connected to %s", outgoing->name);
|
||||
|
||||
n->connection->outgoing = outgoing;
|
||||
return;
|
||||
if(!n->connection->outgoing) {
|
||||
n->connection->outgoing = outgoing;
|
||||
return;
|
||||
} else {
|
||||
goto remove;
|
||||
}
|
||||
}
|
||||
|
||||
init_configuration(&outgoing->config_tree);
|
||||
|
|
@ -615,12 +621,16 @@ void setup_outgoing_connection(outgoing_t *outgoing) {
|
|||
if(n)
|
||||
outgoing->aip = outgoing->ai = get_known_addresses(n);
|
||||
if(!outgoing->ai) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "No address known for %s", outgoing->name);
|
||||
return;
|
||||
logger(DEBUG_ALWAYS, LOG_DEBUG, "No address known for %s", outgoing->name);
|
||||
goto remove;
|
||||
}
|
||||
}
|
||||
|
||||
do_outgoing_connection(outgoing);
|
||||
return;
|
||||
|
||||
remove:
|
||||
list_delete(outgoing_list, outgoing);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -696,8 +706,10 @@ void handle_new_meta_connection(void *data, int flags) {
|
|||
|
||||
c = new_connection();
|
||||
c->name = xstrdup("<unknown>");
|
||||
#ifndef DISABLE_LEGACY
|
||||
c->outcipher = myself->connection->outcipher;
|
||||
c->outdigest = myself->connection->outdigest;
|
||||
#endif
|
||||
c->outmaclength = myself->connection->outmaclength;
|
||||
c->outcompression = myself->connection->outcompression;
|
||||
|
||||
|
|
@ -796,6 +808,11 @@ void try_outgoing_connections(void) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if(!strcmp(name, myself->name)) {
|
||||
free(name);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
|
||||
for list_each(outgoing_t, outgoing, outgoing_list) {
|
||||
|
|
|
|||
16
src/netutl.c
16
src/netutl.c
|
|
@ -39,6 +39,9 @@ struct addrinfo *str2addrinfo(const char *address, const char *service, int sock
|
|||
hint.ai_family = addressfamily;
|
||||
hint.ai_socktype = socktype;
|
||||
|
||||
#if HAVE_DECL_RES_INIT
|
||||
res_init();
|
||||
#endif
|
||||
err = getaddrinfo(address, service, &hint, &ai);
|
||||
|
||||
if(err) {
|
||||
|
|
@ -80,7 +83,13 @@ void sockaddr2str(const sockaddr_t *sa, char **addrstr, char **portstr) {
|
|||
char *scopeid;
|
||||
int err;
|
||||
|
||||
if(sa->sa.sa_family == AF_UNKNOWN) {
|
||||
if(sa->sa.sa_family == AF_UNSPEC) {
|
||||
if(addrstr)
|
||||
*addrstr = xstrdup("unspec");
|
||||
if(portstr)
|
||||
*portstr = xstrdup("unspec");
|
||||
return;
|
||||
} else if(sa->sa.sa_family == AF_UNKNOWN) {
|
||||
if(addrstr)
|
||||
*addrstr = xstrdup(sa->unknown.address);
|
||||
if(portstr)
|
||||
|
|
@ -112,7 +121,10 @@ char *sockaddr2hostname(const sockaddr_t *sa) {
|
|||
char port[NI_MAXSERV] = "unknown";
|
||||
int err;
|
||||
|
||||
if(sa->sa.sa_family == AF_UNKNOWN) {
|
||||
if(sa->sa.sa_family == AF_UNSPEC) {
|
||||
xasprintf(&str, "unspec port unspec");
|
||||
return str;
|
||||
} else if(sa->sa.sa_family == AF_UNKNOWN) {
|
||||
xasprintf(&str, "%s port %s", sa->unknown.address, sa->unknown.port);
|
||||
return str;
|
||||
}
|
||||
|
|
|
|||
67
src/node.c
67
src/node.c
|
|
@ -30,12 +30,11 @@
|
|||
#include "utils.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
static digest_t *sha256;
|
||||
#include "ed25519/sha512.h"
|
||||
|
||||
splay_tree_t *node_tree;
|
||||
static splay_tree_t *node_id_tree;
|
||||
static hash_t *node_udp_cache;
|
||||
static hash_t *node_id_cache;
|
||||
static splay_tree_t *node_udp_tree;
|
||||
|
||||
node_t *myself;
|
||||
|
||||
|
|
@ -47,22 +46,23 @@ static int node_id_compare(const node_t *a, const node_t *b) {
|
|||
return memcmp(&a->id, &b->id, sizeof(node_id_t));
|
||||
}
|
||||
|
||||
void init_nodes(void) {
|
||||
sha256 = digest_open_by_name("sha256", sizeof(node_id_t));
|
||||
static int node_udp_compare(const node_t *a, const node_t *b) {
|
||||
int result = sockaddrcmp(&a->address, &b->address);
|
||||
if (result)
|
||||
return result;
|
||||
return (a->name && b->name) ? strcmp(a->name, b->name) : 0;
|
||||
}
|
||||
|
||||
void init_nodes(void) {
|
||||
node_tree = splay_alloc_tree((splay_compare_t) node_compare, (splay_action_t) free_node);
|
||||
node_id_tree = splay_alloc_tree((splay_compare_t) node_id_compare, NULL);
|
||||
node_udp_cache = hash_alloc(0x100, sizeof(sockaddr_t));
|
||||
node_id_cache = hash_alloc(0x100, sizeof(node_id_t));
|
||||
node_udp_tree = splay_alloc_tree((splay_compare_t) node_udp_compare, NULL);
|
||||
}
|
||||
|
||||
void exit_nodes(void) {
|
||||
hash_free(node_id_cache);
|
||||
hash_free(node_udp_cache);
|
||||
splay_delete_tree(node_udp_tree);
|
||||
splay_delete_tree(node_id_tree);
|
||||
splay_delete_tree(node_tree);
|
||||
|
||||
digest_close(sha256);
|
||||
}
|
||||
|
||||
node_t *new_node(void) {
|
||||
|
|
@ -86,15 +86,17 @@ void free_node(node_t *n) {
|
|||
|
||||
sockaddrfree(&n->address);
|
||||
|
||||
#ifndef DISABLE_LEGACY
|
||||
cipher_close(n->incipher);
|
||||
digest_close(n->indigest);
|
||||
cipher_close(n->outcipher);
|
||||
digest_close(n->outdigest);
|
||||
#endif
|
||||
|
||||
ecdsa_free(n->ecdsa);
|
||||
sptps_stop(&n->sptps);
|
||||
|
||||
timeout_del(&n->mtutimeout);
|
||||
timeout_del(&n->udp_ping_timeout);
|
||||
|
||||
if(n->hostname)
|
||||
free(n->hostname);
|
||||
|
|
@ -109,15 +111,16 @@ void free_node(node_t *n) {
|
|||
}
|
||||
|
||||
void node_add(node_t *n) {
|
||||
digest_create(sha256, n->name, strlen(n->name), &n->id);
|
||||
unsigned char buf[64];
|
||||
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);
|
||||
}
|
||||
|
||||
void node_del(node_t *n) {
|
||||
hash_delete(node_udp_cache, &n->address);
|
||||
hash_delete(node_id_cache, &n->id);
|
||||
splay_delete(node_udp_tree, n);
|
||||
|
||||
for splay_each(subnet_t, s, n->subnet_tree)
|
||||
subnet_del(n, s);
|
||||
|
|
@ -138,19 +141,13 @@ node_t *lookup_node(char *name) {
|
|||
}
|
||||
|
||||
node_t *lookup_node_id(const node_id_t *id) {
|
||||
node_t *n = hash_search(node_id_cache, id);
|
||||
if(!n) {
|
||||
node_t tmp = {.id = *id};
|
||||
n = splay_search(node_id_tree, &tmp);
|
||||
if(n)
|
||||
hash_insert(node_id_cache, id, n);
|
||||
}
|
||||
|
||||
return n;
|
||||
node_t n = {.id = *id};
|
||||
return splay_search(node_id_tree, &n);
|
||||
}
|
||||
|
||||
node_t *lookup_node_udp(const sockaddr_t *sa) {
|
||||
return hash_search(node_udp_cache, sa);
|
||||
node_t tmp = {.address = *sa};
|
||||
return splay_search(node_udp_tree, &tmp);
|
||||
}
|
||||
|
||||
void update_node_udp(node_t *n, const sockaddr_t *sa) {
|
||||
|
|
@ -159,7 +156,7 @@ void update_node_udp(node_t *n, const sockaddr_t *sa) {
|
|||
return;
|
||||
}
|
||||
|
||||
hash_delete(node_udp_cache, &n->address);
|
||||
splay_delete(node_udp_tree, n);
|
||||
|
||||
if(sa) {
|
||||
n->address = *sa;
|
||||
|
|
@ -170,7 +167,7 @@ void update_node_udp(node_t *n, const sockaddr_t *sa) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
hash_insert(node_udp_cache, sa, n);
|
||||
splay_insert(node_udp_tree, n);
|
||||
free(n->hostname);
|
||||
n->hostname = sockaddr2hostname(&n->address);
|
||||
logger(DEBUG_PROTOCOL, LOG_DEBUG, "UDP address of %s set to %s", n->name, n->hostname);
|
||||
|
|
@ -179,6 +176,7 @@ void update_node_udp(node_t *n, const sockaddr_t *sa) {
|
|||
/* invalidate UDP information - note that this is a security feature as well to make sure
|
||||
we can't be tricked into flooding any random address with UDP packets */
|
||||
n->status.udp_confirmed = false;
|
||||
n->maxrecentlen = 0;
|
||||
n->mtuprobes = 0;
|
||||
n->minmtu = 0;
|
||||
n->maxmtu = MTU;
|
||||
|
|
@ -188,13 +186,18 @@ 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)
|
||||
sprintf(id + 2 * c, "%02hhx", n->id.x[c]);
|
||||
snprintf(id + 2 * c, 3, "%02hhx", n->id.x[c]);
|
||||
id[sizeof id - 1] = 0;
|
||||
send_request(c, "%d %d %s %s %s %d %d %d %d %x %x %s %s %d %hd %hd %hd %ld", CONTROL, REQ_DUMP_NODES,
|
||||
n->name, id, n->hostname ?: "unknown port unknown", cipher_get_nid(n->outcipher),
|
||||
digest_get_nid(n->outdigest), (int)digest_length(n->outdigest), 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->name, id, n->hostname ?: "unknown port unknown",
|
||||
#ifdef DISABLE_LEGACY
|
||||
0, 0, 0,
|
||||
#else
|
||||
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);
|
||||
}
|
||||
|
||||
return send_request(c, "%d %d", CONTROL, REQ_DUMP_NODES);
|
||||
|
|
|
|||
25
src/node.h
25
src/node.h
|
|
@ -38,17 +38,19 @@ typedef struct node_status_t {
|
|||
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 unused:23;
|
||||
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 unused:21;
|
||||
} node_status_t;
|
||||
|
||||
typedef struct node_t {
|
||||
char *name; /* name of this node */
|
||||
char *hostname; /* the hostname of its real ip */
|
||||
node_id_t id; /* unique node ID (name hash) */
|
||||
uint32_t options; /* options turned on for this node */
|
||||
|
||||
int sock; /* Socket to use for outgoing UDP packets */
|
||||
sockaddr_t address; /* his real (internet) ip to send UDP packets to */
|
||||
char *hostname; /* the hostname of its real ip */
|
||||
|
||||
node_status_t status;
|
||||
time_t last_state_change;
|
||||
|
|
@ -57,11 +59,13 @@ typedef struct node_t {
|
|||
ecdsa_t *ecdsa; /* His public ECDSA key */
|
||||
sptps_t sptps;
|
||||
|
||||
#ifndef DISABLE_LEGACY
|
||||
cipher_t *incipher; /* Cipher for UDP packets */
|
||||
digest_t *indigest; /* Digest for UDP packets */
|
||||
|
||||
cipher_t *outcipher; /* Cipher for UDP packets */
|
||||
digest_t *outdigest; /* Digest for UDP packets */
|
||||
#endif
|
||||
|
||||
int incompression; /* Compressionlevel, 0 = no compression */
|
||||
int outcompression; /* Compressionlevel, 0 = no compression */
|
||||
|
|
@ -85,16 +89,21 @@ typedef struct node_t {
|
|||
uint32_t farfuture; /* Packets in a row that have arrived from the far future */
|
||||
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 */
|
||||
timeout_t udp_ping_timeout; /* Ping timeout event */
|
||||
|
||||
struct timeval mtu_ping_sent; /* Last time a MTU probe was sent */
|
||||
|
||||
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 mtu; /* Maximum size of packets to send to this node */
|
||||
length_t minmtu; /* Probed minimum MTU */
|
||||
length_t maxmtu; /* Probed maximum MTU */
|
||||
int mtuprobes; /* Number of probes */
|
||||
timeout_t mtutimeout; /* Probe event */
|
||||
struct timeval probe_time; /* Time the last probe was sent or received */
|
||||
int probe_counter; /* Number of probes received since last burst was sent */
|
||||
float rtt; /* Last measured round trip time */
|
||||
float bandwidth; /* Last measured bandwidth */
|
||||
float packetloss; /* Last measured packet loss rate */
|
||||
|
||||
uint64_t in_packets;
|
||||
uint64_t in_bytes;
|
||||
|
|
|
|||
87
src/nolegacy/crypto.c
Normal file
87
src/nolegacy/crypto.c
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
crypto.c -- Cryptographic miscellaneous functions and initialisation
|
||||
Copyright (C) 2007-2014 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 "../crypto.h"
|
||||
|
||||
#ifndef HAVE_MINGW
|
||||
|
||||
static int random_fd = -1;
|
||||
|
||||
static void random_init(void) {
|
||||
random_fd = open("/dev/urandom", O_RDONLY);
|
||||
if(random_fd < 0)
|
||||
random_fd = open("/dev/random", O_RDONLY);
|
||||
if(random_fd < 0) {
|
||||
fprintf(stderr, "Could not open source of random numbers: %s\n", strerror(errno));
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static void random_exit(void) {
|
||||
close(random_fd);
|
||||
}
|
||||
|
||||
void randomize(void *out, size_t outlen) {
|
||||
while(outlen) {
|
||||
size_t len = read(random_fd, out, outlen);
|
||||
if(len <= 0) {
|
||||
if(errno == EAGAIN || errno == EINTR)
|
||||
continue;
|
||||
fprintf(stderr, "Could not read random numbers: %s\n", strerror(errno));
|
||||
abort();
|
||||
}
|
||||
out += len;
|
||||
outlen -= len;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <wincrypt.h>
|
||||
HCRYPTPROV prov;
|
||||
|
||||
void random_init(void) {
|
||||
if(!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
|
||||
fprintf(stderr, "CryptAcquireContext() failed!\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void random_exit(void) {
|
||||
CryptReleaseContext(prov, 0);
|
||||
}
|
||||
|
||||
void randomize(void *out, size_t outlen) {
|
||||
if(!CryptGenRandom(prov, outlen, out)) {
|
||||
fprintf(stderr, "CryptGenRandom() failed\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void crypto_init(void) {
|
||||
random_init();
|
||||
}
|
||||
|
||||
void crypto_exit(void) {
|
||||
random_exit();
|
||||
}
|
||||
106
src/nolegacy/prf.c
Normal file
106
src/nolegacy/prf.c
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
prf.c -- Pseudo-Random Function for key material generation
|
||||
Copyright (C) 2011-2013 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 "../prf.h"
|
||||
#include "../ed25519/sha512.h"
|
||||
|
||||
static void memxor(char *buf, char c, size_t len) {
|
||||
for(size_t i = 0; i < len; i++)
|
||||
buf[i] ^= c;
|
||||
}
|
||||
|
||||
static const size_t mdlen = 64;
|
||||
static const size_t blklen = 128;
|
||||
|
||||
static bool hmac_sha512(const char *key, size_t keylen, const char *msg, size_t msglen, char *out) {
|
||||
char tmp[blklen + mdlen];
|
||||
sha512_context md;
|
||||
|
||||
if(keylen <= blklen) {
|
||||
memcpy(tmp, key, keylen);
|
||||
memset(tmp + keylen, 0, blklen - keylen);
|
||||
} else {
|
||||
if(sha512(key, keylen, tmp) != 0)
|
||||
return false;
|
||||
memset(tmp + mdlen, 0, blklen - mdlen);
|
||||
}
|
||||
|
||||
if(sha512_init(&md) != 0)
|
||||
return false;
|
||||
|
||||
// ipad
|
||||
memxor(tmp, 0x36, blklen);
|
||||
if(sha512_update(&md, tmp, blklen) != 0)
|
||||
return false;
|
||||
|
||||
// message
|
||||
if(sha512_update(&md, msg, msglen) != 0)
|
||||
return false;
|
||||
|
||||
if(sha512_final(&md, tmp + blklen) != 0)
|
||||
return false;
|
||||
|
||||
// opad
|
||||
memxor(tmp, 0x36 ^ 0x5c, blklen);
|
||||
if(sha512(tmp, sizeof tmp, out) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Generate key material from a master secret and a seed, based on RFC 4346 section 5.
|
||||
We use SHA512 instead of MD5 and SHA1.
|
||||
*/
|
||||
|
||||
bool prf(const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, size_t outlen) {
|
||||
/* Data is what the "inner" HMAC function processes.
|
||||
It consists of the previous HMAC result plus the seed.
|
||||
*/
|
||||
|
||||
char data[mdlen + seedlen];
|
||||
memset(data, 0, mdlen);
|
||||
memcpy(data + mdlen, seed, seedlen);
|
||||
|
||||
char hash[mdlen];
|
||||
|
||||
while(outlen > 0) {
|
||||
/* Inner HMAC */
|
||||
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))
|
||||
return false;
|
||||
out += mdlen;
|
||||
outlen -= mdlen;
|
||||
} else {
|
||||
if(!hmac_sha512(secret, secretlen, data, sizeof data, hash))
|
||||
return false;
|
||||
memcpy(out, hash, outlen);
|
||||
out += outlen;
|
||||
outlen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -79,6 +79,13 @@ size_t cipher_keylength(const cipher_t *cipher) {
|
|||
return cipher->cipher->key_len + cipher->cipher->iv_len;
|
||||
}
|
||||
|
||||
size_t cipher_blocksize(const cipher_t *cipher) {
|
||||
if(!cipher || !cipher->cipher)
|
||||
return 1;
|
||||
|
||||
return cipher->cipher->block_size;
|
||||
}
|
||||
|
||||
bool cipher_set_key(cipher_t *cipher, void *key, bool encrypt) {
|
||||
bool result;
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ bool sigalrm = false;
|
|||
|
||||
extern char **g_argv;
|
||||
extern bool use_logfile;
|
||||
extern bool use_syslog;
|
||||
|
||||
/* Some functions the less gifted operating systems might lack... */
|
||||
|
||||
|
|
@ -61,12 +62,9 @@ static bool install_service(void) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if(!strchr(program_name, '\\')) {
|
||||
GetCurrentDirectory(sizeof command - 1, command + 1);
|
||||
strncat(command, "\\", sizeof command - strlen(command));
|
||||
}
|
||||
|
||||
strncat(command, program_name, sizeof command - strlen(command));
|
||||
HMODULE module = GetModuleHandle(NULL);
|
||||
GetModuleFileName(module, command + 1, sizeof command - 1);
|
||||
command[sizeof command - 1] = 0;
|
||||
|
||||
strncat(command, "\"", sizeof command - strlen(command));
|
||||
|
||||
|
|
@ -189,6 +187,8 @@ bool init_service(void) {
|
|||
Detach from current terminal
|
||||
*/
|
||||
bool detach(void) {
|
||||
logmode_t logmode;
|
||||
|
||||
#ifndef HAVE_MINGW
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
signal(SIGUSR1, SIG_IGN);
|
||||
|
|
@ -200,7 +200,7 @@ bool detach(void) {
|
|||
|
||||
if(do_detach) {
|
||||
#ifndef HAVE_MINGW
|
||||
if(daemon(0, 0)) {
|
||||
if(daemon(1, 0)) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Couldn't detach from terminal: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
|
@ -210,12 +210,17 @@ bool detach(void) {
|
|||
#endif
|
||||
}
|
||||
|
||||
openlogger(identname, use_logfile?LOGMODE_FILE:(do_detach?LOGMODE_SYSLOG:LOGMODE_STDERR));
|
||||
if(use_logfile)
|
||||
logmode = LOGMODE_FILE;
|
||||
else if(use_syslog || do_detach)
|
||||
logmode = LOGMODE_SYSLOG;
|
||||
else
|
||||
logmode = LOGMODE_STDERR;
|
||||
|
||||
openlogger(identname, logmode);
|
||||
|
||||
logger(DEBUG_ALWAYS, LOG_NOTICE, "tincd %s (%s %s) starting, debug level %d",
|
||||
VERSION, BUILD_DATE, BUILD_TIME, debug_level);
|
||||
BUILD_VERSION, BUILD_DATE, BUILD_TIME, debug_level);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,9 @@ static bool (*request_handlers[])(connection_t *, const char *) = {
|
|||
add_subnet_h, del_subnet_h,
|
||||
add_edge_h, del_edge_h,
|
||||
key_changed_h, req_key_h, ans_key_h, tcppacket_h, control_h,
|
||||
NULL, NULL, /* Not "real" requests (yet) */
|
||||
sptps_tcppacket_h,
|
||||
udp_info_h, mtu_info_h,
|
||||
};
|
||||
|
||||
/* Request names */
|
||||
|
|
@ -51,6 +54,7 @@ static char (*request_name[]) = {
|
|||
"PING", "PONG",
|
||||
"ADD_SUBNET", "DEL_SUBNET",
|
||||
"ADD_EDGE", "DEL_EDGE", "KEY_CHANGED", "REQ_KEY", "ANS_KEY", "PACKET", "CONTROL",
|
||||
"REQ_PUBKEY", "ANS_PUBKEY", "SPTPS_PACKET", "UDP_INFO", "MTU_INFO",
|
||||
};
|
||||
|
||||
static splay_tree_t *past_request_tree;
|
||||
|
|
@ -132,7 +136,8 @@ bool receive_request(connection_t *c, const char *request) {
|
|||
if(!request_handlers[reqno](c, request)) {
|
||||
/* Something went wrong. Probably scriptkiddies. Terminate. */
|
||||
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Error while processing %s from %s (%s)", request_name[reqno], c->name, c->hostname);
|
||||
if(reqno != TERMREQ)
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Error while processing %s from %s (%s)", request_name[reqno], c->name, c->hostname);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
/* Protocol version. Different major versions are incompatible. */
|
||||
|
||||
#define PROT_MAJOR 17
|
||||
#define PROT_MINOR 4 /* Should not exceed 255! */
|
||||
#define PROT_MINOR 7 /* Should not exceed 255! */
|
||||
|
||||
/* Silly Windows */
|
||||
|
||||
|
|
@ -48,7 +48,8 @@ typedef enum request_t {
|
|||
/* Tinc 1.1 requests */
|
||||
CONTROL,
|
||||
REQ_PUBKEY, ANS_PUBKEY,
|
||||
REQ_SPTPS,
|
||||
SPTPS_PACKET,
|
||||
UDP_INFO, MTU_INFO,
|
||||
LAST /* Guardian for the highest request number */
|
||||
} request_t;
|
||||
|
||||
|
|
@ -107,6 +108,9 @@ extern void send_key_changed(void);
|
|||
extern bool send_req_key(struct node_t *);
|
||||
extern bool send_ans_key(struct node_t *);
|
||||
extern bool send_tcppacket(struct connection_t *, const struct vpn_packet_t *);
|
||||
extern bool send_sptps_tcppacket(struct connection_t *, const char*, int);
|
||||
extern bool send_udp_info(struct node_t *, struct node_t *);
|
||||
extern bool send_mtu_info(struct node_t *, struct node_t *, int);
|
||||
|
||||
/* Request handlers */
|
||||
|
||||
|
|
@ -128,6 +132,9 @@ extern bool key_changed_h(struct connection_t *, const char *);
|
|||
extern bool req_key_h(struct connection_t *, const char *);
|
||||
extern bool ans_key_h(struct connection_t *, const char *);
|
||||
extern bool tcppacket_h(struct connection_t *, const char *);
|
||||
extern bool sptps_tcppacket_h(struct connection_t *, const char *);
|
||||
extern bool control_h(struct connection_t *, const char *);
|
||||
extern bool udp_info_h(struct connection_t *, const char *);
|
||||
extern bool mtu_info_h(struct connection_t *, const char *);
|
||||
|
||||
#endif /* __TINC_PROTOCOL_H__ */
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@
|
|||
#include "utils.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
#include "ed25519/sha512.h"
|
||||
|
||||
ecdsa_t *invitation_key = NULL;
|
||||
|
||||
static bool send_proxyrequest(connection_t *c) {
|
||||
|
|
@ -115,7 +117,7 @@ static bool send_proxyrequest(connection_t *c) {
|
|||
i += 2;
|
||||
c->tcplen += 22;
|
||||
} else {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Address family %hx not supported for SOCKS 5 proxies!", c->address.sa.sa_family);
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Address family %x not supported for SOCKS 5 proxies!", c->address.sa.sa_family);
|
||||
return false;
|
||||
}
|
||||
if(i > len)
|
||||
|
|
@ -211,17 +213,13 @@ static bool receive_invitation_sptps(void *handle, uint8_t type, const void *dat
|
|||
return false;
|
||||
|
||||
// Recover the filename from the cookie and the key
|
||||
digest_t *digest = digest_open_by_name("sha256", 18);
|
||||
if(!digest)
|
||||
abort();
|
||||
char *fingerprint = ecdsa_get_base64_public_key(invitation_key);
|
||||
char hashbuf[18 + strlen(fingerprint)];
|
||||
char cookie[25];
|
||||
char cookie[64];
|
||||
memcpy(hashbuf, data, 18);
|
||||
memcpy(hashbuf + 18, fingerprint, sizeof hashbuf - 18);
|
||||
digest_create(digest, hashbuf, sizeof hashbuf, cookie);
|
||||
sha512(hashbuf, sizeof hashbuf, cookie);
|
||||
b64encode_urlsafe(cookie, cookie, 18);
|
||||
digest_close(digest);
|
||||
free(fingerprint);
|
||||
|
||||
char filename[PATH_MAX], usedname[PATH_MAX];
|
||||
|
|
@ -388,7 +386,7 @@ bool id_h(connection_t *c, const char *request) {
|
|||
|
||||
/* Forbid version rollback for nodes whose Ed25519 key we know */
|
||||
|
||||
if(ecdsa_active(c->ecdsa) && c->protocol_minor < 2) {
|
||||
if(ecdsa_active(c->ecdsa) && c->protocol_minor < 1) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Peer %s (%s) tries to roll back protocol version to %d.%d",
|
||||
c->name, c->hostname, c->protocol_major, c->protocol_minor);
|
||||
return false;
|
||||
|
|
@ -412,6 +410,9 @@ bool id_h(connection_t *c, const char *request) {
|
|||
}
|
||||
|
||||
bool send_metakey(connection_t *c) {
|
||||
#ifdef DISABLE_LEGACY
|
||||
return false;
|
||||
#else
|
||||
if(!myself->connection->rsa) {
|
||||
logger(DEBUG_CONNECTIONS, LOG_ERR, "Peer %s (%s) uses legacy protocol which we don't support", c->name, c->hostname);
|
||||
return false;
|
||||
|
|
@ -480,9 +481,13 @@ bool send_metakey(connection_t *c) {
|
|||
|
||||
c->status.encryptout = true;
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool metakey_h(connection_t *c, const char *request) {
|
||||
#ifdef DISABLE_LEGACY
|
||||
return false;
|
||||
#else
|
||||
if(!myself->connection->rsa)
|
||||
return false;
|
||||
|
||||
|
|
@ -545,9 +550,13 @@ bool metakey_h(connection_t *c, const char *request) {
|
|||
c->allow_request = CHALLENGE;
|
||||
|
||||
return send_challenge(c);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool send_challenge(connection_t *c) {
|
||||
#ifdef DISABLE_LEGACY
|
||||
return false;
|
||||
#else
|
||||
const size_t len = rsa_size(c->rsa);
|
||||
char buffer[len * 2 + 1];
|
||||
|
||||
|
|
@ -565,9 +574,13 @@ bool send_challenge(connection_t *c) {
|
|||
/* Send the challenge */
|
||||
|
||||
return send_request(c, "%d %s", CHALLENGE, buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool challenge_h(connection_t *c, const char *request) {
|
||||
#ifdef DISABLE_LEGACY
|
||||
return false;
|
||||
#else
|
||||
if(!myself->connection->rsa)
|
||||
return false;
|
||||
|
||||
|
|
@ -606,9 +619,13 @@ bool challenge_h(connection_t *c, const char *request) {
|
|||
c->allow_request = CHAL_REPLY;
|
||||
|
||||
return send_request(c, "%d %s", CHAL_REPLY, buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool chal_reply_h(connection_t *c, const char *request) {
|
||||
#ifdef DISABLE_LEGACY
|
||||
return false;
|
||||
#else
|
||||
char hishash[MAX_STRING_SIZE];
|
||||
|
||||
if(sscanf(request, "%*d " MAX_STRING, hishash) != 1) {
|
||||
|
|
@ -645,9 +662,13 @@ bool chal_reply_h(connection_t *c, const char *request) {
|
|||
c->allow_request = ACK;
|
||||
|
||||
return send_ack(c);
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool send_upgrade(connection_t *c) {
|
||||
#ifdef DISABLE_LEGACY
|
||||
return false;
|
||||
#else
|
||||
/* Special case when protocol_minor is 1: the other end is Ed25519 capable,
|
||||
* but doesn't know our key yet. So send it now. */
|
||||
|
||||
|
|
@ -659,6 +680,7 @@ static bool send_upgrade(connection_t *c) {
|
|||
bool result = send_request(c, "%d %s", ACK, pubkey);
|
||||
free(pubkey);
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool send_ack(connection_t *c) {
|
||||
|
|
@ -758,6 +780,8 @@ static bool upgrade_h(connection_t *c, const char *request) {
|
|||
logger(DEBUG_ALWAYS, LOG_INFO, "Got Ed25519 public key from %s (%s), upgrading!", c->name, c->hostname);
|
||||
append_config_file(c->name, "Ed25519PublicKey", pubkey);
|
||||
c->allow_request = TERMREQ;
|
||||
if(c->outgoing)
|
||||
c->outgoing->timeout = 0;
|
||||
return send_termreq(c);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,19 +37,26 @@
|
|||
bool send_add_edge(connection_t *c, const edge_t *e) {
|
||||
bool x;
|
||||
char *address, *port;
|
||||
char *local_address, *local_port;
|
||||
|
||||
sockaddr2str(&e->address, &address, &port);
|
||||
sockaddr2str(&e->local_address, &local_address, &local_port);
|
||||
|
||||
x = send_request(c, "%d %x %s %s %s %s %x %d %s %s", ADD_EDGE, rand(),
|
||||
e->from->name, e->to->name, address, port,
|
||||
e->options, e->weight, local_address, local_port);
|
||||
if(e->local_address.sa.sa_family) {
|
||||
char *local_address, *local_port;
|
||||
sockaddr2str(&e->local_address, &local_address, &local_port);
|
||||
|
||||
x = send_request(c, "%d %x %s %s %s %s %x %d %s %s", ADD_EDGE, rand(),
|
||||
e->from->name, e->to->name, address, port,
|
||||
e->options, e->weight, local_address, local_port);
|
||||
free(local_address);
|
||||
free(local_port);
|
||||
} else {
|
||||
x = send_request(c, "%d %x %s %s %s %s %x %d", ADD_EDGE, rand(),
|
||||
e->from->name, e->to->name, address, port,
|
||||
e->options, e->weight);
|
||||
}
|
||||
|
||||
free(address);
|
||||
free(port);
|
||||
free(local_address);
|
||||
free(local_port);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
|
@ -61,9 +68,9 @@ bool add_edge_h(connection_t *c, const char *request) {
|
|||
char to_name[MAX_STRING_SIZE];
|
||||
char to_address[MAX_STRING_SIZE];
|
||||
char to_port[MAX_STRING_SIZE];
|
||||
char address_local[MAX_STRING_SIZE] = "unknown";
|
||||
char port_local[MAX_STRING_SIZE] = "unknown";
|
||||
sockaddr_t address, local_address;
|
||||
char address_local[MAX_STRING_SIZE];
|
||||
char port_local[MAX_STRING_SIZE];
|
||||
sockaddr_t address, local_address = {{0}};
|
||||
uint32_t options;
|
||||
int weight;
|
||||
|
||||
|
|
@ -117,27 +124,71 @@ bool add_edge_h(connection_t *c, const char *request) {
|
|||
/* Convert addresses */
|
||||
|
||||
address = str2sockaddr(to_address, to_port);
|
||||
local_address = str2sockaddr(address_local, port_local);
|
||||
if(parameter_count >= 8)
|
||||
local_address = str2sockaddr(address_local, port_local);
|
||||
|
||||
/* Check if edge already exists */
|
||||
|
||||
e = lookup_edge(from, to);
|
||||
|
||||
if(e) {
|
||||
if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address) || sockaddrcmp(&e->local_address, &local_address)) {
|
||||
if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address)) {
|
||||
if(from == myself) {
|
||||
logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself which does not match existing entry",
|
||||
"ADD_EDGE", c->name, c->hostname);
|
||||
send_add_edge(c, e);
|
||||
sockaddrfree(&local_address);
|
||||
return true;
|
||||
} else {
|
||||
logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) which does not match existing entry",
|
||||
"ADD_EDGE", c->name, c->hostname);
|
||||
edge_del(e);
|
||||
graph();
|
||||
e->options = options;
|
||||
if(sockaddrcmp(&e->address, &address)) {
|
||||
sockaddrfree(&e->address);
|
||||
e->address = address;
|
||||
}
|
||||
if(e->weight != weight) {
|
||||
splay_node_t *node = splay_unlink(edge_weight_tree, e);
|
||||
e->weight = weight;
|
||||
splay_insert_node(edge_weight_tree, node);
|
||||
}
|
||||
|
||||
goto done;
|
||||
}
|
||||
} else
|
||||
} else if(sockaddrcmp(&e->local_address, &local_address)) {
|
||||
if(from == myself) {
|
||||
if(e->local_address.sa.sa_family && local_address.sa.sa_family) {
|
||||
// Someone has the wrong local address for ourself. Correct then.
|
||||
logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself which does not match existing entry",
|
||||
"ADD_EDGE", c->name, c->hostname);
|
||||
send_add_edge(c, e);
|
||||
sockaddrfree(&local_address);
|
||||
return true;
|
||||
}
|
||||
// Otherwise, just ignore it.
|
||||
sockaddrfree(&local_address);
|
||||
return true;
|
||||
} else if(local_address.sa.sa_family && local_address.sa.sa_family != AF_UNKNOWN) {
|
||||
// We learned a new local address for this edge.
|
||||
// local_address.sa.sa_family will be 0 if we got it from older tinc versions
|
||||
// local_address.sa.sa_family will be 255 (AF_UNKNOWN) if we got it from newer versions
|
||||
// but for edge which does not have local_address
|
||||
sockaddrfree(&e->local_address);
|
||||
e->local_address = local_address;
|
||||
|
||||
// Tell others about it.
|
||||
if(!tunnelserver)
|
||||
forward_request(c, request);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
sockaddrfree(&local_address);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
sockaddrfree(&local_address);
|
||||
return true;
|
||||
}
|
||||
} else if(from == myself) {
|
||||
logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself which does not exist",
|
||||
"ADD_EDGE", c->name, c->hostname);
|
||||
|
|
@ -147,6 +198,7 @@ bool add_edge_h(connection_t *c, const char *request) {
|
|||
e->to = to;
|
||||
send_del_edge(c, e);
|
||||
free_edge(e);
|
||||
sockaddrfree(&local_address);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -159,6 +211,7 @@ bool add_edge_h(connection_t *c, const char *request) {
|
|||
e->weight = weight;
|
||||
edge_add(e);
|
||||
|
||||
done:
|
||||
/* Tell the rest about the new edge */
|
||||
|
||||
if(!tunnelserver)
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
static bool mykeyused = false;
|
||||
|
||||
void send_key_changed(void) {
|
||||
#ifndef DISABLE_LEGACY
|
||||
send_request(everyone, "%d %x %s", KEY_CHANGED, rand(), myself->name);
|
||||
|
||||
/* Immediately send new keys to directly connected nodes to keep UDP mappings alive */
|
||||
|
|
@ -43,6 +44,7 @@ void send_key_changed(void) {
|
|||
for list_each(connection_t, c, connection_list)
|
||||
if(c->edge && c->node && c->node->status.reachable && !c->node->status.sptps)
|
||||
send_ans_key(c->node);
|
||||
#endif
|
||||
|
||||
/* Force key exchange for connections using SPTPS */
|
||||
|
||||
|
|
@ -87,9 +89,13 @@ bool key_changed_h(connection_t *c, const char *request) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool send_sptps_data_myself(void *handle, uint8_t type, const void *data, size_t len) {
|
||||
return send_sptps_data(handle, myself, type, data, len);
|
||||
}
|
||||
|
||||
static bool send_initial_sptps_data(void *handle, uint8_t type, const void *data, size_t len) {
|
||||
node_t *to = handle;
|
||||
to->sptps.send_data = send_sptps_data;
|
||||
to->sptps.send_data = send_sptps_data_myself;
|
||||
char buf[len * 4 / 3 + 5];
|
||||
b64encode(data, buf, len);
|
||||
return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, to->name, REQ_KEY, buf);
|
||||
|
|
@ -103,9 +109,6 @@ bool send_req_key(node_t *to) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if(to->sptps.label)
|
||||
logger(DEBUG_ALWAYS, LOG_DEBUG, "send_req_key(%s) called while sptps->label != NULL!", to->name);
|
||||
|
||||
char label[25 + strlen(myself->name) + strlen(to->name)];
|
||||
snprintf(label, sizeof label, "tinc UDP key expansion %s %s", myself->name, to->name);
|
||||
sptps_stop(&to->sptps);
|
||||
|
|
@ -121,7 +124,52 @@ bool send_req_key(node_t *to) {
|
|||
|
||||
/* REQ_KEY is overloaded to allow arbitrary requests to be routed between two nodes. */
|
||||
|
||||
static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, int reqno) {
|
||||
static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, node_t *to, int reqno) {
|
||||
/* If this is a SPTPS packet, see if sending UDP info helps.
|
||||
Note that we only do this if we're the destination or the static relay;
|
||||
otherwise every hop would initiate its own UDP info message, resulting in elevated chatter. */
|
||||
if((reqno == REQ_KEY || reqno == SPTPS_PACKET) && to->via == myself)
|
||||
send_udp_info(myself, from);
|
||||
|
||||
if(reqno == SPTPS_PACKET) {
|
||||
/* This is a SPTPS data packet. */
|
||||
|
||||
char buf[MAX_STRING_SIZE];
|
||||
int len;
|
||||
if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode(buf, buf, strlen(buf)))) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s) to %s (%s): %s", "SPTPS_PACKET", from->name, from->hostname, to->name, to->hostname, "invalid SPTPS data");
|
||||
return true;
|
||||
}
|
||||
|
||||
if(to != myself) {
|
||||
/* We don't just forward the request, because we want to use UDP if it's available. */
|
||||
send_sptps_data(to, from, 0, buf, len);
|
||||
try_tx(to, true);
|
||||
} else {
|
||||
/* The packet is for us */
|
||||
if(!sptps_receive_data(&from->sptps, buf, len)) {
|
||||
/* Uh-oh. It might be that the tunnel is stuck in some corrupted state,
|
||||
so let's restart SPTPS in case that helps. But don't do that too often
|
||||
to prevent storms. */
|
||||
if(from->last_req_key < now.tv_sec - 10) {
|
||||
logger(DEBUG_PROTOCOL, LOG_ERR, "Failed to decode TCP packet from %s (%s), restarting SPTPS", from->name, from->hostname);
|
||||
send_req_key(from);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
send_mtu_info(myself, from, MTU);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Requests that are not SPTPS data packets are forwarded as-is. */
|
||||
|
||||
if (to != myself)
|
||||
return send_request(to->nexthop->connection, "%s", request);
|
||||
|
||||
/* The request is for us */
|
||||
|
||||
switch(reqno) {
|
||||
case REQ_PUBKEY: {
|
||||
if(!node_read_ecdsa_public_key(from)) {
|
||||
|
|
@ -176,24 +224,9 @@ static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, in
|
|||
from->status.validkey = false;
|
||||
from->status.waitingforkey = true;
|
||||
from->last_req_key = now.tv_sec;
|
||||
sptps_start(&from->sptps, from, false, true, myself->connection->ecdsa, from->ecdsa, label, sizeof label, send_sptps_data, receive_sptps_record);
|
||||
sptps_receive_data(&from->sptps, buf, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
case REQ_SPTPS: {
|
||||
if(!from->status.validkey) {
|
||||
logger(DEBUG_PROTOCOL, LOG_ERR, "Got REQ_SPTPS from %s (%s) but we don't have a valid key yet", from->name, from->hostname);
|
||||
return true;
|
||||
}
|
||||
|
||||
char buf[MAX_STRING_SIZE];
|
||||
int len;
|
||||
if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode(buf, buf, strlen(buf)))) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_SPTPS", from->name, from->hostname, "invalid SPTPS data");
|
||||
return true;
|
||||
}
|
||||
sptps_start(&from->sptps, from, false, true, myself->connection->ecdsa, from->ecdsa, label, sizeof label, send_sptps_data_myself, receive_sptps_record);
|
||||
sptps_receive_data(&from->sptps, buf, len);
|
||||
send_mtu_info(myself, from, MTU);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -241,7 +274,7 @@ bool req_key_h(connection_t *c, const char *request) {
|
|||
if(to == myself) { /* Yes */
|
||||
/* Is this an extended REQ_KEY message? */
|
||||
if(experimental && reqno)
|
||||
return req_key_ext_h(c, request, from, reqno);
|
||||
return req_key_ext_h(c, request, from, to, reqno);
|
||||
|
||||
/* No, just send our key back */
|
||||
send_ans_key(from);
|
||||
|
|
@ -255,7 +288,10 @@ bool req_key_h(connection_t *c, const char *request) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/* TODO: forwarding SPTPS packets in this way is inefficient because we send them over TCP without checking for UDP connectivity */
|
||||
/* Is this an extended REQ_KEY message? */
|
||||
if(experimental && reqno)
|
||||
return req_key_ext_h(c, request, from, to, reqno);
|
||||
|
||||
send_request(to->nexthop->connection, "%s", request);
|
||||
}
|
||||
|
||||
|
|
@ -266,6 +302,9 @@ bool send_ans_key(node_t *to) {
|
|||
if(to->status.sptps)
|
||||
abort();
|
||||
|
||||
#ifdef DISABLE_LEGACY
|
||||
return false;
|
||||
#else
|
||||
size_t keylen = myself->incipher ? cipher_keylength(myself->incipher) : 1;
|
||||
char key[keylen * 2 + 1];
|
||||
|
||||
|
|
@ -300,12 +339,15 @@ bool send_ans_key(node_t *to) {
|
|||
to->received = 0;
|
||||
if(replaywin) memset(to->late, 0, replaywin);
|
||||
|
||||
to->status.validkey_in = true;
|
||||
|
||||
return send_request(to->nexthop->connection, "%d %s %s %s %d %d %d %d", ANS_KEY,
|
||||
myself->name, to->name, key,
|
||||
cipher_get_nid(to->incipher),
|
||||
digest_get_nid(to->indigest),
|
||||
(int)digest_length(to->indigest),
|
||||
to->incompression);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ans_key_h(connection_t *c, const char *request) {
|
||||
|
|
@ -358,7 +400,7 @@ bool ans_key_h(connection_t *c, const char *request) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if(!*address && from->address.sa.sa_family != AF_UNSPEC) {
|
||||
if(!*address && from->address.sa.sa_family != AF_UNSPEC && to->minmtu) {
|
||||
char *address, *port;
|
||||
logger(DEBUG_PROTOCOL, LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name);
|
||||
sockaddr2str(&from->address, &address, &port);
|
||||
|
|
@ -371,10 +413,12 @@ bool ans_key_h(connection_t *c, const char *request) {
|
|||
return send_request(to->nexthop->connection, "%s", request);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_LEGACY
|
||||
/* Don't use key material until every check has passed. */
|
||||
cipher_close(from->outcipher);
|
||||
digest_close(from->outdigest);
|
||||
from->status.validkey = false;
|
||||
#endif
|
||||
if (!from->status.sptps) from->status.validkey = false;
|
||||
|
||||
if(compression < 0 || compression > 11) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
|
||||
|
|
@ -388,9 +432,18 @@ bool ans_key_h(connection_t *c, const char *request) {
|
|||
if(from->status.sptps) {
|
||||
char buf[strlen(key)];
|
||||
int len = b64decode(key, buf, strlen(key));
|
||||
|
||||
if(!len || !sptps_receive_data(&from->sptps, buf, len))
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Error processing SPTPS data from %s (%s)", from->name, from->hostname);
|
||||
if(!len || !sptps_receive_data(&from->sptps, buf, len)) {
|
||||
/* Uh-oh. It might be that the tunnel is stuck in some corrupted state,
|
||||
so let's restart SPTPS in case that helps. But don't do that too often
|
||||
to prevent storms.
|
||||
Note that simply relying on handshake timeout is not enough, because
|
||||
that doesn't apply to key regeneration. */
|
||||
if(from->last_req_key < now.tv_sec - 10) {
|
||||
logger(DEBUG_PROTOCOL, LOG_ERR, "Failed to decode handshake TCP packet from %s (%s), restarting SPTPS", from->name, from->hostname);
|
||||
send_req_key(from);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if(from->status.validkey) {
|
||||
if(*address && *port) {
|
||||
|
|
@ -398,16 +451,17 @@ bool ans_key_h(connection_t *c, const char *request) {
|
|||
sockaddr_t sa = str2sockaddr(address, port);
|
||||
update_node_udp(from, &sa);
|
||||
}
|
||||
|
||||
/* Don't send probes if we can't send UDP packets directly to that node.
|
||||
TODO: the indirect (via) condition can change at any time as edges are added and removed, so this should probably be moved to graph.c. */
|
||||
if((from->via == myself || from->via == from) && from->options & OPTION_PMTU_DISCOVERY && !(from->options & OPTION_TCPONLY))
|
||||
send_mtu_probe(from);
|
||||
}
|
||||
|
||||
send_mtu_info(myself, from, MTU);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DISABLE_LEGACY
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses legacy protocol!", from->name, from->hostname);
|
||||
return false;
|
||||
#else
|
||||
/* Check and lookup cipher and digest algorithms */
|
||||
|
||||
if(cipher) {
|
||||
|
|
@ -458,8 +512,6 @@ bool ans_key_h(connection_t *c, const char *request) {
|
|||
update_node_udp(from, &sa);
|
||||
}
|
||||
|
||||
if(from->options & OPTION_PMTU_DISCOVERY && !(from->options & OPTION_TCPONLY))
|
||||
send_mtu_probe(from);
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,15 @@
|
|||
#include "netutl.h"
|
||||
#include "protocol.h"
|
||||
#include "utils.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(x, y) (((x)<(y))?(x):(y))
|
||||
#endif
|
||||
|
||||
int maxoutbufsize = 0;
|
||||
int mtu_info_interval = 5;
|
||||
int udp_info_interval = 5;
|
||||
|
||||
/* Status and error notification routines */
|
||||
|
||||
|
|
@ -149,3 +156,229 @@ bool tcppacket_h(connection_t *c, const char *request) {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool send_sptps_tcppacket(connection_t *c, const char* packet, int len) {
|
||||
/* If there already is a lot of data in the outbuf buffer, discard this packet.
|
||||
We use a very simple Random Early Drop algorithm. */
|
||||
|
||||
if(2.0 * c->outbuf.len / (float)maxoutbufsize - 1 > (float)rand()/(float)RAND_MAX)
|
||||
return true;
|
||||
|
||||
if(!send_request(c, "%d %d", SPTPS_PACKET, len))
|
||||
return false;
|
||||
|
||||
send_meta_raw(c, packet, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sptps_tcppacket_h(connection_t *c, const char* request) {
|
||||
short int len;
|
||||
|
||||
if(sscanf(request, "%*d %hd", &len) != 1) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "SPTPS_PACKET", c->name,
|
||||
c->hostname);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Set sptpslen to len, this will tell receive_meta() that a SPTPS packet is coming. */
|
||||
|
||||
c->sptpslen = len;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Transmitting UDP information */
|
||||
|
||||
bool send_udp_info(node_t *from, node_t *to) {
|
||||
/* If there's a static relay in the path, there's no point in sending the message
|
||||
farther than the static relay. */
|
||||
to = (to->via == myself) ? to->nexthop : to->via;
|
||||
|
||||
/* Skip cases where sending UDP info messages doesn't make sense.
|
||||
This is done here in order to avoid repeating the same logic in multiple callsites. */
|
||||
|
||||
if(to == myself)
|
||||
return true;
|
||||
|
||||
if(!to->status.reachable)
|
||||
return true;
|
||||
|
||||
if(from == myself) {
|
||||
if(to->connection)
|
||||
return true;
|
||||
|
||||
struct timeval elapsed;
|
||||
timersub(&now, &to->udp_info_sent, &elapsed);
|
||||
if(elapsed.tv_sec < udp_info_interval)
|
||||
return true;
|
||||
}
|
||||
|
||||
if((myself->options | from->options | to->options) & OPTION_TCPONLY)
|
||||
return true;
|
||||
|
||||
if((to->nexthop->options >> 24) < 5)
|
||||
return true;
|
||||
|
||||
char *from_address, *from_port;
|
||||
/* If we're the originator, the address we use is irrelevant
|
||||
because the first intermediate node will ignore it.
|
||||
We use our local address as it somewhat makes sense
|
||||
and it's simpler than introducing an encoding for "null" addresses anyway. */
|
||||
sockaddr2str((from != myself) ? &from->address : &to->nexthop->connection->edge->local_address, &from_address, &from_port);
|
||||
|
||||
bool x = send_request(to->nexthop->connection, "%d %s %s %s %s", UDP_INFO, from->name, to->name, from_address, from_port);
|
||||
|
||||
free(from_address);
|
||||
free(from_port);
|
||||
|
||||
if(from == myself)
|
||||
to->udp_info_sent = now;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
bool udp_info_h(connection_t *c, const char* request) {
|
||||
char from_name[MAX_STRING_SIZE];
|
||||
char to_name[MAX_STRING_SIZE];
|
||||
char from_address[MAX_STRING_SIZE];
|
||||
char from_port[MAX_STRING_SIZE];
|
||||
|
||||
if(sscanf(request, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING, from_name, to_name, from_address, from_port) != 4) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "UDP_INFO", c->name, c->hostname);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!check_id(from_name) || !check_id(to_name)) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "UDP_INFO", c->name, c->hostname, "invalid name");
|
||||
return false;
|
||||
}
|
||||
|
||||
node_t *from = lookup_node(from_name);
|
||||
if(!from) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list", "UDP_INFO", c->name, c->hostname, from_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(from != from->via) {
|
||||
/* Not supposed to happen, as it means the message wandered past a static relay */
|
||||
logger(DEBUG_PROTOCOL, LOG_WARNING, "Got UDP info message from %s (%s) which we can't reach directly", from->name, from->hostname);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If we have a direct edge to "from", we are in a better position
|
||||
to guess its address than it is itself. */
|
||||
if(!from->connection && !from->status.udp_confirmed) {
|
||||
sockaddr_t from_addr = str2sockaddr(from_address, from_port);
|
||||
if(sockaddrcmp(&from_addr, &from->address))
|
||||
update_node_udp(from, &from_addr);
|
||||
}
|
||||
|
||||
node_t *to = lookup_node(to_name);
|
||||
if(!to) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list", "UDP_INFO", c->name, c->hostname, to_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Send our own data (which could be what we just received) up the chain. */
|
||||
|
||||
return send_udp_info(from, to);
|
||||
}
|
||||
|
||||
/* Transmitting MTU information */
|
||||
|
||||
bool send_mtu_info(node_t *from, node_t *to, int mtu) {
|
||||
/* Skip cases where sending MTU info messages doesn't make sense.
|
||||
This is done here in order to avoid repeating the same logic in multiple callsites. */
|
||||
|
||||
if(to == myself)
|
||||
return true;
|
||||
|
||||
if(!to->status.reachable)
|
||||
return true;
|
||||
|
||||
if(from == myself) {
|
||||
if(to->connection)
|
||||
return true;
|
||||
|
||||
struct timeval elapsed;
|
||||
timersub(&now, &to->mtu_info_sent, &elapsed);
|
||||
if(elapsed.tv_sec < mtu_info_interval)
|
||||
return true;
|
||||
}
|
||||
|
||||
if((to->nexthop->options >> 24) < 6)
|
||||
return true;
|
||||
|
||||
/* We will send the passed-in MTU value, unless we believe ours is better. */
|
||||
|
||||
node_t *via = (from->via == myself) ? from->nexthop : from->via;
|
||||
if(from->minmtu == from->maxmtu && from->via == myself) {
|
||||
/* We have a direct measurement. Override the value entirely.
|
||||
Note that we only do that if we are sitting as a static relay in the path;
|
||||
otherwise, we can't guarantee packets will flow through us, and increasing
|
||||
MTU could therefore end up being too optimistic. */
|
||||
mtu = from->minmtu;
|
||||
} else if(via->minmtu == via->maxmtu) {
|
||||
/* Static relay. Ensure packets will make it through the entire relay path. */
|
||||
mtu = MIN(mtu, via->minmtu);
|
||||
} else if(via->nexthop->minmtu == via->nexthop->maxmtu) {
|
||||
/* Dynamic relay. Ensure packets will make it through the entire relay path. */
|
||||
mtu = MIN(mtu, via->nexthop->minmtu);
|
||||
}
|
||||
|
||||
if(from == myself)
|
||||
to->mtu_info_sent = now;
|
||||
|
||||
/* If none of the conditions above match in the steady state, it means we're using TCP,
|
||||
so the MTU is irrelevant. That said, it is still important to honor the MTU that was passed in,
|
||||
because other parts of the relay path might be able to use UDP, which means they care about the MTU. */
|
||||
|
||||
return send_request(to->nexthop->connection, "%d %s %s %d", MTU_INFO, from->name, to->name, mtu);
|
||||
}
|
||||
|
||||
bool mtu_info_h(connection_t *c, const char* request) {
|
||||
char from_name[MAX_STRING_SIZE];
|
||||
char to_name[MAX_STRING_SIZE];
|
||||
int mtu;
|
||||
|
||||
if(sscanf(request, "%*d "MAX_STRING" "MAX_STRING" %d", from_name, to_name, &mtu) != 3) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "MTU_INFO", c->name, c->hostname);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(mtu < 512) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "MTU_INFO", c->name, c->hostname, "invalid MTU");
|
||||
return false;
|
||||
}
|
||||
|
||||
mtu = MIN(mtu, MTU);
|
||||
|
||||
if(!check_id(from_name) || !check_id(to_name)) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "MTU_INFO", c->name, c->hostname, "invalid name");
|
||||
return false;
|
||||
}
|
||||
|
||||
node_t *from = lookup_node(from_name);
|
||||
if(!from) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list", "MTU_INFO", c->name, c->hostname, from_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If we don't know the current MTU for that node, use the one we received.
|
||||
Even if we're about to make our own measurements, the value we got from downstream nodes should be pretty close
|
||||
so it's a good idea to use it in the mean time. */
|
||||
if(from->mtu != mtu && from->minmtu != from->maxmtu) {
|
||||
logger(DEBUG_TRAFFIC, LOG_INFO, "Using provisional MTU %d for node %s (%s)", mtu, from->name, from->hostname);
|
||||
from->mtu = mtu;
|
||||
}
|
||||
|
||||
node_t *to = lookup_node(to_name);
|
||||
if(!to) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list", "MTU_INFO", c->name, c->hostname, to_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Continue passing the MTU value (or a better one if we have it) up the chain. */
|
||||
|
||||
return send_mtu_info(from, to, mtu);
|
||||
}
|
||||
|
|
|
|||
512
src/route.c
512
src/route.c
|
|
@ -105,6 +105,260 @@ static bool checklength(node_t *source, vpn_packet_t *packet, length_t length) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static void swap_mac_addresses(vpn_packet_t *packet) {
|
||||
mac_t tmp;
|
||||
memcpy(&tmp, &DATA(packet)[0], sizeof tmp);
|
||||
memcpy(&DATA(packet)[0], &DATA(packet)[6], sizeof tmp);
|
||||
memcpy(&DATA(packet)[6], &tmp, sizeof tmp);
|
||||
}
|
||||
|
||||
/* RFC 792 */
|
||||
|
||||
static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, length_t ether_size, uint8_t type, uint8_t code) {
|
||||
struct ip ip = {0};
|
||||
struct icmp icmp = {0};
|
||||
|
||||
struct in_addr ip_src;
|
||||
struct in_addr ip_dst;
|
||||
uint32_t oldlen;
|
||||
|
||||
if(ratelimit(3))
|
||||
return;
|
||||
|
||||
/* Swap Ethernet source and destination addresses */
|
||||
|
||||
swap_mac_addresses(packet);
|
||||
|
||||
/* Copy headers from packet into properly aligned structs on the stack */
|
||||
|
||||
memcpy(&ip, DATA(packet) + ether_size, ip_size);
|
||||
|
||||
/* Remember original source and destination */
|
||||
|
||||
ip_src = ip.ip_src;
|
||||
ip_dst = ip.ip_dst;
|
||||
|
||||
/* Try to reply with an IP address assigned to the local machine */
|
||||
|
||||
if (type == ICMP_TIME_EXCEEDED && code == ICMP_EXC_TTL) {
|
||||
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sockfd != -1) {
|
||||
struct sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr = ip.ip_src;
|
||||
if (!connect(sockfd, (const struct sockaddr*) &addr, sizeof(addr))) {
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
if (!getsockname(sockfd, (struct sockaddr*) &addr, &addrlen) && addrlen <= sizeof(addr)) {
|
||||
ip_dst = addr.sin_addr;
|
||||
}
|
||||
}
|
||||
close(sockfd);
|
||||
}
|
||||
}
|
||||
|
||||
oldlen = packet->len - ether_size;
|
||||
|
||||
if(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
|
||||
icmp.icmp_nextmtu = htons(packet->len - ether_size);
|
||||
|
||||
if(oldlen >= IP_MSS - ip_size - icmp_size)
|
||||
oldlen = IP_MSS - ip_size - icmp_size;
|
||||
|
||||
/* Copy first part of original contents to ICMP message */
|
||||
|
||||
memmove(DATA(packet) + ether_size + ip_size + icmp_size, DATA(packet) + ether_size, oldlen);
|
||||
|
||||
/* Fill in IPv4 header */
|
||||
|
||||
ip.ip_v = 4;
|
||||
ip.ip_hl = ip_size / 4;
|
||||
ip.ip_tos = 0;
|
||||
ip.ip_len = htons(ip_size + icmp_size + oldlen);
|
||||
ip.ip_id = 0;
|
||||
ip.ip_off = 0;
|
||||
ip.ip_ttl = 255;
|
||||
ip.ip_p = IPPROTO_ICMP;
|
||||
ip.ip_sum = 0;
|
||||
ip.ip_src = ip_dst;
|
||||
ip.ip_dst = ip_src;
|
||||
|
||||
ip.ip_sum = inet_checksum(&ip, ip_size, ~0);
|
||||
|
||||
/* Fill in ICMP header */
|
||||
|
||||
icmp.icmp_type = type;
|
||||
icmp.icmp_code = code;
|
||||
icmp.icmp_cksum = 0;
|
||||
|
||||
icmp.icmp_cksum = inet_checksum(&icmp, icmp_size, ~0);
|
||||
icmp.icmp_cksum = inet_checksum(DATA(packet) + ether_size + ip_size + icmp_size, oldlen, icmp.icmp_cksum);
|
||||
|
||||
/* Copy structs on stack back to packet */
|
||||
|
||||
memcpy(DATA(packet) + ether_size, &ip, ip_size);
|
||||
memcpy(DATA(packet) + ether_size + ip_size, &icmp, icmp_size);
|
||||
|
||||
packet->len = ether_size + ip_size + icmp_size + oldlen;
|
||||
|
||||
send_packet(source, packet);
|
||||
}
|
||||
|
||||
/* RFC 2463 */
|
||||
|
||||
static void route_ipv6_unreachable(node_t *source, vpn_packet_t *packet, length_t ether_size, uint8_t type, uint8_t code) {
|
||||
struct ip6_hdr ip6;
|
||||
struct icmp6_hdr icmp6 = {0};
|
||||
uint16_t checksum;
|
||||
|
||||
struct {
|
||||
struct in6_addr ip6_src; /* source address */
|
||||
struct in6_addr ip6_dst; /* destination address */
|
||||
uint32_t length;
|
||||
uint32_t next;
|
||||
} pseudo;
|
||||
|
||||
if(ratelimit(3))
|
||||
return;
|
||||
|
||||
/* Swap Ethernet source and destination addresses */
|
||||
|
||||
swap_mac_addresses(packet);
|
||||
|
||||
/* Copy headers from packet to structs on the stack */
|
||||
|
||||
memcpy(&ip6, DATA(packet) + ether_size, ip6_size);
|
||||
|
||||
/* Remember original source and destination */
|
||||
|
||||
pseudo.ip6_src = ip6.ip6_dst;
|
||||
pseudo.ip6_dst = ip6.ip6_src;
|
||||
|
||||
/* Try to reply with an IP address assigned to the local machine */
|
||||
|
||||
if (type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT) {
|
||||
int sockfd = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||
if (sockfd != -1) {
|
||||
struct sockaddr_in6 addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin6_family = AF_INET6;
|
||||
addr.sin6_addr = ip6.ip6_src;
|
||||
if (!connect(sockfd, (const struct sockaddr*) &addr, sizeof(addr))) {
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin6_family = AF_INET6;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
if (!getsockname(sockfd, (struct sockaddr*) &addr, &addrlen) && addrlen <= sizeof(addr)) {
|
||||
pseudo.ip6_src = addr.sin6_addr;
|
||||
}
|
||||
}
|
||||
close(sockfd);
|
||||
}
|
||||
}
|
||||
|
||||
pseudo.length = packet->len - ether_size;
|
||||
|
||||
if(type == ICMP6_PACKET_TOO_BIG)
|
||||
icmp6.icmp6_mtu = htonl(pseudo.length);
|
||||
|
||||
if(pseudo.length >= IP_MSS - ip6_size - icmp6_size)
|
||||
pseudo.length = IP_MSS - ip6_size - icmp6_size;
|
||||
|
||||
/* Copy first part of original contents to ICMP message */
|
||||
|
||||
memmove(DATA(packet) + ether_size + ip6_size + icmp6_size, DATA(packet) + ether_size, pseudo.length);
|
||||
|
||||
/* Fill in IPv6 header */
|
||||
|
||||
ip6.ip6_flow = htonl(0x60000000UL);
|
||||
ip6.ip6_plen = htons(icmp6_size + pseudo.length);
|
||||
ip6.ip6_nxt = IPPROTO_ICMPV6;
|
||||
ip6.ip6_hlim = 255;
|
||||
ip6.ip6_src = pseudo.ip6_src;
|
||||
ip6.ip6_dst = pseudo.ip6_dst;
|
||||
|
||||
/* Fill in ICMP header */
|
||||
|
||||
icmp6.icmp6_type = type;
|
||||
icmp6.icmp6_code = code;
|
||||
icmp6.icmp6_cksum = 0;
|
||||
|
||||
/* Create pseudo header */
|
||||
|
||||
pseudo.length = htonl(icmp6_size + pseudo.length);
|
||||
pseudo.next = htonl(IPPROTO_ICMPV6);
|
||||
|
||||
/* Generate checksum */
|
||||
|
||||
checksum = inet_checksum(&pseudo, sizeof pseudo, ~0);
|
||||
checksum = inet_checksum(&icmp6, icmp6_size, checksum);
|
||||
checksum = inet_checksum(DATA(packet) + ether_size + ip6_size + icmp6_size, ntohl(pseudo.length) - icmp6_size, checksum);
|
||||
|
||||
icmp6.icmp6_cksum = checksum;
|
||||
|
||||
/* Copy structs on stack back to packet */
|
||||
|
||||
memcpy(DATA(packet) + ether_size, &ip6, ip6_size);
|
||||
memcpy(DATA(packet) + ether_size + ip6_size, &icmp6, icmp6_size);
|
||||
|
||||
packet->len = ether_size + ip6_size + ntohl(pseudo.length);
|
||||
|
||||
send_packet(source, packet);
|
||||
}
|
||||
|
||||
static bool do_decrement_ttl(node_t *source, vpn_packet_t *packet) {
|
||||
uint16_t type = DATA(packet)[12] << 8 | DATA(packet)[13];
|
||||
length_t ethlen = ether_size;
|
||||
|
||||
if(type == ETH_P_8021Q) {
|
||||
type = DATA(packet)[16] << 8 | DATA(packet)[17];
|
||||
ethlen += 4;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case ETH_P_IP:
|
||||
if(!checklength(source, packet, ethlen + ip_size))
|
||||
return false;
|
||||
|
||||
if(DATA(packet)[ethlen + 8] <= 1) {
|
||||
if(DATA(packet)[ethlen + 11] != IPPROTO_ICMP || DATA(packet)[ethlen + 32] != ICMP_TIME_EXCEEDED)
|
||||
route_ipv4_unreachable(source, packet, ethlen, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t old = DATA(packet)[ethlen + 8] << 8 | DATA(packet)[ethlen + 9];
|
||||
DATA(packet)[ethlen + 8]--;
|
||||
uint16_t new = DATA(packet)[ethlen + 8] << 8 | DATA(packet)[ethlen + 9];
|
||||
|
||||
uint32_t checksum = DATA(packet)[ethlen + 10] << 8 | DATA(packet)[ethlen + 11];
|
||||
checksum += old + (~new & 0xFFFF);
|
||||
while(checksum >> 16)
|
||||
checksum = (checksum & 0xFFFF) + (checksum >> 16);
|
||||
DATA(packet)[ethlen + 10] = checksum >> 8;
|
||||
DATA(packet)[ethlen + 11] = checksum & 0xff;
|
||||
|
||||
return true;
|
||||
|
||||
case ETH_P_IPV6:
|
||||
if(!checklength(source, packet, ethlen + ip6_size))
|
||||
return false;
|
||||
|
||||
if(DATA(packet)[ethlen + 7] <= 1) {
|
||||
if(DATA(packet)[ethlen + 6] != IPPROTO_ICMPV6 || DATA(packet)[ethlen + 40] != ICMP6_TIME_EXCEEDED)
|
||||
route_ipv6_unreachable(source, packet, ethlen, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT);
|
||||
return false;
|
||||
}
|
||||
|
||||
DATA(packet)[ethlen + 7]--;
|
||||
|
||||
return true;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *packet) {
|
||||
if(!source || !via || !(via->options & OPTION_CLAMP_MSS))
|
||||
return;
|
||||
|
|
@ -164,7 +418,7 @@ static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *pac
|
|||
/* Found it */
|
||||
uint16_t oldmss = DATA(packet)[start + 22 + i] << 8 | DATA(packet)[start + 23 + i];
|
||||
uint16_t newmss = mtu - start - 20;
|
||||
uint16_t csum = DATA(packet)[start + 16] << 8 | DATA(packet)[start + 17];
|
||||
uint32_t csum = DATA(packet)[start + 16] << 8 | DATA(packet)[start + 17];
|
||||
|
||||
if(oldmss <= newmss)
|
||||
break;
|
||||
|
|
@ -175,22 +429,17 @@ static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *pac
|
|||
DATA(packet)[start + 22 + i] = newmss >> 8;
|
||||
DATA(packet)[start + 23 + i] = newmss & 0xff;
|
||||
csum ^= 0xffff;
|
||||
csum -= oldmss;
|
||||
csum += oldmss ^ 0xffff;
|
||||
csum += newmss;
|
||||
csum = (csum & 0xffff) + (csum >> 16);
|
||||
csum += csum >> 16;
|
||||
csum ^= 0xffff;
|
||||
DATA(packet)[start + 16] = csum >> 8;
|
||||
DATA(packet)[start + 17] = csum & 0xff;
|
||||
DATA(packet)[start + 17] = csum;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void swap_mac_addresses(vpn_packet_t *packet) {
|
||||
mac_t tmp;
|
||||
memcpy(&tmp, &DATA(packet)[0], sizeof tmp);
|
||||
memcpy(&DATA(packet)[0], &DATA(packet)[6], sizeof tmp);
|
||||
memcpy(&DATA(packet)[6], &tmp, sizeof tmp);
|
||||
}
|
||||
|
||||
static void age_subnets(void *data) {
|
||||
bool left = false;
|
||||
|
||||
|
|
@ -248,77 +497,12 @@ static void learn_mac(mac_t *address) {
|
|||
}
|
||||
}
|
||||
|
||||
/* RFC 792 */
|
||||
static void route_broadcast(node_t *source, vpn_packet_t *packet) {
|
||||
if(decrement_ttl && source != myself)
|
||||
if(!do_decrement_ttl(source, packet))
|
||||
return;
|
||||
|
||||
static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, length_t ether_size, uint8_t type, uint8_t code) {
|
||||
struct ip ip = {0};
|
||||
struct icmp icmp = {0};
|
||||
|
||||
struct in_addr ip_src;
|
||||
struct in_addr ip_dst;
|
||||
uint32_t oldlen;
|
||||
|
||||
if(ratelimit(3))
|
||||
return;
|
||||
|
||||
/* Swap Ethernet source and destination addresses */
|
||||
|
||||
swap_mac_addresses(packet);
|
||||
|
||||
/* Copy headers from packet into properly aligned structs on the stack */
|
||||
|
||||
memcpy(&ip, DATA(packet) + ether_size, ip_size);
|
||||
|
||||
/* Remember original source and destination */
|
||||
|
||||
ip_src = ip.ip_src;
|
||||
ip_dst = ip.ip_dst;
|
||||
|
||||
oldlen = packet->len - ether_size;
|
||||
|
||||
if(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
|
||||
icmp.icmp_nextmtu = htons(packet->len - ether_size);
|
||||
|
||||
if(oldlen >= IP_MSS - ip_size - icmp_size)
|
||||
oldlen = IP_MSS - ip_size - icmp_size;
|
||||
|
||||
/* Copy first part of original contents to ICMP message */
|
||||
|
||||
memmove(DATA(packet) + ether_size + ip_size + icmp_size, DATA(packet) + ether_size, oldlen);
|
||||
|
||||
/* Fill in IPv4 header */
|
||||
|
||||
ip.ip_v = 4;
|
||||
ip.ip_hl = ip_size / 4;
|
||||
ip.ip_tos = 0;
|
||||
ip.ip_len = htons(ip_size + icmp_size + oldlen);
|
||||
ip.ip_id = 0;
|
||||
ip.ip_off = 0;
|
||||
ip.ip_ttl = 255;
|
||||
ip.ip_p = IPPROTO_ICMP;
|
||||
ip.ip_sum = 0;
|
||||
ip.ip_src = ip_dst;
|
||||
ip.ip_dst = ip_src;
|
||||
|
||||
ip.ip_sum = inet_checksum(&ip, ip_size, ~0);
|
||||
|
||||
/* Fill in ICMP header */
|
||||
|
||||
icmp.icmp_type = type;
|
||||
icmp.icmp_code = code;
|
||||
icmp.icmp_cksum = 0;
|
||||
|
||||
icmp.icmp_cksum = inet_checksum(&icmp, icmp_size, ~0);
|
||||
icmp.icmp_cksum = inet_checksum(DATA(packet) + ether_size + ip_size + icmp_size, oldlen, icmp.icmp_cksum);
|
||||
|
||||
/* Copy structs on stack back to packet */
|
||||
|
||||
memcpy(DATA(packet) + ether_size, &ip, ip_size);
|
||||
memcpy(DATA(packet) + ether_size + ip_size, &icmp, icmp_size);
|
||||
|
||||
packet->len = ether_size + ip_size + icmp_size + oldlen;
|
||||
|
||||
send_packet(source, packet);
|
||||
broadcast_packet(source, packet);
|
||||
}
|
||||
|
||||
/* RFC 791 */
|
||||
|
|
@ -396,7 +580,7 @@ static void route_ipv4(node_t *source, vpn_packet_t *packet) {
|
|||
}
|
||||
|
||||
if (!subnet->owner) {
|
||||
broadcast_packet(source, packet);
|
||||
route_broadcast(source, packet);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -411,6 +595,10 @@ static void route_ipv4(node_t *source, vpn_packet_t *packet) {
|
|||
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
|
||||
return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_ANO);
|
||||
|
||||
if(decrement_ttl && source != myself && subnet->owner != myself)
|
||||
if(!do_decrement_ttl(source, packet))
|
||||
return;
|
||||
|
||||
if(priorityinheritance)
|
||||
packet->priority = DATA(packet)[15];
|
||||
|
||||
|
|
@ -441,86 +629,6 @@ static void route_ipv4(node_t *source, vpn_packet_t *packet) {
|
|||
send_packet(subnet->owner, packet);
|
||||
}
|
||||
|
||||
/* RFC 2463 */
|
||||
|
||||
static void route_ipv6_unreachable(node_t *source, vpn_packet_t *packet, length_t ether_size, uint8_t type, uint8_t code) {
|
||||
struct ip6_hdr ip6;
|
||||
struct icmp6_hdr icmp6 = {0};
|
||||
uint16_t checksum;
|
||||
|
||||
struct {
|
||||
struct in6_addr ip6_src; /* source address */
|
||||
struct in6_addr ip6_dst; /* destination address */
|
||||
uint32_t length;
|
||||
uint32_t next;
|
||||
} pseudo;
|
||||
|
||||
if(ratelimit(3))
|
||||
return;
|
||||
|
||||
/* Swap Ethernet source and destination addresses */
|
||||
|
||||
swap_mac_addresses(packet);
|
||||
|
||||
/* Copy headers from packet to structs on the stack */
|
||||
|
||||
memcpy(&ip6, DATA(packet) + ether_size, ip6_size);
|
||||
|
||||
/* Remember original source and destination */
|
||||
|
||||
pseudo.ip6_src = ip6.ip6_dst;
|
||||
pseudo.ip6_dst = ip6.ip6_src;
|
||||
|
||||
pseudo.length = packet->len - ether_size;
|
||||
|
||||
if(type == ICMP6_PACKET_TOO_BIG)
|
||||
icmp6.icmp6_mtu = htonl(pseudo.length);
|
||||
|
||||
if(pseudo.length >= IP_MSS - ip6_size - icmp6_size)
|
||||
pseudo.length = IP_MSS - ip6_size - icmp6_size;
|
||||
|
||||
/* Copy first part of original contents to ICMP message */
|
||||
|
||||
memmove(DATA(packet) + ether_size + ip6_size + icmp6_size, DATA(packet) + ether_size, pseudo.length);
|
||||
|
||||
/* Fill in IPv6 header */
|
||||
|
||||
ip6.ip6_flow = htonl(0x60000000UL);
|
||||
ip6.ip6_plen = htons(icmp6_size + pseudo.length);
|
||||
ip6.ip6_nxt = IPPROTO_ICMPV6;
|
||||
ip6.ip6_hlim = 255;
|
||||
ip6.ip6_src = pseudo.ip6_src;
|
||||
ip6.ip6_dst = pseudo.ip6_dst;
|
||||
|
||||
/* Fill in ICMP header */
|
||||
|
||||
icmp6.icmp6_type = type;
|
||||
icmp6.icmp6_code = code;
|
||||
icmp6.icmp6_cksum = 0;
|
||||
|
||||
/* Create pseudo header */
|
||||
|
||||
pseudo.length = htonl(icmp6_size + pseudo.length);
|
||||
pseudo.next = htonl(IPPROTO_ICMPV6);
|
||||
|
||||
/* Generate checksum */
|
||||
|
||||
checksum = inet_checksum(&pseudo, sizeof pseudo, ~0);
|
||||
checksum = inet_checksum(&icmp6, icmp6_size, checksum);
|
||||
checksum = inet_checksum(DATA(packet) + ether_size + ip6_size + icmp6_size, ntohl(pseudo.length) - icmp6_size, checksum);
|
||||
|
||||
icmp6.icmp6_cksum = checksum;
|
||||
|
||||
/* Copy structs on stack back to packet */
|
||||
|
||||
memcpy(DATA(packet) + ether_size, &ip6, ip6_size);
|
||||
memcpy(DATA(packet) + ether_size + ip6_size, &icmp6, icmp6_size);
|
||||
|
||||
packet->len = ether_size + ip6_size + ntohl(pseudo.length);
|
||||
|
||||
send_packet(source, packet);
|
||||
}
|
||||
|
||||
static void route_neighborsol(node_t *source, vpn_packet_t *packet);
|
||||
|
||||
static void route_ipv6(node_t *source, vpn_packet_t *packet) {
|
||||
|
|
@ -556,7 +664,7 @@ static void route_ipv6(node_t *source, vpn_packet_t *packet) {
|
|||
}
|
||||
|
||||
if (!subnet->owner) {
|
||||
broadcast_packet(source, packet);
|
||||
route_broadcast(source, packet);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -571,6 +679,10 @@ static void route_ipv6(node_t *source, vpn_packet_t *packet) {
|
|||
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
|
||||
return route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN);
|
||||
|
||||
if(decrement_ttl && source != myself && subnet->owner != myself)
|
||||
if(!do_decrement_ttl(source, packet))
|
||||
return;
|
||||
|
||||
via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
|
||||
|
||||
if(via == source) {
|
||||
|
|
@ -687,6 +799,10 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet) {
|
|||
if(subnet->owner == myself)
|
||||
return; /* silently ignore */
|
||||
|
||||
if(decrement_ttl)
|
||||
if(!do_decrement_ttl(source, packet))
|
||||
return;
|
||||
|
||||
/* Create neighbor advertation reply */
|
||||
|
||||
memcpy(DATA(packet), DATA(packet) + ETH_ALEN, ETH_ALEN); /* copy destination address */
|
||||
|
|
@ -782,15 +898,17 @@ static void route_arp(node_t *source, vpn_packet_t *packet) {
|
|||
if(subnet->owner == myself)
|
||||
return; /* silently ignore */
|
||||
|
||||
memcpy(DATA(packet), DATA(packet) + ETH_ALEN, ETH_ALEN); /* copy destination address */
|
||||
DATA(packet)[ETH_ALEN * 2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
|
||||
if(decrement_ttl)
|
||||
if(!do_decrement_ttl(source, packet))
|
||||
return;
|
||||
|
||||
memcpy(&addr, arp.arp_tpa, sizeof addr); /* save protocol addr */
|
||||
memcpy(arp.arp_tpa, arp.arp_spa, sizeof addr); /* swap destination and source protocol address */
|
||||
memcpy(arp.arp_spa, &addr, sizeof addr); /* ... */
|
||||
|
||||
memcpy(arp.arp_tha, arp.arp_sha, ETH_ALEN); /* set target hard/proto addr */
|
||||
memcpy(arp.arp_sha, DATA(packet) + ETH_ALEN, ETH_ALEN); /* add fake source hard addr */
|
||||
memcpy(arp.arp_sha, DATA(packet) + ETH_ALEN, ETH_ALEN); /* set source hard/proto addr */
|
||||
arp.arp_sha[ETH_ALEN - 1] ^= 0xFF; /* for consistency with route_packet() */
|
||||
arp.arp_op = htons(ARPOP_REPLY);
|
||||
|
||||
/* Copy structs on stack back to packet */
|
||||
|
|
@ -818,7 +936,7 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
|
|||
subnet = lookup_subnet_mac(NULL, &dest);
|
||||
|
||||
if(!subnet || !subnet->owner) {
|
||||
broadcast_packet(source, packet);
|
||||
route_broadcast(source, packet);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -830,6 +948,10 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
|
|||
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
|
||||
return;
|
||||
|
||||
if(decrement_ttl && source != myself && subnet->owner != myself)
|
||||
if(!do_decrement_ttl(source, packet))
|
||||
return;
|
||||
|
||||
uint16_t type = DATA(packet)[12] << 8 | DATA(packet)[13];
|
||||
|
||||
if(priorityinheritance && type == ETH_P_IP && packet->len >= ether_size + ip_size)
|
||||
|
|
@ -888,58 +1010,6 @@ static void send_pcap(vpn_packet_t *packet) {
|
|||
}
|
||||
}
|
||||
|
||||
static bool do_decrement_ttl(node_t *source, vpn_packet_t *packet) {
|
||||
uint16_t type = DATA(packet)[12] << 8 | DATA(packet)[13];
|
||||
length_t ethlen = ether_size;
|
||||
|
||||
if(type == ETH_P_8021Q) {
|
||||
type = DATA(packet)[16] << 8 | DATA(packet)[17];
|
||||
ethlen += 4;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case ETH_P_IP:
|
||||
if(!checklength(source, packet, ethlen + ip_size))
|
||||
return false;
|
||||
|
||||
if(DATA(packet)[ethlen + 8] < 1) {
|
||||
if(DATA(packet)[ethlen + 11] != IPPROTO_ICMP || DATA(packet)[ethlen + 32] != ICMP_TIME_EXCEEDED)
|
||||
route_ipv4_unreachable(source, packet, ethlen, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t old = DATA(packet)[ethlen + 8] << 8 | DATA(packet)[ethlen + 9];
|
||||
DATA(packet)[ethlen + 8]--;
|
||||
uint16_t new = DATA(packet)[ethlen + 8] << 8 | DATA(packet)[ethlen + 9];
|
||||
|
||||
uint32_t checksum = DATA(packet)[ethlen + 10] << 8 | DATA(packet)[ethlen + 11];
|
||||
checksum += old + (~new & 0xFFFF);
|
||||
while(checksum >> 16)
|
||||
checksum = (checksum & 0xFFFF) + (checksum >> 16);
|
||||
DATA(packet)[ethlen + 10] = checksum >> 8;
|
||||
DATA(packet)[ethlen + 11] = checksum & 0xff;
|
||||
|
||||
return true;
|
||||
|
||||
case ETH_P_IPV6:
|
||||
if(!checklength(source, packet, ethlen + ip6_size))
|
||||
return false;
|
||||
|
||||
if(DATA(packet)[ethlen + 7] < 1) {
|
||||
if(DATA(packet)[ethlen + 6] != IPPROTO_ICMPV6 || DATA(packet)[ethlen + 40] != ICMP6_TIME_EXCEEDED)
|
||||
route_ipv6_unreachable(source, packet, ethlen, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT);
|
||||
return false;
|
||||
}
|
||||
|
||||
DATA(packet)[ethlen + 7]--;
|
||||
|
||||
return true;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void route(node_t *source, vpn_packet_t *packet) {
|
||||
if(pcap)
|
||||
send_pcap(packet);
|
||||
|
|
@ -952,10 +1022,6 @@ void route(node_t *source, vpn_packet_t *packet) {
|
|||
if(!checklength(source, packet, ether_size))
|
||||
return;
|
||||
|
||||
if(decrement_ttl && source != myself)
|
||||
if(!do_decrement_ttl(source, packet))
|
||||
return;
|
||||
|
||||
uint16_t type = DATA(packet)[12] << 8 | DATA(packet)[13];
|
||||
|
||||
switch (routing_mode) {
|
||||
|
|
@ -984,7 +1050,7 @@ void route(node_t *source, vpn_packet_t *packet) {
|
|||
break;
|
||||
|
||||
case RMODE_HUB:
|
||||
broadcast_packet(source, packet);
|
||||
route_broadcast(source, packet);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
78
src/script.c
78
src/script.c
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
script.c -- call an external script
|
||||
Copyright (C) 1999-2005 Ivo Timmermans,
|
||||
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2015 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
|
||||
|
|
@ -26,21 +26,59 @@
|
|||
#include "script.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
#ifdef HAVE_PUTENV
|
||||
static void unputenv(const char *p) {
|
||||
const char *e = strchr(p, '=');
|
||||
if(!e)
|
||||
return;
|
||||
int len = e - p;
|
||||
#ifndef HAVE_UNSETENV
|
||||
#ifdef HAVE_MINGW
|
||||
// Windows requires putenv("FOO=") to unset %FOO%
|
||||
len++;
|
||||
#endif
|
||||
#endif
|
||||
char var[len + 1];
|
||||
strncpy(var, p, len);
|
||||
var[len] = 0;
|
||||
#ifdef HAVE_UNSETENV
|
||||
unsetenv(var);
|
||||
#else
|
||||
// We must keep what we putenv() around in memory.
|
||||
// To do this without memory leaks, keep things in a list and reuse if possible.
|
||||
static list_t list = {};
|
||||
for list_each(char, data, &list) {
|
||||
if(!strcmp(data, var)) {
|
||||
putenv(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
char *data = xstrdup(var);
|
||||
list_insert_tail(&list, data);
|
||||
putenv(data);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
static void putenv(const char *p) {}
|
||||
static void unputenv(const char *p) {}
|
||||
#endif
|
||||
|
||||
bool execute_script(const char *name, char **envp) {
|
||||
#ifdef HAVE_SYSTEM
|
||||
char *scriptname;
|
||||
char scriptname[PATH_MAX];
|
||||
char *command;
|
||||
|
||||
xasprintf(&scriptname, "%s" SLASH "%s%s", confbase, name, scriptextension);
|
||||
snprintf(scriptname, sizeof scriptname, "%s" SLASH "%s%s", confbase, name, scriptextension);
|
||||
|
||||
/* First check if there is a script */
|
||||
|
||||
#ifdef HAVE_MINGW
|
||||
if(!*scriptextension) {
|
||||
const char *pathext = getenv("PATHEXT") ?: ".COM;.EXE;.BAT;.CMD";
|
||||
char fullname[strlen(scriptname) + strlen(pathext)];
|
||||
char *ext = fullname + strlen(scriptname);
|
||||
strcpy(fullname, scriptname);
|
||||
size_t pathlen = strlen(pathext);
|
||||
size_t scriptlen = strlen(scriptname);
|
||||
char fullname[scriptlen + pathlen + 1];
|
||||
char *ext = fullname + scriptlen;
|
||||
strncpy(fullname, scriptname, sizeof fullname);
|
||||
|
||||
const char *p = pathext;
|
||||
bool found = false;
|
||||
|
|
@ -51,32 +89,26 @@ bool execute_script(const char *name, char **envp) {
|
|||
ext[q - p] = 0;
|
||||
q++;
|
||||
} else {
|
||||
strcpy(ext, p);
|
||||
strncpy(ext, p, pathlen + 1);
|
||||
}
|
||||
if((found = !access(fullname, F_OK)))
|
||||
break;
|
||||
p = q;
|
||||
}
|
||||
if(!found) {
|
||||
free(scriptname);
|
||||
if(!found)
|
||||
return true;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
|
||||
if(access(scriptname, F_OK)) {
|
||||
free(scriptname);
|
||||
if(access(scriptname, F_OK))
|
||||
return true;
|
||||
}
|
||||
|
||||
logger(DEBUG_STATUS, LOG_INFO, "Executing script %s", name);
|
||||
|
||||
#ifdef HAVE_PUTENV
|
||||
/* Set environment */
|
||||
|
||||
for(int i = 0; envp[i]; i++)
|
||||
putenv(envp[i]);
|
||||
#endif
|
||||
|
||||
if(scriptinterpreter)
|
||||
xasprintf(&command, "%s \"%s\"", scriptinterpreter, scriptname);
|
||||
|
|
@ -86,19 +118,11 @@ bool execute_script(const char *name, char **envp) {
|
|||
int status = system(command);
|
||||
|
||||
free(command);
|
||||
free(scriptname);
|
||||
|
||||
/* Unset environment */
|
||||
|
||||
for(int i = 0; envp[i]; i++) {
|
||||
char *e = strchr(envp[i], '=');
|
||||
if(e) {
|
||||
char p[e - envp[i] + 1];
|
||||
strncpy(p, envp[i], e - envp[i]);
|
||||
p[e - envp[i]] = '\0';
|
||||
putenv(p);
|
||||
}
|
||||
}
|
||||
for(int i = 0; envp[i]; i++)
|
||||
unputenv(envp[i]);
|
||||
|
||||
if(status != -1) {
|
||||
#ifdef WEXITSTATUS
|
||||
|
|
@ -121,6 +145,6 @@ bool execute_script(const char *name, char **envp) {
|
|||
logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "system", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,6 +106,12 @@ extern splay_node_t *splay_search_closest_greater_node(splay_tree_t *, const voi
|
|||
extern void splay_foreach(const splay_tree_t *, splay_action_t);
|
||||
extern void splay_foreach_node(const splay_tree_t *, splay_action_t);
|
||||
|
||||
/*
|
||||
Iterates over a tree.
|
||||
|
||||
CAUTION: while this construct supports deleting the current item,
|
||||
it does *not* support deleting *other* nodes while iterating on the tree.
|
||||
*/
|
||||
#define splay_each(type, item, tree) (type *item = (type *)1; item; item = NULL) for(splay_node_t *node = (tree)->head, *next; item = node ? node->data : NULL, next = node ? node->next : NULL, node; node = next)
|
||||
|
||||
#endif
|
||||
|
|
|
|||
167
src/sptps.c
167
src/sptps.c
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
sptps.c -- Simple Peer-to-Peer Security
|
||||
Copyright (C) 2011-2014 Guus Sliepen <guus@tinc-vpn.org>,
|
||||
Copyright (C) 2011-2015 Guus Sliepen <guus@tinc-vpn.org>,
|
||||
2010 Brandon L. Black <blblack@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
|
@ -204,7 +204,7 @@ static bool generate_key_material(sptps_t *s, const char *shared, size_t len) {
|
|||
|
||||
// Create the HMAC seed, which is "key expansion" + session label + server nonce + client nonce
|
||||
char seed[s->labellen + 64 + 13];
|
||||
strcpy(seed, "key expansion");
|
||||
memcpy(seed, "key expansion", 13);
|
||||
if(s->initiator) {
|
||||
memcpy(seed + 13, s->mykex + 1, 32);
|
||||
memcpy(seed + 45, s->hiskex + 1, 32);
|
||||
|
|
@ -384,10 +384,11 @@ static bool sptps_check_seqno(sptps_t *s, uint32_t seqno, bool update_state) {
|
|||
if (update_state)
|
||||
s->farfuture++;
|
||||
if(farfuture)
|
||||
return error(s, EIO, "Packet is %d seqs in the future, dropped (%u)\n", seqno - s->inseqno, s->farfuture);
|
||||
return update_state ? error(s, EIO, "Packet is %d seqs in the future, dropped (%u)\n", seqno - s->inseqno, s->farfuture) : false;
|
||||
|
||||
// Unless we have seen lots of them, in which case we consider the others lost.
|
||||
warning(s, "Lost %d packets\n", seqno - s->inseqno);
|
||||
if(update_state)
|
||||
warning(s, "Lost %d packets\n", seqno - s->inseqno);
|
||||
if (update_state) {
|
||||
// Mark all packets in the replay window as being late.
|
||||
memset(s->late, 255, s->replaywin);
|
||||
|
|
@ -395,7 +396,7 @@ static bool sptps_check_seqno(sptps_t *s, uint32_t seqno, bool update_state) {
|
|||
} else if (seqno < s->inseqno) {
|
||||
// If the sequence number is farther in the past than the bitmap goes, or if the packet was already received, drop it.
|
||||
if((s->inseqno >= s->replaywin * 8 && seqno < s->inseqno - s->replaywin * 8) || !(s->late[(seqno / 8) % s->replaywin] & (1 << seqno % 8)))
|
||||
return error(s, EIO, "Received late or replayed packet, seqno %d, last received %d\n", seqno, s->inseqno);
|
||||
return update_state ? error(s, EIO, "Received late or replayed packet, seqno %d, last received %d\n", seqno, s->inseqno) : false;
|
||||
} else if (update_state) {
|
||||
// We missed some packets. Mark them in the bitmap as being late.
|
||||
for(int i = s->inseqno; i < seqno; i++)
|
||||
|
|
@ -447,6 +448,7 @@ static bool sptps_receive_data_datagram(sptps_t *s, const char *data, size_t len
|
|||
uint32_t seqno;
|
||||
memcpy(&seqno, data, 4);
|
||||
seqno = ntohl(seqno);
|
||||
data += 4; len -= 4;
|
||||
|
||||
if(!s->instate) {
|
||||
if(seqno != s->inseqno)
|
||||
|
|
@ -454,39 +456,40 @@ static bool sptps_receive_data_datagram(sptps_t *s, const char *data, size_t len
|
|||
|
||||
s->inseqno = seqno + 1;
|
||||
|
||||
uint8_t type = data[4];
|
||||
uint8_t type = *(data++); len--;
|
||||
|
||||
if(type != SPTPS_HANDSHAKE)
|
||||
return error(s, EIO, "Application record received before handshake finished");
|
||||
|
||||
return receive_handshake(s, data + 5, len - 5);
|
||||
return receive_handshake(s, data, len);
|
||||
}
|
||||
|
||||
// Decrypt
|
||||
|
||||
char buffer[len];
|
||||
|
||||
size_t outlen;
|
||||
|
||||
if(!chacha_poly1305_decrypt(s->incipher, seqno, data + 4, len - 4, buffer, &outlen))
|
||||
if(!chacha_poly1305_decrypt(s->incipher, seqno, data, len, buffer, &outlen))
|
||||
return error(s, EIO, "Failed to decrypt and verify packet");
|
||||
|
||||
if(!sptps_check_seqno(s, seqno, true))
|
||||
return false;
|
||||
|
||||
// Append a NULL byte for safety.
|
||||
buffer[len - 20] = 0;
|
||||
buffer[outlen] = 0;
|
||||
|
||||
uint8_t type = buffer[0];
|
||||
data = buffer;
|
||||
len = outlen;
|
||||
|
||||
uint8_t type = *(data++); len--;
|
||||
|
||||
if(type < SPTPS_HANDSHAKE) {
|
||||
if(!s->instate)
|
||||
return error(s, EIO, "Application record received before handshake finished");
|
||||
if(!s->receive_record(s->handle, type, buffer + 1, len - 21))
|
||||
abort();
|
||||
if(!s->receive_record(s->handle, type, data, len))
|
||||
return false;
|
||||
} else if(type == SPTPS_HANDSHAKE) {
|
||||
if(!receive_handshake(s, buffer + 1, len - 21))
|
||||
abort();
|
||||
if(!receive_handshake(s, data, len))
|
||||
return false;
|
||||
} else {
|
||||
return error(s, EIO, "Invalid record type %d", type);
|
||||
}
|
||||
|
|
@ -495,90 +498,92 @@ static bool sptps_receive_data_datagram(sptps_t *s, const char *data, size_t len
|
|||
}
|
||||
|
||||
// Receive incoming data. Check if it contains a complete record, if so, handle it.
|
||||
bool sptps_receive_data(sptps_t *s, const void *data, size_t len) {
|
||||
size_t sptps_receive_data(sptps_t *s, const void *data, size_t len) {
|
||||
size_t total_read = 0;
|
||||
|
||||
if(!s->state)
|
||||
return error(s, EIO, "Invalid session state zero");
|
||||
|
||||
if(s->datagram)
|
||||
return sptps_receive_data_datagram(s, data, len);
|
||||
return sptps_receive_data_datagram(s, data, len) ? len : false;
|
||||
|
||||
while(len) {
|
||||
// First read the 2 length bytes.
|
||||
if(s->buflen < 2) {
|
||||
size_t toread = 2 - s->buflen;
|
||||
if(toread > len)
|
||||
toread = len;
|
||||
|
||||
memcpy(s->inbuf + s->buflen, data, toread);
|
||||
|
||||
s->buflen += toread;
|
||||
len -= toread;
|
||||
data += toread;
|
||||
|
||||
// Exit early if we don't have the full length.
|
||||
if(s->buflen < 2)
|
||||
return true;
|
||||
|
||||
// Get the length bytes
|
||||
|
||||
memcpy(&s->reclen, s->inbuf, 2);
|
||||
s->reclen = ntohs(s->reclen);
|
||||
|
||||
// If we have the length bytes, ensure our buffer can hold the whole request.
|
||||
s->inbuf = realloc(s->inbuf, s->reclen + 19UL);
|
||||
if(!s->inbuf)
|
||||
return error(s, errno, strerror(errno));
|
||||
|
||||
// Exit early if we have no more data to process.
|
||||
if(!len)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read up to the end of the record.
|
||||
size_t toread = s->reclen + (s->instate ? 19UL : 3UL) - s->buflen;
|
||||
// First read the 2 length bytes.
|
||||
if(s->buflen < 2) {
|
||||
size_t toread = 2 - s->buflen;
|
||||
if(toread > len)
|
||||
toread = len;
|
||||
|
||||
memcpy(s->inbuf + s->buflen, data, toread);
|
||||
|
||||
total_read += toread;
|
||||
s->buflen += toread;
|
||||
len -= toread;
|
||||
data += toread;
|
||||
|
||||
// If we don't have a whole record, exit.
|
||||
if(s->buflen < s->reclen + (s->instate ? 19UL : 3UL))
|
||||
return true;
|
||||
// Exit early if we don't have the full length.
|
||||
if(s->buflen < 2)
|
||||
return total_read;
|
||||
|
||||
// Update sequence number.
|
||||
// Get the length bytes
|
||||
|
||||
uint32_t seqno = s->inseqno++;
|
||||
memcpy(&s->reclen, s->inbuf, 2);
|
||||
s->reclen = ntohs(s->reclen);
|
||||
|
||||
// Check HMAC and decrypt.
|
||||
if(s->instate) {
|
||||
if(!chacha_poly1305_decrypt(s->incipher, seqno, s->inbuf + 2UL, s->reclen + 17UL, s->inbuf + 2UL, NULL))
|
||||
return error(s, EINVAL, "Failed to decrypt and verify record");
|
||||
}
|
||||
// If we have the length bytes, ensure our buffer can hold the whole request.
|
||||
s->inbuf = realloc(s->inbuf, s->reclen + 19UL);
|
||||
if(!s->inbuf)
|
||||
return error(s, errno, strerror(errno));
|
||||
|
||||
// Append a NULL byte for safety.
|
||||
s->inbuf[s->reclen + 3UL] = 0;
|
||||
|
||||
uint8_t type = s->inbuf[2];
|
||||
|
||||
if(type < SPTPS_HANDSHAKE) {
|
||||
if(!s->instate)
|
||||
return error(s, EIO, "Application record received before handshake finished");
|
||||
if(!s->receive_record(s->handle, type, s->inbuf + 3, s->reclen))
|
||||
return false;
|
||||
} else if(type == SPTPS_HANDSHAKE) {
|
||||
if(!receive_handshake(s, s->inbuf + 3, s->reclen))
|
||||
return false;
|
||||
} else {
|
||||
return error(s, EIO, "Invalid record type %d", type);
|
||||
}
|
||||
|
||||
s->buflen = 0;
|
||||
// Exit early if we have no more data to process.
|
||||
if(!len)
|
||||
return total_read;
|
||||
}
|
||||
|
||||
return true;
|
||||
// Read up to the end of the record.
|
||||
size_t toread = s->reclen + (s->instate ? 19UL : 3UL) - s->buflen;
|
||||
if(toread > len)
|
||||
toread = len;
|
||||
|
||||
memcpy(s->inbuf + s->buflen, data, toread);
|
||||
total_read += toread;
|
||||
s->buflen += toread;
|
||||
len -= toread;
|
||||
data += toread;
|
||||
|
||||
// If we don't have a whole record, exit.
|
||||
if(s->buflen < s->reclen + (s->instate ? 19UL : 3UL))
|
||||
return total_read;
|
||||
|
||||
// Update sequence number.
|
||||
|
||||
uint32_t seqno = s->inseqno++;
|
||||
|
||||
// Check HMAC and decrypt.
|
||||
if(s->instate) {
|
||||
if(!chacha_poly1305_decrypt(s->incipher, seqno, s->inbuf + 2UL, s->reclen + 17UL, s->inbuf + 2UL, NULL))
|
||||
return error(s, EINVAL, "Failed to decrypt and verify record");
|
||||
}
|
||||
|
||||
// Append a NULL byte for safety.
|
||||
s->inbuf[s->reclen + 3UL] = 0;
|
||||
|
||||
uint8_t type = s->inbuf[2];
|
||||
|
||||
if(type < SPTPS_HANDSHAKE) {
|
||||
if(!s->instate)
|
||||
return error(s, EIO, "Application record received before handshake finished");
|
||||
if(!s->receive_record(s->handle, type, s->inbuf + 3, s->reclen))
|
||||
return false;
|
||||
} else if(type == SPTPS_HANDSHAKE) {
|
||||
if(!receive_handshake(s, s->inbuf + 3, s->reclen))
|
||||
return false;
|
||||
} else {
|
||||
return error(s, EIO, "Invalid record type %d", type);
|
||||
}
|
||||
|
||||
s->buflen = 0;
|
||||
|
||||
return total_read;
|
||||
}
|
||||
|
||||
// Start a SPTPS session.
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ extern void (*sptps_log)(sptps_t *s, int s_errno, const char *format, va_list ap
|
|||
extern bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_t *mykey, ecdsa_t *hiskey, const void *label, size_t labellen, send_data_t send_data, receive_record_t receive_record);
|
||||
extern bool sptps_stop(sptps_t *s);
|
||||
extern bool sptps_send_record(sptps_t *s, uint8_t type, const void *data, uint16_t len);
|
||||
extern bool sptps_receive_data(sptps_t *s, const void *data, size_t len);
|
||||
extern size_t sptps_receive_data(sptps_t *s, const void *data, size_t len);
|
||||
extern bool sptps_force_kex(sptps_t *s);
|
||||
extern bool sptps_verify_datagram(sptps_t *s, const void *data, size_t len);
|
||||
|
||||
|
|
|
|||
|
|
@ -88,7 +88,10 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
FILE *fp = fopen(argv[1], "w");
|
||||
if(fp) {
|
||||
ecdsa_write_pem_private_key(key, fp);
|
||||
if(!ecdsa_write_pem_private_key(key, fp)) {
|
||||
fprintf(stderr, "Could not write ECDSA private key\n");
|
||||
return 1;
|
||||
}
|
||||
fclose(fp);
|
||||
} else {
|
||||
fprintf(stderr, "Could not open '%s' for writing: %s\n", argv[1], strerror(errno));
|
||||
|
|
@ -97,7 +100,8 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
fp = fopen(argv[2], "w");
|
||||
if(fp) {
|
||||
ecdsa_write_pem_public_key(key, fp);
|
||||
if(!ecdsa_write_pem_public_key(key, fp))
|
||||
fprintf(stderr, "Could not write ECDSA public key\n");
|
||||
fclose(fp);
|
||||
} else {
|
||||
fprintf(stderr, "Could not open '%s' for writing: %s\n", argv[2], strerror(errno));
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ bool send_request(void *c, const char *msg, ...) { return false; }
|
|||
struct list_t *connection_list = NULL;
|
||||
bool send_meta(void *c, const char *msg , int len) { return false; }
|
||||
char *logfilename = NULL;
|
||||
bool do_detach = false;
|
||||
struct timeval now;
|
||||
|
||||
static bool send_data(void *handle, uint8_t type, const void *data, size_t len) {
|
||||
|
|
@ -46,11 +47,16 @@ static bool receive_record(void *handle, uint8_t type, const void *data, uint16_
|
|||
}
|
||||
|
||||
static void receive_data(sptps_t *sptps) {
|
||||
char buf[4096];
|
||||
char buf[4096], *bufp = buf;
|
||||
int fd = *(int *)sptps->handle;
|
||||
size_t len = recv(fd, buf, sizeof buf, 0);
|
||||
if(!sptps_receive_data(sptps, buf, len))
|
||||
abort();
|
||||
while(len) {
|
||||
size_t done = sptps_receive_data(sptps, bufp, len);
|
||||
if(!done)
|
||||
abort();
|
||||
bufp += done;
|
||||
len -= done;
|
||||
}
|
||||
}
|
||||
|
||||
struct timespec start;
|
||||
|
|
@ -101,19 +107,26 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
fprintf(stderr, "Ed25519 sign for %lg seconds: ", duration);
|
||||
for(clock_start(); clock_countto(duration);)
|
||||
ecdsa_sign(key1, buf1, 256, buf2);
|
||||
fprintf(stderr, "%22.2lf op/s\n", rate);
|
||||
if(!ecdsa_sign(key1, buf1, 256, buf2))
|
||||
return 1;
|
||||
fprintf(stderr, "%20.2lf op/s\n", rate);
|
||||
|
||||
fprintf(stderr, "Ed25519 verify for %lg seconds: ", duration);
|
||||
for(clock_start(); clock_countto(duration);)
|
||||
ecdsa_verify(key1, buf1, 256, buf2);
|
||||
fprintf(stderr, "%20.2lf op/s\n", rate);
|
||||
if(!ecdsa_verify(key1, buf1, 256, buf2)) {
|
||||
fprintf(stderr, "Signature verification failed\n");
|
||||
return 1;
|
||||
}
|
||||
fprintf(stderr, "%18.2lf op/s\n", rate);
|
||||
|
||||
ecdh1 = ecdh_generate_public(buf1);
|
||||
fprintf(stderr, "ECDH for %lg seconds: ", duration);
|
||||
for(clock_start(); clock_countto(duration);) {
|
||||
ecdh2 = ecdh_generate_public(buf2);
|
||||
ecdh_compute_shared(ecdh2, buf1, buf3);
|
||||
if(!ecdh2)
|
||||
return 1;
|
||||
if(!ecdh_compute_shared(ecdh2, buf1, buf3))
|
||||
return 1;
|
||||
}
|
||||
fprintf(stderr, "%28.2lf op/s\n", rate);
|
||||
ecdh_free(ecdh1);
|
||||
|
|
|
|||
|
|
@ -35,8 +35,10 @@ bool send_request(void *c, const char *msg, ...) { return false; }
|
|||
struct list_t *connection_list = NULL;
|
||||
bool send_meta(void *c, const char *msg , int len) { return false; }
|
||||
char *logfilename = NULL;
|
||||
bool do_detach = false;
|
||||
struct timeval now;
|
||||
|
||||
static bool special;
|
||||
static bool verbose;
|
||||
static bool readonly;
|
||||
static bool writeonly;
|
||||
|
|
@ -69,6 +71,7 @@ static struct option const long_options[] = {
|
|||
{"writeonly", no_argument, NULL, 'w'},
|
||||
{"packet-loss", required_argument, NULL, 'L'},
|
||||
{"replay-window", required_argument, NULL, 'W'},
|
||||
{"special", no_argument, NULL, 's'},
|
||||
{"verbose", required_argument, NULL, 'v'},
|
||||
{"help", no_argument, NULL, 1},
|
||||
{NULL, 0, NULL, 0}
|
||||
|
|
@ -88,6 +91,7 @@ static void usage() {
|
|||
" -w, --writeonly Only send data from stdin to the socket.\n"
|
||||
" -L, --packet-loss RATE Fake packet loss of RATE percent.\n"
|
||||
" -R, --replay-window N Set replay window to N bytes.\n"
|
||||
" -s, --special Enable special handling of lines starting with #, ^ and $.\n"
|
||||
" -v, --verbose Display debug messages.\n"
|
||||
"\n");
|
||||
fprintf(stderr, "Report bugs to tinc@tinc-vpn.org.\n");
|
||||
|
|
@ -106,7 +110,7 @@ int main(int argc, char *argv[]) {
|
|||
ecdsa_t *mykey = NULL, *hiskey = NULL;
|
||||
bool quit = false;
|
||||
|
||||
while((r = getopt_long(argc, argv, "dqrtwL:W:v", long_options, &option_index)) != EOF) {
|
||||
while((r = getopt_long(argc, argv, "dqrstwL:W:v", long_options, &option_index)) != EOF) {
|
||||
switch (r) {
|
||||
case 0: /* long option */
|
||||
break;
|
||||
|
|
@ -149,6 +153,10 @@ int main(int argc, char *argv[]) {
|
|||
verbose = true;
|
||||
break;
|
||||
|
||||
case 's': /* special character handling */
|
||||
special = true;
|
||||
break;
|
||||
|
||||
case '?': /* wrong options */
|
||||
usage();
|
||||
return 1;
|
||||
|
|
@ -271,11 +279,19 @@ int main(int argc, char *argv[]) {
|
|||
crypto_init();
|
||||
|
||||
FILE *fp = fopen(argv[1], "r");
|
||||
if(!fp) {
|
||||
fprintf(stderr, "Could not open %s: %s\n", argv[1], strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
if(!(mykey = ecdsa_read_pem_private_key(fp)))
|
||||
return 1;
|
||||
fclose(fp);
|
||||
|
||||
fp = fopen(argv[2], "r");
|
||||
if(!fp) {
|
||||
fprintf(stderr, "Could not open %s: %s\n", argv[2], strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
if(!(hiskey = ecdsa_read_pem_public_key(fp)))
|
||||
return 1;
|
||||
fclose(fp);
|
||||
|
|
@ -315,11 +331,11 @@ int main(int argc, char *argv[]) {
|
|||
readonly = true;
|
||||
continue;
|
||||
}
|
||||
if(buf[0] == '#')
|
||||
if(special && buf[0] == '#')
|
||||
s.outseqno = atoi(buf + 1);
|
||||
if(buf[0] == '^')
|
||||
if(special && buf[0] == '^')
|
||||
sptps_send_record(&s, SPTPS_HANDSHAKE, NULL, 0);
|
||||
else if(buf[0] == '$') {
|
||||
else if(special && buf[0] == '$') {
|
||||
sptps_force_kex(&s);
|
||||
if(len > 1)
|
||||
sptps_send_record(&s, 0, buf, len);
|
||||
|
|
@ -348,8 +364,19 @@ int main(int argc, char *argv[]) {
|
|||
fprintf(stderr, "Dropped.\n");
|
||||
continue;
|
||||
}
|
||||
if(!sptps_receive_data(&s, buf, len) && !datagram)
|
||||
return 1;
|
||||
char *bufp = buf;
|
||||
while(len) {
|
||||
size_t done = sptps_receive_data(&s, bufp, len);
|
||||
if(!done) {
|
||||
if(!datagram)
|
||||
return 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
bufp += done;
|
||||
len -= done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,9 +40,9 @@ splay_tree_t *subnet_tree;
|
|||
|
||||
/* Subnet lookup cache */
|
||||
|
||||
hash_t *ipv4_cache;
|
||||
hash_t *ipv6_cache;
|
||||
hash_t *mac_cache;
|
||||
static hash_t *ipv4_cache;
|
||||
static hash_t *ipv6_cache;
|
||||
static hash_t *mac_cache;
|
||||
|
||||
void subnet_cache_flush(void) {
|
||||
hash_clear(ipv4_cache);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#define __TINC_SUBNET_H__
|
||||
|
||||
#include "net.h"
|
||||
#include "node.h"
|
||||
|
||||
typedef enum subnet_type_t {
|
||||
SUBNET_MAC = 0,
|
||||
|
|
@ -44,8 +45,6 @@ typedef struct subnet_ipv6_t {
|
|||
int prefixlength;
|
||||
} subnet_ipv6_t;
|
||||
|
||||
#include "node.h"
|
||||
|
||||
typedef struct subnet_t {
|
||||
struct node_t *owner; /* the owner of this subnet */
|
||||
|
||||
|
|
|
|||
|
|
@ -401,11 +401,8 @@ bool net2str(char *netstr, int len, const subnet_t *subnet) {
|
|||
len -= result;
|
||||
}
|
||||
|
||||
if (subnet->weight != DEFAULT_WEIGHT) {
|
||||
if (subnet->weight != DEFAULT_WEIGHT)
|
||||
snprintf(netstr, len, "#%d", subnet->weight);
|
||||
netstr += result;
|
||||
len -= result;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
12
src/system.h
12
src/system.h
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
system.h -- system headers
|
||||
Copyright (C) 1998-2005 Ivo Timmermans
|
||||
2003-2013 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2003-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -25,12 +25,6 @@
|
|||
|
||||
#include "have.h"
|
||||
|
||||
#ifndef HAVE_STDBOOL_H
|
||||
typedef int bool;
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRSIGNAL
|
||||
# define strsignal(p) ""
|
||||
#endif
|
||||
|
|
@ -39,8 +33,4 @@ typedef int bool;
|
|||
|
||||
#include "dropin.h"
|
||||
|
||||
#ifndef HAVE_SOCKLEN_T
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
|
||||
#endif /* __TINC_SYSTEM_H__ */
|
||||
|
|
|
|||
592
src/tincctl.c
592
src/tincctl.c
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
tincctl.c -- Controlling a running tincd
|
||||
Copyright (C) 2007-2014 Guus Sliepen <guus@tinc-vpn.org>
|
||||
Copyright (C) 2007-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -31,6 +31,7 @@
|
|||
#include "control_common.h"
|
||||
#include "crypto.h"
|
||||
#include "ecdsagen.h"
|
||||
#include "fsck.h"
|
||||
#include "info.h"
|
||||
#include "invitation.h"
|
||||
#include "names.h"
|
||||
|
|
@ -66,7 +67,7 @@ char line[4096];
|
|||
static int code;
|
||||
static int req;
|
||||
static int result;
|
||||
static bool force = false;
|
||||
bool force = false;
|
||||
bool tty = true;
|
||||
bool confbasegiven = false;
|
||||
bool netnamegiven = false;
|
||||
|
|
@ -87,8 +88,8 @@ static struct option const long_options[] = {
|
|||
|
||||
static void version(void) {
|
||||
printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
|
||||
VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
|
||||
printf("Copyright (C) 1998-2014 Ivo Timmermans, Guus Sliepen and others.\n"
|
||||
BUILD_VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
|
||||
printf("Copyright (C) 1998-2016 Ivo Timmermans, Guus Sliepen and others.\n"
|
||||
"See the AUTHORS file for a complete list.\n\n"
|
||||
"tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
|
||||
"and you are welcome to redistribute it under certain conditions;\n"
|
||||
|
|
@ -105,6 +106,7 @@ static void usage(bool status) {
|
|||
" -c, --config=DIR Read configuration options from DIR.\n"
|
||||
" -n, --net=NETNAME Connect to net NETNAME.\n"
|
||||
" --pidfile=FILENAME Read control cookie from FILENAME.\n"
|
||||
" --force Force some commands to work despite warnings.\n"
|
||||
" --help Display this help and exit.\n"
|
||||
" --version Output version information and exit.\n"
|
||||
"\n"
|
||||
|
|
@ -119,8 +121,12 @@ static void usage(bool status) {
|
|||
" restart [tincd options] Restart tincd.\n"
|
||||
" reload Partially reload configuration of running tincd.\n"
|
||||
" pid Show PID of currently running tincd.\n"
|
||||
#ifdef DISABLE_LEGACY
|
||||
" generate-keys Generate a new Ed25519 public/private keypair.\n"
|
||||
#else
|
||||
" generate-keys [bits] Generate new RSA and Ed25519 public/private keypairs.\n"
|
||||
" generate-rsa-keys [bits] Generate a new RSA public/private keypair.\n"
|
||||
#endif
|
||||
" generate-ed25519-keys Generate a new Ed25519 public/private keypair.\n"
|
||||
" dump Dump a list of one of the following things:\n"
|
||||
" [reachable] nodes - all known nodes in the VPN\n"
|
||||
|
|
@ -128,6 +134,7 @@ static void usage(bool status) {
|
|||
" subnets - all known subnets in the VPN\n"
|
||||
" connections - all meta connections with ourself\n"
|
||||
" [di]graph - graph of the VPN in dotty format\n"
|
||||
" invitations - outstanding invitations\n"
|
||||
" info NODE|SUBNET|ADDRESS Give information about a particular NODE, SUBNET or ADDRESS.\n"
|
||||
" purge Purge unreachable nodes\n"
|
||||
" debug N Set debug level\n"
|
||||
|
|
@ -140,12 +147,15 @@ static void usage(bool status) {
|
|||
" log [level] Dump log output [up to the specified level]\n"
|
||||
" export Export host configuration of local node to standard output\n"
|
||||
" export-all Export all host configuration files to standard output\n"
|
||||
" import [--force] Import host configuration file(s) from standard input\n"
|
||||
" exchange [--force] Same as export followed by import\n"
|
||||
" exchange-all [--force] Same as export-all followed by import\n"
|
||||
" import Import host configuration file(s) from standard input\n"
|
||||
" exchange Same as export followed by import\n"
|
||||
" exchange-all Same as export-all followed by import\n"
|
||||
" invite NODE [...] Generate an invitation for NODE\n"
|
||||
" join INVITATION Join a VPN using an INVITIATION\n"
|
||||
" join INVITATION Join a VPN using an INVITATION\n"
|
||||
" network [NETNAME] List all known networks, or switch to the one named NETNAME.\n"
|
||||
" fsck Check the configuration files for problems.\n"
|
||||
" sign [FILE] Generate a signed version of a file.\n"
|
||||
" verify NODE [FILE] Verify that a file was signed by the given NODE.\n"
|
||||
"\n");
|
||||
printf("Report bugs to tinc@tinc-vpn.org.\n");
|
||||
}
|
||||
|
|
@ -225,6 +235,12 @@ FILE *fopenmask(const char *filename, const char *mode, mode_t perms) {
|
|||
perms &= ~mask;
|
||||
umask(~perms);
|
||||
FILE *f = fopen(filename, mode);
|
||||
|
||||
if(!f) {
|
||||
fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FCHMOD
|
||||
if((perms & 0444) && f)
|
||||
fchmod(fileno(f), perms);
|
||||
|
|
@ -314,7 +330,7 @@ static void disable_old_keys(const char *filename, const char *what) {
|
|||
|
||||
static FILE *ask_and_open(const char *filename, const char *what, const char *mode, bool ask, mode_t perms) {
|
||||
FILE *r;
|
||||
char *directory;
|
||||
char directory[PATH_MAX] = ".";
|
||||
char buf[PATH_MAX];
|
||||
char buf2[PATH_MAX];
|
||||
|
||||
|
|
@ -342,7 +358,7 @@ static FILE *ask_and_open(const char *filename, const char *what, const char *mo
|
|||
if(filename[0] != '/') {
|
||||
#endif
|
||||
/* The directory is a relative path or a filename. */
|
||||
directory = get_current_dir_name();
|
||||
getcwd(directory, sizeof directory);
|
||||
snprintf(buf2, sizeof buf2, "%s" SLASH "%s", directory, filename);
|
||||
filename = buf2;
|
||||
}
|
||||
|
|
@ -368,7 +384,7 @@ static FILE *ask_and_open(const char *filename, const char *what, const char *mo
|
|||
static bool ed25519_keygen(bool ask) {
|
||||
ecdsa_t *key;
|
||||
FILE *f;
|
||||
char *pubname, *privname;
|
||||
char fname[PATH_MAX];
|
||||
|
||||
fprintf(stderr, "Generating Ed25519 keypair:\n");
|
||||
|
||||
|
|
@ -378,29 +394,25 @@ static bool ed25519_keygen(bool ask) {
|
|||
} else
|
||||
fprintf(stderr, "Done.\n");
|
||||
|
||||
xasprintf(&privname, "%s" SLASH "ed25519_key.priv", confbase);
|
||||
f = ask_and_open(privname, "private Ed25519 key", "a", ask, 0600);
|
||||
free(privname);
|
||||
snprintf(fname, sizeof fname, "%s" SLASH "ed25519_key.priv", confbase);
|
||||
f = ask_and_open(fname, "private Ed25519 key", "a", ask, 0600);
|
||||
|
||||
if(!f)
|
||||
return false;
|
||||
goto error;
|
||||
|
||||
if(!ecdsa_write_pem_private_key(key, f)) {
|
||||
fprintf(stderr, "Error writing private key!\n");
|
||||
ecdsa_free(key);
|
||||
fclose(f);
|
||||
return false;
|
||||
goto error;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
if(name)
|
||||
xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
|
||||
snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
|
||||
else
|
||||
xasprintf(&pubname, "%s" SLASH "ed25519_key.pub", confbase);
|
||||
snprintf(fname, sizeof fname, "%s" SLASH "ed25519_key.pub", confbase);
|
||||
|
||||
f = ask_and_open(pubname, "public Ed25519 key", "a", ask, 0666);
|
||||
free(pubname);
|
||||
f = ask_and_open(fname, "public Ed25519 key", "a", ask, 0666);
|
||||
|
||||
if(!f)
|
||||
return false;
|
||||
|
|
@ -413,8 +425,15 @@ static bool ed25519_keygen(bool ask) {
|
|||
ecdsa_free(key);
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
if(f)
|
||||
fclose(f);
|
||||
ecdsa_free(key);
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_LEGACY
|
||||
/*
|
||||
Generate a public/private RSA keypair, and ask for a file to store
|
||||
them in.
|
||||
|
|
@ -422,7 +441,7 @@ static bool ed25519_keygen(bool ask) {
|
|||
static bool rsa_keygen(int bits, bool ask) {
|
||||
rsa_t *key;
|
||||
FILE *f;
|
||||
char *pubname, *privname;
|
||||
char fname[PATH_MAX];
|
||||
|
||||
// Make sure the key size is a multiple of 8 bits.
|
||||
bits &= ~0x7;
|
||||
|
|
@ -441,45 +460,46 @@ static bool rsa_keygen(int bits, bool ask) {
|
|||
} else
|
||||
fprintf(stderr, "Done.\n");
|
||||
|
||||
xasprintf(&privname, "%s" SLASH "rsa_key.priv", confbase);
|
||||
f = ask_and_open(privname, "private RSA key", "a", ask, 0600);
|
||||
free(privname);
|
||||
snprintf(fname, sizeof fname, "%s" SLASH "rsa_key.priv", confbase);
|
||||
f = ask_and_open(fname, "private RSA key", "a", ask, 0600);
|
||||
|
||||
if(!f)
|
||||
return false;
|
||||
goto error;
|
||||
|
||||
if(!rsa_write_pem_private_key(key, f)) {
|
||||
fprintf(stderr, "Error writing private key!\n");
|
||||
fclose(f);
|
||||
rsa_free(key);
|
||||
return false;
|
||||
goto error;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
if(name)
|
||||
xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
|
||||
snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
|
||||
else
|
||||
xasprintf(&pubname, "%s" SLASH "rsa_key.pub", confbase);
|
||||
snprintf(fname, sizeof fname, "%s" SLASH "rsa_key.pub", confbase);
|
||||
|
||||
f = ask_and_open(pubname, "public RSA key", "a", ask, 0666);
|
||||
free(pubname);
|
||||
f = ask_and_open(fname, "public RSA key", "a", ask, 0666);
|
||||
|
||||
if(!f)
|
||||
return false;
|
||||
goto error;
|
||||
|
||||
if(!rsa_write_pem_public_key(key, f)) {
|
||||
fprintf(stderr, "Error writing public key!\n");
|
||||
fclose(f);
|
||||
rsa_free(key);
|
||||
return false;
|
||||
goto error;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
rsa_free(key);
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
if(f)
|
||||
fclose(f);
|
||||
rsa_free(key);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
char buffer[4096];
|
||||
size_t blen = 0;
|
||||
|
|
@ -842,6 +862,13 @@ static int cmd_start(int argc, char *argv[]) {
|
|||
}
|
||||
return status;
|
||||
#else
|
||||
int pfd[2] = {-1, -1};
|
||||
if(socketpair(AF_UNIX, SOCK_STREAM, 0, pfd)) {
|
||||
fprintf(stderr, "Could not create umbilical socket: %s\n", strerror(errno));
|
||||
free(nargv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pid_t pid = fork();
|
||||
if(pid == -1) {
|
||||
fprintf(stderr, "Could not fork: %s\n", strerror(errno));
|
||||
|
|
@ -849,8 +876,15 @@ static int cmd_start(int argc, char *argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
if(!pid)
|
||||
if(!pid) {
|
||||
close(pfd[0]);
|
||||
char buf[100] = "";
|
||||
snprintf(buf, sizeof buf, "%d", pfd[1]);
|
||||
setenv("TINC_UMBILICAL", buf, true);
|
||||
exit(execvp(c, nargv));
|
||||
} else {
|
||||
close(pfd[1]);
|
||||
}
|
||||
|
||||
free(nargv);
|
||||
|
||||
|
|
@ -858,12 +892,33 @@ static int cmd_start(int argc, char *argv[]) {
|
|||
#ifdef SIGINT
|
||||
signal(SIGINT, SIG_IGN);
|
||||
#endif
|
||||
|
||||
// Pass all log messages from the umbilical to stderr.
|
||||
// A nul-byte right before closure means tincd started succesfully.
|
||||
bool failure = true;
|
||||
char buf[1024];
|
||||
ssize_t len;
|
||||
|
||||
while((len = read(pfd[0], buf, sizeof buf)) > 0) {
|
||||
failure = buf[len - 1];
|
||||
if(!failure)
|
||||
len--;
|
||||
write(2, buf, len);
|
||||
}
|
||||
|
||||
if(len)
|
||||
failure = true;
|
||||
|
||||
close(pfd[0]);
|
||||
|
||||
// Make sure the child process is really gone.
|
||||
result = waitpid(pid, &status, 0);
|
||||
|
||||
#ifdef SIGINT
|
||||
signal(SIGINT, SIG_DFL);
|
||||
#endif
|
||||
|
||||
if(result != pid || !WIFEXITED(status) || WEXITSTATUS(status)) {
|
||||
if(failure || result != pid || !WIFEXITED(status) || WEXITSTATUS(status)) {
|
||||
fprintf(stderr, "Error starting %s\n", c);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -934,6 +989,65 @@ static int cmd_reload(int argc, char *argv[]) {
|
|||
|
||||
}
|
||||
|
||||
static int dump_invitations(void) {
|
||||
char dname[PATH_MAX];
|
||||
snprintf(dname, sizeof dname, "%s" SLASH "invitations", confbase);
|
||||
DIR *dir = opendir(dname);
|
||||
if(!dir) {
|
||||
if(errno == ENOENT) {
|
||||
fprintf(stderr, "No outstanding invitations.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Cannot not read directory %s: %s\n", dname, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct dirent *ent;
|
||||
bool found = false;
|
||||
|
||||
while((ent = readdir(dir))) {
|
||||
char buf[MAX_STRING_SIZE];
|
||||
if(b64decode(ent->d_name, buf, 24) != 18)
|
||||
continue;
|
||||
|
||||
char fname[PATH_MAX];
|
||||
snprintf(fname, sizeof fname, "%s" SLASH "%s", dname, ent->d_name);
|
||||
FILE *f = fopen(fname, "r");
|
||||
if(!f) {
|
||||
fprintf(stderr, "Cannot open %s: %s\n", fname, strerror(errno));
|
||||
fclose(f);
|
||||
continue;
|
||||
}
|
||||
|
||||
buf[0] = 0;
|
||||
if(!fgets(buf, sizeof buf, f)) {
|
||||
fprintf(stderr, "Invalid invitation file %s", fname);
|
||||
fclose(f);
|
||||
continue;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
char *eol = buf + strlen(buf);
|
||||
while(strchr("\t \r\n", *--eol))
|
||||
*eol = 0;
|
||||
if(strncmp(buf, "Name = ", 7) || !check_id(buf + 7)) {
|
||||
fprintf(stderr, "Invalid invitation file %s", fname);
|
||||
continue;
|
||||
}
|
||||
|
||||
found = true;
|
||||
printf("%s %s\n", ent->d_name, buf + 7);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
|
||||
if(!found)
|
||||
fprintf(stderr, "No outstanding invitations.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_dump(int argc, char *argv[]) {
|
||||
bool only_reachable = false;
|
||||
|
||||
|
|
@ -954,6 +1068,9 @@ static int cmd_dump(int argc, char *argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
if(!strcasecmp(argv[1], "invitations"))
|
||||
return dump_invitations();
|
||||
|
||||
if(!connect_tincd(true))
|
||||
return 1;
|
||||
|
||||
|
|
@ -1316,6 +1433,29 @@ char *get_my_name(bool verbose) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ecdsa_t *get_pubkey(FILE *f) {
|
||||
char buf[4096];
|
||||
char *value;
|
||||
while(fgets(buf, sizeof buf, f)) {
|
||||
int len = strcspn(buf, "\t =");
|
||||
value = buf + len;
|
||||
value += strspn(value, "\t ");
|
||||
if(*value == '=') {
|
||||
value++;
|
||||
value += strspn(value, "\t ");
|
||||
}
|
||||
if(!rstrip(value))
|
||||
continue;
|
||||
buf[len] = 0;
|
||||
if(strcasecmp(buf, "Ed25519PublicKey"))
|
||||
continue;
|
||||
if(*value)
|
||||
return ecdsa_set_base64_public_key(value);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const var_t variables[] = {
|
||||
/* Server configuration */
|
||||
{"AddressFamily", VAR_SERVER},
|
||||
|
|
@ -1358,8 +1498,17 @@ const var_t variables[] = {
|
|||
{"ScriptsInterpreter", VAR_SERVER},
|
||||
{"StrictSubnets", VAR_SERVER},
|
||||
{"TunnelServer", VAR_SERVER},
|
||||
{"UDPDiscovery", VAR_SERVER},
|
||||
{"UDPDiscoveryKeepaliveInterval", VAR_SERVER},
|
||||
{"UDPDiscoveryInterval", VAR_SERVER},
|
||||
{"UDPDiscoveryTimeout", VAR_SERVER},
|
||||
{"MTUInfoInterval", VAR_SERVER},
|
||||
{"UDPInfoInterval", VAR_SERVER},
|
||||
{"UDPRcvBuf", VAR_SERVER},
|
||||
{"UDPSndBuf", VAR_SERVER},
|
||||
{"UPnP", VAR_SERVER},
|
||||
{"UPnPDiscoverWait", VAR_SERVER},
|
||||
{"UPnPRefreshPeriod", VAR_SERVER},
|
||||
{"VDEGroup", VAR_SERVER},
|
||||
{"VDEPort", VAR_SERVER},
|
||||
/* Host configuration */
|
||||
|
|
@ -1519,11 +1668,11 @@ static int cmd_config(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
// Open the right configuration file.
|
||||
char *filename;
|
||||
char filename[PATH_MAX];
|
||||
if(node)
|
||||
xasprintf(&filename, "%s" SLASH "%s", hosts_dir, node);
|
||||
snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, node);
|
||||
else
|
||||
filename = tinc_conf;
|
||||
snprintf(filename, sizeof filename, "%s", tinc_conf);
|
||||
|
||||
FILE *f = fopen(filename, "r");
|
||||
if(!f) {
|
||||
|
|
@ -1531,11 +1680,11 @@ static int cmd_config(int argc, char *argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
char *tmpfile = NULL;
|
||||
char tmpfile[PATH_MAX];
|
||||
FILE *tf = NULL;
|
||||
|
||||
if(action >= -1) {
|
||||
xasprintf(&tmpfile, "%s.config.tmp", filename);
|
||||
snprintf(tmpfile, sizeof tmpfile, "%s.config.tmp", filename);
|
||||
tf = fopen(tmpfile, "w");
|
||||
if(!tf) {
|
||||
fprintf(stderr, "Could not open temporary file %s: %s\n", tmpfile, strerror(errno));
|
||||
|
|
@ -1598,6 +1747,11 @@ static int cmd_config(int argc, char *argv[]) {
|
|||
}
|
||||
set = true;
|
||||
continue;
|
||||
// Add
|
||||
} else if(action > 0) {
|
||||
// Check if we've already seen this variable with the same value
|
||||
if(!strcasecmp(bvalue, value))
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1630,7 +1784,7 @@ static int cmd_config(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
// Add new variable if necessary.
|
||||
if(action > 0 || (action == 0 && !set)) {
|
||||
if((action > 0 && !found)|| (action == 0 && !set)) {
|
||||
if(fprintf(tf, "%s = %s\n", variable, value) < 0) {
|
||||
fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno));
|
||||
return 1;
|
||||
|
|
@ -1679,7 +1833,7 @@ static int cmd_config(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
static bool try_bind(int port) {
|
||||
struct addrinfo *ai = NULL;
|
||||
struct addrinfo *ai = NULL, *aip;
|
||||
struct addrinfo hint = {
|
||||
.ai_flags = AI_PASSIVE,
|
||||
.ai_family = AF_UNSPEC,
|
||||
|
|
@ -1687,24 +1841,30 @@ static bool try_bind(int port) {
|
|||
.ai_protocol = IPPROTO_TCP,
|
||||
};
|
||||
|
||||
bool success = true;
|
||||
char portstr[16];
|
||||
snprintf(portstr, sizeof portstr, "%d", port);
|
||||
|
||||
if(getaddrinfo(NULL, portstr, &hint, &ai) || !ai)
|
||||
return false;
|
||||
|
||||
while(ai) {
|
||||
for(aip = ai; aip; aip = aip->ai_next) {
|
||||
int fd = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP);
|
||||
if(!fd)
|
||||
return false;
|
||||
if(!fd) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
int result = bind(fd, ai->ai_addr, ai->ai_addrlen);
|
||||
closesocket(fd);
|
||||
if(result)
|
||||
return false;
|
||||
ai = ai->ai_next;
|
||||
if(result) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
freeaddrinfo(ai);
|
||||
return success;
|
||||
}
|
||||
|
||||
int check_port(char *name) {
|
||||
|
|
@ -1716,11 +1876,11 @@ int check_port(char *name) {
|
|||
for(int i = 0; i < 100; i++) {
|
||||
int port = 0x1000 + (rand() & 0x7fff);
|
||||
if(try_bind(port)) {
|
||||
char *filename;
|
||||
xasprintf(&filename, "%s" SLASH "hosts" SLASH "%s", confbase, name);
|
||||
char filename[PATH_MAX];
|
||||
snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", confbase, name);
|
||||
FILE *f = fopen(filename, "a");
|
||||
free(filename);
|
||||
if(!f) {
|
||||
fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
|
||||
fprintf(stderr, "Please change tinc's Port manually.\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1800,14 +1960,19 @@ static int cmd_init(int argc, char *argv[]) {
|
|||
fprintf(f, "Name = %s\n", name);
|
||||
fclose(f);
|
||||
|
||||
if(!rsa_keygen(2048, false) || !ed25519_keygen(false))
|
||||
#ifndef DISABLE_LEGACY
|
||||
if(!rsa_keygen(2048, false))
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
if(!ed25519_keygen(false))
|
||||
return 1;
|
||||
|
||||
check_port(name);
|
||||
|
||||
#ifndef HAVE_MINGW
|
||||
char *filename;
|
||||
xasprintf(&filename, "%s" SLASH "tinc-up", confbase);
|
||||
char filename[PATH_MAX];
|
||||
snprintf(filename, sizeof filename, "%s" SLASH "tinc-up", confbase);
|
||||
if(access(filename, F_OK)) {
|
||||
FILE *f = fopenmask(filename, "w", 0777);
|
||||
if(!f) {
|
||||
|
|
@ -1824,7 +1989,11 @@ static int cmd_init(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
static int cmd_generate_keys(int argc, char *argv[]) {
|
||||
#ifdef DISABLE_LEGACY
|
||||
if(argc > 1) {
|
||||
#else
|
||||
if(argc > 2) {
|
||||
#endif
|
||||
fprintf(stderr, "Too many arguments!\n");
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -1832,9 +2001,18 @@ static int cmd_generate_keys(int argc, char *argv[]) {
|
|||
if(!name)
|
||||
name = get_my_name(false);
|
||||
|
||||
return !(rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true) && ed25519_keygen(true));
|
||||
#ifndef DISABLE_LEGACY
|
||||
if(!rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true))
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
if(!ed25519_keygen(true))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_LEGACY
|
||||
static int cmd_generate_rsa_keys(int argc, char *argv[]) {
|
||||
if(argc > 2) {
|
||||
fprintf(stderr, "Too many arguments!\n");
|
||||
|
|
@ -1846,6 +2024,7 @@ static int cmd_generate_rsa_keys(int argc, char *argv[]) {
|
|||
|
||||
return !rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int cmd_generate_ed25519_keys(int argc, char *argv[]) {
|
||||
if(argc > 1) {
|
||||
|
|
@ -1903,12 +2082,12 @@ static int cmd_edit(int argc, char *argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
char *filename = NULL;
|
||||
char filename[PATH_MAX] = "";
|
||||
|
||||
if(strncmp(argv[1], "hosts" SLASH, 6)) {
|
||||
for(int i = 0; conffiles[i]; i++) {
|
||||
if(!strcmp(argv[1], conffiles[i])) {
|
||||
xasprintf(&filename, "%s" SLASH "%s", confbase, argv[1]);
|
||||
snprintf(filename, sizeof filename, "%s" SLASH "%s", confbase, argv[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1916,8 +2095,8 @@ static int cmd_edit(int argc, char *argv[]) {
|
|||
argv[1] += 6;
|
||||
}
|
||||
|
||||
if(!filename) {
|
||||
xasprintf(&filename, "%s" SLASH "%s", hosts_dir, argv[1]);
|
||||
if(!*filename) {
|
||||
snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, argv[1]);
|
||||
char *dash = strchr(argv[1], '-');
|
||||
if(dash) {
|
||||
*dash++ = 0;
|
||||
|
|
@ -1935,6 +2114,7 @@ static int cmd_edit(int argc, char *argv[]) {
|
|||
xasprintf(&command, "edit \"%s\"", filename);
|
||||
#endif
|
||||
int result = system(command);
|
||||
free(command);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
|
@ -1946,8 +2126,8 @@ static int cmd_edit(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
static int export(const char *name, FILE *out) {
|
||||
char *filename;
|
||||
xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name);
|
||||
char filename[PATH_MAX];
|
||||
snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, name);
|
||||
FILE *in = fopen(filename, "r");
|
||||
if(!in) {
|
||||
fprintf(stderr, "Could not open configuration file %s: %s\n", filename, strerror(errno));
|
||||
|
|
@ -2034,7 +2214,7 @@ static int cmd_import(int argc, char *argv[]) {
|
|||
|
||||
char buf[4096];
|
||||
char name[4096];
|
||||
char *filename = NULL;
|
||||
char filename[PATH_MAX] = "";
|
||||
int count = 0;
|
||||
bool firstline = true;
|
||||
|
||||
|
|
@ -2050,8 +2230,7 @@ static int cmd_import(int argc, char *argv[]) {
|
|||
if(out)
|
||||
fclose(out);
|
||||
|
||||
free(filename);
|
||||
xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name);
|
||||
snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, name);
|
||||
|
||||
if(!force && !access(filename, F_OK)) {
|
||||
fprintf(stderr, "Host configuration file %s already exists, skipping.\n", filename);
|
||||
|
|
@ -2105,27 +2284,29 @@ static int cmd_exchange_all(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
static int switch_network(char *name) {
|
||||
if(strcmp(name, ".")) {
|
||||
if(!check_netname(name, false)) {
|
||||
fprintf(stderr, "Invalid character in netname!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!check_netname(name, true))
|
||||
fprintf(stderr, "Warning: unsafe character in netname!\n");
|
||||
}
|
||||
|
||||
if(fd >= 0) {
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
free(confbase);
|
||||
confbase = NULL;
|
||||
free(pidfilename);
|
||||
pidfilename = NULL;
|
||||
free(logfilename);
|
||||
logfilename = NULL;
|
||||
free(unixsocketname);
|
||||
unixsocketname = NULL;
|
||||
free_names();
|
||||
netname = strcmp(name, ".") ? xstrdup(name) : NULL;
|
||||
make_names(false);
|
||||
|
||||
free(tinc_conf);
|
||||
free(hosts_dir);
|
||||
free(prompt);
|
||||
|
||||
free(netname);
|
||||
netname = strcmp(name, ".") ? xstrdup(name) : NULL;
|
||||
|
||||
make_names();
|
||||
xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
|
||||
xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
|
||||
xasprintf(&prompt, "%s> ", identname);
|
||||
|
|
@ -2158,11 +2339,10 @@ static int cmd_network(int argc, char *argv[]) {
|
|||
continue;
|
||||
}
|
||||
|
||||
char *fname;
|
||||
xasprintf(&fname, "%s/%s/tinc.conf", confdir, ent->d_name);
|
||||
char fname[PATH_MAX];
|
||||
snprintf(fname, sizeof fname, "%s/%s/tinc.conf", confdir, ent->d_name);
|
||||
if(!access(fname, R_OK))
|
||||
printf("%s\n", ent->d_name);
|
||||
free(fname);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
|
|
@ -2170,6 +2350,240 @@ static int cmd_network(int argc, char *argv[]) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_fsck(int argc, char *argv[]) {
|
||||
if(argc > 1) {
|
||||
fprintf(stderr, "Too many arguments!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return fsck(orig_argv[0]);
|
||||
}
|
||||
|
||||
static void *readfile(FILE *in, size_t *len) {
|
||||
size_t count = 0;
|
||||
size_t alloced = 4096;
|
||||
char *buf = xmalloc(alloced);
|
||||
|
||||
while(!feof(in)) {
|
||||
size_t read = fread(buf + count, 1, alloced - count, in);
|
||||
if(!read)
|
||||
break;
|
||||
count += read;
|
||||
if(count >= alloced) {
|
||||
alloced *= 2;
|
||||
buf = xrealloc(buf, alloced);
|
||||
}
|
||||
}
|
||||
|
||||
if(len)
|
||||
*len = count;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int cmd_sign(int argc, char *argv[]) {
|
||||
if(argc > 2) {
|
||||
fprintf(stderr, "Too many arguments!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!name) {
|
||||
name = get_my_name(true);
|
||||
if(!name)
|
||||
return 1;
|
||||
}
|
||||
|
||||
char fname[PATH_MAX];
|
||||
snprintf(fname, sizeof fname, "%s" SLASH "ed25519_key.priv", confbase);
|
||||
FILE *fp = fopen(fname, "r");
|
||||
if(!fp) {
|
||||
fprintf(stderr, "Could not open %s: %s\n", fname, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
ecdsa_t *key = ecdsa_read_pem_private_key(fp);
|
||||
|
||||
if(!key) {
|
||||
fprintf(stderr, "Could not read private key from %s\n", fname);
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
FILE *in;
|
||||
|
||||
if(argc == 2) {
|
||||
in = fopen(argv[1], "rb");
|
||||
if(!in) {
|
||||
fprintf(stderr, "Could not open %s: %s\n", argv[1], strerror(errno));
|
||||
ecdsa_free(key);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
in = stdin;
|
||||
}
|
||||
|
||||
size_t len;
|
||||
char *data = readfile(in, &len);
|
||||
if(in != stdin)
|
||||
fclose(in);
|
||||
if(!data) {
|
||||
fprintf(stderr, "Error reading %s: %s\n", argv[1], strerror(errno));
|
||||
ecdsa_free(key);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Ensure we sign our name and current time as well
|
||||
long t = time(NULL);
|
||||
char *trailer;
|
||||
xasprintf(&trailer, " %s %ld", name, t);
|
||||
int trailer_len = strlen(trailer);
|
||||
|
||||
data = xrealloc(data, len + trailer_len);
|
||||
memcpy(data + len, trailer, trailer_len);
|
||||
free(trailer);
|
||||
|
||||
char sig[87];
|
||||
if(!ecdsa_sign(key, data, len + trailer_len, sig)) {
|
||||
fprintf(stderr, "Error generating signature\n");
|
||||
free(data);
|
||||
ecdsa_free(key);
|
||||
return 1;
|
||||
}
|
||||
b64encode(sig, sig, 64);
|
||||
ecdsa_free(key);
|
||||
|
||||
fprintf(stdout, "Signature = %s %ld %s\n", name, t, sig);
|
||||
fwrite(data, len, 1, stdout);
|
||||
|
||||
free(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_verify(int argc, char *argv[]) {
|
||||
if(argc < 2) {
|
||||
fprintf(stderr, "Not enough arguments!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(argc > 3) {
|
||||
fprintf(stderr, "Too many arguments!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *node = argv[1];
|
||||
if(!strcmp(node, ".")) {
|
||||
if(!name) {
|
||||
name = get_my_name(true);
|
||||
if(!name)
|
||||
return 1;
|
||||
}
|
||||
node = name;
|
||||
} else if(!strcmp(node, "*")) {
|
||||
node = NULL;
|
||||
} else {
|
||||
if(!check_id(node)) {
|
||||
fprintf(stderr, "Invalid node name\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
FILE *in;
|
||||
|
||||
if(argc == 3) {
|
||||
in = fopen(argv[2], "rb");
|
||||
if(!in) {
|
||||
fprintf(stderr, "Could not open %s: %s\n", argv[2], strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
in = stdin;
|
||||
}
|
||||
|
||||
size_t len;
|
||||
char *data = readfile(in, &len);
|
||||
if(in != stdin)
|
||||
fclose(in);
|
||||
if(!data) {
|
||||
fprintf(stderr, "Error reading %s: %s\n", argv[1], strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *newline = memchr(data, '\n', len);
|
||||
if(!newline || (newline - data > MAX_STRING_SIZE - 1)) {
|
||||
fprintf(stderr, "Invalid input\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
*newline++ = '\0';
|
||||
size_t skip = newline - data;
|
||||
|
||||
char signer[MAX_STRING_SIZE] = "";
|
||||
char sig[MAX_STRING_SIZE] = "";
|
||||
long t = 0;
|
||||
|
||||
if(sscanf(data, "Signature = %s %ld %s", signer, &t, sig) != 3 || strlen(sig) != 86 || !t || !check_id(signer)) {
|
||||
fprintf(stderr, "Invalid input\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(node && strcmp(node, signer)) {
|
||||
fprintf(stderr, "Signature is not made by %s\n", node);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!node)
|
||||
node = signer;
|
||||
|
||||
char *trailer;
|
||||
xasprintf(&trailer, " %s %ld", signer, t);
|
||||
int trailer_len = strlen(trailer);
|
||||
|
||||
data = xrealloc(data, len + trailer_len);
|
||||
memcpy(data + len, trailer, trailer_len);
|
||||
free(trailer);
|
||||
|
||||
newline = data + skip;
|
||||
|
||||
char fname[PATH_MAX];
|
||||
snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, node);
|
||||
FILE *fp = fopen(fname, "r");
|
||||
if(!fp) {
|
||||
fprintf(stderr, "Could not open %s: %s\n", fname, strerror(errno));
|
||||
free(data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ecdsa_t *key = get_pubkey(fp);
|
||||
if(!key) {
|
||||
rewind(fp);
|
||||
key = ecdsa_read_pem_public_key(fp);
|
||||
}
|
||||
if(!key) {
|
||||
fprintf(stderr, "Could not read public key from %s\n", fname);
|
||||
fclose(fp);
|
||||
free(data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
if(b64decode(sig, sig, 86) != 64 || !ecdsa_verify(key, newline, len + trailer_len - (newline - data), sig)) {
|
||||
fprintf(stderr, "Invalid signature\n");
|
||||
free(data);
|
||||
ecdsa_free(key);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ecdsa_free(key);
|
||||
|
||||
fwrite(newline, len - (newline - data), 1, stdout);
|
||||
|
||||
free(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
const char *command;
|
||||
int (*function)(int argc, char *argv[]);
|
||||
|
|
@ -2180,6 +2594,7 @@ static const struct {
|
|||
{"restart", cmd_restart},
|
||||
{"reload", cmd_reload},
|
||||
{"dump", cmd_dump},
|
||||
{"list", cmd_dump},
|
||||
{"purge", cmd_purge},
|
||||
{"debug", cmd_debug},
|
||||
{"retry", cmd_retry},
|
||||
|
|
@ -2196,7 +2611,9 @@ static const struct {
|
|||
{"set", cmd_config},
|
||||
{"init", cmd_init},
|
||||
{"generate-keys", cmd_generate_keys},
|
||||
#ifndef DISABLE_LEGACY
|
||||
{"generate-rsa-keys", cmd_generate_rsa_keys},
|
||||
#endif
|
||||
{"generate-ed25519-keys", cmd_generate_ed25519_keys},
|
||||
{"help", cmd_help},
|
||||
{"version", cmd_version},
|
||||
|
|
@ -2210,6 +2627,9 @@ static const struct {
|
|||
{"invite", cmd_invite},
|
||||
{"join", cmd_join},
|
||||
{"network", cmd_network},
|
||||
{"fsck", cmd_fsck},
|
||||
{"sign", cmd_sign},
|
||||
{"verify", cmd_verify},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
|
|
@ -2444,7 +2864,7 @@ int main(int argc, char *argv[]) {
|
|||
if(!parse_options(argc, argv))
|
||||
return 1;
|
||||
|
||||
make_names();
|
||||
make_names(false);
|
||||
xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
|
||||
xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
tincctl.h -- header for tincctl.c.
|
||||
Copyright (C) 2011-2013 Guus Sliepen <guus@tinc-vpn.org>
|
||||
Copyright (C) 2011-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -21,6 +21,7 @@
|
|||
#define __TINC_TINCCTL_H__
|
||||
|
||||
extern bool tty;
|
||||
extern bool force;
|
||||
extern char line[4096];
|
||||
extern int fd;
|
||||
extern char buffer[4096];
|
||||
|
|
@ -49,6 +50,7 @@ extern bool sendline(int fd, char *format, ...);
|
|||
extern bool recvline(int fd, char *line, size_t len);
|
||||
extern int check_port(char *name);
|
||||
extern FILE *fopenmask(const char *filename, const char *mode, mode_t perms);
|
||||
extern ecdsa_t *get_pubkey(FILE *f);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
47
src/tincd.c
47
src/tincd.c
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
tincd.c -- the main file for tincd
|
||||
Copyright (C) 1998-2005 Ivo Timmermans
|
||||
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2008 Max Rijevski <maksuf@gmail.com>
|
||||
2009 Michael Tokarev <mjt@tls.msk.ru>
|
||||
2010 Julien Muchembled <jm@jmuchemb.eu>
|
||||
|
|
@ -43,8 +43,6 @@
|
|||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
#include "conf.h"
|
||||
#include "control.h"
|
||||
#include "crypto.h"
|
||||
|
|
@ -85,6 +83,9 @@ static const char *switchuser = NULL;
|
|||
/* If nonzero, write log entries to a separate file. */
|
||||
bool use_logfile = false;
|
||||
|
||||
/* If nonzero, use syslog instead of stderr in no-detach mode. */
|
||||
bool use_syslog = false;
|
||||
|
||||
char **g_argv; /* a copy of the cmdline arguments */
|
||||
|
||||
static int status = 1;
|
||||
|
|
@ -101,6 +102,7 @@ static struct option const long_options[] = {
|
|||
{"chroot", no_argument, NULL, 'R'},
|
||||
{"user", required_argument, NULL, 'U'},
|
||||
{"logfile", optional_argument, NULL, 4},
|
||||
{"syslog", no_argument, NULL, 's'},
|
||||
{"pidfile", required_argument, NULL, 5},
|
||||
{"option", required_argument, NULL, 'o'},
|
||||
{NULL, 0, NULL, 0}
|
||||
|
|
@ -125,6 +127,7 @@ static void usage(bool status) {
|
|||
" -L, --mlock Lock tinc into main memory.\n"
|
||||
#endif
|
||||
" --logfile[=FILENAME] Write log entries to a logfile.\n"
|
||||
" -s --syslog Use syslog instead of stderr with --no-detach.\n"
|
||||
" --pidfile=FILENAME Write PID and control socket cookie to FILENAME.\n"
|
||||
" --bypass-security Disables meta protocol security, for debugging.\n"
|
||||
" -o, --option[HOST.]KEY=VALUE Set global/host configuration value.\n"
|
||||
|
|
@ -146,7 +149,7 @@ static bool parse_options(int argc, char **argv) {
|
|||
|
||||
cmdline_conf = list_alloc((list_action_t)free_config);
|
||||
|
||||
while((r = getopt_long(argc, argv, "c:DLd::n:o:RU:", long_options, &option_index)) != EOF) {
|
||||
while((r = getopt_long(argc, argv, "c:DLd::n:so:RU:", long_options, &option_index)) != EOF) {
|
||||
switch (r) {
|
||||
case 0: /* long option */
|
||||
break;
|
||||
|
|
@ -181,6 +184,11 @@ static bool parse_options(int argc, char **argv) {
|
|||
netname = xstrdup(optarg);
|
||||
break;
|
||||
|
||||
case 's': /* syslog */
|
||||
use_logfile = false;
|
||||
use_syslog = true;
|
||||
break;
|
||||
|
||||
case 'o': /* option */
|
||||
cfg = parse_config_line(optarg, NULL, ++lineno);
|
||||
if (!cfg)
|
||||
|
|
@ -216,6 +224,7 @@ static bool parse_options(int argc, char **argv) {
|
|||
break;
|
||||
|
||||
case 4: /* write log entries to a file */
|
||||
use_syslog = false;
|
||||
use_logfile = true;
|
||||
if(!optarg && optind < argc && *argv[optind] != '-')
|
||||
optarg = argv[optind++];
|
||||
|
|
@ -252,11 +261,14 @@ static bool parse_options(int argc, char **argv) {
|
|||
netname = NULL;
|
||||
}
|
||||
|
||||
if(netname && (strpbrk(netname, "\\/") || *netname == '.')) {
|
||||
if(netname && !check_netname(netname, false)) {
|
||||
fprintf(stderr, "Invalid character in netname!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(netname && !check_netname(netname, true))
|
||||
fprintf(stderr, "Warning: unsafe character in netname!\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -328,12 +340,13 @@ int main(int argc, char **argv) {
|
|||
if(!parse_options(argc, argv))
|
||||
return 1;
|
||||
|
||||
make_names();
|
||||
make_names(true);
|
||||
chdir(confbase);
|
||||
|
||||
if(show_version) {
|
||||
printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
|
||||
VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
|
||||
printf("Copyright (C) 1998-2014 Ivo Timmermans, Guus Sliepen and others.\n"
|
||||
BUILD_VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
|
||||
printf("Copyright (C) 1998-2016 Ivo Timmermans, Guus Sliepen and others.\n"
|
||||
"See the AUTHORS file for a complete list.\n\n"
|
||||
"tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
|
||||
"and you are welcome to redistribute it under certain conditions;\n"
|
||||
|
|
@ -352,6 +365,18 @@ int main(int argc, char **argv) {
|
|||
logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "WSAStartup", winerror(GetLastError()));
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
// Check if we got an umbilical fd from the process that started us
|
||||
char *umbstr = getenv("TINC_UMBILICAL");
|
||||
if(umbstr) {
|
||||
umbilical = atoi(umbstr);
|
||||
if(fcntl(umbilical, F_GETFL) < 0)
|
||||
umbilical = 0;
|
||||
#ifdef FD_CLOEXEC
|
||||
if(umbilical)
|
||||
fcntl(umbilical, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
openlogger("tinc", use_logfile?LOGMODE_FILE:LOGMODE_STDERR);
|
||||
|
|
@ -455,6 +480,12 @@ int main2(int argc, char **argv) {
|
|||
|
||||
logger(DEBUG_ALWAYS, LOG_NOTICE, "Ready");
|
||||
|
||||
if(umbilical) { // snip!
|
||||
write(umbilical, "", 1);
|
||||
close(umbilical);
|
||||
umbilical = 0;
|
||||
}
|
||||
|
||||
try_outgoing_connections();
|
||||
|
||||
status = main_loop();
|
||||
|
|
|
|||
164
src/upnp.c
Normal file
164
src/upnp.c
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
upnp.c -- UPnP-IGD client
|
||||
Copyright (C) 2015 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 "upnp.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "miniupnpc/miniupnpc.h"
|
||||
#include "miniupnpc/upnpcommands.h"
|
||||
#include "miniupnpc/upnperrors.h"
|
||||
|
||||
#include "system.h"
|
||||
#include "logger.h"
|
||||
#include "names.h"
|
||||
#include "net.h"
|
||||
#include "netutl.h"
|
||||
#include "utils.h"
|
||||
|
||||
static bool upnp_tcp;
|
||||
static bool upnp_udp;
|
||||
static int upnp_discover_wait = 5;
|
||||
static int upnp_refresh_period = 60;
|
||||
|
||||
// Unfortunately, libminiupnpc devs don't seem to care about API compatibility,
|
||||
// and there are slight changes to function signatures between library versions.
|
||||
// Well, at least they publish a "MINIUPNPC_API_VERSION" constant, so we got that going for us, which is nice.
|
||||
// Differences between API versions are documented in "apiversions.txt" in the libminiupnpc distribution.
|
||||
|
||||
#ifndef MINIUPNPC_API_VERSION
|
||||
#define MINIUPNPC_API_VERSION 0
|
||||
#endif
|
||||
|
||||
static struct UPNPDev *upnp_discover(int delay, int *error) {
|
||||
#if MINIUPNPC_API_VERSION <= 13
|
||||
|
||||
#if MINIUPNPC_API_VERSION < 8
|
||||
#warning "The version of libminiupnpc you're building against seems to be too old. Expect trouble."
|
||||
#endif
|
||||
|
||||
return upnpDiscover(delay, NULL, NULL, false, false, error);
|
||||
|
||||
#elif MINIUPNPC_API_VERSION <= 14
|
||||
|
||||
return upnpDiscover(delay, NULL NULL, false, false, 2, error);
|
||||
|
||||
#else
|
||||
|
||||
#if MINIUPNPC_API_VERSION > 15
|
||||
#warning "The version of libminiupnpc you're building against seems to be too recent. Expect trouble."
|
||||
#endif
|
||||
|
||||
return upnpDiscover(delay, NULL, NULL, UPNP_LOCAL_PORT_ANY, false, 2, error);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static void upnp_add_mapping(struct UPNPUrls *urls, struct IGDdatas *data, const char *myaddr, int socket, const char *proto) {
|
||||
// Extract the port from the listening socket.
|
||||
// Note that we can't simply use listen_socket[].sa because this won't have the port
|
||||
// if we're running with Port=0 (dynamically assigned port).
|
||||
sockaddr_t sa;
|
||||
socklen_t salen = sizeof sa;
|
||||
if (getsockname(socket, &sa.sa, &salen)) {
|
||||
logger(DEBUG_PROTOCOL, LOG_ERR, "[upnp] Unable to get socket address: [%d] %s", sockerrno, sockstrerror(sockerrno));
|
||||
return;
|
||||
}
|
||||
char *port;
|
||||
sockaddr2str(&sa, NULL, &port);
|
||||
if (!port) {
|
||||
logger(DEBUG_PROTOCOL, LOG_ERR, "[upnp] Unable to get socket port");
|
||||
return;
|
||||
}
|
||||
|
||||
// Use a lease twice as long as the refresh period so that the mapping won't expire before we refresh.
|
||||
char lease_duration[16];
|
||||
snprintf(lease_duration, sizeof lease_duration, "%d", upnp_refresh_period * 2);
|
||||
|
||||
int error = UPNP_AddPortMapping(urls->controlURL, data->first.servicetype, port, port, myaddr, identname, proto, NULL, lease_duration);
|
||||
if (error == 0) {
|
||||
logger(DEBUG_PROTOCOL, LOG_INFO, "[upnp] Successfully set port mapping (%s:%s %s for %s seconds)", myaddr, port, proto, lease_duration);
|
||||
} else {
|
||||
logger(DEBUG_PROTOCOL, LOG_ERR, "[upnp] Failed to set port mapping (%s:%s %s for %s seconds): [%d] %s", myaddr, port, proto, lease_duration, error, strupnperror(error));
|
||||
}
|
||||
|
||||
free(port);
|
||||
}
|
||||
|
||||
static void upnp_refresh() {
|
||||
logger(DEBUG_PROTOCOL, LOG_INFO, "[upnp] Discovering IGD devices");
|
||||
|
||||
int error;
|
||||
struct UPNPDev *devices = upnp_discover(upnp_discover_wait * 1000, &error);
|
||||
if (!devices) {
|
||||
logger(DEBUG_PROTOCOL, LOG_WARNING, "[upnp] Unable to find IGD devices: [%d] %s", error, strupnperror(error));
|
||||
freeUPNPDevlist(devices);
|
||||
return;
|
||||
}
|
||||
|
||||
struct UPNPUrls urls;
|
||||
struct IGDdatas data;
|
||||
char myaddr[64];
|
||||
int result = UPNP_GetValidIGD(devices, &urls, &data, myaddr, sizeof myaddr);
|
||||
if (result <= 0) {
|
||||
logger(DEBUG_PROTOCOL, LOG_WARNING, "[upnp] No IGD found");
|
||||
freeUPNPDevlist(devices);
|
||||
return;
|
||||
}
|
||||
logger(DEBUG_PROTOCOL, LOG_INFO, "[upnp] IGD found: [%d] %s (local address: %s, service type: %s)", result, urls.controlURL, myaddr, data.first.servicetype);
|
||||
|
||||
for (int i = 0; i < listen_sockets; i++) {
|
||||
if (upnp_tcp) upnp_add_mapping(&urls, &data, myaddr, listen_socket[i].tcp.fd, "TCP");
|
||||
if (upnp_udp) upnp_add_mapping(&urls, &data, myaddr, listen_socket[i].udp.fd, "UDP");
|
||||
}
|
||||
|
||||
FreeUPNPUrls(&urls);
|
||||
freeUPNPDevlist(devices);
|
||||
}
|
||||
|
||||
static void *upnp_thread(void *data) {
|
||||
while (true) {
|
||||
time_t start = time(NULL);
|
||||
upnp_refresh();
|
||||
|
||||
// Make sure we'll stick to the refresh period no matter how long upnp_refresh() takes.
|
||||
time_t refresh_time = start + upnp_refresh_period;
|
||||
time_t now = time(NULL);
|
||||
if (now < refresh_time) sleep(refresh_time - now);
|
||||
}
|
||||
|
||||
// TODO: we don't have a clean thread shutdown procedure, so we can't remove the mapping.
|
||||
// this is probably not a concern as long as the UPnP device honors the lease duration,
|
||||
// but considering how bug-riddled these devices often are, that's a big "if".
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void upnp_init(bool tcp, bool udp) {
|
||||
upnp_tcp = tcp;
|
||||
upnp_udp = udp;
|
||||
|
||||
get_config_int(lookup_config(config_tree, "UPnPDiscoverWait"), &upnp_discover_wait);
|
||||
get_config_int(lookup_config(config_tree, "UPnPRefreshPeriod"), &upnp_refresh_period);
|
||||
|
||||
pthread_t thread;
|
||||
int error = pthread_create(&thread, NULL, upnp_thread, NULL);
|
||||
if (error) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to start UPnP-IGD client thread: [%d] %s", error, strerror(error));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
ecdsagen.c -- ECDSA key generation and export
|
||||
Copyright (C) 2011-2013 Guus Sliepen <guus@tinc-vpn.org>
|
||||
upnp.h -- UPnP-IGD client
|
||||
Copyright (C) 2015 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
|
||||
|
|
@ -17,25 +17,11 @@
|
|||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
#ifndef __UPNP_H__
|
||||
#define __UPNP_H__
|
||||
|
||||
#include "../ecdsagen.h"
|
||||
#include "../utils.h"
|
||||
#include "../xalloc.h"
|
||||
#include "system.h"
|
||||
|
||||
// Generate ECDSA key
|
||||
extern void upnp_init(bool, bool);
|
||||
|
||||
ecdsa_t *ecdsa_generate(void) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "EC support using libgcrypt not implemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Write PEM ECDSA keys
|
||||
|
||||
bool ecdsa_write_pem_public_key(ecdsa_t *ecdsa, FILE *fp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ecdsa_write_pem_private_key(ecdsa_t *ecdsa, FILE *fp) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
18
src/utils.c
18
src/utils.c
|
|
@ -158,7 +158,7 @@ int b64encode_urlsafe(const void *src, char *dst, int length) {
|
|||
const char *winerror(int err) {
|
||||
static char buf[1024], *ptr;
|
||||
|
||||
ptr = buf + sprintf(buf, "(%d) ", err);
|
||||
ptr = buf + snprintf(buf, sizeof buf, "(%d) ", err);
|
||||
|
||||
if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), ptr, sizeof(buf) - (ptr - buf), NULL)) {
|
||||
|
|
@ -191,6 +191,22 @@ bool check_id(const char *id) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool check_netname(const char *netname, bool strict) {
|
||||
if(!netname || !*netname || *netname == '.')
|
||||
return false;
|
||||
|
||||
for(const char *c = netname; *c; c++) {
|
||||
if(iscntrl(*c))
|
||||
return false;
|
||||
if(*c == '/' || *c == '\\')
|
||||
return false;
|
||||
if(strict && strchr(" $%<>:`\"|?*", *c))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Windows doesn't define HOST_NAME_MAX. */
|
||||
#ifndef HOST_NAME_MAX
|
||||
#define HOST_NAME_MAX 255
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ extern const char *winerror(int);
|
|||
extern unsigned int bitfield_to_int(const void *bitfield, size_t size);
|
||||
|
||||
extern bool check_id(const char *);
|
||||
extern bool check_netname(const char *, bool strict);
|
||||
char *replace_name(const char *name);
|
||||
|
||||
#endif /* __TINC_UTILS_H__ */
|
||||
|
|
|
|||
|
|
@ -18,7 +18,14 @@
|
|||
*/
|
||||
|
||||
#include "version.h"
|
||||
#include "version_git.h"
|
||||
#include "../config.h"
|
||||
|
||||
/* This file is always rebuilt (even if there are no changes) so that the following is updated */
|
||||
const char* const BUILD_DATE = __DATE__;
|
||||
const char* const BUILD_TIME = __TIME__;
|
||||
#ifdef GIT_DESCRIPTION
|
||||
const char* const BUILD_VERSION = GIT_DESCRIPTION;
|
||||
#else
|
||||
const char* const BUILD_VERSION = VERSION;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -22,5 +22,6 @@
|
|||
|
||||
extern const char* const BUILD_DATE;
|
||||
extern const char* const BUILD_TIME;
|
||||
extern const char* const BUILD_VERSION;
|
||||
|
||||
#endif /* __TINC_VERSION_H__ */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue