Compare commits

..

25 commits

Author SHA1 Message Date
lagertonne
3189f2ad9c Trying to apply patches...
Some checks failed
continuous-integration/drone/push Build is failing
2022-04-25 13:50:45 +02:00
lagertonne
8e732eefc2 Make patches more flat
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-25 13:36:15 +02:00
lagertonne
d787d2479a Add patches for alternative ciphersuite
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-25 13:11:44 +02:00
lagertonne
56d25e7bd6 fix broken focal build
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-23 15:45:38 +02:00
lagertonne
093206d6f2 Make package installation noninteractive
Some checks failed
continuous-integration/drone/push Build is failing
2022-04-23 15:37:43 +02:00
lagertonne
5a8168ab4c Add focal building
Some checks reported errors
continuous-integration/drone/push Build was killed
2022-04-23 15:18:13 +02:00
lagertonne
ce9368f414 Add .drone.yml
All checks were successful
continuous-integration/drone/push Build is passing
2022-04-23 10:57:20 +02:00
lagertonne
bb0afc8780 Add debian files 2022-04-23 10:57:20 +02:00
lagertonne
cf5509bd45 upstream: 1.18 2022-04-23 10:57:20 +02:00
Shengjing Zhu
8e468ffc54 Import Debian changes 1.1~pre17-1.1
tinc (1.1~pre17-1.1) experimental; urgency=medium

  * Non-maintainer upload.
  * Fix systemd service install path. Closes: #910618
  * Fix typo in --enable-miniupnpc option.
2019-08-26 13:44:53 +02:00
Guus Sliepen
150c40db86 Import Debian changes 1.1~pre17-1
tinc (1.1~pre17-1) experimental; urgency=medium

  * New upstream release.
    - Includes fixes for CVE-2018-16737, CVE-2018-16738.
    - The GUI is no longer part of upstream, so has been removed.
  * Link with the miniupnpc library.
  * Bump Standards-Version.
  * Bump debian/compat.
2019-08-26 13:44:53 +02:00
Guus Sliepen
46616ac501 Import Debian changes 1.1~pre15-1
tinc (1.1~pre15-1) experimental; urgency=medium

  * New upstream release.
  * Bump Standards-Version.
  * Bump debian/compat.
  * Don't use while loops checking PID files anymore, the tinc CLI will
    wait properly for the daemon to start or stop. Closes: #772379, #832784
  * Clean up scripts as suggested by Dominik George. Closes: #832781
  * Test for /etc/default/tinc before trying to source it. Closes: #777262
2019-08-26 13:44:52 +02:00
Guus Sliepen
3c37b83332 Import Debian changes 1.1~pre14-16-g15b868e-1
tinc (1.1~pre14-16-g15b868e-1) experimental; urgency=medium

  * New upstream release.
    - Use the latest git version in order to compile with OpenSSL 1.1.0.
  * Bump debian/compat and Standards-Version.
  * Fix the version number in configure.ac.
  * Make the build reproducible.
2019-08-26 13:44:52 +02:00
Guus Sliepen
03136efdbe Import Debian changes 1.1~pre12-1
tinc (1.1~pre12-1) experimental; urgency=medium

  * New upstream release.
  * Bump Standards-Version.
  * Depend on python-wxgtk3.0 for the GUI.
  * Use dh --with python2.
  * Add Build-Depends for dh-python.
  * Update links in debian/control and debian/copyright.
2019-08-26 13:44:52 +02:00
Guus Sliepen
ff4039db4b Import Debian changes 1.1~pre11-1
tinc (1.1~pre11-1) experimental; urgency=medium

  * New upstream release.
  * Update NEWS.Debian to reflect that tincctl has been renamed to tinc.
    Closes: #729889
  * Warn about incompatibility with previous 1.1preX releases, and that new
    Ed25519 keys should be generated.
  * Add native systemd service files.
  * Automatically convert networks listed in nets.boot to systemd service
    instances on upgrade.
  * Don't restart tinc on upgrade for now.
2019-08-26 13:44:52 +02:00
Guus Sliepen
edfe2872c3 Import Debian changes 1.1~pre9-1
tinc (1.1~pre9-1) experimental; urgency=low

  * New upstream release.
2019-08-26 13:44:51 +02:00
Guus Sliepen
43bffaeb98 Import Debian changes 1.1~pre8-2
tinc (1.1~pre8-2) experimental; urgency=low

  * Run make clean after the configure step to get rid of .o files that were
    accidentily left in the orig.tar.gz.
2019-08-26 13:44:51 +02:00
Guus Sliepen
b0db4c75f6 Import Debian changes 1.1~pre8-1
tinc (1.1~pre8-1) experimental; urgency=low

  * New upstream release.
    - Handles whitespace between command line flags and optional arguments.
      Closes: #710267
  * Bump Standards-Version.
  * Source /lib/lsb/init-functions in the init.d script.
  * Don't use texi2html anymore, use automake's install-html target which uses
    makeinfo.
2019-08-26 13:44:51 +02:00
Guus Sliepen
5c54f47af6 Import Debian changes 1.1~pre7-2
tinc (1.1~pre7-2) experimental; urgency=low

  [ Gian Piero Carrubba ]
  * Init script fails to pass extra arguments to tincd. Closes: #704701
    + Remove the '--' as it is passed unaltered to tincd, preventing it to read
      trailing parameters.
    + Pass extra arguments also when restarting the daemon.
  * Set process limits when started by ifupdown. Closes: #704702

  [ Guus Sliepen ]
  * Check whether the tincd process is still running in the if-post-down script.
    Closes: #704708
2019-08-26 13:44:51 +02:00
Guus Sliepen
a62bf04cde Import Debian changes 1.1~pre7-1
tinc (1.1~pre7-1) experimental; urgency=high

  * New upstream release.
    - Drop packets forwarded via TCP if they are too big (CVE-2013-1428).
2019-08-26 13:44:50 +02:00
Guus Sliepen
2127705d53 Import Debian changes 1.1~pre6-1
tinc (1.1~pre6-1) experimental; urgency=low

  * New upstream release.
2019-08-26 13:44:50 +02:00
Guus Sliepen
e9142bd3a6 Import Debian changes 1.1~pre4-1
tinc (1.1~pre4-1) experimental; urgency=low

  [ Gian Piero ]
  * Allow resource limits to be set in /etc/default/tinc. Closes: #690685

  [ Guus Sliepen ]
  * New upstream release.
2019-08-26 13:44:50 +02:00
Guus Sliepen
cfba637f96 Import Debian changes 1.1~pre3-1
tinc (1.1~pre3-1) experimental; urgency=low

  * New upstream release.
  * Bump Standards-Version.
  * Enable parallel builds.
  * Bump debian/compat to 9, so tinc gets build with hardening flags.
  * Move tinc-gui to its own package.
2019-08-26 13:44:50 +02:00
Michael Tokarev
446afddf38 Import Debian changes 1.1~pre2-2
tinc (1.1~pre2-2) experimental; urgency=low

  * add forgotten build-depend on libncurses5-dev for new `tincctl top'
  * add libevent-dev build dependency
  * remove build dependency on gettext
2019-08-26 13:44:49 +02:00
Michael Tokarev
cf2ac65444 Import Debian changes 1.1~pre2-1
tinc (1.1~pre2-1) experimental; urgency=low

  * first cut of 1.1-tobe.
    Rewrote control scripts et al to use tincctl.
  * build-depend on libssl >>1.0.0 to get proper EC support
  * remove crypto-related symlinks from src/ in clean --
    probably should go into upstream makefile instead
2019-08-26 13:44:49 +02:00
253 changed files with 44883 additions and 11765 deletions

74
.drone.yml Normal file
View file

@ -0,0 +1,74 @@
kind: pipeline
name: default
steps:
- name: Build Bullseye
image: debian:bullseye
volumes:
- name: finished_files
path: /deb_files
commands:
- apt update
- apt -y upgrade
- apt -y install --no-install-recommends build-essential equivs devscripts git rename
- git clean -f -d -x
- mk-build-deps --install --tool='apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes' debian/control
- dpkg-buildpackage -b -uc
- rename 's/\.deb/_bullseye\.deb/' ../*.deb
- mkdir -p /deb_files/bullseye/
- cp ../tinc*.deb /deb_files/bullseye/
- find /deb_files/
- name: Build Buster
image: debian:buster
volumes:
- name: finished_files
path: /deb_files
commands:
- apt update
- apt -y upgrade
- apt -y install --no-install-recommends build-essential equivs devscripts git rename
- git clean -f -d -x
- mk-build-deps --install --tool='apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes' debian/control
- dpkg-buildpackage -b -uc
- rename 's/\.deb/_buster\.deb/' ../*.deb
- mkdir -p /deb_files/buster/
- cp ../tinc*.deb /deb_files/buster/
- find /deb_files/
- name: Build Ubuntu Focal
image: ubuntu:focal
volumes:
- name: finished_files
path: /deb_files
commands:
- apt update
- apt -y upgrade
- DEBIAN_FRONTEND=noninteractive apt -y install --no-install-recommends build-essential equivs devscripts git rename
- git clean -f -d -x
- mk-build-deps --install --tool='apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes' debian/control
- dpkg-buildpackage -b -uc
- rename 's/\.deb/_focal\.deb/' ../*.deb
- mkdir -p /deb_files/focal/
- cp ../tinc*.deb /deb_files/focal/
- find /deb_files/
- name: gitea_release
image: plugins/gitea-release
volumes:
- name: finished_files
path: /deb_files
settings:
api_key:
from_secret: GITEA_KEY
base_url: https://git.neulandlabor.de/
files:
- /deb_files/buster/*
- /deb_files/bullseye/*
- /deb_files/focal/*
when:
event: tag
volumes:
- name: finished_files
temp: {}

22
AUTHORS
View file

@ -1,20 +1,25 @@
Main tinc authors: Main tinc authors:
- Guus Sliepen <guus@tinc-vpn.org> - Guus Sliepen <guus@tinc-vpn.org>
- Ivo Timmermans (inactive) - Ivo Timmermans (inactive)
Significant contributions from: Significant code contributions from:
- Michael Tokarev <mjt@tls.msk.ru>
- Brandon Black <blblack@gmail.com>
- Etienne Dechamps <etienne@edechamps.fr>
- Florian Forster <octo@verplant.org> - Florian Forster <octo@verplant.org>
- Grzegorz Dymarek <gregd72002@googlemail.com> - Grzegorz Dymarek <gregd72002@googlemail.com>
- Max Rijevski <maksuf@gmail.com>
- Scott Lamb <slamb@slamb.org>
- Julien Muchembled <jm@jmuchemb.eu> - Julien Muchembled <jm@jmuchemb.eu>
- Timothy Redaelli <timothy@redaelli.eu>
- Brandon Black <blblack@gmail.com>
- Loïc Grenié <loic.grenie@gmail.com> - Loïc Grenié <loic.grenie@gmail.com>
- Max Rijevski <maksuf@gmail.com>
- Michael Tokarev <mjt@tls.msk.ru>
- Scott Lamb <slamb@slamb.org>
- Sven-Haegar Koch <haegar@sdinet.de>
- Timothy Redaelli <timothy@redaelli.eu>
These files are from other sources: These files are from other sources:
* lib/pidfile.h and lib/pidfile.c are by Martin Schulze, taken from
* lib/pidfile.h and lib/pidfile.c are by Martin Schulze, taken from
the syslog 1.3 sources. the syslog 1.3 sources.
* src/bsd/tunemu.c and tunemu.h are by Friedrich Schöller * src/bsd/tunemu.c and tunemu.h are by Friedrich Schöller
@ -23,5 +28,4 @@ These files are from other sources:
Also some of the macro files in the directory m4, and their Also some of the macro files in the directory m4, and their
accompanying files in lib, were taken from GNU fileutils. accompanying files in lib, were taken from GNU fileutils.
Please see the file THANKS for more information on contributions from Please see the file THANKS for a list of all contributors to tinc.
users.

View file

@ -1,4 +1,4 @@
Copyright (C) 1998-2019 Ivo Timmermans, Guus Sliepen and others. Copyright (C) 1998-2021 Ivo Timmermans, Guus Sliepen and others.
See the AUTHORS file for a complete list. See the AUTHORS file for a complete list.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under

View file

@ -1,19 +1,17 @@
The following applies to tinc: The following applies to tinc:
This program is released under the GPL with the additional exemption that > This program is released under the GPL with the additional exemption that
compiling, linking, and/or using OpenSSL is allowed. You may provide binary > compiling, linking, and/or using OpenSSL is allowed. You may provide binary
packages linked to the OpenSSL libraries, provided that all other requirements > packages linked to the OpenSSL libraries, provided that all other requirements
of the GPL are met. > of the GPL are met.
The following applies to the LZO library: The following applies to the LZO library:
Hereby I grant a special exception to the tinc VPN project > Hereby I grant a special exception to the tinc VPN project
(http://tinc.nl.linux.org/) to link the LZO library with the OpenSSL library > (https://www.tinc-vpn.org/) to link the LZO library with the OpenSSL library
(http://www.openssl.org). > (https://openssl.org).
>
Markus F.X.J. Oberhumer > Markus F.X.J. Oberhumer
When tinc is compiled with the --enable-tunemu option, the resulting binary When tinc is compiled with the --enable-tunemu option, the resulting binary
falls under the GPL version 3 or later. falls under the GPL version 3 or later.

1971
ChangeLog

File diff suppressed because it is too large Load diff

View file

@ -2,14 +2,39 @@
AUTOMAKE_OPTIONS = gnu AUTOMAKE_OPTIONS = gnu
SUBDIRS = src doc systemd SUBDIRS = src doc test systemd bash_completion.d
ACLOCAL_AMFLAGS = -I m4 ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = COPYING.README README.android EXTRA_DIST = COPYING.README README.android
@CODE_COVERAGE_RULES@
# If git describe works, force autoconf to run in order to make sure we have the
# current version number from git in the resulting configure script.
configure-version:
-cd $(srcdir) && git describe && autoconf --force
# Triggering the README target means we are building a distribution (make dist).
README: configure-version
ChangeLog: ChangeLog:
git log > ChangeLog (cd $(srcdir) && git log) > ChangeLog
deb:
dpkg-buildpackage -rfakeroot
rpm: dist
cp $(distdir).tar.gz /usr/src/redhat/SOURCES/
cp redhat/tinc.spec /usr/src/redhat/SOURCES/
cd /usr/src/redhat/SOURCES/ && rpm -bb tinc.spec
release:
rm -f ChangeLog
$(MAKE) ChangeLog
echo "Please edit the NEWS file now..."
/usr/bin/editor $(srcdir)/NEWS
$(MAKE) dist
astyle: astyle:
astyle --options=.astylerc -nQ src/*.[ch] src/*/*.[ch] astyle --options=.astylerc -nQ src/*.[ch] src/*/*.[ch]

View file

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.16.2 from Makefile.am. # Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc. # Copyright (C) 1994-2020 Free Software Foundation, Inc.
@ -94,9 +94,12 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/ax_cflags_warn_all.m4 \ $(top_srcdir)/m4/ax_cflags_warn_all.m4 \
$(top_srcdir)/m4/ax_check_compile_flag.m4 \ $(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_check_link_flag.m4 \ $(top_srcdir)/m4/ax_check_link_flag.m4 \
$(top_srcdir)/m4/ax_require_defined.m4 $(top_srcdir)/m4/lzo.m4 \ $(top_srcdir)/m4/ax_code_coverage.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/zlib.m4 \ $(top_srcdir)/m4/ax_require_defined.m4 \
$(top_srcdir)/configure.ac $(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/libgcrypt.m4 \
$(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) \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4) $(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
@ -205,6 +208,8 @@ am__relativize = \
DIST_ARCHIVES = $(distdir).tar.gz DIST_ARCHIVES = $(distdir).tar.gz
GZIP_ENV = --best GZIP_ENV = --best
DIST_TARGETS = dist-gzip DIST_TARGETS = dist-gzip
# Exists only to be overridden by the user if desired.
AM_DISTCHECK_DVI_TARGET = dvi
distuninstallcheck_listfiles = find . -type f -print distuninstallcheck_listfiles = find . -type f -print
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
@ -219,8 +224,15 @@ AWK = @AWK@
CC = @CC@ CC = @CC@
CCDEPMODE = @CCDEPMODE@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@ CFLAGS = @CFLAGS@
CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@
CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@
CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
CODE_COVERAGE_LIBS = @CODE_COVERAGE_LIBS@
CPP = @CPP@ CPP = @CPP@
CPPFLAGS = @CPPFLAGS@ CPPFLAGS = @CPPFLAGS@
CURSES_LIBS = @CURSES_LIBS@
CYGPATH_W = @CYGPATH_W@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@ DEFS = @DEFS@
DEPDIR = @DEPDIR@ DEPDIR = @DEPDIR@
@ -229,17 +241,21 @@ ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@ ECHO_T = @ECHO_T@
EGREP = @EGREP@ EGREP = @EGREP@
EXEEXT = @EXEEXT@ EXEEXT = @EXEEXT@
GCOV = @GCOV@
GENHTML = @GENHTML@
GREP = @GREP@ GREP = @GREP@
INSTALL = @INSTALL@ INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@ INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LCOV = @LCOV@
LDFLAGS = @LDFLAGS@ LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@ LIBOBJS = @LIBOBJS@
LIBS = @LIBS@ LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@ LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@ MAKEINFO = @MAKEINFO@
MINIUPNPC_LIBS = @MINIUPNPC_LIBS@
MKDIR_P = @MKDIR_P@ MKDIR_P = @MKDIR_P@
OBJEXT = @OBJEXT@ OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@ PACKAGE = @PACKAGE@
@ -250,6 +266,8 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@ PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@ PATH_SEPARATOR = @PATH_SEPARATOR@
READLINE_LIBS = @READLINE_LIBS@
SED = @SED@
SET_MAKE = @SET_MAKE@ SET_MAKE = @SET_MAKE@
SHELL = @SHELL@ SHELL = @SHELL@
STRIP = @STRIP@ STRIP = @STRIP@
@ -307,7 +325,7 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@ top_srcdir = @top_srcdir@
AUTOMAKE_OPTIONS = gnu AUTOMAKE_OPTIONS = gnu
SUBDIRS = src doc systemd SUBDIRS = src doc test systemd bash_completion.d
ACLOCAL_AMFLAGS = -I m4 ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = COPYING.README README.android EXTRA_DIST = COPYING.README README.android
all: config.h all: config.h
@ -473,12 +491,6 @@ distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am $(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES) distdir-am: $(DISTFILES)
@case `sed 15q $(srcdir)/NEWS` in \
*"$(VERSION)"*) : ;; \
*) \
echo "NEWS not updated; not releasing" 1>&2; \
exit 1;; \
esac
$(am__remove_distdir) $(am__remove_distdir)
test -d "$(distdir)" || mkdir "$(distdir)" test -d "$(distdir)" || mkdir "$(distdir)"
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
@ -621,7 +633,7 @@ distcheck: dist
$(DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \
--srcdir=../.. --prefix="$$dc_install_base" \ --srcdir=../.. --prefix="$$dc_install_base" \
&& $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \
&& $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
@ -797,8 +809,33 @@ uninstall-am:
.PRECIOUS: Makefile .PRECIOUS: Makefile
@CODE_COVERAGE_RULES@
# If git describe works, force autoconf to run in order to make sure we have the
# current version number from git in the resulting configure script.
configure-version:
-cd $(srcdir) && git describe && autoconf --force
# Triggering the README target means we are building a distribution (make dist).
README: configure-version
ChangeLog: ChangeLog:
git log > ChangeLog (cd $(srcdir) && git log) > ChangeLog
deb:
dpkg-buildpackage -rfakeroot
rpm: dist
cp $(distdir).tar.gz /usr/src/redhat/SOURCES/
cp redhat/tinc.spec /usr/src/redhat/SOURCES/
cd /usr/src/redhat/SOURCES/ && rpm -bb tinc.spec
release:
rm -f ChangeLog
$(MAKE) ChangeLog
echo "Please edit the NEWS file now..."
/usr/bin/editor $(srcdir)/NEWS
$(MAKE) dist
astyle: astyle:
astyle --options=.astylerc -nQ src/*.[ch] src/*/*.[ch] astyle --options=.astylerc -nQ src/*.[ch] src/*/*.[ch]

1158
NEWS

File diff suppressed because it is too large Load diff

149
README
View file

@ -1,11 +1,7 @@
This is the README file for tinc version 1.0.36. Installation This is the README file for tinc version 1.1pre18. Installation
instructions may be found in the INSTALL file. instructions may be found in the INSTALL file.
tinc is Copyright (C) 1998-2019 by: tinc is Copyright © 1998-2021 Ivo Timmermans, Guus Sliepen <guus@tinc-vpn.org>, and others.
Ivo Timmermans,
Guus Sliepen <guus@tinc-vpn.org>,
and others.
For a complete list of authors see the AUTHORS file. For a complete list of authors see the AUTHORS file.
@ -15,119 +11,94 @@ the Free Software Foundation; either version 2 of the License, or (at
your option) any later version. See the file COPYING for more details. your option) any later version. See the file COPYING for more details.
This is a pre-release
---------------------
Please note that this is NOT a stable release. Until version 1.1.0 is released,
please use one of the 1.0.x versions if you need a stable version of tinc.
Although tinc 1.1 will be protocol compatible with tinc 1.0.x, the
functionality of the tinc program may still change, and the control socket
protocol is not fixed yet.
Security statement Security statement
------------------ ------------------
In August 2000, we discovered the existence of a security hole in all versions This version uses an experimental and unfinished cryptographic protocol. Use it
of tinc up to and including 1.0pre2. This had to do with the way we exchanged at your own risk.
keys. Since then, we have been working on a new authentication scheme to make
tinc as secure as possible. The current version uses the OpenSSL library and
uses strong authentication with RSA keys.
On the 29th of December 2001, Jerome Etienne posted a security analysis of tinc When connecting to nodes that use the legacy protocol used in tinc 1.0, be
1.0pre4. Due to a lack of sequence numbers and a message authentication code aware that any security issues in tinc 1.0 will apply to tinc 1.1 as well. On
for each packet, an attacker could possibly disrupt certain network services or September 6th, 2018, Michael Yonly contacted us and provided proof-of-concept
launch a denial of service attack by replaying intercepted packets. The current code that allowed a remote attacker to create an authenticated, one-way
version adds sequence numbers and message authentication codes to prevent such connection with a node using the legacy protocol, and also that there was a
attacks.
On September the 15th of 2003, Peter Gutmann contacted us and showed us a
writeup describing various security issues in several VPN daemons. He showed
that tinc lacks perfect forward security, the connection authentication could
be done more properly, that the sequence number we use as an IV is not the best
practice and that the default length of the HMAC for packets is too short in
his opinion. We do not know of a way to exploit these weaknesses, but these
issues are being addressed in the tinc 1.1 branch.
The Sweet32 attack affects versions of tinc prior to 1.0.30.
On September 6th, 2018, Michael Yonly contacted us and provided
proof-of-concept code that allowed a remote attacker to create an
authenticated, one-way connection with a node, and also that there was a
possibility for a man-in-the-middle to force UDP packets from a node to be sent possibility for a man-in-the-middle to force UDP packets from a node to be sent
in plaintext. The first issue was trivial to exploit on tinc versions prior to in plaintext. The first issue was trivial to exploit on tinc versions prior to
1.0.30, but the changes in 1.0.30 to mitigate the Sweet32 attack made this 1.0.30, but the changes in 1.0.30 to mitigate the Sweet32 attack made this
weakness much harder to exploit. These issues have been fixed in tinc 1.0.35. weakness much harder to exploit. These issues have been fixed in tinc 1.0.35
The new protocol in the tinc 1.1 branch is not susceptible to these issues. and tinc 1.1pre17. The new protocol in the tinc 1.1 branch is not susceptible
to these issues. However, be aware that SPTPS is only used between nodes
Cryptography is a hard thing to get right. We cannot make any running tinc 1.1pre* or later, and in a VPN with nodes running different
guarantees. Time, review and feedback are the only things that can versions, the security might only be as good as that of the oldest version.
prove the security of any cryptographic product. If you wish to review
tinc or give us feedback, you are strongly encouraged to do so.
Compatibility Compatibility
------------- -------------
Version 1.0.35 is compatible with 1.0pre8, 1.0 and later, but not with older Version 1.1pre18 is compatible with 1.0pre8, 1.0 and later, but not with older
versions of tinc. Note that since version 1.0.30, tinc requires all nodes in versions of tinc.
the VPN to be compiled with a version of LibreSSL or OpenSSL that supports the
AES256 and SHA256 algorithms. When the ExperimentalProtocol option is used, tinc is still compatible with
1.0.X, 1.1pre11 and later, but not with any version between 1.1pre1 and
1.1pre10.
Requirements Requirements
------------ ------------
The OpenSSL library is used for all cryptographic functions. You can find it at In order to compile tinc, you will need a GNU C compiler environment. Please
https://www.openssl.org/. You will need version 1.0.1 or later with support for ensure you have the latest stable versions of all the required libraries:
AES256 and SHA256 enabled. If this library is not installed on your system, the
configure script will fail. The manual in doc/tinc.texi contains more detailed
information on how to install this library. Alternatively, you may also use the
LibreSSL library.
The zlib library is used for optional compression. You can - LibreSSL (http://www.libressl.org/) or OpenSSL (https://openssl.org/) version 1.0.0 or later.
find it at https://zlib.net/. Because of a possible exploit in
earlier versions we recommend that you download version 1.1.4 or later.
The LZO library is also used for optional compression. You can The following libraries are used by default, but can be disabled if necessary:
find it at https://www.oberhumer.com/opensource/lzo/.
In order to compile tinc, you will need a C99 compliant compiler. - zlib (https://zlib.net/)
- LZO (https://www.oberhumer.com/opensource/lzo/)
- ncurses (https://invisible-island.net/ncurses/)
- readline (https://cnswww.cns.cwru.edu/php/chet/readline/rltop.html)
Features Features
-------- --------
This version of tinc supports multiple virtual networks at once. To Tinc is a peer-to-peer VPN daemon that supports VPNs with an arbitrary number
use this feature, you may supply a netname via the -n or --net of nodes. Instead of configuring tunnels, you give tinc the location and
options. The standard locations for the config files will then be public key of a few nodes in the VPN. After making the initial connections to
/etc/tinc/<net>/. those nodes, tinc will learn about all other nodes on the VPN, and will make
connections automatically. When direct connections are not possible, data will
be forwarded by intermediate nodes.
tincd regenerates its encryption key pairs. It does this on the first Tinc 1.1 support two protocols. The first is a legacy protocol that provides
activity after the keys have expired. This period is adjustable in the backwards compatibility with tinc 1.0 nodes, and which by default uses 2048 bit
configuration file, and the default time is 3600 seconds (one hour). RSA keys for authentication, and encrypts traffic using AES256 in CBC mode
and HMAC-SHA256. The second is a new protocol which uses Curve25519 keys for
authentication, and encrypts traffic using Chacha20-Poly1305, and provides
forward secrecy.
This version supports multiple subnets at once. They are also sorted Tinc fully supports IPv6.
on subnet mask size. This means that it is possible to have
overlapping subnets on the VPN, as long as their subnet mask sizes
differ.
Since pre5, tinc can operate in several routing modes. The default mode, Tinc can operate in several routing modes. In the default mode, "router", every
"router", works exactly like the older version, and uses Subnet lines to node is associated with one or more IPv4 and/or IPv6 Subnets. The other two
determine the destination of packets. The other two modes, "switch" and "hub", modes, "switch" and "hub", let the tinc daemons work together to form a virtual
allow the tinc daemons to work together like a single network switch or hub. Ethernet network switch or hub.
This is useful for bridging networks. The latter modes only work properly on
Linux, FreeBSD and Windows.
The algorithms used for encryption and generating message authentication codes
can now be changed in the configuration files. All cipher and digest algorithms
supported by OpenSSL can be used. Useful ciphers are "blowfish" (default),
"bf-ofb", "des", "des3", et cetera. Useful digests are "sha1" (default), "md5",
et cetera.
Support for routing IPv6 packets has been added. Just add Subnet lines with
IPv6 addresses (without using :: abbreviations) and use ifconfig or ip (from
the iproute package) to give the virtual network interface corresponding IPv6
addresses. tinc does not provide autoconfiguration for IPv6 hosts. Consider
using radvd or zebra if you need it.
It is also possible to make tunnels to other tinc daemons over IPv6 networks,
if the operating system supports IPv6. tinc will automatically use both IPv6
and IPv4 when available, but this can be changed by adding the option
"AddressFamily = ipv4" or "AddressFamily = ipv6" to the tinc.conf file.
Normally, when started tinc will detach and run in the background. In a native Normally, when started tinc will detach and run in the background. In a native
Windows environment this means tinc will install itself as a service, which will Windows environment this means tinc will install itself as a service, which will
restart after reboots. To prevent tinc from detaching or running as a service, restart after reboots. To prevent tinc from detaching or running as a service,
use the -D option. use the -D option.
The status of the VPN can be queried using the "tinc" command, which connects
to a running tinc daemon via a control connection. The same tool also makes it
easy to start and stop tinc, and to change its configuration.

View file

@ -1,25 +1,23 @@
Quick how-to cross compile tinc for android (done from $HOME/android/): Quick how-to cross compile tinc for Android (done from $HOME/android/):
- Download android NDK and setup local ARM toolchain: - Download Android NDK and setup local ARM toolchain:
wget http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86.tar.bz2
tar xfj android-ndk-r9d-linux-x86.tar.bz2
./android-ndk-r9d/build/tools/make-standalone-toolchain.sh --platform=android-5 --install-dir=/tmp/my-android-toolchain
- Download and cross-compile openSSL for ARM: wget http://dl.google.com/android/ndk/android-ndk-r8b-linux-x86.tar.bz2
wget http://www.openssl.org/source/openssl-1.0.1h.tar.gz tar xfj android-ndk-r8b-linux-x86.tar.bz2
tar xfz openssl-1.0.1h.tar.gz ./android-ndk-r8b/build/tools/make-standalone-toolchain.sh --platform=android-5 --install-dir=/tmp/my-android-toolchain
cd openssl-1.0.1h
./Configure dist - Download and cross-compile OpenSSL for ARM:
make CC=/tmp/my-android-toolchain/bin/arm-linux-androideabi-gcc AR="/tmp/my-android-toolchain/bin/arm-linux-androideabi-ar r" RANLIB=/tmp/my-android-toolchain/bin/arm-linux-androideabi-ranlib
cd - wget http://www.openssl.org/source/openssl-1.0.1c.tar.gz
tar xfz openssl-1.0.1c.tar.gz
cd openssl-1.0.1c
./Configure dist
make CC=/tmp/my-android-toolchain/bin/arm-linux-androideabi-gcc AR="/tmp/my-android-toolchain/bin/arm-linux-androideabi-ar r" RANLIB=/tmp/my-android-toolchain/bin/arm-linux-androideabi-ranlib
- Clone and cross-compile tinc: - Clone and cross-compile tinc:
git clone git://tinc-vpn.org/tinc
cd tinc
autoreconf -fsi
CC=/tmp/my-android-toolchain/bin/arm-linux-androideabi-gcc ./configure --host=arm-linux --disable-lzo --with-openssl-lib=$HOME/android/openssl-1.0.1g --with-openssl-include=$HOME/android/openssl-1.0.1g/include/ --disable-hardening
make -j5
- Strip tincd binary to make it smaller
/tmp/my-android-toolchain/bin/arm-linux-androideabi-strip src/tincd
git clone git://tinc-vpn.org/tinc
cd tinc
autoreconf -fsi
CC=/tmp/my-android-toolchain/bin/arm-linux-androideabi-gcc ./configure --host=arm-linux --disable-lzo --with-openssl-lib=$HOME/android/openssl-1.0.1c --with-openssl-include=$HOME/android/openssl-1.0.1c/include/
make -j5

29
THANKS
View file

@ -1,9 +1,11 @@
We would like to thank the following people for their contributions to tinc: We would like to thank the following people for their contributions to tinc:
* Aaron Li
* Alexander Reil and Gemeinde Berg * Alexander Reil and Gemeinde Berg
* Alexander Ried * Alexander Ried
* Alexis Hildebrandt * Alexis Hildebrandt
* Allesandro Gatti * Allesandro Gatti
* Andreas Rammhold
* Andreas van Cranenburgh * Andreas van Cranenburgh
* Andrew Hahn * Andrew Hahn
* Anthony G. Basile * Anthony G. Basile
@ -22,28 +24,32 @@ We would like to thank the following people for their contributions to tinc:
* Delf Eldkraft * Delf Eldkraft
* Dennis Joachimsthaler * Dennis Joachimsthaler
* dnk * dnk
* Егор Палкин
* Élie Bouttier * Élie Bouttier
* Enrique Zanardi * Enrique Zanardi
* Erik Tews * Erik Tews
* Etienne Dechamps * Etienne Dechamps
* Fabian Maurer
* Florent Clairambault * Florent Clairambault
* Florian Forster * Florian Forster
* Florian Klink * Florian Klink
* Florian Weik * Florian Weik
* Flynn Marquardt * Flynn Marquardt
* Franz Pletz * Franz Pletz
* Fufu Fang
* Gary Kessler and Claudia Gonzalez * Gary Kessler and Claudia Gonzalez
* Grzegorz Dymarek * Grzegorz Dymarek
* Gusariev Oleksandr * Gusariev Oleksandr
* Hans Bayle * Hans Bayle
* Harvest * Harvest
* Ivo van Dong * Huai An Hsu
* iczero
* Ilia Pavlikhin
* Ivan Mirić
* Ivo Smits * Ivo Smits
* Ivo van Dong
* James Cook * James Cook
* James MacLean * James MacLean
* Jamie Briggs * Jamie Briggs
* Jan Štembera
* Jason Harper * Jason Harper
* Jason Livesay * Jason Livesay
* Jasper Krijgsman * Jasper Krijgsman
@ -51,17 +57,21 @@ We would like to thank the following people for their contributions to tinc:
* Jeroen Domburg * Jeroen Domburg
* Jeroen Ubbink * Jeroen Ubbink
* Jerome Etienne * Jerome Etienne
* Jo-Philipp Wich * Jiang Sheng
* Jochen Voss * Jochen Voss
* Jo-Philipp Wich
* Julien Muchembled * Julien Muchembled
* Lavrans Laading * Lavrans Laading
* leptonyu
* Loïc Dachary * Loïc Dachary
* Loïc Grenié * Loïc Grenié
* Lubomír Bulej * Lubomír Bulej
* luckyhacky * luckyhacky
* LunarShaddow * LunarShaddow
* Maciej S. Szmigiero
* Mads Kiilerich * Mads Kiilerich
* Marc A. Lehmann * Marc A. Lehmann
* Marco Oggioni
* Mark Glines * Mark Glines
* Mark Petryk * Mark Petryk
* Markus Goetz * Markus Goetz
@ -73,30 +83,33 @@ We would like to thank the following people for their contributions to tinc:
* Max Rijevski * Max Rijevski
* Menno Smits * Menno Smits
* Mesar Hameed * Mesar Hameed
* Michael Taylor
* Michael Tokarev * Michael Tokarev
* Michael Yonli * Michael Yonli
* Miles Nordin * Miles Nordin
* Nathan Stratton Treadway
* Murat Donmez * Murat Donmez
* Nathan Stratton Treadway
* Nick Hibma * Nick Hibma
* Nick Patavalis * Nick Patavalis
* Pacien Tran-Girard
* Patrick Helms
* Paul Littlefield * Paul Littlefield
* Philipp Babel * Philipp Babel
* Pierre Emeriaud * Pierre Emeriaud
* Pierre-Olivier Mercier * Pierre-Olivier Mercier
* Rafael Wolf
* Rafael Sadowski * Rafael Sadowski
* Rafał Leśniak * Rafał Leśniak
* René Rüthlein
* Rhosyn Celyn * Rhosyn Celyn
* Robert van der Meulen * Robert van der Meulen
* Robert Waniek * Robert Waniek
* Rosen Penev
* Rumko * Rumko
* Ryan Miller * Ryan Miller
* Sam Bryan * Sam Bryan
* Samuel Thibault * Samuel Thibault
* Saverio Proto * Saverio Proto
* Scott Lamb * Scott Lamb
* Shengjing Zhu
* Steffan Karger * Steffan Karger
* Stig Fagrell * Stig Fagrell
* Sven-Haegar Koch * Sven-Haegar Koch
@ -111,7 +124,9 @@ We would like to thank the following people for their contributions to tinc:
* Vil Brekin * Vil Brekin
* Vincent Laurent * Vincent Laurent
* Vittorio Gambaletta * Vittorio Gambaletta
* Volker Augustin
* Wendy Willard * Wendy Willard
* Werner Schreiber
* Wessel Dankers * Wessel Dankers
* William A. Kennington III * William A. Kennington III
* William McArthur * William McArthur

18
aclocal.m4 vendored
View file

@ -1,4 +1,4 @@
# generated automatically by aclocal 1.16.2 -*- Autoconf -*- # generated automatically by aclocal 1.16.3 -*- Autoconf -*-
# Copyright (C) 1996-2020 Free Software Foundation, Inc. # Copyright (C) 1996-2020 Free Software Foundation, Inc.
@ -35,7 +35,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.16' [am__api_version='1.16'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro. dnl require some minimum version. Point them to the right macro.
m4_if([$1], [1.16.2], [], m4_if([$1], [1.16.3], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
]) ])
@ -51,7 +51,7 @@ m4_define([_AM_AUTOCONF_VERSION], [])
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.16.2])dnl [AM_AUTOMAKE_VERSION([1.16.3])dnl
m4_ifndef([AC_AUTOCONF_VERSION], m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
@ -703,12 +703,7 @@ AC_DEFUN([AM_MISSING_HAS_RUN],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([missing])dnl AC_REQUIRE_AUX_FILE([missing])dnl
if test x"${MISSING+set}" != xset; then if test x"${MISSING+set}" != xset; then
case $am_aux_dir in MISSING="\${SHELL} '$am_aux_dir/missing'"
*\ * | *\ *)
MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
*)
MISSING="\${SHELL} $am_aux_dir/missing" ;;
esac
fi fi
# Use eval to expand $SHELL # Use eval to expand $SHELL
if eval "$MISSING --is-lightweight"; then if eval "$MISSING --is-lightweight"; then
@ -1140,7 +1135,12 @@ m4_include([m4/ax_append_flag.m4])
m4_include([m4/ax_cflags_warn_all.m4]) m4_include([m4/ax_cflags_warn_all.m4])
m4_include([m4/ax_check_compile_flag.m4]) m4_include([m4/ax_check_compile_flag.m4])
m4_include([m4/ax_check_link_flag.m4]) m4_include([m4/ax_check_link_flag.m4])
m4_include([m4/ax_code_coverage.m4])
m4_include([m4/ax_require_defined.m4]) m4_include([m4/ax_require_defined.m4])
m4_include([m4/curses.m4])
m4_include([m4/libgcrypt.m4])
m4_include([m4/lzo.m4]) m4_include([m4/lzo.m4])
m4_include([m4/miniupnpc.m4])
m4_include([m4/openssl.m4]) m4_include([m4/openssl.m4])
m4_include([m4/readline.m4])
m4_include([m4/zlib.m4]) m4_include([m4/zlib.m4])

View file

@ -0,0 +1,2 @@
bash_completiondir = @datarootdir@/bash-completion/completions/
dist_bash_completion_DATA = tinc

View file

@ -0,0 +1,490 @@
# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
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 \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = bash_completion.d
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/ax_append_flag.m4 \
$(top_srcdir)/m4/ax_cflags_warn_all.m4 \
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_check_link_flag.m4 \
$(top_srcdir)/m4/ax_code_coverage.m4 \
$(top_srcdir)/m4/ax_require_defined.m4 \
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/libgcrypt.m4 \
$(top_srcdir)/m4/lzo.m4 $(top_srcdir)/m4/miniupnpc.m4 \
$(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 $(dist_bash_completion_DATA) \
$(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
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 =
SOURCES =
DIST_SOURCES =
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \
test -z "$$files" \
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && rm -f $$files; }; \
}
am__installdirs = "$(DESTDIR)$(bash_completiondir)"
DATA = $(dist_bash_completion_DATA)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
am__DIST_COMMON = $(srcdir)/Makefile.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@
CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@
CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
CODE_COVERAGE_LIBS = @CODE_COVERAGE_LIBS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CURSES_LIBS = @CURSES_LIBS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
GCOV = @GCOV@
GENHTML = @GENHTML@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LCOV = @LCOV@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MINIUPNPC_LIBS = @MINIUPNPC_LIBS@
MKDIR_P = @MKDIR_P@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
READLINE_LIBS = @READLINE_LIBS@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
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@
bash_completiondir = @datarootdir@/bash-completion/completions/
dist_bash_completion_DATA = tinc
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu bash_completion.d/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu bash_completion.d/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
install-dist_bash_completionDATA: $(dist_bash_completion_DATA)
@$(NORMAL_INSTALL)
@list='$(dist_bash_completion_DATA)'; test -n "$(bash_completiondir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(bash_completiondir)'"; \
$(MKDIR_P) "$(DESTDIR)$(bash_completiondir)" || exit 1; \
fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(bash_completiondir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(bash_completiondir)" || exit $$?; \
done
uninstall-dist_bash_completionDATA:
@$(NORMAL_UNINSTALL)
@list='$(dist_bash_completion_DATA)'; test -n "$(bash_completiondir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
dir='$(DESTDIR)$(bash_completiondir)'; $(am__uninstall_files_from_dir)
tags TAGS:
ctags CTAGS:
cscope cscopelist:
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(DATA)
installdirs:
for dir in "$(DESTDIR)$(bash_completiondir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-generic
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am: install-dist_bash_completionDATA
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-dist_bash_completionDATA
.MAKE: install-am install-strip
.PHONY: all all-am check check-am clean clean-generic cscopelist-am \
ctags-am distclean distclean-generic distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dist_bash_completionDATA install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-generic pdf pdf-am ps ps-am tags-am uninstall \
uninstall-am uninstall-dist_bash_completionDATA
.PRECIOUS: Makefile
# 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.
.NOEXPORT:

92
bash_completion.d/tinc Normal file
View file

@ -0,0 +1,92 @@
_tinc() {
local cur prev opts confvars commands nets
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts="-c -d -D -K -n -o -L -R -U --config --no-detach --debug --net --option --mlock --logfile --pidfile --chroot --user --help --version"
confvars="Address AddressFamily BindToAddress BindToInterface Broadcast BroadcastSubnet Cipher ClampMSS Compression ConnectTo DecrementTTL Device DeviceStandby DeviceType Digest DirectOnly Ed25519PrivateKeyFile Ed25519PublicKey Ed25519PublicKeyFile ExperimentalProtocol Forwarding FWMark GraphDumpFile Hostnames IffOneQueue IndirectData Interface InvitationExpire KeyExpire ListenAddress LocalDiscovery MACExpire MACLength MaxOutputBufferSize MaxTimeout Mode MTUInfoInterval Name PMTU PMTUDiscovery PingInterval PingTimeout Port PriorityInheritance PrivateKeyFile ProcessPriority Proxy PublicKeyFile ReplayWindow StrictSubnets Subnet TCPOnly TunnelServer UDPDiscovery UDPDiscoveryKeepaliveInterval UDPDiscoveryInterval UDPDiscoveryTimeout UDPInfoInterval UDPRcvBuf UDPSndBuf UPnP UPnPDiscoverWait UPnPRefreshPeriod VDEGroup VDEPort Weight"
commands="add connect debug del disconnect dump edit export export-all generate-ed25519-keys generate-keys generate-rsa-keys get help import info init invite join list log network pcap pid purge reload restart retry set sign start stop top verify version"
case ${prev} in
-c|--config)
compopt -o dirnames 2>/dev/null
return 0
;;
-n|--net)
nets=""
pushd /etc/tinc >/dev/null 2>/dev/null
for dir in *; do
if [[ -f "$dir/tinc.conf" ]]; then
nets="$nets $dir"
fi
done
popd >/dev/null 2>/dev/null
COMPREPLY=( $(compgen -W "${nets}" -- ${cur}) )
return 0
;;
-o|--option)
compopt -o nospace
COMPREPLY=( $(compgen -W "${confvars}" -- ${cur}) )
if [[ ${#COMPREPLY[*]} == 1 ]] ; then
COMPREPLY=$COMPREPLY=
fi
return 0
;;
-U|--user)
COMPREPLY=( $(compgen -u ${cur}) )
return 0
;;
--logfile|--pidfile)
compopt -o filenames 2>/dev/null
COMPREPLY=( $(compgen -f ${cur}) )
return 0
esac
if [[ ${cur} == -* ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
if [[ $1 == "d" ]]; then
if [[ -z ${cur} ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
fi
return 0
fi
COMPREPLY=( $(compgen -W "${commands}" -- ${cur}) )
case $prev in
get|set|add|del)
COMPREPLY=( $(compgen -W "${confvars}" -- ${cur}) )
return 0
;;
dump|list|reachable)
COMPREPLY=( $(compgen -W "reachable nodes edges subnets connections graph invitations" -- ${cur}) )
return 0
;;
network)
nets=""
pushd /etc/tinc >/dev/null 2>/dev/null
for dir in *; do
if [[ -f "$dir/tinc.conf" ]]; then
nets="$nets $dir"
fi
done
popd >/dev/null 2>/dev/null
COMPREPLY=( $(compgen -W "${nets}" -- ${cur}) )
return 0
;;
esac
if [[ -z ${cur} ]] ; then
COMPREPLY=( $(compgen -W "${opts} ${commands}" -- ${cur}) )
fi
return 0
}
_tincd() {
_tinc d;
}
_tincctl() {
_tinc ctl;
}
complete -F _tincd tincd
complete -F _tincctl tinc

View file

@ -1,5 +1,8 @@
/* config.h.in. Generated from configure.ac by autoheader. */ /* config.h.in. Generated from configure.ac by autoheader. */
/* Disable support for the legacy (tinc 1.0) protocol */
#undef DISABLE_LEGACY
/* Support for jumbograms (packets up to 9000 bytes) */ /* Support for jumbograms (packets up to 9000 bytes) */
#undef ENABLE_JUMBOGRAMS #undef ENABLE_JUMBOGRAMS
@ -15,9 +18,6 @@
/* Define to 1 if you have the <arpa/inet.h> header file. */ /* Define to 1 if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H #undef HAVE_ARPA_INET_H
/* Define to 1 if you have the <arpa/nameser.h> header file. */
#undef HAVE_ARPA_NAMESER_H
/* Define to 1 if you have the `asprintf' function. */ /* Define to 1 if you have the `asprintf' function. */
#undef HAVE_ASPRINTF #undef HAVE_ASPRINTF
@ -27,8 +27,11 @@
/* Unknown BSD variant */ /* Unknown BSD variant */
#undef HAVE_BSD #undef HAVE_BSD
/* Cygwin */ /* have curses support */
#undef HAVE_CYGWIN #undef HAVE_CURSES
/* Define to 1 if you have the <curses.h> header file. */
#undef HAVE_CURSES_H
/* Define to 1 if you have the `daemon' function. */ /* Define to 1 if you have the `daemon' function. */
#undef HAVE_DAEMON #undef HAVE_DAEMON
@ -40,22 +43,6 @@
you don't. */ you don't. */
#undef HAVE_DECL_EVP_AES_256_CFB #undef HAVE_DECL_EVP_AES_256_CFB
/* Define to 1 if you have the declaration of `freeaddrinfo', and to 0 if you
don't. */
#undef HAVE_DECL_FREEADDRINFO
/* Define to 1 if you have the declaration of `gai_strerror', and to 0 if you
don't. */
#undef HAVE_DECL_GAI_STRERROR
/* Define to 1 if you have the declaration of `getaddrinfo', and to 0 if you
don't. */
#undef HAVE_DECL_GETADDRINFO
/* Define to 1 if you have the declaration of `getnameinfo', and to 0 if you
don't. */
#undef HAVE_DECL_GETNAMEINFO
/* Define to 1 if you have the declaration of `OpenSSL_add_all_algorithms', /* Define to 1 if you have the declaration of `OpenSSL_add_all_algorithms',
and to 0 if you don't. */ and to 0 if you don't. */
#undef HAVE_DECL_OPENSSL_ADD_ALL_ALGORITHMS #undef HAVE_DECL_OPENSSL_ADD_ALL_ALGORITHMS
@ -73,6 +60,9 @@
/* DragonFly */ /* DragonFly */
#undef HAVE_DRAGONFLY #undef HAVE_DRAGONFLY
/* Define to 1 if you have the `ERR_remove_state' function. */
#undef HAVE_ERR_REMOVE_STATE
/* Define to 1 if you have the `EVP_CIPHER_CTX_new' function. */ /* Define to 1 if you have the `EVP_CIPHER_CTX_new' function. */
#undef HAVE_EVP_CIPHER_CTX_NEW #undef HAVE_EVP_CIPHER_CTX_NEW
@ -94,6 +84,9 @@
/* FreeBSD */ /* FreeBSD */
#undef HAVE_FREEBSD #undef HAVE_FREEBSD
/* Define to 1 if you have the <gcrypt.h> header file. */
#undef HAVE_GCRYPT_H
/* Define to 1 if you have the <getopt.h> header file. */ /* Define to 1 if you have the <getopt.h> header file. */
#undef HAVE_GETOPT_H #undef HAVE_GETOPT_H
@ -103,12 +96,12 @@
/* Define to 1 if you have the `gettimeofday' function. */ /* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY #undef HAVE_GETTIMEOFDAY
/* Define to 1 if you have the `HMAC_CTX_new' function. */
#undef HAVE_HMAC_CTX_NEW
/* Define to 1 if you have the <inttypes.h> header file. */ /* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H #undef HAVE_INTTYPES_H
/* Define to 1 if you have the `nsl' library (-lnsl). */
#undef HAVE_LIBNSL
/* Define to 1 if you have the `resolv' library (-lresolv). */ /* Define to 1 if you have the `resolv' library (-lresolv). */
#undef HAVE_LIBRESOLV #undef HAVE_LIBRESOLV
@ -142,9 +135,18 @@
/* MinGW */ /* MinGW */
#undef HAVE_MINGW #undef HAVE_MINGW
/* have miniupnpc support */
#undef HAVE_MINIUPNPC
/* Define to 1 if you have the <miniupnpc/miniupnpc.h> header file. */
#undef HAVE_MINIUPNPC_MINIUPNPC_H
/* Define to 1 if you have the `mlockall' function. */ /* Define to 1 if you have the `mlockall' function. */
#undef HAVE_MLOCKALL #undef HAVE_MLOCKALL
/* Define to 1 if you have the `nanosleep' function. */
#undef HAVE_NANOSLEEP
/* NetBSD */ /* NetBSD */
#undef HAVE_NETBSD #undef HAVE_NETBSD
@ -232,27 +234,36 @@
/* Define to 1 if you have the <openssl/sha.h> header file. */ /* Define to 1 if you have the <openssl/sha.h> header file. */
#undef HAVE_OPENSSL_SHA_H #undef HAVE_OPENSSL_SHA_H
/* Define to 1 if you have the `pselect' function. */
#undef HAVE_PSELECT
/* Define to 1 if you have the `putenv' function. */ /* Define to 1 if you have the `putenv' function. */
#undef HAVE_PUTENV #undef HAVE_PUTENV
/* Define to 1 if you have the `RAND_bytes' function. */ /* Define to 1 if you have the `RAND_bytes' function. */
#undef HAVE_RAND_BYTES #undef HAVE_RAND_BYTES
/* have readline support */
#undef HAVE_READLINE
/* Define to 1 if you have the <readline/history.h> header file. */
#undef HAVE_READLINE_HISTORY_H
/* Define to 1 if you have the <readline/readline.h> header file. */
#undef HAVE_READLINE_READLINE_H
/* Define to 1 if you have the `recvmmsg' function. */
#undef HAVE_RECVMMSG
/* Define to 1 if you have the <resolv.h> header file. */ /* Define to 1 if you have the <resolv.h> header file. */
#undef HAVE_RESOLV_H #undef HAVE_RESOLV_H
/* Define to 1 if you have the `RSA_set0_key' function. */ /* Define to 1 if you have the `RSA_set0_key' function. */
#undef HAVE_RSA_SET0_KEY #undef HAVE_RSA_SET0_KEY
/* Define to 1 if the system has the type `socklen_t'. */
#undef HAVE_SOCKLEN_T
/* Solaris/SunOS */ /* Solaris/SunOS */
#undef HAVE_SOLARIS #undef HAVE_SOLARIS
/* Define to 1 if you have the <stddef.h> header file. */
#undef HAVE_STDDEF_H
/* Define to 1 if you have the <stdint.h> header file. */ /* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H #undef HAVE_STDINT_H
@ -268,9 +279,6 @@
/* Define to 1 if you have the `strsignal' function. */ /* Define to 1 if you have the `strsignal' function. */
#undef HAVE_STRSIGNAL #undef HAVE_STRSIGNAL
/* Define to 1 if the system has the type `struct addrinfo'. */
#undef HAVE_STRUCT_ADDRINFO
/* Define to 1 if the system has the type `struct arphdr'. */ /* Define to 1 if the system has the type `struct arphdr'. */
#undef HAVE_STRUCT_ARPHDR #undef HAVE_STRUCT_ARPHDR
@ -286,12 +294,6 @@
/* Define to 1 if the system has the type `struct icmp6_hdr'. */ /* Define to 1 if the system has the type `struct icmp6_hdr'. */
#undef HAVE_STRUCT_ICMP6_HDR #undef HAVE_STRUCT_ICMP6_HDR
/* Define to 1 if the system has the type `struct in6_addr'. */
#undef HAVE_STRUCT_IN6_ADDR
/* Define to 1 if the system has the type `struct in_addr'. */
#undef HAVE_STRUCT_IN_ADDR
/* Define to 1 if the system has the type `struct ip'. */ /* Define to 1 if the system has the type `struct ip'. */
#undef HAVE_STRUCT_IP #undef HAVE_STRUCT_IP
@ -304,15 +306,9 @@
/* Define to 1 if the system has the type `struct nd_opt_hdr'. */ /* Define to 1 if the system has the type `struct nd_opt_hdr'. */
#undef HAVE_STRUCT_ND_OPT_HDR #undef HAVE_STRUCT_ND_OPT_HDR
/* Define to 1 if the system has the type `struct sockaddr_in6'. */
#undef HAVE_STRUCT_SOCKADDR_IN6
/* Define to 1 if you have the <syslog.h> header file. */ /* Define to 1 if you have the <syslog.h> header file. */
#undef HAVE_SYSLOG_H #undef HAVE_SYSLOG_H
/* Define to 1 if you have the `system' function. */
#undef HAVE_SYSTEM
/* Define to 1 if you have the <sys/file.h> header file. */ /* Define to 1 if you have the <sys/file.h> header file. */
#undef HAVE_SYS_FILE_H #undef HAVE_SYS_FILE_H
@ -340,8 +336,8 @@
/* Define to 1 if you have the <sys/types.h> header file. */ /* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H #undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <sys/uio.h> header file. */ /* Define to 1 if you have the <sys/un.h> header file. */
#undef HAVE_SYS_UIO_H #undef HAVE_SYS_UN_H
/* Define to 1 if you have the <sys/wait.h> header file. */ /* Define to 1 if you have the <sys/wait.h> header file. */
#undef HAVE_SYS_WAIT_H #undef HAVE_SYS_WAIT_H
@ -352,9 +348,6 @@
/* Define to 1 if you have the `unsetenv' function. */ /* Define to 1 if you have the `unsetenv' function. */
#undef HAVE_UNSETENV #undef HAVE_UNSETENV
/* Define to 1 if you have the `usleep' function. */
#undef HAVE_USLEEP
/* Define to 1 if you have the `vsyslog' function. */ /* Define to 1 if you have the `vsyslog' function. */
#undef HAVE_VSYSLOG #undef HAVE_VSYSLOG
@ -388,9 +381,6 @@
/* Define to the version of this package. */ /* Define to the version of this package. */
#undef PACKAGE_VERSION #undef PACKAGE_VERSION
/* Define as the return type of signal handlers (`int' or `void'). */
#undef RETSIGTYPE
/* Define to 1 if you have the ANSI C header files. */ /* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS #undef STDC_HEADERS
@ -419,9 +409,6 @@
/* Version number of package */ /* Version number of package */
#undef VERSION #undef VERSION
/* Compile with support for Windows 2000 */
#undef WITH_WINDOWS2000
/* Define to 1 if on MINIX. */ /* Define to 1 if on MINIX. */
#undef _MINIX #undef _MINIX
@ -432,11 +419,11 @@
/* Define to 1 if you need to in order for `stat' and other things to work. */ /* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE #undef _POSIX_SOURCE
/* Enable BSD extensions */
#undef __USE_BSD
/* Defined if the __malloc__ attribute is not supported. */ /* Defined if the __malloc__ attribute is not supported. */
#undef __malloc__ #undef __malloc__
/* Define to `int' if <sys/types.h> does not define. */ /* Defined if the __nonnull__ attribute is not supported. */
#undef pid_t #undef __nonnull__
/* Defined if the __warn_unused_result__ attribute is not supported. */
#undef __warn_unused_result__

2473
configure vendored

File diff suppressed because it is too large Load diff

View file

@ -1,26 +1,28 @@
dnl Process this file with autoconf to produce a configure script. dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61) origcflags="$CFLAGS"
AC_INIT([tinc], [1.0.36])
AC_PREREQ(2.69)
AC_INIT([tinc], m4_esyscmd_s((git describe || echo UNKNOWN) | sed 's/release-//'))
AC_CONFIG_SRCDIR([src/tincd.c]) AC_CONFIG_SRCDIR([src/tincd.c])
AM_INIT_AUTOMAKE([1.11 check-news std-options subdir-objects nostdinc silent-rules -Wall]) AM_INIT_AUTOMAKE([std-options subdir-objects nostdinc silent-rules -Wall])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
AM_SILENT_RULES([yes]) AM_SILENT_RULES([yes])
# Enable GNU extensions. AC_USE_SYSTEM_EXTENSIONS
# Define this here, not in acconfig's @TOP@ section, since definitions
# in the latter don't make it into the configure-time tests.
AC_GNU_SOURCE
AC_DEFINE([__USE_BSD], 1, [Enable BSD extensions])
dnl Checks for programs. dnl Checks for programs.
AC_PROG_CC_C99 AC_PROG_CC
AC_PROG_CC_STDC
AC_PROG_CPP AC_PROG_CPP
AC_PROG_INSTALL AC_PROG_INSTALL
AM_PROG_CC_C_O AM_PROG_CC_C_O
dnl Check whether to enable code coverage testing, and if so, clear the default CFLAGS.
AX_CODE_COVERAGE
AS_IF([test "x$enable_code_coverage" = "xyes" -a "x$origcflags" = "x"], [CFLAGS=""])
dnl Check and set OS dnl Check and set OS
AC_CANONICAL_HOST AC_CANONICAL_HOST
@ -60,13 +62,14 @@ case $host_os in
AC_DEFINE(HAVE_BSD, 1, [Unknown BSD variant]) AC_DEFINE(HAVE_BSD, 1, [Unknown BSD variant])
;; ;;
*cygwin*) *cygwin*)
cygwin=true AC_MSG_ERROR("Cygwin is no longer supported. Use MinGW to build native Windows binaries.")
AC_DEFINE(HAVE_CYGWIN, 1, [Cygwin])
;; ;;
*mingw*) *mingw*)
mingw=true mingw=true
AC_DEFINE(HAVE_MINGW, 1, [MinGW]) AC_DEFINE(HAVE_MINGW, 1, [MinGW])
LIBS="$LIBS -lws2_32 -lgdi32 -lcrypt32" LIBS="$LIBS -lws2_32 -lgdi32 -lcrypt32 -liphlpapi"
LDFLAGS="$LDFLAGS -static"
CPPFLAGS="$CPPFLAGS -DMINIUPNP_STATICLIB"
;; ;;
*) *)
AC_MSG_ERROR("Unknown operating system.") AC_MSG_ERROR("Unknown operating system.")
@ -88,6 +91,7 @@ AC_ARG_ENABLE(vde,
AS_HELP_STRING([--enable-vde], [enable support for Virtual Distributed Ethernet]), AS_HELP_STRING([--enable-vde], [enable support for Virtual Distributed Ethernet]),
[ AS_IF([test "x$enable_vde" = "xyes"], [ AS_IF([test "x$enable_vde" = "xyes"],
[ AC_CHECK_HEADERS(libvdeplug_dyn.h, [], [AC_MSG_ERROR([VDE plug header files not found.]); break]) [ AC_CHECK_HEADERS(libvdeplug_dyn.h, [], [AC_MSG_ERROR([VDE plug header files not found.]); break])
AC_CHECK_LIB(dl, dlopen, [LIBS="$LIBS -ldl"], [AC_MSG_ERROR([VDE plug depends on libdl.]); break])
AC_DEFINE(ENABLE_VDE, 1, [Support for VDE]) AC_DEFINE(ENABLE_VDE, 1, [Support for VDE])
vde=true vde=true
], ],
@ -107,13 +111,6 @@ AC_ARG_ENABLE(tunemu,
[tunemu=false] [tunemu=false]
) )
AC_ARG_WITH(windows2000,
AS_HELP_STRING([--with-windows2000], [compile with support for Windows 2000. This disables support for tunneling over existing IPv6 networks.]),
[ AS_IF([test "x$with_windows2000" = "xyes"],
[AC_DEFINE(WITH_WINDOWS2000, 1, [Compile with support for Windows 2000])])
]
)
AC_ARG_WITH(systemd, AC_ARG_WITH(systemd,
AS_HELP_STRING([--with-systemd@<:@=DIR@:>@], [install systemd service files @<:@to DIR if specified@:>@]), AS_HELP_STRING([--with-systemd@<:@=DIR@:>@], [install systemd service files @<:@to DIR if specified@:>@]),
[ systemd=true; systemd_path="$with_systemd" ], [ systemd=true; systemd_path="$with_systemd" ],
@ -137,12 +134,8 @@ AM_CONDITIONAL(WITH_SYSTEMD, test "$systemd" = true)
AC_CACHE_SAVE AC_CACHE_SAVE
if test -d /sw/include ; then AS_IF([test -d /sw/include], [CPPFLAGS="$CPPFLAGS -I/sw/include"])
CPPFLAGS="$CPPFLAGS -I/sw/include" AS_IF([test -d /sw/lib], [LIBS="$LIBS -L/sw/lib"])
fi
if test -d /sw/lib ; then
LIBS="$LIBS -L/sw/lib"
fi
dnl Compiler hardening flags dnl Compiler hardening flags
dnl No -fstack-protector-all because it doesn't work on all platforms or architectures. dnl No -fstack-protector-all because it doesn't work on all platforms or architectures.
@ -169,13 +162,11 @@ AS_IF([test "x$enable_hardening" != "xno"],
] ]
); );
dnl Checks for libraries.
dnl Checks for header files. dnl Checks for header files.
dnl We do this in multiple stages, because unlike Linux all the other operating systems really suck and don't include their own dependencies. dnl We do this in multiple stages, because unlike Linux all the other operating systems really suck and don't include their own dependencies.
AC_CHECK_HEADERS([syslog.h sys/file.h sys/ioctl.h sys/mman.h sys/param.h sys/resource.h sys/socket.h sys/time.h sys/uio.h sys/wait.h netdb.h arpa/inet.h arpa/nameser.h dirent.h getopt.h]) AC_CHECK_HEADERS([syslog.h sys/file.h sys/ioctl.h sys/mman.h sys/param.h sys/resource.h sys/socket.h sys/time.h sys/un.h sys/wait.h netdb.h arpa/inet.h dirent.h getopt.h stddef.h])
AC_CHECK_HEADERS([net/if.h net/if_types.h linux/if_tun.h net/if_tun.h net/if_utun.h net/tun/if_tun.h net/if_tap.h net/tap/if_tap.h net/ethernet.h net/if_arp.h netinet/in_systm.h netinet/in.h netinet/in6.h netpacket/packet.h], AC_CHECK_HEADERS([net/if.h net/if_types.h net/ethernet.h net/if_arp.h netinet/in_systm.h netinet/in.h netinet/in6.h netpacket/packet.h],
[], [], [#include "$srcdir/src/have.h"] [], [], [#include "$srcdir/src/have.h"]
) )
AC_CHECK_HEADERS([netinet/if_ether.h netinet/ip.h netinet/ip6.h resolv.h], AC_CHECK_HEADERS([netinet/if_ether.h netinet/ip.h netinet/ip6.h resolv.h],
@ -186,48 +177,77 @@ AC_CHECK_HEADERS([netinet/tcp.h netinet/ip_icmp.h netinet/icmp6.h],
) )
dnl Checks for typedefs, structures, and compiler characteristics. dnl Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_PID_T
tinc_ATTRIBUTE(__malloc__) tinc_ATTRIBUTE(__malloc__)
tinc_ATTRIBUTE(__nonnull__)
tinc_ATTRIBUTE(__warn_unused_result__)
AC_CHECK_TYPES([socklen_t, struct ether_header, struct arphdr, struct ether_arp, struct in_addr, struct addrinfo, struct ip, struct icmp, struct in6_addr, struct sockaddr_in6, struct ip6_hdr, struct icmp6_hdr, struct nd_neighbor_solicit, struct nd_opt_hdr], , , AC_CHECK_TYPES([struct ether_header, struct arphdr, struct ether_arp, struct ip, struct icmp, struct ip6_hdr, struct icmp6_hdr, struct nd_neighbor_solicit, struct nd_opt_hdr], , ,
[#include "$srcdir/src/have.h"] [#include "$srcdir/src/have.h"]
) )
dnl Checks for library functions. dnl Checks for library functions.
AC_TYPE_SIGNAL AC_CHECK_FUNCS([asprintf daemon fchmod flock fork gettimeofday mlockall putenv recvmmsg strsignal nanosleep unsetenv vsyslog devname fdevname],
AC_CHECK_FUNCS([asprintf daemon fchmod flock fork gettimeofday mlockall pselect putenv strsignal system unsetenv usleep vsyslog devname fdevname],
[], [], [#include "$srcdir/src/have.h"] [], [], [#include "$srcdir/src/have.h"]
) )
AC_CHECK_FUNC(getopt_long, [getopt=true; AC_DEFINE(HAVE_GETOPT_LONG, 1, [getopt_long()])], [getopt=false]) AC_CHECK_FUNC(getopt_long, [getopt=true; AC_DEFINE(HAVE_GETOPT_LONG, 1, [getopt_long()])], [getopt=false])
AM_CONDITIONAL(GETOPT, test "$getopt" = true) AM_CONDITIONAL(GETOPT, test "$getopt" = true)
dnl Support for SunOS
AC_CHECK_FUNC(socket, [], [
AC_CHECK_LIB(socket, connect)
])
AC_CHECK_FUNC(gethostbyname, [], [
AC_CHECK_LIB(nsl, gethostbyname)
])
AC_CHECK_DECLS([freeaddrinfo, gai_strerror, getaddrinfo, getnameinfo],
[], [], [#include "$srcdir/src/have.h"]
)
AC_CHECK_DECLS([res_init], [AC_CHECK_LIB(resolv, res_init)], [], [ AC_CHECK_DECLS([res_init], [AC_CHECK_LIB(resolv, res_init)], [], [
#include <netinet/in.h> #include <netinet/in.h>
#include <resolv.h> #include <resolv.h>
]) ])
dnl Operating system specific checks
case $host_os in
*linux*)
AC_CHECK_HEADERS([linux/if_tun.h],
[], [AC_MSG_ERROR([Required header file missng])], [#include "$srcdir/src/have.h"]
)
;;
*bsd*|*dragonfly*|*darwin*)
AC_CHECK_HEADERS([net/if_tun.h net/if_utun.h net/tun/if_tun.h net/if_tap.h net/tap/if_tap.h],
[], [], [#include "$srcdir/src/have.h"]
)
;;
*solaris*)
AC_CHECK_FUNC(socket, [], [AC_CHECK_LIB(socket, connect)])
;;
*)
;;
esac
AC_CACHE_SAVE AC_CACHE_SAVE
AC_ARG_ENABLE(legacy-protocol,
AS_HELP_STRING([--disable-legacy-protocol], [disable support for the legacy (tinc 1.0) protocol]),
[ AS_IF([test "x$enable_legacy_protocol" = "xno"],
[ AC_DEFINE(DISABLE_LEGACY, 1, [Disable support for the legacy (tinc 1.0) protocol]) ])
]
)
dnl These are defined in files in m4/ dnl These are defined in files in m4/
dnl AC_ARG_WITH(libgcrypt, AC_HELP_STRING([--with-libgcrypt], [enable use of libgcrypt instead of OpenSSL])], [])
dnl AC_ARG_WITH(openssl, AC_HELP_STRING([--without-openssl], [disable support for OpenSSL])], [])
tinc_CURSES
tinc_READLINE
tinc_ZLIB tinc_ZLIB
tinc_LZO tinc_LZO
tinc_OPENSSL
AS_IF([test "x$enable_legacy_protocol" != "xno"],
[AS_IF([test -n "$with_libgcrypt"],
[gcrypt=true; tinc_LIBGCRYPT],
[openssl=true; tinc_OPENSSL])
]
)
AM_CONDITIONAL(OPENSSL, test -n "$openssl")
AM_CONDITIONAL(GCRYPT, test -n "$gcrypt")
tinc_MINIUPNPC
AM_CONDITIONAL(MINIUPNPC, test "x$enable_miniupnpc" = "xyes")
dnl Check if support for jumbograms is requested dnl Check if support for jumbograms is requested
AC_ARG_ENABLE(jumbograms, AC_ARG_ENABLE(jumbograms,
@ -242,6 +262,6 @@ if test "x$runstatedir" = "x"; then
AC_SUBST([runstatedir], ['${localstatedir}/run']) AC_SUBST([runstatedir], ['${localstatedir}/run'])
fi fi
AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile systemd/Makefile]) AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile test/Makefile test/testlib.sh systemd/Makefile bash_completion.d/Makefile])
AC_OUTPUT AC_OUTPUT

35
debian/NEWS vendored
View file

@ -1,6 +1,6 @@
tinc (1.0.27-1) unstable; urgency=medium tinc (1.1~pre11-1) experimental; urgency=medium
This package now provides native systemd service files, allowing multiple This package now provides a native systemd service file, allowing multiple
instances of tinc to be managed. Existing networks listed in instances of tinc to be managed. Existing networks listed in
/etc/tinc/nets.boot will be converted to service instances once during this /etc/tinc/nets.boot will be converted to service instances once during this
upgrade. Afterwards, you can enable and disable networks using: upgrade. Afterwards, you can enable and disable networks using:
@ -11,4 +11,33 @@ tinc (1.0.27-1) unstable; urgency=medium
If you do not have systemd installed, the SysV init script will continue to If you do not have systemd installed, the SysV init script will continue to
work as usual. For more information, see README.Debian. work as usual. For more information, see README.Debian.
-- Guus Sliepen <guus@debian.org> Sun, 10 Apr 2016 01:33:55 +0200 Please note that tinc 1.1pre11 is backwards compatible with tinc 1.0.x, but
is not backwards compatible with 1.1pre1 to 1.1pre10 nodes if
ExperimentalProtocol is enabled, which is the default.
If you have more than one node running an 1.1 prerelease version in your VPN,
make sure you upgrade them all at the same time, or disable the new protocol
by adding the following line to tinc.conf:
ExperimentalProtocol = no
If you do want to use the new protocol, be aware that this version of tinc
switched to Ed25519 keys. You can generate a new Ed25519 keypair by running
the following command:
tinc -n <netname> generate-ed25519-keys
You have to manually restart tinc after this upgrade.
-- Guus Sliepen <guus@debian.org> Sat, 08 Jan 2015 14:02:27 +0100
tinc (1.1~pre2-1) experimental; urgency=low
tinc-1.1 has separate control utility, tinc (without the d), which is now
used to start/stop tinc instances, to reload configuration, to get various
information about running tincd (including dump of nodes and connections)
and so on. tincd still reacts to some signals as before, but this usage is
deprecated. In particular, -k option is now gone. Also, node/connection/etc
dumps are produced on tincctl stdout, not into syslog.
-- Michael Tokarev <mjt@tls.msk.ru> Sun, 07 Aug 2011 13:16:17 +0400

View file

@ -9,7 +9,7 @@ There are several ways in which tinc may be automatically started at boot:
Systemd Systemd
------- -------
Since 1.0.27-1, the tinc package comes with native systemd service files. Since 1.1~pre11-1, the tinc package comes with native systemd service files.
To enable and start a net, call: To enable and start a net, call:
systemctl enable tinc@<netname> systemctl enable tinc@<netname>
@ -57,7 +57,6 @@ tinc-config <directory>
tinc-debug <level> tinc-debug <level>
tinc-mlock yes tinc-mlock yes
tinc-logfile <filename> tinc-logfile <filename>
tinc-pidfile <filename>
tinc-chroot yes tinc-chroot yes
tinc-user <username> tinc-user <username>
@ -70,11 +69,10 @@ iface vpn inet static
tinc-debug 1 tinc-debug 1
tinc-mlock yes tinc-mlock yes
tinc-user nobody tinc-user nobody
tinc-pidfile /tmp/tinc.pid
This will start a tinc daemon that reads its configuration from This will start a tinc daemon that reads its configuration from
/etc/tinc/myvpn, logs at debug level 1, locks itself in RAM, runs as user /etc/tinc/myvpn, logs at debug level 1, locks itself in RAM, runs as user
nobody, and creates a network interface called "vpn". Ifup then sets the nobody, and creates a network interface called "vpn". Ifup then sets the
address and netmask on that interface. address and netmask on that interface.
-- Guus Sliepen <guus@debian.org>, Sun, 10 April 2016, 01:38:08 +0200 -- Guus Sliepen <guus@debian.org>, Thu, 8 January 2015, 13:37:46 +0100

258
debian/changelog vendored
View file

@ -1,163 +1,88 @@
tinc (1.0.36-2) unstable; urgency=medium tinc (1.1~pre18-1) experimental; urgency=medium
* Disable support for libvdeplug. Closes: #973233 * New upstream release.
- The patch for EVP_DecryptUpdate is no longer necessary.
* Disable support for VDE.
-- Guus Sliepen <guus@debian.org> Sun, 22 Nov 2020 10:40:27 +0100 -- Guus Sliepen <guus@debian.org> Sun, 27 Jun 2021 20:10:22 +0200
tinc (1.0.36-1) unstable; urgency=medium tinc (1.1~pre17-1.2) experimental; urgency=medium
* New upstream version 1.0.36 * Non-maintainer upload.
* Add Vcs tags to debian/control. * Add patch to fix EVP_DecryptUpdate issue. Closes: #923438
-- Don Armstrong <don@debian.org> Sun, 31 May 2020 15:11:34 -0700
tinc (1.1~pre17-1.1) experimental; urgency=medium
* Non-maintainer upload.
* Fix systemd service install path. Closes: #910618
* Fix typo in --enable-miniupnpc option.
-- Shengjing Zhu <zhsj@debian.org> Wed, 10 Oct 2018 10:58:42 +0800
tinc (1.1~pre17-1) experimental; urgency=medium
* New upstream release.
- Includes fixes for CVE-2018-16737, CVE-2018-16738.
- The GUI is no longer part of upstream, so has been removed.
* Link with the miniupnpc library.
* Bump Standards-Version. * Bump Standards-Version.
* Bump debian/compat.
-- Guus Sliepen <guus@debian.org> Mon, 26 Aug 2019 14:17:21 +0200 -- Guus Sliepen <guus@debian.org> Mon, 08 Oct 2018 16:32:57 +0200
tinc (1.0.35-2) unstable; urgency=medium tinc (1.1~pre15-1) experimental; urgency=medium
* Bump Standards-Version and Build-Depend on debhelper-compat (= 12).
* Remove calls to dh_installinit and dh_systemd_start from debian/rules,
compat level 12 does the right thing by default.
* Ensure we clean up doc/tinc.info.
-- Guus Sliepen <guus@debian.org> Mon, 28 Jan 2019 21:54:45 +0100
tinc (1.0.35-1) unstable; urgency=medium
* New upstream release.
- Includes fixes for CVE-2018-16737, CVE-2018-16738, CVE-2018-16758.
-- Guus Sliepen <guus@debian.org> Mon, 08 Oct 2018 16:09:06 +0200
tinc (1.0.34-1) unstable; urgency=medium
[ Guus Sliepen ]
* New upstream release.
- Fixes a potential segmentation fault when connecting to an IPv6
peer via a proxy. Closes: #887401
* Add support for the $EXTRA variable in /etc/default/tinc when using
systemd. Closes: #887116
[ Benda Xu ]
* Prevent possible incorrect IPv6 checksums due to function inlining.
Closes: #891400
-- Guus Sliepen <guus@debian.org> Tue, 12 Jun 2018 23:00:49 +0200
tinc (1.0.33-1) unstable; urgency=medium
* New upstream release. * New upstream release.
* Bump Standards-Version.
* Bump debian/compat.
* Don't use while loops checking PID files anymore, the tinc CLI will
wait properly for the daemon to start or stop. Closes: #772379, #832784
* Clean up scripts as suggested by Dominik George. Closes: #832781
* Test for /etc/default/tinc before trying to source it. Closes: #777262 * Test for /etc/default/tinc before trying to source it. Closes: #777262
* Use --runstatedir=/run.
-- Guus Sliepen <guus@debian.org> Sat, 04 Nov 2017 16:22:06 +0100 -- Guus Sliepen <guus@debian.org> Tue, 05 Sep 2017 21:03:51 +0200
tinc (1.0.32-1) unstable; urgency=medium tinc (1.1~pre12-1) experimental; urgency=medium
* New upstream release.
* Add a note to new nets.boot files that it is not used with systemd.
Closes: #841052
* In the post-down script, read the pid file only once. Closes: #832784
* Explicitly use /bin/sleep from coreutils. Closes: #772379
* Bump Standards-Version.
-- Guus Sliepen <guus@debian.org> Tue, 05 Sep 2017 20:23:36 +0200
tinc (1.0.31-1) unstable; urgency=medium
* New upstream release. * New upstream release.
* Bump Standards-Version. * Bump Standards-Version.
* Bump debian/compat. * Depend on python-wxgtk3.0 for the GUI.
* Add missing Depends: lsb-base. * Use dh --with python2.
* Add Build-Depends for dh-python.
* Update links in debian/control and debian/copyright.
-- Guus Sliepen <guus@debian.org> Sun, 15 Jan 2017 16:20:40 +0100 -- Guus Sliepen <guus@debian.org> Sun, 24 Apr 2016 14:51:14 +0200
tinc (1.0.29-2) unstable; urgency=medium tinc (1.1~pre11-1) experimental; urgency=medium
* Rebuild with libssl-dev from unstable.
-- Guus Sliepen <guus@debian.org> Thu, 27 Oct 2016 13:09:46 +0200
tinc (1.0.29-1) unstable; urgency=medium
* New upstream release. * New upstream release.
* Bump debian/compat. * Update NEWS.Debian to reflect that tincctl has been renamed to tinc.
Closes: #729889
-- Guus Sliepen <guus@debian.org> Mon, 10 Oct 2016 22:30:25 +0200 * Warn about incompatibility with previous 1.1preX releases, and that new
Ed25519 keys should be generated.
tinc (1.0.28-1) unstable; urgency=medium * Add native systemd service files.
* New upstream release.
- Fixes FTBFS on kfreebsd.
* Systemd service files are now provided by upstream.
-- Guus Sliepen <guus@debian.org> Sun, 10 Apr 2016 15:44:28 +0200
tinc (1.0.27-2) unstable; urgency=medium
* Fix tinc@.service.
-- Guus Sliepen <guus@debian.org> Sun, 10 Apr 2016 12:45:33 +0200
tinc (1.0.27-1) unstable; urgency=medium
* New upstream release.
* Bump Standards-Version.
* Add native systemd unit files.
* Automatically convert networks listed in nets.boot to systemd service * Automatically convert networks listed in nets.boot to systemd service
instances on upgrade. instances on upgrade.
* Don't restart tinc on upgrade for now.
-- Guus Sliepen <guus@debian.org> Sun, 10 Apr 2016 01:39:16 +0200 -- Guus Sliepen <guus@debian.org> Thu, 08 Jan 2015 14:51:34 +0100
tinc (1.0.26-1) unstable; urgency=medium tinc (1.1~pre9-1) experimental; urgency=low
* New upstream release.
* Use the contents, not the presence, of the pidfile to check that tincd is
shut down properly. Closes: #774682
* Bump Standards-Version.
-- Guus Sliepen <guus@debian.org> Sun, 05 Jul 2015 17:23:08 +0200
tinc (1.0.24-2) unstable; urgency=medium
* Improve the init script: stopping tinc now waits for the process to
terminate. If that doesn't happen in 5 seconds, it will send the TERM
signal again (which helps if tinc is waiting for a script to finish
executing). It now also detects whether the process mentioned in the PID
file is actually running, and if not it will exit early and without
warnings. Closes: #748107
-- Guus Sliepen <guus@debian.org> Wed, 14 May 2014 21:44:16 +0200
tinc (1.0.24-1) unstable; urgency=medium
[ Guus Sliepen ]
* New upstream release
* Add a debian/watch file.
* Bump Standards-Version.
[ Gian Piero Carrubba ]
* Allow resource limits to be set in /etc/default/tinc.
Closes: #690685, #704702
-- Guus Sliepen <guus@debian.org> Sun, 11 May 2014 21:17:13 +0200
tinc (1.0.23-2) unstable; urgency=low
* Use if-statements instead of && in shell scripts. Closes: #731279
The && operator does not clear the error status, and if the next statement
in a shell script does not change the error status it would cause the
script to prematurely exit. Thanks to Peter Reinholdtsen for spotting it.
* Use absolute path to tincd in the if-post-down script.
-- Guus Sliepen <guus@debian.org> Thu, 05 Dec 2013 09:41:13 +0000
tinc (1.0.23-1) unstable; urgency=low
* New upstream release. * New upstream release.
-- Guus Sliepen <guus@debian.org> Sat, 19 Oct 2013 21:06:05 +0200 -- Guus Sliepen <guus@debian.org> Sun, 08 Sep 2013 18:00:28 +0200
tinc (1.0.22-1) unstable; urgency=low tinc (1.1~pre8-2) experimental; urgency=low
* Run make clean after the configure step to get rid of .o files that were
accidentily left in the orig.tar.gz.
-- Guus Sliepen <guus@debian.org> Wed, 14 Aug 2013 16:13:43 +0200
tinc (1.1~pre8-1) experimental; urgency=low
* New upstream release. * New upstream release.
- Handles whitespace between command line flags and optional arguments. - Handles whitespace between command line flags and optional arguments.
@ -167,20 +92,73 @@ tinc (1.0.22-1) unstable; urgency=low
* Don't use texi2html anymore, use automake's install-html target which uses * Don't use texi2html anymore, use automake's install-html target which uses
makeinfo. makeinfo.
-- Guus Sliepen <guus@debian.org> Wed, 14 Aug 2013 15:34:29 +0200 -- Guus Sliepen <guus@debian.org> Wed, 14 Aug 2013 15:34:41 +0200
tinc (1.0.21-1) unstable; urgency=low tinc (1.1~pre7-2) experimental; urgency=low
[ Gian Piero Carrubba ]
* Init script fails to pass extra arguments to tincd. Closes: #704701
+ Remove the '--' as it is passed unaltered to tincd, preventing it to read
trailing parameters.
+ Pass extra arguments also when restarting the daemon.
* Set process limits when started by ifupdown. Closes: #704702
[ Guus Sliepen ]
* Check whether the tincd process is still running in the if-post-down script.
Closes: #704708
-- Guus Sliepen <guus@debian.org> Wed, 01 May 2013 10:41:31 +0200
tinc (1.1~pre7-1) experimental; urgency=high
* New upstream release. * New upstream release.
- Includes fix for CVE-2013-1428. - Drop packets forwarded via TCP if they are too big (CVE-2013-1428).
-- Guus Sliepen <guus@debian.org> Sun, 05 May 2013 10:42:33 +0200 -- Guus Sliepen <guus@debian.org> Tue, 23 Apr 2013 11:37:38 +0200
tinc (1.0.19-3) unstable; urgency=high tinc (1.1~pre6-1) experimental; urgency=low
* Drop packets forwarded via TCP if they are too big (CVE-2013-1428). * New upstream release.
-- Guus Sliepen <guus@debian.org> Fri, 12 Apr 2013 22:52:10 +0200 -- Guus Sliepen <guus@debian.org> Wed, 20 Feb 2013 16:53:33 +0100
tinc (1.1~pre4-1) experimental; urgency=low
[ Gian Piero Carrubba ]
* Allow resource limits to be set in /etc/default/tinc. Closes: #690685
[ Guus Sliepen ]
* New upstream release.
-- Guus Sliepen <guus@debian.org> Wed, 05 Dec 2012 23:05:01 +0100
tinc (1.1~pre3-1) experimental; urgency=low
* New upstream release.
* Bump Standards-Version.
* Enable parallel builds.
* Bump debian/compat to 9, so tinc gets build with hardening flags.
* Move tinc-gui to its own package.
-- Guus Sliepen <guus@debian.org> Sun, 14 Oct 2012 23:51:21 +0200
tinc (1.1~pre2-2) experimental; urgency=low
* add forgotten build-depend on libncurses5-dev for new `tincctl top'
* add libevent-dev build dependency
* remove build dependency on gettext
-- Michael Tokarev <mjt@tls.msk.ru> Sun, 07 Aug 2011 17:32:39 +0400
tinc (1.1~pre2-1) experimental; urgency=low
* first cut of 1.1-tobe.
Rewrote control scripts et al to use tincctl.
* build-depend on libssl >>1.0.0 to get proper EC support
* remove crypto-related symlinks from src/ in clean --
probably should go into upstream makefile instead
-- Michael Tokarev <mjt@tls.msk.ru> Sun, 07 Aug 2011 12:57:15 +0400
tinc (1.0.19-2) unstable; urgency=low tinc (1.0.19-2) unstable; urgency=low

1
debian/compat vendored Normal file
View file

@ -0,0 +1 @@
11

12
debian/control vendored
View file

@ -2,17 +2,13 @@ Source: tinc
Section: net Section: net
Priority: optional Priority: optional
Maintainer: Guus Sliepen <guus@debian.org> Maintainer: Guus Sliepen <guus@debian.org>
Standards-Version: 4.4.0 Standards-Version: 4.2.1
Build-Depends: libssl-dev, debhelper-compat (= 12), gettext, texinfo, zlib1g-dev, liblzo2-dev Build-Depends: libssl-dev (>>1.0.0), debhelper (>= 11), texinfo, zlib1g-dev, liblzo2-dev, libncurses5-dev, libreadline-dev, libminiupnpc-dev, quilt
Homepage: http://www.tinc-vpn.org/ Homepage: https://www.tinc-vpn.org/
Vcs-Browser: https://salsa.debian.org/guus/tinc
Vcs-Git: https://salsa.debian.org/guus/tinc.git
Rules-Requires-Root: no
Package: tinc Package: tinc
Architecture: any Architecture: any
Pre-Depends: ${misc:Pre-Depends} Depends: ${shlibs:Depends}, ${misc:Depends}
Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base (>= 3.0-6)
Description: Virtual Private Network daemon Description: Virtual Private Network daemon
tinc is a daemon with which you can create a virtual private network tinc is a daemon with which you can create a virtual private network
(VPN). One daemon can handle multiple connections, so you can (VPN). One daemon can handle multiple connections, so you can

10
debian/copyright vendored
View file

@ -1,14 +1,14 @@
This package was debianized by Ivo Timmermans <ivo@debian.org> on This package was debianized by Ivo Timmermans <ivo@debian.org> on
Fri, 21 Apr 2000 17:07:50 +0200. Fri, 21 Apr 2000 17:07:50 +0200.
It was downloaded from http://www.tinc-vpn.org/ It was downloaded from https://www.tinc-vpn.org/
Upstream Authors: Upstream Authors:
Guus Sliepen <guus@tinc-vpn.org> Guus Sliepen <guus@tinc-vpn.org>
Ivo Timmermans <ivo@tinc-vpn.org> Ivo Timmermans
Copyright (C) 1998-2005 Ivo Timmermans Copyright (C) 1998-2005 Ivo Timmermans
1998-2008 Guus Sliepen <guus@tinc-vpn.org> 1998-2016 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -28,7 +28,7 @@ all other requirements of the GPL are met.
The following applies to the LZO library: The following applies to the LZO library:
Hereby I grant a special exception to the tinc VPN project Hereby I grant a special exception to the tinc VPN project
(http://tinc.nl.linux.org/) to link the LZO library with the OpenSSL library (https://wwww.tinc-vpn.org/) to link the LZO library with the OpenSSL library
(http://www.openssl.org). (https://openssl.org).
Markus F.X.J. Oberhumer Markus F.X.J. Oberhumer

View file

@ -0,0 +1,879 @@
From cc521f3d5f3a0c758163c871e75f5e533e86771b Mon Sep 17 00:00:00 2001
From: Guus Sliepen <guus@tinc-vpn.org>
Date: Mon, 2 Aug 2021 23:53:13 +0200
Subject: [PATCH 01/10] Add AES-256-GCM support to SPTPS.
This also adds a simple cipher suite negotiation, where peers announce the
ciphers they support, and their preferred cipher. Since we need to bump the
SPTPS version anyway, also prefer little endian over network byte order.
---
doc/SPTPS | 45 +++++--
src/invitation.c | 11 +-
src/protocol_auth.c | 25 +++-
src/protocol_key.c | 30 ++++-
src/sptps.c | 310 +++++++++++++++++++++++++++++++++-----------
src/sptps.h | 44 ++++++-
src/sptps_test.c | 13 +-
7 files changed, 382 insertions(+), 96 deletions(-)
diff --git a/doc/SPTPS b/doc/SPTPS
index 2d8fee5b..2da27604 100644
--- a/doc/SPTPS
+++ b/doc/SPTPS
@@ -18,8 +18,8 @@ Stream record layer
A record consists of these fields:
-- uint32_t seqno (network byte order)
-- uint16_t length (network byte order)
+- uint32_t seqno (little endian)
+- uint16_t length (little endian)
- uint8_t type
- opaque data[length]
- opaque hmac[HMAC_SIZE] (HMAC over all preceding fields)
@@ -45,8 +45,8 @@ Datagram record layer
A record consists of these fields:
-- uint16_t length (network byte order)
-- uint32_t seqno (network byte order)
+- uint16_t length (little endian)
+- uint32_t seqno (little endian)
- uint8_t type
- opaque data[length]
- opaque hmac[HMAC_SIZE] (HMAC over all preceding fields)
@@ -75,7 +75,7 @@ SIG ->
...encrypt and HMAC using session keys from now on...
App ->
- <- App
+ <- App
...
...
@@ -91,7 +91,7 @@ ACK ->
...encrypt and HMAC using new session keys from now on...
App ->
- <- App
+ <- App
...
...
---------------------
@@ -102,7 +102,11 @@ connection.
Key EXchange message:
-- uint8_t kex_version (always 0 in this version of SPTPS)
+- uint8_t kex_version (always 1 in this version of SPTPS)
+- uint8_t
+ - high 4 bits: public key algorithm
+ - low 4 bits: preferred cipher suite
+- uint16_t bitmask of cipher suites supported
- opaque nonce[32] (random number)
- opaque ecdh_key[ECDH_SIZE]
@@ -162,9 +166,34 @@ The expanded key is used as follows:
Where initiator_cipher_key is the key used by session initiator to encrypt
messages sent to the responder.
+Public key suites
+-----------------
+
+0: Ed25519 + SHA512
+1: Ed448 + SHAKE256?
+
+Symmetric cipher suites
+-----------------------
+
+Value in parentheses is the static priority used to break ties in cipher suite
+negotiation. We favor those algorithms that run faster without hardware
+acceleration.
+
+0: Chacha20-Poly1305 (1)
+1: AES256-GCM (0)
+
+Cipher suite selection
+----------------------
+
+Public key suites are required to match on both sides. The symmetric suite is chosen as follows:
+
+1. AND the supported cipher suite bitmasks
+2. If both preferred cipher suites are possible, choose the one with the highest static priority.
+3. If only one is possible, choose that one.
+4. If none is possible, choose the suite from the resulting bitmask that has the highest static priority.
+
TODO:
-----
- Document format of ECDH public key, ECDSA signature
-- Document how CTR mode is used
- Refer to TLS RFCs where appropriate
diff --git a/src/invitation.c b/src/invitation.c
index cff9e727..6c49af48 100644
--- a/src/invitation.c
+++ b/src/invitation.c
@@ -1399,7 +1399,16 @@ next:
}
// Start an SPTPS session
- if(!sptps_start(&sptps, NULL, true, false, key, hiskey, "tinc invitation", 15, invitation_send, invitation_receive)) {
+ sptps_params_t params = {
+ .initiator = true,
+ .mykey = key,
+ .hiskey = hiskey,
+ .label = "tinc invitation",
+ .send_data = invitation_send,
+ .receive_record = invitation_receive,
+ };
+
+ if(!sptps_start(&sptps, &params)) {
ecdsa_free(hiskey);
ecdsa_free(key);
return 1;
diff --git a/src/protocol_auth.c b/src/protocol_auth.c
index 22254575..050b266c 100644
--- a/src/protocol_auth.c
+++ b/src/protocol_auth.c
@@ -412,7 +412,17 @@ bool id_h(connection_t *c, const char *request) {
c->protocol_minor = 2;
- return sptps_start(&c->sptps, c, false, false, invitation_key, c->ecdsa, "tinc invitation", 15, send_meta_sptps, receive_invitation_sptps);
+ sptps_params_t params = {
+ .handle = c,
+ .initiator = false,
+ .mykey = invitation_key,
+ .hiskey = c->ecdsa,
+ .label = "tinc invitation",
+ .send_data = send_meta_sptps,
+ .receive_record = receive_invitation_sptps,
+ };
+
+ return sptps_start(&c->sptps, &params);
}
/* Check if identity is a valid name */
@@ -507,7 +517,18 @@ bool id_h(connection_t *c, const char *request) {
snprintf(label, labellen, "tinc TCP key expansion %s %s", c->name, myself->name);
}
- return sptps_start(&c->sptps, c, c->outgoing, false, myself->connection->ecdsa, c->ecdsa, label, labellen, send_meta_sptps, receive_meta_sptps);
+ sptps_params_t params = {
+ .handle = c,
+ .initiator = c->outgoing,
+ .mykey = myself->connection->ecdsa,
+ .hiskey = c->ecdsa,
+ .label = label,
+ .labellen = sizeof(label),
+ .send_data = send_meta_sptps,
+ .receive_record = receive_meta_sptps,
+ };
+
+ return sptps_start(&c->sptps, &params);
} else {
return send_metakey(c);
}
diff --git a/src/protocol_key.c b/src/protocol_key.c
index 740d2fb4..da53c16c 100644
--- a/src/protocol_key.c
+++ b/src/protocol_key.c
@@ -128,7 +128,20 @@ bool send_req_key(node_t *to) {
to->status.waitingforkey = true;
to->last_req_key = now.tv_sec;
to->incompression = myself->incompression;
- return sptps_start(&to->sptps, to, true, true, myself->connection->ecdsa, to->ecdsa, label, labellen, send_initial_sptps_data, receive_sptps_record);
+
+ sptps_params_t params = {
+ .handle = to,
+ .initiator = true,
+ .datagram = true,
+ .mykey = myself->connection->ecdsa,
+ .hiskey = to->ecdsa,
+ .label = label,
+ .labellen = sizeof(label),
+ .send_data = send_initial_sptps_data,
+ .receive_record = receive_sptps_record,
+ };
+
+ return sptps_start(&to->sptps, &params);
}
return send_request(to->nexthop->connection, "%d %s %s", REQ_KEY, myself->name, to->name);
@@ -249,7 +262,20 @@ static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, no
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, labellen, send_sptps_data_myself, receive_sptps_record);
+
+ sptps_params_t params = {
+ .handle = from,
+ .initiator = false,
+ .datagram = true,
+ .mykey = myself->connection->ecdsa,
+ .hiskey = from->ecdsa,
+ .label = label,
+ .labellen = sizeof(label),
+ .send_data = send_sptps_data_myself,
+ .receive_record = receive_sptps_record,
+ };
+
+ sptps_start(&from->sptps, &params);
sptps_receive_data(&from->sptps, buf, len);
send_mtu_info(myself, from, MTU);
return true;
diff --git a/src/sptps.c b/src/sptps.c
index a0483c34..33c41424 100644
--- a/src/sptps.c
+++ b/src/sptps.c
@@ -28,6 +28,10 @@
#include "sptps.h"
#include "random.h"
+#ifdef HAVE_OPENSSL
+#include <openssl/evp.h>
+#endif
+
unsigned int sptps_replaywin = 16;
/*
@@ -90,25 +94,159 @@ static void warning(sptps_t *s, const char *format, ...) {
va_end(ap);
}
+static bool cipher_init(uint8_t suite, void **ctx, const uint8_t *key, bool key_half) {
+ switch(suite) {
+ case SPTPS_CHACHA_POLY1305:
+ *ctx = chacha_poly1305_init();
+ return ctx && chacha_poly1305_set_key(*ctx, key + (key_half ? CHACHA_POLY1305_KEYLEN : 0));
+
+ case SPTPS_AES256_GCM:
+#ifdef HAVE_OPENSSL
+ *ctx = EVP_CIPHER_CTX_new();
+
+ if(!ctx) {
+ return false;
+ }
+
+ return EVP_EncryptInit_ex(*ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)
+ && EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_AEAD_SET_IVLEN, 4, NULL)
+ && EVP_EncryptInit_ex(*ctx, NULL, NULL, key + (key_half ? 32 : 0), key);
+#endif
+
+ default:
+ return false;
+ }
+}
+
+static void cipher_exit(uint8_t suite, void *ctx) {
+ switch(suite) {
+ case SPTPS_CHACHA_POLY1305:
+ chacha_poly1305_exit(ctx);
+ break;
+
+ case SPTPS_AES256_GCM:
+#ifdef HAVE_OPENSSL
+ EVP_CIPHER_CTX_free(ctx);
+ break;
+#endif
+
+ default:
+ break;
+ }
+}
+
+static bool cipher_encrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) {
+ switch(suite) {
+ case SPTPS_CHACHA_POLY1305:
+ chacha_poly1305_encrypt(ctx, seqno, in, inlen, out, outlen);
+ return true;
+
+ case SPTPS_AES256_GCM:
+#ifdef HAVE_OPENSSL
+ {
+ if(!EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, (uint8_t *)&seqno)) {
+ return false;
+ }
+
+ int outlen1 = 0, outlen2 = 0;
+
+ if(!EVP_EncryptUpdate(ctx, out, &outlen1, in, (int)inlen)) {
+ return false;
+ }
+
+ if(!EVP_EncryptFinal_ex(ctx, out + outlen1, &outlen2)) {
+ return false;
+ }
+
+ outlen1 += outlen2;
+
+ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, out + outlen1)) {
+ return false;
+ }
+
+ outlen1 += 16;
+
+ if(outlen) {
+ *outlen = outlen1;
+ }
+
+ return true;
+ }
+
+#endif
+
+ default:
+ return false;
+ }
+}
+
+static bool cipher_decrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) {
+ switch(suite) {
+ case SPTPS_CHACHA_POLY1305:
+ return chacha_poly1305_decrypt(ctx, seqno, in, inlen, out, outlen);
+
+ case SPTPS_AES256_GCM:
+#ifdef HAVE_OPENSSL
+ {
+ if(inlen < 16) {
+ return false;
+ }
+
+ inlen -= 16;
+
+ if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (uint8_t *)&seqno)) {
+ return false;
+ }
+
+ int outlen1 = 0, outlen2 = 0;
+
+ if(!EVP_DecryptUpdate(ctx, out, &outlen1, in, (int)inlen)) {
+ return false;
+ }
+
+ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, (void *)(in + inlen))) {
+ return false;
+ }
+
+ if(!EVP_DecryptFinal_ex(ctx, out + outlen1, &outlen2)) {
+ return false;
+ }
+
+ if(outlen) {
+ *outlen = outlen1 + outlen2;
+ }
+
+ return true;
+ }
+
+#endif
+
+ default:
+ return false;
+ }
+}
+
+
// Send a record (datagram version, accepts all record types, handles encryption and authentication).
static bool send_record_priv_datagram(sptps_t *s, uint8_t type, const void *data, uint16_t len) {
- uint8_t *buffer = alloca(len + 21UL);
-
+ uint8_t *buffer = alloca(len + SPTPS_DATAGRAM_OVERHEAD);
// Create header with sequence number, length and record type
uint32_t seqno = s->outseqno++;
- uint32_t netseqno = ntohl(seqno);
- memcpy(buffer, &netseqno, 4);
+ memcpy(buffer, &seqno, 4);
buffer[4] = type;
memcpy(buffer + 5, data, len);
if(s->outstate) {
// If first handshake has finished, encrypt and HMAC
- chacha_poly1305_encrypt(s->outcipher, seqno, buffer + 4, len + 1, buffer + 4, NULL);
- return s->send_data(s->handle, type, buffer, len + 21UL);
+ if(!cipher_encrypt(s->cipher_suite, s->outcipher, seqno, buffer + 4, len + 1, buffer + 4, NULL)) {
+ return error(s, EINVAL, "Failed to encrypt message");
+ }
+
+ return s->send_data(s->handle, type, buffer, len + SPTPS_DATAGRAM_OVERHEAD);
} else {
// Otherwise send as plaintext
- return s->send_data(s->handle, type, buffer, len + 5UL);
+ return s->send_data(s->handle, type, buffer, len + SPTPS_DATAGRAM_HEADER);
}
}
// Send a record (private version, accepts all record types, handles encryption and authentication).
@@ -117,11 +255,11 @@ static bool send_record_priv(sptps_t *s, uint8_t type, const void *data, uint16_
return send_record_priv_datagram(s, type, data, len);
}
- uint8_t *buffer = alloca(len + 19UL);
+ uint8_t *buffer = alloca(len + SPTPS_OVERHEAD);
// Create header with sequence number, length and record type
uint32_t seqno = s->outseqno++;
- uint16_t netlen = htons(len);
+ uint16_t netlen = len;
memcpy(buffer, &netlen, 2);
buffer[2] = type;
@@ -129,11 +267,14 @@ static bool send_record_priv(sptps_t *s, uint8_t type, const void *data, uint16_
if(s->outstate) {
// If first handshake has finished, encrypt and HMAC
- chacha_poly1305_encrypt(s->outcipher, seqno, buffer + 2, len + 1, buffer + 2, NULL);
- return s->send_data(s->handle, type, buffer, len + 19UL);
+ if(!cipher_encrypt(s->cipher_suite, s->outcipher, seqno, buffer + 2, len + 1, buffer + 2, NULL)) {
+ return error(s, EINVAL, "Failed to encrypt message");
+ }
+
+ return s->send_data(s->handle, type, buffer, len + SPTPS_OVERHEAD);
} else {
// Otherwise send as plaintext
- return s->send_data(s->handle, type, buffer, len + 3UL);
+ return s->send_data(s->handle, type, buffer, len + SPTPS_HEADER);
}
}
@@ -161,7 +302,7 @@ static bool send_kex(sptps_t *s) {
return false;
}
- s->mykex = realloc(s->mykex, 1 + 32 + keylen);
+ s->mykex = realloc(s->mykex, 4 + 32 + keylen);
if(!s->mykex) {
return error(s, errno, strerror(errno));
@@ -169,16 +310,18 @@ static bool send_kex(sptps_t *s) {
// Set version byte to zero.
s->mykex[0] = SPTPS_VERSION;
+ s->mykex[1] = s->preferred_suite;
+ memcpy(s->mykex + 2, &s->cipher_suites, 2);
// Create a random nonce.
- randomize(s->mykex + 1, 32);
+ randomize(s->mykex + 4, 32);
// Create a new ECDH public key.
- if(!(s->ecdh = ecdh_generate_public(s->mykex + 1 + 32))) {
+ if(!(s->ecdh = ecdh_generate_public(s->mykex + 4 + 32))) {
return error(s, EINVAL, "Failed to generate ECDH public key");
}
- return send_record_priv(s, SPTPS_HANDSHAKE, s->mykex, 1 + 32 + keylen);
+ return send_record_priv(s, SPTPS_HANDSHAKE, s->mykex, 4 + 32 + keylen);
}
// Send a SIGnature record, containing an Ed25519 signature over both KEX records.
@@ -192,9 +335,9 @@ static bool send_sig(sptps_t *s) {
uint8_t *sig = alloca(siglen);
msg[0] = s->initiator;
- memcpy(msg + 1, s->mykex, 1 + 32 + keylen);
- memcpy(msg + 1 + 33 + keylen, s->hiskex, 1 + 32 + keylen);
- memcpy(msg + 1 + 2 * (33 + keylen), s->label, s->labellen);
+ memcpy(msg + 1, s->mykex, 4 + 32 + keylen);
+ memcpy(msg + 1 + (4 + 32 + keylen), s->hiskex, 4 + 32 + keylen);
+ memcpy(msg + 1 + 2 * (4 + 32 + keylen), s->label, s->labellen);
// Sign the result.
if(!ecdsa_sign(s->mykey, msg, msglen, sig)) {
@@ -207,16 +350,6 @@ static bool send_sig(sptps_t *s) {
// Generate key material from the shared secret created from the ECDHE key exchange.
static bool generate_key_material(sptps_t *s, const uint8_t *shared, size_t len) {
- // Initialise cipher and digest structures if necessary
- if(!s->outstate) {
- s->incipher = chacha_poly1305_init();
- s->outcipher = chacha_poly1305_init();
-
- if(!s->incipher || !s->outcipher) {
- return error(s, EINVAL, "Failed to open cipher");
- }
- }
-
// Allocate memory for key material
size_t keylen = 2 * CHACHA_POLY1305_KEYLEN;
@@ -261,14 +394,8 @@ static bool receive_ack(sptps_t *s, const uint8_t *data, uint16_t len) {
return error(s, EIO, "Invalid ACK record length");
}
- if(s->initiator) {
- if(!chacha_poly1305_set_key(s->incipher, s->key)) {
- return error(s, EINVAL, "Failed to set counter");
- }
- } else {
- if(!chacha_poly1305_set_key(s->incipher, s->key + CHACHA_POLY1305_KEYLEN)) {
- return error(s, EINVAL, "Failed to set counter");
- }
+ if(!cipher_init(s->cipher_suite, &s->incipher, s->key, s->initiator)) {
+ return error(s, EINVAL, "Failed to initialize cipher");
}
free(s->key);
@@ -278,14 +405,51 @@ static bool receive_ack(sptps_t *s, const uint8_t *data, uint16_t len) {
return true;
}
+static uint8_t select_cipher_suite(uint16_t mask, uint8_t pref1, uint8_t pref2) {
+ // Check if there is a viable preference, if so select the lowest one
+ uint8_t selection = 255;
+
+ if(mask & (1U << pref1)) {
+ selection = pref1;
+ }
+
+ if(pref2 < selection && (mask & (1U << pref2))) {
+ selection = pref2;
+ }
+
+ // Otherwise, select the lowest cipher suite both sides support
+ if(selection == 255) {
+ selection = 0;
+
+ while(!(mask & 1U)) {
+ selection++;
+ mask >>= 1;
+ }
+ }
+
+ return selection;
+}
+
// Receive a Key EXchange record, respond by sending a SIG record.
static bool receive_kex(sptps_t *s, const uint8_t *data, uint16_t len) {
// Verify length of the HELLO record
- if(len != 1 + 32 + ECDH_SIZE) {
+ if(len != 4 + 32 + ECDH_SIZE) {
return error(s, EIO, "Invalid KEX record length");
}
- // Ignore version number for now.
+ if(data[0] != SPTPS_VERSION) {
+ return error(s, EIO, "Incompatible SPTPS version");
+ }
+
+ uint16_t suites;
+ memcpy(&suites, data + 2, 2);
+ suites &= s->cipher_suites;
+
+ if(!suites) {
+ return error(s, EIO, "No matching cipher suites");
+ }
+
+ s->cipher_suite = select_cipher_suite(suites, s->preferred_suite, data[1] & 0xf);
// Make a copy of the KEX message, send_sig() and receive_sig() need it
if(s->hiskex) {
@@ -322,9 +486,9 @@ static bool receive_sig(sptps_t *s, const uint8_t *data, uint16_t len) {
uint8_t *msg = alloca(msglen);
msg[0] = !s->initiator;
- memcpy(msg + 1, s->hiskex, 1 + 32 + keylen);
- memcpy(msg + 1 + 33 + keylen, s->mykex, 1 + 32 + keylen);
- memcpy(msg + 1 + 2 * (33 + keylen), s->label, s->labellen);
+ memcpy(msg + 1, s->hiskex, 4 + 32 + keylen);
+ memcpy(msg + 1 + (4 + 32 + keylen), s->mykex, 4 + 32 + keylen);
+ memcpy(msg + 1 + 2 * (4 + 32 + keylen), s->label, s->labellen);
// Verify signature.
if(!ecdsa_verify(s->hiskey, msg, msglen, data)) {
@@ -334,7 +498,7 @@ static bool receive_sig(sptps_t *s, const uint8_t *data, uint16_t len) {
// Compute shared secret.
uint8_t shared[ECDH_SHARED_SIZE];
- if(!ecdh_compute_shared(s->ecdh, s->hiskex + 1 + 32, shared)) {
+ if(!ecdh_compute_shared(s->ecdh, s->hiskex + 4 + 32, shared)) {
return error(s, EINVAL, "Failed to compute ECDH shared secret");
}
@@ -360,15 +524,8 @@ static bool receive_sig(sptps_t *s, const uint8_t *data, uint16_t len) {
return false;
}
- // TODO: only set new keys after ACK has been set/received
- if(s->initiator) {
- if(!chacha_poly1305_set_key(s->outcipher, s->key + CHACHA_POLY1305_KEYLEN)) {
- return error(s, EINVAL, "Failed to set key");
- }
- } else {
- if(!chacha_poly1305_set_key(s->outcipher, s->key)) {
- return error(s, EINVAL, "Failed to set key");
- }
+ if(!cipher_init(s->cipher_suite, &s->outcipher, s->key, !s->initiator)) {
+ return error(s, EINVAL, "Failed to initialize cipher");
}
return true;
@@ -518,15 +675,13 @@ bool sptps_verify_datagram(sptps_t *s, const void *vdata, size_t len) {
const uint8_t *data = vdata;
uint32_t seqno;
memcpy(&seqno, data, 4);
- seqno = ntohl(seqno);
if(!sptps_check_seqno(s, seqno, false)) {
return false;
}
uint8_t *buffer = alloca(len);
- size_t outlen;
- return chacha_poly1305_decrypt(s->incipher, seqno, data + 4, len - 4, buffer, &outlen);
+ return cipher_decrypt(s->cipher_suite, s->incipher, seqno, data + 4, len - 4, buffer, NULL);
}
// Receive incoming data, datagram version.
@@ -537,7 +692,6 @@ static bool sptps_receive_data_datagram(sptps_t *s, const uint8_t *data, size_t
uint32_t seqno;
memcpy(&seqno, data, 4);
- seqno = ntohl(seqno);
data += 4;
len -= 4;
@@ -563,7 +717,7 @@ static bool sptps_receive_data_datagram(sptps_t *s, const uint8_t *data, size_t
uint8_t *buffer = alloca(len);
size_t outlen;
- if(!chacha_poly1305_decrypt(s->incipher, seqno, data, len, buffer, &outlen)) {
+ if(!cipher_decrypt(s->cipher_suite, s->incipher, seqno, data, len, buffer, &outlen)) {
return error(s, EIO, "Failed to decrypt and verify packet");
}
@@ -635,10 +789,9 @@ size_t sptps_receive_data(sptps_t *s, const void *vdata, size_t len) {
// 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);
+ s->inbuf = realloc(s->inbuf, s->reclen + SPTPS_OVERHEAD);
if(!s->inbuf) {
return error(s, errno, strerror(errno));
@@ -651,7 +804,7 @@ size_t sptps_receive_data(sptps_t *s, const void *vdata, size_t len) {
}
// Read up to the end of the record.
- size_t toread = s->reclen + (s->instate ? 19UL : 3UL) - s->buflen;
+ size_t toread = s->reclen + (s->instate ? SPTPS_OVERHEAD : SPTPS_HEADER) - s->buflen;
if(toread > len) {
toread = len;
@@ -662,7 +815,7 @@ size_t sptps_receive_data(sptps_t *s, const void *vdata, size_t len) {
s->buflen += toread;
// If we don't have a whole record, exit.
- if(s->buflen < s->reclen + (s->instate ? 19UL : 3UL)) {
+ if(s->buflen < s->reclen + (s->instate ? SPTPS_OVERHEAD : SPTPS_HEADER)) {
return total_read;
}
@@ -672,13 +825,13 @@ size_t sptps_receive_data(sptps_t *s, const void *vdata, size_t len) {
// Check HMAC and decrypt.
if(s->instate) {
- if(!chacha_poly1305_decrypt(s->incipher, seqno, s->inbuf + 2UL, s->reclen + 17UL, s->inbuf + 2UL, NULL)) {
+ if(!cipher_decrypt(s->cipher_suite, 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;
+ s->inbuf[s->reclen + SPTPS_HEADER] = 0;
uint8_t type = s->inbuf[2];
@@ -704,16 +857,18 @@ size_t sptps_receive_data(sptps_t *s, const void *vdata, size_t len) {
}
// Start a SPTPS session.
-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) {
+bool sptps_start(sptps_t *s, const sptps_params_t *params) {
// Initialise struct sptps
memset(s, 0, sizeof(*s));
- s->handle = handle;
- s->initiator = initiator;
- s->datagram = datagram;
- s->mykey = mykey;
- s->hiskey = hiskey;
+ s->handle = params->handle;
+ s->initiator = params->initiator;
+ s->datagram = params->datagram;
+ s->mykey = params->mykey;
+ s->hiskey = params->hiskey;
s->replaywin = sptps_replaywin;
+ s->cipher_suites = params->cipher_suites ? params->cipher_suites & SPTPS_ALL_CIPHER_SUITES : SPTPS_ALL_CIPHER_SUITES;
+ s->preferred_suite = params->preferred_suite;
if(s->replaywin) {
s->late = malloc(s->replaywin);
@@ -725,13 +880,16 @@ bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_
memset(s->late, 0, s->replaywin);
}
- s->label = malloc(labellen);
+ s->labellen = params->labellen ? params->labellen : strlen(params->label);
+ s->label = malloc(s->labellen);
if(!s->label) {
return error(s, errno, strerror(errno));
}
- if(!datagram) {
+ memcpy(s->label, params->label, s->labellen);
+
+ if(!s->datagram) {
s->inbuf = malloc(7);
if(!s->inbuf) {
@@ -741,11 +899,9 @@ bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_
s->buflen = 0;
}
- memcpy(s->label, label, labellen);
- s->labellen = labellen;
- s->send_data = send_data;
- s->receive_record = receive_record;
+ s->send_data = params->send_data;
+ s->receive_record = params->receive_record;
// Do first KEX immediately
s->state = SPTPS_KEX;
@@ -755,8 +911,8 @@ bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_
// Stop a SPTPS session.
bool sptps_stop(sptps_t *s) {
// Clean up any resources.
- chacha_poly1305_exit(s->incipher);
- chacha_poly1305_exit(s->outcipher);
+ cipher_exit(s->cipher_suite, s->incipher);
+ cipher_exit(s->cipher_suite, s->outcipher);
ecdh_free(s->ecdh);
free(s->inbuf);
free(s->mykex);
diff --git a/src/sptps.h b/src/sptps.h
index 96edc366..b9ec11fd 100644
--- a/src/sptps.h
+++ b/src/sptps.h
@@ -26,7 +26,7 @@
#include "ecdh.h"
#include "ecdsa.h"
-#define SPTPS_VERSION 0
+#define SPTPS_VERSION 1
// Record types
#define SPTPS_HANDSHAKE 128 // Key exchange and authentication
@@ -34,7 +34,10 @@
#define SPTPS_CLOSE 130 // Application closed the connection
// Overhead for datagrams
-#define SPTPS_DATAGRAM_OVERHEAD 21
+static const size_t SPTPS_OVERHEAD = 19;
+static const size_t SPTPS_HEADER = 3;
+static const size_t SPTPS_DATAGRAM_OVERHEAD = 21;
+static const size_t SPTPS_DATAGRAM_HEADER = 5;
typedef bool (*send_data_t)(void *handle, uint8_t type, const void *data, size_t len);
typedef bool (*receive_record_t)(void *handle, uint8_t type, const void *data, uint16_t len);
@@ -47,9 +50,40 @@ typedef enum sptps_state_t {
SPTPS_ACK = 4, // Waiting for an ACKnowledgement record
} sptps_state_t;
+// Public key suites
+enum {
+ SPTPS_ED25519 = 0,
+};
+
+// Cipher suites
+enum {
+ SPTPS_CHACHA_POLY1305 = 0,
+ SPTPS_AES256_GCM = 1,
+ SPTPS_ALL_CIPHER_SUITES = 0x3,
+};
+
+typedef struct sptps_params {
+ void *handle;
+ bool initiator;
+ bool datagram;
+ uint8_t preferred_suite;
+ uint16_t cipher_suites;
+ ecdsa_t *mykey;
+ ecdsa_t *hiskey;
+ const void *label;
+ size_t labellen;
+ send_data_t send_data;
+ receive_record_t receive_record;
+} sptps_params_t;
+
typedef struct sptps {
bool initiator;
bool datagram;
+ uint8_t preferred_suite;
+ uint16_t cipher_suites;
+
+ uint8_t pk_suite;
+ uint8_t cipher_suite;
sptps_state_t state;
uint8_t *inbuf;
@@ -57,7 +91,7 @@ typedef struct sptps {
uint16_t reclen;
bool instate;
- chacha_poly1305_ctx_t *incipher;
+ void *incipher;
uint32_t inseqno;
uint32_t received;
unsigned int replaywin;
@@ -65,7 +99,7 @@ typedef struct sptps {
uint8_t *late;
bool outstate;
- chacha_poly1305_ctx_t *outcipher;
+ void *outcipher;
uint32_t outseqno;
ecdsa_t *mykey;
@@ -87,7 +121,7 @@ extern unsigned int sptps_replaywin;
extern void sptps_log_quiet(sptps_t *s, int s_errno, const char *format, va_list ap);
extern void sptps_log_stderr(sptps_t *s, int s_errno, const char *format, va_list ap);
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_start(sptps_t *s, const struct sptps_params *params);
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 size_t sptps_receive_data(sptps_t *s, const void *data, size_t len);
diff --git a/src/sptps_test.c b/src/sptps_test.c
index 249f2e4f..e77ab9c7 100644
--- a/src/sptps_test.c
+++ b/src/sptps_test.c
@@ -562,7 +562,18 @@ static int run_test(int argc, char *argv[]) {
sptps_t s;
- if(!sptps_start(&s, &sock, initiator, datagram, mykey, hiskey, "sptps_test", 10, send_data, receive_record)) {
+ sptps_params_t params = {
+ .handle = &sock,
+ .initiator = initiator,
+ .datagram = datagram,
+ .mykey = mykey,
+ .hiskey = hiskey,
+ .label = "sptps_test",
+ .send_data = send_data,
+ .receive_record = receive_record,
+ };
+
+ if(!sptps_start(&s, &params)) {
free(mykey);
free(hiskey);
return 1;
--
2.36.0

View file

@ -0,0 +1,91 @@
From 1d0eea4899f9642a3945c07b9266e660b9f9ce71 Mon Sep 17 00:00:00 2001
From: Guus Sliepen <guus@tinc-vpn.org>
Date: Tue, 3 Aug 2021 00:38:37 +0200
Subject: [PATCH 02/10] Add cipher suite selection options to sptps_test.
---
src/sptps_test.c | 38 +++++++++++++++++++++++++++-----------
1 file changed, 27 insertions(+), 11 deletions(-)
diff --git a/src/sptps_test.c b/src/sptps_test.c
index e77ab9c7..32ed62d3 100644
--- a/src/sptps_test.c
+++ b/src/sptps_test.c
@@ -127,6 +127,8 @@ static struct option const long_options[] = {
{"replay-window", required_argument, NULL, 'W'},
{"special", no_argument, NULL, 's'},
{"verbose", required_argument, NULL, 'v'},
+ {"cipher-suites", required_argument, NULL, 'M'},
+ {"preferred-cipher", required_argument, NULL, 'P'},
{"help", no_argument, NULL, 1},
{NULL, 0, NULL, 0}
};
@@ -136,19 +138,21 @@ static void usage(void) {
"Usage: %s [options] my_ed25519_key_file his_ed25519_key_file [host] port\n"
"\n"
"Valid options are:\n"
- " -d, --datagram Enable datagram mode.\n"
- " -q, --quit Quit when EOF occurs on stdin.\n"
- " -r, --readonly Only send data from the socket to stdout.\n"
+ " -d, --datagram Enable datagram mode.\n"
+ " -q, --quit Quit when EOF occurs on stdin.\n"
+ " -r, --readonly Only send data from the socket to stdout.\n"
#ifdef HAVE_LINUX
- " -t, --tun Use a tun device instead of stdio.\n"
+ " -t, --tun Use a tun device instead of stdio.\n"
#endif
- " -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"
- " -4 Use IPv4.\n"
- " -6 Use IPv6.\n"
+ " -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"
+ " -M, --cipher-suites MASK Set the mask of allowed cipher suites.\n"
+ " -P, --preferred-suite N Set the preferred cipher suite.\n"
+ " -s, --special Enable special handling of lines starting with #, ^ and $.\n"
+ " -v, --verbose Display debug messages.\n"
+ " -4 Use IPv4.\n"
+ " -6 Use IPv6.\n"
"\n"
"Report bugs to tinc@tinc-vpn.org.\n";
@@ -326,6 +330,8 @@ static int run_test(int argc, char *argv[]) {
int r;
int option_index = 0;
bool quit = false;
+ unsigned long cipher_suites = SPTPS_ALL_CIPHER_SUITES;
+ unsigned long preferred_suite = 0;
while((r = getopt_long(argc, argv, "dqrstwL:W:v46", long_options, &option_index)) != EOF) {
switch(r) {
@@ -366,6 +372,14 @@ static int run_test(int argc, char *argv[]) {
sptps_replaywin = atoi(optarg);
break;
+ case 'M': /* cipher suites */
+ cipher_suites = strtoul(optarg, NULL, 0);
+ break;
+
+ case 'P': /* preferred cipher */
+ preferred_suite = strtoul(optarg, NULL, 0);
+ break;
+
case 'v': /* be verbose */
verbose = true;
break;
@@ -571,6 +585,8 @@ static int run_test(int argc, char *argv[]) {
.label = "sptps_test",
.send_data = send_data,
.receive_record = receive_record,
+ .cipher_suites = cipher_suites,
+ .preferred_suite = preferred_suite,
};
if(!sptps_start(&s, &params)) {
--
2.36.0

View file

@ -0,0 +1,285 @@
From c0f0610037847ea2abae1e7a826d36a55f9dfa36 Mon Sep 17 00:00:00 2001
From: Guus Sliepen <guus@tinc-vpn.org>
Date: Tue, 3 Aug 2021 00:39:05 +0200
Subject: [PATCH 03/10] Let sptps_speed benchmark all cipher suites.
---
src/sptps_speed.c | 212 +++++++++++++++++++++++++++-------------------
1 file changed, 125 insertions(+), 87 deletions(-)
diff --git a/src/sptps_speed.c b/src/sptps_speed.c
index c7c6e546..45bbeb5c 100644
--- a/src/sptps_speed.c
+++ b/src/sptps_speed.c
@@ -168,22 +168,76 @@ static int run_benchmark(int argc, char *argv[]) {
fprintf(stderr, "%28.2lf op/s\n", rate);
ecdh_free(ecdh1);
- // SPTPS authentication phase
-
int fd[2];
+ struct pollfd pfd[2] = {{fd[0], POLLIN}, {fd[1], POLLIN}};
+
+ sptps_params_t params1 = {
+ .handle = fd + 0,
+ .initiator = true,
+ .datagram = false,
+ .mykey = key1,
+ .hiskey = key2,
+ .label = "sptps_speed",
+ .send_data = send_data,
+ .receive_record = receive_record,
+ };
+
+ sptps_params_t params2 = {
+ .handle = fd + 1,
+ .initiator = false,
+ .datagram = false,
+ .mykey = key2,
+ .hiskey = key1,
+ .label = "sptps_speed",
+ .send_data = send_data,
+ .receive_record = receive_record,
+ };
+
+ static const char *suite_names[] = {
+ "Chacha20-Poly1305",
+ "AES-256-GCM",
+ };
+
+ for(uint8_t suite = 0; suite < 2; suite++) {
+ fprintf(stderr, "\nCipher suite %u (%s):\n", suite, suite_names[suite]);
+ params1.preferred_suite = params2.preferred_suite = suite;
+
+ // SPTPS authentication phase
+
+ fprintf(stderr, "SPTPS/TCP authenticate for %lg seconds: ", duration);
+
+ if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) {
+ fprintf(stderr, "Could not create a UNIX socket pair: %s\n", sockstrerror(sockerrno));
+ return 1;
+ }
- if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) {
- fprintf(stderr, "Could not create a UNIX socket pair: %s\n", sockstrerror(sockerrno));
- return 1;
- }
+ pfd[0].fd = fd[0], pfd[1].fd = fd[1];
+ params1.datagram = params2.datagram = false;
- struct pollfd pfd[2] = {{fd[0], POLLIN, 0}, {fd[1], POLLIN, 0}};
+ for(clock_start(); clock_countto(duration);) {
+ sptps_start(&sptps1, &params1);
+ sptps_start(&sptps2, &params2);
- fprintf(stderr, "SPTPS/TCP authenticate for %lg seconds: ", duration);
+ while(poll(pfd, 2, 0)) {
+ if(pfd[0].revents) {
+ receive_data(&sptps1);
+ }
- for(clock_start(); clock_countto(duration);) {
- sptps_start(&sptps1, fd + 0, true, false, key1, key2, "sptps_speed", 11, send_data, receive_record);
- sptps_start(&sptps2, fd + 1, false, false, key2, key1, "sptps_speed", 11, send_data, receive_record);
+ if(pfd[1].revents) {
+ receive_data(&sptps2);
+ }
+ }
+
+ sptps_stop(&sptps1);
+ sptps_stop(&sptps2);
+ }
+
+ fprintf(stderr, "%10.2lf op/s\n", rate * 2);
+
+ // SPTPS data
+
+ sptps_start(&sptps1, &params1);
+ sptps_start(&sptps2, &params2);
while(poll(pfd, 2, 0)) {
if(pfd[0].revents) {
@@ -195,65 +249,68 @@ static int run_benchmark(int argc, char *argv[]) {
}
}
- sptps_stop(&sptps1);
- sptps_stop(&sptps2);
- }
+ fprintf(stderr, "SPTPS/TCP transmit for %lg seconds: ", duration);
- fprintf(stderr, "%10.2lf op/s\n", rate * 2);
+ for(clock_start(); clock_countto(duration);) {
+ if(!sptps_send_record(&sptps1, 0, buf1, 1451)) {
+ abort();
+ }
- // SPTPS data
+ receive_data(&sptps2);
+ }
- sptps_start(&sptps1, fd + 0, true, false, key1, key2, "sptps_speed", 11, send_data, receive_record);
- sptps_start(&sptps2, fd + 1, false, false, key2, key1, "sptps_speed", 11, send_data, receive_record);
+ rate *= 2 * 1451 * 8;
- while(poll(pfd, 2, 0)) {
- if(pfd[0].revents) {
- receive_data(&sptps1);
+ if(rate > 1e9) {
+ fprintf(stderr, "%14.2lf Gbit/s\n", rate / 1e9);
+ } else if(rate > 1e6) {
+ fprintf(stderr, "%14.2lf Mbit/s\n", rate / 1e6);
+ } else if(rate > 1e3) {
+ fprintf(stderr, "%14.2lf kbit/s\n", rate / 1e3);
}
- if(pfd[1].revents) {
- receive_data(&sptps2);
- }
- }
+ sptps_stop(&sptps1);
+ sptps_stop(&sptps2);
- fprintf(stderr, "SPTPS/TCP transmit for %lg seconds: ", duration);
+ close(fd[0]);
+ close(fd[1]);
- for(clock_start(); clock_countto(duration);) {
- if(!sptps_send_record(&sptps1, 0, buf1, 1451)) {
- abort();
+ // SPTPS datagram authentication phase
+
+ if(socketpair(AF_UNIX, SOCK_DGRAM, 0, fd)) {
+ fprintf(stderr, "Could not create a UNIX socket pair: %s\n", sockstrerror(sockerrno));
+ return 1;
}
- receive_data(&sptps2);
- }
+ pfd[0].fd = fd[0], pfd[1].fd = fd[1];
+ params1.datagram = params2.datagram = true;
- rate *= 2 * 1451 * 8;
+ fprintf(stderr, "SPTPS/UDP authenticate for %lg seconds: ", duration);
- if(rate > 1e9) {
- fprintf(stderr, "%14.2lf Gbit/s\n", rate / 1e9);
- } else if(rate > 1e6) {
- fprintf(stderr, "%14.2lf Mbit/s\n", rate / 1e6);
- } else if(rate > 1e3) {
- fprintf(stderr, "%14.2lf kbit/s\n", rate / 1e3);
- }
+ for(clock_start(); clock_countto(duration);) {
+ sptps_start(&sptps1, &params1);
+ sptps_start(&sptps2, &params2);
- sptps_stop(&sptps1);
- sptps_stop(&sptps2);
+ while(poll(pfd, 2, 0)) {
+ if(pfd[0].revents) {
+ receive_data(&sptps1);
+ }
- // SPTPS datagram authentication phase
+ if(pfd[1].revents) {
+ receive_data(&sptps2);
+ }
+ }
- close(fd[0]);
- close(fd[1]);
+ sptps_stop(&sptps1);
+ sptps_stop(&sptps2);
+ }
- if(socketpair(AF_UNIX, SOCK_DGRAM, 0, fd)) {
- fprintf(stderr, "Could not create a UNIX socket pair: %s\n", sockstrerror(sockerrno));
- return 1;
- }
+ fprintf(stderr, "%10.2lf op/s\n", rate * 2);
- fprintf(stderr, "SPTPS/UDP authenticate for %lg seconds: ", duration);
+ // SPTPS datagram data
- for(clock_start(); clock_countto(duration);) {
- sptps_start(&sptps1, fd + 0, true, true, key1, key2, "sptps_speed", 11, send_data, receive_record);
- sptps_start(&sptps2, fd + 1, false, true, key2, key1, "sptps_speed", 11, send_data, receive_record);
+ sptps_start(&sptps1, &params1);
+ sptps_start(&sptps2, &params2);
while(poll(pfd, 2, 0)) {
if(pfd[0].revents) {
@@ -265,54 +322,35 @@ static int run_benchmark(int argc, char *argv[]) {
}
}
- sptps_stop(&sptps1);
- sptps_stop(&sptps2);
- }
-
- fprintf(stderr, "%10.2lf op/s\n", rate * 2);
+ fprintf(stderr, "SPTPS/UDP transmit for %lg seconds: ", duration);
- // SPTPS datagram data
-
- sptps_start(&sptps1, fd + 0, true, true, key1, key2, "sptps_speed", 11, send_data, receive_record);
- sptps_start(&sptps2, fd + 1, false, true, key2, key1, "sptps_speed", 11, send_data, receive_record);
-
- while(poll(pfd, 2, 0)) {
- if(pfd[0].revents) {
- receive_data(&sptps1);
- }
+ for(clock_start(); clock_countto(duration);) {
+ if(!sptps_send_record(&sptps1, 0, buf1, 1451)) {
+ abort();
+ }
- if(pfd[1].revents) {
receive_data(&sptps2);
}
- }
- fprintf(stderr, "SPTPS/UDP transmit for %lg seconds: ", duration);
+ rate *= 2 * 1451 * 8;
- for(clock_start(); clock_countto(duration);) {
- if(!sptps_send_record(&sptps1, 0, buf1, 1451)) {
- abort();
+ if(rate > 1e9) {
+ fprintf(stderr, "%14.2lf Gbit/s\n", rate / 1e9);
+ } else if(rate > 1e6) {
+ fprintf(stderr, "%14.2lf Mbit/s\n", rate / 1e6);
+ } else if(rate > 1e3) {
+ fprintf(stderr, "%14.2lf kbit/s\n", rate / 1e3);
}
- receive_data(&sptps2);
- }
-
- rate *= 2 * 1451 * 8;
+ sptps_stop(&sptps1);
+ sptps_stop(&sptps2);
- if(rate > 1e9) {
- fprintf(stderr, "%14.2lf Gbit/s\n", rate / 1e9);
- } else if(rate > 1e6) {
- fprintf(stderr, "%14.2lf Mbit/s\n", rate / 1e6);
- } else if(rate > 1e3) {
- fprintf(stderr, "%14.2lf kbit/s\n", rate / 1e3);
+ close(fd[0]);
+ close(fd[1]);
}
- sptps_stop(&sptps1);
- sptps_stop(&sptps2);
-
// Clean up
- close(fd[0]);
- close(fd[1]);
ecdsa_free(key1);
ecdsa_free(key2);
--
2.36.0

View file

@ -0,0 +1,219 @@
From 9d423c31024e37655aac014662cb5bee82c26464 Mon Sep 17 00:00:00 2001
From: Guus Sliepen <guus@tinc-vpn.org>
Date: Mon, 9 Aug 2021 21:55:09 +0200
Subject: [PATCH 04/10] If we link with OpenSSL, use it for Chacha20-Poly1305
as well.
---
src/sptps.c | 128 ++++++++++++++++++++++++++++++++--------------------
1 file changed, 78 insertions(+), 50 deletions(-)
diff --git a/src/sptps.c b/src/sptps.c
index 33c41424..55b9e5ca 100644
--- a/src/sptps.c
+++ b/src/sptps.c
@@ -96,12 +96,26 @@ static void warning(sptps_t *s, const char *format, ...) {
static bool cipher_init(uint8_t suite, void **ctx, const uint8_t *key, bool key_half) {
switch(suite) {
+#ifndef HAVE_OPENSSL
+
case SPTPS_CHACHA_POLY1305:
*ctx = chacha_poly1305_init();
return ctx && chacha_poly1305_set_key(*ctx, key + (key_half ? CHACHA_POLY1305_KEYLEN : 0));
+#else
+
+ case SPTPS_CHACHA_POLY1305:
+ *ctx = EVP_CIPHER_CTX_new();
+
+ if(!ctx) {
+ return false;
+ }
+
+ return EVP_EncryptInit_ex(*ctx, EVP_chacha20_poly1305(), NULL, NULL, NULL)
+ && EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, NULL)
+ && EVP_EncryptInit_ex(*ctx, NULL, NULL, key + (key_half ? CHACHA_POLY1305_KEYLEN : 0), key);
+
case SPTPS_AES256_GCM:
-#ifdef HAVE_OPENSSL
*ctx = EVP_CIPHER_CTX_new();
if(!ctx) {
@@ -109,8 +123,8 @@ static bool cipher_init(uint8_t suite, void **ctx, const uint8_t *key, bool key_
}
return EVP_EncryptInit_ex(*ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)
- && EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_AEAD_SET_IVLEN, 4, NULL)
- && EVP_EncryptInit_ex(*ctx, NULL, NULL, key + (key_half ? 32 : 0), key);
+ && EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, NULL)
+ && EVP_EncryptInit_ex(*ctx, NULL, NULL, key + (key_half ? 64 : 0), key);
#endif
default:
@@ -120,12 +134,16 @@ static bool cipher_init(uint8_t suite, void **ctx, const uint8_t *key, bool key_
static void cipher_exit(uint8_t suite, void *ctx) {
switch(suite) {
+#ifndef HAVE_OPENSSL
+
case SPTPS_CHACHA_POLY1305:
chacha_poly1305_exit(ctx);
break;
+#else
+
+ case SPTPS_CHACHA_POLY1305:
case SPTPS_AES256_GCM:
-#ifdef HAVE_OPENSSL
EVP_CIPHER_CTX_free(ctx);
break;
#endif
@@ -136,43 +154,48 @@ static void cipher_exit(uint8_t suite, void *ctx) {
}
static bool cipher_encrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) {
+ uint8_t nonce[12] = {seqno, seqno >> 8, seqno >> 16, seqno >> 24};
+
switch(suite) {
+#ifndef HAVE_OPENSSL
+
case SPTPS_CHACHA_POLY1305:
chacha_poly1305_encrypt(ctx, seqno, in, inlen, out, outlen);
return true;
- case SPTPS_AES256_GCM:
-#ifdef HAVE_OPENSSL
- {
- if(!EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, (uint8_t *)&seqno)) {
- return false;
- }
+#else
- int outlen1 = 0, outlen2 = 0;
+ case SPTPS_CHACHA_POLY1305:
+ case SPTPS_AES256_GCM: {
+ if(!EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, nonce)) {
+ return false;
+ }
- if(!EVP_EncryptUpdate(ctx, out, &outlen1, in, (int)inlen)) {
- return false;
- }
+ int outlen1 = 0, outlen2 = 0;
- if(!EVP_EncryptFinal_ex(ctx, out + outlen1, &outlen2)) {
- return false;
- }
+ if(!EVP_EncryptUpdate(ctx, out, &outlen1, in, (int)inlen)) {
+ return false;
+ }
- outlen1 += outlen2;
+ if(!EVP_EncryptFinal_ex(ctx, out + outlen1, &outlen2)) {
+ return false;
+ }
- if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, out + outlen1)) {
- return false;
- }
+ outlen1 += outlen2;
- outlen1 += 16;
+ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, out + outlen1)) {
+ return false;
+ }
- if(outlen) {
- *outlen = outlen1;
- }
+ outlen1 += 16;
- return true;
+ if(outlen) {
+ *outlen = outlen1;
}
+ return true;
+ }
+
#endif
default:
@@ -181,44 +204,49 @@ static bool cipher_encrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8
}
static bool cipher_decrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) {
+ uint8_t nonce[12] = {seqno, seqno >> 8, seqno >> 16, seqno >> 24};
+
switch(suite) {
+#ifndef HAVE_OPENSSL
+
case SPTPS_CHACHA_POLY1305:
return chacha_poly1305_decrypt(ctx, seqno, in, inlen, out, outlen);
- case SPTPS_AES256_GCM:
-#ifdef HAVE_OPENSSL
- {
- if(inlen < 16) {
- return false;
- }
+#else
- inlen -= 16;
+ case SPTPS_CHACHA_POLY1305:
+ case SPTPS_AES256_GCM: {
+ if(inlen < 16) {
+ return false;
+ }
- if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (uint8_t *)&seqno)) {
- return false;
- }
+ inlen -= 16;
- int outlen1 = 0, outlen2 = 0;
+ if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, nonce)) {
+ return false;
+ }
- if(!EVP_DecryptUpdate(ctx, out, &outlen1, in, (int)inlen)) {
- return false;
- }
+ int outlen1 = 0, outlen2 = 0;
- if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, (void *)(in + inlen))) {
- return false;
- }
+ if(!EVP_DecryptUpdate(ctx, out, &outlen1, in, (int)inlen)) {
+ return false;
+ }
- if(!EVP_DecryptFinal_ex(ctx, out + outlen1, &outlen2)) {
- return false;
- }
+ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, (void *)(in + inlen))) {
+ return false;
+ }
- if(outlen) {
- *outlen = outlen1 + outlen2;
- }
+ if(!EVP_DecryptFinal_ex(ctx, out + outlen1, &outlen2)) {
+ return false;
+ }
- return true;
+ if(outlen) {
+ *outlen = outlen1 + outlen2;
}
+ return true;
+ }
+
#endif
default:
--
2.36.0

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,117 @@
From d64b9c4a2f48ce7533e9f7a8f5f6e890764515ab Mon Sep 17 00:00:00 2001
From: Guus Sliepen <guus@tinc-vpn.org>
Date: Tue, 10 Aug 2021 23:08:04 +0200
Subject: [PATCH 06/10] Ensure we are compatible with LibreSSL.
---
src/sptps.c | 66 ++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 53 insertions(+), 13 deletions(-)
diff --git a/src/sptps.c b/src/sptps.c
index 33e88ed9..7c8d20b7 100644
--- a/src/sptps.c
+++ b/src/sptps.c
@@ -107,26 +107,26 @@ static bool cipher_init(uint8_t suite, void **ctx, const uint8_t *key, bool key_
#else
case SPTPS_CHACHA_POLY1305:
- *ctx = EVP_CIPHER_CTX_new();
+#ifdef EVP_F_EVP_AEAD_CTX_INIT
+ *ctx = malloc(sizeof(EVP_AEAD_CTX));
- if(!ctx) {
- return false;
- }
+ return *ctx && EVP_AEAD_CTX_init(*ctx, EVP_aead_chacha20_poly1305(), key + (key_half ? CIPHER_KEYLEN : 0), 32, 16, NULL);
+#else
+ *ctx = EVP_CIPHER_CTX_new();
- return EVP_EncryptInit_ex(*ctx, EVP_chacha20_poly1305(), NULL, NULL, NULL)
- && EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, NULL)
+ return *ctx
+ && EVP_EncryptInit_ex(*ctx, EVP_chacha20_poly1305(), NULL, NULL, NULL)
+ && EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL)
&& EVP_EncryptInit_ex(*ctx, NULL, NULL, key + (key_half ? CIPHER_KEYLEN : 0), key);
+#endif
case SPTPS_AES256_GCM:
*ctx = EVP_CIPHER_CTX_new();
- if(!ctx) {
- return false;
- }
-
- return EVP_EncryptInit_ex(*ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)
- && EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, NULL)
- && EVP_EncryptInit_ex(*ctx, NULL, NULL, key + (key_half ? 64 : 0), key);
+ return *ctx
+ && EVP_EncryptInit_ex(*ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)
+ && EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL)
+ && EVP_EncryptInit_ex(*ctx, NULL, NULL, key + (key_half ? CIPHER_KEYLEN : 0), key);
#endif
default:
@@ -145,6 +145,12 @@ static void cipher_exit(uint8_t suite, void *ctx) {
#else
case SPTPS_CHACHA_POLY1305:
+#ifdef EVP_F_EVP_AEAD_CTX_INIT
+ EVP_AEAD_CTX_cleanup(ctx);
+ free(ctx);
+ break;
+#endif
+
case SPTPS_AES256_GCM:
EVP_CIPHER_CTX_free(ctx);
break;
@@ -176,6 +182,23 @@ static bool cipher_encrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8
#else
case SPTPS_CHACHA_POLY1305:
+#ifdef EVP_F_EVP_AEAD_CTX_INIT
+ {
+ size_t outlen1;
+
+ if(!EVP_AEAD_CTX_seal(ctx, out, &outlen1, inlen + 16, nonce, sizeof(nonce), in, inlen, NULL, 0)) {
+ return false;
+ }
+
+ if(outlen) {
+ *outlen = outlen1;
+ }
+
+ return true;
+ }
+
+#endif
+
case SPTPS_AES256_GCM: {
if(!EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, nonce)) {
return false;
@@ -239,6 +262,23 @@ static bool cipher_decrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8
#else
case SPTPS_CHACHA_POLY1305:
+#ifdef EVP_F_EVP_AEAD_CTX_INIT
+ {
+ size_t outlen1;
+
+ if(!EVP_AEAD_CTX_open(ctx, out, &outlen1, inlen, nonce, sizeof(nonce), in, inlen + 16, NULL, 0)) {
+ return false;
+ }
+
+ if(outlen) {
+ *outlen = outlen1;
+ }
+
+ return true;
+ }
+
+#endif
+
case SPTPS_AES256_GCM: {
if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, nonce)) {
return false;
--
2.36.0

View file

@ -0,0 +1,26 @@
From 948be5b4a813e814e36be23a63817df283e8db91 Mon Sep 17 00:00:00 2001
From: Guus Sliepen <guus@tinc-vpn.org>
Date: Tue, 10 Aug 2021 23:08:52 +0200
Subject: [PATCH 07/10] Fix infinite loop on SPTPS errors when running
sptps_test in datagram mode.
---
src/sptps_test.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/sptps_test.c b/src/sptps_test.c
index 32ed62d3..7e5977ed 100644
--- a/src/sptps_test.c
+++ b/src/sptps_test.c
@@ -721,6 +721,8 @@ static int run_test(int argc, char *argv[]) {
free(mykey);
free(hiskey);
return 1;
+ } else {
+ break;
}
}
--
2.36.0

View file

@ -0,0 +1,40 @@
From 440bf1e9e484ac9800308dafbb5089e400df3522 Mon Sep 17 00:00:00 2001
From: Guus Sliepen <guus@tinc-vpn.org>
Date: Sun, 22 Aug 2021 22:16:42 +0200
Subject: [PATCH 08/10] Fix documentation of default cipher algorithm used for
the legacy protocol.
---
doc/tinc.conf.5.in | 2 +-
doc/tinc.texi | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/doc/tinc.conf.5.in b/doc/tinc.conf.5.in
index d7aa7d99..0cfdd089 100644
--- a/doc/tinc.conf.5.in
+++ b/doc/tinc.conf.5.in
@@ -562,7 +562,7 @@ Multiple
.Va Address
variables can be specified, in which case each address will be tried until a working
connection has been established.
-.It Va Cipher Li = Ar cipher Pq blowfish
+.It Va Cipher Li = Ar cipher Pq aes-256-cbc
The symmetric cipher algorithm used to encrypt UDP packets.
Any cipher supported by LibreSSL or OpenSSL is recognised.
Furthermore, specifying
diff --git a/doc/tinc.texi b/doc/tinc.texi
index 2e519d1c..ab3dca23 100644
--- a/doc/tinc.texi
+++ b/doc/tinc.texi
@@ -1328,7 +1328,7 @@ Multiple Address variables can be specified, in which case each address will be
tried until a working connection has been established.
@cindex Cipher
-@item Cipher = <@var{cipher}> (blowfish)
+@item Cipher = <@var{cipher}> (aes-256-cbc)
The symmetric cipher algorithm used to encrypt UDP packets using the legacy protocol.
Any cipher supported by LibreSSL or OpenSSL is recognized.
Furthermore, specifying @samp{none} will turn off packet encryption.
--
2.36.0

View file

@ -0,0 +1,230 @@
From 4e64f72feb99b7933e907fb0fab93368749db779 Mon Sep 17 00:00:00 2001
From: Guus Sliepen <guus@tinc-vpn.org>
Date: Sun, 22 Aug 2021 22:44:04 +0200
Subject: [PATCH 09/10] Make the ExperimentalProtocol option obsolete.
Remove mentions of it from the documentation, but keep supporting the
option for now, as this makes it easier to test compatibility with the
legacy protocol.
---
README.md | 8 ++++----
doc/tinc.conf.5.in | 18 +++---------------
doc/tinc.texi | 21 ++++++---------------
src/tincctl.c | 2 +-
test/integration/algorithms.py | 4 ++--
test/integration/legacy_protocol.py | 4 ++--
test/integration/splice.py | 4 ++--
7 files changed, 20 insertions(+), 41 deletions(-)
diff --git a/README.md b/README.md
index 11129f79..9e3a64a4 100644
--- a/README.md
+++ b/README.md
@@ -55,12 +55,12 @@ versions, the security might only be as good as that of the oldest version.
## Compatibility
-Version 1.1pre18 is compatible with 1.0pre8, 1.0 and later, but not with older
+Version 1.1pre18 is compatible with 1.0 and later, but not with older
versions of tinc.
-When the ExperimentalProtocol option is used, tinc is still compatible with
-1.0.X, 1.1pre11 and later, but not with any version between 1.1pre1 and
-1.1pre10.
+Note that this pre-release version of tinc 1.1 might be incompatible with older
+pre-release versions as the new cryptographic protocol might still undergo
+changes.
## Requirements
diff --git a/doc/tinc.conf.5.in b/doc/tinc.conf.5.in
index 0cfdd089..a5a56ed5 100644
--- a/doc/tinc.conf.5.in
+++ b/doc/tinc.conf.5.in
@@ -287,15 +287,6 @@ When combined with the IndirectData option,
packets for nodes for which we do not have a meta connection with are also dropped.
.It Va Ed25519PrivateKeyFile Li = Ar filename Po Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /ed25519_key.priv Pc
The file in which the private Ed25519 key of this tinc daemon resides.
-This is only used if
-.Va ExperimentalProtocol
-is enabled.
-.It Va ExperimentalProtocol Li = yes | no Pq yes
-When this option is enabled, the SPTPS protocol will be used when connecting to nodes that also support it.
-Ephemeral ECDH will be used for key exchanges,
-and Ed25519 will be used instead of RSA for authentication.
-When enabled, an Ed25519 key must have been generated before with
-.Nm tinc generate-ed25519-keys .
.It Va Forwarding Li = off | internal | kernel Po internal Pc Bq experimental
This option selects the way indirect packets are forwarded.
.Bl -tag -width indent
@@ -569,8 +560,7 @@ Furthermore, specifying
.Qq none
will turn off packet encryption.
It is best to use only those ciphers which support CBC mode.
-This option has no effect for connections between nodes using
-.Va ExperimentalProtocol .
+This option only affects communication using the legacy protocol.
.It Va ClampMSS Li = yes | no Pq yes
This option specifies whether tinc should clamp the maximum segment size (MSS)
of TCP packets to the path MTU. This helps in situations where ICMP
@@ -585,8 +575,7 @@ Any digest supported by LibreSSL or OpenSSL is recognised.
Furthermore, specifying
.Qq none
will turn off packet authentication.
-This option has no effect for connections between nodes using
-.Va ExperimentalProtocol .
+This option only affects communication using the legacy protocol.
.It Va IndirectData Li = yes | no Pq no
When set to yes, only nodes which already have a meta connection to you
will try to establish direct communication with you.
@@ -596,8 +585,7 @@ The length of the message authentication code used to authenticate UDP packets.
Can be anything from
.Qq 0
up to the length of the digest produced by the digest algorithm.
-This option has no effect for connections between nodes using
-.Va ExperimentalProtocol .
+This option only affects communication using the legacy protocol.
.It Va PMTU Li = Ar mtu Po 1514 Pc
This option controls the initial path MTU to this node.
.It Va PMTUDiscovery Li = yes | no Po yes Pc
diff --git a/doc/tinc.texi b/doc/tinc.texi
index ab3dca23..c1e62a52 100644
--- a/doc/tinc.texi
+++ b/doc/tinc.texi
@@ -1025,15 +1025,6 @@ packets for nodes for which we do not have a meta connection with are also dropp
@cindex Ed25519PrivateKeyFile
@item Ed25519PrivateKeyFile = <@var{path}> (@file{@value{sysconfdir}/tinc/@var{netname}/ed25519_key.priv})
The file in which the private Ed25519 key of this tinc daemon resides.
-This is only used if ExperimentalProtocol is enabled.
-
-@cindex ExperimentalProtocol
-@item ExperimentalProtocol = <yes|no> (yes)
-When this option is enabled, the SPTPS protocol will be used when connecting to nodes that also support it.
-Ephemeral ECDH will be used for key exchanges,
-and Ed25519 will be used instead of RSA for authentication.
-When enabled, an Ed25519 key must have been generated before with
-@command{tinc generate-ed25519-keys}.
@cindex Forwarding
@item Forwarding = <off|internal|kernel> (internal) [experimental]
@@ -1333,7 +1324,7 @@ The symmetric cipher algorithm used to encrypt UDP packets using the legacy prot
Any cipher supported by LibreSSL or OpenSSL is recognized.
Furthermore, specifying @samp{none} will turn off packet encryption.
It is best to use only those ciphers which support CBC mode.
-This option has no effect for connections using the SPTPS protocol, which always use AES-256-CTR.
+This option only affects communication using the legacy protocol.
@cindex ClampMSS
@item ClampMSS = <yes|no> (yes)
@@ -1352,7 +1343,7 @@ Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib),
The digest algorithm used to authenticate UDP packets using the legacy protocol.
Any digest supported by LibreSSL or OpenSSL is recognized.
Furthermore, specifying @samp{none} will turn off packet authentication.
-This option has no effect for connections using the SPTPS protocol, which always use HMAC-SHA-256.
+This option only affects communication using the legacy protocol.
@cindex IndirectData
@item IndirectData = <yes|no> (no)
@@ -1365,7 +1356,7 @@ It is best to leave this option out or set it to no.
The length of the message authentication code used to authenticate UDP packets using the legacy protocol.
Can be anything from 0
up to the length of the digest produced by the digest algorithm.
-This option has no effect for connections using the SPTPS protocol, which never truncate MACs.
+This option only affects communication using the legacy protocol.
@cindex PMTU
@item PMTU = <@var{mtu}> (1514)
@@ -3030,9 +3021,9 @@ Therefore, tinc also authenticates the data.
Finally, tinc uses sequence numbers (which themselves are also authenticated) to prevent an attacker from replaying valid packets.
Since version 1.1pre3, tinc has two protocols used to protect your data; the legacy protocol, and the new Simple Peer-to-Peer Security (SPTPS) protocol.
-The SPTPS protocol is designed to address some weaknesses in the legacy protocol.
-The new authentication protocol is used when two nodes connect to each other that both have the ExperimentalProtocol option set to yes,
-otherwise the legacy protocol will be used.
+The SPTPS protocol is designed to address some weaknesses in the legacy protocol,
+and is used automatically if both sides support it.
+Once two nodes have connected with the new protocol, rollback to the legacy protocol is not allowed.
@menu
* Legacy authentication protocol::
diff --git a/src/tincctl.c b/src/tincctl.c
index 9b39f2ce..2032b33a 100644
--- a/src/tincctl.c
+++ b/src/tincctl.c
@@ -1651,7 +1651,7 @@ const var_t variables[] = {
{"DeviceType", VAR_SERVER},
{"DirectOnly", VAR_SERVER | VAR_SAFE},
{"Ed25519PrivateKeyFile", VAR_SERVER},
- {"ExperimentalProtocol", VAR_SERVER},
+ {"ExperimentalProtocol", VAR_SERVER | VAR_OBSOLETE},
{"Forwarding", VAR_SERVER},
{"FWMark", VAR_SERVER},
{"GraphDumpFile", VAR_SERVER | VAR_OBSOLETE},
diff --git a/test/integration/algorithms.py b/test/integration/algorithms.py
index b056c7d5..52e0f820 100755
--- a/test/integration/algorithms.py
+++ b/test/integration/algorithms.py
@@ -23,7 +23,7 @@ def init(ctx: Test, digest: str, cipher: str) -> T.Tuple[Tinc, Tinc]:
set Digest {digest}
set Cipher {cipher}
"""
- foo.cmd(stdin=stdin)
+ foo.cmd("--force", stdin=stdin)
foo.start()
stdin = f"""
@@ -35,7 +35,7 @@ def init(ctx: Test, digest: str, cipher: str) -> T.Tuple[Tinc, Tinc]:
set Digest {digest}
set Cipher {cipher}
"""
- bar.cmd(stdin=stdin)
+ bar.cmd("--force", stdin=stdin)
foo.add_script(bar.script_up)
bar.add_script(foo.script_up)
diff --git a/test/integration/legacy_protocol.py b/test/integration/legacy_protocol.py
index 845ac345..f7ab1bd2 100755
--- a/test/integration/legacy_protocol.py
+++ b/test/integration/legacy_protocol.py
@@ -73,14 +73,14 @@ with Test("foo 1.1, bar 1.1") as context:
with Test("foo 1.1, bar 1.0") as context:
foo_node, bar_node = init(context)
- bar_node.cmd("set", "ExperimentalProtocol", "no")
+ bar_node.cmd("--force", "set", "ExperimentalProtocol", "no")
foo_node.cmd("del", f"{bar_node}.Ed25519PublicKey")
bar_node.cmd("del", f"{foo_node}.Ed25519PublicKey")
run_keys_test(foo_node, bar_node, empty=True)
with Test("bar 1.0 must not be allowed to connect") as context:
foo_node, bar_node = init(context)
- bar_node.cmd("set", "ExperimentalProtocol", "no")
+ bar_node.cmd("--force", "set", "ExperimentalProtocol", "no")
bar_up = bar_node.add_script(Script.SUBNET_UP)
bar_node.cmd("start")
diff --git a/test/integration/splice.py b/test/integration/splice.py
index 578845fb..868ffbc3 100755
--- a/test/integration/splice.py
+++ b/test/integration/splice.py
@@ -28,7 +28,7 @@ def init(ctx: Test, *options: str) -> T.Tuple[Tinc, Tinc]:
set Subnet 10.96.96.1
{custom}
"""
- foo.cmd(stdin=stdin)
+ foo.cmd("--force", stdin=stdin)
stdin = f"""
init {bar}
@@ -39,7 +39,7 @@ def init(ctx: Test, *options: str) -> T.Tuple[Tinc, Tinc]:
set Subnet 10.96.96.2
{custom}
"""
- bar.cmd(stdin=stdin)
+ bar.cmd("--force", stdin=stdin)
foo.add_script(Script.SUBNET_UP)
bar.add_script(Script.SUBNET_UP)
--
2.36.0

View file

@ -0,0 +1,322 @@
From f4db140a8ffc63b575181299c3964e4634606280 Mon Sep 17 00:00:00 2001
From: Guus Sliepen <guus@tinc-vpn.org>
Date: Tue, 31 Aug 2021 16:27:47 +0200
Subject: [PATCH 10/10] Move poly1305_get_tag() into poly1305.c, hide
poly1305_init().
The crypto library on Windows exposes a symbol named poly1305_init(),
which clashes with ours. We can avoid this by moving poly1305_get_tag()
to poly1305.[ch], where it belongs better, and this allows us to make
all the lower-level Poly1305 functions static.
Also remove the support for associated data while we are at it, since we
are never using it.
---
src/chacha-poly1305/chacha.h | 1 -
src/chacha-poly1305/chachapoly.c | 58 ++++----------------------------
src/chacha-poly1305/chachapoly.h | 6 ++--
src/chacha-poly1305/poly1305.c | 54 +++++++++++++++++++++++++----
src/chacha-poly1305/poly1305.h | 20 +----------
src/sptps.c | 4 +--
6 files changed, 58 insertions(+), 85 deletions(-)
diff --git a/src/chacha-poly1305/chacha.h b/src/chacha-poly1305/chacha.h
index a137ab6b..d4784f49 100644
--- a/src/chacha-poly1305/chacha.h
+++ b/src/chacha-poly1305/chacha.h
@@ -31,4 +31,3 @@ void chacha_encrypt_bytes(struct chacha_ctx *x, const unsigned char *m,
unsigned char *c, uint32_t bytes);
#endif /* CHACHA_H */
-
diff --git a/src/chacha-poly1305/chachapoly.c b/src/chacha-poly1305/chachapoly.c
index 9a6620ce..68f04edd 100644
--- a/src/chacha-poly1305/chachapoly.c
+++ b/src/chacha-poly1305/chachapoly.c
@@ -53,52 +53,6 @@ static int memcmp_eq(const void *av, const void *bv, int n) {
return res;
}
-/**
- * Poly1305 tag generation. This concatenates a string according to the rules
- * outlined in RFC 7539 and calculates the tag.
- *
- * \param poly_key 32 byte secret one-time key for poly1305
- * \param ad associated data
- * \param ad_len associated data length in bytes
- * \param ct ciphertext
- * \param ct_len ciphertext length in bytes
- * \param tag pointer to 16 bytes for tag storage
- */
-static void poly1305_get_tag(unsigned char *poly_key, const void *ad,
- int ad_len, const void *ct, int ct_len, unsigned char *tag) {
- struct poly1305_context poly;
- unsigned left_over;
- uint64_t len;
- unsigned char pad[16];
-
- poly1305_init(&poly, poly_key);
- memset(&pad, 0, sizeof(pad));
-
- /* associated data and padding */
- poly1305_update(&poly, ad, ad_len);
- left_over = ad_len % 16;
-
- if(left_over) {
- poly1305_update(&poly, pad, 16 - left_over);
- }
-
- /* payload and padding */
- poly1305_update(&poly, ct, ct_len);
- left_over = ct_len % 16;
-
- if(left_over) {
- poly1305_update(&poly, pad, 16 - left_over);
- }
-
- /* lengths */
- len = ad_len;
- poly1305_update(&poly, (unsigned char *)&len, 8);
- len = ct_len;
- poly1305_update(&poly, (unsigned char *)&len, 8);
-
- poly1305_finish(&poly, tag);
-}
-
int chachapoly_init(struct chachapoly_ctx *ctx, const void *key, int key_len) {
assert(key_len == 128 || key_len == 256);
@@ -108,7 +62,7 @@ int chachapoly_init(struct chachapoly_ctx *ctx, const void *key, int key_len) {
}
int chachapoly_crypt(struct chachapoly_ctx *ctx, const void *nonce,
- const void *ad, int ad_len, void *input, int input_len,
+ void *input, int input_len,
void *output, void *tag, int tag_len, int encrypt) {
unsigned char poly_key[CHACHA_BLOCKLEN];
unsigned char calc_tag[POLY1305_TAGLEN];
@@ -121,7 +75,7 @@ int chachapoly_crypt(struct chachapoly_ctx *ctx, const void *nonce,
/* check tag if decrypting */
if(encrypt == 0 && tag_len) {
- poly1305_get_tag(poly_key, ad, ad_len, input, input_len, calc_tag);
+ poly1305_get_tag(poly_key, input, input_len, calc_tag);
if(memcmp_eq(calc_tag, tag, tag_len) != 0) {
return CHACHAPOLY_INVALID_MAC;
@@ -135,7 +89,7 @@ int chachapoly_crypt(struct chachapoly_ctx *ctx, const void *nonce,
/* add tag if encrypting */
if(encrypt && tag_len) {
- poly1305_get_tag(poly_key, ad, ad_len, output, input_len, calc_tag);
+ poly1305_get_tag(poly_key, output, input_len, calc_tag);
memcpy(tag, calc_tag, tag_len);
}
@@ -143,7 +97,7 @@ int chachapoly_crypt(struct chachapoly_ctx *ctx, const void *nonce,
}
int chachapoly_crypt_short(struct chachapoly_ctx *ctx, const void *nonce,
- const void *ad, int ad_len, void *input, int input_len,
+ void *input, int input_len,
void *output, void *tag, int tag_len, int encrypt) {
unsigned char keystream[CHACHA_BLOCKLEN];
unsigned char calc_tag[POLY1305_TAGLEN];
@@ -159,7 +113,7 @@ int chachapoly_crypt_short(struct chachapoly_ctx *ctx, const void *nonce,
/* check tag if decrypting */
if(encrypt == 0 && tag_len) {
- poly1305_get_tag(keystream, ad, ad_len, input, input_len, calc_tag);
+ poly1305_get_tag(keystream, input, input_len, calc_tag);
if(memcmp_eq(calc_tag, tag, tag_len) != 0) {
return CHACHAPOLY_INVALID_MAC;
@@ -174,7 +128,7 @@ int chachapoly_crypt_short(struct chachapoly_ctx *ctx, const void *nonce,
/* add tag if encrypting */
if(encrypt && tag_len) {
- poly1305_get_tag(keystream, ad, ad_len, output, input_len, calc_tag);
+ poly1305_get_tag(keystream, output, input_len, calc_tag);
memcpy(tag, calc_tag, tag_len);
}
diff --git a/src/chacha-poly1305/chachapoly.h b/src/chacha-poly1305/chachapoly.h
index ffc9576d..5d01f525 100644
--- a/src/chacha-poly1305/chachapoly.h
+++ b/src/chacha-poly1305/chachapoly.h
@@ -52,8 +52,6 @@ int chachapoly_init(struct chachapoly_ctx *ctx, const void *key, int key_len);
*
* \param ctx context data
* \param nonce nonce (12 bytes)
- * \param ad associated data
- * \param ad_len associated data length in bytes
* \param input plaintext/ciphertext input
* \param input_len input length in bytes;
* \param output plaintext/ciphertext output
@@ -65,7 +63,7 @@ int chachapoly_init(struct chachapoly_ctx *ctx, const void *key, int key_len);
* failed when decrypting
*/
int chachapoly_crypt(struct chachapoly_ctx *ctx, const void *nonce,
- const void *ad, int ad_len, void *input, int input_len,
+ void *input, int input_len,
void *output, void *tag, int tag_len, int encrypt);
/**
@@ -76,7 +74,7 @@ int chachapoly_crypt(struct chachapoly_ctx *ctx, const void *nonce,
* chachapoly_crypt.
*/
int chachapoly_crypt_short(struct chachapoly_ctx *ctx, const void *nonce,
- const void *ad, int ad_len, void *input, int input_len,
+ void *input, int input_len,
void *output, void *tag, int tag_len, int encrypt);
#endif
diff --git a/src/chacha-poly1305/poly1305.c b/src/chacha-poly1305/poly1305.c
index 0c90564c..b25435a7 100644
--- a/src/chacha-poly1305/poly1305.c
+++ b/src/chacha-poly1305/poly1305.c
@@ -5,6 +5,20 @@ public domain
#include "poly1305.h"
+/* use memcpy() to copy blocks of memory (typically faster) */
+#define USE_MEMCPY 1
+/* use unaligned little-endian load/store (can be faster) */
+#define USE_UNALIGNED 0
+
+struct poly1305_context {
+ uint32_t r[5];
+ uint32_t h[5];
+ uint32_t pad[4];
+ size_t leftover;
+ unsigned char buffer[POLY1305_BLOCK_SIZE];
+ unsigned char final;
+};
+
#if (USE_UNALIGNED == 1)
#define U8TO32(p) \
(*((uint32_t *)(p)))
@@ -33,7 +47,7 @@ U32TO8(unsigned char *p, uint32_t v) {
}
#endif
-void
+static void
poly1305_init(struct poly1305_context *st, const unsigned char key[32]) {
/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
st->r[0] = (U8TO32(&key[ 0])) & 0x3ffffff;
@@ -131,7 +145,7 @@ poly1305_blocks(struct poly1305_context *st, const unsigned char *m, size_t byte
st->h[4] = h4;
}
-void
+static void
poly1305_finish(struct poly1305_context *st, unsigned char mac[16]) {
uint32_t h0, h1, h2, h3, h4, c;
uint32_t g0, g1, g2, g3, g4;
@@ -241,8 +255,7 @@ poly1305_finish(struct poly1305_context *st, unsigned char mac[16]) {
st->pad[3] = 0;
}
-
-void
+static void
poly1305_update(struct poly1305_context *st, const unsigned char *m, size_t bytes) {
size_t i;
@@ -293,10 +306,37 @@ poly1305_update(struct poly1305_context *st, const unsigned char *m, size_t byte
}
}
+/**
+ * Poly1305 tag generation. This concatenates a string according to the rules
+ * outlined in RFC 7539 and calculates the tag.
+ *
+ * \param key 32 byte secret one-time key for poly1305
+ * \param ct ciphertext
+ * \param ct_len ciphertext length in bytes
+ * \param tag pointer to 16 bytes for tag storage
+ */
void
-poly1305_auth(unsigned char mac[16], const unsigned char *m, size_t bytes, const unsigned char key[32]) {
+poly1305_get_tag(const unsigned char key[32], const void *ct, int ct_len, unsigned char tag[16]) {
struct poly1305_context ctx;
+ unsigned left_over;
+ uint64_t len;
+ unsigned char pad[16];
+
poly1305_init(&ctx, key);
- poly1305_update(&ctx, m, bytes);
- poly1305_finish(&ctx, mac);
+ memset(&pad, 0, sizeof(pad));
+
+ /* payload and padding */
+ poly1305_update(&ctx, ct, ct_len);
+ left_over = ct_len % 16;
+
+ if(left_over) {
+ poly1305_update(&ctx, pad, 16 - left_over);
+ }
+
+ /* lengths */
+ len = 0;
+ poly1305_update(&ctx, (unsigned char *)&len, 8);
+ len = ct_len;
+ poly1305_update(&ctx, (unsigned char *)&len, 8);
+ poly1305_finish(&ctx, tag);
}
diff --git a/src/chacha-poly1305/poly1305.h b/src/chacha-poly1305/poly1305.h
index 624a19a9..5fc3b903 100644
--- a/src/chacha-poly1305/poly1305.h
+++ b/src/chacha-poly1305/poly1305.h
@@ -9,24 +9,6 @@
#define POLY1305_TAGLEN 16
#define POLY1305_BLOCK_SIZE 16
-/* use memcpy() to copy blocks of memory (typically faster) */
-#define USE_MEMCPY 1
-/* use unaligned little-endian load/store (can be faster) */
-#define USE_UNALIGNED 0
-
-struct poly1305_context {
- uint32_t r[5];
- uint32_t h[5];
- uint32_t pad[4];
- size_t leftover;
- unsigned char buffer[POLY1305_BLOCK_SIZE];
- unsigned char final;
-};
-
-void poly1305_init(struct poly1305_context *ctx, const unsigned char key[32]);
-void poly1305_update(struct poly1305_context *ctx, const unsigned char *m, size_t bytes);
-void poly1305_finish(struct poly1305_context *ctx, unsigned char mac[16]);
-void poly1305_auth(unsigned char mac[16], const unsigned char *m, size_t bytes, const unsigned char key[32]);
+void poly1305_get_tag(const unsigned char key[32], const void *ct, int ct_len, unsigned char tag[16]);
#endif /* POLY1305_H */
-
diff --git a/src/sptps.c b/src/sptps.c
index 7c8d20b7..8f713fe6 100644
--- a/src/sptps.c
+++ b/src/sptps.c
@@ -168,7 +168,7 @@ static bool cipher_encrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8
#ifndef HAVE_OPENSSL
case SPTPS_CHACHA_POLY1305: {
- if(chachapoly_crypt(ctx, nonce, NULL, 0, (void *)in, inlen, out, out + inlen, 16, 1) != CHACHAPOLY_OK) {
+ if(chachapoly_crypt(ctx, nonce, (void *)in, inlen, out, out + inlen, 16, 1) != CHACHAPOLY_OK) {
return false;
}
@@ -249,7 +249,7 @@ static bool cipher_decrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8
#ifndef HAVE_OPENSSL
case SPTPS_CHACHA_POLY1305:
- if(chachapoly_crypt(ctx, nonce, NULL, 0, (void *)in, inlen, out, (void *)(in + inlen), 16, 0) != CHACHAPOLY_OK) {
+ if(chachapoly_crypt(ctx, nonce, (void *)in, inlen, out, (void *)(in + inlen), 16, 0) != CHACHAPOLY_OK) {
return false;
}
--
2.36.0

View file

@ -1,65 +0,0 @@
Package: tinc
Version: 1.0.33-1
Severity: important
Dear Guus,
I have been using tinc since 2009 and it is great!
When PMTUDiscovery=yes and Mode=switch, and if ipv6 is used inside
tinc, the ICMPv6 "Packet Too Big" packets have incorrect checksums.
It can be reproduced by `ping6 <host in tinc> -s 1800` and `tcpdump -i
<tinc interface>`. Consequently, the host ignores the tinc-generated
ICMPv6 packets, PMTUDiscovery does not work and the connections freeze
when data flows are big.
I find the bug is gone if the function "inet_checksum" in route.c is
not inlined, either by compiling tinc with "-O2
-fno-inline-functions", or apply a patch such as,
diff --git a/src/route.c b/src/route.c
index ff82c06e..cd55383a 100644
--- a/src/route.c
+++ b/src/route.c
@@ -60,7 +60,7 @@ static const size_t opt_size = sizeof(struct nd_opt_hdr);
/* RFC 1071 */
-static uint16_t inet_checksum(void *data, int len, uint16_t prevsum) {
+__attribute__ ((noinline)) static uint16_t inet_checksum(void *data, int len, uint16_t prevsum) {
uint16_t *p = data;
uint32_t checksum = prevsum ^ 0xFFFF;
I have tested with gcc-7.3.0 and gcc-5.4.0. They behaved the same. I
am not good at assembly to find out what really happened, but it is
for sure that inet_checksum does not work as expected if compiled
inline.
Thanks!
Yours,
Benda
-- System Information:
Debian Release: buster/sid
APT prefers unstable
APT policy: (500, 'unstable')
Architecture: amd64 (x86_64)
Kernel: Linux 4.9.0-5-amd64 (SMP w/8 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) (ignored: LC_ALL set to en_US.UTF-8), LANGUAGE=en_US:en (charmap=UTF-8) (ignored: LC_ALL set to en_US.UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: sysvinit (via /sbin/init)
Versions of packages tinc depends on:
ii libc6 2.26-2
ii liblzo2-2 2.08-1.2+b2
ii libssl1.1 1.1.0g-2
ii lsb-base 9.20170808
ii zlib1g 1:1.2.8.dfsg-5
tinc recommends no packages.
tinc suggests no packages.

11
debian/patches/fix-version-number vendored Normal file
View file

@ -0,0 +1,11 @@
--- a/configure.ac
+++ b/configure.ac
@@ -3,7 +3,7 @@
origcflags="$CFLAGS"
AC_PREREQ(2.69)
-AC_INIT([tinc], m4_esyscmd_s((git describe || echo UNKNOWN) | sed 's/release-//'))
+AC_INIT([tinc], [1.1~pre18])
AC_CONFIG_SRCDIR([src/tincd.c])
AM_INIT_AUTOMAKE([std-options subdir-objects nostdinc silent-rules -Wall])
AC_CONFIG_HEADERS([config.h])

13
debian/patches/series vendored
View file

@ -1,2 +1,11 @@
fix-incorrect-icmpv6-checksum 0001-Add-AES-256-GCM-support-to-SPTPS.patch
support-etc-defaults-tinc 0002-Add-cipher-suite-selection-options-to-sptps_test.patch
0003-Let-sptps_speed-benchmark-all-cipher-suites.patch
0004-If-we-link-with-OpenSSL-use-it-for-Chacha20-Poly1305.patch
0005-Update-the-built-in-Chacha20-Poly1305-code-to-an-RFC.patch
0006-Ensure-we-are-compatible-with-LibreSSL.patch
0007-Fix-infinite-loop-on-SPTPS-errors-when-running-sptps.patch
0008-Fix-documentation-of-default-cipher-algorithm-used-f.patch
0009-Make-the-ExperimentalProtocol-option-obsolete.patch
0010-Move-poly1305_get_tag-into-poly1305.c-hide-poly1305_.patch
fix-version-number

View file

@ -1,12 +0,0 @@
--- a/systemd/tinc@.service.in
+++ b/systemd/tinc@.service.in
@@ -9,7 +9,8 @@
[Service]
Type=simple
WorkingDirectory=@sysconfdir@/tinc/%i
-ExecStart=@sbindir@/tincd -n %i -D
+EnvironmentFile=/etc/default/tinc
+ExecStart=@sbindir@/tincd -n %i -D $EXTRA
ExecReload=@sbindir@/tincd -n %i -kHUP
KillMode=mixed
Restart=on-failure

10
debian/postinst vendored
View file

@ -6,16 +6,8 @@ set -e
case "$1" in case "$1" in
configure) configure)
if [ ! -e /dev/.devfsd ] ; then if [ ! -e /dev/.devfs ] ; then
if [ ! -e /dev/net/tun ] ; then if [ ! -e /dev/tun ] ; then if [ -e /dev/MAKEDEV ]; then
echo "Creating tun device..."
cd /dev && ./MAKEDEV net/tun 2>/dev/null || ./MAKEDEV tun 2>/dev/null || echo "Failed to create tun device."
fi; fi; fi
fi; fi
if [ ! -e $NETSFILE ] ; then if [ ! -e $NETSFILE ] ; then
echo "## This file contains all names of the networks to be started on system startup when using sysvinit." > $NETSFILE echo "## This file contains all names of the networks to be started on system startup." > $NETSFILE
echo "## If you are using systemd, use systemctl enable tinc@netname to enable individual networks." >> $NETSFILE
fi fi
;; ;;

2
debian/preinst vendored
View file

@ -8,7 +8,7 @@ set -e
case "$1" in case "$1" in
upgrade) upgrade)
if dpkg --compare-versions "$2" '<<' "1.0.27-1"; then if dpkg --compare-versions "$2" '<<' "1.1~pre11-1"; then
if [ -f "$NETSFILE" ]; then if [ -f "$NETSFILE" ]; then
echo -n "Creating systemd service instances from nets.boot:" echo -n "Creating systemd service instances from nets.boot:"
mkdir -p "$WANTS" mkdir -p "$WANTS"

17
debian/rules vendored
View file

@ -1,16 +1,21 @@
#!/usr/bin/make -f #!/usr/bin/make -f
%: %:
dh $@ dh $@ --with quilt
override_dh_clean:
dh_clean
rm -f doc/tinc.info
override_dh_auto_configure: override_dh_auto_configure:
dh_auto_configure -- --enable-uml --with-systemd=/lib/systemd/system --runstatedir=/run dh_auto_configure -- --enable-uml \
--with-systemd=/lib/systemd/system/
$(MAKE) clean
override_dh_auto_install: override_dh_auto_install:
dh_auto_install -- install-html dh_auto_install -- install-html
# Remove info dir file # Remove info dir file
rm -f debian/tinc/usr/share/info/dir rm -f debian/tinc/usr/share/info/dir
override_dh_auto_test:
# Don't run the tests, it involves starting tinc daemons and making network connections.
# I don't think the autobuilders will like this.
override_dh_installinit:
dh_installinit -r

2
debian/tinc.default vendored
View file

@ -4,4 +4,4 @@
# Limits to be configured for the tincd process. Please read your shell # Limits to be configured for the tincd process. Please read your shell
# (pointed by /bin/sh) documentation for ulimit. You probably want to raise the # (pointed by /bin/sh) documentation for ulimit. You probably want to raise the
# max locked memory value if using both --mlock and --user flags. # max locked memory value if using both --mlock and --user flags.
# LIMITS="-l 1024" # LIMITS="-l 128"

7
debian/tinc.dirs vendored
View file

@ -1,7 +0,0 @@
usr/sbin
usr/share
etc
etc/init.d
usr/share/locale
usr/share/doc/tinc
etc/tinc

6
debian/tinc.files vendored
View file

@ -1,6 +0,0 @@
usr/sbin/tincd
usr/share/man
etc
usr/share/doc/tinc
usr/share/locale
usr/share/info

View file

@ -2,40 +2,12 @@
set -e set -e
if [ "$METHOD" = loopback -o -z "$IF_TINC_NET" ]; then test "$METHOD" != loopback -a -n "$IF_TINC_NET" || exit 0
exit 0
fi
# Determine location of the PID file if test -z "$IF_TINC_PIDFILE"; then
/usr/sbin/tinc -n "$IF_TINC_NET" stop $EXTRA
EXTRA=""
if [ -n "$IF_TINC_PIDFILE" ]; then
EXTRA="--pidfile=$IF_TINC_PIDFILE"
else else
IF_TINC_PIDFILE=/var/run/tinc.$IF_TINC_NET.pid /usr/sbin/tinc -n "$IF_TINC_NET" --pidfile="$IF_TINC_PIDFILE" stop
fi fi
# Stop the tinc daemon
read pid rest < $IF_TINC_PIDFILE 2>/dev/null
/usr/sbin/tincd -n "$IF_TINC_NET" -k $EXTRA
# Wait for it to shut down properly
/bin/sleep 0.1
i=0;
while [ -f $IF_TINC_PIDFILE ] ; do
if [ ! -e "/proc/$pid" ] ; then
exit 0
fi
if [ $i = '30' ] ; then
echo 'Failed to stop tinc daemon!'
exit 1
fi
/bin/sleep 0.1
i=$(($i+1))
done
exit 0 exit 0

56
debian/tinc.if-pre-up vendored
View file

@ -2,13 +2,13 @@
set -e set -e
if [ "$METHOD" = loopback -o -z "$IF_TINC_NET" ]; then test -n "$IF_TINC_NET" || exit 0
exit 0
fi
# Read options from /etc/default # Read options from /etc/default
[ -r /etc/default/tinc ] && . /etc/default/tinc if test -e /etc/default/tinc; then
. /etc/default/tinc
fi
# Set process limits # Set process limits
@ -23,48 +23,24 @@ setlimits() {
fi fi
done done
} }
test -n "$LIMITS" && setlimits $LIMITS test -n "$LIMITS" && setlimits $LIMITS
# Read options from /etc/network/interfaces # Read options from /etc/network/interfaces
[ -n "$IF_TINC_CONFIG" ] && EXTRA="$EXTRA -c $IF_TINC_CONFIG" test -z "$IF_TINC_CONFIG" || EXTRA="$EXTRA -c $IF_TINC_CONFIG"
[ -n "$IF_TINC_DEBUG" ] && EXTRA="$EXTRA -d$IF_TINC_DEBUG" test -z "$IF_TINC_DEBUG" || EXTRA="$EXTRA -d$IF_TINC_DEBUG"
[ -n "$IF_TINC_MLOCK" ] && EXTRA="$EXTRA --mlock" test -z "$IF_TINC_MLOCK" || EXTRA="$EXTRA --mlock"
[ -n "$IF_TINC_LOGFILE" ] && EXTRA="$EXTRA --logfile=$IF_TINC_LOGFILE" test -z "$IF_TINC_LOGFILE" || EXTRA="$EXTRA --logfile=$IF_TINC_LOGFILE"
[ -n "$IF_TINC_PIDFILE" ] && EXTRA="$EXTRA --pidfile=$IF_TINC_PIDFILE" || IF_TINC_PIDFILE=/var/run/tinc.$IF_TINC_NET.pid test -z "$IF_TINC_PIDFILE" || EXTRA="$EXTRA --pidfile=$IF_TINC_PIDFILE" || IF_TINC_PIDFILE=/var/run/tinc.$IF_TINC_NET.pid
[ -n "$IF_TINC_CHROOT" ] && EXTRA="$EXTRA --chroot" test -z "$IF_TINC_CHROOT" || EXTRA="$EXTRA --chroot"
[ -n "$IF_TINC_USER" ] && EXTRA="$EXTRA --user=$IF_TINC_USER" test -z "$IF_TINC_USER" || EXTRA="$EXTRA --user=$IF_TINC_USER"
# Start tinc daemon # Start tinc daemon
/usr/sbin/tincd -n "$IF_TINC_NET" -o "Interface=$IFACE" $EXTRA if test -z "$IF_TINC_PIDFILE"; then
/usr/sbin/tinc -n "$IF_TINC_NET" start -o "Interface=$IFACE" $EXTRA
# Wait for it to come up properly else
/usr/sbin/tinc -n "$IF_TINC_NET" --pidfile="$IF_TINC_PIDFILE" start -o "Interface=$IFACE" $EXTRA
/bin/sleep 0.1 fi
i=0;
while [ ! -f $IF_TINC_PIDFILE ] ; do
if [ $i = '30' ] ; then
echo 'Failed to start tinc daemon!'
exit 1
fi
/bin/sleep 0.1
i=$(($i+1))
done
while read pid rest < $IF_TINC_PIDFILE ; do
if [ -e "/proc/$pid" ] ; then
exit 0
fi
if [ $i = '30' ] ; then
echo 'Failed to start tinc daemon!'
exit 1
fi
/bin/sleep 0.1
i=$(($i+1))
done
exit 0 exit 0

10
debian/tinc.if-up vendored
View file

@ -2,8 +2,10 @@
set -e set -e
if [ "$METHOD" = loopback -o -n "$IF_TINC_NET" ]; then test "$METHOD" != loopback -a -n "$IF_TINC_NET" || exit 0
exit 0
fi
invoke-rc.d tinc alarm || exit 0 if test -z "$IF_TINC_PIDFILE"; then
/usr/sbin/tinc -n "$IF_TINC_NET" retry
else
/usr/sbin/tinc -n "$IF_TINC_NET" --pidfile="$IF_TINC_PIDFILE" retry
fi

View file

@ -21,6 +21,7 @@
. /lib/lsb/init-functions . /lib/lsb/init-functions
DAEMON="/usr/sbin/tincd" DAEMON="/usr/sbin/tincd"
CONTROL="/usr/sbin/tinc"
NAME="tinc" NAME="tinc"
DESC="tinc daemons" DESC="tinc daemons"
TCONF="/etc/tinc" TCONF="/etc/tinc"
@ -41,7 +42,10 @@ foreach_net() {
shift shift
egrep '^[ ]*[a-zA-Z0-9_-]+' $NETSFILE | while read net args; do egrep '^[ ]*[a-zA-Z0-9_-]+' $NETSFILE | while read net args; do
echo -n " $net" echo -n " $net"
"$@" $net $args case "$1" in
start|restart) $CONTROL -n $net $1 $EXTRA $args ;;
*) $CONTROL -n $net $1 ;;
esac
done done
echo "." echo "."
} }
@ -49,7 +53,7 @@ foreach_net() {
signal_running() { signal_running() {
for i in /var/run/tinc.*pid; do for i in /var/run/tinc.*pid; do
if [ -f "$i" ]; then if [ -f "$i" ]; then
head -1 $i | while read pid; do head -1 $i | while read pid junk; do
kill -$1 $pid kill -$1 $pid
done done
fi fi
@ -70,51 +74,6 @@ setlimits() {
test -n "$LIMITS" && setlimits $LIMITS test -n "$LIMITS" && setlimits $LIMITS
start() {
$DAEMON $EXTRA -n "$@"
}
stop() {
[ -f /var/run/tinc.$1.pid ] || return
read pid rest </var/run/tinc.$1.pid || return
kill -0 "$pid" 2>/dev/null || return
$DAEMON -n $1 -k || return
i=0;
/bin/sleep 0.5
# Wait for the pidfile to disappear
while [ -f /var/run/tinc.$1.pid ]; do
# And check that there is an actual process running
kill -0 "$pid" 2>/dev/null || return
if [ $i = '10' ] ; then
# It's still alive, kill it again and give up
$DAEMON -n $1 -k && /bin/sleep 0.5
break
else
echo -n "."
i=$(($i+1))
fi
/bin/sleep 0.5
done
}
reload() {
$DAEMON -n $1 -kHUP
}
alarm() {
$DAEMON -n $1 -kALRM
}
restart() {
stop "$@"
start "$@"
}
case "$1" in case "$1" in
start) start)
foreach_net "Starting $DESC:" start foreach_net "Starting $DESC:" start
@ -128,11 +87,15 @@ case "$1" in
restart) restart)
foreach_net "Restarting $DESC:" restart foreach_net "Restarting $DESC:" restart
;; ;;
alarm) force-restart)
$0 stop
$0 start
;;
retry)
signal_running ALRM signal_running ALRM
;; ;;
*) *)
echo "Usage: /etc/init.d/$NAME {start|stop|reload|restart|force-reload|alarm}" echo "Usage: /etc/init.d/$NAME {start|stop|reload|restart|force-reload|retry}"
exit 1 exit 1
;; ;;
esac esac

View file

@ -1,70 +0,0 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1
mQINBEVZzTABEADawFv/ibQ48uA1eRhL07vdM36Pcq2HDyuyNA+vYEalNH4jLmha
nGPvDALWwX0DXIWDAG8zeTj8s8zliLIjuPS4WRI2YdKIvWeG9fEvpKSXVWa42ica
dpzn/H2aBd4Ax6rQaiTXKOvxANAp2Veb+73ssPV5AL00uGTpzhh98xQzfFQCZ9ZL
YSVPqbMed5oCt/4jM9FBO2CuBtkfiO0dVVYtW7FAVjcIlE2NaZol/KGvz7wsS+yA
dE42W0l5MdQueLmTF4AIUSSTyPFGMQoyqh+MPif73Y589IGcW6GdfKYWnVDo6Trh
HOhcEky+uTYKb6NL0vrJgUiYVMzAOXFDdJni1eQGO6EfZRNYtTga3alWq/jVelK7
BID5JyNbkrTAqdPnhJGivVyk8gGX3+Hng8rkXTfWhp6yAYau1QfBm0F2tIQmpL1C
+7DoLvFErboQf685jXJBjzyvsJxB2ZLH1OOw6mNL0hy2LFkIyGza/bktY2em4apo
KWV5AM5LpyW6THH1oDS7706xFNkf4IFhKE0hKPzBiRnMDjRtMI131lkc5+P8Lqf5
jLTCFUgbEhU6Dz2YjhHAumVm0NWJETUpFDtVvMrqk+mp5xldUOWRNlYQC5aQOyda
eHOlNzB/BFbPhKMWI/zWlEH6f0t6WjHb4iwpWO47511aVNHF59aPzbAHxwARAQAB
tC9UaW5jIERldmVsb3BtZW50IFRlYW0gPHRpbmMtZGV2ZWxAdGluYy12cG4ub3Jn
PokCNgQTAQIAIAUCRVnNMAIbAwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEEpg
hLnA1x9KxOAQAMPhO2WTXv9AaGQBQhyyoGseKoSfcRjtI9YEfE0OInQQ2E+SPYF/
dkfeLGAUqa4foTYQlMqfw70vBhTdVCb7HLTGn6/ICFUtDwakUQCgUQGlUVQiondA
8W6jj+QWrh5BQhHuXy2nCVaKnksu0/xQPsJotghxuYqaot3iJ4qVw9iT/Yeo9irH
Ffftqu0OVCdQ5zQuFNI9YCv/C83L59ecH7bOzYz2efTyobvxrhmgQtgOQwCWOE09
Kr3veM9KLG33YoXlqv8QN/3CwtsJvSwfhj+R2JowZC7RqHe/yznRzmRMsgbrolxi
uiJLonGxcNNkD7WhXi7/zL4A/JaC27XrFf1MPLv8aiTwnOIfrXd5jawpauUOZOXK
UjIZHlIqviB0r5s7A+AFeHW38Tp9VzNuQ7aEl5bHbSXV+s7DTAwGb279z0AVaJ3h
5hWFxupw7UoGdzROwCBYzeX3sioAL6QvkXua8X6zOH45VEiSwrRX3Hlx/MLo7Z4g
PWgFLf6WviHQXCG834To1XIwUk9RgNsL7OzGjtaCuRymADImKMNwierq2zTfoRFQ
v9onIadIMF1fsc70hiBG9yAi36MEuk4VxG8Jc3PQQfSFm4RWazv1k3E0AAIob2Ek
DLVjvLO62Navo/OQ6D7yyiX0qes5S7/k3F1h8+87eRn3yxZE2kbxPg8KuQENBEVZ
zYYBCACoYgExmMKEtABL3pir/IXI4exR/45hkP6txFIrkVQb8DGJ9H39kiDr4gtj
F+pvcgMpec35S3m4fJ7WhDNvbDB4ZvONc1NMKs9cqDXfB+TLWPm4W+SkcKUrs+nK
i8l7ieggTALJcvRoLTX2EFmUFrD6y870W3rK2SfC/0VJX8Ou5cPbwCeueExjo5x0
3gNfu0jWUS0cyA9y+1rVVekrLuJY/+SI4jv3gdzrYbxD0f6dpbpC37QHoJdd0KGF
acPtT2azjY+HxW10EA3Aw9oZWFXnb1nFg2RbDpkaGLmLbaXweltLyw154UmCXxym
PXPqi9bSfEkj0GiYrapk4mW114u9ABEBAAGJA0QEGAECAA8FAkVZzYcCGwIFCQHh
M4ABKQkQSmCEucDXH0rAXSAEGQECAAYFAkVZzYcACgkQ017duBDeLmmu3wf/TFZM
tLKxiyQPtGSTE3eULPdWCEMDZXdSPTY0QHM7Zvh+qn1ei+iFpD0549MYnBEAwDIV
4o62Nrcg8IPu0CEkZIAn2JiFFGYvMGk91awZGV1GS3umd7Dt349E1oKDPZVzRn+j
QIKarXxxabRmx2s/dZZgSs/eguWTboBFmvls9tVfe8x/xPvcHFmqHVUoGKEJy6Tm
no+s4yNjpc5wAaRml+GYf1tK9WMFuZn79qKxkYv4WI96dXR0FL59YbFRkkaI+1/b
G31MvWTqVjY1nJGslByFPUUB8Ca1djtp1gx6NXnOYr3V5MEDfdbjjPu79No+/y6M
tIua5yNtSRlk2nKhIqo3D/sGQ/uHijiMRAtoLhiyqYMc9W9vx/KOoCUHoMJqE39a
Eputvgwwo0rwgSmNfB1dzneFojBdJ47WBSHC8NKtkpJj6mzvvlaI9jmEpK54x3nl
OmBj3X/xaepoRGAtrmgTBP4A9hSjrTMGu/tUQjlX+Xcr6n3g7GSVe5FpUyIMPXEU
+JZDTiEUyn1OdzfNGmnWP+KJX5pQVq4czf5XK6otLZJELDVw/Hbjnjmdz5WOKgEH
jSof3WPeMBgPAcd/cMAZeiGtWM1UpJBHqEXTkthmrpmtRftJKDbooNM9d5OwKiT+
I3vNBv/plMSr8NDjhTWC+ihrN6RBj1vaqpDgGpucPhoO2hwNqWuI4q5WUKtCyw6J
An7ErNaH4c0nVaZq6kJ8Vxdt+LpKYmOsJ8y9xtl6StcrkKNn+6ZfCfee7DEo2bvb
scfpqJqqOqb5KOagTpYs8mo6yQ3leRvFtoeBOQHVQzct23EwOMxbDyeunT50a1eH
MZTEWuIiuCUudM81QXU46oIcaAtj8tpG0Tmnku9g27EjwxUt+8kVmhlPHMb2TdoF
k5d0ce+JuxIG5+i+t8sUCorMc8zfp4g1bxZeMOcPnfyO3bSW11EVcN7ZxHlFC+XE
YOByP50CM3P8lItPlQ+WpY9kYWjiwu9kVPaGQ16G47nspngJInU5dhka3KJGtIZe
q7kBDQRFWc3GAQgAz/JUs24niKsd0ZtOjUWd4R4y0gjS0kC/vvLL2gbXYkA9tcjG
5iEvVWJY34QsudX0v1ULsVnJ89X/gsk8hAhAia1TQm+0Qq+MSxEaQkMSaOO8N70U
XzgH1dielvpea20WO4MyWQuRIJ0K2nsGmEPnt6ZP7fK8HVHFNggP/mQ6LMu1reAF
gvb8cEtjb9B5QaCUEoLjsbsuo+vLW7AWy4GfIRNESHw2Qt08AUaGrihpu6zi7N2b
QkHHJtqa63GzYJ+kYzAVvrFJXdwL/TRXLBzv+6yyvYSIHi8uB6/o6CZN6hpjfpME
ph+oYPqXeNOyMd1E9Kg8ymcPrNyQKfE3WnCRXQARAQABiQIlBBgBAgAPBQJFWc3H
AhsMBQkB4TOAAAoJEEpghLnA1x9KXYMP/3D9JYti6C8DWuX2hWv+2SUbLcMa5u1e
ETewIo5S3mqGWSaxX4YLPVRkZ1lOLmFysOLimf0thYm7IsatLcWmBdYUpK92ilvr
Sk2sKlhrOoBXEX/79Kz+Aj5PjeyiQxgQ7Ba/afwhU6aTqs2Dp1T0YNu2eBvV+1QH
lZnW2Wh96zzwc0dJUuY9eBk5Fgpu08Wce7o6jxFPtVyAaQa0zcNAmw2TSY7wbunJ
WTl9OgATAyqVCuhWW7AnPcSqkH8lQigSc00wfqJKOD2Us0FqN6UKDCZTyQkdP6hx
G+3aUkkvGSOxy7u9bVWmrikuJMoiIY/CH/m+GcJJATVibI7t5MhhtBGySKc3PAwc
58sVe9AnbDvs84efrNP59j2KG2KKqcqjTGAmKyJnG3N50xJGakDIsqfneIRNWpEE
pOOPaOqR4qnPAS9OSt9A3hqBpWPjQcScd6AuO+J2PE5y23pTnb9PtLBQb5e4VFiv
N54u8j4bU2CO0SC2isZ3CR68dPHthWsxt4XbjhgktjbpQRQ8L2EDBQ8oE13GOrOw
P8x4Q0eC5uzkXNyRqzKOsxlZEuc+75aDDd3M2GDw08FG7GI1p/L+NgenwT+9TmFX
2hOKVrjgyx+fPut1t5DJJubDWXGOK33qvrL7HTCEv1zz7LNbbPwwNHK4lfMAWuJW
D9wc3Y9Se/P/
=5MAs
-----END PGP PUBLIC KEY BLOCK-----

2
debian/watch vendored
View file

@ -1,2 +0,0 @@
version=3
opts=pgpsigurlmangle=s/$/.sig/ http://www.tinc-vpn.org/packages/tinc-(1\.0\.\d+)\.tar\.gz

View file

@ -3,20 +3,23 @@
info_TEXINFOS = tinc.texi info_TEXINFOS = tinc.texi
tinc_TEXINFOS = tincinclude.texi tinc_TEXINFOS = tincinclude.texi
man_MANS = tincd.8 tinc.conf.5 man_MANS = tincd.8 tinc.8 tinc.conf.5 tinc-gui.8
EXTRA_DIST = tincinclude.texi.in tincd.8.in tinc.conf.5.in sample-config EXTRA_DIST = tincinclude.texi.in tincd.8.in tinc.8.in tinc.conf.5.in tinc-gui.8.in sample-config
CLEANFILES = *.html tincd.8 tinc.conf.5 tincinclude.texi CLEANFILES = *.html tincd.8 tinc.8 tinc.conf.5 tinc-gui.8 tincinclude.texi
texi2html: tinc.texi
$(AM_V_GEN)texi2html -split=chapter $<
tincd.8.html: tincd.8 tincd.8.html: tincd.8
$(AM_V_GEN)w3mman2html $< > $@ $(AM_V_GEN)w3mman2html $? > $@
tinc.8.html: tinc.8
$(AM_V_GEN)w3mman2html $? > $@
tinc-gui.8.html: tinc-gui.8
$(AM_V_GEN)w3mman2html $? > $@
tinc.conf.5.html: tinc.conf.5 tinc.conf.5.html: tinc.conf.5
$(AM_V_GEN)w3mman2html $< > $@ $(AM_V_GEN)w3mman2html $? > $@
substitute = sed \ substitute = sed \
-e s,'@PACKAGE\@',"$(PACKAGE)",g \ -e s,'@PACKAGE\@',"$(PACKAGE)",g \
@ -28,6 +31,12 @@ substitute = sed \
tincd.8: $(srcdir)/tincd.8.in tincd.8: $(srcdir)/tincd.8.in
$(AM_V_GEN)$(substitute) $(srcdir)/tincd.8.in > $@ $(AM_V_GEN)$(substitute) $(srcdir)/tincd.8.in > $@
tinc.8: $(srcdir)/tinc.8.in
$(AM_V_GEN)$(substitute) $(srcdir)/tinc.8.in > $@
tinc-gui.8: $(srcdir)/tinc-gui.8.in
$(AM_V_GEN)$(substitute) $(srcdir)/tinc-gui.8.in > $@
tinc.conf.5: $(srcdir)/tinc.conf.5.in tinc.conf.5: $(srcdir)/tinc.conf.5.in
$(AM_V_GEN)$(substitute) $(srcdir)/tinc.conf.5.in > $@ $(AM_V_GEN)$(substitute) $(srcdir)/tinc.conf.5.in > $@

View file

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.16.2 from Makefile.am. # Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc. # Copyright (C) 1994-2020 Free Software Foundation, Inc.
@ -94,9 +94,12 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/ax_cflags_warn_all.m4 \ $(top_srcdir)/m4/ax_cflags_warn_all.m4 \
$(top_srcdir)/m4/ax_check_compile_flag.m4 \ $(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_check_link_flag.m4 \ $(top_srcdir)/m4/ax_check_link_flag.m4 \
$(top_srcdir)/m4/ax_require_defined.m4 $(top_srcdir)/m4/lzo.m4 \ $(top_srcdir)/m4/ax_code_coverage.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/zlib.m4 \ $(top_srcdir)/m4/ax_require_defined.m4 \
$(top_srcdir)/configure.ac $(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/libgcrypt.m4 \
$(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) \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4) $(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
@ -209,8 +212,15 @@ AWK = @AWK@
CC = @CC@ CC = @CC@
CCDEPMODE = @CCDEPMODE@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@ CFLAGS = @CFLAGS@
CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@
CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@
CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
CODE_COVERAGE_LIBS = @CODE_COVERAGE_LIBS@
CPP = @CPP@ CPP = @CPP@
CPPFLAGS = @CPPFLAGS@ CPPFLAGS = @CPPFLAGS@
CURSES_LIBS = @CURSES_LIBS@
CYGPATH_W = @CYGPATH_W@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@ DEFS = @DEFS@
DEPDIR = @DEPDIR@ DEPDIR = @DEPDIR@
@ -219,17 +229,21 @@ ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@ ECHO_T = @ECHO_T@
EGREP = @EGREP@ EGREP = @EGREP@
EXEEXT = @EXEEXT@ EXEEXT = @EXEEXT@
GCOV = @GCOV@
GENHTML = @GENHTML@
GREP = @GREP@ GREP = @GREP@
INSTALL = @INSTALL@ INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@ INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LCOV = @LCOV@
LDFLAGS = @LDFLAGS@ LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@ LIBOBJS = @LIBOBJS@
LIBS = @LIBS@ LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@ LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@ MAKEINFO = @MAKEINFO@
MINIUPNPC_LIBS = @MINIUPNPC_LIBS@
MKDIR_P = @MKDIR_P@ MKDIR_P = @MKDIR_P@
OBJEXT = @OBJEXT@ OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@ PACKAGE = @PACKAGE@
@ -240,6 +254,8 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@ PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@ PATH_SEPARATOR = @PATH_SEPARATOR@
READLINE_LIBS = @READLINE_LIBS@
SED = @SED@
SET_MAKE = @SET_MAKE@ SET_MAKE = @SET_MAKE@
SHELL = @SHELL@ SHELL = @SHELL@
STRIP = @STRIP@ STRIP = @STRIP@
@ -298,9 +314,9 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@ top_srcdir = @top_srcdir@
info_TEXINFOS = tinc.texi info_TEXINFOS = tinc.texi
tinc_TEXINFOS = tincinclude.texi tinc_TEXINFOS = tincinclude.texi
man_MANS = tincd.8 tinc.conf.5 man_MANS = tincd.8 tinc.8 tinc.conf.5 tinc-gui.8
EXTRA_DIST = tincinclude.texi.in tincd.8.in tinc.conf.5.in sample-config EXTRA_DIST = tincinclude.texi.in tincd.8.in tinc.8.in tinc.conf.5.in tinc-gui.8.in sample-config
CLEANFILES = *.html tincd.8 tinc.conf.5 tincinclude.texi CLEANFILES = *.html tincd.8 tinc.8 tinc.conf.5 tinc-gui.8 tincinclude.texi
substitute = sed \ substitute = sed \
-e s,'@PACKAGE\@',"$(PACKAGE)",g \ -e s,'@PACKAGE\@',"$(PACKAGE)",g \
-e s,'@VERSION\@',"$(VERSION)",g \ -e s,'@VERSION\@',"$(VERSION)",g \
@ -830,18 +846,27 @@ uninstall-man: uninstall-man5 uninstall-man8
.PRECIOUS: Makefile .PRECIOUS: Makefile
texi2html: tinc.texi
$(AM_V_GEN)texi2html -split=chapter $<
tincd.8.html: tincd.8 tincd.8.html: tincd.8
$(AM_V_GEN)w3mman2html $< > $@ $(AM_V_GEN)w3mman2html $? > $@
tinc.8.html: tinc.8
$(AM_V_GEN)w3mman2html $? > $@
tinc-gui.8.html: tinc-gui.8
$(AM_V_GEN)w3mman2html $? > $@
tinc.conf.5.html: tinc.conf.5 tinc.conf.5.html: tinc.conf.5
$(AM_V_GEN)w3mman2html $< > $@ $(AM_V_GEN)w3mman2html $? > $@
tincd.8: $(srcdir)/tincd.8.in tincd.8: $(srcdir)/tincd.8.in
$(AM_V_GEN)$(substitute) $(srcdir)/tincd.8.in > $@ $(AM_V_GEN)$(substitute) $(srcdir)/tincd.8.in > $@
tinc.8: $(srcdir)/tinc.8.in
$(AM_V_GEN)$(substitute) $(srcdir)/tinc.8.in > $@
tinc-gui.8: $(srcdir)/tinc-gui.8.in
$(AM_V_GEN)$(substitute) $(srcdir)/tinc-gui.8.in > $@
tinc.conf.5: $(srcdir)/tinc.conf.5.in tinc.conf.5: $(srcdir)/tinc.conf.5.in
$(AM_V_GEN)$(substitute) $(srcdir)/tinc.conf.5.in > $@ $(AM_V_GEN)$(substitute) $(srcdir)/tinc.conf.5.in > $@

View file

@ -16,7 +16,7 @@ Name = alpha
ConnectTo = beta ConnectTo = beta
# The tap device tinc will use. # The tap device tinc will use.
# /dev/tap0 for ethertap, FreeBSD or OpenBSD # Default is /dev/tap0 for ethertap or FreeBSD,
# /dev/tun0 for Solaris # /dev/tun0 for Solaris and OpenBSD,
# /dev/net/tun for Linux tun/tap # and /dev/net/tun for Linux tun/tap device.
Device = /dev/net/tun Device = /dev/net/tun

View file

@ -3,9 +3,9 @@
% Load plain if necessary, i.e., if running under initex. % Load plain if necessary, i.e., if running under initex.
\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
% %
\def\texinfoversion{2020-02-11.09} \def\texinfoversion{2020-10-24.12}
% %
% Copyright 1985, 1986, 1988, 1990-2019 Free Software Foundation, Inc. % Copyright 1985, 1986, 1988, 1990-2020 Free Software Foundation, Inc.
% %
% This texinfo.tex file is free software: you can redistribute it and/or % This texinfo.tex file is free software: you can redistribute it and/or
% modify it under the terms of the GNU General Public License as % modify it under the terms of the GNU General Public License as
@ -33,7 +33,7 @@
% The texinfo.tex in any given distribution could well be out % The texinfo.tex in any given distribution could well be out
% of date, so if that's what you're using, please check. % of date, so if that's what you're using, please check.
% %
% Send bug reports to bug-texinfo@gnu.org. Please include including a % Send bug reports to bug-texinfo@gnu.org. Please include a
% complete document in each bug report with which we can reproduce the % complete document in each bug report with which we can reproduce the
% problem. Patches are, of course, greatly appreciated. % problem. Patches are, of course, greatly appreciated.
% %
@ -349,34 +349,19 @@
\ifodd\pageno \advance\hoffset by \bindingoffset \ifodd\pageno \advance\hoffset by \bindingoffset
\else \advance\hoffset by -\bindingoffset\fi \else \advance\hoffset by -\bindingoffset\fi
% %
\checkchapterpage
%
% Retrieve the information for the headings from the marks in the page, % Retrieve the information for the headings from the marks in the page,
% and call Plain TeX's \makeheadline and \makefootline, which use the % and call Plain TeX's \makeheadline and \makefootline, which use the
% values in \headline and \footline. % values in \headline and \footline.
% %
% This is used to check if we are on the first page of a chapter.
\ifcase1\the\savedtopmark\fi
\let\prevchaptername\thischaptername
\ifcase0\firstmark\fi
\let\curchaptername\thischaptername
%
\ifodd\pageno \getoddheadingmarks \else \getevenheadingmarks \fi
%
\ifx\curchaptername\prevchaptername
\let\thischapterheading\thischapter
\else
% \thischapterheading is the same as \thischapter except it is blank
% for the first page of a chapter. This is to prevent the chapter name
% being shown twice.
\def\thischapterheading{}%
\fi
%
% Common context changes for both heading and footing. % Common context changes for both heading and footing.
% Do this outside of the \shipout so @code etc. will be expanded in % Do this outside of the \shipout so @code etc. will be expanded in
% the headline as they should be, not taken literally (outputting ''code). % the headline as they should be, not taken literally (outputting ''code).
\def\commonheadfootline{\let\hsize=\txipagewidth \texinfochars} \def\commonheadfootline{\let\hsize=\txipagewidth \texinfochars}
% %
\ifodd\pageno \getoddheadingmarks \else \getevenheadingmarks \fi
\global\setbox\headlinebox = \vbox{\commonheadfootline \makeheadline}% \global\setbox\headlinebox = \vbox{\commonheadfootline \makeheadline}%
%
\ifodd\pageno \getoddfootingmarks \else \getevenfootingmarks \fi \ifodd\pageno \getoddfootingmarks \else \getevenfootingmarks \fi
\global\setbox\footlinebox = \vbox{\commonheadfootline \makefootline}% \global\setbox\footlinebox = \vbox{\commonheadfootline \makefootline}%
% %
@ -423,6 +408,22 @@
\ifr@ggedbottom \kern-\dimen@ \vfil \fi} \ifr@ggedbottom \kern-\dimen@ \vfil \fi}
} }
% Check if we are on the first page of a chapter. Used for printing headings.
\newif\ifchapterpage
\def\checkchapterpage{%
% Get the chapter that was current at the end of the last page
\ifcase1\the\savedtopmark\fi
\let\prevchaptername\thischaptername
%
\ifodd\pageno \getoddheadingmarks \else \getevenheadingmarks \fi
\let\curchaptername\thischaptername
%
\ifx\curchaptername\prevchaptername
\chapterpagefalse
\else
\chapterpagetrue
\fi
}
% Argument parsing % Argument parsing
@ -1010,7 +1011,7 @@ where each line of input produces a line of output.}
\let\setfilename=\comment \let\setfilename=\comment
% @bye. % @bye.
\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} \outer\def\bye{\chappager\pagelabels\tracingstats=1\ptexend}
\message{pdf,} \message{pdf,}
@ -1137,6 +1138,45 @@ where each line of input produces a line of output.}
\fi \fi
% Output page labels information.
% See PDF reference v.1.7 p.594, section 8.3.1.
\ifpdf
\def\pagelabels{%
\def\title{0 << /P (T-) /S /D >>}%
\edef\roman{\the\romancount << /S /r >>}%
\edef\arabic{\the\arabiccount << /S /D >>}%
%
% Page label ranges must be increasing. Remove any duplicates.
% (There is a slight chance of this being wrong if e.g. there is
% a @contents but no @titlepage, etc.)
%
\ifnum\romancount=0 \def\roman{}\fi
\ifnum\arabiccount=0 \def\title{}%
\else
\ifnum\romancount=\arabiccount \def\roman{}\fi
\fi
%
\ifnum\romancount<\arabiccount
\pdfcatalog{/PageLabels << /Nums [\title \roman \arabic ] >> }\relax
\else
\pdfcatalog{/PageLabels << /Nums [\title \arabic \roman ] >> }\relax
\fi
}
\else
\let\pagelabels\relax
\fi
\newcount\pagecount \pagecount=0
\newcount\romancount \romancount=0
\newcount\arabiccount \arabiccount=0
\ifpdf
\let\ptxadvancepageno\advancepageno
\def\advancepageno{%
\ptxadvancepageno\global\advance\pagecount by 1
}
\fi
% PDF uses PostScript string constants for the names of xref targets, % PDF uses PostScript string constants for the names of xref targets,
% for display in the outlines, and in other places. Thus, we have to % for display in the outlines, and in other places. Thus, we have to
% double any backslashes. Otherwise, a name like "\node" will be % double any backslashes. Otherwise, a name like "\node" will be
@ -1427,7 +1467,13 @@ output) for that.)}
% subentries, which we calculated on our first read of the .toc above. % subentries, which we calculated on our first read of the .toc above.
% %
% We use the node names as the destinations. % We use the node names as the destinations.
%
% Currently we prefix the section name with the section number
% for chapter and appendix headings only in order to avoid too much
% horizontal space being required in the PDF viewer.
\def\numchapentry##1##2##3##4{% \def\numchapentry##1##2##3##4{%
\dopdfoutline{##2 ##1}{count-\expnumber{chap##2}}{##3}{##4}}%
\def\unnchapentry##1##2##3##4{%
\dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}% \dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}%
\def\numsecentry##1##2##3##4{% \def\numsecentry##1##2##3##4{%
\dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}% \dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}%
@ -1669,9 +1715,13 @@ output) for that.)}
% Therefore, we read toc only once. % Therefore, we read toc only once.
% %
% We use node names as destinations. % We use node names as destinations.
%
% Currently we prefix the section name with the section number
% for chapter and appendix headings only in order to avoid too much
% horizontal space being required in the PDF viewer.
\def\partentry##1##2##3##4{}% ignore parts in the outlines \def\partentry##1##2##3##4{}% ignore parts in the outlines
\def\numchapentry##1##2##3##4{% \def\numchapentry##1##2##3##4{%
\dopdfoutline{##1}{1}{##3}{##4}}% \dopdfoutline{##2 ##1}{1}{##3}{##4}}%
\def\numsecentry##1##2##3##4{% \def\numsecentry##1##2##3##4{%
\dopdfoutline{##1}{2}{##3}{##4}}% \dopdfoutline{##1}{2}{##3}{##4}}%
\def\numsubsecentry##1##2##3##4{% \def\numsubsecentry##1##2##3##4{%
@ -1683,7 +1733,8 @@ output) for that.)}
\let\appsecentry\numsecentry% \let\appsecentry\numsecentry%
\let\appsubsecentry\numsubsecentry% \let\appsubsecentry\numsubsecentry%
\let\appsubsubsecentry\numsubsubsecentry% \let\appsubsubsecentry\numsubsubsecentry%
\let\unnchapentry\numchapentry% \def\unnchapentry##1##2##3##4{%
\dopdfoutline{##1}{1}{##3}{##4}}%
\let\unnsecentry\numsecentry% \let\unnsecentry\numsecentry%
\let\unnsubsecentry\numsubsecentry% \let\unnsubsecentry\numsubsecentry%
\let\unnsubsubsecentry\numsubsubsecentry% \let\unnsubsubsecentry\numsubsubsecentry%
@ -2496,7 +2547,7 @@ end
\def\it{\fam=\itfam \setfontstyle{it}} \def\it{\fam=\itfam \setfontstyle{it}}
\def\sl{\fam=\slfam \setfontstyle{sl}} \def\sl{\fam=\slfam \setfontstyle{sl}}
\def\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf} \def\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf}
\def\tt{\fam=\ttfam \setfontstyle{tt}} \def\tt{\fam=\ttfam \setfontstyle{tt}}\def\ttstylename{tt}
% Texinfo sort of supports the sans serif font style, which plain TeX does not. % Texinfo sort of supports the sans serif font style, which plain TeX does not.
% So we set up a \sf. % So we set up a \sf.
@ -2987,10 +3038,18 @@ end
% arg (if given), and not the url (which is then just the link target). % arg (if given), and not the url (which is then just the link target).
\newif\ifurefurlonlylink \newif\ifurefurlonlylink
% The default \pretolerance setting stops the penalty inserted in
% \urefallowbreak being a discouragement to line breaking. Set it to
% a negative value for this paragraph only. Hopefully this does not
% conflict with redefinitions of \par done elsewhere.
\def\nopretolerance{%
\pretolerance=-1
\def\par{\endgraf\pretolerance=100 \let\par\endgraf}%
}
% The main macro is \urefbreak, which allows breaking at expected % The main macro is \urefbreak, which allows breaking at expected
% places within the url. (There used to be another version, which % places within the url.
% didn't support automatic breaking.) \def\urefbreak{\nopretolerance \begingroup \urefcatcodes \dourefbreak}
\def\urefbreak{\begingroup \urefcatcodes \dourefbreak}
\let\uref=\urefbreak \let\uref=\urefbreak
% %
\def\dourefbreak#1{\urefbreakfinish #1,,,\finish} \def\dourefbreak#1{\urefbreakfinish #1,,,\finish}
@ -3101,14 +3160,14 @@ end
% Allow a ragged right output to aid breaking long URL's. There can % Allow a ragged right output to aid breaking long URL's. There can
% be a break at the \allowbreak with no extra glue (if the existing stretch in % be a break at the \allowbreak with no extra glue (if the existing stretch in
% the line is sufficent), a break at the \penalty100 with extra glue added % the line is sufficient), a break at the \penalty with extra glue added
% at the end of the line, or no break at all here. % at the end of the line, or no break at all here.
% Changing the value of the penalty and/or the amount of stretch affects how % Changing the value of the penalty and/or the amount of stretch affects how
% preferrable one choice is over the other. % preferable one choice is over the other.
\def\urefallowbreak{% \def\urefallowbreak{%
\allowbreak \penalty0\relax
\hskip 0pt plus 2 em\relax \hskip 0pt plus 2 em\relax
\penalty300 \penalty1000\relax
\hskip 0pt plus -2 em\relax \hskip 0pt plus -2 em\relax
} }
@ -3305,6 +3364,25 @@ end
\def\sup{\ifmmode \expandafter\ptexsp \else \expandafter\finishsup\fi} \def\sup{\ifmmode \expandafter\ptexsp \else \expandafter\finishsup\fi}
\def\finishsup#1{$\ptexsp{\hbox{\switchtolllsize #1}}$}% \def\finishsup#1{$\ptexsp{\hbox{\switchtolllsize #1}}$}%
% provide this command from LaTeX as it is very common
\def\frac#1#2{{{#1}\over{#2}}}
% @displaymath.
% \globaldefs is needed to recognize the end lines in \tex and
% \end tex. Set \thisenv as @end displaymath is seen before @end tex.
{\obeylines
\globaldefs=1
\envdef\displaymath{%
\tex
\def\thisenv{\displaymath}%
$$%
}
\def\Edisplaymath{$$
\def\thisenv{\tex}%
\end tex
}}
% @inlinefmt{FMTNAME,PROCESSED-TEXT} and @inlineraw{FMTNAME,RAW-TEXT}. % @inlinefmt{FMTNAME,PROCESSED-TEXT} and @inlineraw{FMTNAME,RAW-TEXT}.
% Ignore unless FMTNAME == tex; then it is like @iftex and @tex, % Ignore unless FMTNAME == tex; then it is like @iftex and @tex,
% except specified as a normal braced arg, so no newlines to worry about. % except specified as a normal braced arg, so no newlines to worry about.
@ -3509,7 +3587,7 @@ end
% @pounds{} is a sterling sign, which Knuth put in the CM italic font. % @pounds{} is a sterling sign, which Knuth put in the CM italic font.
% %
\def\pounds{{\it\$}} \def\pounds{\ifmonospace{\ecfont\char"BF}\else{\it\$}\fi}
% @euro{} comes from a separate font, depending on the current style. % @euro{} comes from a separate font, depending on the current style.
% We use the free feym* fonts from the eurosym package by Henrik % We use the free feym* fonts from the eurosym package by Henrik
@ -3658,11 +3736,19 @@ end
\fi \fi
% Quotes. % Quotes.
\chardef\quotedblleft="5C
\chardef\quotedblright=`\"
\chardef\quoteleft=`\` \chardef\quoteleft=`\`
\chardef\quoteright=`\' \chardef\quoteright=`\'
% only change font for tt for correct kerning and to avoid using
% \ecfont unless necessary.
\def\quotedblleft{%
\ifmonospace{\ecfont\char"10}\else{\char"5C}\fi
}
\def\quotedblright{%
\ifmonospace{\ecfont\char"11}\else{\char`\"}\fi
}
\message{page headings,} \message{page headings,}
@ -3784,12 +3870,19 @@ end
\newtoks\evenheadline % headline on even pages \newtoks\evenheadline % headline on even pages
\newtoks\oddheadline % headline on odd pages \newtoks\oddheadline % headline on odd pages
\newtoks\evenchapheadline% headline on even pages with a new chapter
\newtoks\oddchapheadline % headline on odd pages with a new chapter
\newtoks\evenfootline % footline on even pages \newtoks\evenfootline % footline on even pages
\newtoks\oddfootline % footline on odd pages \newtoks\oddfootline % footline on odd pages
% Now make \makeheadline and \makefootline in Plain TeX use those variables % Now make \makeheadline and \makefootline in Plain TeX use those variables
\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline \headline={{\textfonts\rm
\else \the\evenheadline \fi}} \ifchapterpage
\ifodd\pageno\the\oddchapheadline\else\the\evenchapheadline\fi
\else
\ifodd\pageno\the\oddheadline\else\the\evenheadline\fi
\fi}}
\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline \footline={{\textfonts\rm \ifodd\pageno \the\oddfootline
\else \the\evenfootline \fi}\HEADINGShook} \else \the\evenfootline \fi}\HEADINGShook}
\let\HEADINGShook=\relax \let\HEADINGShook=\relax
@ -3805,12 +3898,14 @@ end
\def\evenheading{\parsearg\evenheadingxxx} \def\evenheading{\parsearg\evenheadingxxx}
\def\evenheadingxxx #1{\evenheadingyyy #1\|\|\|\|\finish} \def\evenheadingxxx #1{\evenheadingyyy #1\|\|\|\|\finish}
\def\evenheadingyyy #1\|#2\|#3\|#4\finish{% \def\evenheadingyyy #1\|#2\|#3\|#4\finish{%
\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} \global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
\global\evenchapheadline=\evenheadline}
\def\oddheading{\parsearg\oddheadingxxx} \def\oddheading{\parsearg\oddheadingxxx}
\def\oddheadingxxx #1{\oddheadingyyy #1\|\|\|\|\finish} \def\oddheadingxxx #1{\oddheadingyyy #1\|\|\|\|\finish}
\def\oddheadingyyy #1\|#2\|#3\|#4\finish{% \def\oddheadingyyy #1\|#2\|#3\|#4\finish{%
\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} \global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}%
\global\oddchapheadline=\oddheadline}
\parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}% \parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}%
@ -3877,37 +3972,34 @@ end
\parseargdef\headings{\csname HEADINGS#1\endcsname} \parseargdef\headings{\csname HEADINGS#1\endcsname}
\def\headingsoff{% non-global headings elimination \def\headingsoff{% non-global headings elimination
\evenheadline={\hfil}\evenfootline={\hfil}% \evenheadline={\hfil}\evenfootline={\hfil}\evenchapheadline={\hfil}%
\oddheadline={\hfil}\oddfootline={\hfil}% \oddheadline={\hfil}\oddfootline={\hfil}\oddchapheadline={\hfil}%
} }
\def\HEADINGSoff{{\globaldefs=1 \headingsoff}} % global setting \def\HEADINGSoff{{\globaldefs=1 \headingsoff}} % global setting
\HEADINGSoff % it's the default \HEADINGSoff % it's the default
% When we turn headings on, set the page number to 1. % When we turn headings on, set the page number to 1.
\def\pageone{
\global\pageno=1
\global\arabiccount = \pagecount
}
% For double-sided printing, put current file name in lower left corner, % For double-sided printing, put current file name in lower left corner,
% chapter name on inside top of right hand pages, document % chapter name on inside top of right hand pages, document
% title on inside top of left hand pages, and page numbers on outside top % title on inside top of left hand pages, and page numbers on outside top
% edge of all pages. % edge of all pages.
\def\HEADINGSdouble{% \def\HEADINGSdouble{%
\global\pageno=1 \pageone
\global\evenfootline={\hfil} \HEADINGSdoublex
\global\oddfootline={\hfil}
\global\evenheadline={\line{\folio\hfil\thistitle}}
\global\oddheadline={\line{\thischapterheading\hfil\folio}}
\global\let\contentsalignmacro = \chapoddpage
} }
\let\contentsalignmacro = \chappager \let\contentsalignmacro = \chappager
% For single-sided printing, chapter title goes across top left of page, % For single-sided printing, chapter title goes across top left of page,
% page number on top right. % page number on top right.
\def\HEADINGSsingle{% \def\HEADINGSsingle{%
\global\pageno=1 \pageone
\global\evenfootline={\hfil} \HEADINGSsinglex
\global\oddfootline={\hfil}
\global\evenheadline={\line{\thischapterheading\hfil\folio}}
\global\oddheadline={\line{\thischapterheading\hfil\folio}}
\global\let\contentsalignmacro = \chappager
} }
\def\HEADINGSon{\HEADINGSdouble} \def\HEADINGSon{\HEADINGSdouble}
@ -3917,7 +4009,9 @@ end
\global\evenfootline={\hfil} \global\evenfootline={\hfil}
\global\oddfootline={\hfil} \global\oddfootline={\hfil}
\global\evenheadline={\line{\folio\hfil\thistitle}} \global\evenheadline={\line{\folio\hfil\thistitle}}
\global\oddheadline={\line{\thischapterheading\hfil\folio}} \global\oddheadline={\line{\thischapter\hfil\folio}}
\global\evenchapheadline={\line{\folio\hfil}}
\global\oddchapheadline={\line{\hfil\folio}}
\global\let\contentsalignmacro = \chapoddpage \global\let\contentsalignmacro = \chapoddpage
} }
@ -3925,8 +4019,22 @@ end
\def\HEADINGSsinglex{% \def\HEADINGSsinglex{%
\global\evenfootline={\hfil} \global\evenfootline={\hfil}
\global\oddfootline={\hfil} \global\oddfootline={\hfil}
\global\evenheadline={\line{\thischapterheading\hfil\folio}} \global\evenheadline={\line{\thischapter\hfil\folio}}
\global\oddheadline={\line{\thischapterheading\hfil\folio}} \global\oddheadline={\line{\thischapter\hfil\folio}}
\global\evenchapheadline={\line{\hfil\folio}}
\global\oddchapheadline={\line{\hfil\folio}}
\global\let\contentsalignmacro = \chappager
}
% for @setchapternewpage off
\def\HEADINGSsinglechapoff{%
\pageone
\global\evenfootline={\hfil}
\global\oddfootline={\hfil}
\global\evenheadline={\line{\thischapter\hfil\folio}}
\global\oddheadline={\line{\thischapter\hfil\folio}}
\global\evenchapheadline=\evenheadline
\global\oddchapheadline=\oddheadline
\global\let\contentsalignmacro = \chappager \global\let\contentsalignmacro = \chappager
} }
@ -4841,7 +4949,7 @@ end
% like the previous two, but they put @code around the argument. % like the previous two, but they put @code around the argument.
\def\docodeindex#1{\edef\indexname{#1}\parsearg\docodeindexxxx} \def\docodeindex#1{\edef\indexname{#1}\parsearg\docodeindexxxx}
\def\docodeindexxxx #1{\doind{\indexname}{\code{#1}}} \def\docodeindexxxx #1{\docind{\indexname}{#1}}
% Used for the aux, toc and index files to prevent expansion of Texinfo % Used for the aux, toc and index files to prevent expansion of Texinfo
@ -5117,64 +5225,66 @@ end
\let\lbracechar\{% \let\lbracechar\{%
\let\rbracechar\}% \let\rbracechar\}%
% %
%
\let\do\indexnofontsdef
%
% Non-English letters. % Non-English letters.
\def\AA{AA}% \do\AA{AA}%
\def\AE{AE}% \do\AE{AE}%
\def\DH{DZZ}% \do\DH{DZZ}%
\def\L{L}% \do\L{L}%
\def\OE{OE}% \do\OE{OE}%
\def\O{O}% \do\O{O}%
\def\TH{TH}% \do\TH{TH}%
\def\aa{aa}% \do\aa{aa}%
\def\ae{ae}% \do\ae{ae}%
\def\dh{dzz}% \do\dh{dzz}%
\def\exclamdown{!}% \do\exclamdown{!}%
\def\l{l}% \do\l{l}%
\def\oe{oe}% \do\oe{oe}%
\def\ordf{a}% \do\ordf{a}%
\def\ordm{o}% \do\ordm{o}%
\def\o{o}% \do\o{o}%
\def\questiondown{?}% \do\questiondown{?}%
\def\ss{ss}% \do\ss{ss}%
\def\th{th}% \do\th{th}%
% %
\def\LaTeX{LaTeX}% \do\LaTeX{LaTeX}%
\def\TeX{TeX}% \do\TeX{TeX}%
% %
% Assorted special characters. \defglyph gives the control sequence a % Assorted special characters.
% definition that removes the {} that follows its use. \do\atchar{@}%
\defglyph\atchar{@}% \do\arrow{->}%
\defglyph\arrow{->}% \do\bullet{bullet}%
\defglyph\bullet{bullet}% \do\comma{,}%
\defglyph\comma{,}% \do\copyright{copyright}%
\defglyph\copyright{copyright}% \do\dots{...}%
\defglyph\dots{...}% \do\enddots{...}%
\defglyph\enddots{...}% \do\equiv{==}%
\defglyph\equiv{==}% \do\error{error}%
\defglyph\error{error}% \do\euro{euro}%
\defglyph\euro{euro}% \do\expansion{==>}%
\defglyph\expansion{==>}% \do\geq{>=}%
\defglyph\geq{>=}% \do\guillemetleft{<<}%
\defglyph\guillemetleft{<<}% \do\guillemetright{>>}%
\defglyph\guillemetright{>>}% \do\guilsinglleft{<}%
\defglyph\guilsinglleft{<}% \do\guilsinglright{>}%
\defglyph\guilsinglright{>}% \do\leq{<=}%
\defglyph\leq{<=}% \do\lbracechar{\{}%
\defglyph\lbracechar{\{}% \do\minus{-}%
\defglyph\minus{-}% \do\point{.}%
\defglyph\point{.}% \do\pounds{pounds}%
\defglyph\pounds{pounds}% \do\print{-|}%
\defglyph\print{-|}% \do\quotedblbase{"}%
\defglyph\quotedblbase{"}% \do\quotedblleft{"}%
\defglyph\quotedblleft{"}% \do\quotedblright{"}%
\defglyph\quotedblright{"}% \do\quoteleft{`}%
\defglyph\quoteleft{`}% \do\quoteright{'}%
\defglyph\quoteright{'}% \do\quotesinglbase{,}%
\defglyph\quotesinglbase{,}% \do\rbracechar{\}}%
\defglyph\rbracechar{\}}% \do\registeredsymbol{R}%
\defglyph\registeredsymbol{R}% \do\result{=>}%
\defglyph\result{=>}% \do\textdegree{o}%
\defglyph\textdegree{o}%
% %
% We need to get rid of all macros, leaving only the arguments (if present). % We need to get rid of all macros, leaving only the arguments (if present).
% Of course this is not nearly correct, but it is the best we can do for now. % Of course this is not nearly correct, but it is the best we can do for now.
@ -5189,7 +5299,10 @@ end
\macrolist \macrolist
\let\value\indexnofontsvalue \let\value\indexnofontsvalue
} }
\def\defglyph#1#2{\def#1##1{#2}} % see above
% Give the control sequence a definition that removes the {} that follows
% its use, e.g. @AA{} -> AA
\def\indexnofontsdef#1#2{\def#1##1{#2}}%
@ -5208,6 +5321,20 @@ end
\fi \fi
} }
% Same as \doind, but for code indices
\def\docind#1#2{%
\iflinks
{%
%
\requireopenindexfile{#1}%
\edef\writeto{\csname#1indfile\endcsname}%
%
\def\indextext{#2}%
\safewhatsit\docindwrite
}%
\fi
}
% Check if an index file has been opened, and if not, open it. % Check if an index file has been opened, and if not, open it.
\def\requireopenindexfile#1{% \def\requireopenindexfile#1{%
\ifnum\csname #1indfile\endcsname=0 \ifnum\csname #1indfile\endcsname=0
@ -5274,6 +5401,9 @@ end
% trim spaces. % trim spaces.
\edef\trimmed{\segment}% \edef\trimmed{\segment}%
\edef\trimmed{\expandafter\eatspaces\expandafter{\trimmed}}% \edef\trimmed{\expandafter\eatspaces\expandafter{\trimmed}}%
\ifincodeindex
\edef\trimmed{\noexpand\code{\trimmed}}%
\fi
% %
\xdef\bracedtext{\bracedtext{\trimmed}}% \xdef\bracedtext{\bracedtext{\trimmed}}%
% %
@ -5339,7 +5469,12 @@ end
% Write the entry in \indextext to the index file. % Write the entry in \indextext to the index file.
% %
\def\doindwrite{%
\newif\ifincodeindex
\def\doindwrite{\incodeindexfalse\doindwritex}
\def\docindwrite{\incodeindextrue\doindwritex}
\def\doindwritex{%
\maybemarginindex \maybemarginindex
% %
\atdummies \atdummies
@ -5559,7 +5694,11 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\else \else
\begindoublecolumns \begindoublecolumns
\catcode`\\=0\relax \catcode`\\=0\relax
\catcode`\@=12\relax %
% Make @ an escape character to give macros a chance to work. This
% should work because we (hopefully) don't otherwise use @ in index files.
%\catcode`\@=12\relax
\catcode`\@=0\relax
\input \jobname.\indexname s \input \jobname.\indexname s
\enddoublecolumns \enddoublecolumns
\fi \fi
@ -6401,18 +6540,16 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\def\CHAPPAGoff{% \def\CHAPPAGoff{%
\global\let\contentsalignmacro = \chappager \global\let\contentsalignmacro = \chappager
\global\let\pchapsepmacro=\chapbreak \global\let\pchapsepmacro=\chapbreak
\global\let\pagealignmacro=\chappager} \global\def\HEADINGSon{\HEADINGSsinglechapoff}}
\def\CHAPPAGon{% \def\CHAPPAGon{%
\global\let\contentsalignmacro = \chappager \global\let\contentsalignmacro = \chappager
\global\let\pchapsepmacro=\chappager \global\let\pchapsepmacro=\chappager
\global\let\pagealignmacro=\chappager
\global\def\HEADINGSon{\HEADINGSsingle}} \global\def\HEADINGSon{\HEADINGSsingle}}
\def\CHAPPAGodd{% \def\CHAPPAGodd{%
\global\let\contentsalignmacro = \chapoddpage \global\let\contentsalignmacro = \chapoddpage
\global\let\pchapsepmacro=\chapoddpage \global\let\pchapsepmacro=\chapoddpage
\global\let\pagealignmacro=\chapoddpage
\global\def\HEADINGSon{\HEADINGSdouble}} \global\def\HEADINGSon{\HEADINGSdouble}}
\CHAPPAGon \CHAPPAGon
@ -6777,9 +6914,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% %
\def\startcontents#1{% \def\startcontents#1{%
% If @setchapternewpage on, and @headings double, the contents should % If @setchapternewpage on, and @headings double, the contents should
% start on an odd page, unlike chapters. Thus, we maintain % start on an odd page, unlike chapters.
% \contentsalignmacro in parallel with \pagealignmacro.
% From: Torbjorn Granlund <tege@matematik.su.se>
\contentsalignmacro \contentsalignmacro
\immediate\closeout\tocfile \immediate\closeout\tocfile
% %
@ -6794,6 +6929,9 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% %
% Roman numerals for page numbers. % Roman numerals for page numbers.
\ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi
\def\thistitle{}% no title in double-sided headings
% Record where the Roman numerals started.
\ifnum\romancount=0 \global\romancount=\pagecount \fi
} }
% redefined for the two-volume lispref. We always output on % redefined for the two-volume lispref. We always output on
@ -6816,8 +6954,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\fi \fi
\closein 1 \closein 1
\endgroup \endgroup
\lastnegativepageno = \pageno \contentsendroman
\global\pageno = \savepageno
} }
% And just the chapters. % And just the chapters.
@ -6852,11 +6989,21 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\vfill \eject \vfill \eject
\contentsalignmacro % in case @setchapternewpage odd is in effect \contentsalignmacro % in case @setchapternewpage odd is in effect
\endgroup \endgroup
\lastnegativepageno = \pageno \contentsendroman
\global\pageno = \savepageno
} }
\let\shortcontents = \summarycontents \let\shortcontents = \summarycontents
% Get ready to use Arabic numerals again
\def\contentsendroman{%
\lastnegativepageno = \pageno
\global\pageno = \savepageno
%
% If \romancount > \arabiccount, the contents are at the end of the
% document. Otherwise, advance where the Arabic numerals start for
% the page numbers.
\ifnum\romancount>\arabiccount\else\global\arabiccount=\pagecount\fi
}
% Typeset the label for a chapter or appendix for the short contents. % Typeset the label for a chapter or appendix for the short contents.
% The arg is, e.g., `A' for an appendix, or `3' for a chapter. % The arg is, e.g., `A' for an appendix, or `3' for a chapter.
% %
@ -7444,13 +7591,9 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount \newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount
% %
% We typeset each line of the verbatim in an \hbox, so we can handle % We typeset each line of the verbatim in an \hbox, so we can handle
% tabs. The \global is in case the verbatim line starts with an accent, % tabs.
% or some other command that starts with a begin-group. Otherwise, the
% entire \verbbox would disappear at the corresponding end-group, before
% it is typeset. Meanwhile, we can't have nested verbatim commands
% (can we?), so the \global won't be overwriting itself.
\newbox\verbbox \newbox\verbbox
\def\starttabbox{\global\setbox\verbbox=\hbox\bgroup} \def\starttabbox{\setbox\verbbox=\hbox\bgroup}
% %
\begingroup \begingroup
\catcode`\^^I=\active \catcode`\^^I=\active
@ -7461,7 +7604,8 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\divide\dimen\verbbox by\tabw \divide\dimen\verbbox by\tabw
\multiply\dimen\verbbox by\tabw % compute previous multiple of \tabw \multiply\dimen\verbbox by\tabw % compute previous multiple of \tabw
\advance\dimen\verbbox by\tabw % advance to next multiple of \tabw \advance\dimen\verbbox by\tabw % advance to next multiple of \tabw
\wd\verbbox=\dimen\verbbox \box\verbbox \starttabbox \wd\verbbox=\dimen\verbbox
\leavevmode\box\verbbox \starttabbox
}% }%
} }
\endgroup \endgroup
@ -7471,9 +7615,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\let\nonarrowing = t% \let\nonarrowing = t%
\nonfillstart \nonfillstart
\tt % easiest (and conventionally used) font for verbatim \tt % easiest (and conventionally used) font for verbatim
% The \leavevmode here is for blank lines. Otherwise, we would \def\par{\egroup\leavevmode\box\verbbox\endgraf\starttabbox}%
% never \starttabbox and the \egroup would end verbatim mode.
\def\par{\leavevmode\egroup\box\verbbox\endgraf}%
\tabexpand \tabexpand
\setupmarkupstyle{verbatim}% \setupmarkupstyle{verbatim}%
% Respect line breaks, % Respect line breaks,
@ -7481,7 +7623,6 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% make each space count. % make each space count.
% Must do in this order: % Must do in this order:
\obeylines \uncatcodespecials \sepspaces \obeylines \uncatcodespecials \sepspaces
\everypar{\starttabbox}%
} }
% Do the @verb magic: verbatim text is quoted by unique % Do the @verb magic: verbatim text is quoted by unique
@ -7516,13 +7657,16 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% ignore everything up to the first ^^M, that's the newline at the end % ignore everything up to the first ^^M, that's the newline at the end
% of the @verbatim input line itself. Otherwise we get an extra blank % of the @verbatim input line itself. Otherwise we get an extra blank
% line in the output. % line in the output.
\xdef\doverbatim#1^^M#2@end verbatim{#2\noexpand\end\gobble verbatim}% \xdef\doverbatim#1^^M#2@end verbatim{%
\starttabbox#2\egroup\noexpand\end\gobble verbatim}%
% We really want {...\end verbatim} in the body of the macro, but % We really want {...\end verbatim} in the body of the macro, but
% without the active space; thus we have to use \xdef and \gobble. % without the active space; thus we have to use \xdef and \gobble.
% The \egroup ends the \verbbox started at the end of the last line in
% the block.
\endgroup \endgroup
% %
\envdef\verbatim{% \envdef\verbatim{%
\setupverbatim\doverbatim \setnormaldispenv\setupverbatim\doverbatim
} }
\let\Everbatim = \afterenvbreak \let\Everbatim = \afterenvbreak
@ -7540,7 +7684,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\wlog{texinfo.tex: doing @verbatiminclude of #1^^J}% \wlog{texinfo.tex: doing @verbatiminclude of #1^^J}%
\edef\tmp{\noexpand\input #1 } \edef\tmp{\noexpand\input #1 }
\expandafter \expandafter
}\tmp }\expandafter\starttabbox\tmp\egroup
\afterenvbreak \afterenvbreak
}% }%
} }
@ -10706,6 +10850,8 @@ directory should work if nowhere else does.}
\DeclareUnicodeCharacter{0233}{\=y}% \DeclareUnicodeCharacter{0233}{\=y}%
\DeclareUnicodeCharacter{0237}{\dotless{j}}% \DeclareUnicodeCharacter{0237}{\dotless{j}}%
% %
\DeclareUnicodeCharacter{02BC}{'}%
%
\DeclareUnicodeCharacter{02DB}{\ogonek{ }}% \DeclareUnicodeCharacter{02DB}{\ogonek{ }}%
% %
% Greek letters upper case % Greek letters upper case
@ -11340,6 +11486,18 @@ directory should work if nowhere else does.}
\globaldefs = 0 \globaldefs = 0
}} }}
\def\bsixpaper{{\globaldefs = 1
\afourpaper
\internalpagesizes{140mm}{100mm}%
{-6.35mm}{-12.7mm}%
{\bindingoffset}{14pt}%
{176mm}{125mm}%
\let\SETdispenvsize=\smallword
\lispnarrowing = 0.2in
\globaldefs = 0
}}
% @pagesizes TEXTHEIGHT[,TEXTWIDTH] % @pagesizes TEXTHEIGHT[,TEXTWIDTH]
% Perhaps we should allow setting the margins, \topskip, \parskip, % Perhaps we should allow setting the margins, \topskip, \parskip,
% and/or leading, also. Or perhaps we should compute them somehow. % and/or leading, also. Or perhaps we should compute them somehow.
@ -11353,12 +11511,12 @@ directory should work if nowhere else does.}
\setleading{\textleading}% \setleading{\textleading}%
% %
\dimen0 = #1\relax \dimen0 = #1\relax
\advance\dimen0 by \voffset \advance\dimen0 by 2.5in % default 1in margin above heading line
\advance\dimen0 by 1in % reference point for DVI is 1 inch from top of page % and 1.5in to include heading, footing and
% bottom margin
% %
\dimen2 = \hsize \dimen2 = \hsize
\advance\dimen2 by \normaloffset \advance\dimen2 by 2in % default to 1 inch margin on each side
\advance\dimen2 by 1in % reference point is 1 inch from left edge of page
% %
\internalpagesizes{#1}{\hsize}% \internalpagesizes{#1}{\hsize}%
{\voffset}{\normaloffset}% {\voffset}{\normaloffset}%

57
doc/tinc-gui.8.in Normal file
View file

@ -0,0 +1,57 @@
.Dd 2011-06-26
.Dt TINC-GUI 8
.\" Manual page created by:
.\" Guus Sliepen <guus@tinc-vpn.org>
.Sh NAME
.Nm tinc-gui
.Nd tinc GUI
.Sh SYNOPSIS
.Nm
.Op Fl n
.Op Fl -net Ns = Ns Ar NETNAME
.Op Fl -pidfile Ns = Ns Ar FILENAME
.Op Fl -help
.Sh DESCRIPTION
This is a Python/wxWidgets based graphical user interface for tinc, a secure virtual private network (VPN) project.
.Nm
communicates with
.Xr tincd 8
to alter and inspect the running VPN's state.
It can show the current settings, the list of connections, nodes, subnets, and edges.
For now, the debug level can be changed from the GUI, and by right-clicking on a node in the list of connections,
a pop-up menu will appear that allows one to disconnect that node.
.Sh OPTIONS
.Bl -tag -width indent
.It Fl n, -net Ns = Ns Ar NETNAME
Communicate with tincd(8) connected with
.Ar NETNAME .
.It Fl -pidfile Ns = Ns Ar FILENAME
Use the cookie from
.Ar FILENAME
to authenticate with a running tinc daemon.
If unspecified, the default is
.Pa @runstatedir@/tinc. Ns Ar NETNAME Ns Pa .pid.
.It Fl -help
Display short list of options.
.El
.Sh BUGS
The GUI is not finished yet, the final version will have much more functionality.
If you find any bugs, report them to tinc@tinc-vpn.org.
.Sh SEE ALSO
.Xr tincd 8 ,
.Pa http://www.tinc-vpn.org/ .
.Pp
The full documentation for tinc is maintained as a Texinfo manual.
If the info and tinc programs are properly installed at your site,
the command
.Ic info tinc
should give you access to the complete manual.
.Pp
tinc comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it under certain conditions;
see the file COPYING for details.
.Sh AUTHORS
.An "Ivo Timmermans"
.An "Guus Sliepen" Aq guus@tinc-vpn.org
.Pp
And thanks to many others for their contributions to tinc!

345
doc/tinc.8.in Normal file
View file

@ -0,0 +1,345 @@
.Dd 2014-01-16
.Dt TINCCTL 8
.\" Manual page created by:
.\" Scott Lamb
.Sh NAME
.Nm tinc
.Nd tinc VPN control
.Sh SYNOPSIS
.Nm
.Op Fl bcn
.Op Fl -config Ns = Ns Ar DIR
.Op Fl -net Ns = Ns Ar NETNAME
.Op Fl -pidfile Ns = Ns Ar FILENAME
.Op Fl -batch
.Op Fl -force
.Op Fl -help
.Op Fl -version
.Op Ar COMMAND
.Sh DESCRIPTION
This is the control program of tinc, a secure virtual private network (VPN)
project.
.Nm
can start and stop
.Xr tincd 8 ,
and can to alter and inspect the state of a running VPN.
It can also be used to change the configuration,
or to import or export host configuration files from other nodes.
If
.Nm
is started with a
.Ar COMMAND ,
this command is immediately executed, after which
.Nm
exits.
If no
.Ar COMMAND
is given,
.Nm
will act as a shell;
it will display a prompt, and commands can be entered on the prompt.
If
.Nm
is compiled with libreadline, history and command completion are available on the prompt.
One can also pipe a script containing commands through
.Nm .
In that case, lines starting with a # symbol will be ignored.
.Sh OPTIONS
.Bl -tag -width indent
.It Fl n, -net Ns = Ns Ar NETNAME
Communicate with tincd(8) connected with
.Ar NETNAME .
.It Fl -pidfile Ns = Ns Ar FILENAME
Use the cookie from
.Ar FILENAME
to authenticate with a running tinc daemon.
If unspecified, the default is
.Pa @runstatedir@/tinc. Ns Ar NETNAME Ns Pa .pid.
.It Fl b, -batch
Don't ask for anything (non-interactive mode).
.It Fl -force
Force some commands to work despite warnings.
.It Fl -help
Display short list of options.
.It Fl -version
Output version information and exit.
.El
.Sh ENVIRONMENT VARIABLES
.Bl -tag -width indent
.It Ev NETNAME
If no netname is specified on the command line with the
.Fl n
option, the value of this environment variable is used.
.El
.Sh COMMANDS
.Bl -tag -width indent
.It init Op Ar name
Create initial configuration files and RSA and Ed25519 key pairs with default length.
If no
.Ar name
for this node is given, it will be asked for.
.It get Ar variable
Print the current value of configuration variable
.Ar variable .
If more than one variable with the same name exists,
the value of each of them will be printed on a separate line.
.It set Ar variable Ar value
Set configuration variable
.Ar variable
to the given
.Ar value .
All previously existing configuration variables with the same name are removed.
To set a variable for a specific host, use the notation
.Ar host Ns Li . Ns Ar variable .
.It add Ar variable Ar value
As above, but without removing any previously existing configuration variables.
If the variable already exists with the given value, nothing happens.
.It del Ar variable Op Ar value
Remove configuration variables with the same name and
.Ar value .
If no
.Ar value
is given, all configuration variables with the same name will be removed.
.It edit Ar filename
Start an editor for the given configuration file.
You do not need to specify the full path to the file.
.It export
Export the host configuration file of the local node to standard output.
.It export-all
Export all host configuration files to standard output.
.It import
Import host configuration data generated by the
.Nm
export command from standard input.
Already existing host configuration files are not overwritten unless the option
.Fl -force
is used.
.It exchange
The same as export followed by import.
.It exchange-all
The same as export-all followed by import.
.It invite Ar name
Prepares an invitation for a new node with the given
.Ar name ,
and prints a short invitation URL that can be used with the join command.
.It join Op Ar URL
Join an existing VPN using an invitation URL created using the invite command.
If no
.Ar URL
is given, it will be read from standard input.
.It start Op tincd options
Start
.Xr tincd 8 ,
optionally with the given extra options.
.It stop
Stop
.Xr tincd 8 .
.It restart Op tincd options
Restart
.Xr tincd 8 ,
optionally with the given extra options.
.It reload
Partially rereads configuration files. Connections to hosts whose host
config files are removed are closed. New outgoing connections specified
in
.Xr tinc.conf 5
will be made.
.It pid
Shows the PID of the currently running
.Xr tincd 8 .
.It generate-keys Op bits
Generate both RSA and Ed25519 key pairs (see below) and exit.
.It generate-ed25519-keys
Generate public/private Ed25519 key pair and exit.
.It generate-rsa-keys Op bits
Generate public/private RSA key pair and exit.
If
.Ar bits
is omitted, the default length will be 2048 bits.
When saving keys to existing files, tinc will not delete the old keys;
you have to remove them manually.
.It dump [reachable] nodes
Dump a list of all known nodes in the VPN.
If the keyword reachable is used, only lists reachable nodes.
.It dump edges
Dump a list of all known connections in the VPN.
.It dump subnets
Dump a list of all known subnets in the VPN.
.It dump connections
Dump a list of all meta connections with ourself.
.It dump graph | digraph
Dump a graph of the VPN in
.Xr dotty 1
format.
Nodes are colored according to their reachability:
red nodes are unreachable, orange nodes are indirectly reachable, green nodes are directly reachable.
Black nodes are either directly or indirectly reachable, but direct reachability has not been tried yet.
.It dump invitations
Dump a list of outstanding invitations.
The filename of the invitation, as well as the name of the node that is being invited is shown for each invitation.
.It info Ar node | subnet | address
Show information about a particular node, subnet or address.
If an address is given, any matching subnet will be shown.
.It purge
Purges all information remembered about unreachable nodes.
.It debug Ar N
Sets debug level to
.Ar N .
.It log Op Ar N
Capture log messages from a running tinc daemon.
An optional debug level can be given that will be applied only for log messages sent to
.Nm tinc .
.It retry
Forces
.Xr tincd 8
to try to connect to all uplinks immediately.
Usually
.Xr tincd 8
attempts to do this itself,
but increases the time it waits between the attempts each time it failed,
and if
.Xr tincd 8
didn't succeed to connect to an uplink the first time after it started,
it defaults to the maximum time of 15 minutes.
.It disconnect Ar NODE
Closes the meta connection with the given
.Ar NODE .
.It top
If
.Nm
is compiled with libcurses support, this will display live traffic statistics
for all the known nodes, similar to the UNIX
.Xr top 1
command.
See below for more information.
.It pcap
Dump VPN traffic going through the local tinc node in
.Xr pcap-savefile 5
format to standard output,
from where it can be redirected to a file or piped through a program that can parse it directly,
such as
.Xr tcpdump 8 .
.It network Op Ar netname
If
.Ar netname
is given, switch to that network.
Otherwise, display a list of all networks for which configuration files exist.
.It fsck
This will check the configuration files for possible problems,
such as unsafe file permissions, missing executable bit on script,
unknown and obsolete configuration variables, wrong public and/or private keys, and so on.
.Pp
When problems are found, this will be printed on a line with WARNING or ERROR in front of it.
Most problems must be corrected by the user itself, however in some cases (like file permissions and missing public keys),
tinc will ask if it should fix the problem.
.It sign Op Ar filename
Sign a file with the local node's private key.
If no
.Ar filename
is given, the file is read from standard input.
The signed file is written to standard output.
.It verify Ar name Op Ar filename
Check the signature of a file against a node's public key.
The
.Ar name
of the node must be given,
or can be
.Li .
to check against the local node's public key, or
.Li *
to allow a signature from any node whose public key is known.
If no
.Ar filename
is given, the file is read from standard input.
If the verification is successful,
a copy of the input with the signature removed is written to standard output,
and the exit code will be zero.
If the verification failed,
nothing will be written to standard output, and the exit code will be non-zero.
.El
.Sh EXAMPLES
Examples of some commands:
.Bd -literal -offset indent
tinc -n vpn dump graph | circo -Txlib
tinc -n vpn pcap | tcpdump -r -
tinc -n vpn top
.Pp
.Ed
Examples of changing the configuration using
.Nm :
.Bd -literal -offset indent
tinc -n vpn init foo
tinc -n vpn add Subnet 192.168.1.0/24
tinc -n vpn add bar.Address bar.example.com
tinc -n vpn add ConnectTo bar
tinc -n vpn export | gpg --clearsign | mail -s "My config" vpnmaster@example.com
.Ed
.Sh TOP
The top command connects to a running tinc daemon and repeatedly queries its per-node traffic counters.
It displays a list of all the known nodes in the left-most column,
and the amount of bytes and packets read from and sent to each node in the other columns.
By default, the information is updated every second.
The behaviour of the top command can be changed using the following keys:
.Bl -tag
.It Ic s
Change the interval between updates.
After pressing the
.Ic s
key, enter the desired interval in seconds, followed by enter.
Fractional seconds are honored.
Intervals lower than 0.1 seconds are not allowed.
.It Ic c
Toggle between displaying current traffic rates (in packets and bytes per second)
and cumulative traffic (total packets and bytes since the tinc daemon started).
.It Ic n
Sort the list of nodes by name.
.It Ic i
Sort the list of nodes by incoming amount of bytes.
.It Ic I
Sort the list of nodes by incoming amount of packets.
.It Ic o
Sort the list of nodes by outgoing amount of bytes.
.It Ic O
Sort the list of nodes by outgoing amount of packets.
.It Ic t
Sort the list of nodes by sum of incoming and outgoing amount of bytes.
.It Ic T
Sort the list of nodes by sum of incoming and outgoing amount of packets.
.It Ic b
Show amount of traffic in bytes.
.It Ic k
Show amount of traffic in kilobytes.
.It Ic M
Show amount of traffic in megabytes.
.It Ic G
Show amount of traffic in gigabytes.
.It Ic q
Quit.
.El
.Sh BUGS
If you find any bugs, report them to tinc@tinc-vpn.org.
.Sh SEE ALSO
.Xr tincd 8 ,
.Xr tinc.conf 5 ,
.Xr dotty 1 ,
.Xr pcap-savefile 5 ,
.Xr tcpdump 8 ,
.Xr top 1 ,
.Pa http://www.tinc-vpn.org/ ,
.Pa http://www.cabal.org/ .
.Pp
The full documentation for tinc is maintained as a Texinfo manual.
If the info and tinc programs are properly installed at your site,
the command
.Ic info tinc
should give you access to the complete manual.
.Pp
tinc comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it under certain conditions;
see the file COPYING for details.
.Sh AUTHORS
.An "Ivo Timmermans"
.An "Guus Sliepen" Aq guus@tinc-vpn.org
.Pp
And thanks to many others for their contributions to tinc!

View file

@ -1,4 +1,4 @@
.Dd 2016-10-29 .Dd 2017-09-02
.Dt TINC.CONF 5 .Dt TINC.CONF 5
.\" Manual page created by: .\" Manual page created by:
.\" Ivo Timmermans .\" Ivo Timmermans
@ -11,20 +11,12 @@ The files in the
.Pa @sysconfdir@/tinc/ .Pa @sysconfdir@/tinc/
directory contain runtime and security information for the tinc daemon. directory contain runtime and security information for the tinc daemon.
.Sh NETWORKS .Sh NETWORKS
It is perfectly ok for you to run more than one tinc daemon. To distinguish multiple instances of tinc running on one computer,
However, in its default form, you can use the
you will soon notice that you can't use two different configuration files without the
.Fl c
option.
.Pp
We have thought of another way of dealing with this: network names.
This means that you call
.Nm
with the
.Fl n .Fl n
option, which will assign a name to this daemon. option to assign a network name to each tinc daemon.
.Pp .Pp
The effect of this is that the daemon will set its configuration root to The effect of this option is that the daemon will set its configuration root to
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa / , .Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa / ,
where where
.Ar NETNAME .Ar NETNAME
@ -32,13 +24,14 @@ is your argument to the
.Fl n .Fl n
option. option.
You'll notice that messages appear in syslog as coming from You'll notice that messages appear in syslog as coming from
.Nm tincd. Ns Ar NETNAME . .Nm tincd. Ns Ar NETNAME ,
and on Linux, unless specified otherwise, the name of the virtual network interface will be the same as the network name.
.Pp .Pp
However, it is not strictly necessary that you call tinc with the It is recommended that you use network names even if you run only one instance of tinc.
However, you can choose not to use the
.Fl n .Fl n
option. option.
In this case, the network name would just be empty, In this case, the network name would just be empty, and
and it will be used as such.
.Nm tinc .Nm tinc
now looks for files in now looks for files in
.Pa @sysconfdir@/tinc/ , .Pa @sysconfdir@/tinc/ ,
@ -48,11 +41,6 @@ the configuration file should be
.Pa @sysconfdir@/tinc/tinc.conf , .Pa @sysconfdir@/tinc/tinc.conf ,
and the host configuration files are now expected to be in and the host configuration files are now expected to be in
.Pa @sysconfdir@/tinc/hosts/ . .Pa @sysconfdir@/tinc/hosts/ .
.Pp
But it is highly recommended that you use this feature of
.Nm tinc ,
because it will be so much clearer whom your daemon talks to.
Hence, we will assume that you use it.
.Sh NAMES .Sh NAMES
Each tinc daemon must have a name that is unique in the network which it will be part of. Each tinc daemon must have a name that is unique in the network which it will be part of.
The name will be used by other tinc daemons for identification. The name will be used by other tinc daemons for identification.
@ -63,24 +51,34 @@ file.
To make things easy, To make things easy,
choose something that will give unique and easy to remember names to your tinc daemon(s). choose something that will give unique and easy to remember names to your tinc daemon(s).
You could try things like hostnames, owner surnames or location names. You could try things like hostnames, owner surnames or location names.
However, you are only allowed to use alphanumerical characters (a-z, A-Z, and 0-9) and underscores (_) in the name.
.Sh INITIAL CONFIGURATION
If you have not configured tinc yet, you can easily create a basic configuration using the following command:
.Bd -literal -offset indent
.Nm tinc Fl n Ar NETNAME Li init Ar NAME
.Ed
.Pp
You can further change the configuration as needed either by manually editing the configuration files,
or by using
.Xr tinc 8 .
.Sh PUBLIC/PRIVATE KEYS .Sh PUBLIC/PRIVATE KEYS
You should use The
.Ic tincd -K .Nm tinc Li init
to generate public/private keypairs. command will have generated both RSA and Ed25519 public/private key pairs.
It will generate two keys. The private keys should be stored in files named
The private key should be stored in a separate file .Pa rsa_key.priv
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /rsa_key.priv and
\-\- where .Pa ed25519_key.priv
.Ar NETNAME in the directory
stands for the network (see .Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /
.Sx NETWORKS ) The public keys should be stored in the host configuration file
above. .Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Va NAME .
The public key should be stored in the host configuration file The RSA keys are used for backwards compatibility with tinc version 1.0.
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Va NAME If you are upgrading from version 1.0 to 1.1, you can keep the old configuration files,
\-\- where but you will need to create Ed25519 keys using the following command:
.Va NAME .Bd -literal -offset indent
stands for the name of the local tinc daemon (see .Nm tinc Fl n Ar NETNAME Li generate-ed25519-keys
.Sx NAMES ) . .Ed
.Sh SERVER CONFIGURATION .Sh SERVER CONFIGURATION
The server configuration of the daemon is done in the file The server configuration of the daemon is done in the file
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf . .Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf .
@ -103,6 +101,10 @@ Although all configuration options for the local host listed in this document ca
it is recommended to put host specific configuration options in the host configuration file, it is recommended to put host specific configuration options in the host configuration file,
as this makes it easy to exchange with other nodes. as this makes it easy to exchange with other nodes.
.Pp .Pp
You can edit the config file manually, but it is recommended that you use
.Xr tinc 8
to change configuration variables for you.
.Pp
Here are all valid variables, listed in alphabetical order. Here are all valid variables, listed in alphabetical order.
The default value is given between parentheses. The default value is given between parentheses.
.Bl -tag -width indent .Bl -tag -width indent
@ -112,26 +114,24 @@ If
.Qq any .Qq any
is selected, then depending on the operating system both IPv4 and IPv6 or just is selected, then depending on the operating system both IPv4 and IPv6 or just
IPv6 listening sockets will be created. IPv6 listening sockets will be created.
.It Va BindToAddress Li = Ar address Oo Ar port Oc Bq experimental .It Va AutoConnect Li = yes | no Pq yes
If your computer has more than one IPv4 or IPv6 address, If set to yes,
.Nm tinc .Nm tinc
will by default listen on all of them for incoming connections. will automatically set up meta connections to other nodes,
Multiple without requiring
.Va ConnectTo
variables.
.Pp
Note: it is not possible to connect to nodes using zero (system-assigned) ports in this way.
.It Va BindToAddress Li = Ar address Op Ar port
This is the same as
.Va ListenAddress ,
however the address given with the
.Va BindToAddress .Va BindToAddress
variables may be specified, option will also be used for outgoing connections. This is useful if your
in which case listening sockets for each specified address are made. computer has more than one IPv4 or IPv6 address, and you want
.Pp .Nm tinc
If no to only use a specific one for outgoing packets.
.Ar port
is specified, the socket will be bound to the port specified by the
.Va Port
option, or to port 655 if neither is given.
To only bind to a specific port but not to a specific address, use
.Li *
for the
.Ar address .
.Pp
This option may not work on all platforms.
.It Va BindToInterface Li = Ar interface Bq experimental .It Va BindToInterface Li = Ar interface Bq experimental
If your computer has more than one network interface, If your computer has more than one network interface,
.Nm tinc .Nm tinc
@ -157,6 +157,13 @@ Broadcast packets are sent directly to all nodes that can be reached directly.
Broadcast packets received from other nodes are never forwarded. Broadcast packets received from other nodes are never forwarded.
If the IndirectData option is also set, broadcast packets will only be sent to nodes which we have a meta connection to. If the IndirectData option is also set, broadcast packets will only be sent to nodes which we have a meta connection to.
.El .El
.It Va BroadcastSubnet Li = Ar address Ns Op Li / Ns Ar prefixlength
Declares a broadcast subnet. Any packet with a destination address falling into such a subnet will be routed as a broadcast (provided all nodes have it declared).
This is most useful to declare subnet broadcast addresses (e.g. 10.42.255.255), otherwise
.Nm tinc
won't know what to do with them.
.Pp
Note that global broadcast addresses (MAC ff:ff:ff:ff:ff:ff, IPv4 255.255.255.255), as well as multicast space (IPv4 224.0.0.0/4, IPv6 ff00::/8) are always considered broadcast addresses and don't need to be declared.
.It Va ConnectTo Li = Ar name .It Va ConnectTo Li = Ar name
Specifies which other tinc daemon to connect to on startup. Specifies which other tinc daemon to connect to on startup.
Multiple Multiple
@ -169,7 +176,9 @@ The names should be known to this tinc daemon
line). line).
.Pp .Pp
If you don't specify a host with If you don't specify a host with
.Va ConnectTo , .Va ConnectTo
and have disabled
.Va AutoConnect ,
.Nm tinc .Nm tinc
won't try to connect to other daemons at all, won't try to connect to other daemons at all,
and will instead just listen for incoming connections. and will instead just listen for incoming connections.
@ -193,6 +202,13 @@ instead of
.Va Device . .Va Device .
The info pages of the tinc package contain more information The info pages of the tinc package contain more information
about configuring the virtual network device. about configuring the virtual network device.
.It Va DeviceStandby Li = yes | no Po no Pc
When disabled,
.Nm tinc
calls tinc-up on startup, and tinc-down on shutdown. When enabled,
.Nm tinc
will only call tinc-up when at least one node is reachable, and will call tinc-down as soon as no nodes are reachable.
On Windows, this also determines when the virtual network interface "cable" is "plugged".
.It Va DeviceType Li = Ar type Pq platform dependent .It Va DeviceType Li = Ar type Pq platform dependent
The type of the virtual network device. The type of the virtual network device.
Tinc will normally automatically select the right type of tun/tap interface, and this option should not be used. Tinc will normally automatically select the right type of tun/tap interface, and this option should not be used.
@ -218,6 +234,11 @@ Do NOT connect multiple
.Nm tinc .Nm tinc
daemons to the same multicast address, this will very likely cause routing loops. daemons to the same multicast address, this will very likely cause routing loops.
Also note that this can cause decrypted VPN packets to be sent out on a real network if misconfigured. Also note that this can cause decrypted VPN packets to be sent out on a real network if misconfigured.
.It fd
Use a file descriptor, given directly as an integer or passed through a unix domain socket.
On Linux, an abstract socket address can be specified by using "@" as a prefix.
All packets are read from this interface.
Packets received for the local node are written to it.
.It uml Pq not compiled in by default .It uml Pq not compiled in by default
Create a UNIX socket with the filename specified by Create a UNIX socket with the filename specified by
.Va Device , .Va Device ,
@ -264,6 +285,17 @@ When this option is enabled, packets that cannot be sent directly to the destina
but which would have to be forwarded by an intermediate node, are dropped instead. but which would have to be forwarded by an intermediate node, are dropped instead.
When combined with the IndirectData option, When combined with the IndirectData option,
packets for nodes for which we do not have a meta connection with are also dropped. packets for nodes for which we do not have a meta connection with are also dropped.
.It Va Ed25519PrivateKeyFile Li = Ar filename Po Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /ed25519_key.priv Pc
The file in which the private Ed25519 key of this tinc daemon resides.
This is only used if
.Va ExperimentalProtocol
is enabled.
.It Va ExperimentalProtocol Li = yes | no Pq yes
When this option is enabled, the SPTPS protocol will be used when connecting to nodes that also support it.
Ephemeral ECDH will be used for key exchanges,
and Ed25519 will be used instead of RSA for authentication.
When enabled, an Ed25519 key must have been generated before with
.Nm tinc generate-ed25519-keys .
.It Va Forwarding Li = off | internal | kernel Po internal Pc Bq experimental .It Va Forwarding Li = off | internal | kernel Po internal Pc Bq experimental
This option selects the way indirect packets are forwarded. This option selects the way indirect packets are forwarded.
.Bl -tag -width indent .Bl -tag -width indent
@ -275,22 +307,16 @@ Incoming packets that are meant for another node are forwarded by tinc internall
.Pp .Pp
This is the default mode, and unless you really know you need another forwarding mode, don't change it. This is the default mode, and unless you really know you need another forwarding mode, don't change it.
.It kernel .It kernel
Incoming packets are always sent to the TUN/TAP device, even if the packets are not for the local node. Incoming packets using the legacy protocol are always sent to the TUN/TAP device,
even if the packets are not for the local node.
This is less efficient, but allows the kernel to apply its routing and firewall rules on them, This is less efficient, but allows the kernel to apply its routing and firewall rules on them,
and can also help debugging. and can also help debugging.
Incoming packets using the SPTPS protocol are dropped, since they are end-to-end encrypted.
.El .El
.It Va GraphDumpFile Li = Ar filename Bq experimental .It Va FWMark Li = Ar value Po 0 Pc Bq experimental
If this option is present, When set to a non-zero value, all TCP and UDP sockets created by tinc will use the given value as the firewall mark.
.Nm tinc This can be used for mark-based routing or for packet filtering.
will dump the current network graph to the file This option is currently only supported on Linux.
.Ar filename
every minute, unless there were no changes to the graph.
The file is in a format that can be read by graphviz tools.
If
.Ar filename
starts with a pipe symbol |,
then the rest of the filename is interpreted as a shell command
that is executed, the graph is then sent to stdin.
.It Va Hostnames Li = yes | no Pq no .It Va Hostnames Li = yes | no Pq no
This option selects whether IP addresses (both real and on the VPN) should This option selects whether IP addresses (both real and on the VPN) should
be resolved. Since DNS lookups are blocking, it might affect tinc's be resolved. Since DNS lookups are blocking, it might affect tinc's
@ -308,11 +334,40 @@ Under Windows, this variable is used to select which network interface will be u
If you specified a If you specified a
.Va Device , .Va Device ,
this variable is almost always already correctly set. this variable is almost always already correctly set.
.It Va InvitationExpire Li = Ar seconds Pq 604800
This option controls the period invitations are valid.
.It Va KeyExpire Li = Ar seconds Pq 3600 .It Va KeyExpire Li = Ar seconds Pq 3600
This option controls the period the encryption keys used to encrypt the data are valid. This option controls the period the encryption keys used to encrypt the data are valid.
It is common practice to change keys at regular intervals to make it even harder for crackers, It is common practice to change keys at regular intervals to make it even harder for crackers,
even though it is thought to be nearly impossible to crack a single key. even though it is thought to be nearly impossible to crack a single key.
.It Va LocalDiscovery Li = yes | no Po no Pc Bq experimental .It Va ListenAddress Li = Ar address Op Ar port
If your computer has more than one IPv4 or IPv6 address,
.Nm tinc
will by default listen on all of them for incoming connections.
This option can be used to restrict which addresses tinc listens on.
Multiple
.Va ListenAddress
variables may be specified,
in which case listening sockets for each specified address are made.
.Pp
If no
.Ar port
is specified, the socket will listen on the port specified by the
.Va Port
option, or to port 655 if neither is given.
To only listen on a specific port but not on a specific address, use
.Li *
for the
.Ar address .
.Pp
If
.Ar port
is set to zero, it will be randomly assigned by the system. This is useful to randomize source ports of UDP packets, which can improve UDP hole punching reliability. In this case it is recommended to set
.Va AddressFamily
as well, otherwise
.Nm tinc
will assign different ports to different address families but other nodes can only know of one.
.It Va LocalDiscovery Li = yes | no Pq yes
When enabled, When enabled,
.Nm tinc .Nm tinc
will try to detect peers that are on the same local network. will try to detect peers that are on the same local network.
@ -320,14 +375,20 @@ This will allow direct communication using LAN addresses, even if both peers are
and they only ConnectTo a third node outside the NAT, and they only ConnectTo a third node outside the NAT,
which normally would prevent the peers from learning each other's LAN address. which normally would prevent the peers from learning each other's LAN address.
.Pp .Pp
Currently, local discovery is implemented by sending broadcast packets to the LAN during path MTU discovery. Currently, local discovery is implemented by sending some packets to the local address of the node during UDP discovery. This will not work with old nodes that don't transmit their local address.
This feature may not work in all possible situations. .It Va LogLevel Li = level Pq 0
This option controls the verbosity of the logging. The higher the debug level, the more messages it will log.
.It Va MACExpire Li = Ar seconds Pq 600 .It Va MACExpire Li = Ar seconds Pq 600
This option controls the amount of time MAC addresses are kept before they are removed. This option controls the amount of time MAC addresses are kept before they are removed.
This only has effect when This only has effect when
.Va Mode .Va Mode
is set to is set to
.Qq switch . .Qq switch .
.It Va MaxConnectionBurst Li = Ar count Pq 100
This option controls how many connections tinc accepts in quick succession.
If there are more connections than the given number in a short time interval,
tinc will reduce the number of accepted connections to only one per second,
until the burst has passed.
.It Va MaxTimeout Li = Ar seconds Pq 900 .It Va MaxTimeout Li = Ar seconds Pq 900
This is the maximum delay before trying to reconnect to other tinc daemons. This is the maximum delay before trying to reconnect to other tinc daemons.
.It Va Mode Li = router | switch | hub Pq router .It Va Mode Li = router | switch | hub Pq router
@ -337,7 +398,7 @@ This option selects the way packets are routed to other daemons.
In this mode In this mode
.Va Subnet .Va Subnet
variables in the host configuration files will be used to form a routing table. variables in the host configuration files will be used to form a routing table.
Only unicast packets of routable protocols (IPv4 and IPv6) are supported in this mode. Only packets of routable protocols (IPv4 and IPv6) are supported in this mode.
.Pp .Pp
This is the default mode, and unless you really know you need another mode, don't change it. This is the default mode, and unless you really know you need another mode, don't change it.
.It switch .It switch
@ -355,7 +416,8 @@ while no routing table is managed.
.It Va Name Li = Ar name Bq required .It Va Name Li = Ar name Bq required
This is the name which identifies this tinc daemon. This is the name which identifies this tinc daemon.
It must be unique for the virtual private network this daemon will connect to. It must be unique for the virtual private network this daemon will connect to.
The Name may only consist of alphanumeric and underscore characters. .Va Name
may only consist of alphanumeric and underscore characters (a-z, A-Z, 0-9 and _), and is case sensitive.
If If
.Va Name .Va Name
starts with a starts with a
@ -385,7 +447,9 @@ It will allow this tinc daemon to authenticate itself to other daemons.
.It Va PrivateKeyFile Li = Ar filename Po Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /rsa_key.priv Pc .It Va PrivateKeyFile Li = Ar filename Po Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /rsa_key.priv Pc
The file in which the private RSA key of this tinc daemon resides. The file in which the private RSA key of this tinc daemon resides.
.It Va ProcessPriority Li = low | normal | high .It Va ProcessPriority Li = low | normal | high
When this option is used the priority of the tincd process will be adjusted. When this option is used the priority of the
.Nm tincd
process will be adjusted.
Increasing the priority may help to reduce latency and packet loss on the VPN. Increasing the priority may help to reduce latency and packet loss on the VPN.
.It Va Proxy Li = socks4 | socks5 | http | exec Ar ... Bq experimental .It Va Proxy Li = socks4 | socks5 | http | exec Ar ... Bq experimental
Use a proxy when making outgoing connections. Use a proxy when making outgoing connections.
@ -419,13 +483,13 @@ and
.Ev REMOTEPORT .Ev REMOTEPORT
are available. are available.
.El .El
.It Va ReplayWindow Li = Ar bytes Pq 16 .It Va ReplayWindow Li = Ar bytes Pq 32
This is the size of the replay tracking window for each remote node, in bytes. This is the size of the replay tracking window for each remote node, in bytes.
The window is a bitfield which tracks 1 packet per bit, so for example The window is a bitfield which tracks 1 packet per bit, so for example
the default setting of 16 will track up to 128 packets in the window. In high the default setting of 32 will track up to 256 packets in the window. In high
bandwidth scenarios, setting this to a higher value can reduce packet loss from bandwidth scenarios, setting this to a higher value can reduce packet loss from
the interaction of replay tracking with underlying real packet loss and/or the interaction of replay tracking with underlying real packet loss and/or
reordering. Setting this to zero will disable replay tracking completely and reordering. Setting this to zero will disable replay tracking completely and
pass all traffic, but leaves tinc vulnerable to replay-based attacks on your pass all traffic, but leaves tinc vulnerable to replay-based attacks on your
traffic. traffic.
.It Va StrictSubnets Li = yes | no Po no Pc Bq experimental .It Va StrictSubnets Li = yes | no Po no Pc Bq experimental
@ -440,12 +504,42 @@ and will only allow connections with nodes for which host config files are prese
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ .Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/
directory. directory.
Setting this options also implicitly sets StrictSubnets. Setting this options also implicitly sets StrictSubnets.
.It Va UDPRcvBuf Li = Ar bytes Pq OS default .It Va UDPDiscovery Li = yes | no Po yes Pc
When this option is enabled tinc will try to establish UDP connectivity to nodes,
using TCP while it determines if a node is reachable over UDP. If it is disabled,
tinc always assumes a node is reachable over UDP.
Note that tinc will never use UDP with nodes that have
.Va TCPOnly
enabled.
.It Va UDPDiscoveryKeepaliveInterval Li = Ar seconds Pq 9
The minimum amount of time between sending UDP ping datagrams to check UDP connectivity once it has been established.
Note that these pings are large, since they are used to verify link MTU as well.
.It Va UDPDiscoveryInterval Li = Ar seconds Pq 2
The minimum amount of time between sending UDP ping datagrams to try to establish UDP connectivity.
.It Va UDPDiscoveryTimeout Li = Ar seconds Pq 30
If tinc doesn't receive any UDP ping replies over the specified interval,
it will assume UDP communication is broken and will fall back to TCP.
.It Va UDPInfoInterval Li = Ar seconds Pq 5
The minimum amount of time between sending periodic updates about UDP addresses, which are mostly useful for UDP hole punching.
.It Va UDPRcvBuf Li = Ar bytes Pq 1048576
Sets the socket receive buffer size for the UDP socket, in bytes. Sets the socket receive buffer size for the UDP socket, in bytes.
If unset, the default buffer size will be used by the operating system. If set to zero, the default buffer size will be used by the operating system.
.It Va UDPSndBuf Li = Ar bytes Pq OS default Note: this setting can have a significant impact on performance, especially raw throughput.
.It Va UDPSndBuf Li = Ar bytes Pq 1048576
Sets the socket send buffer size for the UDP socket, in bytes. Sets the socket send buffer size for the UDP socket, in bytes.
If unset, the default buffer size will be used by the operating system. If set to zero, the default buffer size will be used by the operating system.
Note: this setting can have a significant impact on performance, especially raw throughput.
.It Va UPnP Li = yes | udponly | no Po no Pc
If this option is enabled then tinc will search for UPnP-IGD devices on the local network.
It will then create and maintain port mappings for tinc's listening TCP and UDP ports.
If set to "udponly", tinc will only create a mapping for its UDP (data) port, not for its TCP (metaconnection) port.
Note that tinc must have been built with miniupnpc support for this feature to be available.
Furthermore, be advised that enabling this can have security implications, because the miniupnpc library that
tinc uses might not be well-hardened with regard to malicious UPnP replies.
.It Va UPnPDiscoverWait Li = Ar seconds Pq 5
The amount of time to wait for replies when probing the local network for UPnP devices.
.It Va UPnPRefreshPeriod Li = Ar seconds Pq 60
How often tinc will re-add the port mapping, in case it gets reset on the UPnP device. This also controls the duration of the port mapping itself, which will be set to twice that duration.
.El .El
.Sh HOST CONFIGURATION FILES .Sh HOST CONFIGURATION FILES
The host configuration files contain all information needed The host configuration files contain all information needed
@ -468,13 +562,15 @@ Multiple
.Va Address .Va Address
variables can be specified, in which case each address will be tried until a working variables can be specified, in which case each address will be tried until a working
connection has been established. connection has been established.
.It Va Cipher Li = Ar cipher Pq aes-256-cbc .It Va Cipher Li = Ar cipher Pq blowfish
The symmetric cipher algorithm used to encrypt UDP packets. The symmetric cipher algorithm used to encrypt UDP packets.
Any cipher supported by LibreSSL or OpenSSL is recognised. Any cipher supported by LibreSSL or OpenSSL is recognised.
Furthermore, specifying Furthermore, specifying
.Qq none .Qq none
will turn off packet encryption. will turn off packet encryption.
It is best to use only those ciphers which support CBC mode. It is best to use only those ciphers which support CBC mode.
This option has no effect for connections between nodes using
.Va ExperimentalProtocol .
.It Va ClampMSS Li = yes | no Pq yes .It Va ClampMSS Li = yes | no Pq yes
This option specifies whether tinc should clamp the maximum segment size (MSS) This option specifies whether tinc should clamp the maximum segment size (MSS)
of TCP packets to the path MTU. This helps in situations where ICMP of TCP packets to the path MTU. This helps in situations where ICMP
@ -483,12 +579,14 @@ Fragmentation Needed or Packet too Big messages are dropped by firewalls.
This option sets the level of compression used for UDP packets. This option sets the level of compression used for UDP packets.
Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib), Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib),
10 (fast lzo) and 11 (best lzo). 10 (fast lzo) and 11 (best lzo).
.It Va Digest Li = Ar digest Pq sha256 .It Va Digest Li = Ar digest Pq sha1
The digest algorithm used to authenticate UDP packets. The digest algorithm used to authenticate UDP packets.
Any digest supported by LibreSSL or OpenSSL is recognised. Any digest supported by LibreSSL or OpenSSL is recognised.
Furthermore, specifying Furthermore, specifying
.Qq none .Qq none
will turn off packet authentication. will turn off packet authentication.
This option has no effect for connections between nodes using
.Va ExperimentalProtocol .
.It Va IndirectData Li = yes | no Pq no .It Va IndirectData Li = yes | no Pq no
When set to yes, only nodes which already have a meta connection to you When set to yes, only nodes which already have a meta connection to you
will try to establish direct communication with you. will try to establish direct communication with you.
@ -498,16 +596,28 @@ The length of the message authentication code used to authenticate UDP packets.
Can be anything from Can be anything from
.Qq 0 .Qq 0
up to the length of the digest produced by the digest algorithm. up to the length of the digest produced by the digest algorithm.
This option has no effect for connections between nodes using
.Va ExperimentalProtocol .
.It Va PMTU Li = Ar mtu Po 1514 Pc .It Va PMTU Li = Ar mtu Po 1514 Pc
This option controls the initial path MTU to this node. This option controls the initial path MTU to this node.
.It Va PMTUDiscovery Li = yes | no Po yes Pc .It Va PMTUDiscovery Li = yes | no Po yes Pc
When this option is enabled, tinc will try to discover the path MTU to this node. When this option is enabled, tinc will try to discover the path MTU to this node.
After the path MTU has been discovered, it will be enforced on the VPN. After the path MTU has been discovered, it will be enforced on the VPN.
.It Va MTUInfoInterval Li = Ar seconds Pq 5
The minimum amount of time between sending periodic updates about relay path MTU. Useful for quickly determining MTU to indirect nodes.
.It Va Port Li = Ar port Pq 655 .It Va Port Li = Ar port Pq 655
The port number on which this tinc daemon is listening for incoming connections, The port number on which this tinc daemon is listening for incoming connections,
which is used if no port number is specified in an which is used if no port number is specified in an
.Va Address .Va Address
statement. statement.
.Pp
If this is set to zero, the port will be randomly assigned by the system. This is useful to randomize source ports of UDP packets, which can improve UDP hole punching reliability. When setting
.Va Port
to zero it is recommended to set
.Va AddressFamily
as well, otherwise
.Nm tinc
will assign different ports to different address families but other nodes can only know of one.
.It Va PublicKey Li = Ar key Bq obsolete .It Va PublicKey Li = Ar key Bq obsolete
The public RSA key of this tinc daemon. The public RSA key of this tinc daemon.
It will be used to cryptographically verify it's identity and to set up a secure connection. It will be used to cryptographically verify it's identity and to set up a secure connection.
@ -542,7 +652,7 @@ IPv6 subnets are notated like fec0:0:0:1::/64.
MAC addresses are notated like 0:1a:2b:3c:4d:5e. MAC addresses are notated like 0:1a:2b:3c:4d:5e.
.Pp .Pp
A Subnet can be given a weight to indicate its priority over identical Subnets A Subnet can be given a weight to indicate its priority over identical Subnets
owned by different nodes. The default weight is 10. Lower values indicate owned by different nodes. The default weight is 10. Lower values indicate
higher priority. Packets will be sent to the node with the highest priority, higher priority. Packets will be sent to the node with the highest priority,
unless that node is not reachable, in which case the node with the next highest unless that node is not reachable, in which case the node with the next highest
priority will be tried, and so on. priority will be tried, and so on.
@ -556,6 +666,12 @@ Setting this options also implicitly sets IndirectData.
.Pp .Pp
Since version 1.0.10, tinc will automatically detect whether communication via Since version 1.0.10, tinc will automatically detect whether communication via
UDP is possible or not. UDP is possible or not.
.It Va Weight Li = Ar weight
If this variable is set, it overrides the weight given to connections made with
another host. A higher
.Ar weight
means a lower priority is given to this connection when broadcasting or
forwarding packets.
.El .El
.Sh SCRIPTS .Sh SCRIPTS
Apart from reading the server and host configuration files, Apart from reading the server and host configuration files,
@ -568,18 +684,24 @@ this means that tinc will temporarily stop processing packets until the called s
This guarantees that scripts will execute in the exact same order as the events that trigger them. This guarantees that scripts will execute in the exact same order as the events that trigger them.
If you need to run commands asynchronously, you have to ensure yourself that they are being run in the background. If you need to run commands asynchronously, you have to ensure yourself that they are being run in the background.
.Pp .Pp
Under Windows (not Cygwin), the scripts must have the extension Under Windows, the scripts must have the extension
.Pa .bat . .Pa .bat
or
.Pa .cmd .
.Bl -tag -width indent .Bl -tag -width indent
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up
This is the most important script. This is the most important script.
If it is present it will be executed right after the tinc daemon has been started and has connected to the virtual network device. If it is present it will be executed right after the tinc daemon has been started and has connected to the virtual network device (or when the first node becomes reachable if
.Va DeviceStandby
is used).
It should be used to set up the corresponding network interface, It should be used to set up the corresponding network interface,
but can also be used to start other things. but can also be used to start other things.
.Pp .Pp
Under Windows you can use the Network Connections control panel instead of creating this script. Under Windows you can use the Network Connections control panel instead of creating this script.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-down .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-down
This script is started right before the tinc daemon quits. This script is started right before the tinc daemon quits (or when the last node becomes unreachable if
.Va DeviceStandby
is used).
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Ar HOST Ns Pa -up .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Ar HOST Ns Pa -up
This script is started when the tinc daemon with name This script is started when the tinc daemon with name
.Ar HOST .Ar HOST
@ -597,6 +719,10 @@ This script is started when a Subnet becomes reachable.
The Subnet and the node it belongs to are passed in environment variables. The Subnet and the node it belongs to are passed in environment variables.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /subnet-down .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /subnet-down
This script is started when a Subnet becomes unreachable. This script is started when a Subnet becomes unreachable.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /invitation-created
This script is started when a new invitation has been created.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /invitation-accepted
This script is started when an invitation has been used.
.El .El
.Pp .Pp
The scripts are started without command line arguments, but can make use of certain environment variables. The scripts are started without command line arguments, but can make use of certain environment variables.
@ -605,6 +731,8 @@ Under UNIX like operating systems the names of environment variables must be pre
in scripts. in scripts.
Under Windows, in Under Windows, in
.Pa .bat .Pa .bat
or
.Pa .cmd
files, they have to be put between files, they have to be put between
.Li % .Li %
signs. signs.
@ -630,6 +758,14 @@ When a host becomes (un)reachable, this is set to the port number it uses for co
When a subnet becomes (un)reachable, this is set to the subnet. When a subnet becomes (un)reachable, this is set to the subnet.
.It Ev WEIGHT .It Ev WEIGHT
When a subnet becomes (un)reachable, this is set to the subnet weight. When a subnet becomes (un)reachable, this is set to the subnet weight.
.It Ev INVITATION_FILE
When the
.Pa invitation-created
script is called, this is set to the file where the invitation details will be stored.
.It Ev INVITATION_URL
When the
.Pa invitation-created
script is called, this is set to the invitation URL that has been created.
.El .El
.Pp .Pp
Do not forget that under UNIX operating systems, you have to make the scripts executable, using the command Do not forget that under UNIX operating systems, you have to make the scripts executable, using the command
@ -643,7 +779,7 @@ The top directory for configuration files.
The default name of the server configuration file for net The default name of the server configuration file for net
.Ar NETNAME . .Ar NETNAME .
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /conf.d/ .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /conf.d/
Optional directory from which any *.conf file will be loaded Optional directory from which any .conf file will be loaded
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/
Host configuration files are kept in this directory. Host configuration files are kept in this directory.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up
@ -654,9 +790,14 @@ It can be used to set up the corresponding network interface.
If an executable file with this name exists, If an executable file with this name exists,
it will be executed right before the tinc daemon is going to close it will be executed right before the tinc daemon is going to close
its connection to the virtual network device. its connection to the virtual network device.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /invitations/
This directory contains outstanding invitations.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /invitation-data
After a successful join, this file contains a copy of the invitation data received.
.El .El
.Sh SEE ALSO .Sh SEE ALSO
.Xr tincd 8 , .Xr tincd 8 ,
.Xr tinc 8 ,
.Pa https://www.tinc-vpn.org/ , .Pa https://www.tinc-vpn.org/ ,
.Pa http://www.tldp.org/LDP/nag2/ . .Pa http://www.tldp.org/LDP/nag2/ .
.Pp .Pp

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
.Dd 2014-05-11 .Dd 2013-01-14
.Dt TINCD 8 .Dt TINCD 8
.\" Manual page created by: .\" Manual page created by:
.\" Ivo Timmermans .\" Ivo Timmermans
@ -8,17 +8,15 @@
.Nd tinc VPN daemon .Nd tinc VPN daemon
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
.Op Fl cdDkKnoLRU .Op Fl cdDKnsoLRU
.Op Fl -config Ns = Ns Ar DIR .Op Fl -config Ns = Ns Ar DIR
.Op Fl -no-detach .Op Fl -no-detach
.Op Fl -debug Ns Op = Ns Ar LEVEL .Op Fl -debug Ns Op = Ns Ar LEVEL
.Op Fl -kill Ns Op = Ns Ar SIGNAL
.Op Fl -net Ns = Ns Ar NETNAME .Op Fl -net Ns = Ns Ar NETNAME
.Op Fl -generate-keys Ns Op = Ns Ar BITS
.Op Fl -option Ns = Ns Ar [HOST.]KEY=VALUE .Op Fl -option Ns = Ns Ar [HOST.]KEY=VALUE
.Op Fl -mlock .Op Fl -mlock
.Op Fl -logfile Ns Op = Ns Ar FILE .Op Fl -logfile Ns Op = Ns Ar FILE
.Op Fl -pidfile Ns = Ns Ar FILE .Op Fl -syslog
.Op Fl -bypass-security .Op Fl -bypass-security
.Op Fl -chroot .Op Fl -chroot
.Op Fl -user Ns = Ns Ar USER .Op Fl -user Ns = Ns Ar USER
@ -37,7 +35,7 @@ If that succeeds,
it will detach from the controlling terminal and continue in the background, it will detach from the controlling terminal and continue in the background,
accepting and setting up connections to other tinc daemons accepting and setting up connections to other tinc daemons
that are part of the virtual private network. that are part of the virtual private network.
Under Windows (not Cygwin) tinc will install itself as a service, Under Windows tinc will install itself as a service,
which will be restarted automatically after reboots. which will be restarted automatically after reboots.
.Sh OPTIONS .Sh OPTIONS
.Bl -tag -width indent .Bl -tag -width indent
@ -54,14 +52,6 @@ If not mentioned otherwise, this will show log messages on the standard error ou
Increase debug level or set it to Increase debug level or set it to
.Ar LEVEL .Ar LEVEL
(see below). (see below).
.It Fl k, -kill Ns Op = Ns Ar SIGNAL
Attempt to kill a running
.Nm
(optionally with the specified
.Ar SIGNAL
instead of SIGTERM) and exit.
Under Windows (not Cygwin) the optional argument is ignored,
the service will always be stopped and removed.
.It Fl n, -net Ns = Ns Ar NETNAME .It Fl n, -net Ns = Ns Ar NETNAME
Connect to net Connect to net
.Ar NETNAME . .Ar NETNAME .
@ -73,13 +63,6 @@ for
.Ar NETNAME .Ar NETNAME
is the same as not specifying any is the same as not specifying any
.Ar NETNAME . .Ar NETNAME .
.It Fl K, -generate-keys Ns Op = Ns Ar BITS
Generate public/private RSA keypair and exit.
If
.Ar BITS
is omitted, the default length will be 2048 bits.
When saving keys to existing files, tinc will not delete the old keys,
you have to remove them manually.
.It Fl o, -option Ns = Ns Ar [HOST.]KEY=VALUE .It Fl o, -option Ns = Ns Ar [HOST.]KEY=VALUE
Without specifying a Without specifying a
.Ar HOST , .Ar HOST ,
@ -99,18 +82,25 @@ This option can be used more than once to specify multiple configuration variabl
.It Fl L, -mlock .It Fl L, -mlock
Lock tinc into main memory. Lock tinc into main memory.
This will prevent sensitive data like shared private keys to be written to the system swap files/partitions. This will prevent sensitive data like shared private keys to be written to the system swap files/partitions.
This option is not supported on all platforms.
.It Fl -logfile Ns Op = Ns Ar FILE .It Fl -logfile Ns Op = Ns Ar FILE
Write log entries to a file instead of to the system logging facility. Write log entries to a file instead of to the system logging facility.
If If
.Ar FILE .Ar FILE
is omitted, the default is is omitted, the default is
.Pa @localstatedir@/log/tinc. Ns Ar NETNAME Ns Pa .log. .Pa @localstatedir@/log/tinc. Ns Ar NETNAME Ns Pa .log.
.It Fl -pidfile Ns = Ns Ar FILE .It Fl s, -syslog
Write PID to When this option is is set, tinc uses syslog instead of stderr in --no-detach mode.
.It Fl -pidfile Ns = Ns Ar FILENAME
Store a cookie in
.Ar FILENAME
which allows
.Xr tinc 8
to authenticate.
If
.Ar FILE .Ar FILE
instead of is omitted, the default is
.Pa @runstatedir@/tinc. Ns Ar NETNAME Ns Pa .pid. .Pa @runstatedir@/tinc. Ns Ar NETNAME Ns Pa .pid.
Under Windows this option will be ignored.
.It Fl -bypass-security .It Fl -bypass-security
Disables encryption and authentication of the meta protocol. Disables encryption and authentication of the meta protocol.
Only useful for debugging. Only useful for debugging.
@ -118,10 +108,12 @@ Only useful for debugging.
With this option tinc chroots into the directory where network With this option tinc chroots into the directory where network
config is located (@sysconfdir@/tinc/NETNAME if -n option is used, config is located (@sysconfdir@/tinc/NETNAME if -n option is used,
or to the directory specified with -c option) after initialization. or to the directory specified with -c option) after initialization.
This option is not supported on all platforms.
.It Fl U, -user Ns = Ns Ar USER .It Fl U, -user Ns = Ns Ar USER
setuid to the specified setuid to the specified
.Ar USER .Ar USER
after initialization. after initialization.
This option is not supported on all platforms.
.It Fl -help .It Fl -help
Display short list of options. Display short list of options.
.It Fl -version .It Fl -version
@ -151,15 +143,6 @@ If the
.Fl -logfile .Fl -logfile
option is used, this will also close and reopen the log file, option is used, this will also close and reopen the log file,
useful when log rotation is used. useful when log rotation is used.
.It INT
Temporarily increases debug level to 5.
Send this signal again to revert to the original level.
.It USR1
Dumps the connection list to syslog.
.It USR2
Dumps virtual network device statistics, all known nodes, edges and subnets to syslog.
.It WINCH
Purges all information remembered about unreachable nodes.
.El .El
.Sh DEBUG LEVELS .Sh DEBUG LEVELS
The tinc daemon can send a lot of messages to the syslog. The tinc daemon can send a lot of messages to the syslog.
@ -206,6 +189,7 @@ If you find any bugs, report them to tinc@tinc-vpn.org.
.Sh TODO .Sh TODO
A lot, especially security auditing. A lot, especially security auditing.
.Sh SEE ALSO .Sh SEE ALSO
.Xr tinc 8 ,
.Xr tinc.conf 5 , .Xr tinc.conf 5 ,
.Pa https://www.tinc-vpn.org/ , .Pa https://www.tinc-vpn.org/ ,
.Pa http://www.cabal.org/ . .Pa http://www.cabal.org/ .

View file

@ -1,5 +1,5 @@
@set VERSION 1.0.36 @set VERSION 1.1pre17-49-g4cc4b9bc
@set PACKAGE tinc @set PACKAGE tinc
@set sysconfdir /etc @set sysconfdir /usr/local/etc
@set localstatedir /var @set localstatedir /usr/local/var
@set runstatedir /run @set runstatedir /usr/local/var/run

View file

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# install - install a program, script, or datafile # install - install a program, script, or datafile
scriptversion=2018-03-11.20; # UTC scriptversion=2020-11-14.01; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was # This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the # later released in X11R6 (xc/config/util/install.sh) with the
@ -69,6 +69,11 @@ posix_mkdir=
# Desired mode of installed file. # Desired mode of installed file.
mode=0755 mode=0755
# Create dirs (including intermediate dirs) using mode 755.
# This is like GNU 'install' as of coreutils 8.32 (2020).
mkdir_umask=22
backupsuffix=
chgrpcmd= chgrpcmd=
chmodcmd=$chmodprog chmodcmd=$chmodprog
chowncmd= chowncmd=
@ -99,18 +104,28 @@ Options:
--version display version info and exit. --version display version info and exit.
-c (ignored) -c (ignored)
-C install only if different (preserve the last data modification time) -C install only if different (preserve data modification time)
-d create directories instead of installing files. -d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP. -g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE. -m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER. -o USER $chownprog installed files to USER.
-p pass -p to $cpprog.
-s $stripprog installed files. -s $stripprog installed files.
-S SUFFIX attempt to back up existing files, with suffix SUFFIX.
-t DIRECTORY install into DIRECTORY. -t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory. -T report an error if DSTFILE is a directory.
Environment variables override the default commands: Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG RMPROG STRIPPROG
By default, rm is invoked with -f; when overridden with RMPROG,
it's up to you to specify -f if you want it.
If -S is not specified, no backups are attempted.
Email bug reports to bug-automake@gnu.org.
Automake home page: https://www.gnu.org/software/automake/
" "
while test $# -ne 0; do while test $# -ne 0; do
@ -137,8 +152,13 @@ while test $# -ne 0; do
-o) chowncmd="$chownprog $2" -o) chowncmd="$chownprog $2"
shift;; shift;;
-p) cpprog="$cpprog -p";;
-s) stripcmd=$stripprog;; -s) stripcmd=$stripprog;;
-S) backupsuffix="$2"
shift;;
-t) -t)
is_target_a_directory=always is_target_a_directory=always
dst_arg=$2 dst_arg=$2
@ -255,6 +275,10 @@ do
dstdir=$dst dstdir=$dst
test -d "$dstdir" test -d "$dstdir"
dstdir_status=$? dstdir_status=$?
# Don't chown directories that already exist.
if test $dstdir_status = 0; then
chowncmd=""
fi
else else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
@ -301,22 +325,6 @@ do
if test $dstdir_status != 0; then if test $dstdir_status != 0; then
case $posix_mkdir in case $posix_mkdir in
'') '')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode. # With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask. # Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then if test -n "$dir_arg"; then
@ -326,52 +334,49 @@ do
fi fi
posix_mkdir=false posix_mkdir=false
case $umask in # The $RANDOM variable is not portable (e.g., dash). Use it
*[123567][0-7][0-7]) # here however when possible just to lower collision chance.
# POSIX mkdir -p sets u+wx bits regardless of umask, which tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
# Note that $RANDOM variable is not portable (e.g. dash); Use it
# here however when possible just to lower collision chance.
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 trap '
ret=$?
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
exit $ret
' 0
# Because "mkdir -p" follows existing symlinks and we likely work # Because "mkdir -p" follows existing symlinks and we likely work
# directly in world-writeable /tmp, make sure that the '$tmpdir' # directly in world-writeable /tmp, make sure that the '$tmpdir'
# directory is successfully created first before we actually test # directory is successfully created first before we actually test
# 'mkdir -p' feature. # 'mkdir -p'.
if (umask $mkdir_umask && if (umask $mkdir_umask &&
$mkdirprog $mkdir_mode "$tmpdir" && $mkdirprog $mkdir_mode "$tmpdir" &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
then then
if test -z "$dir_arg" || { if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m. # Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't. # other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
test_tmpdir="$tmpdir/a" test_tmpdir="$tmpdir/a"
ls_ld_tmpdir=`ls -ld "$test_tmpdir"` ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
case $ls_ld_tmpdir in case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;; d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;; d????-?--*) different_mode=755;;
*) false;; *) false;;
esac && esac &&
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && { $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
} }
} }
then posix_mkdir=: then posix_mkdir=:
fi fi
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
else else
# Remove any dirs left behind by ancient mkdir implementations. # Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
fi fi
trap '' 0;; trap '' 0;;
esac;;
esac esac
if if
@ -382,7 +387,7 @@ do
then : then :
else else
# The umask is ridiculous, or mkdir does not conform to POSIX, # mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the # or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go. # directory the slow way, step by step, checking for races as we go.
@ -411,7 +416,7 @@ do
prefixes= prefixes=
else else
if $posix_mkdir; then if $posix_mkdir; then
(umask=$mkdir_umask && (umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently. # Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1 test -d "$prefix" || exit 1
@ -488,6 +493,13 @@ do
then then
rm -f "$dsttmp" rm -f "$dsttmp"
else else
# If $backupsuffix is set, and the file being installed
# already exists, attempt a backup. Don't worry if it fails,
# e.g., if mv doesn't support -f.
if test -n "$backupsuffix" && test -f "$dst"; then
$doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
fi
# Rename the file to the real destination. # Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
@ -502,9 +514,9 @@ do
# file should still install successfully. # file should still install successfully.
{ {
test ! -f "$dst" || test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null || $doit $rmcmd "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
} || } ||
{ echo "$0: cannot unlink or rename $dst" >&2 { echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1 (exit 1); exit 1

View file

@ -9,8 +9,8 @@ AC_DEFUN([tinc_ATTRIBUTE],
CFLAGS="$CFLAGS -Wall -Werror" CFLAGS="$CFLAGS -Wall -Werror"
AC_COMPILE_IFELSE( AC_COMPILE_IFELSE(
[AC_LANG_SOURCE( [AC_LANG_SOURCE(
[void *test(void) __attribute__ (($1)); [void *test(void *x) __attribute__ (($1));
void *test(void) { return (void *)0; } void *test(void *x) { return (void *)x; }
], ],
)], )],
[tinc_cv_attribute_$1=yes], [tinc_cv_attribute_$1=yes],

View file

@ -49,21 +49,23 @@
# modified version of the Autoconf Macro, you may extend this special # modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well. # exception to the GPL to apply to your modified version as well.
#serial 2 #serial 6
AC_DEFUN([AX_APPEND_FLAG], AC_DEFUN([AX_APPEND_FLAG],
[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX [dnl
AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])dnl AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF
AS_VAR_SET_IF(FLAGS, AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])
[case " AS_VAR_GET(FLAGS) " in AS_VAR_SET_IF(FLAGS,[
*" $1 "*) AS_CASE([" AS_VAR_GET(FLAGS) "],
AC_RUN_LOG([: FLAGS already contains $1]) [*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])],
;; [
*) AS_VAR_APPEND(FLAGS,[" $1"])
AC_RUN_LOG([: FLAGS="$FLAGS $1"]) AC_RUN_LOG([: FLAGS="$FLAGS"])
AS_VAR_SET(FLAGS, ["AS_VAR_GET(FLAGS) $1"]) ])
;; ],
esac], [
[AS_VAR_SET(FLAGS,["$1"])]) AS_VAR_SET(FLAGS,[$1])
AC_RUN_LOG([: FLAGS="$FLAGS"])
])
AS_VAR_POPDEF([FLAGS])dnl AS_VAR_POPDEF([FLAGS])dnl
])dnl AX_APPEND_FLAG ])dnl AX_APPEND_FLAG

264
m4/ax_code_coverage.m4 Normal file
View file

@ -0,0 +1,264 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_code_coverage.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_CODE_COVERAGE()
#
# DESCRIPTION
#
# Defines CODE_COVERAGE_CPPFLAGS, CODE_COVERAGE_CFLAGS,
# CODE_COVERAGE_CXXFLAGS and CODE_COVERAGE_LIBS which should be included
# in the CPPFLAGS, CFLAGS CXXFLAGS and LIBS/LIBADD variables of every
# build target (program or library) which should be built with code
# coverage support. Also defines CODE_COVERAGE_RULES which should be
# substituted in your Makefile; and $enable_code_coverage which can be
# used in subsequent configure output. CODE_COVERAGE_ENABLED is defined
# and substituted, and corresponds to the value of the
# --enable-code-coverage option, which defaults to being disabled.
#
# Test also for gcov program and create GCOV variable that could be
# substituted.
#
# Note that all optimisation flags in CFLAGS must be disabled when code
# coverage is enabled.
#
# Usage example:
#
# configure.ac:
#
# AX_CODE_COVERAGE
#
# Makefile.am:
#
# @CODE_COVERAGE_RULES@
# my_program_LIBS = ... $(CODE_COVERAGE_LIBS) ...
# my_program_CPPFLAGS = ... $(CODE_COVERAGE_CPPFLAGS) ...
# my_program_CFLAGS = ... $(CODE_COVERAGE_CFLAGS) ...
# my_program_CXXFLAGS = ... $(CODE_COVERAGE_CXXFLAGS) ...
#
# This results in a "check-code-coverage" rule being added to any
# Makefile.am which includes "@CODE_COVERAGE_RULES@" (assuming the module
# has been configured with --enable-code-coverage). Running `make
# check-code-coverage` in that directory will run the module's test suite
# (`make check`) and build a code coverage report detailing the code which
# was touched, then print the URI for the report.
#
# In earlier versions of this macro, CODE_COVERAGE_LDFLAGS was defined
# instead of CODE_COVERAGE_LIBS. They are both still defined, but use of
# CODE_COVERAGE_LIBS is preferred for clarity; CODE_COVERAGE_LDFLAGS is
# deprecated. They have the same value.
#
# This code was derived from Makefile.decl in GLib, originally licenced
# under LGPLv2.1+.
#
# LICENSE
#
# Copyright (c) 2012, 2016 Philip Withnall
# Copyright (c) 2012 Xan Lopez
# Copyright (c) 2012 Christian Persch
# Copyright (c) 2012 Paolo Borelli
# Copyright (c) 2012 Dan Winship
# Copyright (c) 2015 Bastien ROUCARIES
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or (at
# your option) any later version.
#
# This library 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 Lesser
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#serial 21
AC_DEFUN([AX_CODE_COVERAGE],[
dnl Check for --enable-code-coverage
AC_REQUIRE([AC_PROG_SED])
# allow to override gcov location
AC_ARG_WITH([gcov],
[AS_HELP_STRING([--with-gcov[=GCOV]], [use given GCOV for coverage (GCOV=gcov).])],
[_AX_CODE_COVERAGE_GCOV_PROG_WITH=$with_gcov],
[_AX_CODE_COVERAGE_GCOV_PROG_WITH=gcov])
AC_MSG_CHECKING([whether to build with code coverage support])
AC_ARG_ENABLE([code-coverage],
AS_HELP_STRING([--enable-code-coverage],
[Whether to enable code coverage support]),,
enable_code_coverage=no)
AM_CONDITIONAL([CODE_COVERAGE_ENABLED], [test x$enable_code_coverage = xyes])
AC_SUBST([CODE_COVERAGE_ENABLED], [$enable_code_coverage])
AC_MSG_RESULT($enable_code_coverage)
AS_IF([ test "$enable_code_coverage" = "yes" ], [
# check for gcov
AC_CHECK_TOOL([GCOV],
[$_AX_CODE_COVERAGE_GCOV_PROG_WITH],
[:])
AS_IF([test "X$GCOV" = "X:"],
[AC_MSG_ERROR([gcov is needed to do coverage])])
AC_SUBST([GCOV])
dnl Check if gcc is being used
AS_IF([ test "$GCC" = "no" ], [
AC_MSG_ERROR([not compiling with gcc, which is required for gcov code coverage])
])
AC_CHECK_PROG([LCOV], [lcov], [lcov])
AC_CHECK_PROG([GENHTML], [genhtml], [genhtml])
AS_IF([ test -z "$LCOV" ], [
AC_MSG_ERROR([To enable code coverage reporting you must have lcov installed])
])
AS_IF([ test -z "$GENHTML" ], [
AC_MSG_ERROR([Could not find genhtml from the lcov package])
])
dnl Build the code coverage flags
dnl Define CODE_COVERAGE_LDFLAGS for backwards compatibility
CODE_COVERAGE_CPPFLAGS="-DNDEBUG"
CODE_COVERAGE_CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage"
CODE_COVERAGE_CXXFLAGS="-O0 -g -fprofile-arcs -ftest-coverage"
CODE_COVERAGE_LIBS="-lgcov"
CODE_COVERAGE_LDFLAGS="$CODE_COVERAGE_LIBS"
AC_SUBST([CODE_COVERAGE_CPPFLAGS])
AC_SUBST([CODE_COVERAGE_CFLAGS])
AC_SUBST([CODE_COVERAGE_CXXFLAGS])
AC_SUBST([CODE_COVERAGE_LIBS])
AC_SUBST([CODE_COVERAGE_LDFLAGS])
[CODE_COVERAGE_RULES_CHECK='
-$(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) -k check
$(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) code-coverage-capture
']
[CODE_COVERAGE_RULES_CAPTURE='
$(code_coverage_v_lcov_cap)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --capture --output-file "$(CODE_COVERAGE_OUTPUT_FILE).tmp" --test-name "$(call code_coverage_sanitize,$(PACKAGE_NAME)-$(PACKAGE_VERSION))" --no-checksum --compat-libtool $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_OPTIONS)
$(code_coverage_v_lcov_ign)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --remove "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "/tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN) --output-file "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_RMOPTS)
-@rm -f $(CODE_COVERAGE_OUTPUT_FILE).tmp
$(code_coverage_v_genhtml)LANG=C $(GENHTML) $(code_coverage_quiet) $(addprefix --prefix ,$(CODE_COVERAGE_DIRECTORY)) --output-directory "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_GENHTML_OPTIONS)
@echo "file://$(abs_builddir)/$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html"
']
[CODE_COVERAGE_RULES_CLEAN='
clean: code-coverage-clean
distclean: code-coverage-clean
code-coverage-clean:
-$(LCOV) --directory $(top_builddir) -z
-rm -rf $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_FILE).tmp $(CODE_COVERAGE_OUTPUT_DIRECTORY)
-find . \( -name "*.gcda" -o -name "*.gcno" -o -name "*.gcov" \) -delete
']
], [
[CODE_COVERAGE_RULES_CHECK='
@echo "Need to reconfigure with --enable-code-coverage"
']
CODE_COVERAGE_RULES_CAPTURE="$CODE_COVERAGE_RULES_CHECK"
CODE_COVERAGE_RULES_CLEAN=''
])
[CODE_COVERAGE_RULES='
# Code coverage
#
# Optional:
# - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting.
# Multiple directories may be specified, separated by whitespace.
# (Default: $(top_builddir))
# - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated
# by lcov for code coverage. (Default:
# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info)
# - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage
# reports to be created. (Default:
# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage)
# - CODE_COVERAGE_BRANCH_COVERAGE: Set to 1 to enforce branch coverage,
# set to 0 to disable it and leave empty to stay with the default.
# (Default: empty)
# - CODE_COVERAGE_LCOV_SHOPTS_DEFAULT: Extra options shared between both lcov
# instances. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE)
# - CODE_COVERAGE_LCOV_SHOPTS: Extra options to shared between both lcov
# instances. (Default: $CODE_COVERAGE_LCOV_SHOPTS_DEFAULT)
# - CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH: --gcov-tool pathtogcov
# - CODE_COVERAGE_LCOV_OPTIONS_DEFAULT: Extra options to pass to the
# collecting lcov instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH)
# - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the collecting lcov
# instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_DEFAULT)
# - CODE_COVERAGE_LCOV_RMOPTS_DEFAULT: Extra options to pass to the filtering
# lcov instance. (Default: empty)
# - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering lcov
# instance. (Default: $CODE_COVERAGE_LCOV_RMOPTS_DEFAULT)
# - CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT: Extra options to pass to the
# genhtml instance. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE)
# - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml
# instance. (Default: $CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT)
# - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore
#
# The generated report will be titled using the $(PACKAGE_NAME) and
# $(PACKAGE_VERSION). In order to add the current git hash to the title,
# use the git-version-gen script, available online.
# Optional variables
CODE_COVERAGE_DIRECTORY ?= $(top_builddir)
CODE_COVERAGE_OUTPUT_FILE ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info
CODE_COVERAGE_OUTPUT_DIRECTORY ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage
CODE_COVERAGE_BRANCH_COVERAGE ?=
CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= $(if $(CODE_COVERAGE_BRANCH_COVERAGE),\
--rc lcov_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE))
CODE_COVERAGE_LCOV_SHOPTS ?= $(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT)
CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH ?= --gcov-tool "$(GCOV)"
CODE_COVERAGE_LCOV_OPTIONS_DEFAULT ?= $(CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH)
CODE_COVERAGE_LCOV_OPTIONS ?= $(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT)
CODE_COVERAGE_LCOV_RMOPTS_DEFAULT ?=
CODE_COVERAGE_LCOV_RMOPTS ?= $(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT)
CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?=\
$(if $(CODE_COVERAGE_BRANCH_COVERAGE),\
--rc genhtml_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE))
CODE_COVERAGE_GENHTML_OPTIONS ?= $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULTS)
CODE_COVERAGE_IGNORE_PATTERN ?=
code_coverage_v_lcov_cap = $(code_coverage_v_lcov_cap_$(V))
code_coverage_v_lcov_cap_ = $(code_coverage_v_lcov_cap_$(AM_DEFAULT_VERBOSITY))
code_coverage_v_lcov_cap_0 = @echo " LCOV --capture"\
$(CODE_COVERAGE_OUTPUT_FILE);
code_coverage_v_lcov_ign = $(code_coverage_v_lcov_ign_$(V))
code_coverage_v_lcov_ign_ = $(code_coverage_v_lcov_ign_$(AM_DEFAULT_VERBOSITY))
code_coverage_v_lcov_ign_0 = @echo " LCOV --remove /tmp/*"\
$(CODE_COVERAGE_IGNORE_PATTERN);
code_coverage_v_genhtml = $(code_coverage_v_genhtml_$(V))
code_coverage_v_genhtml_ = $(code_coverage_v_genhtml_$(AM_DEFAULT_VERBOSITY))
code_coverage_v_genhtml_0 = @echo " GEN " $(CODE_COVERAGE_OUTPUT_DIRECTORY);
code_coverage_quiet = $(code_coverage_quiet_$(V))
code_coverage_quiet_ = $(code_coverage_quiet_$(AM_DEFAULT_VERBOSITY))
code_coverage_quiet_0 = --quiet
# sanitizes the test-name: replaces with underscores: dashes and dots
code_coverage_sanitize = $(subst -,_,$(subst .,_,$(1)))
# Use recursive makes in order to ignore errors during check
check-code-coverage:'"$CODE_COVERAGE_RULES_CHECK"'
# Capture code coverage data
code-coverage-capture: code-coverage-capture-hook'"$CODE_COVERAGE_RULES_CAPTURE"'
# Hook rule executed before code-coverage-capture, overridable by the user
code-coverage-capture-hook:
'"$CODE_COVERAGE_RULES_CLEAN"'
GITIGNOREFILES ?=
GITIGNOREFILES += $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_DIRECTORY)
A''M_DISTCHECK_CONFIGURE_FLAGS ?=
A''M_DISTCHECK_CONFIGURE_FLAGS += --disable-code-coverage
.PHONY: check-code-coverage code-coverage-capture code-coverage-capture-hook code-coverage-clean
']
AC_SUBST([CODE_COVERAGE_RULES])
m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([CODE_COVERAGE_RULES])])
])

44
m4/curses.m4 Normal file
View file

@ -0,0 +1,44 @@
dnl Check to find the curses headers/libraries
AC_DEFUN([tinc_CURSES],
[
AC_ARG_ENABLE([curses],
AS_HELP_STRING([--disable-curses], [disable curses support]))
AS_IF([test "x$enable_curses" != "xno"], [
AC_DEFINE(HAVE_CURSES, 1, [have curses support])
curses=true
AC_ARG_WITH(curses,
AS_HELP_STRING([--with-curses=DIR], [curses base directory, or:]),
[curses="$withval"
CPPFLAGS="$CPPFLAGS -I$withval/include"
LDFLAGS="$LDFLAGS -L$withval/lib"]
)
AC_ARG_WITH(curses-include,
AS_HELP_STRING([--with-curses-include=DIR], [curses headers directory]),
[curses_include="$withval"
CPPFLAGS="$CPPFLAGS -I$withval"]
)
AC_ARG_WITH(curses-lib,
AS_HELP_STRING([--with-curses-lib=DIR], [curses library directory]),
[curses_lib="$withval"
LDFLAGS="$LDFLAGS -L$withval"]
)
AC_CHECK_HEADERS(curses.h,
[],
[AC_MSG_ERROR("curses header files not found."); break]
)
AC_CHECK_LIB(ncurses, initscr,
[CURSES_LIBS="-lncurses"; AC_CHECK_LIB(tinfo, wtimeout, [CURSES_LIBS+=" -ltinfo"], [])],
[AC_CHECK_LIB(curses, initscr,
[CURSES_LIBS="-lcurses"],
[AC_MSG_ERROR("curses libraries not found.")]
)]
)
])
AC_SUBST(CURSES_LIBS)
])

33
m4/libgcrypt.m4 Normal file
View file

@ -0,0 +1,33 @@
dnl Check to find the libgcrypt headers/libraries
AC_DEFUN([tinc_LIBGCRYPT],
[
AC_ARG_WITH(libgcrypt,
AS_HELP_STRING([--with-libgcrypt=DIR], [libgcrypt base directory, or:]),
[libgcrypt="$withval"
CPPFLAGS="$CPPFLAGS -I$withval/include"
LDFLAGS="$LDFLAGS -L$withval/lib"]
)
AC_ARG_WITH(libgcrypt-include,
AS_HELP_STRING([--with-libgcrypt-include=DIR], [libgcrypt headers directory (without trailing /libgcrypt)]),
[libgcrypt_include="$withval"
CPPFLAGS="$CPPFLAGS -I$withval"]
)
AC_ARG_WITH(libgcrypt-lib,
AS_HELP_STRING([--with-libgcrypt-lib=DIR], [libgcrypt library directory]),
[libgcrypt_lib="$withval"
LDFLAGS="$LDFLAGS -L$withval"]
)
AC_CHECK_HEADERS([gcrypt.h],
[],
[AC_MSG_ERROR([libgcrypt header files not found.]); break]
)
AC_CHECK_LIB(gcrypt, gcry_cipher_encrypt,
[LIBS="-lgcrypt $LIBS"],
[AC_MSG_ERROR([libgcrypt libraries not found.])]
)
])

40
m4/miniupnpc.m4 Normal file
View file

@ -0,0 +1,40 @@
dnl Check to find the miniupnpc headers/libraries
AC_DEFUN([tinc_MINIUPNPC],
[
AC_ARG_ENABLE([miniupnpc],
AS_HELP_STRING([--enable-miniupnpc], [enable miniupnpc support]))
AS_IF([test "x$enable_miniupnpc" = "xyes"], [
AC_DEFINE(HAVE_MINIUPNPC, 1, [have miniupnpc support])
AC_ARG_WITH(miniupnpc,
AS_HELP_STRING([--with-miniupnpc=DIR], [miniupnpc base directory, or:]),
[miniupnpc="$withval"
CPPFLAGS="$CPPFLAGS -I$withval/include"
LDFLAGS="$LDFLAGS -L$withval/lib"]
)
AC_ARG_WITH(miniupnpc-include,
AS_HELP_STRING([--with-miniupnpc-include=DIR], [miniupnpc headers directory]),
[miniupnpc_include="$withval"
CPPFLAGS="$CPPFLAGS -I$withval"]
)
AC_ARG_WITH(miniupnpc-lib,
AS_HELP_STRING([--with-miniupnpc-lib=DIR], [miniupnpc library directory]),
[miniupnpc_lib="$withval"
LDFLAGS="$LDFLAGS -L$withval"]
)
AC_CHECK_HEADERS(miniupnpc/miniupnpc.h,
[],
[AC_MSG_ERROR("miniupnpc header files not found."); break]
)
AC_CHECK_LIB(miniupnpc, upnpDiscover,
[MINIUPNPC_LIBS="$LIBS -lminiupnpc"],
[AC_MSG_ERROR("miniupnpc libraries not found.")]
)
])
AC_SUBST(MINIUPNPC_LIBS)
])

View file

@ -35,7 +35,7 @@ AC_DEFUN([tinc_OPENSSL],
LDFLAGS="$LDFLAGS -L$withval"] LDFLAGS="$LDFLAGS -L$withval"]
) )
AC_CHECK_HEADERS(openssl/evp.h openssl/rsa.h openssl/rand.h openssl/err.h openssl/sha.h openssl/pem.h openssl/engine.h, AC_CHECK_HEADERS([openssl/evp.h openssl/rsa.h openssl/rand.h openssl/err.h openssl/sha.h openssl/pem.h openssl/engine.h],
[], [],
[AC_MSG_ERROR([LibreSSL/OpenSSL header files not found.]); break] [AC_MSG_ERROR([LibreSSL/OpenSSL header files not found.]); break]
) )
@ -54,5 +54,6 @@ AC_DEFUN([tinc_OPENSSL],
[#include <openssl/evp.h>] [#include <openssl/evp.h>]
) )
AC_CHECK_FUNCS([BN_GENCB_new RSA_set0_key], , , [#include <openssl/rsa.h>]) AC_CHECK_FUNCS([BN_GENCB_new ERR_remove_state RSA_set0_key], , , [#include <openssl/rsa.h>])
AC_CHECK_FUNCS([HMAC_CTX_new], , , [#include <openssl/hmac.h>])
]) ])

42
m4/readline.m4 Normal file
View file

@ -0,0 +1,42 @@
dnl Check to find the readline headers/libraries
AC_DEFUN([tinc_READLINE],
[
AC_ARG_ENABLE([readline],
AS_HELP_STRING([--disable-readline], [disable readline support]))
AS_IF([test "x$enable_readline" != "xno"], [
AC_DEFINE(HAVE_READLINE, 1, [have readline support])
readline=true
AC_ARG_WITH(readline,
AS_HELP_STRING([--with-readline=DIR], [readline base directory, or:]),
[readline="$withval"
CPPFLAGS="$CPPFLAGS -I$withval/include"
LDFLAGS="$LDFLAGS -L$withval/lib"]
)
AC_ARG_WITH(readline-include,
AS_HELP_STRING([--with-readline-include=DIR], [readline headers directory]),
[readline_include="$withval"
CPPFLAGS="$CPPFLAGS -I$withval"]
)
AC_ARG_WITH(readline-lib,
AS_HELP_STRING([--with-readline-lib=DIR], [readline library directory]),
[readline_lib="$withval"
LDFLAGS="$LDFLAGS -L$withval"]
)
AC_CHECK_HEADERS([readline/readline.h readline/history.h],
[],
[AC_MSG_ERROR("readline header files not found."); break]
)
AC_CHECK_LIB(readline, readline,
[READLINE_LIBS="-lreadline"],
[AC_MSG_ERROR("readline library not found.")],
[$CURSES_LIBS]
)
])
AC_SUBST(READLINE_LIBS)
])

View file

@ -1,54 +1,174 @@
## Produce this file with automake to get Makefile.in ## Produce this file with automake to get Makefile.in
sbin_PROGRAMS = tincd sbin_PROGRAMS = tincd tinc
check_PROGRAMS = sptps_test sptps_keypair
EXTRA_PROGRAMS = sptps_test sptps_keypair
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
EXTRA_PROGRAMS += sptps_speed
endif
ed25519_SOURCES = \
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_SOURCES = \
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
tincd_SOURCES = \ tincd_SOURCES = \
have.h \ address_cache.c address_cache.h \
system.h \ autoconnect.c autoconnect.h \
avl_tree.c avl_tree.h \ buffer.c buffer.h \
cipher.h \
conf.c conf.h \ conf.c conf.h \
connection.c connection.h \ connection.c connection.h \
control.c control.h \
control_common.h \
crypto.h \
device.h \ device.h \
digest.h \
dropin.c dropin.h \ dropin.c dropin.h \
dummy_device.c \ dummy_device.c \
ecdh.h \
ecdsa.h \
ecdsagen.h \
edge.c edge.h \ edge.c edge.h \
ethernet.h \ ethernet.h \
event.c event.h \ event.c event.h \
fake-getaddrinfo.c fake-getaddrinfo.h \ fd_device.c \
fake-getnameinfo.c fake-getnameinfo.h \
graph.c graph.h \ graph.c graph.h \
hash.c hash.h \
have.h \
ipv4.h \ ipv4.h \
ipv6.h \ ipv6.h \
list.c list.h \ list.c list.h \
logger.c logger.h \ logger.c logger.h \
meta.c meta.h \ meta.c meta.h \
multicast_device.c \ multicast_device.c \
names.c names.h \
net.c net.h \ net.c net.h \
net_packet.c \ net_packet.c \
net_setup.c \ net_setup.c \
net_socket.c \ net_socket.c \
netutl.c netutl.h \ netutl.c netutl.h \
node.c node.h \ node.c node.h \
pidfile.c pidfile.h \ prf.h \
process.c process.h \ process.c process.h \
protocol.c protocol.h \ protocol.c protocol.h \
protocol_auth.c \ protocol_auth.c \
protocol_edge.c \ protocol_edge.c \
protocol_misc.c \
protocol_key.c \ protocol_key.c \
protocol_misc.c \
protocol_subnet.c \ protocol_subnet.c \
proxy.c proxy.h \
raw_socket_device.c \ raw_socket_device.c \
route.c route.h \ 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.c subnet.h \
subnet_parse.c \
system.h \
tincd.c \ tincd.c \
utils.c utils.h \ utils.c utils.h \
xalloc.h xalloc.h \
version.c version.h \
ed25519/ecdh.c \
ed25519/ecdsa.c \
$(ed25519_SOURCES) \
$(chacha_poly1305_SOURCES)
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/ecdh.c \
ed25519/ecdsa.c \
ed25519/ecdsagen.c \
$(ed25519_SOURCES) \
$(chacha_poly1305_SOURCES)
sptps_test_SOURCES = \
logger.c logger.h \
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 = \
logger.c logger.h \
sptps.c sptps.h \
sptps_speed.c \
utils.c utils.h \
ed25519/ecdh.c \
ed25519/ecdsa.c \
ed25519/ecdsagen.c \
$(ed25519_SOURCES) \
$(chacha_poly1305_SOURCES)
## Conditionally compile device drivers
if !GETOPT if !GETOPT
tincd_SOURCES += \ tincd_SOURCES += \
getopt.c getopt.h \ getopt.c getopt.h \
getopt1.c 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 endif
if LINUX if LINUX
@ -70,10 +190,6 @@ if MINGW
tincd_SOURCES += mingw/device.c mingw/common.h tincd_SOURCES += mingw/device.c mingw/common.h
endif endif
if CYGWIN
tincd_SOURCES += cygwin/device.c
endif
if UML if UML
tincd_SOURCES += uml_device.c tincd_SOURCES += uml_device.c
endif endif
@ -82,8 +198,88 @@ if VDE
tincd_SOURCES += vde_device.c tincd_SOURCES += vde_device.c
endif endif
if OPENSSL
tincd_SOURCES += \
openssl/cipher.c \
openssl/crypto.c \
openssl/digest.c openssl/digest.h \
openssl/prf.c \
openssl/rsa.c
tinc_SOURCES += \
openssl/cipher.c \
openssl/crypto.c \
openssl/digest.c openssl/digest.h \
openssl/prf.c \
openssl/rsa.c \
openssl/rsagen.c
sptps_test_SOURCES += \
openssl/crypto.c \
openssl/digest.c openssl/digest.h \
openssl/prf.c
sptps_keypair_SOURCES += \
openssl/crypto.c
sptps_speed_SOURCES += \
openssl/crypto.c \
openssl/digest.c openssl/digest.h \
openssl/prf.c
else
if GCRYPT
tincd_SOURCES += \
gcrypt/cipher.c \
gcrypt/crypto.c \
gcrypt/digest.c gcrypt/digest.h \
gcrypt/prf.c \
gcrypt/rsa.c
tinc_SOURCES += \
gcrypt/cipher.c \
gcrypt/crypto.c \
gcrypt/digest.c gcrypt/digest.h \
gcrypt/prf.c \
gcrypt/rsa.c \
gcrypt/rsagen.c
sptps_test_SOURCES += \
gcrypt/cipher.c \
gcrypt/crypto.c \
gcrypt/digest.c gcrypt/digest.h \
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@ -lm $(CODE_COVERAGE_LIBS)
if TUNEMU if TUNEMU
LIBS += -lpcap LIBS += -lpcap
endif endif
AM_CPPFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DRUNSTATEDIR=\"$(runstatedir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -I $(abs_top_builddir)/ AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DRUNSTATEDIR=\"$(runstatedir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\" -iquote. $(CODE_COVERAGE_CFLAGS)
AM_CPPFLAGS = $(CODE_COVERAGE_CPPFLAGS)

File diff suppressed because it is too large Load diff

281
src/address_cache.c Normal file
View file

@ -0,0 +1,281 @@
/*
address_cache.c -- Manage cache of recently seen addresses
Copyright (C) 2018 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "system.h"
#include "address_cache.h"
#include "conf.h"
#include "names.h"
#include "netutl.h"
#include "xalloc.h"
static const unsigned int NOT_CACHED = -1;
// Find edges pointing to this node, and use them to build a list of unique, known addresses.
static struct addrinfo *get_known_addresses(node_t *n) {
struct addrinfo *ai = NULL;
struct addrinfo *oai = NULL;
for splay_each(edge_t, e, n->edge_tree) {
if(!e->reverse) {
continue;
}
bool found = false;
for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) {
if(!sockaddrcmp(&e->reverse->address, (sockaddr_t *)aip->ai_addr)) {
found = true;
break;
}
}
if(found) {
continue;
}
oai = ai;
ai = xzalloc(sizeof(*ai));
ai->ai_family = e->reverse->address.sa.sa_family;
ai->ai_socktype = SOCK_STREAM;
ai->ai_protocol = IPPROTO_TCP;
ai->ai_addrlen = SALEN(e->reverse->address.sa);
ai->ai_addr = xmalloc(ai->ai_addrlen);
memcpy(ai->ai_addr, &e->reverse->address, ai->ai_addrlen);
ai->ai_next = oai;
}
return ai;
}
static void free_known_addresses(struct addrinfo *ai) {
for(struct addrinfo *aip = ai, *next; aip; aip = next) {
next = aip->ai_next;
free(aip);
}
}
static unsigned int find_cached(address_cache_t *cache, const sockaddr_t *sa) {
for(unsigned int i = 0; i < cache->data.used; i++)
if(!sockaddrcmp(&cache->data.address[i], sa)) {
return i;
}
return NOT_CACHED;
}
void add_recent_address(address_cache_t *cache, const sockaddr_t *sa) {
// Check if it's already cached
unsigned int pos = find_cached(cache, sa);
// It's in the first spot, so nothing to do
if(pos == 0) {
return;
}
// Shift everything, move/add the address to the first slot
if(pos == NOT_CACHED) {
if(cache->data.used < MAX_CACHED_ADDRESSES) {
cache->data.used++;
}
pos = cache->data.used - 1;
}
memmove(&cache->data.address[1], &cache->data.address[0], pos * sizeof(cache->data.address[0]));
cache->data.address[0] = *sa;
// Write the cache
char fname[PATH_MAX];
snprintf(fname, sizeof(fname), "%s" SLASH "cache" SLASH "%s", confbase, cache->node->name);
FILE *fp = fopen(fname, "wb");
if(fp) {
fwrite(&cache->data, sizeof(cache->data), 1, fp);
fclose(fp);
}
}
const sockaddr_t *get_recent_address(address_cache_t *cache) {
// Check if there is an address in our cache of recently seen addresses
if(cache->tried < cache->data.used) {
return &cache->data.address[cache->tried++];
}
// Next, check any recently seen addresses not in our cache
while(cache->tried == cache->data.used) {
if(!cache->ai) {
cache->aip = cache->ai = get_known_addresses(cache->node);
}
if(cache->ai) {
if(cache->aip) {
sockaddr_t *sa = (sockaddr_t *)cache->aip->ai_addr;
cache->aip = cache->aip->ai_next;
if(find_cached(cache, sa) != NOT_CACHED) {
continue;
}
return sa;
} else {
free_known_addresses(cache->ai);
cache->ai = NULL;
}
}
cache->tried++;
}
// Otherwise, check if there are any known Address statements
if(!cache->config_tree) {
init_configuration(&cache->config_tree);
read_host_config(cache->config_tree, cache->node->name, false);
cache->cfg = lookup_config(cache->config_tree, "Address");
}
while(cache->cfg && !cache->aip) {
char *address, *port;
get_config_string(cache->cfg, &address);
char *space = strchr(address, ' ');
if(space) {
port = xstrdup(space + 1);
*space = 0;
} else {
if(!get_config_string(lookup_config(cache->config_tree, "Port"), &port)) {
port = xstrdup("655");
}
}
if(cache->ai) {
free_known_addresses(cache->ai);
}
cache->aip = cache->ai = str2addrinfo(address, port, SOCK_STREAM);
if(cache->ai) {
struct addrinfo *ai = NULL;
for(; cache->aip; cache->aip = cache->aip->ai_next) {
struct addrinfo *oai = ai;
ai = xzalloc(sizeof(*ai));
ai->ai_family = cache->aip->ai_family;
ai->ai_socktype = cache->aip->ai_socktype;
ai->ai_protocol = cache->aip->ai_protocol;
ai->ai_addrlen = cache->aip->ai_addrlen;
ai->ai_addr = xmalloc(ai->ai_addrlen);
memcpy(ai->ai_addr, cache->aip->ai_addr, ai->ai_addrlen);
ai->ai_next = oai;
}
freeaddrinfo(cache->ai);
cache->aip = cache->ai = ai;
}
free(address);
free(port);
cache->cfg = lookup_config_next(cache->config_tree, cache->cfg);
}
if(cache->ai) {
if(cache->aip) {
sockaddr_t *sa = (sockaddr_t *)cache->aip->ai_addr;
cache->aip = cache->aip->ai_next;
return sa;
} else {
free_known_addresses(cache->ai);
cache->ai = NULL;
}
}
// We're all out of addresses.
exit_configuration(&cache->config_tree);
return false;
}
address_cache_t *open_address_cache(node_t *node) {
address_cache_t *cache = xmalloc(sizeof(*cache));
cache->node = node;
// Try to open an existing address cache
char fname[PATH_MAX];
snprintf(fname, sizeof(fname), "%s" SLASH "cache" SLASH "%s", confbase, node->name);
FILE *fp = fopen(fname, "rb");
if(!fp || fread(&cache->data, sizeof(cache->data), 1, fp) != 1 || cache->data.version != ADDRESS_CACHE_VERSION) {
memset(&cache->data, 0, sizeof(cache->data));
}
if(fp) {
fclose(fp);
}
// Ensure we have a valid state
cache->config_tree = NULL;
cache->cfg = NULL;
cache->ai = NULL;
cache->aip = NULL;
cache->tried = 0;
cache->data.version = ADDRESS_CACHE_VERSION;
if(cache->data.used > MAX_CACHED_ADDRESSES) {
cache->data.used = 0;
}
return cache;
}
void reset_address_cache(address_cache_t *cache, const sockaddr_t *sa) {
if(sa) {
add_recent_address(cache, sa);
}
if(cache->config_tree) {
exit_configuration(&cache->config_tree);
}
if(cache->ai) {
free_known_addresses(cache->ai);
}
cache->config_tree = NULL;
cache->cfg = NULL;
cache->ai = NULL;
cache->aip = NULL;
cache->tried = 0;
}
void close_address_cache(address_cache_t *cache) {
if(cache->config_tree) {
exit_configuration(&cache->config_tree);
}
if(cache->ai) {
free_known_addresses(cache->ai);
}
free(cache);
}

50
src/address_cache.h Normal file
View file

@ -0,0 +1,50 @@
#ifndef TINC_ADDRESS_CACHE_H
#define TINC_ADDRESS_CACHE_H
/*
address_cache.h -- header for address_cache.c
Copyright (C) 2018 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "net.h"
#define MAX_CACHED_ADDRESSES 8
#define ADDRESS_CACHE_VERSION 1
typedef struct address_cache_t {
struct node_t *node;
struct splay_tree_t *config_tree;
struct config_t *cfg;
struct addrinfo *ai;
struct addrinfo *aip;
unsigned int tried;
struct {
unsigned int version;
unsigned int used;
sockaddr_t address[MAX_CACHED_ADDRESSES];
} data;
} address_cache_t;
void add_recent_address(address_cache_t *cache, const sockaddr_t *sa);
const sockaddr_t *get_recent_address(address_cache_t *cache);
address_cache_t *open_address_cache(struct node_t *node);
void reset_address_cache(address_cache_t *cache, const sockaddr_t *sa);
void close_address_cache(address_cache_t *cache);
#endif

194
src/autoconnect.c Normal file
View file

@ -0,0 +1,194 @@
/*
autoconnect.c -- automatic connection establishment
Copyright (C) 2017 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "system.h"
#include "connection.h"
#include "logger.h"
#include "node.h"
#include "xalloc.h"
static void make_new_connection() {
/* Select a random node we haven't connected to yet. */
int count = 0;
for splay_each(node_t, n, node_tree) {
if(n == myself || n->connection || !(n->status.has_address || n->status.reachable)) {
continue;
}
count++;
}
if(!count) {
return;
}
int r = rand() % count;
for splay_each(node_t, n, node_tree) {
if(n == myself || n->connection || !(n->status.has_address || n->status.reachable)) {
continue;
}
if(r--) {
continue;
}
bool found = false;
for list_each(outgoing_t, outgoing, outgoing_list) {
if(outgoing->node == n) {
found = true;
break;
}
}
if(!found) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "Autoconnecting to %s", n->name);
outgoing_t *outgoing = xzalloc(sizeof(*outgoing));
outgoing->node = n;
list_insert_tail(outgoing_list, outgoing);
setup_outgoing_connection(outgoing, false);
}
break;
}
}
static void connect_to_unreachable() {
/* Select a random known node. The rationale is that if there are many
* reachable nodes, and only a few unreachable nodes, we don't want all
* reachable nodes to try to connect to the unreachable ones at the
* same time. This way, we back off automatically. Conversely, if there
* are only a few reachable nodes, and many unreachable ones, we're
* going to try harder to connect to them. */
int r = rand() % node_tree->count;
for splay_each(node_t, n, node_tree) {
if(r--) {
continue;
}
/* Is it unreachable and do we know an address for it? If not, return. */
if(n == myself || n->connection || n->status.reachable || !n->status.has_address) {
return;
}
/* Are we already trying to make an outgoing connection to it? If so, return. */
for list_each(outgoing_t, outgoing, outgoing_list) {
if(outgoing->node == n) {
return;
}
}
logger(DEBUG_CONNECTIONS, LOG_INFO, "Autoconnecting to %s", n->name);
outgoing_t *outgoing = xzalloc(sizeof(*outgoing));
outgoing->node = n;
list_insert_tail(outgoing_list, outgoing);
setup_outgoing_connection(outgoing, false);
return;
}
}
static void drop_superfluous_outgoing_connection() {
/* Choose a random outgoing connection to a node that has at least one other connection. */
int count = 0;
for list_each(connection_t, c, connection_list) {
if(!c->edge || !c->outgoing || !c->node || c->node->edge_tree->count < 2) {
continue;
}
count++;
}
if(!count) {
return;
}
int r = rand() % count;
for list_each(connection_t, c, connection_list) {
if(!c->edge || !c->outgoing || !c->node || c->node->edge_tree->count < 2) {
continue;
}
if(r--) {
continue;
}
logger(DEBUG_CONNECTIONS, LOG_INFO, "Autodisconnecting from %s", c->name);
list_delete(outgoing_list, c->outgoing);
c->outgoing = NULL;
terminate_connection(c, c->edge);
break;
}
}
static void drop_superfluous_pending_connections() {
for list_each(outgoing_t, o, outgoing_list) {
/* Only look for connections that are waiting to be retried later. */
bool found = false;
for list_each(connection_t, c, connection_list) {
if(c->outgoing == o) {
found = true;
break;
}
}
if(found) {
continue;
}
logger(DEBUG_CONNECTIONS, LOG_INFO, "Cancelled outgoing connection to %s", o->node->name);
list_delete_node(outgoing_list, node);
}
}
void do_autoconnect() {
/* Count number of active connections. */
int nc = 0;
for list_each(connection_t, c, connection_list) {
if(c->edge) {
nc++;
}
}
/* Less than 3 connections? Eagerly try to make a new one. */
if(nc < 3) {
make_new_connection();
return;
}
/* More than 3 connections? See if we can get rid of a superfluous one. */
if(nc > 3) {
drop_superfluous_outgoing_connection();
}
/* Drop pending outgoing connections from the outgoing list. */
drop_superfluous_pending_connections();
/* Check if there are unreachable nodes that we should try to connect to. */
connect_to_unreachable();
}

25
src/autoconnect.h Normal file
View file

@ -0,0 +1,25 @@
#ifndef TINC_AUTOCONNECT_H
#define TINC_AUTOCONNECT_H
/*
autoconnect.h -- header for autoconnect.c
Copyright (C) 2017 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
extern void do_autoconnect(void);
#endif

View file

@ -1,757 +0,0 @@
/*
avl_tree.c -- avl_ tree and linked list convenience
Copyright (C) 1998 Michael H. Buselli
2000-2005 Ivo Timmermans,
2000-2015 Guus Sliepen <guus@tinc-vpn.org>
2000-2005 Wessel Dankers <wsl@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.
Original AVL tree library by Michael H. Buselli <cosine@cosine.org>.
Modified 2000-11-28 by Wessel Dankers <wsl@tinc-vpn.org> to use counts
instead of depths, to add the ->next and ->prev and to generally obfuscate
the code. Mail me if you found a bug.
Cleaned up and incorporated some of the ideas from the red-black tree
library for inclusion into tinc (https://www.tinc-vpn.org/) by
Guus Sliepen <guus@tinc-vpn.org>.
*/
#include "system.h"
#include "avl_tree.h"
#include "xalloc.h"
#ifdef AVL_COUNT
#define AVL_NODE_COUNT(n) ((n) ? (n)->count : 0)
#define AVL_L_COUNT(n) (AVL_NODE_COUNT((n)->left))
#define AVL_R_COUNT(n) (AVL_NODE_COUNT((n)->right))
#define AVL_CALC_COUNT(n) (AVL_L_COUNT(n) + AVL_R_COUNT(n) + 1)
#endif
#ifdef AVL_DEPTH
#define AVL_NODE_DEPTH(n) ((n) ? (n)->depth : 0)
#define L_AVL_DEPTH(n) (AVL_NODE_DEPTH((n)->left))
#define R_AVL_DEPTH(n) (AVL_NODE_DEPTH((n)->right))
#define AVL_CALC_DEPTH(n) ((L_AVL_DEPTH(n)>R_AVL_DEPTH(n)?L_AVL_DEPTH(n):R_AVL_DEPTH(n)) + 1)
#endif
#ifndef AVL_DEPTH
static int lg(unsigned int u) __attribute__((__const__));
static int lg(unsigned int u) {
int r = 1;
if(!u) {
return 0;
}
if(u & 0xffff0000) {
u >>= 16;
r += 16;
}
if(u & 0x0000ff00) {
u >>= 8;
r += 8;
}
if(u & 0x000000f0) {
u >>= 4;
r += 4;
}
if(u & 0x0000000c) {
u >>= 2;
r += 2;
}
if(u & 0x00000002) {
r++;
}
return r;
}
#endif
/* Internal helper functions */
static int avl_check_balance(const avl_node_t *node) {
#ifdef AVL_DEPTH
int d;
d = R_AVL_DEPTH(node) - L_AVL_DEPTH(node);
return d < -1 ? -1 : d > 1 ? 1 : 0;
#else
/* int d;
* d = lg(AVL_R_COUNT(node)) - lg(AVL_L_COUNT(node));
* d = d<-1?-1:d>1?1:0;
*/
int pl, r;
pl = lg(AVL_L_COUNT(node));
r = AVL_R_COUNT(node);
if(r >> pl + 1) {
return 1;
}
if(pl < 2 || r >> pl - 2) {
return 0;
}
return -1;
#endif
}
static void avl_rebalance(avl_tree_t *tree, avl_node_t *node) {
avl_node_t *child;
avl_node_t *gchild;
avl_node_t *parent;
avl_node_t **superparent;
while(node) {
parent = node->parent;
superparent =
parent ? node ==
parent->left ? &parent->left : &parent->right : &tree->root;
switch(avl_check_balance(node)) {
case -1:
child = node->left;
#ifdef AVL_DEPTH
if(L_AVL_DEPTH(child) >= R_AVL_DEPTH(child)) {
#else
if(AVL_L_COUNT(child) >= AVL_R_COUNT(child)) {
#endif
node->left = child->right;
if(node->left) {
node->left->parent = node;
}
child->right = node;
node->parent = child;
*superparent = child;
child->parent = parent;
#ifdef AVL_COUNT
node->count = AVL_CALC_COUNT(node);
child->count = AVL_CALC_COUNT(child);
#endif
#ifdef AVL_DEPTH
node->depth = AVL_CALC_DEPTH(node);
child->depth = AVL_CALC_DEPTH(child);
#endif
} else {
gchild = child->right;
node->left = gchild->right;
if(node->left) {
node->left->parent = node;
}
child->right = gchild->left;
if(child->right) {
child->right->parent = child;
}
gchild->right = node;
gchild->right->parent = gchild;
gchild->left = child;
gchild->left->parent = gchild;
*superparent = gchild;
gchild->parent = parent;
#ifdef AVL_COUNT
node->count = AVL_CALC_COUNT(node);
child->count = AVL_CALC_COUNT(child);
gchild->count = AVL_CALC_COUNT(gchild);
#endif
#ifdef AVL_DEPTH
node->depth = AVL_CALC_DEPTH(node);
child->depth = AVL_CALC_DEPTH(child);
gchild->depth = AVL_CALC_DEPTH(gchild);
#endif
}
break;
case 1:
child = node->right;
#ifdef AVL_DEPTH
if(R_AVL_DEPTH(child) >= L_AVL_DEPTH(child)) {
#else
if(AVL_R_COUNT(child) >= AVL_L_COUNT(child)) {
#endif
node->right = child->left;
if(node->right) {
node->right->parent = node;
}
child->left = node;
node->parent = child;
*superparent = child;
child->parent = parent;
#ifdef AVL_COUNT
node->count = AVL_CALC_COUNT(node);
child->count = AVL_CALC_COUNT(child);
#endif
#ifdef AVL_DEPTH
node->depth = AVL_CALC_DEPTH(node);
child->depth = AVL_CALC_DEPTH(child);
#endif
} else {
gchild = child->left;
node->right = gchild->left;
if(node->right) {
node->right->parent = node;
}
child->left = gchild->right;
if(child->left) {
child->left->parent = child;
}
gchild->left = node;
gchild->left->parent = gchild;
gchild->right = child;
gchild->right->parent = gchild;
*superparent = gchild;
gchild->parent = parent;
#ifdef AVL_COUNT
node->count = AVL_CALC_COUNT(node);
child->count = AVL_CALC_COUNT(child);
gchild->count = AVL_CALC_COUNT(gchild);
#endif
#ifdef AVL_DEPTH
node->depth = AVL_CALC_DEPTH(node);
child->depth = AVL_CALC_DEPTH(child);
gchild->depth = AVL_CALC_DEPTH(gchild);
#endif
}
break;
default:
#ifdef AVL_COUNT
node->count = AVL_CALC_COUNT(node);
#endif
#ifdef AVL_DEPTH
node->depth = AVL_CALC_DEPTH(node);
#endif
}
node = parent;
}
}
/* (De)constructors */
avl_tree_t *avl_alloc_tree(avl_compare_t compare, avl_action_t delete) {
avl_tree_t *tree;
tree = xmalloc_and_zero(sizeof(avl_tree_t));
tree->compare = compare;
tree->delete = delete;
return tree;
}
void avl_free_tree(avl_tree_t *tree) {
free(tree);
}
avl_node_t *avl_alloc_node(void) {
return xmalloc_and_zero(sizeof(avl_node_t));
}
void avl_free_node(avl_tree_t *tree, avl_node_t *node) {
if(node->data && tree->delete) {
tree->delete(node->data);
}
free(node);
}
/* Searching */
void *avl_search(const avl_tree_t *tree, const void *data) {
avl_node_t *node;
node = avl_search_node(tree, data);
return node ? node->data : NULL;
}
void *avl_search_closest(const avl_tree_t *tree, const void *data, int *result) {
avl_node_t *node;
node = avl_search_closest_node(tree, data, result);
return node ? node->data : NULL;
}
void *avl_search_closest_smaller(const avl_tree_t *tree, const void *data) {
avl_node_t *node;
node = avl_search_closest_smaller_node(tree, data);
return node ? node->data : NULL;
}
void *avl_search_closest_greater(const avl_tree_t *tree, const void *data) {
avl_node_t *node;
node = avl_search_closest_greater_node(tree, data);
return node ? node->data : NULL;
}
avl_node_t *avl_search_node(const avl_tree_t *tree, const void *data) {
avl_node_t *node;
int result;
node = avl_search_closest_node(tree, data, &result);
return result ? NULL : node;
}
avl_node_t *avl_search_closest_node(const avl_tree_t *tree, const void *data,
int *result) {
avl_node_t *node;
int c;
node = tree->root;
if(!node) {
if(result) {
*result = 0;
}
return NULL;
}
for(;;) {
c = tree->compare(data, node->data);
if(c < 0) {
if(node->left) {
node = node->left;
} else {
if(result) {
*result = -1;
}
break;
}
} else if(c > 0) {
if(node->right) {
node = node->right;
} else {
if(result) {
*result = 1;
}
break;
}
} else {
if(result) {
*result = 0;
}
break;
}
}
return node;
}
avl_node_t *avl_search_closest_smaller_node(const avl_tree_t *tree,
const void *data) {
avl_node_t *node;
int result;
node = avl_search_closest_node(tree, data, &result);
if(result < 0) {
node = node->prev;
}
return node;
}
avl_node_t *avl_search_closest_greater_node(const avl_tree_t *tree,
const void *data) {
avl_node_t *node;
int result;
node = avl_search_closest_node(tree, data, &result);
if(result > 0) {
node = node->next;
}
return node;
}
/* Insertion and deletion */
avl_node_t *avl_insert(avl_tree_t *tree, void *data) {
avl_node_t *closest, *new;
int result;
if(!tree->root) {
new = avl_alloc_node();
new->data = data;
avl_insert_top(tree, new);
} else {
closest = avl_search_closest_node(tree, data, &result);
switch(result) {
case -1:
new = avl_alloc_node();
new->data = data;
avl_insert_before(tree, closest, new);
break;
case 1:
new = avl_alloc_node();
new->data = data;
avl_insert_after(tree, closest, new);
break;
default:
return NULL;
}
}
#ifdef AVL_COUNT
new->count = 1;
#endif
#ifdef AVL_DEPTH
new->depth = 1;
#endif
return new;
}
avl_node_t *avl_insert_node(avl_tree_t *tree, avl_node_t *node) {
avl_node_t *closest;
int result;
if(!tree->root) {
avl_insert_top(tree, node);
} else {
closest = avl_search_closest_node(tree, node->data, &result);
switch(result) {
case -1:
avl_insert_before(tree, closest, node);
break;
case 1:
avl_insert_after(tree, closest, node);
break;
case 0:
return NULL;
}
}
#ifdef AVL_COUNT
node->count = 1;
#endif
#ifdef AVL_DEPTH
node->depth = 1;
#endif
return node;
}
void avl_insert_top(avl_tree_t *tree, avl_node_t *node) {
node->prev = node->next = node->parent = NULL;
tree->head = tree->tail = tree->root = node;
}
void avl_insert_before(avl_tree_t *tree, avl_node_t *before,
avl_node_t *node) {
if(!before) {
if(tree->tail) {
avl_insert_after(tree, tree->tail, node);
} else {
avl_insert_top(tree, node);
}
return;
}
node->next = before;
node->parent = before;
node->prev = before->prev;
if(before->left) {
avl_insert_after(tree, before->prev, node);
return;
}
if(before->prev) {
before->prev->next = node;
} else {
tree->head = node;
}
before->prev = node;
before->left = node;
avl_rebalance(tree, before);
}
void avl_insert_after(avl_tree_t *tree, avl_node_t *after, avl_node_t *node) {
if(!after) {
if(tree->head) {
avl_insert_before(tree, tree->head, node);
} else {
avl_insert_top(tree, node);
}
return;
}
if(after->right) {
avl_insert_before(tree, after->next, node);
return;
}
node->prev = after;
node->parent = after;
node->next = after->next;
if(after->next) {
after->next->prev = node;
} else {
tree->tail = node;
}
after->next = node;
after->right = node;
avl_rebalance(tree, after);
}
avl_node_t *avl_unlink(avl_tree_t *tree, void *data) {
avl_node_t *node;
node = avl_search_node(tree, data);
if(node) {
avl_unlink_node(tree, node);
}
return node;
}
void avl_unlink_node(avl_tree_t *tree, avl_node_t *node) {
avl_node_t *parent;
avl_node_t **superparent;
avl_node_t *subst, *left, *right;
avl_node_t *balnode;
if(node->prev) {
node->prev->next = node->next;
} else {
tree->head = node->next;
}
if(node->next) {
node->next->prev = node->prev;
} else {
tree->tail = node->prev;
}
parent = node->parent;
superparent =
parent ? node ==
parent->left ? &parent->left : &parent->right : &tree->root;
left = node->left;
right = node->right;
if(!left) {
*superparent = right;
if(right) {
right->parent = parent;
}
balnode = parent;
} else if(!right) {
*superparent = left;
left->parent = parent;
balnode = parent;
} else {
subst = node->prev;
if(!subst) { // This only happens if node is not actually in a tree at all.
abort();
}
if(subst == left) {
balnode = subst;
} else {
balnode = subst->parent;
balnode->right = subst->left;
if(balnode->right) {
balnode->right->parent = balnode;
}
subst->left = left;
left->parent = subst;
}
subst->right = right;
subst->parent = parent;
right->parent = subst;
*superparent = subst;
}
avl_rebalance(tree, balnode);
node->next = node->prev = node->parent = node->left = node->right = NULL;
#ifdef AVL_COUNT
node->count = 0;
#endif
#ifdef AVL_DEPTH
node->depth = 0;
#endif
}
void avl_delete_node(avl_tree_t *tree, avl_node_t *node) {
avl_unlink_node(tree, node);
avl_free_node(tree, node);
}
void avl_delete(avl_tree_t *tree, void *data) {
avl_node_t *node;
node = avl_search_node(tree, data);
if(node) {
avl_delete_node(tree, node);
}
}
/* Fast tree cleanup */
void avl_delete_tree(avl_tree_t *tree) {
avl_node_t *node, *next;
for(node = tree->head; node; node = next) {
next = node->next;
avl_free_node(tree, node);
}
avl_free_tree(tree);
}
/* Tree walking */
void avl_foreach(const avl_tree_t *tree, avl_action_t action) {
avl_node_t *node, *next;
for(node = tree->head; node; node = next) {
next = node->next;
action(node->data);
}
}
void avl_foreach_node(const avl_tree_t *tree, avl_action_t action) {
avl_node_t *node, *next;
for(node = tree->head; node; node = next) {
next = node->next;
action(node);
}
}
/* Indexing */
#ifdef AVL_COUNT
unsigned int avl_count(const avl_tree_t *tree) {
return AVL_NODE_COUNT(tree->root);
}
avl_node_t *avl_get_node(const avl_tree_t *tree, unsigned int index) {
avl_node_t *node;
unsigned int c;
node = tree->root;
while(node) {
c = AVL_L_COUNT(node);
if(index < c) {
node = node->left;
} else if(index > c) {
node = node->right;
index -= c + 1;
} else {
return node;
}
}
return NULL;
}
unsigned int avl_index(const avl_node_t *node) {
avl_node_t *next;
unsigned int index;
index = AVL_L_COUNT(node);
while((next = node->parent)) {
if(node == next->right) {
index += AVL_L_COUNT(next) + 1;
}
node = next;
}
return index;
}
#endif
#ifdef AVL_DEPTH
unsigned int avl_depth(const avl_tree_t *tree) {
return AVL_NODE_DEPTH(tree->root);
}
#endif

View file

@ -1,142 +0,0 @@
#ifndef TINC_AVL_TREE_H
#define TINC_AVL_TREE_H
/*
avl_tree.h -- header file for avl_tree.c
Copyright (C) 1998 Michael H. Buselli
2000-2005 Ivo Timmermans,
2000-2006 Guus Sliepen <guus@tinc-vpn.org>
2000-2005 Wessel Dankers <wsl@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.
Original AVL tree library by Michael H. Buselli <cosine@cosine.org>.
Modified 2000-11-28 by Wessel Dankers <wsl@tinc-vpn.org> to use counts
instead of depths, to add the ->next and ->prev and to generally obfuscate
the code. Mail me if you found a bug.
Cleaned up and incorporated some of the ideas from the red-black tree
library for inclusion into tinc (https://www.tinc-vpn.org/) by
Guus Sliepen <guus@tinc-vpn.org>.
*/
#ifndef AVL_DEPTH
#ifndef AVL_COUNT
#define AVL_DEPTH
#endif
#endif
typedef struct avl_node_t {
/* Linked list part */
struct avl_node_t *next;
struct avl_node_t *prev;
/* Tree part */
struct avl_node_t *parent;
struct avl_node_t *left;
struct avl_node_t *right;
#ifdef AVL_COUNT
unsigned int count;
#endif
#ifdef AVL_DEPTH
unsigned char depth;
#endif
/* Payload */
void *data;
} avl_node_t;
typedef int (*avl_compare_t)(const void *data1, const void *data2);
typedef void (*avl_action_t)(const void *data);
typedef void (*avl_action_node_t)(const avl_node_t *node);
typedef struct avl_tree_t {
/* Linked list part */
avl_node_t *head;
avl_node_t *tail;
/* Tree part */
avl_node_t *root;
avl_compare_t compare;
avl_action_t delete;
} avl_tree_t;
/* (De)constructors */
extern avl_tree_t *avl_alloc_tree(avl_compare_t compare, avl_action_t delete);
extern void avl_free_tree(avl_tree_t *tree);
extern avl_node_t *avl_alloc_node(void);
extern void avl_free_node(avl_tree_t *tree, avl_node_t *node);
/* Insertion and deletion */
extern avl_node_t *avl_insert(avl_tree_t *tree, void *data);
extern avl_node_t *avl_insert_node(avl_tree_t *tree, avl_node_t *node);
extern void avl_insert_top(avl_tree_t *tree, avl_node_t *node);
extern void avl_insert_before(avl_tree_t *tree, avl_node_t *before, avl_node_t *node);
extern void avl_insert_after(avl_tree_t *tree, avl_node_t *after, avl_node_t *node);
extern avl_node_t *avl_unlink(avl_tree_t *tree, void *data);
extern void avl_unlink_node(avl_tree_t *tree, avl_node_t *node);
extern void avl_delete(avl_tree_t *tree, void *data);
extern void avl_delete_node(avl_tree_t *tree, avl_node_t *node);
/* Fast tree cleanup */
extern void avl_delete_tree(avl_tree_t *tree);
/* Searching */
extern void *avl_search(const avl_tree_t *tree, const void *data);
extern void *avl_search_closest(const avl_tree_t *tree, const void *data, int *result);
extern void *avl_search_closest_smaller(const avl_tree_t *tree, const void *data);
extern void *avl_search_closest_greater(const avl_tree_t *tree, const void *data);
extern avl_node_t *avl_search_node(const avl_tree_t *tree, const void *data);
extern avl_node_t *avl_search_closest_node(const avl_tree_t *tree, const void *data, int *result);
extern avl_node_t *avl_search_closest_smaller_node(const avl_tree_t *tree, const void *data);
extern avl_node_t *avl_search_closest_greater_node(const avl_tree_t *tree, const void *data);
/* Tree walking */
extern void avl_foreach(const avl_tree_t *tree, avl_action_t action);
extern void avl_foreach_node(const avl_tree_t *tree, avl_action_t action);
/* Indexing */
#ifdef AVL_COUNT
extern unsigned int avl_count(const avl_tree_t *tree);
extern avl_node_t *avl_get_node(const avl_tree_t *tree, unsigned int index);
extern unsigned int avl_index(const avl_node_t *node);
#endif
#ifdef AVL_DEPTH
extern unsigned int avl_depth(const avl_tree_t *tree);
#endif
#endif

View file

@ -1,7 +1,7 @@
/* /*
device.c -- Interaction BSD tun/tap device device.c -- Interaction BSD tun/tap device
Copyright (C) 2001-2005 Ivo Timmermans, Copyright (C) 2001-2005 Ivo Timmermans,
2001-2016 Guus Sliepen <guus@tinc-vpn.org> 2001-2021 Guus Sliepen <guus@tinc-vpn.org>
2009 Grzegorz Dymarek <gregd72002@googlemail.com> 2009 Grzegorz Dymarek <gregd72002@googlemail.com>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
@ -24,13 +24,14 @@
#include "../conf.h" #include "../conf.h"
#include "../device.h" #include "../device.h"
#include "../logger.h" #include "../logger.h"
#include "../names.h"
#include "../net.h" #include "../net.h"
#include "../route.h" #include "../route.h"
#include "../utils.h" #include "../utils.h"
#include "../xalloc.h" #include "../xalloc.h"
#ifdef ENABLE_TUNEMU #ifdef ENABLE_TUNEMU
#include "tunemu.h" #include "bsd/tunemu.h"
#endif #endif
#ifdef HAVE_NET_IF_UTUN_H #ifdef HAVE_NET_IF_UTUN_H
@ -39,8 +40,13 @@
#include <net/if_utun.h> #include <net/if_utun.h>
#endif #endif
#if defined(HAVE_FREEBSD) || defined(HAVE_DRAGONFLY)
#define DEFAULT_TUN_DEVICE "/dev/tun" // Use the autoclone device
#define DEFAULT_TAP_DEVICE "/dev/tap"
#else
#define DEFAULT_TUN_DEVICE "/dev/tun0" #define DEFAULT_TUN_DEVICE "/dev/tun0"
#define DEFAULT_TAP_DEVICE "/dev/tap0" #define DEFAULT_TAP_DEVICE "/dev/tap0"
#endif
typedef enum device_type { typedef enum device_type {
DEVICE_TYPE_TUN, DEVICE_TYPE_TUN,
@ -56,8 +62,6 @@ int device_fd = -1;
char *device = NULL; char *device = NULL;
char *iface = NULL; char *iface = NULL;
static const char *device_info = "OS X utun device"; static const char *device_info = "OS X utun device";
static uint64_t device_total_in = 0;
static uint64_t device_total_out = 0;
#if defined(ENABLE_TUNEMU) #if defined(ENABLE_TUNEMU)
static device_type_t device_type = DEVICE_TYPE_TUNEMU; static device_type_t device_type = DEVICE_TYPE_TUNEMU;
#elif defined(HAVE_OPENBSD) || defined(HAVE_FREEBSD) || defined(HAVE_DRAGONFLY) #elif defined(HAVE_OPENBSD) || defined(HAVE_FREEBSD) || defined(HAVE_DRAGONFLY)
@ -71,7 +75,7 @@ static bool setup_utun(void) {
device_fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL); device_fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
if(device_fd == -1) { if(device_fd == -1) {
logger(LOG_ERR, "Could not open PF_SYSTEM socket: %s\n", strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "Could not open PF_SYSTEM socket: %s\n", strerror(errno));
return false; return false;
} }
@ -80,7 +84,7 @@ static bool setup_utun(void) {
strlcpy(info.ctl_name, UTUN_CONTROL_NAME, sizeof(info.ctl_name)); strlcpy(info.ctl_name, UTUN_CONTROL_NAME, sizeof(info.ctl_name));
if(ioctl(device_fd, CTLIOCGINFO, &info) == -1) { if(ioctl(device_fd, CTLIOCGINFO, &info) == -1) {
logger(LOG_ERR, "ioctl(CTLIOCGINFO) failed: %s", strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "ioctl(CTLIOCGINFO) failed: %s", strerror(errno));
return false; return false;
} }
@ -104,7 +108,7 @@ static bool setup_utun(void) {
}; };
if(connect(device_fd, (struct sockaddr *)&sc, sizeof(sc)) == -1) { if(connect(device_fd, (struct sockaddr *)&sc, sizeof(sc)) == -1) {
logger(LOG_ERR, "Could not connect utun socket: %s\n", strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "Could not connect utun socket: %s\n", strerror(errno));
return false; return false;
} }
@ -117,22 +121,14 @@ static bool setup_utun(void) {
iface = xstrdup(name); iface = xstrdup(name);
} }
logger(LOG_INFO, "%s is a %s", device, device_info); logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
return true; return true;
} }
#endif #endif
static bool setup_device(void) { static bool setup_device(void) {
// Find out which device file to open get_config_string(lookup_config(config_tree, "Device"), &device);
if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
if(routing_mode == RMODE_ROUTER) {
device = xstrdup(DEFAULT_TUN_DEVICE);
} else {
device = xstrdup(DEFAULT_TAP_DEVICE);
}
}
// Find out if it's supposed to be a tun or a tap device // Find out if it's supposed to be a tun or a tap device
@ -161,26 +157,36 @@ static bool setup_device(void) {
} else if(!strcasecmp(type, "tap")) { } else if(!strcasecmp(type, "tap")) {
device_type = DEVICE_TYPE_TAP; device_type = DEVICE_TYPE_TAP;
} else { } else {
logger(LOG_ERR, "Unknown device type %s!", type); logger(DEBUG_ALWAYS, LOG_ERR, "Unknown device type %s!", type);
return false; return false;
} }
} else { } else {
#ifdef HAVE_NET_IF_UTUN_H #ifdef HAVE_NET_IF_UTUN_H
if(strncmp(device, "utun", 4) == 0 || strncmp(device, "/dev/utun", 9) == 0) { if(device && (strncmp(device, "utun", 4) == 0 || strncmp(device, "/dev/utun", 9) == 0)) {
device_type = DEVICE_TYPE_UTUN; device_type = DEVICE_TYPE_UTUN;
} else } else
#endif #endif
if(strstr(device, "tap") || routing_mode != RMODE_ROUTER) { if((device && strstr(device, "tap")) || routing_mode != RMODE_ROUTER) {
device_type = DEVICE_TYPE_TAP; device_type = DEVICE_TYPE_TAP;
} }
} }
if(routing_mode == RMODE_SWITCH && device_type != DEVICE_TYPE_TAP) { if(routing_mode == RMODE_SWITCH && device_type != DEVICE_TYPE_TAP) {
logger(LOG_ERR, "Only tap devices support switch mode!"); logger(DEBUG_ALWAYS, LOG_ERR, "Only tap devices support switch mode!");
return false; return false;
} }
// Find out which device file to open
if(!device) {
if(device_type == DEVICE_TYPE_TAP) {
device = xstrdup(DEFAULT_TAP_DEVICE);
} else {
device = xstrdup(DEFAULT_TUN_DEVICE);
}
}
// Open the device // Open the device
switch(device_type) { switch(device_type) {
@ -203,7 +209,7 @@ static bool setup_device(void) {
} }
if(device_fd < 0) { if(device_fd < 0) {
logger(LOG_ERR, "Could not open %s: %s", device, strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", device, strerror(errno));
return false; return false;
} }
@ -233,7 +239,7 @@ static bool setup_device(void) {
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) { if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) {
iface = xstrdup(strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname); iface = xstrdup(strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname);
} else if(strcmp(iface, strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname)) { } else if(strcmp(iface, strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname)) {
logger(LOG_WARNING, "Warning: Interface does not match Device. $INTERFACE might be set incorrectly."); logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: Interface does not match Device. $INTERFACE might be set incorrectly.");
} }
// Configure the device as best as we can // Configure the device as best as we can
@ -248,7 +254,7 @@ static bool setup_device(void) {
const int zero = 0; const int zero = 0;
if(ioctl(device_fd, TUNSIFHEAD, &zero, sizeof(zero)) == -1) { if(ioctl(device_fd, TUNSIFHEAD, &zero, sizeof(zero)) == -1) {
logger(LOG_ERR, "System call `%s' failed: %s", "ioctl", strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "ioctl", strerror(errno));
return false; return false;
} }
} }
@ -270,7 +276,7 @@ static bool setup_device(void) {
const int one = 1; const int one = 1;
if(ioctl(device_fd, TUNSIFHEAD, &one, sizeof(one)) == -1) { if(ioctl(device_fd, TUNSIFHEAD, &one, sizeof(one)) == -1) {
logger(LOG_ERR, "System call `%s' failed: %s", "ioctl", strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "ioctl", strerror(errno));
return false; return false;
} }
} }
@ -297,10 +303,7 @@ static bool setup_device(void) {
struct ifreq ifr; struct ifreq ifr;
if(ioctl(device_fd, TAPGIFNAME, (void *)&ifr) == 0) { if(ioctl(device_fd, TAPGIFNAME, (void *)&ifr) == 0) {
if(iface) { free(iface);
free(iface);
}
iface = xstrdup(ifr.ifr_name); iface = xstrdup(ifr.ifr_name);
} }
} }
@ -323,7 +326,7 @@ static bool setup_device(void) {
#endif #endif
logger(LOG_INFO, "%s is a %s", device, device_info); logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
return true; return true;
} }
@ -341,112 +344,115 @@ static void close_device(void) {
close(device_fd); close(device_fd);
} }
device_fd = -1;
free(device); free(device);
device = NULL;
free(iface); free(iface);
iface = NULL;
device_info = NULL;
} }
static bool read_packet(vpn_packet_t *packet) { static bool read_packet(vpn_packet_t *packet) {
int lenin; int inlen;
switch(device_type) { switch(device_type) {
case DEVICE_TYPE_TUN: case DEVICE_TYPE_TUN:
#ifdef ENABLE_TUNEMU #ifdef ENABLE_TUNEMU
case DEVICE_TYPE_TUNEMU: case DEVICE_TYPE_TUNEMU:
if(device_type == DEVICE_TYPE_TUNEMU) { if(device_type == DEVICE_TYPE_TUNEMU) {
lenin = tunemu_read(device_fd, packet->data + 14, MTU - 14); inlen = tunemu_read(device_fd, DATA(packet) + 14, MTU - 14);
} else } else
#endif #endif
lenin = read(device_fd, packet->data + 14, MTU - 14); inlen = read(device_fd, DATA(packet) + 14, MTU - 14);
if(lenin <= 0) { if(inlen <= 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno)); device, strerror(errno));
return false; return false;
} }
switch(packet->data[14] >> 4) { switch(DATA(packet)[14] >> 4) {
case 4: case 4:
packet->data[12] = 0x08; DATA(packet)[12] = 0x08;
packet->data[13] = 0x00; DATA(packet)[13] = 0x00;
break; break;
case 6: case 6:
packet->data[12] = 0x86; DATA(packet)[12] = 0x86;
packet->data[13] = 0xDD; DATA(packet)[13] = 0xDD;
break; break;
default: default:
ifdebug(TRAFFIC) logger(LOG_ERR, logger(DEBUG_TRAFFIC, LOG_ERR,
"Unknown IP version %d while reading packet from %s %s", "Unknown IP version %d while reading packet from %s %s",
packet->data[14] >> 4, device_info, device); DATA(packet)[14] >> 4, device_info, device);
return false; return false;
} }
memset(packet->data, 0, 12); memset(DATA(packet), 0, 12);
packet->len = lenin + 14; packet->len = inlen + 14;
break; break;
case DEVICE_TYPE_UTUN: case DEVICE_TYPE_UTUN:
case DEVICE_TYPE_TUNIFHEAD: { case DEVICE_TYPE_TUNIFHEAD: {
if((lenin = read(device_fd, packet->data + 10, MTU - 10)) <= 0) { if((inlen = read(device_fd, DATA(packet) + 10, MTU - 10)) <= 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno)); device, strerror(errno));
return false; return false;
} }
switch(packet->data[14] >> 4) { switch(DATA(packet)[14] >> 4) {
case 4: case 4:
packet->data[12] = 0x08; DATA(packet)[12] = 0x08;
packet->data[13] = 0x00; DATA(packet)[13] = 0x00;
break; break;
case 6: case 6:
packet->data[12] = 0x86; DATA(packet)[12] = 0x86;
packet->data[13] = 0xDD; DATA(packet)[13] = 0xDD;
break; break;
default: default:
ifdebug(TRAFFIC) logger(LOG_ERR, logger(DEBUG_TRAFFIC, LOG_ERR,
"Unknown IP version %d while reading packet from %s %s", "Unknown IP version %d while reading packet from %s %s",
packet->data[14] >> 4, device_info, device); DATA(packet)[14] >> 4, device_info, device);
return false; return false;
} }
memset(packet->data, 0, 12); memset(DATA(packet), 0, 12);
packet->len = lenin + 10; packet->len = inlen + 10;
break; break;
} }
case DEVICE_TYPE_TAP: case DEVICE_TYPE_TAP:
if((lenin = read(device_fd, packet->data, MTU)) <= 0) { if((inlen = read(device_fd, DATA(packet), MTU)) <= 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno)); device, strerror(errno));
return false; return false;
} }
packet->len = lenin; packet->len = inlen;
break; break;
default: default:
return false; return false;
} }
device_total_in += packet->len; logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s",
packet->len, device_info);
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s",
packet->len, device_info);
return true; return true;
} }
static bool write_packet(vpn_packet_t *packet) { static bool write_packet(vpn_packet_t *packet) {
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s", logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s",
packet->len, device_info); packet->len, device_info);
switch(device_type) { switch(device_type) {
case DEVICE_TYPE_TUN: case DEVICE_TYPE_TUN:
if(write(device_fd, packet->data + 14, packet->len - 14) < 0) { if(write(device_fd, DATA(packet) + 14, packet->len - 14) < 0) {
logger(LOG_ERR, "Error while writing to %s %s: %s", device_info, logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info,
device, strerror(errno)); device, strerror(errno));
return false; return false;
} }
@ -455,7 +461,7 @@ static bool write_packet(vpn_packet_t *packet) {
case DEVICE_TYPE_UTUN: case DEVICE_TYPE_UTUN:
case DEVICE_TYPE_TUNIFHEAD: { case DEVICE_TYPE_TUNIFHEAD: {
int af = (packet->data[12] << 8) + packet->data[13]; int af = (DATA(packet)[12] << 8) + DATA(packet)[13];
uint32_t type; uint32_t type;
switch(af) { switch(af) {
@ -468,16 +474,16 @@ static bool write_packet(vpn_packet_t *packet) {
break; break;
default: default:
ifdebug(TRAFFIC) logger(LOG_ERR, logger(DEBUG_TRAFFIC, LOG_ERR,
"Unknown address family %x while writing packet to %s %s", "Unknown address family %x while writing packet to %s %s",
af, device_info, device); af, device_info, device);
return false; return false;
} }
memcpy(packet->data + 10, &type, sizeof(type)); memcpy(DATA(packet) + 10, &type, sizeof(type));
if(write(device_fd, packet->data + 10, packet->len - 10) < 0) { if(write(device_fd, DATA(packet) + 10, packet->len - 10) < 0) {
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
strerror(errno)); strerror(errno));
return false; return false;
} }
@ -486,8 +492,8 @@ static bool write_packet(vpn_packet_t *packet) {
} }
case DEVICE_TYPE_TAP: case DEVICE_TYPE_TAP:
if(write(device_fd, packet->data, packet->len) < 0) { if(write(device_fd, DATA(packet), packet->len) < 0) {
logger(LOG_ERR, "Error while writing to %s %s: %s", device_info, logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info,
device, strerror(errno)); device, strerror(errno));
return false; return false;
} }
@ -497,8 +503,8 @@ static bool write_packet(vpn_packet_t *packet) {
#ifdef ENABLE_TUNEMU #ifdef ENABLE_TUNEMU
case DEVICE_TYPE_TUNEMU: case DEVICE_TYPE_TUNEMU:
if(tunemu_write(device_fd, packet->data + 14, packet->len - 14) < 0) { if(tunemu_write(device_fd, DATA(packet) + 14, packet->len - 14) < 0) {
logger(LOG_ERR, "Error while writing to %s %s: %s", device_info, logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info,
device, strerror(errno)); device, strerror(errno));
return false; return false;
} }
@ -510,21 +516,12 @@ static bool write_packet(vpn_packet_t *packet) {
return false; return false;
} }
device_total_out += packet->len;
return true; return true;
} }
static void dump_device_stats(void) {
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
}
const devops_t os_devops = { const devops_t os_devops = {
.setup = setup_device, .setup = setup_device,
.close = close_device, .close = close_device,
.read = read_packet, .read = read_packet,
.write = write_packet, .write = write_packet,
.dump_stats = dump_device_stats,
}; };

View file

@ -45,9 +45,9 @@
#define PPPIOCSFLAGS _IOW('t', 89, int) #define PPPIOCSFLAGS _IOW('t', 89, int)
#define PPPIOCSNPMODE _IOW('t', 75, struct npioctl) #define PPPIOCSNPMODE _IOW('t', 75, struct npioctl)
#define PPPIOCATTCHAN _IOW('t', 56, int) #define PPPIOCATTCHAN _IOW('t', 56, int)
#define PPPIOCGCHAN _IOR('t', 55, int) #define PPPIOCGCHAN _IOR('t', 55, int)
#define PPPIOCCONNECT _IOW('t', 58, int) #define PPPIOCCONNECT _IOW('t', 58, int)
#define PPPIOCGUNIT _IOR('t', 86, int) #define PPPIOCGUNIT _IOR('t', 86, int)
struct sockaddr_ppp { struct sockaddr_ppp {
u_int8_t ppp_len; u_int8_t ppp_len;
@ -83,7 +83,7 @@ static char *data_buffer = NULL;
static void tun_error(char *format, ...) { static void tun_error(char *format, ...) {
va_list vl; va_list vl;
va_start(vl, format); va_start(vl, format);
vsnprintf(tunemu_error, ERROR_BUFFER_SIZE, format, vl); vsnprintf(tunemu_error, sizeof(tunemu_error), format, vl);
va_end(vl); va_end(vl);
} }

110
src/buffer.c Normal file
View file

@ -0,0 +1,110 @@
/*
buffer.c -- buffer management
Copyright (C) 2011 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 "buffer.h"
#include "xalloc.h"
void buffer_compact(buffer_t *buffer, uint32_t maxsize) {
if(buffer->len >= maxsize || buffer->offset / 7 > buffer->len / 8) {
memmove(buffer->data, buffer->data + buffer->offset, buffer->len - buffer->offset);
buffer->len -= buffer->offset;
buffer->offset = 0;
}
}
// Make sure we can add size bytes to the buffer, and return a pointer to the start of those bytes.
char *buffer_prepare(buffer_t *buffer, uint32_t size) {
if(!buffer->data) {
buffer->maxlen = size;
buffer->data = xmalloc(size);
} else {
if(buffer->offset && buffer->len + size > buffer->maxlen) {
memmove(buffer->data, buffer->data + buffer->offset, buffer->len - buffer->offset);
buffer->len -= buffer->offset;
buffer->offset = 0;
}
if(buffer->len + size > buffer->maxlen) {
buffer->maxlen = buffer->len + size;
buffer->data = xrealloc(buffer->data, buffer->maxlen);
}
}
char *start = buffer->data + buffer->len;
buffer->len += size;
return start;
}
// Copy data into the buffer.
void buffer_add(buffer_t *buffer, const char *data, uint32_t size) {
memcpy(buffer_prepare(buffer, size), data, size);
}
// Remove given number of bytes from the buffer, return a pointer to the start of them.
static char *buffer_consume(buffer_t *buffer, uint32_t size) {
char *start = buffer->data + buffer->offset;
buffer->offset += size;
if(buffer->offset >= buffer->len) {
buffer->offset = 0;
buffer->len = 0;
}
return start;
}
// Check if there is a complete line in the buffer, and if so, return it NULL-terminated.
char *buffer_readline(buffer_t *buffer) {
char *newline = memchr(buffer->data + buffer->offset, '\n', buffer->len - buffer->offset);
if(!newline) {
return NULL;
}
uint32_t len = newline + 1 - (buffer->data + buffer->offset);
*newline = 0;
return buffer_consume(buffer, len);
}
// Check if we have enough bytes in the buffer, and if so, return a pointer to the start of them.
char *buffer_read(buffer_t *buffer, uint32_t size) {
if(buffer->len - buffer->offset < size) {
return NULL;
}
return buffer_consume(buffer, size);
}
void buffer_clear(buffer_t *buffer) {
free(buffer->data);
buffer->data = NULL;
buffer->maxlen = 0;
buffer->len = 0;
buffer->offset = 0;
}

18
src/buffer.h Normal file
View file

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

View file

@ -0,0 +1,106 @@
#include "../system.h"
#include "../cipher.h"
#include "../xalloc.h"
#include "chacha.h"
#include "chacha-poly1305.h"
#include "poly1305.h"
struct chacha_poly1305_ctx {
struct chacha_ctx main_ctx, header_ctx;
};
chacha_poly1305_ctx_t *chacha_poly1305_init(void) {
chacha_poly1305_ctx_t *ctx = xzalloc(sizeof(*ctx));
return ctx;
}
void chacha_poly1305_exit(chacha_poly1305_ctx_t *ctx) {
free(ctx);
}
bool chacha_poly1305_set_key(chacha_poly1305_ctx_t *ctx, const void *vkey) {
const uint8_t *key = vkey;
chacha_keysetup(&ctx->main_ctx, key, 256);
chacha_keysetup(&ctx->header_ctx, key + 32, 256);
return true;
}
static void put_u64(void *vp, uint64_t v) {
uint8_t *p = (uint8_t *) vp;
p[0] = (uint8_t)(v >> 56) & 0xff;
p[1] = (uint8_t)(v >> 48) & 0xff;
p[2] = (uint8_t)(v >> 40) & 0xff;
p[3] = (uint8_t)(v >> 32) & 0xff;
p[4] = (uint8_t)(v >> 24) & 0xff;
p[5] = (uint8_t)(v >> 16) & 0xff;
p[6] = (uint8_t)(v >> 8) & 0xff;
p[7] = (uint8_t) v & 0xff;
}
bool chacha_poly1305_encrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen, void *voutdata, size_t *outlen) {
uint8_t seqbuf[8];
const uint8_t one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */
uint8_t poly_key[POLY1305_KEYLEN];
uint8_t *outdata = voutdata;
/*
* Run ChaCha20 once to generate the Poly1305 key. The IV is the
* packet sequence number.
*/
memset(poly_key, 0, sizeof(poly_key));
put_u64(seqbuf, seqnr);
chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL);
chacha_encrypt_bytes(&ctx->main_ctx, poly_key, poly_key, sizeof(poly_key));
/* Set Chacha's block counter to 1 */
chacha_ivsetup(&ctx->main_ctx, seqbuf, one);
chacha_encrypt_bytes(&ctx->main_ctx, indata, outdata, inlen);
poly1305_auth(outdata + inlen, outdata, inlen, poly_key);
if(outlen) {
*outlen = inlen + POLY1305_TAGLEN;
}
return true;
}
bool chacha_poly1305_decrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *vindata, size_t inlen, void *outdata, size_t *outlen) {
uint8_t seqbuf[8];
const uint8_t one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */
uint8_t expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN];
const uint8_t *indata = vindata;
/*
* Run ChaCha20 once to generate the Poly1305 key. The IV is the
* packet sequence number.
*/
memset(poly_key, 0, sizeof(poly_key));
put_u64(seqbuf, seqnr);
chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL);
chacha_encrypt_bytes(&ctx->main_ctx, poly_key, poly_key, sizeof(poly_key));
/* Set Chacha's block counter to 1 */
chacha_ivsetup(&ctx->main_ctx, seqbuf, one);
/* Check tag before anything else */
inlen -= POLY1305_TAGLEN;
const uint8_t *tag = indata + inlen;
poly1305_auth(expected_tag, indata, inlen, poly_key);
if(memcmp(expected_tag, tag, POLY1305_TAGLEN)) {
return false;
}
chacha_encrypt_bytes(&ctx->main_ctx, indata, outdata, inlen);
if(outlen) {
*outlen = inlen;
}
return true;
}

View file

@ -0,0 +1,15 @@
#ifndef CHACHA_POLY1305_H
#define CHACHA_POLY1305_H
#define CHACHA_POLY1305_KEYLEN 64
typedef struct chacha_poly1305_ctx chacha_poly1305_ctx_t;
extern chacha_poly1305_ctx_t *chacha_poly1305_init(void);
extern void chacha_poly1305_exit(chacha_poly1305_ctx_t *);
extern bool chacha_poly1305_set_key(chacha_poly1305_ctx_t *ctx, const void *key);
extern bool chacha_poly1305_encrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen, void *outdata, size_t *outlen);
extern bool chacha_poly1305_decrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen, void *outdata, size_t *outlen);
#endif //CHACHA_POLY1305_H

View file

@ -0,0 +1,224 @@
/*
chacha-merged.c version 20080118
D. J. Bernstein
Public domain.
*/
#include "../system.h"
#include "chacha.h"
typedef struct chacha_ctx chacha_ctx;
#define U8C(v) (v##U)
#define U32C(v) (v##U)
#define U8V(v) ((uint8_t)(v) & U8C(0xFF))
#define U32V(v) ((uint32_t)(v) & U32C(0xFFFFFFFF))
#define ROTL32(v, n) \
(U32V((v) << (n)) | ((v) >> (32 - (n))))
#define U8TO32_LITTLE(p) \
(((uint32_t)((p)[0]) ) | \
((uint32_t)((p)[1]) << 8) | \
((uint32_t)((p)[2]) << 16) | \
((uint32_t)((p)[3]) << 24))
#define U32TO8_LITTLE(p, v) \
do { \
(p)[0] = U8V((v) ); \
(p)[1] = U8V((v) >> 8); \
(p)[2] = U8V((v) >> 16); \
(p)[3] = U8V((v) >> 24); \
} while (0)
#define ROTATE(v,c) (ROTL32(v,c))
#define XOR(v,w) ((v) ^ (w))
#define PLUS(v,w) (U32V((v) + (w)))
#define PLUSONE(v) (PLUS((v),1))
#define QUARTERROUND(a,b,c,d) \
a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
static const char sigma[16] = "expand 32-byte k";
static const char tau[16] = "expand 16-byte k";
void chacha_keysetup(chacha_ctx *x, const uint8_t *k, uint32_t kbits) {
const char *constants;
x->input[4] = U8TO32_LITTLE(k + 0);
x->input[5] = U8TO32_LITTLE(k + 4);
x->input[6] = U8TO32_LITTLE(k + 8);
x->input[7] = U8TO32_LITTLE(k + 12);
if(kbits == 256) { /* recommended */
k += 16;
constants = sigma;
} else { /* kbits == 128 */
constants = tau;
}
x->input[8] = U8TO32_LITTLE(k + 0);
x->input[9] = U8TO32_LITTLE(k + 4);
x->input[10] = U8TO32_LITTLE(k + 8);
x->input[11] = U8TO32_LITTLE(k + 12);
x->input[0] = U8TO32_LITTLE(constants + 0);
x->input[1] = U8TO32_LITTLE(constants + 4);
x->input[2] = U8TO32_LITTLE(constants + 8);
x->input[3] = U8TO32_LITTLE(constants + 12);
}
void chacha_ivsetup(chacha_ctx *x, const uint8_t *iv, const uint8_t *counter) {
x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0);
x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4);
x->input[14] = U8TO32_LITTLE(iv + 0);
x->input[15] = U8TO32_LITTLE(iv + 4);
}
void
chacha_encrypt_bytes(chacha_ctx *x, const uint8_t *m, uint8_t *c, uint32_t bytes) {
uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
uint8_t *ctarget = NULL;
uint8_t tmp[64];
uint32_t i;
if(!bytes) {
return;
}
j0 = x->input[0];
j1 = x->input[1];
j2 = x->input[2];
j3 = x->input[3];
j4 = x->input[4];
j5 = x->input[5];
j6 = x->input[6];
j7 = x->input[7];
j8 = x->input[8];
j9 = x->input[9];
j10 = x->input[10];
j11 = x->input[11];
j12 = x->input[12];
j13 = x->input[13];
j14 = x->input[14];
j15 = x->input[15];
for(;;) {
if(bytes < 64) {
for(i = 0; i < bytes; ++i) {
tmp[i] = m[i];
}
m = tmp;
ctarget = c;
c = tmp;
}
x0 = j0;
x1 = j1;
x2 = j2;
x3 = j3;
x4 = j4;
x5 = j5;
x6 = j6;
x7 = j7;
x8 = j8;
x9 = j9;
x10 = j10;
x11 = j11;
x12 = j12;
x13 = j13;
x14 = j14;
x15 = j15;
for(i = 20; i > 0; i -= 2) {
QUARTERROUND(x0, x4, x8, x12)
QUARTERROUND(x1, x5, x9, x13)
QUARTERROUND(x2, x6, x10, x14)
QUARTERROUND(x3, x7, x11, x15)
QUARTERROUND(x0, x5, x10, x15)
QUARTERROUND(x1, x6, x11, x12)
QUARTERROUND(x2, x7, x8, x13)
QUARTERROUND(x3, x4, x9, x14)
}
x0 = PLUS(x0, j0);
x1 = PLUS(x1, j1);
x2 = PLUS(x2, j2);
x3 = PLUS(x3, j3);
x4 = PLUS(x4, j4);
x5 = PLUS(x5, j5);
x6 = PLUS(x6, j6);
x7 = PLUS(x7, j7);
x8 = PLUS(x8, j8);
x9 = PLUS(x9, j9);
x10 = PLUS(x10, j10);
x11 = PLUS(x11, j11);
x12 = PLUS(x12, j12);
x13 = PLUS(x13, j13);
x14 = PLUS(x14, j14);
x15 = PLUS(x15, j15);
x0 = XOR(x0, U8TO32_LITTLE(m + 0));
x1 = XOR(x1, U8TO32_LITTLE(m + 4));
x2 = XOR(x2, U8TO32_LITTLE(m + 8));
x3 = XOR(x3, U8TO32_LITTLE(m + 12));
x4 = XOR(x4, U8TO32_LITTLE(m + 16));
x5 = XOR(x5, U8TO32_LITTLE(m + 20));
x6 = XOR(x6, U8TO32_LITTLE(m + 24));
x7 = XOR(x7, U8TO32_LITTLE(m + 28));
x8 = XOR(x8, U8TO32_LITTLE(m + 32));
x9 = XOR(x9, U8TO32_LITTLE(m + 36));
x10 = XOR(x10, U8TO32_LITTLE(m + 40));
x11 = XOR(x11, U8TO32_LITTLE(m + 44));
x12 = XOR(x12, U8TO32_LITTLE(m + 48));
x13 = XOR(x13, U8TO32_LITTLE(m + 52));
x14 = XOR(x14, U8TO32_LITTLE(m + 56));
x15 = XOR(x15, U8TO32_LITTLE(m + 60));
j12 = PLUSONE(j12);
if(!j12) {
j13 = PLUSONE(j13);
/* stopping at 2^70 bytes per nonce is user's responsibility */
}
U32TO8_LITTLE(c + 0, x0);
U32TO8_LITTLE(c + 4, x1);
U32TO8_LITTLE(c + 8, x2);
U32TO8_LITTLE(c + 12, x3);
U32TO8_LITTLE(c + 16, x4);
U32TO8_LITTLE(c + 20, x5);
U32TO8_LITTLE(c + 24, x6);
U32TO8_LITTLE(c + 28, x7);
U32TO8_LITTLE(c + 32, x8);
U32TO8_LITTLE(c + 36, x9);
U32TO8_LITTLE(c + 40, x10);
U32TO8_LITTLE(c + 44, x11);
U32TO8_LITTLE(c + 48, x12);
U32TO8_LITTLE(c + 52, x13);
U32TO8_LITTLE(c + 56, x14);
U32TO8_LITTLE(c + 60, x15);
if(bytes <= 64) {
if(bytes < 64) {
for(i = 0; i < bytes; ++i) {
ctarget[i] = c[i];
}
}
x->input[12] = j12;
x->input[13] = j13;
return;
}
bytes -= 64;
c += 64;
m += 64;
}
}

View file

@ -0,0 +1,24 @@
/*
chacha-merged.c version 20080118
D. J. Bernstein
Public domain.
*/
#ifndef CHACHA_H
#define CHACHA_H
struct chacha_ctx {
uint32_t input[16];
};
#define CHACHA_MINKEYLEN 16
#define CHACHA_NONCELEN 8
#define CHACHA_CTRLEN 8
#define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN)
#define CHACHA_BLOCKLEN 64
void chacha_keysetup(struct chacha_ctx *x, const uint8_t *k, uint32_t kbits);
void chacha_ivsetup(struct chacha_ctx *x, const uint8_t *iv, const uint8_t *ctr);
void chacha_encrypt_bytes(struct chacha_ctx *x, const uint8_t *m, uint8_t *c, uint32_t bytes);
#endif /* CHACHA_H */

View file

@ -0,0 +1,205 @@
/*
* Public Domain poly1305 from Andrew Moon
* poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna
*/
#include "../system.h"
#include "poly1305.h"
#define mul32x32_64(a,b) ((uint64_t)(a) * (b))
#define U8TO32_LE(p) \
(((uint32_t)((p)[0])) | \
((uint32_t)((p)[1]) << 8) | \
((uint32_t)((p)[2]) << 16) | \
((uint32_t)((p)[3]) << 24))
#define U32TO8_LE(p, v) \
do { \
(p)[0] = (uint8_t)((v)); \
(p)[1] = (uint8_t)((v) >> 8); \
(p)[2] = (uint8_t)((v) >> 16); \
(p)[3] = (uint8_t)((v) >> 24); \
} while (0)
void
poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen, const unsigned char key[POLY1305_KEYLEN]) {
uint32_t t0, t1, t2, t3;
uint32_t h0, h1, h2, h3, h4;
uint32_t r0, r1, r2, r3, r4;
uint32_t s1, s2, s3, s4;
uint32_t b, nb;
size_t j;
uint64_t t[5];
uint64_t f0, f1, f2, f3;
uint32_t g0, g1, g2, g3, g4;
uint64_t c;
unsigned char mp[16];
/* clamp key */
t0 = U8TO32_LE(key + 0);
t1 = U8TO32_LE(key + 4);
t2 = U8TO32_LE(key + 8);
t3 = U8TO32_LE(key + 12);
/* precompute multipliers */
r0 = t0 & 0x3ffffff;
t0 >>= 26;
t0 |= t1 << 6;
r1 = t0 & 0x3ffff03;
t1 >>= 20;
t1 |= t2 << 12;
r2 = t1 & 0x3ffc0ff;
t2 >>= 14;
t2 |= t3 << 18;
r3 = t2 & 0x3f03fff;
t3 >>= 8;
r4 = t3 & 0x00fffff;
s1 = r1 * 5;
s2 = r2 * 5;
s3 = r3 * 5;
s4 = r4 * 5;
/* init state */
h0 = 0;
h1 = 0;
h2 = 0;
h3 = 0;
h4 = 0;
/* full blocks */
if(inlen < 16) {
goto poly1305_donna_atmost15bytes;
}
poly1305_donna_16bytes:
m += 16;
inlen -= 16;
t0 = U8TO32_LE(m - 16);
t1 = U8TO32_LE(m - 12);
t2 = U8TO32_LE(m - 8);
t3 = U8TO32_LE(m - 4);
h0 += t0 & 0x3ffffff;
h1 += ((((uint64_t) t1 << 32) | t0) >> 26) & 0x3ffffff;
h2 += ((((uint64_t) t2 << 32) | t1) >> 20) & 0x3ffffff;
h3 += ((((uint64_t) t3 << 32) | t2) >> 14) & 0x3ffffff;
h4 += (t3 >> 8) | (1 << 24);
poly1305_donna_mul:
t[0] = mul32x32_64(h0, r0) + mul32x32_64(h1, s4) + mul32x32_64(h2, s3) + mul32x32_64(h3, s2) + mul32x32_64(h4, s1);
t[1] = mul32x32_64(h0, r1) + mul32x32_64(h1, r0) + mul32x32_64(h2, s4) + mul32x32_64(h3, s3) + mul32x32_64(h4, s2);
t[2] = mul32x32_64(h0, r2) + mul32x32_64(h1, r1) + mul32x32_64(h2, r0) + mul32x32_64(h3, s4) + mul32x32_64(h4, s3);
t[3] = mul32x32_64(h0, r3) + mul32x32_64(h1, r2) + mul32x32_64(h2, r1) + mul32x32_64(h3, r0) + mul32x32_64(h4, s4);
t[4] = mul32x32_64(h0, r4) + mul32x32_64(h1, r3) + mul32x32_64(h2, r2) + mul32x32_64(h3, r1) + mul32x32_64(h4, r0);
h0 = (uint32_t) t[0] & 0x3ffffff;
c = (t[0] >> 26);
t[1] += c;
h1 = (uint32_t) t[1] & 0x3ffffff;
b = (uint32_t)(t[1] >> 26);
t[2] += b;
h2 = (uint32_t) t[2] & 0x3ffffff;
b = (uint32_t)(t[2] >> 26);
t[3] += b;
h3 = (uint32_t) t[3] & 0x3ffffff;
b = (uint32_t)(t[3] >> 26);
t[4] += b;
h4 = (uint32_t) t[4] & 0x3ffffff;
b = (uint32_t)(t[4] >> 26);
h0 += b * 5;
if(inlen >= 16) {
goto poly1305_donna_16bytes;
}
/* final bytes */
poly1305_donna_atmost15bytes:
if(!inlen) {
goto poly1305_donna_finish;
}
for(j = 0; j < inlen; j++) {
mp[j] = m[j];
}
mp[j++] = 1;
for(; j < 16; j++) {
mp[j] = 0;
}
inlen = 0;
t0 = U8TO32_LE(mp + 0);
t1 = U8TO32_LE(mp + 4);
t2 = U8TO32_LE(mp + 8);
t3 = U8TO32_LE(mp + 12);
h0 += t0 & 0x3ffffff;
h1 += ((((uint64_t) t1 << 32) | t0) >> 26) & 0x3ffffff;
h2 += ((((uint64_t) t2 << 32) | t1) >> 20) & 0x3ffffff;
h3 += ((((uint64_t) t3 << 32) | t2) >> 14) & 0x3ffffff;
h4 += (t3 >> 8);
goto poly1305_donna_mul;
poly1305_donna_finish:
b = h0 >> 26;
h0 = h0 & 0x3ffffff;
h1 += b;
b = h1 >> 26;
h1 = h1 & 0x3ffffff;
h2 += b;
b = h2 >> 26;
h2 = h2 & 0x3ffffff;
h3 += b;
b = h3 >> 26;
h3 = h3 & 0x3ffffff;
h4 += b;
b = h4 >> 26;
h4 = h4 & 0x3ffffff;
h0 += b * 5;
b = h0 >> 26;
h0 = h0 & 0x3ffffff;
h1 += b;
g0 = h0 + 5;
b = g0 >> 26;
g0 &= 0x3ffffff;
g1 = h1 + b;
b = g1 >> 26;
g1 &= 0x3ffffff;
g2 = h2 + b;
b = g2 >> 26;
g2 &= 0x3ffffff;
g3 = h3 + b;
b = g3 >> 26;
g3 &= 0x3ffffff;
g4 = h4 + b - (1 << 26);
b = (g4 >> 31) - 1;
nb = ~b;
h0 = (h0 & nb) | (g0 & b);
h1 = (h1 & nb) | (g1 & b);
h2 = (h2 & nb) | (g2 & b);
h3 = (h3 & nb) | (g3 & b);
h4 = (h4 & nb) | (g4 & b);
f0 = ((h0) | (h1 << 26)) + (uint64_t) U8TO32_LE(&key[16]);
f1 = ((h1 >> 6) | (h2 << 20)) + (uint64_t) U8TO32_LE(&key[20]);
f2 = ((h2 >> 12) | (h3 << 14)) + (uint64_t) U8TO32_LE(&key[24]);
f3 = ((h3 >> 18) | (h4 << 8)) + (uint64_t) U8TO32_LE(&key[28]);
U32TO8_LE(&out[0], f0);
f1 += (f0 >> 32);
U32TO8_LE(&out[4], f1);
f2 += (f1 >> 32);
U32TO8_LE(&out[8], f2);
f3 += (f2 >> 32);
U32TO8_LE(&out[12], f3);
}

View file

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

46
src/cipher.h Normal file
View file

@ -0,0 +1,46 @@
#ifndef TINC_CIPHER_H
#define TINC_CIPHER_H
/*
cipher.h -- header file cipher.c
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
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.
*/
#define CIPHER_MAX_BLOCK_SIZE 32
#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 *name) __attribute__((__malloc__));
extern cipher_t *cipher_open_by_nid(int nid) __attribute__((__malloc__));
extern void cipher_close(cipher_t *cipher);
extern size_t cipher_keylength(const cipher_t *cipher);
extern size_t cipher_blocksize(const cipher_t *cipher);
extern uint64_t cipher_budget(const cipher_t *cipher);
extern bool cipher_set_key(cipher_t *cipher, void *key, bool encrypt) __attribute__((__warn_unused_result__));
extern bool cipher_set_key_from_rsa(cipher_t *cipher, void *rsa, size_t len, bool encrypt) __attribute__((__warn_unused_result__));
extern bool cipher_encrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) __attribute__((__warn_unused_result__));
extern bool cipher_decrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) __attribute__((__warn_unused_result__));
extern int cipher_get_nid(const cipher_t *cipher);
extern bool cipher_active(const cipher_t *cipher);
#endif
#endif

View file

@ -1,10 +1,11 @@
/* /*
conf.c -- configuration code conf.c -- configuration code
Copyright (C) 1998 Robert van der Meulen Copyright (C) 1998 Robert van der Meulen
1998-2005 Ivo Timmermans 1998-2005 Ivo Timmermans
2000-2014 Guus Sliepen <guus@tinc-vpn.org> 2000 Cris van Pelt
2010-2011 Julien Muchembled <jm@jmuchemb.eu> 2010-2011 Julien Muchembled <jm@jmuchemb.eu>
2000 Cris van Pelt 2000-2021 Guus Sliepen <guus@tinc-vpn.org>
2013 Florent Clairambault <florent@clairambault.fr>
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -23,25 +24,23 @@
#include "system.h" #include "system.h"
#include "avl_tree.h" #include "splay_tree.h"
#include "connection.h" #include "connection.h"
#include "conf.h" #include "conf.h"
#include "list.h" #include "list.h"
#include "logger.h" #include "logger.h"
#include "netutl.h" /* for str2address */ #include "names.h"
#include "netutl.h" /* for str2address */
#include "protocol.h" #include "protocol.h"
#include "utils.h" /* for cp */ #include "utils.h" /* for cp */
#include "xalloc.h" #include "xalloc.h"
avl_tree_t *config_tree; splay_tree_t *config_tree;
int pinginterval = 0; /* seconds between pings */ int pinginterval = 0; /* seconds between pings */
int pingtimeout = 0; /* seconds to wait for response */ int pingtimeout = 0; /* seconds to wait for response */
char *confbase = NULL; /* directory in which all config files are */
char *netname = NULL; /* name of the vpn network */
list_t *cmdline_conf = NULL; /* global/host configuration values given at the command line */ list_t *cmdline_conf = NULL; /* global/host configuration values given at the command line */
static int config_compare(const config_t *a, const config_t *b) { static int config_compare(const config_t *a, const config_t *b) {
int result; int result;
@ -67,17 +66,17 @@ static int config_compare(const config_t *a, const config_t *b) {
} }
} }
void init_configuration(avl_tree_t **config_tree) { void init_configuration(splay_tree_t **config_tree) {
*config_tree = avl_alloc_tree((avl_compare_t) config_compare, (avl_action_t) free_config); *config_tree = splay_alloc_tree((splay_compare_t) config_compare, (splay_action_t) free_config);
} }
void exit_configuration(avl_tree_t **config_tree) { void exit_configuration(splay_tree_t **config_tree) {
avl_delete_tree(*config_tree); splay_delete_tree(*config_tree);
*config_tree = NULL; *config_tree = NULL;
} }
config_t *new_config(void) { config_t *new_config(void) {
return xmalloc_and_zero(sizeof(config_t)); return xzalloc(sizeof(config_t));
} }
void free_config(config_t *cfg) { void free_config(config_t *cfg) {
@ -87,18 +86,18 @@ void free_config(config_t *cfg) {
free(cfg); free(cfg);
} }
void config_add(avl_tree_t *config_tree, config_t *cfg) { void config_add(splay_tree_t *config_tree, config_t *cfg) {
avl_insert(config_tree, cfg); splay_insert(config_tree, cfg);
} }
config_t *lookup_config(const avl_tree_t *config_tree, char *variable) { config_t *lookup_config(splay_tree_t *config_tree, char *variable) {
config_t cfg, *found; config_t cfg, *found;
cfg.variable = variable; cfg.variable = variable;
cfg.file = NULL; cfg.file = NULL;
cfg.line = 0; cfg.line = 0;
found = avl_search_closest_greater(config_tree, &cfg); found = splay_search_closest_greater(config_tree, &cfg);
if(!found) { if(!found) {
return NULL; return NULL;
@ -111,11 +110,11 @@ config_t *lookup_config(const avl_tree_t *config_tree, char *variable) {
return found; return found;
} }
config_t *lookup_config_next(const avl_tree_t *config_tree, const config_t *cfg) { config_t *lookup_config_next(splay_tree_t *config_tree, const config_t *cfg) {
avl_node_t *node; splay_node_t *node;
config_t *found; config_t *found;
node = avl_search_node(config_tree, cfg); node = splay_search_node(config_tree, cfg);
if(node) { if(node) {
if(node->next) { if(node->next) {
@ -143,7 +142,7 @@ bool get_config_bool(const config_t *cfg, bool *result) {
return true; return true;
} }
logger(LOG_ERR, "\"yes\" or \"no\" expected for configuration variable %s in %s line %d", logger(DEBUG_ALWAYS, LOG_ERR, "\"yes\" or \"no\" expected for configuration variable %s in %s line %d",
cfg->variable, cfg->file, cfg->line); cfg->variable, cfg->file, cfg->line);
return false; return false;
@ -158,7 +157,7 @@ bool get_config_int(const config_t *cfg, int *result) {
return true; return true;
} }
logger(LOG_ERR, "Integer expected for configuration variable %s in %s line %d", logger(DEBUG_ALWAYS, LOG_ERR, "Integer expected for configuration variable %s in %s line %d",
cfg->variable, cfg->file, cfg->line); cfg->variable, cfg->file, cfg->line);
return false; return false;
@ -188,7 +187,7 @@ bool get_config_address(const config_t *cfg, struct addrinfo **result) {
return true; return true;
} }
logger(LOG_ERR, "Hostname or IP address expected for configuration variable %s in %s line %d", logger(DEBUG_ALWAYS, LOG_ERR, "Hostname or IP address expected for configuration variable %s in %s line %d",
cfg->variable, cfg->file, cfg->line); cfg->variable, cfg->file, cfg->line);
return false; return false;
@ -202,25 +201,19 @@ bool get_config_subnet(const config_t *cfg, subnet_t **result) {
} }
if(!str2net(&subnet, cfg->value)) { if(!str2net(&subnet, cfg->value)) {
logger(LOG_ERR, "Subnet expected for configuration variable %s in %s line %d", logger(DEBUG_ALWAYS, LOG_ERR, "Subnet expected for configuration variable %s in %s line %d",
cfg->variable, cfg->file, cfg->line); cfg->variable, cfg->file, cfg->line);
return false; return false;
} }
/* Teach newbies what subnets are... */ if(subnetcheck(subnet)) {
*(*result = new_subnet()) = subnet;
if(((subnet.type == SUBNET_IPV4) return true;
&& !maskcheck(&subnet.net.ipv4.address, subnet.net.ipv4.prefixlength, sizeof(ipv4_t)))
|| ((subnet.type == SUBNET_IPV6)
&& !maskcheck(&subnet.net.ipv6.address, subnet.net.ipv6.prefixlength, sizeof(ipv6_t)))) {
logger(LOG_ERR, "Network address and prefix length do not match for configuration variable %s in %s line %d",
cfg->variable, cfg->file, cfg->line);
return false;
} }
*(*result = new_subnet()) = subnet; logger(DEBUG_ALWAYS, LOG_ERR, "Network address and prefix length do not match for configuration variable %s in %s line %d",
cfg->variable, cfg->file, cfg->line);
return true; return false;
} }
/* /*
@ -246,9 +239,10 @@ static char *readline(FILE *fp, char *buf, size_t buflen) {
return buf; return buf;
} }
*newline = '\0'; /* kill newline */ /* kill newline and carriage return if necessary */
*newline = '\0';
if(newline > p && newline[-1] == '\r') { /* and carriage return if necessary */ if(newline > p && newline[-1] == '\r') {
newline[-1] = '\0'; newline[-1] = '\0';
} }
@ -282,10 +276,10 @@ config_t *parse_config_line(char *line, const char *fname, int lineno) {
const char err[] = "No value for variable"; const char err[] = "No value for variable";
if(fname) if(fname)
logger(LOG_ERR, "%s `%s' on line %d while reading config file %s", logger(DEBUG_ALWAYS, LOG_ERR, "%s `%s' on line %d while reading config file %s",
err, variable, lineno, fname); err, variable, lineno, fname);
else else
logger(LOG_ERR, "%s `%s' in command line option %d", logger(DEBUG_ALWAYS, LOG_ERR, "%s `%s' in command line option %d",
err, variable, lineno); err, variable, lineno);
return NULL; return NULL;
@ -304,7 +298,7 @@ config_t *parse_config_line(char *line, const char *fname, int lineno) {
Parse a configuration file and put the results in the configuration tree Parse a configuration file and put the results in the configuration tree
starting at *base. starting at *base.
*/ */
bool read_config_file(avl_tree_t *config_tree, const char *fname) { bool read_config_file(splay_tree_t *config_tree, const char *fname, bool verbose) {
FILE *fp; FILE *fp;
char buffer[MAX_STRING_SIZE]; char buffer[MAX_STRING_SIZE];
char *line; char *line;
@ -316,7 +310,7 @@ bool read_config_file(avl_tree_t *config_tree, const char *fname) {
fp = fopen(fname, "r"); fp = fopen(fname, "r");
if(!fp) { if(!fp) {
logger(LOG_ERR, "Cannot open config file %s: %s", fname, strerror(errno)); logger(verbose ? DEBUG_ALWAYS : DEBUG_CONNECTIONS, LOG_ERR, "Cannot open config file %s: %s", fname, strerror(errno));
return false; return false;
} }
@ -364,11 +358,12 @@ bool read_config_file(avl_tree_t *config_tree, const char *fname) {
return result; return result;
} }
void read_config_options(avl_tree_t *config_tree, const char *prefix) { void read_config_options(splay_tree_t *config_tree, const char *prefix) {
size_t prefix_len = prefix ? strlen(prefix) : 0; size_t prefix_len = prefix ? strlen(prefix) : 0;
for(const list_node_t *node = cmdline_conf->tail; node; node = node->prev) { for(const list_node_t *node = cmdline_conf->tail; node; node = node->prev) {
const config_t *cfg = node->data; const config_t *cfg = node->data;
config_t *new;
if(!prefix) { if(!prefix) {
if(strchr(cfg->variable, '.')) { if(strchr(cfg->variable, '.')) {
@ -381,7 +376,7 @@ void read_config_options(avl_tree_t *config_tree, const char *prefix) {
} }
} }
config_t *new = new_config(); new = new_config();
if(prefix) { if(prefix) {
new->variable = xstrdup(cfg->variable + prefix_len + 1); new->variable = xstrdup(cfg->variable + prefix_len + 1);
@ -403,14 +398,14 @@ bool read_server_config(void) {
read_config_options(config_tree, NULL); read_config_options(config_tree, NULL);
snprintf(fname, sizeof(fname), "%s/tinc.conf", confbase); snprintf(fname, sizeof(fname), "%s" SLASH "tinc.conf", confbase);
errno = 0; errno = 0;
x = read_config_file(config_tree, fname); x = read_config_file(config_tree, fname, true);
// We will try to read the conf files in the "conf.d" dir // We will try to read the conf files in the "conf.d" dir
if(x) { if(x) {
char dname[PATH_MAX]; char dname[PATH_MAX];
snprintf(dname, sizeof(dname), "%s/conf.d", confbase); snprintf(dname, sizeof(dname), "%s" SLASH "conf.d", confbase);
DIR *dir = opendir(dname); DIR *dir = opendir(dname);
// If we can find this dir // If we can find this dir
@ -423,12 +418,12 @@ bool read_server_config(void) {
// And we try to read the ones that end with ".conf" // And we try to read the ones that end with ".conf"
if(l > 5 && !strcmp(".conf", & ep->d_name[ l - 5 ])) { if(l > 5 && !strcmp(".conf", & ep->d_name[ l - 5 ])) {
if((size_t)snprintf(fname, sizeof(fname), "%s/%s", dname, ep->d_name) >= sizeof(fname)) { if((size_t)snprintf(fname, sizeof(fname), "%s" SLASH "%s", dname, ep->d_name) >= sizeof(fname)) {
logger(LOG_ERR, "Pathname too long: %s/%s", dname, ep->d_name); logger(DEBUG_ALWAYS, LOG_ERR, "Pathname too long: %s/%s", dname, ep->d_name);
return false; return false;
} }
x = read_config_file(config_tree, fname); x = read_config_file(config_tree, fname, true);
} }
} }
@ -437,166 +432,32 @@ bool read_server_config(void) {
} }
if(!x && errno) { if(!x && errno) {
logger(LOG_ERR, "Failed to read `%s': %s", fname, strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "Failed to read `%s': %s", fname, strerror(errno));
} }
return x; return x;
} }
bool read_connection_config(connection_t *c) { bool read_host_config(splay_tree_t *config_tree, const char *name, bool verbose) {
read_config_options(config_tree, name);
char fname[PATH_MAX]; char fname[PATH_MAX];
bool x; snprintf(fname, sizeof(fname), "%s" SLASH "hosts" SLASH "%s", confbase, name);
return read_config_file(config_tree, fname, verbose);
read_config_options(c->config_tree, c->name);
snprintf(fname, sizeof(fname), "%s/hosts/%s", confbase, c->name);
x = read_config_file(c->config_tree, fname);
return x;
} }
static void disable_old_keys(const char *filename) { bool append_config_file(const char *name, const char *key, const char *value) {
char tmpfile[PATH_MAX] = ""; char fname[PATH_MAX];
char buf[1024]; snprintf(fname, sizeof(fname), "%s" SLASH "hosts" SLASH "%s", confbase, name);
bool disabled = false;
FILE *r, *w;
r = fopen(filename, "r"); FILE *fp = fopen(fname, "a");
if(!r) { if(!fp) {
return; logger(DEBUG_ALWAYS, LOG_DEBUG, "Cannot open config file %s: %s", fname, strerror(errno));
return false;
} }
int len = snprintf(tmpfile, sizeof(tmpfile), "%s.tmp", filename); fprintf(fp, "\n# The following line was automatically added by tinc\n%s = %s\n", key, value);
fclose(fp);
if(len < 0 || len >= PATH_MAX) { return true;
fprintf(stderr, "Pathname too long: %s.tmp\n", filename);
w = NULL;
} else {
w = fopen(tmpfile, "w");
}
while(fgets(buf, sizeof(buf), r)) {
if(!strncmp(buf, "-----BEGIN RSA", 14)) {
buf[11] = 'O';
buf[12] = 'L';
buf[13] = 'D';
disabled = true;
} else if(!strncmp(buf, "-----END RSA", 12)) {
buf[ 9] = 'O';
buf[10] = 'L';
buf[11] = 'D';
disabled = true;
}
if(w && fputs(buf, w) < 0) {
disabled = false;
break;
}
}
if(w) {
fclose(w);
}
fclose(r);
if(!w && disabled) {
fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n");
return;
}
if(disabled) {
#ifdef HAVE_MINGW
// We cannot atomically replace files on Windows.
char bakfile[PATH_MAX] = "";
snprintf(bakfile, sizeof(bakfile), "%s.bak", filename);
if(rename(filename, bakfile) || rename(tmpfile, filename)) {
rename(bakfile, filename);
#else
if(rename(tmpfile, filename)) {
#endif
fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n");
} else {
#ifdef HAVE_MINGW
unlink(bakfile);
#endif
fprintf(stderr, "Warning: old key(s) found and disabled.\n");
}
}
unlink(tmpfile);
} }
FILE *ask_and_open(const char *filename, const char *what) {
FILE *r;
char directory[PATH_MAX];
char line[PATH_MAX];
char abspath[PATH_MAX];
const char *fn;
/* Check stdin and stdout */
if(!isatty(0) || !isatty(1)) {
/* Argh, they are running us from a script or something. Write
the files to the current directory and let them burn in hell
for ever. */
fn = filename;
} else {
/* Ask for a file and/or directory name. */
fprintf(stdout, "Please enter a file to save %s to [%s]: ",
what, filename);
fflush(stdout);
fn = readline(stdin, line, sizeof(line));
if(!fn) {
fprintf(stderr, "Error while reading stdin: %s\n",
strerror(errno));
return NULL;
}
if(!strlen(fn))
/* User just pressed enter. */
{
fn = filename;
}
}
#ifdef HAVE_MINGW
if(fn[0] != '\\' && fn[0] != '/' && !strchr(fn, ':')) {
#else
if(fn[0] != '/') {
#endif
/* The directory is a relative path or a filename. */
getcwd(directory, sizeof(directory));
if((size_t)snprintf(abspath, sizeof(abspath), "%s/%s", directory, fn) >= sizeof(abspath)) {
fprintf(stderr, "Pathname too long: %s/%s\n", directory, fn);
return NULL;
}
fn = abspath;
}
umask(0077); /* Disallow everything for group and other */
disable_old_keys(fn);
/* Open it first to keep the inode busy */
r = fopen(fn, "a");
if(!r) {
fprintf(stderr, "Error opening file `%s': %s\n",
fn, strerror(errno));
return NULL;
}
return r;
}

View file

@ -4,7 +4,7 @@
/* /*
conf.h -- header for conf.c conf.h -- header for conf.c
Copyright (C) 1998-2005 Ivo Timmermans Copyright (C) 1998-2005 Ivo Timmermans
2000-2012 Guus Sliepen <guus@tinc-vpn.org> 2000-2013 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -21,8 +21,9 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include "avl_tree.h"
#include "list.h" #include "list.h"
#include "splay_tree.h"
#include "subnet.h"
typedef struct config_t { typedef struct config_t {
char *variable; char *variable;
@ -31,37 +32,33 @@ typedef struct config_t {
int line; int line;
} config_t; } config_t;
#include "subnet.h"
extern avl_tree_t *config_tree; extern splay_tree_t *config_tree;
extern int pinginterval; extern int pinginterval;
extern int pingtimeout; extern int pingtimeout;
extern int maxtimeout; extern int maxtimeout;
extern int mintimeout;
extern bool bypass_security; extern bool bypass_security;
extern char *confbase;
extern char *netname;
extern list_t *cmdline_conf; extern list_t *cmdline_conf;
extern void init_configuration(avl_tree_t **config_tree); extern void init_configuration(splay_tree_t **config_tree);
extern void exit_configuration(avl_tree_t **config_tree); extern void exit_configuration(splay_tree_t **config_tree);
extern config_t *new_config(void) __attribute__((__malloc__)); extern config_t *new_config(void) __attribute__((__malloc__));
extern void free_config(config_t *cfg); extern void free_config(config_t *config);
extern void config_add(avl_tree_t *config_tree, config_t *cfg); extern void config_add(splay_tree_t *config_tree, config_t *config);
extern config_t *lookup_config(const avl_tree_t *config_tree, char *variable); extern config_t *lookup_config(splay_tree_t *config_tree, char *variable);
extern config_t *lookup_config_next(const avl_tree_t *config_tree, const config_t *cfg); extern config_t *lookup_config_next(splay_tree_t *config_tree, const config_t *config);
extern bool get_config_bool(const config_t *cfg, bool *result); extern bool get_config_bool(const config_t *config, bool *result);
extern bool get_config_int(const config_t *cfg, int *result); extern bool get_config_int(const config_t *config, int *result);
extern bool get_config_string(const config_t *cfg, char **result); extern bool get_config_string(const config_t *config, char **result);
extern bool get_config_address(const config_t *cfg, struct addrinfo **result); extern bool get_config_address(const config_t *config, struct addrinfo **result);
extern bool get_config_subnet(const config_t *cfg, struct subnet_t **result); extern bool get_config_subnet(const config_t *config, struct subnet_t **result);
extern config_t *parse_config_line(char *line, const char *fname, int lineno); extern config_t *parse_config_line(char *line, const char *fname, int lineno);
extern bool read_config_file(avl_tree_t *config_tree, const char *fname); extern bool read_config_file(splay_tree_t *config_tree, const char *filename, bool verbose);
extern void read_config_options(avl_tree_t *config_tree, const char *prefix); extern void read_config_options(splay_tree_t *config_tree, const char *prefix);
extern bool read_server_config(void); extern bool read_server_config(void);
extern bool read_connection_config(struct connection_t *c); extern bool read_host_config(splay_tree_t *config_tree, const char *name, bool verbose);
extern FILE *ask_and_open(const char *fname, const char *what); extern bool append_config_file(const char *name, const char *key, const char *value);
#endif #endif

View file

@ -1,6 +1,6 @@
/* /*
connection.c -- connection list management connection.c -- connection list management
Copyright (C) 2000-2016 Guus Sliepen <guus@tinc-vpn.org>, Copyright (C) 2000-2013 Guus Sliepen <guus@tinc-vpn.org>,
2000-2005 Ivo Timmermans 2000-2005 Ivo Timmermans
2008 Max Rijevski <maksuf@gmail.com> 2008 Max Rijevski <maksuf@gmail.com>
@ -21,100 +21,68 @@
#include "system.h" #include "system.h"
#include "avl_tree.h" #include "list.h"
#include "cipher.h"
#include "conf.h" #include "conf.h"
#include "control_common.h"
#include "list.h"
#include "logger.h" #include "logger.h"
#include "net.h"
#include "rsa.h"
#include "subnet.h" #include "subnet.h"
#include "utils.h" #include "utils.h"
#include "xalloc.h" #include "xalloc.h"
avl_tree_t *connection_tree; /* Meta connections */ list_t *connection_list;
connection_t *everyone; connection_t *everyone;
static int connection_compare(const connection_t *a, const connection_t *b) {
return a < b ? -1 : a == b ? 0 : 1;
}
void init_connections(void) { void init_connections(void) {
connection_tree = avl_alloc_tree((avl_compare_t) connection_compare, (avl_action_t) free_connection); connection_list = list_alloc((list_action_t) free_connection);
everyone = new_connection(); everyone = new_connection();
everyone->name = xstrdup("everyone"); everyone->name = xstrdup("everyone");
everyone->hostname = xstrdup("BROADCAST"); everyone->hostname = xstrdup("BROADCAST");
} }
void exit_connections(void) { void exit_connections(void) {
avl_delete_tree(connection_tree); list_delete_list(connection_list);
free_connection(everyone); free_connection(everyone);
} }
connection_t *new_connection(void) { connection_t *new_connection(void) {
connection_t *c; return xzalloc(sizeof(connection_t));
c = xmalloc_and_zero(sizeof(connection_t));
if(!c) {
return NULL;
}
gettimeofday(&c->start, NULL);
return c;
}
void free_connection_partially(connection_t *c) {
free(c->inkey);
free(c->outkey);
free(c->mychallenge);
free(c->hischallenge);
free(c->outbuf);
c->inkey = NULL;
c->outkey = NULL;
c->mychallenge = NULL;
c->hischallenge = NULL;
c->outbuf = NULL;
c->status.pinged = false;
c->status.active = false;
c->status.connecting = false;
c->status.timeout = false;
c->status.encryptout = false;
c->status.decryptin = false;
c->status.mst = false;
c->options = 0;
c->buflen = 0;
c->reqlen = 0;
c->tcplen = 0;
c->allow_request = 0;
c->outbuflen = 0;
c->outbufsize = 0;
c->outbufstart = 0;
c->last_ping_time = 0;
c->last_flushed_time = 0;
c->inbudget = 0;
c->outbudget = 0;
if(c->inctx) {
EVP_CIPHER_CTX_reset(c->inctx);
free(c->inctx);
c->inctx = NULL;
}
if(c->outctx) {
EVP_CIPHER_CTX_reset(c->outctx);
free(c->outctx);
c->outctx = NULL;
}
if(c->rsa_key) {
RSA_free(c->rsa_key);
c->rsa_key = NULL;
}
} }
void free_connection(connection_t *c) { void free_connection(connection_t *c) {
free_connection_partially(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);
free(c->hischallenge);
free(c->mychallenge);
buffer_clear(&c->inbuf);
buffer_clear(&c->outbuf);
io_del(&c->io);
if(c->socket > 0) {
if(c->status.tarpit) {
tarpit(c->socket);
} else {
closesocket(c->socket);
}
}
free(c->name); free(c->name);
free(c->hostname); free(c->hostname);
@ -127,25 +95,20 @@ void free_connection(connection_t *c) {
} }
void connection_add(connection_t *c) { void connection_add(connection_t *c) {
avl_insert(connection_tree, c); list_insert_tail(connection_list, c);
} }
void connection_del(connection_t *c) { void connection_del(connection_t *c) {
avl_delete(connection_tree, c); list_delete(connection_list, c);
} }
void dump_connections(void) { bool dump_connections(connection_t *cdump) {
avl_node_t *node; for list_each(connection_t, c, connection_list) {
connection_t *c; send_request(cdump, "%d %d %s %s %x %d %x",
CONTROL, REQ_DUMP_CONNECTIONS,
logger(LOG_DEBUG, "Connections:"); c->name, c->hostname, c->options, c->socket,
bitfield_to_int(&c->status, sizeof(c->status)));
for(node = connection_tree->head; node; node = node->next) {
c = node->data;
logger(LOG_DEBUG, " %s at %s options %x socket %d status %04x outbuf %d/%d/%d",
c->name, c->hostname, c->options, c->socket, bitfield_to_int(&c->status, sizeof(c->status)),
c->outbufsize, c->outbufstart, c->outbuflen);
} }
logger(LOG_DEBUG, "End of connections."); return send_request(cdump, "%d %d", CONTROL, REQ_DUMP_CONNECTIONS);
} }

View file

@ -3,7 +3,7 @@
/* /*
connection.h -- header for connection.c connection.h -- header for connection.c
Copyright (C) 2000-2016 Guus Sliepen <guus@tinc-vpn.org>, Copyright (C) 2000-2013 Guus Sliepen <guus@tinc-vpn.org>,
2000-2005 Ivo Timmermans 2000-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
@ -21,45 +21,50 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include <openssl/rsa.h> #include "buffer.h"
#include <openssl/evp.h> #include "cipher.h"
#include "digest.h"
#if OPENSSL_VERSION_NUMBER < 0x10100000L #include "rsa.h"
#define EVP_CIPHER_CTX_reset(c) EVP_CIPHER_CTX_cleanup(c) #include "list.h"
#endif #include "sptps.h"
#include "avl_tree.h"
#define OPTION_INDIRECT 0x0001 #define OPTION_INDIRECT 0x0001
#define OPTION_TCPONLY 0x0002 #define OPTION_TCPONLY 0x0002
#define OPTION_PMTU_DISCOVERY 0x0004 #define OPTION_PMTU_DISCOVERY 0x0004
#define OPTION_CLAMP_MSS 0x0008 #define OPTION_CLAMP_MSS 0x0008
#define OPTION_VERSION(x) ((x) >> 24) /* Top 8 bits are for protocol minor version */
typedef struct connection_status_t { typedef struct connection_status_t {
unsigned int pinged: 1; /* sent ping */ unsigned int pinged: 1; /* sent ping */
unsigned int active: 1; /* 1 if active.. */ unsigned int unused_active: 1;
unsigned int connecting: 1; /* 1 if we are waiting for a non-blocking connect() to finish */ unsigned int connecting: 1; /* 1 if we are waiting for a non-blocking connect() to finish */
unsigned int unused_termreq: 1; /* the termination of this connection was requested */ unsigned int unused_termreq: 1; /* the termination of this connection was requested */
unsigned int remove: 1; /* Set to 1 if you want this connection removed */ unsigned int remove_unused: 1; /* Set to 1 if you want this connection removed */
unsigned int timeout: 1; /* 1 if gotten timeout */ unsigned int timeout_unused: 1; /* 1 if gotten timeout */
unsigned int encryptout: 1; /* 1 if we can encrypt outgoing traffic */ unsigned int encryptout: 1; /* 1 if we can encrypt outgoing traffic */
unsigned int decryptin: 1; /* 1 if we have to decrypt incoming traffic */ unsigned int decryptin: 1; /* 1 if we have to decrypt incoming traffic */
unsigned int mst: 1; /* 1 if this connection is part of a minimum spanning tree */ unsigned int mst: 1; /* 1 if this connection is part of a minimum spanning tree */
unsigned int proxy_passed: 1; /* 1 if we are connecting via a proxy and we have finished talking with it */ unsigned int control: 1; /* 1 if this is a control connection */
unsigned int tarpit: 1; /* 1 if the connection should be added to the tarpit */ unsigned int pcap: 1; /* 1 if this is a control connection requesting packet capture */
unsigned int unused: 21; unsigned int log: 1; /* 1 if this is a control connection requesting log dump */
unsigned int invitation: 1; /* 1 if this is an invitation */
unsigned int invitation_used: 1; /* 1 if the invitation has been consumed */
unsigned int tarpit: 1; /* 1 if the connection should be added to the tarpit */
unsigned int unused: 17;
} connection_status_t; } connection_status_t;
#include "ecdsa.h"
#include "edge.h" #include "edge.h"
#include "net.h" #include "net.h"
#include "node.h" #include "node.h"
typedef struct connection_t { typedef struct connection_t {
char *name; /* name he claims to have */ char *name; /* name he claims to have */
char *hostname; /* the hostname of its real ip */
union sockaddr_t address; /* his real (internet) ip */ union sockaddr_t address; /* his real (internet) ip */
char *hostname; /* the hostname of its real ip */ int protocol_major; /* used protocol */
int protocol_version; /* used protocol */ int protocol_minor; /* used protocol */
int socket; /* socket used for this connection */ int socket; /* socket used for this connection */
uint32_t options; /* options for this connection */ uint32_t options; /* options for this connection */
@ -71,53 +76,48 @@ typedef struct connection_t {
struct node_t *node; /* node associated with the other end */ struct node_t *node; /* node associated with the other end */
struct edge_t *edge; /* edge associated with this connection */ struct edge_t *edge; /* edge associated with this connection */
RSA *rsa_key; /* his public/private key */ #ifndef DISABLE_LEGACY
const EVP_CIPHER *incipher; /* Cipher he will use to send data to us */ rsa_t *rsa; /* his public RSA key */
const EVP_CIPHER *outcipher; /* Cipher we will use to send data to him */ cipher_t *incipher; /* Cipher he will use to send data to us */
EVP_CIPHER_CTX *inctx; /* Context of encrypted meta data that will come from him to us */ cipher_t *outcipher; /* Cipher we will use to send data to him */
EVP_CIPHER_CTX *outctx; /* Context of encrypted meta data that will be sent from us to him */ digest_t *indigest;
uint64_t inbudget; /* Encrypted bytes send budget */ digest_t *outdigest;
uint64_t outbudget; /* Encrypted bytes receive budget */ uint64_t inbudget;
char *inkey; /* His symmetric meta key + iv */ uint64_t outbudget;
char *outkey; /* Our symmetric meta key + iv */ #endif
int inkeylength; /* Length of his key + iv */
int outkeylength; /* Length of our key + iv */ ecdsa_t *ecdsa; /* his public ECDSA key */
const EVP_MD *indigest; sptps_t sptps;
const EVP_MD *outdigest;
int inmaclength; int inmaclength;
int outmaclength; int outmaclength;
int incompression; int incompression;
int outcompression; int outcompression;
char *mychallenge; /* challenge we received from him */
char *hischallenge; /* challenge we sent to him */
char buffer[MAXBUFSIZE]; /* metadata input buffer */ char *hischallenge; /* The challenge we sent to him */
int buflen; /* bytes read into buffer */ char *mychallenge; /* The challenge we received */
int reqlen; /* length of incoming request */
length_t tcplen; /* length of incoming TCPpacket */ struct buffer_t inbuf;
struct buffer_t outbuf;
io_t io; /* input/output event on this metadata connection */
int tcplen; /* length of incoming TCPpacket */
int sptpslen; /* length of incoming SPTPS packet */
int allow_request; /* defined if there's only one request possible */ int allow_request; /* defined if there's only one request possible */
char *outbuf; /* metadata output buffer */
int outbufstart; /* index of first meaningful byte in output buffer */
int outbuflen; /* number of meaningful bytes in output buffer */
int outbufsize; /* number of bytes allocated to output buffer */
time_t last_ping_time; /* last time we saw some activity from the other end or pinged them */ time_t last_ping_time; /* last time we saw some activity from the other end or pinged them */
time_t last_flushed_time; /* last time buffer was empty. Only meaningful if outbuflen > 0 */
avl_tree_t *config_tree; /* Pointer to configuration tree belonging to him */ splay_tree_t *config_tree; /* Pointer to configuration tree belonging to him */
} connection_t; } connection_t;
extern avl_tree_t *connection_tree; extern list_t *connection_list;
extern connection_t *everyone; extern connection_t *everyone;
extern void init_connections(void); extern void init_connections(void);
extern void exit_connections(void); extern void exit_connections(void);
extern connection_t *new_connection(void) __attribute__((__malloc__)); extern connection_t *new_connection(void) __attribute__((__malloc__));
extern void free_connection(connection_t *c); extern void free_connection(connection_t *c);
extern void free_connection_partially(connection_t *c);
extern void connection_add(connection_t *c); extern void connection_add(connection_t *c);
extern void connection_del(connection_t *c); extern void connection_del(connection_t *c);
extern void dump_connections(void); extern bool dump_connections(struct connection_t *c);
#endif #endif

241
src/control.c Normal file
View file

@ -0,0 +1,241 @@
/*
control.c -- Control socket handling.
Copyright (C) 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 "crypto.h"
#include "conf.h"
#include "control.h"
#include "control_common.h"
#include "graph.h"
#include "logger.h"
#include "meta.h"
#include "names.h"
#include "net.h"
#include "netutl.h"
#include "protocol.h"
#include "route.h"
#include "utils.h"
#include "xalloc.h"
char controlcookie[65];
static bool control_return(connection_t *c, int type, int error) {
return send_request(c, "%d %d %d", CONTROL, type, error);
}
static bool control_ok(connection_t *c, int type) {
return control_return(c, type, 0);
}
bool control_h(connection_t *c, const char *request) {
int type;
if(!c->status.control || c->allow_request != CONTROL) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unauthorized control request from %s (%s)", c->name, c->hostname);
return false;
}
if(sscanf(request, "%*d %d", &type) != 1) {
logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "CONTROL", c->name, c->hostname);
return false;
}
switch(type) {
case REQ_STOP:
event_exit();
return control_ok(c, REQ_STOP);
case REQ_DUMP_NODES:
return dump_nodes(c);
case REQ_DUMP_EDGES:
return dump_edges(c);
case REQ_DUMP_SUBNETS:
return dump_subnets(c);
case REQ_DUMP_CONNECTIONS:
return dump_connections(c);
case REQ_PURGE:
purge();
return control_ok(c, REQ_PURGE);
case REQ_SET_DEBUG: {
int new_level;
if(sscanf(request, "%*d %*d %d", &new_level) != 1) {
return false;
}
send_request(c, "%d %d %d", CONTROL, REQ_SET_DEBUG, debug_level);
if(new_level >= 0) {
debug_level = new_level;
}
return true;
}
case REQ_RETRY:
retry();
return control_ok(c, REQ_RETRY);
case REQ_RELOAD:
logger(DEBUG_ALWAYS, LOG_NOTICE, "Got '%s' command", "reload");
int result = reload_configuration();
return control_return(c, REQ_RELOAD, result);
case REQ_DISCONNECT: {
char name[MAX_STRING_SIZE];
bool found = false;
if(sscanf(request, "%*d %*d " MAX_STRING, name) != 1) {
return control_return(c, REQ_DISCONNECT, -1);
}
for list_each(connection_t, other, connection_list) {
if(strcmp(other->name, name)) {
continue;
}
terminate_connection(other, other->edge);
found = true;
}
return control_return(c, REQ_DISCONNECT, found ? 0 : -2);
}
case REQ_DUMP_TRAFFIC:
return dump_traffic(c);
case REQ_PCAP:
sscanf(request, "%*d %*d %d", &c->outmaclength);
c->status.pcap = true;
pcap = true;
return true;
case REQ_LOG:
sscanf(request, "%*d %*d %d", &c->outcompression);
c->status.log = true;
logcontrol = true;
return true;
default:
return send_request(c, "%d %d", CONTROL, REQ_INVALID);
}
}
bool init_control(void) {
randomize(controlcookie, sizeof(controlcookie) / 2);
bin2hex(controlcookie, controlcookie, sizeof(controlcookie) / 2);
mode_t mask = umask(0);
umask(mask | 077);
FILE *f = fopen(pidfilename, "w");
umask(mask);
if(!f) {
logger(DEBUG_ALWAYS, LOG_ERR, "Cannot write control socket cookie file %s: %s", pidfilename, strerror(errno));
return false;
}
// Get the address and port of the first listening socket
char *localhost = NULL;
sockaddr_t sa = {0};
socklen_t len = sizeof(sa);
// Make sure we have a valid address, and map 0.0.0.0 and :: to 127.0.0.1 and ::1.
if(getsockname(listen_socket[0].tcp.fd, &sa.sa, &len)) {
xasprintf(&localhost, "127.0.0.1 port %s", myport);
} else {
if(sa.sa.sa_family == AF_INET) {
if(sa.in.sin_addr.s_addr == 0) {
sa.in.sin_addr.s_addr = htonl(0x7f000001);
}
} else if(sa.sa.sa_family == AF_INET6) {
static const uint8_t zero[16] = {0};
if(!memcmp(sa.in6.sin6_addr.s6_addr, zero, sizeof(zero))) {
sa.in6.sin6_addr.s6_addr[15] = 1;
}
}
localhost = sockaddr2hostname(&sa);
}
fprintf(f, "%d %s %s\n", (int)getpid(), controlcookie, localhost);
free(localhost);
fclose(f);
#ifndef HAVE_MINGW
int unix_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if(unix_fd < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not create UNIX socket: %s", sockstrerror(sockerrno));
return false;
}
struct sockaddr_un sa_un;
sa_un.sun_family = AF_UNIX;
strncpy(sa_un.sun_path, unixsocketname, sizeof(sa_un.sun_path));
sa_un.sun_path[sizeof(sa_un.sun_path) - 1] = 0;
if(connect(unix_fd, (struct sockaddr *)&sa_un, sizeof(sa_un)) >= 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "UNIX socket %s is still in use!", unixsocketname);
return false;
}
unlink(unixsocketname);
umask(mask | 077);
int result = bind(unix_fd, (struct sockaddr *)&sa_un, sizeof(sa_un));
umask(mask);
if(result < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not bind UNIX socket to %s: %s", unixsocketname, sockstrerror(sockerrno));
return false;
}
if(listen(unix_fd, 3) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not listen on UNIX socket %s: %s", unixsocketname, sockstrerror(sockerrno));
return false;
}
io_add(&unix_socket, handle_new_unix_connection, &unix_socket, unix_fd, IO_READ);
#endif
return true;
}
void exit_control(void) {
#ifndef HAVE_MINGW
unlink(unixsocketname);
io_del(&unix_socket);
close(unix_socket.fd);
#endif
unlink(pidfilename);
}

27
src/control.h Normal file
View file

@ -0,0 +1,27 @@
#ifndef TINC_CONTROL_H
#define TINC_CONTROL_H
/*
control.h -- header for control.c.
Copyright (C) 2007 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.
*/
extern bool init_control(void);
extern void exit_control(void);
extern char controlcookie[];
#endif

48
src/control_common.h Normal file
View file

@ -0,0 +1,48 @@
#ifndef TINC_CONTROL_COMMON_H
#define TINC_CONTROL_COMMON_H
/*
control_protocol.h -- control socket protocol.
Copyright (C) 2007 Scott Lamb <slamb@slamb.org>
2009-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
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 "protocol.h"
enum request_type {
REQ_INVALID = -1,
REQ_STOP = 0,
REQ_RELOAD,
REQ_RESTART,
REQ_DUMP_NODES,
REQ_DUMP_EDGES,
REQ_DUMP_SUBNETS,
REQ_DUMP_CONNECTIONS,
REQ_DUMP_GRAPH,
REQ_PURGE,
REQ_SET_DEBUG,
REQ_RETRY,
REQ_CONNECT,
REQ_DISCONNECT,
REQ_DUMP_TRAFFIC,
REQ_PCAP,
REQ_LOG,
};
#define TINC_CTL_VERSION_CURRENT 0
#endif

27
src/crypto.h Normal file
View file

@ -0,0 +1,27 @@
#ifndef TINC_CRYPTO_H
#define TINC_CRYPTO_H
/*
crypto.h -- header for crypto.c
Copyright (C) 2007-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.
*/
extern void crypto_init(void);
extern void crypto_exit(void);
extern void randomize(void *buf, size_t buflen);
#endif

View file

@ -1,287 +0,0 @@
/*
device.c -- Interaction with Windows tap driver in a Cygwin environment
Copyright (C) 2002-2005 Ivo Timmermans,
2002-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 "../net.h"
#include <w32api/windows.h>
#include <w32api/winioctl.h>
#include "../conf.h"
#include "../device.h"
#include "../logger.h"
#include "../route.h"
#include "../utils.h"
#include "../xalloc.h"
#include "../mingw/common.h"
int device_fd = -1;
static HANDLE device_handle = INVALID_HANDLE_VALUE;
char *device = NULL;
char *iface = NULL;
static const char *device_info = "Windows tap device";
static uint64_t device_total_in = 0;
static uint64_t device_total_out = 0;
static pid_t reader_pid;
static int sp[2];
static bool setup_device(void) {
HKEY key, key2;
int i, err;
char regpath[1024];
char adapterid[1024];
char adaptername[1024];
char tapname[1024];
char gelukt = 0;
long len;
bool found = false;
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)) {
logger(LOG_ERR, "Unable to read registry: %s", winerror(GetLastError()));
return false;
}
for(i = 0; ; i++) {
len = sizeof(adapterid);
if(RegEnumKeyEx(key, i, adapterid, &len, 0, 0, 0, NULL)) {
break;
}
/* Find out more about this adapter */
snprintf(regpath, sizeof(regpath), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapterid);
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2)) {
continue;
}
len = sizeof(adaptername);
err = RegQueryValueEx(key2, "Name", 0, 0, adaptername, &len);
RegCloseKey(key2);
if(err) {
continue;
}
if(device) {
if(!strcmp(device, adapterid)) {
found = true;
break;
} else {
continue;
}
}
if(iface) {
if(!strcmp(iface, adaptername)) {
found = true;
break;
} else {
continue;
}
}
snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
if(device_handle != INVALID_HANDLE_VALUE) {
CloseHandle(device_handle);
found = true;
break;
}
}
RegCloseKey(key);
if(!found) {
logger(LOG_ERR, "No Windows tap device found!");
return false;
}
if(!device) {
device = xstrdup(adapterid);
}
if(!iface) {
iface = xstrdup(adaptername);
}
snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, device);
/* Now we are going to open this device twice: once for reading and once for writing.
We do this because apparently it isn't possible to check for activity in the select() loop.
Furthermore I don't really know how to do it the "Windows" way. */
if(socketpair(AF_UNIX, SOCK_DGRAM, PF_UNIX, sp)) {
logger(LOG_DEBUG, "System call `%s' failed: %s", "socketpair", strerror(errno));
return false;
}
/* The parent opens the tap device for writing. */
device_handle = CreateFile(tapname, GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
if(device_handle == INVALID_HANDLE_VALUE) {
logger(LOG_ERR, "Could not open Windows tap device %s (%s) for writing: %s", device, iface, winerror(GetLastError()));
return false;
}
device_fd = sp[0];
/* 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)) {
logger(LOG_ERR, "Could not get MAC address from Windows tap device %s (%s): %s", device, iface, winerror(GetLastError()));
return false;
}
if(routing_mode == RMODE_ROUTER) {
overwrite_mac = 1;
}
/* Now we start the child */
reader_pid = fork();
if(reader_pid == -1) {
logger(LOG_DEBUG, "System call `%s' failed: %s", "fork", strerror(errno));
return false;
}
if(!reader_pid) {
/* The child opens the tap device for reading, blocking.
It passes everything it reads to the socket. */
char buf[MTU];
long lenin;
CloseHandle(device_handle);
device_handle = CreateFile(tapname, GENERIC_READ, FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
if(device_handle == INVALID_HANDLE_VALUE) {
logger(LOG_ERR, "Could not open Windows tap device %s (%s) for reading: %s", device, iface, winerror(GetLastError()));
buf[0] = 0;
write(sp[1], buf, 1);
exit(1);
}
logger(LOG_DEBUG, "Tap reader forked and running.");
/* Notify success */
buf[0] = 1;
write(sp[1], buf, 1);
/* Pass packets */
for(;;) {
ReadFile(device_handle, buf, MTU, &lenin, NULL);
write(sp[1], buf, lenin);
}
}
read(device_fd, &gelukt, 1);
if(gelukt != 1) {
logger(LOG_DEBUG, "Tap reader failed!");
return false;
}
logger(LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
return true;
}
static void close_device(void) {
close(sp[0]);
close(sp[1]);
CloseHandle(device_handle);
kill(reader_pid, SIGKILL);
free(device);
free(iface);
}
static bool read_packet(vpn_packet_t *packet) {
int lenin;
if((lenin = read(sp[0], packet->data, MTU)) <= 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno));
return false;
}
packet->len = lenin;
device_total_in += packet->len;
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", packet->len,
device_info);
return true;
}
static bool write_packet(vpn_packet_t *packet) {
long lenout;
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
packet->len, device_info);
if(!WriteFile(device_handle, packet->data, packet->len, &lenout, NULL)) {
logger(LOG_ERR, "Error while writing to %s %s: %s", device_info, device, winerror(GetLastError()));
return false;
}
device_total_out += packet->len;
return true;
}
static void dump_device_stats(void) {
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
}
const devops_t os_devops = {
.setup = setup_device,
.close = close_device,
.read = read_packet,
.write = write_packet,
.dump_stats = dump_device_stats,
};

View file

@ -25,21 +25,22 @@
extern int device_fd; extern int device_fd;
extern char *device; extern char *device;
extern char *iface; extern char *iface;
typedef struct devops_t { typedef struct devops_t {
bool (*setup)(void); bool (*setup)(void);
void (*close)(void); void (*close)(void);
bool (*read)(struct vpn_packet_t *packet); bool (*read)(struct vpn_packet_t *);
bool (*write)(struct vpn_packet_t *packet); bool (*write)(struct vpn_packet_t *);
void (*dump_stats)(void); void (*enable)(void); /* optional */
void (*disable)(void); /* optional */
} devops_t; } devops_t;
extern const devops_t os_devops; extern const devops_t os_devops;
extern const devops_t dummy_devops; extern const devops_t dummy_devops;
extern const devops_t raw_socket_devops; extern const devops_t raw_socket_devops;
extern const devops_t multicast_devops; extern const devops_t multicast_devops;
extern const devops_t fd_devops;
extern const devops_t uml_devops; extern const devops_t uml_devops;
extern const devops_t vde_devops; extern const devops_t vde_devops;
extern devops_t devops; extern devops_t devops;

42
src/digest.h Normal file
View file

@ -0,0 +1,42 @@
#ifndef TINC_DIGEST_H
#define TINC_DIGEST_H
/*
digest.h -- header file digest.c
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
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.
*/
#define DIGEST_MAX_SIZE 64
#ifndef DISABLE_LEGACY
typedef struct digest digest_t;
extern digest_t *digest_open_by_name(const char *name, int maclength) __attribute__((__malloc__));
extern digest_t *digest_open_by_nid(int nid, int maclength) __attribute__((__malloc__));
extern void digest_close(digest_t *digest);
extern bool digest_create(digest_t *digest, const void *indata, size_t inlen, void *outdata) __attribute__((__warn_unused_result__));
extern bool digest_verify(digest_t *digest, const void *indata, size_t inlen, const void *digestdata) __attribute__((__warn_unused_result__));
extern bool digest_set_key(digest_t *digest, const void *key, size_t len) __attribute__((__warn_unused_result__));
extern int digest_get_nid(const digest_t *digest);
extern size_t digest_keylength(const digest_t *digest);
extern size_t digest_length(const digest_t *digest);
extern bool digest_active(const digest_t *digest);
#endif
#endif

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