Compare commits

...

37 commits

Author SHA1 Message Date
Guus Sliepen
c14863878e Release 1.0.36-2 for unstable 2020-11-22 10:40:54 +01:00
Guus Sliepen
72c0b016d0 Disable support for livdeplug.
Closes: #973233
2020-11-22 10:40:00 +01:00
Guus Sliepen
464df78ca9 Release 1.0.36-1 for unstable 2019-08-26 14:20:47 +02:00
Guus Sliepen
32e725a2c0 Bump Standards-Version. 2019-08-26 14:15:02 +02:00
Guus Sliepen
038933e7fc Add Vcs tags to debian/control. 2019-08-26 14:00:57 +02:00
Guus Sliepen
6932380624 Update upstream source from tag 'upstream/1.0.36'
Update to upstream version '1.0.36'
with Debian dir 1c07c6f457
2019-08-26 13:52:00 +02:00
Guus Sliepen
10b8518c22 New upstream version 1.0.36 2019-08-26 13:52:00 +02:00
Guus Sliepen
b511a112e6 Import Upstream version 1.1~pre17 2019-08-26 13:44:53 +02:00
Guus Sliepen
bc8ca65653 Import Upstream version 1.1~pre15 2019-08-26 13:44:52 +02:00
Guus Sliepen
87cef22421 Import Upstream version 1.1~pre14-16-g15b868e 2019-08-26 13:44:52 +02:00
Guus Sliepen
aa10d88732 Import Upstream version 1.1~pre12 2019-08-26 13:44:52 +02:00
Guus Sliepen
1813f3157e Import Upstream version 1.1~pre11 2019-08-26 13:44:51 +02:00
Guus Sliepen
60cff3039b Import Upstream version 1.1~pre9 2019-08-26 13:44:51 +02:00
Guus Sliepen
f5c641f5cc Import Upstream version 1.1~pre8 2019-08-26 13:44:51 +02:00
Guus Sliepen
2ebbac3278 Import Upstream version 1.1~pre7 2019-08-26 13:44:50 +02:00
Guus Sliepen
26033edb96 Import Upstream version 1.1~pre6 2019-08-26 13:44:50 +02:00
Guus Sliepen
ff64081061 Import Upstream version 1.1~pre4 2019-08-26 13:44:50 +02:00
Guus Sliepen
36f0d3c816 Import Debian changes 1.0.35-2
tinc (1.0.35-2) unstable; 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.
2019-08-26 13:44:49 +02:00
Guus Sliepen
34d5939212 Import Upstream version 1.1~pre3 2019-08-26 13:44:49 +02:00
Guus Sliepen
ecd1f6f67a Import Debian changes 1.0.35-1
tinc (1.0.35-1) unstable; urgency=medium

  * New upstream release.
    - Includes fixes for CVE-2018-16737, CVE-2018-16738, CVE-2018-16758.
2019-08-26 13:44:49 +02:00
Guus Sliepen
02de1cd2f1 Import Upstream version 1.1~pre2 2019-08-26 13:44:49 +02:00
Guus Sliepen
a04a7bcd67 Import Upstream version 1.0.35 2019-08-26 13:44:49 +02:00
Guus Sliepen
f8e1f5a528 Import Debian changes 1.0.34-1
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
2019-08-26 13:44:48 +02:00
Guus Sliepen
b28bb7b29b Import Upstream version 1.0.34 2019-08-26 13:44:48 +02:00
Guus Sliepen
66e86a419b Import Debian changes 1.0.33-1
tinc (1.0.33-1) unstable; urgency=medium

  * New upstream release.
  * Test for /etc/default/tinc before trying to source it. Closes: #777262
  * Use --runstatedir=/run.
2019-08-26 13:44:48 +02:00
Guus Sliepen
5969674c46 Import Upstream version 1.0.33 2019-08-26 13:44:48 +02:00
Guus Sliepen
ac78971aab Import Debian changes 1.0.32-1
tinc (1.0.32-1) unstable; 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.
2019-08-26 13:44:48 +02:00
Guus Sliepen
e0e55285b8 Import Upstream version 1.0.32 2019-08-26 13:44:48 +02:00
Guus Sliepen
2989322746 Import Debian changes 1.0.31-1+deb9u1
tinc (1.0.31-1+deb9u1) stretch-security; urgency=high

  * Prevent oracle attacks (CVE-2018-16737, CVE-2018-16738).
  * Prevent a MITM from forcing a NULL cipher for UDP (CVE-2018-16758).
2019-08-26 13:44:48 +02:00
Guus Sliepen
81ce06b6c9 Import Upstream version 1.0.31 2019-08-26 13:44:47 +02:00
Guus Sliepen
11d9efef1b Import Debian changes 1.0.31-1
tinc (1.0.31-1) unstable; urgency=medium

  * New upstream release.
  * Bump Standards-Version.
  * Bump debian/compat.
  * Add missing Depends: lsb-base.
2019-08-26 13:44:47 +02:00
Guus Sliepen
1077a20a8c Import Upstream version 1.0.29 2019-08-26 13:44:47 +02:00
Guus Sliepen
dcd38ec07d Import Debian changes 1.0.29-2
tinc (1.0.29-2) unstable; urgency=medium

  * Rebuild with libssl-dev from unstable.
2019-08-26 13:44:47 +02:00
Guus Sliepen
502cecde93 Import Debian changes 1.0.29-1
tinc (1.0.29-1) unstable; urgency=medium

  * New upstream release.
  * Bump debian/compat.
2019-08-26 13:44:47 +02:00
Guus Sliepen
e537caa7b1 Import Debian changes 1.0.28-1
tinc (1.0.28-1) unstable; urgency=medium

  * New upstream release.
    - Fixes FTBFS on kfreebsd.
  * Systemd service files are now provided by upstream.
2019-08-26 13:44:47 +02:00
Aron Xu
02fdd053f1 Import Debian changes 1.0.28-1~bpo8+1
tinc (1.0.28-1~bpo8+1) jessie-backports; urgency=medium

  * Rebuild for jessie-backports.

tinc (1.0.28-1) unstable; urgency=medium

  * New upstream release.
    - Fixes FTBFS on kfreebsd.
  * Systemd service files are now provided by upstream.
2019-08-26 13:44:47 +02:00
Guus Sliepen
d08a5d8f0b Import Upstream version 1.0.28 2019-08-26 13:44:46 +02:00
136 changed files with 12126 additions and 8457 deletions

View file

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

184
ChangeLog
View file

@ -1,3 +1,187 @@
Version 1.0.36 August 26 2019
------------------------------------------------------------------------
Guus Sliepen (8):
Remove the call to RAND_load_file().
Update THANKS.
Backport tinc 1.1's str2net() function.
Update THANKS.
Fix spelling errors found by codespell.
Reformat all code using astyle.
Add a missing check for a pathname being too long.
Releasing 1.0.36.
Rosen Penev (2):
Fix compilation when OpenSSL has no ENGINE support
Fix compilation without deprecated OpenSSL APIs
Quentin Rameau (1):
Double-quote nodes in graphviz network file
Werner Schreiber (1):
Fix segfault when dest->mtu is 0.
Version 1.0.35 October 05 2018
------------------------------------------------------------------------
Guus Sliepen (12):
Prevent oracle attacks (CVE-2018-16737, CVE-2018-16738)
Prevent a MITM from forcing a NULL cipher for UDP (CVE-2018-16758)
Check the return value from snprintf().
Check the return values from BN_hex2bn() and RAND_load_file().
Fix all warnings when compiling with -Wall -W -pedantic.
Fix two small memory leaks.
Don't check for NULL-pointers before calling free().
Update THANKS.
Fix checks for Cygwin-related macros.
Fix spelling errors.
Update README and links to required libraries.
Releasing 1.0.35.
AMRI Amine (1):
Fixing typo
Rafael Sadowski (1):
OpenBSD has a proper tap device.
Version 1.0.34 June 12 2018
------------------------------------------------------------------------
Guus Sliepen (10):
Add missing thanks to the NEWS message.
Fix building documentation when using OpenBSD's make.
Fix #ifdefs that were broken due to commit d178b58.
Don't use SOL_IP and SOL_IPV6.
Make systemd service file handling identical to tinc 1.1.
Rename distro/ to systemd/.
Document how to enable tinc at boot time using systemd.
Fix all spelling errors found by codespell.
Properly implement tinc.texi's dependency on tincinclude.texi.
Releasing 1.0.34.
Maximilian Stein (1):
Fix SEGFAULT when trying to connect to IPv6 peer in non-IPv6 environment
wangliushuai (1):
Remove redundant 'break'.
Version 1.0.33 November 04 2017
------------------------------------------------------------------------
Guus Sliepen (31):
Udpate THANKS.
Fix a potential memory leak.
Use AC_CONFIG_MACRO_DIR().
Give absolute path for #include to AC_CHECK_HEADERS().
Prepare for automatic code formatting using Artistic Style.
Never remove items from cmdline_conf.
Use stack-allocated strings for temporary filenames.
Fix a few minor memory leaks.
Remove unused/obsolete checks from configure.ac.
Use getcwd() instead of get_current_dir_name().
Remove xmalloc.c, backport xalloc.h from tinc 1.1.
Update all header guards.
Convert sizeof foo to sizeof(foo).
Reformat all code using astyle.
Don't call ERR_remove_state().
Unconditionally include stdbool.h and inttypes.h.
Remove more obsolete autoconf checks.
Remove obsolete m4/README.
Fix some "make distcheck" errors.
Add some information about the requirements of a chroot environment.
Handle tun/tap device returning EPERM or EBUSY.
Disable PMTU discovery when TCPOnly is used.
Fix all -Wall -W compiler warnings.
Realign comments.
Remove unused functions.
Ensure all parameters have names in header files.
Support autoconf's --runstatedir option.
Const correctness.
Fix compilation errors when --enable-uml is used.
Update THANKS.
Releasing 1.0.33.
Rafael Sadowski (1):
fix tinc.conf for OpenBSD
nemunaire (1):
Allow compilation from a build directory
Version 1.0.32 September 02 2017
------------------------------------------------------------------------
Guus Sliepen (13):
Don't dereference myself->incipher if it's NULL.
Merge remote-tracking branch 'VittGam/master'
Use /dev/udp instead of /dev/ip on Solaris.
Use getmsg()/putmsg() instead of read()/write() on Solaris.
Fix Solaris DeviceType = tap in router Mode.
Bind outgoing TCP sockets.
Move logging of "would block" messages to debug level 4.
Set KillMode=mixed in the systemd service file.
Don't forget about outgoing connections on host file read errors.
Fix Proxy = exec.
Set status.proxy_passed early for Proxy = exec.
Don't try to bind Proxy = exec sockets to an address.
Releasing 1.0.32.
Vittorio Gambaletta (VittGam) (1):
route: Support ToS/DiffServ priority inheritance when routing IPv6 packets.
Version 1.0.31 January 15 2017
------------------------------------------------------------------------
Guus Sliepen (1):
Releasing 1.0.31.
Élie Bouttier (1):
Remove ExecStop in tinc@.service
Version 1.0.30 October 30 2016
------------------------------------------------------------------------
Guus Sliepen (11):
Allow non-empty lines after status code from a HTTP proxy.
Fix proxy reply parsing broken by the previous commit.
Log only the first line of a proxy request rejection message.
Delay sending the real ID request until after a proxy request is granted.
Use AES256 and SHA256 by default, also for the meta-connections.
Enforce maximum amount of bytes sent/received on meta-connections.
Fix bit shifting arithmetic so the code actually does what the last commit message says.
Really fix byte budget calculation.
Use AES in CTR mode instead of OFB mode for meta-connections.
Use CFB mode for meta-connections to improve security.
Releasing 1.0.30.
Version 1.0.29 October 09 2016
------------------------------------------------------------------------
Guus Sliepen (11):
Preserve IPv6 scope_id in edges.
Ensure compatibility with OpenSSL 1.1.0.
Add -Wall to CFLAGS.
Check return value of RSA_generate_key_ex().
Force nul-termination of strings after vsnprintf().
Log warnings about dropped packets only with debug level 5 or higher.
Add a copy of ax_append_flag.m4.
Add ax_require_defined.m4.
Fix possibly unitialized variable.
Fix compiler warnings about format string errors on BSD.
Releasing 1.0.29.
Version 1.0.28 April 10 2016
------------------------------------------------------------------------
Guus Sliepen (8):
Fix compiling bsd/device.c on systems without utun.
Really remove use of __DATE__ and __TIME__ to facilitate reproducible builds.
Add systemd service files.
Update .gitignore.
Ensure the service files are in the tarball.
Explicitly mention that LibreSSL can be used as well.
Update links in the documentation.
Releasing 1.0.28.
Version 1.0.27 April 10 2016
------------------------------------------------------------------------

316
INSTALL
View file

@ -1,8 +1,8 @@
Installation Instructions
*************************
Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation,
Inc.
Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software
Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
@ -12,97 +12,96 @@ without warranty of any kind.
Basic Installation
==================
Briefly, the shell command `./configure && make && make install'
Briefly, the shell command './configure && make && make install'
should configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
more-detailed instructions are generic; see the 'README' file for
instructions specific to this package. Some packages provide this
`INSTALL' file but do not implement all of the features documented
'INSTALL' file but do not implement all of the features documented
below. The lack of an optional feature in a given package is not
necessarily a bug. More recommendations for GNU packages can be found
in *note Makefile Conventions: (standards)Makefile Conventions.
The `configure' shell script attempts to guess correct values for
The 'configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
those values to create a 'Makefile' in each directory of the package.
It may also create one or more '.h' files containing system-dependent
definitions. Finally, it creates a shell script 'config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
file 'config.log' containing compiler output (useful mainly for
debugging 'configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. Caching is
disabled by default to prevent problems with accidental use of stale
cache files.
It can also use an optional file (typically called 'config.cache' and
enabled with '--cache-file=config.cache' or simply '-C') that saves the
results of its tests to speed up reconfiguring. Caching is disabled by
default to prevent problems with accidental use of stale cache files.
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
to figure out how 'configure' could check whether to do them, and mail
diffs or instructions to the address given in the 'README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
some point 'config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You need `configure.ac' if
you want to change it or regenerate `configure' using a newer version
of `autoconf'.
The file 'configure.ac' (or 'configure.in') is used to create
'configure' by a program called 'autoconf'. You need 'configure.ac' if
you want to change it or regenerate 'configure' using a newer version of
'autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system.
1. 'cd' to the directory containing the package's source code and type
'./configure' to configure the package for your system.
Running `configure' might take a while. While running, it prints
Running 'configure' might take a while. While running, it prints
some messages telling which features it is checking for.
2. Type `make' to compile the package.
2. Type 'make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
3. Optionally, type 'make check' to run any self-tests that come with
the package, generally using the just-built uninstalled binaries.
4. Type `make install' to install the programs and any data files and
4. Type 'make install' to install the programs and any data files and
documentation. When installing into a prefix owned by root, it is
recommended that the package be configured and built as a regular
user, and only the `make install' phase executed with root
user, and only the 'make install' phase executed with root
privileges.
5. Optionally, type `make installcheck' to repeat any self-tests, but
5. Optionally, type 'make installcheck' to repeat any self-tests, but
this time using the binaries in their final installed location.
This target does not install anything. Running this target as a
regular user, particularly if the prior `make install' required
regular user, particularly if the prior 'make install' required
root privileges, verifies that the installation completed
correctly.
6. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
source code directory by typing 'make clean'. To also remove the
files that 'configure' created (so you can compile the package for
a different kind of computer), type 'make distclean'. There is
also a 'make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
7. Often, you can also type `make uninstall' to remove the installed
7. Often, you can also type 'make uninstall' to remove the installed
files again. In practice, not all packages have tested that
uninstallation works correctly, even though it is required by the
GNU Coding Standards.
8. Some packages, particularly those that use Automake, provide `make
8. Some packages, particularly those that use Automake, provide 'make
distcheck', which can by used by developers to test that all other
targets like `make install' and `make uninstall' work correctly.
targets like 'make install' and 'make uninstall' work correctly.
This target is generally not run by end users.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. Run `./configure --help'
the 'configure' script does not know about. Run './configure --help'
for details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
You can give 'configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here is
an example:
./configure CC=c99 CFLAGS=-g LIBS=-lposix
@ -113,21 +112,21 @@ Compiling For Multiple Architectures
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you can use GNU `make'. `cd' to the
own directory. To do this, you can use GNU 'make'. 'cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'. This
is known as a "VPATH" build.
the 'configure' script. 'configure' automatically checks for the source
code in the directory that 'configure' is in and in '..'. This is known
as a "VPATH" build.
With a non-GNU `make', it is safer to compile the package for one
With a non-GNU 'make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use `make distclean' before
installed the package for one architecture, use 'make distclean' before
reconfiguring for another architecture.
On MacOS X 10.5 and later systems, you can create libraries and
executables that work on multiple system types--known as "fat" or
"universal" binaries--by specifying multiple `-arch' options to the
compiler but only a single `-arch' option to the preprocessor. Like
"universal" binaries--by specifying multiple '-arch' options to the
compiler but only a single '-arch' option to the preprocessor. Like
this:
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
@ -136,105 +135,104 @@ this:
This is not guaranteed to produce working output in all cases, you
may have to build one architecture at a time and combine the results
using the `lipo' tool if you have problems.
using the 'lipo' tool if you have problems.
Installation Names
==================
By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX', where PREFIX must be an
By default, 'make install' installs the package's commands under
'/usr/local/bin', include files under '/usr/local/include', etc. You
can specify an installation prefix other than '/usr/local' by giving
'configure' the option '--prefix=PREFIX', where PREFIX must be an
absolute file name.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
pass the option '--exec-prefix=PREFIX' to 'configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them. In general, the
default for these options is expressed in terms of `${prefix}', so that
specifying just `--prefix' will affect all of the other directory
options like '--bindir=DIR' to specify different values for particular
kinds of files. Run 'configure --help' for a list of the directories
you can set and what kinds of files go in them. In general, the default
for these options is expressed in terms of '${prefix}', so that
specifying just '--prefix' will affect all of the other directory
specifications that were not explicitly provided.
The most portable way to affect installation locations is to pass the
correct locations to `configure'; however, many packages provide one or
correct locations to 'configure'; however, many packages provide one or
both of the following shortcuts of passing variable assignments to the
`make install' command line to change installation locations without
'make install' command line to change installation locations without
having to reconfigure or recompile.
The first method involves providing an override variable for each
affected directory. For example, `make install
affected directory. For example, 'make install
prefix=/alternate/directory' will choose an alternate location for all
directory configuration variables that were expressed in terms of
`${prefix}'. Any directories that were specified during `configure',
but not in terms of `${prefix}', must each be overridden at install
time for the entire installation to be relocated. The approach of
makefile variable overrides for each directory variable is required by
the GNU Coding Standards, and ideally causes no recompilation.
However, some platforms have known limitations with the semantics of
shared libraries that end up requiring recompilation when using this
method, particularly noticeable in packages that use GNU Libtool.
'${prefix}'. Any directories that were specified during 'configure',
but not in terms of '${prefix}', must each be overridden at install time
for the entire installation to be relocated. The approach of makefile
variable overrides for each directory variable is required by the GNU
Coding Standards, and ideally causes no recompilation. However, some
platforms have known limitations with the semantics of shared libraries
that end up requiring recompilation when using this method, particularly
noticeable in packages that use GNU Libtool.
The second method involves providing the `DESTDIR' variable. For
example, `make install DESTDIR=/alternate/directory' will prepend
`/alternate/directory' before all installation names. The approach of
`DESTDIR' overrides is not required by the GNU Coding Standards, and
The second method involves providing the 'DESTDIR' variable. For
example, 'make install DESTDIR=/alternate/directory' will prepend
'/alternate/directory' before all installation names. The approach of
'DESTDIR' overrides is not required by the GNU Coding Standards, and
does not work on platforms that have drive letters. On the other hand,
it does better at avoiding recompilation issues, and works well even
when some directory options were not specified in terms of `${prefix}'
at `configure' time.
when some directory options were not specified in terms of '${prefix}'
at 'configure' time.
Optional Features
=================
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
with an extra prefix or suffix on their names by giving 'configure' the
option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'.
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
Some packages pay attention to '--enable-FEATURE' options to
'configure', where FEATURE indicates an optional part of the package.
They may also pay attention to '--with-PACKAGE' options, where PACKAGE
is something like 'gnu-as' or 'x' (for the X Window System). The
'README' should mention any '--enable-' and '--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
For packages that use the X Window System, 'configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
you can use the 'configure' options '--x-includes=DIR' and
'--x-libraries=DIR' to specify their locations.
Some packages offer the ability to configure how verbose the
execution of `make' will be. For these packages, running `./configure
execution of 'make' will be. For these packages, running './configure
--enable-silent-rules' sets the default to minimal output, which can be
overridden with `make V=1'; while running `./configure
overridden with 'make V=1'; while running './configure
--disable-silent-rules' sets the default to verbose, which can be
overridden with `make V=0'.
overridden with 'make V=0'.
Particular systems
==================
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
CC is not installed, it is recommended to use the following options in
On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC
is not installed, it is recommended to use the following options in
order to use an ANSI C compiler:
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
HP-UX `make' updates targets which have the same time stamps as
their prerequisites, which makes it generally unusable when shipped
generated files such as `configure' are involved. Use GNU `make'
instead.
HP-UX 'make' updates targets which have the same time stamps as their
prerequisites, which makes it generally unusable when shipped generated
files such as 'configure' are involved. Use GNU 'make' instead.
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
a workaround. If GNU CC is not installed, it is therefore recommended
to try
parse its '<wchar.h>' header file. The option '-nodtk' can be used as a
workaround. If GNU CC is not installed, it is therefore recommended to
try
./configure CC="cc"
@ -242,26 +240,26 @@ and if that doesn't work, try
./configure CC="cc -nodtk"
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
On Solaris, don't put '/usr/ucb' early in your 'PATH'. This
directory contains several dysfunctional programs; working variants of
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
in your `PATH', put it _after_ `/usr/bin'.
these programs are available in '/usr/bin'. So, if you need '/usr/ucb'
in your 'PATH', put it _after_ '/usr/bin'.
On Haiku, software installed for all users goes in `/boot/common',
not `/usr/local'. It is recommended to use the following options:
On Haiku, software installed for all users goes in '/boot/common',
not '/usr/local'. It is recommended to use the following options:
./configure --prefix=/boot/common
Specifying the System Type
==========================
There may be some features `configure' cannot figure out
There may be some features 'configure' cannot figure out
automatically, but needs to determine by the type of machine the package
will run on. Usually, assuming the package is built to be run on the
_same_ architectures, `configure' can figure that out, but if it prints
_same_ architectures, 'configure' can figure that out, but if it prints
a message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
'--build=TYPE' option. TYPE can either be a short name for the system
type, such as 'sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
@ -270,101 +268,101 @@ where SYSTEM can have one of these forms:
OS
KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
See the file 'config.sub' for the possible values of each field. If
'config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option `--target=TYPE' to select the type of system they will
use the option '--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
eventually be run) with '--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
If you want to set default values for 'configure' scripts to share,
you can create a site shell script called 'config.site' that gives
default values for variables like 'CC', 'cache_file', and 'prefix'.
'configure' looks for 'PREFIX/share/config.site' if it exists, then
'PREFIX/etc/config.site' if it exists. Or, you can set the
'CONFIG_SITE' environment variable to the location of the site script.
A warning: not all 'configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
environment passed to 'configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
them in the 'configure' command line, using 'VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is
causes the specified 'gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf limitation. Until the limitation is lifted, you can use
this workaround:
Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an
Autoconf limitation. Until the limitation is lifted, you can use this
workaround:
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
'configure' Invocation
======================
`configure' recognizes the following options to control how it
'configure' recognizes the following options to control how it
operates.
`--help'
`-h'
Print a summary of all of the options to `configure', and exit.
'--help'
'-h'
Print a summary of all of the options to 'configure', and exit.
`--help=short'
`--help=recursive'
'--help=short'
'--help=recursive'
Print a summary of the options unique to this package's
`configure', and exit. The `short' variant lists options used
only in the top level, while the `recursive' variant lists options
also present in any nested packages.
'configure', and exit. The 'short' variant lists options used only
in the top level, while the 'recursive' variant lists options also
present in any nested packages.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
'--version'
'-V'
Print the version of Autoconf used to generate the 'configure'
script, and exit.
`--cache-file=FILE'
'--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
traditionally 'config.cache'. FILE defaults to '/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
'--config-cache'
'-C'
Alias for '--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
'--quiet'
'--silent'
'-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
suppress all normal output, redirect it to '/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
'--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
'configure' can determine that directory automatically.
`--prefix=DIR'
Use DIR as the installation prefix. *note Installation Names::
for more details, including other options available for fine-tuning
the installation locations.
'--prefix=DIR'
Use DIR as the installation prefix. *note Installation Names:: for
more details, including other options available for fine-tuning the
installation locations.
`--no-create'
`-n'
'--no-create'
'-n'
Run the configure checks, but stop before creating any output
files.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.
'configure' also accepts some other, not widely useful, options. Run
'configure --help' for more details.

View file

@ -2,7 +2,7 @@
AUTOMAKE_OPTIONS = gnu
SUBDIRS = m4 src doc
SUBDIRS = src doc systemd
ACLOCAL_AMFLAGS = -I m4
@ -10,3 +10,6 @@ EXTRA_DIST = COPYING.README README.android
ChangeLog:
git log > ChangeLog
astyle:
astyle --options=.astylerc -nQ src/*.[ch] src/*/*.[ch]

View file

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.15 from Makefile.am.
# Makefile.in generated by automake 1.16.2 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
# 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,
@ -90,8 +90,11 @@ host_triplet = @host@
subdir = .
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/lzo.m4 \
$(top_srcdir)/m4/ax_check_link_flag.m4 \
$(top_srcdir)/m4/ax_require_defined.m4 $(top_srcdir)/m4/lzo.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/zlib.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
@ -138,9 +141,9 @@ am__recursive_targets = \
$(RECURSIVE_CLEAN_TARGETS) \
$(am__extra_recursive_targets)
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
cscope distdir dist dist-all distcheck
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
$(LISP)config.h.in
cscope distdir distdir-am dist dist-all distcheck
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \
config.h.in
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
@ -236,7 +239,6 @@ LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
OBJEXT = @OBJEXT@
@ -299,12 +301,13 @@ 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@
AUTOMAKE_OPTIONS = gnu
SUBDIRS = m4 src doc
SUBDIRS = src doc systemd
ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = COPYING.README README.android
all: config.h
@ -313,7 +316,7 @@ all: config.h
.SUFFIXES:
am--refresh: Makefile
@:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
@ -332,16 +335,16 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
echo ' $(SHELL) ./config.status'; \
$(SHELL) ./config.status;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
$(top_srcdir)/configure: $(am__configure_deps)
$(am__cd) $(srcdir) && $(AUTOCONF)
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
$(am__aclocal_m4_deps):
@ -352,7 +355,7 @@ config.h: stamp-h1
stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
@rm -f stamp-h1
cd $(top_builddir) && $(SHELL) ./config.status config.h
$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
$(srcdir)/config.h.in: $(am__configure_deps)
($(am__cd) $(top_srcdir) && $(AUTOHEADER))
rm -f stamp-h1
touch $@
@ -466,7 +469,10 @@ distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
distdir: $(DISTFILES)
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@case `sed 15q $(srcdir)/NEWS` in \
*"$(VERSION)"*) : ;; \
*) \
@ -537,7 +543,7 @@ distdir: $(DISTFILES)
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|| chmod -R a+r "$(distdir)"
dist-gzip: distdir
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz
$(am__post_remove_distdir)
dist-bzip2: distdir
@ -552,6 +558,10 @@ dist-xz: distdir
tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
$(am__post_remove_distdir)
dist-zstd: distdir
tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst
$(am__post_remove_distdir)
dist-tarZ: distdir
@echo WARNING: "Support for distribution archives compressed with" \
"legacy program 'compress' is deprecated." >&2
@ -563,7 +573,7 @@ dist-shar: distdir
@echo WARNING: "Support for shar distribution archives is" \
"deprecated." >&2
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz
$(am__post_remove_distdir)
dist-zip: distdir
@ -581,7 +591,7 @@ dist dist-all:
distcheck: dist
case '$(DIST_ARCHIVES)' in \
*.tar.gz*) \
GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\
*.tar.bz2*) \
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
*.tar.lz*) \
@ -591,9 +601,11 @@ distcheck: dist
*.tar.Z*) \
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
*.shar.gz*) \
GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
*.zip*) \
unzip $(distdir).zip ;;\
*.tar.zst*) \
zstd -dc $(distdir).tar.zst | $(am__untar) ;;\
esac
chmod -R a-w $(distdir)
chmod u+w $(distdir)
@ -770,7 +782,7 @@ uninstall-am:
am--refresh check check-am clean clean-cscope clean-generic \
cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \
dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \
distcheck distclean distclean-generic distclean-hdr \
dist-zstd distcheck distclean distclean-generic distclean-hdr \
distclean-tags distcleancheck distdir distuninstallcheck dvi \
dvi-am html html-am info info-am install install-am \
install-data install-data-am install-dvi install-dvi-am \
@ -788,6 +800,9 @@ uninstall-am:
ChangeLog:
git log > ChangeLog
astyle:
astyle --options=.astylerc -nQ src/*.[ch] src/*/*.[ch]
# 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:

84
NEWS
View file

@ -1,3 +1,85 @@
Version 1.0.36 August 26 2019
* Fix compiling tinc with certain versions of the OpenSSL library.
* Fix parsing some IPv6 addresses with :: in them.
* Fix GraphDumpFile output to handle node names starting with a digit.
* Fix a potential segmentation fault when fragmenting packets.
Thanks to Rosen Penev, Quentin Rameau and Werner Schreiber for their
contributions to this version of tinc.
Version 1.0.35 October 5 2018
* Prevent oracle attacks (CVE-2018-16737, CVE-2018-16738).
* Prevent a MITM from forcing a NULL cipher for UDP (CVE-2018-16758).
* Minor fixes in the documentation.
Thanks to Amine Amri and Rafael Sadowski for their contributions to this
version of tinc.
Version 1.0.34 June 12 2018
* Fix a potential segmentation fault when connecting to an IPv6 peer via a
proxy.
* Minor improvements to the build system.
* Make the systemd service file identical to the one from the 1.1 branch.
* Fix a potential problem causing IPv4 sockets to not work on macOS.
Thanks to Maximilian Stein and Wang Liu Shuai for their contributions to this
version of tinc.
Version 1.0.33 November 4 2017
* Allow compilation from a build directory.
* Source code cleanups.
* Fix some options specified on the command line not surviving a HUP signal.
* Handle tun/tap device returning EPERM or EBUSY.
* Disable PMTUDiscovery when TCPOnly is used.
* Support the --runstatedir option of the autoconf 2.70.
Thanks to Rafael Sadowski and Pierre-Olivier Mercier for their contributions to
this version of tinc.
Version 1.0.32 September 2 2017
* Fix segmentation fault when using Cipher = none.
* Fix Proxy = exec.
* Support PriorityInheritance for IPv6 packets.
* Fixes for Solaris tun/tap support.
* Bind outgoing TCP sockets when ListenAddress is used.
Thanks to Vittorio Gambaletta for his contribution to this version of tinc.
Version 1.0.31 January 15 2017
* Remove ExecStop in tinc@.service.
Thanks to Élie Bouttier for his contribution to this version of tinc.
Version 1.0.30 October 30 2016
* Fix troubles connecting to some HTTP proxies.
* Add mitigations for the Sweet32 attack when using a 64-bit block cipher.
* Use AES256 and SHA256 as the default encryption and digest algorithms.
Version 1.0.29 October 9 2016
* Fix UDP communication with peers with link-local IPv6 addresses.
* Ensure compatibility with OpenSSL 1.1.0.
* Ensure autoreconf can be run without requiring autoconf-archive.
* Log warnings about dropped packets only at debug level 5.
Version 1.0.28 April 10 2016
* Fix compilation on BSD platforms.
* Add systemd service files.
Version 1.0.27 April 10 2016
* When using Proxy, let the proxy resolve hostnames if tinc can't.
@ -289,7 +371,7 @@ Version 1.0.9 Dec 26 2008
* Enable path MTU discovery by default.
* Fixed a memory leak that occured when connections were closed.
* Fixed a memory leak that occurred when connections were closed.
Thanks to Max Rijevski for his contributions to this version of tinc.

50
README
View file

@ -1,7 +1,7 @@
This is the README file for tinc version 1.0.27. Installation
This is the README file for tinc version 1.0.36. Installation
instructions may be found in the INSTALL file.
tinc is Copyright (C) 1998-2016 by:
tinc is Copyright (C) 1998-2019 by:
Ivo Timmermans,
Guus Sliepen <guus@tinc-vpn.org>,
@ -39,44 +39,50 @@ 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
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
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.
Cryptography is a hard thing to get right. We cannot make any
guarantees. Time, review and feedback are the only things that can
prove the security of any cryptographic product. If you wish to review
tinc or give us feedback, you are strongly encouraged to do so.
Changes to configuration file format since 1.0pre5
--------------------------------------------------
Some configuration variables have different names now. Most notably "TapDevice"
should be changed into "Device", and "Device" should be changed into
"BindToDevice".
Compatibility
-------------
Version 1.0.27 is compatible with 1.0pre8, 1.0 and later, but not with older
versions of tinc.
Version 1.0.35 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
the VPN to be compiled with a version of LibreSSL or OpenSSL that supports the
AES256 and SHA256 algorithms.
Requirements
------------
Since 1.0pre3, we use OpenSSL for all cryptographic functions. So you
need to install this library first; grab it from
http://www.openssl.org/. You will need version 0.9.7 or later. If
this library is not installed on you system, configure will fail. The
manual in doc/tinc.texi contains more detailed information on how to
install this library.
The OpenSSL library is used for all cryptographic functions. You can find it at
https://www.openssl.org/. You will need version 1.0.1 or later with support for
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.
Since 1.0pre6, the zlib library is used for optional compression. You can
find it at http://www.gzip.org/zlib/. Because of a possible exploit in
The zlib library is used for optional compression. You can
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.
Since 1.0, the lzo library is also used for optional compression. You can
find it at http://www.oberhumer.com/opensource/lzo/.
The LZO library is also used for optional compression. You can
find it at https://www.oberhumer.com/opensource/lzo/.
In order to compile tinc, you will need a GNU C compiler environment.
In order to compile tinc, you will need a C99 compliant compiler.
Features

42
THANKS
View file

@ -1,34 +1,52 @@
We would like to thank the following people for their contributions to tinc:
* Alexander Reil and Gemeinde Berg
* Alexander Ried
* Alexis Hildebrandt
* Allesandro Gatti
* Andreas van Cranenburgh
* Andrew Hahn
* Anthony G. Basile
* Armin Fisslthaler
* Armijn Hemel
* Armin Fisslthaler
* Aron Cowan
* Ashish Bajaj
* Baptiste Jonglez
* Borg
* Brandon Black
* Cheng LI
* Cris van Pelt
* Darius Jahandarie
* Dato Simó
* David Pflug
* Delf Eldkraft
* Dennis Joachimsthaler
* dnk
* Егор Палкин
* Élie Bouttier
* Enrique Zanardi
* Erik Tews
* Etienne Dechamps
* Florent Clairambault
* Florian Forster
* Florian Klink
* Florian Weik
* Flynn Marquardt
* Franz Pletz
* Gary Kessler and Claudia Gonzalez
* Grzegorz Dymarek
* Gusariev Oleksandr
* Hans Bayle
* Harvest
* Ivo van Dong
* Ivo Smits
* James Cook
* James MacLean
* Jamie Briggs
* Jan Štembera
* Jason Harper
* Jason Livesay
* Jasper Krijgsman
* Jelle de Jong
* Jeroen Domburg
* Jeroen Ubbink
@ -40,6 +58,7 @@ We would like to thank the following people for their contributions to tinc:
* Loïc Dachary
* Loïc Grenié
* Lubomír Bulej
* luckyhacky
* LunarShaddow
* Mads Kiilerich
* Marc A. Lehmann
@ -49,21 +68,33 @@ We would like to thank the following people for their contributions to tinc:
* Martin Kihlgren
* Martin Schobert
* Martin Schürrer
* Martin Weinelt
* Matias Carrasco
* Max Rijevski
* Menno Smits
* Mesar Hameed
* Michael Taylor
* Michael Tokarev
* Michael Yonli
* Miles Nordin
* Nathan Stratton Treadway
* Murat Donmez
* Nick Hibma
* Nick Patavalis
* Paul Littlefield
* Philipp Babel
* Pierre Emeriaud
* Pierre-Olivier Mercier
* Rafael Wolf
* Rafael Sadowski
* Rafał Leśniak
* Rhosyn Celyn
* Robert van der Meulen
* Robert Waniek
* Rumko
* Ryan Miller
* Sam Bryan
* Samuel Thibault
* Saverio Proto
* Scott Lamb
* Steffan Karger
@ -78,13 +109,18 @@ We would like to thank the following people for their contributions to tinc:
* Tonnerre Lombard
* Ulrich Seifert
* Vil Brekin
* Vincent Laurent
* Vittorio Gambaletta
* Wendy Willard
* Wessel Dankers
* William A. Kennington III
* William McArthur
* Wouter van Heyst
* xentec
* 戴 鸣
And everyone we forgot (if we did, please let us know). Thank you!
Ivo Timmermans
Guus Sliepen
---
Ivo Timmermans,
Guus Sliepen.

239
aclocal.m4 vendored
View file

@ -1,6 +1,6 @@
# generated automatically by aclocal 1.14.1 -*- Autoconf -*-
# generated automatically by aclocal 1.16.2 -*- Autoconf -*-
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
# Copyright (C) 1996-2020 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -20,7 +20,7 @@ You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically 'autoreconf'.])])
# Copyright (C) 2002-2013 Free Software Foundation, Inc.
# Copyright (C) 2002-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -32,10 +32,10 @@ To do so, use the procedure documented by the package, typically 'autoreconf'.])
# generated from the m4 files accompanying Automake X.Y.
# (This private macro should not be called outside this file.)
AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.14'
[am__api_version='1.16'
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.
m4_if([$1], [1.14.1], [],
m4_if([$1], [1.16.2], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
@ -51,14 +51,14 @@ m4_define([_AM_AUTOCONF_VERSION], [])
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.14.1])dnl
[AM_AUTOMAKE_VERSION([1.16.2])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
# Copyright (C) 2001-2013 Free Software Foundation, Inc.
# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -110,7 +110,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd`
# AM_CONDITIONAL -*- Autoconf -*-
# Copyright (C) 1997-2013 Free Software Foundation, Inc.
# Copyright (C) 1997-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -141,7 +141,7 @@ AC_CONFIG_COMMANDS_PRE(
Usually this means the macro was only invoked conditionally.]])
fi])])
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
# Copyright (C) 1999-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -332,13 +332,12 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl
# Generate code to set up dependency tracking. -*- Autoconf -*-
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
# Copyright (C) 1999-2020 Free Software Foundation, Inc.
#
# This file 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.
# _AM_OUTPUT_DEPENDENCY_COMMANDS
# ------------------------------
AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
@ -346,49 +345,43 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
# Older Autoconf quotes --file arguments for eval, but not when files
# are listed without --file. Let's play safe and only enable the eval
# if we detect the quoting.
case $CONFIG_FILES in
*\'*) eval set x "$CONFIG_FILES" ;;
*) set x $CONFIG_FILES ;;
esac
# TODO: see whether this extra hack can be removed once we start
# requiring Autoconf 2.70 or later.
AS_CASE([$CONFIG_FILES],
[*\'*], [eval set x "$CONFIG_FILES"],
[*], [set x $CONFIG_FILES])
shift
for mf
# Used to flag and report bootstrapping failures.
am_rc=0
for am_mf
do
# Strip MF so we end up with the name of the file.
mf=`echo "$mf" | sed -e 's/:.*$//'`
# Check whether this is an Automake generated Makefile or not.
# We used to match only the files named 'Makefile.in', but
# some people rename them; so instead we look at the file content.
# Grep'ing the first line is not enough: some people post-process
# each Makefile.in and add a new line on top of each file to say so.
# Grep'ing the whole file is not good either: AIX grep has a line
am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'`
# Check whether this is an Automake generated Makefile which includes
# dependency-tracking related rules and includes.
# Grep'ing the whole file directly is not great: AIX grep has a line
# limit of 2048, but all sed's we know have understand at least 4000.
if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
dirpart=`AS_DIRNAME("$mf")`
else
continue
fi
# Extract the definition of DEPDIR, am__include, and am__quote
# from the Makefile without running 'make'.
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
test -z "$DEPDIR" && continue
am__include=`sed -n 's/^am__include = //p' < "$mf"`
test -z "$am__include" && continue
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
# Find all dependency output files, they are included files with
# $(DEPDIR) in their names. We invoke sed twice because it is the
# simplest approach to changing $(DEPDIR) to its actual value in the
# expansion.
for file in `sed -n "
s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
# Make sure the directory exists.
test -f "$dirpart/$file" && continue
fdir=`AS_DIRNAME(["$file"])`
AS_MKDIR_P([$dirpart/$fdir])
# echo "creating $dirpart/$file"
echo '# dummy' > "$dirpart/$file"
done
sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
|| continue
am_dirpart=`AS_DIRNAME(["$am_mf"])`
am_filepart=`AS_BASENAME(["$am_mf"])`
AM_RUN_LOG([cd "$am_dirpart" \
&& sed -e '/# am--include-marker/d' "$am_filepart" \
| $MAKE -f - am--depfiles]) || am_rc=$?
done
if test $am_rc -ne 0; then
AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments
for automatic dependency tracking. If GNU make was not used, consider
re-running the configure script with MAKE="gmake" (or whatever is
necessary). You can also try re-running configure with the
'--disable-dependency-tracking' option to at least be able to build
the package (albeit without support for automatic dependency tracking).])
fi
AS_UNSET([am_dirpart])
AS_UNSET([am_filepart])
AS_UNSET([am_mf])
AS_UNSET([am_rc])
rm -f conftest-deps.mk
}
])# _AM_OUTPUT_DEPENDENCY_COMMANDS
@ -397,18 +390,17 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
# -----------------------------
# This macro should only be invoked once -- use via AC_REQUIRE.
#
# This code is only required when automatic dependency tracking
# is enabled. FIXME. This creates each '.P' file that we will
# need in order to bootstrap the dependency handling code.
# This code is only required when automatic dependency tracking is enabled.
# This creates each '.Po' and '.Plo' makefile fragment that we'll need in
# order to bootstrap the dependency handling code.
AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
[AC_CONFIG_COMMANDS([depfiles],
[test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
[AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
])
[AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])])
# Do all the work for Automake. -*- Autoconf -*-
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
# Copyright (C) 1996-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -495,11 +487,11 @@ AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
AC_REQUIRE([AC_PROG_MKDIR_P])dnl
# For better backward compatibility. To be removed once Automake 1.9.x
# dies out for good. For more background, see:
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
# We need awk for the "check" target (and possibly the TAP driver). The
# system "awk" is bad on some platforms.
AC_REQUIRE([AC_PROG_AWK])dnl
AC_REQUIRE([AC_PROG_MAKE_SET])dnl
AC_REQUIRE([AM_SET_LEADING_DOT])dnl
@ -563,7 +555,7 @@ END
Aborting the configuration process, to ensure you take notice of the issue.
You can download and install GNU coreutils to get an 'rm' implementation
that behaves properly: <http://www.gnu.org/software/coreutils/>.
that behaves properly: <https://www.gnu.org/software/coreutils/>.
If you want to complete the configuration process using your problematic
'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
@ -573,6 +565,9 @@ END
AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
fi
fi
dnl The trailing newline in this macro's definition is deliberate, for
dnl backward compatibility and to allow trailing 'dnl'-style comments
dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841.
])
dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
@ -602,7 +597,7 @@ for _am_header in $config_headers :; do
done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
# Copyright (C) 2001-2013 Free Software Foundation, Inc.
# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -613,7 +608,7 @@ echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_co
# Define $install_sh.
AC_DEFUN([AM_PROG_INSTALL_SH],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
if test x"${install_sh}" != xset; then
if test x"${install_sh+set}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
@ -623,7 +618,7 @@ if test x"${install_sh}" != xset; then
fi
AC_SUBST([install_sh])])
# Copyright (C) 2003-2013 Free Software Foundation, Inc.
# Copyright (C) 2003-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -642,45 +637,9 @@ fi
rmdir .tst 2>/dev/null
AC_SUBST([am__leading_dot])])
# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
# From Jim Meyering
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
#
# This file 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.
# AM_MAINTAINER_MODE([DEFAULT-MODE])
# ----------------------------------
# Control maintainer-specific portions of Makefiles.
# Default is to disable them, unless 'enable' is passed literally.
# For symmetry, 'disable' may be passed as well. Anyway, the user
# can override the default with the --enable/--disable switch.
AC_DEFUN([AM_MAINTAINER_MODE],
[m4_case(m4_default([$1], [disable]),
[enable], [m4_define([am_maintainer_other], [disable])],
[disable], [m4_define([am_maintainer_other], [enable])],
[m4_define([am_maintainer_other], [enable])
m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
dnl maintainer-mode's default is 'disable' unless 'enable' is passed
AC_ARG_ENABLE([maintainer-mode],
[AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode],
am_maintainer_other[ make rules and dependencies not useful
(and sometimes confusing) to the casual installer])],
[USE_MAINTAINER_MODE=$enableval],
[USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
AC_MSG_RESULT([$USE_MAINTAINER_MODE])
AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
MAINT=$MAINTAINER_MODE_TRUE
AC_SUBST([MAINT])dnl
]
)
# Check to see how 'make' treats includes. -*- Autoconf -*-
# Copyright (C) 2001-2013 Free Software Foundation, Inc.
# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -688,49 +647,42 @@ AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
# AM_MAKE_INCLUDE()
# -----------------
# Check to see how make treats includes.
# Check whether make has an 'include' directive that can support all
# the idioms we need for our automatic dependency tracking code.
AC_DEFUN([AM_MAKE_INCLUDE],
[am_make=${MAKE-make}
cat > confinc << 'END'
[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive])
cat > confinc.mk << 'END'
am__doit:
@echo this is the am__doit target
@echo this is the am__doit target >confinc.out
.PHONY: am__doit
END
# If we don't find an include directive, just comment out the code.
AC_MSG_CHECKING([for style of include used by $am_make])
am__include="#"
am__quote=
_am_result=none
# First try GNU make style include.
echo "include confinc" > confmf
# Ignore all kinds of additional output from 'make'.
case `$am_make -s -f confmf 2> /dev/null` in #(
*the\ am__doit\ target*)
am__include=include
am__quote=
_am_result=GNU
;;
esac
# Now try BSD make style include.
if test "$am__include" = "#"; then
echo '.include "confinc"' > confmf
case `$am_make -s -f confmf 2> /dev/null` in #(
*the\ am__doit\ target*)
am__include=.include
am__quote="\""
_am_result=BSD
;;
esac
fi
AC_SUBST([am__include])
AC_SUBST([am__quote])
AC_MSG_RESULT([$_am_result])
rm -f confinc confmf
])
# BSD make does it like this.
echo '.include "confinc.mk" # ignored' > confmf.BSD
# Other make implementations (GNU, Solaris 10, AIX) do it like this.
echo 'include confinc.mk # ignored' > confmf.GNU
_am_result=no
for s in GNU BSD; do
AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out])
AS_CASE([$?:`cat confinc.out 2>/dev/null`],
['0:this is the am__doit target'],
[AS_CASE([$s],
[BSD], [am__include='.include' am__quote='"'],
[am__include='include' am__quote=''])])
if test "$am__include" != "#"; then
_am_result="yes ($s style)"
break
fi
done
rm -f confinc.* confmf.*
AC_MSG_RESULT([${_am_result}])
AC_SUBST([am__include])])
AC_SUBST([am__quote])])
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
# Copyright (C) 1997-2013 Free Software Foundation, Inc.
# Copyright (C) 1997-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -769,7 +721,7 @@ fi
# Helper functions for option handling. -*- Autoconf -*-
# Copyright (C) 2001-2013 Free Software Foundation, Inc.
# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -798,7 +750,7 @@ AC_DEFUN([_AM_SET_OPTIONS],
AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
# Copyright (C) 1999-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -845,7 +797,7 @@ AC_LANG_POP([C])])
# For backward compatibility.
AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
# Copyright (C) 2001-2013 Free Software Foundation, Inc.
# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -864,7 +816,7 @@ AC_DEFUN([AM_RUN_LOG],
# Check to make sure that the build environment is sane. -*- Autoconf -*-
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
# Copyright (C) 1996-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -945,7 +897,7 @@ AC_CONFIG_COMMANDS_PRE(
rm -f conftest.file
])
# Copyright (C) 2009-2013 Free Software Foundation, Inc.
# Copyright (C) 2009-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1005,7 +957,7 @@ AC_SUBST([AM_BACKSLASH])dnl
_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
])
# Copyright (C) 2001-2013 Free Software Foundation, Inc.
# Copyright (C) 2001-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1033,7 +985,7 @@ fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
# Copyright (C) 2006-2013 Free Software Foundation, Inc.
# Copyright (C) 2006-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1052,7 +1004,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Check how to create a tarball. -*- Autoconf -*-
# Copyright (C) 2004-2013 Free Software Foundation, Inc.
# Copyright (C) 2004-2020 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1184,8 +1136,11 @@ AC_SUBST([am__untar])
]) # _AM_PROG_TAR
m4_include([m4/attribute.m4])
m4_include([m4/ax_append_flag.m4])
m4_include([m4/ax_cflags_warn_all.m4])
m4_include([m4/ax_check_compile_flag.m4])
m4_include([m4/ax_check_link_flag.m4])
m4_include([m4/ax_require_defined.m4])
m4_include([m4/lzo.m4])
m4_include([m4/openssl.m4])
m4_include([m4/zlib.m4])

17
compile
View file

@ -1,9 +1,9 @@
#! /bin/sh
# Wrapper for compilers which do not understand '-c -o'.
scriptversion=2012-10-14.11; # UTC
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
# Copyright (C) 1999-2020 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
@ -17,7 +17,7 @@ scriptversion=2012-10-14.11; # UTC
# 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, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@ -53,7 +53,7 @@ func_file_conv ()
MINGW*)
file_conv=mingw
;;
CYGWIN*)
CYGWIN* | MSYS*)
file_conv=cygwin
;;
*)
@ -67,7 +67,7 @@ func_file_conv ()
mingw/*)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin/*)
cygwin/* | msys/*)
file=`cygpath -m "$file" || echo "$file"`
;;
wine/*)
@ -255,7 +255,8 @@ EOF
echo "compile $scriptversion"
exit $?
;;
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
func_cl_wrapper "$@" # Doesn't return...
;;
esac
@ -339,9 +340,9 @@ exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

679
config.guess vendored

File diff suppressed because it is too large Load diff

View file

@ -21,6 +21,9 @@
/* Define to 1 if you have the `asprintf' function. */
#undef HAVE_ASPRINTF
/* Define to 1 if you have the `BN_GENCB_new' function. */
#undef HAVE_BN_GENCB_NEW
/* Unknown BSD variant */
#undef HAVE_BSD
@ -33,6 +36,10 @@
/* Darwin (MacOS/X) */
#undef HAVE_DARWIN
/* Define to 1 if you have the declaration of `EVP_aes_256_cfb', and to 0 if
you don't. */
#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
@ -49,6 +56,10 @@
don't. */
#undef HAVE_DECL_GETNAMEINFO
/* Define to 1 if you have the declaration of `OpenSSL_add_all_algorithms',
and to 0 if you don't. */
#undef HAVE_DECL_OPENSSL_ADD_ALL_ALGORITHMS
/* Define to 1 if you have the declaration of `res_init', and to 0 if you
don't. */
#undef HAVE_DECL_RES_INIT
@ -62,6 +73,9 @@
/* DragonFly */
#undef HAVE_DRAGONFLY
/* Define to 1 if you have the `EVP_CIPHER_CTX_new' function. */
#undef HAVE_EVP_CIPHER_CTX_NEW
/* Define to 1 if you have the `EVP_EncryptInit_ex' function. */
#undef HAVE_EVP_ENCRYPTINIT_EX
@ -80,9 +94,6 @@
/* FreeBSD */
#undef HAVE_FREEBSD
/* Define to 1 if you have the `ftime' function. */
#undef HAVE_FTIME
/* Define to 1 if you have the <getopt.h> header file. */
#undef HAVE_GETOPT_H
@ -92,9 +103,6 @@
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
/* Define to 1 if you have the `get_current_dir_name' function. */
#undef HAVE_GET_CURRENT_DIR_NAME
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
@ -230,17 +238,14 @@
/* Define to 1 if you have the `putenv' function. */
#undef HAVE_PUTENV
/* Define to 1 if you have the `random' function. */
#undef HAVE_RANDOM
/* Define to 1 if you have the `RAND_pseudo_bytes' function. */
#undef HAVE_RAND_PSEUDO_BYTES
/* Define to 1 if you have the `RAND_bytes' function. */
#undef HAVE_RAND_BYTES
/* Define to 1 if you have the <resolv.h> header file. */
#undef HAVE_RESOLV_H
/* Define to 1 if you have the `select' function. */
#undef HAVE_SELECT
/* Define to 1 if you have the `RSA_set0_key' function. */
#undef HAVE_RSA_SET0_KEY
/* Define to 1 if the system has the type `socklen_t'. */
#undef HAVE_SOCKLEN_T
@ -248,21 +253,12 @@
/* Solaris/SunOS */
#undef HAVE_SOLARIS
/* Define to 1 if you have the <stdbool.h> header file. */
#undef HAVE_STDBOOL_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
@ -272,9 +268,6 @@
/* Define to 1 if you have the `strsignal' function. */
#undef HAVE_STRSIGNAL
/* Define to 1 if you have the `strtol' function. */
#undef HAVE_STRTOL
/* Define to 1 if the system has the type `struct addrinfo'. */
#undef HAVE_STRUCT_ADDRINFO
@ -353,9 +346,6 @@
/* Define to 1 if you have the <sys/wait.h> header file. */
#undef HAVE_SYS_WAIT_H
/* Define to 1 if you have the <time.h> header file. */
#undef HAVE_TIME_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
@ -368,9 +358,6 @@
/* Define to 1 if you have the `vsyslog' function. */
#undef HAVE_VSYSLOG
/* Define to 1 if you have the `writev' function. */
#undef HAVE_WRITEV
/* have zlib compression support */
#undef HAVE_ZLIB
@ -407,12 +394,6 @@
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
#undef TM_IN_SYS_TIME
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
@ -457,15 +438,5 @@
/* Defined if the __malloc__ attribute is not supported. */
#undef __malloc__
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `int' if <sys/types.h> does not define. */
#undef pid_t
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t
/* Define to empty if the keyword `volatile' does not work. Warning: valid
code using `volatile' can become incorrect without. Disable with care. */
#undef volatile

284
config.sub vendored
View file

@ -1,8 +1,8 @@
#! /bin/sh
# Configuration validation subroutine script.
# Copyright 1992-2015 Free Software Foundation, Inc.
# Copyright 1992-2018 Free Software Foundation, Inc.
timestamp='2015-08-20'
timestamp='2018-02-22'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@ -15,7 +15,7 @@ timestamp='2015-08-20'
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
# along with this program; if not, see <https://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@ -33,7 +33,7 @@ timestamp='2015-08-20'
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
@ -53,12 +53,11 @@ timestamp='2015-08-20'
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION] CPU-MFR-OPSYS
$0 [OPTION] ALIAS
Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
Canonicalize a configuration name.
Operation modes:
Options:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
@ -68,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
Copyright 1992-2015 Free Software Foundation, Inc.
Copyright 1992-2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@ -95,7 +94,7 @@ while test $# -gt 0 ; do
*local*)
# First pass through any local machine types.
echo $1
echo "$1"
exit ;;
* )
@ -113,24 +112,24 @@ esac
# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
kopensolaris*-gnu* | \
kopensolaris*-gnu* | cloudabi*-eabi* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
android-linux)
os=-linux-android
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
;;
*)
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
if [ $basic_machine != $1 ]
then os=`echo $1 | sed 's/.*-/-/'`
basic_machine=`echo "$1" | sed 's/-[^-]*$//'`
if [ "$basic_machine" != "$1" ]
then os=`echo "$1" | sed 's/.*-/-/'`
else os=; fi
;;
esac
@ -179,44 +178,44 @@ case $os in
;;
-sco6)
os=-sco5v6
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
;;
-sco5)
os=-sco3.2v5
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
;;
-sco4)
os=-sco3.2v4
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
;;
-sco3.2.[4-9]*)
os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
;;
-sco3.2v[4-9]*)
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
;;
-sco5v6*)
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
;;
-sco*)
os=-sco3.2v2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
;;
-udk*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
;;
-isc)
os=-isc2.2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
;;
-clix*)
basic_machine=clipper-intergraph
;;
-isc*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
;;
-lynx*178)
os=-lynxos178
@ -228,10 +227,7 @@ case $os in
os=-lynxos
;;
-ptx*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
;;
-windowsnt*)
os=`echo $os | sed -e 's/windowsnt/winnt/'`
basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'`
;;
-psos*)
os=-psos
@ -264,7 +260,7 @@ case $basic_machine in
| fido | fr30 | frv | ft32 \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| hexagon \
| i370 | i860 | i960 | ia64 \
| i370 | i860 | i960 | ia16 | ia64 \
| ip2k | iq2000 \
| k1om \
| le32 | le64 \
@ -300,8 +296,9 @@ case $basic_machine in
| nios | nios2 | nios2eb | nios2el \
| ns16k | ns32k \
| open8 | or1k | or1knd | or32 \
| pdp10 | pdp11 | pj | pjl \
| pdp10 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pru \
| pyramid \
| riscv32 | riscv64 \
| rl78 | rx \
@ -315,7 +312,7 @@ case $basic_machine in
| ubicom32 \
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
| visium \
| we32k \
| wasm32 \
| x86 | xc16x | xstormy16 | xtensa \
| z8k | z80)
basic_machine=$basic_machine-unknown
@ -336,7 +333,7 @@ case $basic_machine in
basic_machine=$basic_machine-unknown
os=-none
;;
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65)
;;
ms1)
basic_machine=mt-unknown
@ -365,7 +362,7 @@ case $basic_machine in
;;
# Object if more than one company name word.
*-*-*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2
exit 1
;;
# Recognize the basic CPU types with company name.
@ -388,7 +385,7 @@ case $basic_machine in
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
| i*86-* | i860-* | i960-* | ia16-* | ia64-* \
| ip2k-* | iq2000-* \
| k1om-* \
| le32-* | le64-* \
@ -429,6 +426,7 @@ case $basic_machine in
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
| pru-* \
| pyramid-* \
| riscv32-* | riscv64-* \
| rl78-* | romp-* | rs6000-* | rx-* \
@ -445,6 +443,7 @@ case $basic_machine in
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
| vax-* \
| visium-* \
| wasm32-* \
| we32k-* \
| x86-* | x86_64-* | xc16x-* | xps100-* \
| xstormy16-* | xtensa*-* \
@ -458,7 +457,7 @@ case $basic_machine in
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
386bsd)
basic_machine=i386-unknown
basic_machine=i386-pc
os=-bsd
;;
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
@ -492,7 +491,7 @@ case $basic_machine in
basic_machine=x86_64-pc
;;
amd64-*)
basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
amdahl)
basic_machine=580-amdahl
@ -521,7 +520,7 @@ case $basic_machine in
basic_machine=i386-pc
os=-aros
;;
asmjs)
asmjs)
basic_machine=asmjs-unknown
;;
aux)
@ -537,7 +536,7 @@ case $basic_machine in
os=-linux
;;
blackfin-*)
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'`
os=-linux
;;
bluegene*)
@ -545,13 +544,13 @@ case $basic_machine in
os=-cnk
;;
c54x-*)
basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
c55x-*)
basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
c6x-*)
basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
c90)
basic_machine=c90-cray
@ -640,10 +639,18 @@ case $basic_machine in
basic_machine=rs6000-bull
os=-bosx
;;
dpx2* | dpx2*-bull)
dpx2*)
basic_machine=m68k-bull
os=-sysv3
;;
e500v[12])
basic_machine=powerpc-unknown
os=$os"spe"
;;
e500v[12]-*)
basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
os=$os"spe"
;;
ebmon29k)
basic_machine=a29k-amd
os=-ebmon
@ -733,9 +740,6 @@ case $basic_machine in
hp9k8[0-9][0-9] | hp8[0-9][0-9])
basic_machine=hppa1.0-hp
;;
hppa-next)
os=-nextstep3
;;
hppaosf)
basic_machine=hppa1.1-hp
os=-osf
@ -748,26 +752,26 @@ case $basic_machine in
basic_machine=i370-ibm
;;
i*86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
os=-sysv32
;;
i*86v4*)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
os=-sysv4
;;
i*86v)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
os=-sysv
;;
i*86sol2)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
os=-solaris2
;;
i386mach)
basic_machine=i386-mach
os=-mach
;;
i386-vsta | vsta)
vsta)
basic_machine=i386-unknown
os=-vsta
;;
@ -786,19 +790,16 @@ case $basic_machine in
os=-sysv
;;
leon-*|leon[3-9]-*)
basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'`
;;
m68knommu)
basic_machine=m68k-unknown
os=-linux
;;
m68knommu-*)
basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'`
os=-linux
;;
m88k-omron*)
basic_machine=m88k-omron
;;
magnum | m3230)
basic_machine=mips-mips
os=-sysv
@ -830,10 +831,10 @@ case $basic_machine in
os=-mint
;;
mips3*-*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`
;;
mips3*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown
;;
monitor)
basic_machine=m68k-rom68k
@ -852,7 +853,7 @@ case $basic_machine in
os=-msdos
;;
ms1-*)
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'`
;;
msys)
basic_machine=i686-pc
@ -894,7 +895,7 @@ case $basic_machine in
basic_machine=v70-nec
os=-sysv
;;
next | m*-next )
next | m*-next)
basic_machine=m68k-next
case $os in
-nextstep* )
@ -939,6 +940,12 @@ case $basic_machine in
nsr-tandem)
basic_machine=nsr-tandem
;;
nsv-tandem)
basic_machine=nsv-tandem
;;
nsx-tandem)
basic_machine=nsx-tandem
;;
op50n-* | op60c-*)
basic_machine=hppa1.1-oki
os=-proelf
@ -971,7 +978,7 @@ case $basic_machine in
os=-linux
;;
parisc-*)
basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'`
os=-linux
;;
pbd)
@ -987,7 +994,7 @@ case $basic_machine in
basic_machine=i386-pc
;;
pc98-*)
basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
pentium | p5 | k5 | k6 | nexgen | viac3)
basic_machine=i586-pc
@ -1002,16 +1009,16 @@ case $basic_machine in
basic_machine=i786-pc
;;
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
pentiumpro-* | p6-* | 6x86-* | athlon-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
pentium4-*)
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
pn)
basic_machine=pn-gould
@ -1021,23 +1028,23 @@ case $basic_machine in
ppc | ppcbe) basic_machine=powerpc-unknown
;;
ppc-* | ppcbe-*)
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
ppcle | powerpclittle | ppc-le | powerpc-little)
ppcle | powerpclittle)
basic_machine=powerpcle-unknown
;;
ppcle-* | powerpclittle-*)
basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
ppc64) basic_machine=powerpc64-unknown
;;
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
ppc64le | powerpc64little | ppc64-le | powerpc64-little)
ppc64le | powerpc64little)
basic_machine=powerpc64le-unknown
;;
ppc64le-* | powerpc64little-*)
basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
ps2)
basic_machine=i386-ibm
@ -1091,17 +1098,10 @@ case $basic_machine in
sequent)
basic_machine=i386-sequent
;;
sh)
basic_machine=sh-hitachi
os=-hms
;;
sh5el)
basic_machine=sh5le-unknown
;;
sh64)
basic_machine=sh64-unknown
;;
sparclite-wrs | simso-wrs)
simso-wrs)
basic_machine=sparclite-wrs
os=-vxworks
;;
@ -1120,7 +1120,7 @@ case $basic_machine in
os=-sysv4
;;
strongarm-* | thumb-*)
basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
sun2)
basic_machine=m68000-sun
@ -1242,6 +1242,9 @@ case $basic_machine in
basic_machine=hppa1.1-winbond
os=-proelf
;;
x64)
basic_machine=x86_64-pc
;;
xbox)
basic_machine=i686-pc
os=-mingw32
@ -1250,20 +1253,12 @@ case $basic_machine in
basic_machine=xps100-honeywell
;;
xscale-* | xscalee[bl]-*)
basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'`
;;
ymp)
basic_machine=ymp-cray
os=-unicos
;;
z8k-*-coff)
basic_machine=z8k-unknown
os=-sim
;;
z80-*-coff)
basic_machine=z80-unknown
os=-sim
;;
none)
basic_machine=none-none
os=-none
@ -1292,10 +1287,6 @@ case $basic_machine in
vax)
basic_machine=vax-dec
;;
pdp10)
# there are many clones, so DEC is not a safe bet
basic_machine=pdp10-unknown
;;
pdp11)
basic_machine=pdp11-dec
;;
@ -1305,9 +1296,6 @@ case $basic_machine in
sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
basic_machine=sparc-sun
;;
cydra)
basic_machine=cydra-cydrome
;;
@ -1327,7 +1315,7 @@ case $basic_machine in
# Make sure to match an already-canonicalized machine name.
;;
*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2
exit 1
;;
esac
@ -1335,10 +1323,10 @@ esac
# Here we canonicalize certain aliases for manufacturers.
case $basic_machine in
*-digital*)
basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'`
;;
*-commodore*)
basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'`
;;
*)
;;
@ -1349,8 +1337,8 @@ esac
if [ x"$os" != x"" ]
then
case $os in
# First match some system type aliases
# that might get confused with valid system types.
# First match some system type aliases that might get confused
# with valid system types.
# -solaris* is a basic system type, with this one exception.
-auroraux)
os=-auroraux
@ -1361,18 +1349,19 @@ case $os in
-solaris)
os=-solaris2
;;
-svr4*)
os=-sysv4
;;
-unixware*)
os=-sysv4.2uw
;;
-gnu/linux*)
os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
;;
# First accept the basic system types.
# es1800 is here to avoid being matched by es* (a different OS)
-es1800*)
os=-ose
;;
# Now accept the basic system types.
# The portable systems comes first.
# Each alternative MUST END IN A *, to match a version number.
# Each alternative MUST end in a * to match a version number.
# -sysv* is not here because it comes later, after sysvr4.
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
@ -1382,24 +1371,26 @@ case $os in
| -aos* | -aros* | -cloudabi* | -sortix* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
| -bitrig* | -openbsd* | -solidbsd* \
| -hiux* | -knetbsd* | -mirbsd* | -netbsd* \
| -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* | -cegcc* \
| -chorusos* | -chorusrdb* | -cegcc* | -glidix* \
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
| -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -morphos* | -superux* | -rtmk* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
| -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \
| -midnightbsd*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@ -1416,12 +1407,12 @@ case $os in
-nto*)
os=`echo $os | sed -e 's|nto|nto-qnx|'`
;;
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
| -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
-sim | -xray | -os68k* | -v88r* \
| -windows* | -osx | -abug | -netware* | -os9* \
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
;;
-mac*)
os=`echo $os | sed -e 's|mac|macos|'`
os=`echo "$os" | sed -e 's|mac|macos|'`
;;
-linux-dietlibc)
os=-linux-dietlibc
@ -1430,10 +1421,10 @@ case $os in
os=`echo $os | sed -e 's|linux|linux-gnu|'`
;;
-sunos5*)
os=`echo $os | sed -e 's|sunos5|solaris2|'`
os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
;;
-sunos6*)
os=`echo $os | sed -e 's|sunos6|solaris3|'`
os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
;;
-opened*)
os=-openedition
@ -1444,12 +1435,6 @@ case $os in
-wince*)
os=-wince
;;
-osfrose*)
os=-osfrose
;;
-osf*)
os=-osf
;;
-utek*)
os=-bsd
;;
@ -1474,7 +1459,7 @@ case $os in
-nova*)
os=-rtmk-nova
;;
-ns2 )
-ns2)
os=-nextstep2
;;
-nsk*)
@ -1496,7 +1481,7 @@ case $os in
-oss*)
os=-sysv3
;;
-svr4)
-svr4*)
os=-sysv4
;;
-svr3)
@ -1511,32 +1496,38 @@ case $os in
-ose*)
os=-ose
;;
-es1800*)
os=-ose
;;
-xenix)
os=-xenix
;;
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
os=-mint
;;
-aros*)
os=-aros
;;
-zvmoe)
os=-zvmoe
;;
-dicos*)
os=-dicos
;;
-pikeos*)
# Until real need of OS specific support for
# particular features comes up, bare metal
# configurations are quite functional.
case $basic_machine in
arm*)
os=-eabi
;;
*)
os=-elf
;;
esac
;;
-nacl*)
;;
-ios)
;;
-none)
;;
*)
# Get rid of the `-' at the beginning of $os.
os=`echo $os | sed 's/[^-]*-//'`
echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2
exit 1
;;
esac
@ -1626,12 +1617,12 @@ case $basic_machine in
sparc-* | *-sun)
os=-sunos4.1.1
;;
pru-*)
os=-elf
;;
*-be)
os=-beos
;;
*-haiku)
os=-haiku
;;
*-ibm)
os=-aix
;;
@ -1671,7 +1662,7 @@ case $basic_machine in
m88k-omron*)
os=-luna
;;
*-next )
*-next)
os=-nextstep
;;
*-sequent)
@ -1686,9 +1677,6 @@ case $basic_machine in
i370-*)
os=-mvs
;;
*-next)
os=-nextstep3
;;
*-gould)
os=-sysv
;;
@ -1798,15 +1786,15 @@ case $basic_machine in
vendor=stratus
;;
esac
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"`
;;
esac
echo $basic_machine$os
echo "$basic_machine$os"
exit
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# eval: (add-hook 'write-file-functions 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"

797
configure vendored

File diff suppressed because it is too large Load diff

View file

@ -1,11 +1,11 @@
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
AC_INIT([tinc], [1.0.27])
AC_INIT([tinc], [1.0.36])
AC_CONFIG_SRCDIR([src/tincd.c])
AM_INIT_AUTOMAKE([1.11 check-news std-options subdir-objects nostdinc silent-rules -Wall])
AC_CONFIG_HEADERS([config.h])
AM_MAINTAINER_MODE
AC_CONFIG_MACRO_DIR([m4])
AM_SILENT_RULES([yes])
# Enable GNU extensions.
@ -114,6 +114,17 @@ AC_ARG_WITH(windows2000,
]
)
AC_ARG_WITH(systemd,
AS_HELP_STRING([--with-systemd@<:@=DIR@:>@], [install systemd service files @<:@to DIR if specified@:>@]),
[ systemd=true; systemd_path="$with_systemd" ],
[ systemd=false ]
)
AS_IF([test "x$with_systemd" = "xyes"], [systemd_path="\${libdir}/systemd/system"],
[AS_IF([test "x$with_systemd" = "xno"], [systemd=false])])
AC_SUBST(systemd_path, $systemd_path)
AM_CONDITIONAL(LINUX, test "$linux" = true)
AM_CONDITIONAL(BSD, test "$bsd" = true)
AM_CONDITIONAL(SOLARIS, test "$solaris" = true)
@ -122,6 +133,7 @@ AM_CONDITIONAL(CYGWIN, test "$cygwin" = true)
AM_CONDITIONAL(UML, test "$uml" = true)
AM_CONDITIONAL(VDE, test "$vde" = true)
AM_CONDITIONAL(TUNEMU, test "$tunemu" = true)
AM_CONDITIONAL(WITH_SYSTEMD, test "$systemd" = true)
AC_CACHE_SAVE
@ -135,6 +147,8 @@ fi
dnl Compiler hardening flags
dnl No -fstack-protector-all because it doesn't work on all platforms or architectures.
AX_CFLAGS_WARN_ALL(CFLAGS)
AC_ARG_ENABLE([hardening], AS_HELP_STRING([--disable-hardening], [disable compiler and linker hardening flags]))
AS_IF([test "x$enable_hardening" != "xno"],
[AX_CHECK_COMPILE_FLAG([-DFORTIFY_SOURCE=2], [CPPFLAGS="$CPPFLAGS -DFORTIFY_SOURCE=2"])
@ -160,36 +174,30 @@ dnl Checks for libraries.
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.
AC_HEADER_STDC
AC_CHECK_HEADERS([stdbool.h syslog.h sys/file.h sys/ioctl.h sys/mman.h sys/param.h sys/resource.h sys/socket.h sys/time.h 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/uio.h sys/wait.h netdb.h arpa/inet.h arpa/nameser.h dirent.h getopt.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],
[], [], [#include "src/have.h"]
[], [], [#include "$srcdir/src/have.h"]
)
AC_CHECK_HEADERS([netinet/if_ether.h netinet/ip.h netinet/ip6.h resolv.h],
[], [], [#include "src/have.h"]
[], [], [#include "$srcdir/src/have.h"]
)
AC_CHECK_HEADERS([netinet/tcp.h netinet/ip_icmp.h netinet/icmp6.h],
[], [], [#include "src/have.h"]
[], [], [#include "$srcdir/src/have.h"]
)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_C_VOLATILE
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_HEADER_TIME
AC_STRUCT_TM
tinc_ATTRIBUTE(__malloc__)
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], , ,
[#include "src/have.h"]
[#include "$srcdir/src/have.h"]
)
dnl Checks for library functions.
AC_TYPE_SIGNAL
AC_CHECK_FUNCS([asprintf daemon fchmod flock ftime fork get_current_dir_name gettimeofday mlockall pselect putenv random select strdup strerror strsignal strtol system unsetenv usleep vsyslog writev devname fdevname],
[], [], [#include "src/have.h"]
AC_CHECK_FUNCS([asprintf daemon fchmod flock fork gettimeofday mlockall pselect putenv strsignal system unsetenv usleep vsyslog devname fdevname],
[], [], [#include "$srcdir/src/have.h"]
)
AC_CHECK_FUNC(getopt_long, [getopt=true; AC_DEFINE(HAVE_GETOPT_LONG, 1, [getopt_long()])], [getopt=false])
@ -205,7 +213,7 @@ AC_CHECK_FUNC(gethostbyname, [], [
])
AC_CHECK_DECLS([freeaddrinfo, gai_strerror, getaddrinfo, getnameinfo],
[], [], [#include "src/have.h"]
[], [], [#include "$srcdir/src/have.h"]
)
AC_CHECK_DECLS([res_init], [AC_CHECK_LIB(resolv, res_init)], [], [
@ -229,6 +237,11 @@ AC_ARG_ENABLE(jumbograms,
]
)
AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile m4/Makefile])
dnl Ensure runstatedir is set if we are using a version of autoconf that does not support it
if test "x$runstatedir" = "x"; then
AC_SUBST([runstatedir], ['${localstatedir}/run'])
fi
AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile systemd/Makefile])
AC_OUTPUT

94
debian/changelog vendored
View file

@ -1,3 +1,97 @@
tinc (1.0.36-2) unstable; urgency=medium
* Disable support for libvdeplug. Closes: #973233
-- Guus Sliepen <guus@debian.org> Sun, 22 Nov 2020 10:40:27 +0100
tinc (1.0.36-1) unstable; urgency=medium
* New upstream version 1.0.36
* Add Vcs tags to debian/control.
* Bump Standards-Version.
-- Guus Sliepen <guus@debian.org> Mon, 26 Aug 2019 14:17:21 +0200
tinc (1.0.35-2) unstable; 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.
* 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
tinc (1.0.32-1) unstable; 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.
* Bump Standards-Version.
* Bump debian/compat.
* Add missing Depends: lsb-base.
-- Guus Sliepen <guus@debian.org> Sun, 15 Jan 2017 16:20:40 +0100
tinc (1.0.29-2) unstable; 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.
* Bump debian/compat.
-- Guus Sliepen <guus@debian.org> Mon, 10 Oct 2016 22:30:25 +0200
tinc (1.0.28-1) unstable; urgency=medium
* 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.

1
debian/compat vendored
View file

@ -1 +0,0 @@
9

10
debian/control vendored
View file

@ -2,13 +2,17 @@ Source: tinc
Section: net
Priority: optional
Maintainer: Guus Sliepen <guus@debian.org>
Standards-Version: 3.9.7
Build-Depends: libssl-dev, debhelper (>= 9), gettext, texinfo, zlib1g-dev, liblzo2-dev, libvdeplug-dev, dh-systemd
Standards-Version: 4.4.0
Build-Depends: libssl-dev, debhelper-compat (= 12), gettext, texinfo, zlib1g-dev, liblzo2-dev
Homepage: http://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
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Pre-Depends: ${misc:Pre-Depends}
Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base (>= 3.0-6)
Description: Virtual Private Network daemon
tinc is a daemon with which you can create a virtual private network
(VPN). One daemon can handle multiple connections, so you can

View file

@ -0,0 +1,65 @@
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.

View file

@ -0,0 +1,2 @@
fix-incorrect-icmpv6-checksum
support-etc-defaults-tinc

View file

@ -0,0 +1,12 @@
--- 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

7
debian/postinst vendored
View file

@ -7,14 +7,15 @@ set -e
case "$1" in
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/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
fi; fi
if [ ! -e $NETSFILE ] ; then
echo "## This file contains all names of the networks to be started on system startup." > $NETSFILE
echo "## This file contains all names of the networks to be started on system startup when using sysvinit." > $NETSFILE
echo "## If you are using systemd, use systemctl enable tinc@netname to enable individual networks." >> $NETSFILE
fi
;;

15
debian/rules vendored
View file

@ -1,19 +1,16 @@
#!/usr/bin/make -f
%:
dh $@ --parallel --with systemd
dh $@
override_dh_clean:
dh_clean
rm -f doc/tinc.info
override_dh_auto_configure:
dh_auto_configure -- --enable-uml --enable-vde
dh_auto_configure -- --enable-uml --with-systemd=/lib/systemd/system --runstatedir=/run
override_dh_auto_install:
dh_auto_install -- install-html
# Remove info dir file
rm -f debian/tinc/usr/share/info/dir
override_dh_installinit:
dh_installinit -R
dh_installinit --name=tinc@ --noscripts
override_dh_systemd_start:
dh_systemd_start --restart-after-upgrade

View file

@ -2,28 +2,40 @@
set -e
if [ "$IF_TINC_NET" ] ; then
EXTRA=""
if [ -n "$IF_TINC_PIDFILE" ]; then
EXTRA="--pidfile=$IF_TINC_PIDFILE"
else
IF_TINC_PIDFILE=/var/run/tinc.$IF_TINC_NET.pid
fi
/usr/sbin/tincd -n "$IF_TINC_NET" -k $EXTRA
sleep 0.1
i=0;
while [ -f $IF_TINC_PIDFILE ] && read pid rest < $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
sleep 0.1
i=$(($i+1))
done
if [ "$METHOD" = loopback -o -z "$IF_TINC_NET" ]; then
exit 0
fi
# Determine location of the PID file
EXTRA=""
if [ -n "$IF_TINC_PIDFILE" ]; then
EXTRA="--pidfile=$IF_TINC_PIDFILE"
else
IF_TINC_PIDFILE=/var/run/tinc.$IF_TINC_NET.pid
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

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

@ -2,13 +2,13 @@
set -e
if [ -z "$IF_TINC_NET" ]; then
if [ "$METHOD" = loopback -o -z "$IF_TINC_NET" ]; then
exit 0
fi
# Read options from /etc/default
. /etc/default/tinc
[ -r /etc/default/tinc ] && . /etc/default/tinc
# Set process limits
@ -43,14 +43,14 @@ test -n "$LIMITS" && setlimits $LIMITS
# Wait for it to come up properly
sleep 0.1
/bin/sleep 0.1
i=0;
while [ ! -f $IF_TINC_PIDFILE ] ; do
if [ $i = '30' ] ; then
echo 'Failed to start tinc daemon!'
exit 1
fi
sleep 0.1
/bin/sleep 0.1
i=$(($i+1))
done
@ -63,7 +63,7 @@ while read pid rest < $IF_TINC_PIDFILE ; do
echo 'Failed to start tinc daemon!'
exit 1
fi
sleep 0.1
/bin/sleep 0.1
i=$(($i+1))
done

6
debian/tinc.init vendored
View file

@ -82,7 +82,7 @@ stop() {
$DAEMON -n $1 -k || return
i=0;
sleep 0.5
/bin/sleep 0.5
# Wait for the pidfile to disappear
while [ -f /var/run/tinc.$1.pid ]; do
@ -91,14 +91,14 @@ stop() {
if [ $i = '10' ] ; then
# It's still alive, kill it again and give up
$DAEMON -n $1 -k && sleep 0.5
$DAEMON -n $1 -k && /bin/sleep 0.5
break
else
echo -n "."
i=$(($i+1))
fi
sleep 0.5
/bin/sleep 0.5
done
}

17
debian/tinc@.service vendored
View file

@ -1,17 +0,0 @@
[Unit]
Description=Tinc net %i
PartOf=tinc.service
ReloadPropagatedFrom=tinc.service
[Service]
Type=simple
WorkingDirectory=/etc/tinc/%i
ExecStart=/usr/sbin/tincd -n %i -D
ExecReload=/usr/sbin/tincd -n %i -kHUP
ExecStop=/usr/sbin/tincd -n %i -k
TimeoutStopSec=5
Restart=always
RestartSec=60
[Install]
WantedBy=tinc.service

10
depcomp
View file

@ -1,9 +1,9 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2013-05-30.07; # UTC
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
# Copyright (C) 1999-2020 Free Software Foundation, Inc.
# 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
@ -16,7 +16,7 @@ scriptversion=2013-05-30.07; # UTC
# 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, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@ -783,9 +783,9 @@ exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

View file

@ -1,26 +1,16 @@
## Process this file with automake to get Makefile.in
info_TEXINFOS = tinc.texi
tinc_TEXINFOS = tincinclude.texi
man_MANS = tincd.8 tinc.conf.5
EXTRA_DIST = tincinclude.texi.in tincd.8.in tinc.conf.5.in sample-config.tar.gz
EXTRA_DIST = tincinclude.texi.in tincd.8.in tinc.conf.5.in sample-config
CLEANFILES = *.html tincd.8 tinc.conf.5 tincinclude.texi
# Use `ginstall' in the definition of man_MANS to avoid
# confusion with the `install' target. The install rule transforms `ginstall'
# to install before applying any user-specified name transformations.
transform = s/ginstall/install/; @program_transform_name@
# For additional rules usually of interest only to the maintainer,
# see GNUmakefile and Makefile.maint.
sample-config.tar.gz: sample-config
$(AM_V_GEN)GZIP=$(GZIP_ENV) $(AMTAR) chozf sample-config.tar.gz --exclude .svn sample-config
texi2html: tinc.texi
$(AM_V_GEN)texi2html -split=chapter tinc.texi
$(AM_V_GEN)texi2html -split=chapter $<
tincd.8.html: tincd.8
$(AM_V_GEN)w3mman2html $< > $@
@ -32,15 +22,14 @@ substitute = sed \
-e s,'@PACKAGE\@',"$(PACKAGE)",g \
-e s,'@VERSION\@',"$(VERSION)",g \
-e s,'@sysconfdir\@',"$(sysconfdir)",g \
-e s,'@runstatedir\@',"$(runstatedir)",g \
-e s,'@localstatedir\@',"$(localstatedir)",g
tincd.8: tincd.8.in
$(AM_V_GEN)$(substitute) tincd.8.in > tincd.8
tincd.8: $(srcdir)/tincd.8.in
$(AM_V_GEN)$(substitute) $(srcdir)/tincd.8.in > $@
tinc.conf.5: tinc.conf.5.in
$(AM_V_GEN)$(substitute) tinc.conf.5.in > tinc.conf.5
tinc.conf.5: $(srcdir)/tinc.conf.5.in
$(AM_V_GEN)$(substitute) $(srcdir)/tinc.conf.5.in > $@
tincinclude.texi: tincinclude.texi.in
$(AM_V_GEN)$(substitute) tincinclude.texi.in > tincinclude.texi
tinc.texi: tincinclude.texi
tincinclude.texi: $(srcdir)/tincinclude.texi.in
$(AM_V_GEN)$(substitute) $(srcdir)/tincinclude.texi.in > $@

View file

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.15 from Makefile.am.
# Makefile.in generated by automake 1.16.2 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
# 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,
@ -78,6 +78,7 @@ 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 = :
@ -89,8 +90,11 @@ host_triplet = @host@
subdir = doc
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/lzo.m4 \
$(top_srcdir)/m4/ax_check_link_flag.m4 \
$(top_srcdir)/m4/ax_require_defined.m4 $(top_srcdir)/m4/lzo.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/zlib.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
@ -193,13 +197,8 @@ man8dir = $(mandir)/man8
NROFF = nroff
MANS = $(man_MANS)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
am__DIST_COMMON = $(srcdir)/Makefile.in texinfo.tex
am__DIST_COMMON = $(srcdir)/Makefile.in $(tinc_TEXINFOS) texinfo.tex
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
# Use `ginstall' in the definition of man_MANS to avoid
# confusion with the `install' target. The install rule transforms `ginstall'
# to install before applying any user-specified name transformations.
transform = s/ginstall/install/; @program_transform_name@
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
@ -230,7 +229,6 @@ LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
OBJEXT = @OBJEXT@
@ -293,25 +291,28 @@ 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@
info_TEXINFOS = tinc.texi
tinc_TEXINFOS = tincinclude.texi
man_MANS = tincd.8 tinc.conf.5
EXTRA_DIST = tincinclude.texi.in tincd.8.in tinc.conf.5.in sample-config.tar.gz
EXTRA_DIST = tincinclude.texi.in tincd.8.in tinc.conf.5.in sample-config
CLEANFILES = *.html tincd.8 tinc.conf.5 tincinclude.texi
substitute = sed \
-e s,'@PACKAGE\@',"$(PACKAGE)",g \
-e s,'@VERSION\@',"$(VERSION)",g \
-e s,'@sysconfdir\@',"$(sysconfdir)",g \
-e s,'@runstatedir\@',"$(runstatedir)",g \
-e s,'@localstatedir\@',"$(localstatedir)",g
all: all-am
.SUFFIXES:
.SUFFIXES: .dvi .html .info .pdf .ps .texi
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
@ -328,16 +329,16 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
@ -384,10 +385,10 @@ $(am__aclocal_m4_deps):
else \
rm -rf $(@:.html=.htp); exit 1; \
fi
$(srcdir)/tinc.info: tinc.texi
tinc.dvi: tinc.texi
tinc.pdf: tinc.texi
tinc.html: tinc.texi
$(srcdir)/tinc.info: tinc.texi $(tinc_TEXINFOS)
tinc.dvi: tinc.texi $(tinc_TEXINFOS)
tinc.pdf: tinc.texi $(tinc_TEXINFOS)
tinc.html: tinc.texi $(tinc_TEXINFOS)
.dvi.ps:
$(AM_V_DVIPS)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
$(DVIPS) $(AM_V_texinfo) -o $@ $<
@ -574,7 +575,10 @@ ctags CTAGS:
cscope cscopelist:
distdir: $(DISTFILES)
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
@ -826,14 +830,8 @@ uninstall-man: uninstall-man5 uninstall-man8
.PRECIOUS: Makefile
# For additional rules usually of interest only to the maintainer,
# see GNUmakefile and Makefile.maint.
sample-config.tar.gz: sample-config
$(AM_V_GEN)GZIP=$(GZIP_ENV) $(AMTAR) chozf sample-config.tar.gz --exclude .svn sample-config
texi2html: tinc.texi
$(AM_V_GEN)texi2html -split=chapter tinc.texi
$(AM_V_GEN)texi2html -split=chapter $<
tincd.8.html: tincd.8
$(AM_V_GEN)w3mman2html $< > $@
@ -841,16 +839,14 @@ tincd.8.html: tincd.8
tinc.conf.5.html: tinc.conf.5
$(AM_V_GEN)w3mman2html $< > $@
tincd.8: tincd.8.in
$(AM_V_GEN)$(substitute) tincd.8.in > tincd.8
tincd.8: $(srcdir)/tincd.8.in
$(AM_V_GEN)$(substitute) $(srcdir)/tincd.8.in > $@
tinc.conf.5: tinc.conf.5.in
$(AM_V_GEN)$(substitute) tinc.conf.5.in > tinc.conf.5
tinc.conf.5: $(srcdir)/tinc.conf.5.in
$(AM_V_GEN)$(substitute) $(srcdir)/tinc.conf.5.in > $@
tincinclude.texi: tincinclude.texi.in
$(AM_V_GEN)$(substitute) tincinclude.texi.in > tincinclude.texi
tinc.texi: tincinclude.texi
tincinclude.texi: $(srcdir)/tincinclude.texi.in
$(AM_V_GEN)$(substitute) $(srcdir)/tincinclude.texi.in > $@
# 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.

Binary file not shown.

View file

@ -0,0 +1,15 @@
# Sample host configuration file
# The real IP address of this tinc host. Can be used by other tinc hosts.
Address = 123.234.35.67
# Portnumber for incoming connections. Default is 655.
Port = 655
# Subnet on the virtual private network that is local for this host.
Subnet = 192.168.1.0/24
# The public key generated by `tincd -n example -K' is stored here
-----BEGIN RSA PUBLIC KEY-----
...
-----END RSA PUBLIC KEY-----

View file

@ -0,0 +1,16 @@
# Sample host configuration file
# This file was generated by host beta.
# The real IP address of this tinc host. Can be used by other tinc hosts.
Address = 123.45.67.189
# Portnumber for incoming connections. Default is 655.
Port = 6500
# Subnet on the virtual private network that is local for this host.
Subnet = 192.168.2.0/24
# The public key generated by `tincd -n example -K' is stored here
-----BEGIN RSA PUBLIC KEY-----
...
-----END RSA PUBLIC KEY-----

View file

@ -0,0 +1 @@
# Generate this file with `tincd -n example -K`

View file

@ -0,0 +1,4 @@
#!/bin/sh
# This file closes down the tap device.
ifconfig $INTERFACE down

11
doc/sample-config/tinc-up Normal file
View file

@ -0,0 +1,11 @@
#!/bin/sh
# This file sets up the tap device.
# It gives you the freedom to do anything you want with it.
# Use the correct name for the tap device:
# The environment variable $INTERFACE is set to the right name
# on most platforms, but if it doesn't work try to set it manually.
# Give it the right ip and netmask. Remember, the subnet of the
# tap device must be larger than that of the individual Subnets
# as defined in the host configuration file!
ifconfig $INTERFACE 192.168.1.1 netmask 255.255.0.0

View file

@ -0,0 +1,22 @@
# Sample tinc configuration file
# This is a comment.
# Spaces and tabs are eliminated.
# The = sign isn't strictly necessary any longer, though you may want
# to leave it in as it improves readability :)
# Variable names are treated case insensitive.
# The name of this tinc host. Required.
Name = alpha
# The internet host to connect with.
# Comment these out to make yourself a listen-only connection
# You must use the name of another tinc host.
# May be used multiple times for redundance.
ConnectTo = beta
# The tap device tinc will use.
# /dev/tap0 for ethertap, FreeBSD or OpenBSD
# /dev/tun0 for Solaris
# /dev/net/tun for Linux tun/tap
Device = /dev/net/tun

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
.Dd 2016-04-10
.Dd 2016-10-29
.Dt TINC.CONF 5
.\" Manual page created by:
.\" Ivo Timmermans
@ -222,7 +222,7 @@ Also note that this can cause decrypted VPN packets to be sent out on a real net
Create a UNIX socket with the filename specified by
.Va Device ,
or
.Pa @localstatedir@/run/ Ns Ar NETNAME Ns Pa .umlsocket
.Pa @runstatedir@/ Ns Ar NETNAME Ns Pa .umlsocket
if not specified.
.Nm tinc
will wait for a User Mode Linux instance to connect to this socket.
@ -231,7 +231,7 @@ Uses the libvdeplug library to connect to a Virtual Distributed Ethernet switch,
using the UNIX socket specified by
.Va Device ,
or
.Pa @localstatedir@/run/vde.ctl
.Pa @runstatedir@/vde.ctl
if not specified.
.El
Also, in case tinc does not seem to correctly interpret packets received from the virtual network device,
@ -468,9 +468,9 @@ 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 OpenSSL is recognised.
Any cipher supported by LibreSSL or OpenSSL is recognised.
Furthermore, specifying
.Qq none
will turn off packet encryption.
@ -483,9 +483,9 @@ Fragmentation Needed or Packet too Big messages are dropped by firewalls.
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),
10 (fast lzo) and 11 (best lzo).
.It Va Digest Li = Ar digest Pq sha1
.It Va Digest Li = Ar digest Pq sha256
The digest algorithm used to authenticate UDP packets.
Any digest supported by OpenSSL is recognised.
Any digest supported by LibreSSL or OpenSSL is recognised.
Furthermore, specifying
.Qq none
will turn off packet authentication.
@ -657,7 +657,7 @@ its connection to the virtual network device.
.El
.Sh SEE ALSO
.Xr tincd 8 ,
.Pa http://www.tinc-vpn.org/ ,
.Pa https://www.tinc-vpn.org/ ,
.Pa http://www.tldp.org/LDP/nag2/ .
.Pp
The full documentation for

View file

@ -1,14 +1,14 @@
This is tinc.info, produced by makeinfo version 6.1 from tinc.texi.
This is tinc.info, produced by makeinfo version 6.7 from tinc.texi.
INFO-DIR-SECTION Networking tools
START-INFO-DIR-ENTRY
* tinc: (tinc). The tinc Manual.
END-INFO-DIR-ENTRY
This is the info manual for tinc version 1.0.27, a Virtual Private
This is the info manual for tinc version 1.0.36, a Virtual Private
Network daemon.
Copyright (C) 1998-2016 Ivo Timmermans, Guus Sliepen
Copyright (C) 1998-2019 Ivo Timmermans, Guus Sliepen
<guus@tinc-vpn.org> and Wessel Dankers <wsl@tinc-vpn.org>.
Permission is granted to make and distribute verbatim copies of this
@ -117,10 +117,10 @@ for both the receiving and sending end, it has become largely
runtime-configurable--in short, it has become a full-fledged
professional package.
Tinc also allows more than two sites to connect to eachother and form
a single VPN. Traditionally VPNs are created by making tunnels, which
only have two endpoints. Larger VPNs with more sites are created by
adding more tunnels. Tinc takes another approach: only endpoints are
Tinc also allows more than two sites to connect to each other and
form a single VPN. Traditionally VPNs are created by making tunnels,
which only have two endpoints. Larger VPNs with more sites are created
by adding more tunnels. Tinc takes another approach: only endpoints are
specified, the software itself will take care of creating the tunnels.
This allows for easier configuration and improved scalability.
@ -147,7 +147,7 @@ will most likely compile and run, but it will not be able to send or
receive data packets.
For an up to date list of supported platforms, please check the list
on our website: <http://www.tinc-vpn.org/platforms/>.
on our website: <https://www.tinc-vpn.org/platforms/>.

File: tinc.info, Node: Preparations, Next: Installation, Prev: Introduction, Up: Top
@ -219,12 +219,8 @@ File: tinc.info, Node: Configuration of OpenBSD kernels, Next: Configuration o
2.1.3 Configuration of OpenBSD kernels
--------------------------------------
For OpenBSD version 2.9 and higher, the tun driver is included in the
default kernel configuration. There is also a kernel patch from
<http://diehard.n-r-g.com/stuff/openbsd/> which adds a tap device to
OpenBSD which should work with tinc, but with recent versions of
OpenBSD, a tun device can act as a tap device by setting the link0
option with ifconfig.
Recent versions of OpenBSD come with both tun and tap devices enabled in
the default kernel configuration.

File: tinc.info, Node: Configuration of NetBSD kernels, Next: Configuration of Solaris kernels, Prev: Configuration of OpenBSD kernels, Up: Configuring the kernel
@ -247,7 +243,7 @@ For Solaris 8 (SunOS 5.8) and higher, the tun driver may or may not be
included in the default kernel configuration. If it isn't, the source
can be downloaded from <http://vtun.sourceforge.net/tun/>. For x86 and
sparc64 architectures, precompiled versions can be found at
<http://www.monkey.org/~dugsong/fragroute/>. If the 'net/if_tun.h'
<https://www.monkey.org/~dugsong/fragroute/>. If the 'net/if_tun.h'
header file is missing, install it from the source package.

@ -274,7 +270,8 @@ File: tinc.info, Node: Configuration of Windows, Prev: Configuration of Darwin
------------------------------
You will need to install the latest TAP-Win32 driver from OpenVPN. You
can download it from <http://openvpn.sourceforge.net>. Using the
can download it from
<https://openvpn.net/index.php/open-source/downloads.html>. Using the
Network Connections control panel, configure the TAP-Win32 network
interface in the same way as you would do from the tinc-up script, as
explained in the rest of the documentation.
@ -285,25 +282,25 @@ File: tinc.info, Node: Libraries, Prev: Configuring the kernel, Up: Preparati
2.2 Libraries
=============
Before you can configure or build tinc, you need to have the OpenSSL,
zlib and lzo libraries installed on your system. If you try to
Before you can configure or build tinc, you need to have the LibreSSL or
OpenSSL, zlib and lzo libraries installed on your system. If you try to
configure tinc without having them installed, configure will give you an
error message, and stop.
* Menu:
* OpenSSL::
* LibreSSL/OpenSSL::
* zlib::
* lzo::

File: tinc.info, Node: OpenSSL, Next: zlib, Up: Libraries
File: tinc.info, Node: LibreSSL/OpenSSL, Next: zlib, Up: Libraries
2.2.1 OpenSSL
-------------
2.2.1 LibreSSL/OpenSSL
----------------------
For all cryptography-related functions, tinc uses the functions provided
by the OpenSSL library.
by the LibreSSL or the OpenSSL library.
If this library is not installed, you will get an error when
configuring tinc for build. Support for running tinc with other
@ -313,19 +310,22 @@ cryptographic libraries installed _may_ be added in the future.
if available. Make sure you install the development AND runtime
versions of this package.
If you have to install OpenSSL manually, you can get the source code
from <http://www.openssl.org/>. Instructions on how to configure, build
and install this package are included within the package. Please make
sure you build development and runtime libraries (which is the default).
If your operating system comes neither with LibreSSL or OpenSSL, you
have to install one manually. It is recommended that you get the latest
version of LibreSSL from <http://www.libressl.org/>. Instructions on
how to configure, build and install this package are included within the
package. Please make sure you build development and runtime libraries
(which is the default).
If you installed the OpenSSL libraries from source, it may be
necessary to let configure know where they are, by passing configure one
of the -with-openssl-* parameters.
If you installed the LibreSSL or OpenSSL libraries from source, it
may be necessary to let configure know where they are, by passing
configure one of the -with-openssl-* parameters. Note that you even
have to use -with-openssl-* if you are using LibreSSL.
--with-openssl=DIR OpenSSL library and headers prefix
--with-openssl-include=DIR OpenSSL headers directory
--with-openssl=DIR LibreSSL/OpenSSL library and headers prefix
--with-openssl-include=DIR LibreSSL/OpenSSL headers directory
(Default is OPENSSL_DIR/include)
--with-openssl-lib=DIR OpenSSL library directory
--with-openssl-lib=DIR LibreSSL/OpenSSL library directory
(Default is OPENSSL_DIR/lib)
License
@ -334,7 +334,7 @@ License
The complete source code of tinc is covered by the GNU GPL version 2.
Since the license under which OpenSSL is distributed is not directly
compatible with the terms of the GNU GPL
<http://www.openssl.org/support/faq.html#LEGAL2>, we include an
<https://www.openssl.org/support/faq.html#LEGAL2>, we include an
exemption to the GPL (see also the file COPYING.README) to allow
everyone to create a statically or dynamically linked executable:
@ -347,13 +347,13 @@ everyone to create a statically or dynamically linked executable:
also present the following exemption:
Hereby I grant a special exception to the tinc VPN project
(http://www.tinc-vpn.org/) to link the LZO library with the OpenSSL
library (http://www.openssl.org).
(https://www.tinc-vpn.org/) to link the LZO library with the
OpenSSL library (https://www.openssl.org).
Markus F.X.J. Oberhumer

File: tinc.info, Node: zlib, Next: lzo, Prev: OpenSSL, Up: Libraries
File: tinc.info, Node: zlib, Next: lzo, Prev: LibreSSL/OpenSSL, Up: Libraries
2.2.2 zlib
----------
@ -373,10 +373,9 @@ if available. Make sure you install the development AND runtime
versions of this package.
If you have to install zlib manually, you can get the source code
from <http://www.gzip.org/zlib/>. Instructions on how to configure,
build and install this package are included within the package. Please
make sure you build development and runtime libraries (which is the
default).
from <https://zlib.net/>. Instructions on how to configure, build and
install this package are included within the package. Please make sure
you build development and runtime libraries (which is the default).

File: tinc.info, Node: lzo, Prev: zlib, Up: Libraries
@ -398,7 +397,7 @@ if available. Make sure you install the development AND runtime
versions of this package.
If you have to install lzo manually, you can get the source code from
<http://www.oberhumer.com/opensource/lzo/>. Instructions on how to
<https://www.oberhumer.com/opensource/lzo/>. Instructions on how to
configure, build and install this package are included within the
package. Please make sure you build development and runtime libraries
(which is the default).
@ -416,9 +415,7 @@ startup scripts and sample configurations.
If you cannot use one of the precompiled packages, or you want to
compile tinc for yourself, you can use the source. The source is
distributed under the GNU General Public License (GPL). Download the
source from the download page (http://www.tinc-vpn.org/download/), which
has the checksums of these files listed; you may wish to check these
with md5sum before continuing.
source from the download page (https://www.tinc-vpn.org/download/).
Tinc comes in a convenient autoconf/automake package, which you can
just treat the same as any other package. Which is just untar it, type
@ -456,13 +453,13 @@ File: tinc.info, Node: Darwin (Mac OS X) build environment, Next: Cygwin (Wind
3.1.1 Darwin (Mac OS X) build environment
-----------------------------------------
In order to build tinc on Darwin, you need to install the Mac OS X
Developer Tools from <http://developer.apple.com/tools/macosxtools.html>
and preferably a recent version of Fink from
<http://www.finkproject.org/>.
In order to build tinc on Darwin, you need to install Xcode from
<https://developer.apple.com/xcode/>. It might also help to install a
recent version of Fink from <http://www.finkproject.org/>.
After installation use fink to download and install the following
packages: autoconf25, automake, dlcompat, m4, openssl, zlib and lzo.
You need to download and install LibreSSL (or OpenSSL) and LZO,
either directly from their websites (see *note Libraries::) or using
Fink.

File: tinc.info, Node: Cygwin (Windows) build environment, Next: MinGW (Windows) build environment, Prev: Darwin (Mac OS X) build environment, Up: Building and installing tinc
@ -471,7 +468,7 @@ File: tinc.info, Node: Cygwin (Windows) build environment, Next: MinGW (Window
----------------------------------------
If Cygwin hasn't already been installed, install it directly from
<http://www.cygwin.com/>.
<https://www.cygwin.com/>.
When tinc is compiled in a Cygwin environment, it can only be run in
this environment, but all programs, including those started outside the
@ -485,7 +482,8 @@ File: tinc.info, Node: MinGW (Windows) build environment, Prev: Cygwin (Window
---------------------------------------
You will need to install the MinGW environment from
<http://www.mingw.org>.
<http://www.mingw.org>. You also need to download and install LibreSSL
(or OpenSSL) and LZO.
When tinc is compiled using MinGW it runs natively under Windows, it
is not necessary to keep MinGW installed.
@ -793,13 +791,13 @@ DeviceType = <TYPE> (platform dependent)
uml (not compiled in by default)
Create a UNIX socket with the filename specified by DEVICE, or
'/var/run/NETNAME.umlsocket' if not specified. Tinc will wait
for a User Mode Linux instance to connect to this socket.
'/run/NETNAME.umlsocket' if not specified. Tinc will wait for
a User Mode Linux instance to connect to this socket.
vde (not compiled in by default)
Uses the libvdeplug library to connect to a Virtual
Distributed Ethernet switch, using the UNIX socket specified
by DEVICE, or '/var/run/vde.ctl' if not specified.
by DEVICE, or '/run/vde.ctl' if not specified.
Also, in case tinc does not seem to correctly interpret packets
received from the virtual network device, it can be used to change
@ -983,7 +981,7 @@ ProcessPriority = <low|normal|high>
adjusted. Increasing the priority may help to reduce latency and
packet loss on the VPN.
Proxy = socks4 | socks5 | http | exec ... [experimental]
Proxy = socks4 | socks5 | http | exec ... [experimental]
Use a proxy when making outgoing connections. The following proxy
types are currently supported:
@ -1055,11 +1053,11 @@ Address = <IP ADDRESS|HOSTNAME> [<port>] [recommended]
can be specified, in which case each address will be tried until a
working connection has been established.
Cipher = <CIPHER> (blowfish)
Cipher = <CIPHER> (aes-256-cbc)
The symmetric cipher algorithm used to encrypt UDP packets. Any
cipher supported by OpenSSL is recognized. Furthermore, specifying
"none" will turn off packet encryption. It is best to use only
those ciphers which support CBC mode.
cipher supported by LibreSSL or OpenSSL is recognized.
Furthermore, specifying "none" will turn off packet encryption. It
is best to use only those ciphers which support CBC mode.
ClampMSS = <yes|no> (yes)
This option specifies whether tinc should clamp the maximum segment
@ -1072,10 +1070,10 @@ Compression = <LEVEL> (0)
Possible values are 0 (off), 1 (fast zlib) and any integer up to 9
(best zlib), 10 (fast lzo) and 11 (best lzo).
Digest = <DIGEST> (sha1)
Digest = <DIGEST> (sha256)
The digest algorithm used to authenticate UDP packets. Any digest
supported by OpenSSL is recognized. Furthermore, specifying "none"
will turn off packet authentication.
supported by LibreSSL or OpenSSL is recognized. Furthermore,
specifying "none" will turn off packet authentication.
IndirectData = <yes|no> (no)
This option specifies whether other tinc daemons besides the one
@ -1137,7 +1135,7 @@ Subnet = <ADDRESS[/PREFIXLENGTH[#WEIGHT]]>
Prefixlength is the number of bits set to 1 in the netmask part;
for example: netmask 255.255.255.0 would become /24, 255.255.252.0
becomes /22. This conforms to standard CIDR notation as described
in RFC1519 (http://www.ietf.org/rfc/rfc1519.txt)
in RFC1519 (https://www.ietf.org/rfc/rfc1519.txt)
A Subnet can be given a weight to indicate its priority over
identical Subnets owned by different nodes. The default weight is
@ -1599,7 +1597,7 @@ command line options.
'/var/log/tinc.NETNAME.log'.
'--pidfile=FILE'
Write PID to FILE instead of '/var/run/tinc.NETNAME.pid'.
Write PID to FILE instead of '/run/tinc.NETNAME.pid'.
'--bypass-security'
Disables encryption and authentication. Only useful for debugging.
@ -1611,12 +1609,16 @@ command line options.
chroot is performed after all the initialization is done, after
writing pid files and opening network sockets.
Note that this option alone does not do any good without -U/-user,
below.
This option is best used in combination with the -U/-user option
described below.
Note also that tinc can't run scripts anymore (such as tinc-down or
host-up), unless it's setup to be runnable inside chroot
environment.
You will need to ensure the chroot environment contains all the
files necessary for tinc to run correctly. Most importantly, for
tinc to be able to resolve hostnames inside the chroot environment,
you must copy '/etc/resolv.conf' into the chroot directory. If you
want to be able to run scripts other than 'tinc-up' in the chroot,
you must ensure the appropriate shell is also installed in the
chroot, along with all its dependencies.
'-U, --user=USER'
Switch to the given USER after initialization, at the same time as
@ -1937,8 +1939,7 @@ correct destination MAC address. In those modes every interface should
have a unique MAC address, so make sure they are not the same. Because
switch and hub modes rely on MAC addresses to function correctly, these
modes cannot be used on the following operating systems which don't have
a 'tap' style virtual network device: OpenBSD, NetBSD, Darwin and
Solaris.
a 'tap' style virtual network device: NetBSD, Darwin and Solaris.

File: tinc.info, Node: The meta-connection, Prev: The UDP tunnel, Up: The connection
@ -2098,7 +2099,7 @@ intercept. The encryption algorithm and message authentication
algorithm can be changed in the configuration. The length of the
message authentication codes is also adjustable. The length of the key
for the encryption algorithm is always the default length used by
OpenSSL.
LibreSSL/OpenSSL.
* Menu:
@ -2256,8 +2257,8 @@ In August 2000, we discovered the existence of a security hole in all
versions of tinc up to and including 1.0pre2. This had to do with the
way we exchanged 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.
version uses the LibreSSL or OpenSSL library and uses strong
authentication with RSA keys.
On the 29th of December 2001, Jerome Etienne posted a security
analysis of tinc 1.0pre4. Due to a lack of sequence numbers and a
@ -2277,7 +2278,7 @@ address these issues in tinc 2.0.
Cryptography is a hard thing to get right. We cannot make any
guarantees. Time, review and feedback are the only things that can
prove the security of any cryptographic product. If you wish to review
tinc or give us feedback, you are stronly encouraged to do so.
tinc or give us feedback, you are strongly encouraged to do so.

File: tinc.info, Node: Platform specific information, Next: About us, Prev: Technical information, Up: Top
@ -2289,6 +2290,7 @@ File: tinc.info, Node: Platform specific information, Next: About us, Prev: T
* Interface configuration::
* Routes::
* Automatically starting tinc::

File: tinc.info, Node: Interface configuration, Next: Routes, Up: Platform specific information
@ -2327,11 +2329,6 @@ Solaris 'ifconfig' INTERFACE 'inet6 plumb up'
Darwin (Mac OS X) 'ifconfig' INTERFACE 'inet6' ADDRESS 'prefixlen' PREFIXLENGTH
Windows 'netsh interface ipv6 add address' INTERFACE 'static' ADDRESS/PREFIXLENGTH
On some platforms, when running tinc in switch mode, the VPN
interface must be set to tap mode with an ifconfig command:
OpenBSD 'ifconfig' INTERFACE 'link0'
On Linux, it is possible to create a persistent tun/tap interface
which will continue to exist even if tinc quit, although this is
normally not required. It can be useful to set up a tun/tap interface
@ -2341,7 +2338,7 @@ root privileges at all.
Linux 'ip tuntap add dev' INTERFACE 'mode' TUN|TAP 'user' USERNAME

File: tinc.info, Node: Routes, Prev: Interface configuration, Up: Platform specific information
File: tinc.info, Node: Routes, Next: Automatically starting tinc, Prev: Interface configuration, Up: Platform specific information
7.2 Routes
==========
@ -2376,6 +2373,72 @@ Solaris 'route add -inet6' NETWORK_ADDRESS'/'PREFIXLENGTH LOCAL_ADDR
Darwin (Mac OS X) 'route add -inet6' NETWORK_ADDRESS'/'PREFIXLENGTH '-interface' INTERFACE
Windows 'netsh interface ipv6 add route' NETWORK ADDRESS/PREFIXLENGTH INTERFACE

File: tinc.info, Node: Automatically starting tinc, Prev: Routes, Up: Platform specific information
7.3 Automatically starting tinc
===============================
* Menu:
* Linux::
* Windows::
* Other platforms::

File: tinc.info, Node: Linux, Next: Windows, Up: Automatically starting tinc
7.3.1 Linux
-----------
There are many Linux distributions, and historically, many of them had
their own way of starting programs at boot time. Today, a number of
major Linux distributions have chosen to use systemd as their init
system. Tinc ships with systemd service files that allow you to start
and stop tinc using systemd. There are two service files:
'tinc.service' is used to globally enable or disable all tinc daemons
managed by systemd, and 'tinc@NETNAME.service' is used to enable or
disable specific tinc daemons. So if one has created a tinc network
with netname 'foo', then you have to run the following two commands to
ensure it is started at boot time:
systemctl enable tinc
systemctl enable tinc@foo
To start the tinc daemon immediately if it wasn't already running,
use the following command:
systemctl start tinc@foo
You can also use 'systemctl start tinc', this will start all tinc
daemons that are enabled. You can stop and disable tinc networks in the
same way.
If your system is not using systemd, then you have to look up your
distribution's way of starting tinc at boot time.

File: tinc.info, Node: Windows, Next: Other platforms, Prev: Linux, Up: Automatically starting tinc
7.3.2 Windows
-------------
On Windows, if tinc is started without the '-D' or '--no-detach' option,
it will automatically register itself as a service that is started at
boot time. When tinc is stopped using the '-k' or '--kill', it will
also automatically unregister itself. Once tinc is registered as a
service, it is also possible to stop and start tinc using the Windows
Services Manager.

File: tinc.info, Node: Other platforms, Prev: Windows, Up: Automatically starting tinc
7.3.3 Other platforms
---------------------
On platforms other than the ones mentioned in the earlier sections, you
have to look up your platform's way of starting programs at boot time.

File: tinc.info, Node: About us, Next: Concept Index, Prev: Platform specific information, Up: Top
@ -2393,12 +2456,12 @@ File: tinc.info, Node: Contact information, Next: Authors, Up: About us
8.1 Contact information
=======================
Tinc's website is at <http://www.tinc-vpn.org/>, this server is located
Tinc's website is at <https://www.tinc-vpn.org/>, this server is located
in the Netherlands.
We have an IRC channel on the FreeNode and OFTC IRC networks.
Connect to irc.freenode.net (http://www.freenode.net/) or irc.oftc.net
(http://www.oftc.net/) and join channel #tinc.
Connect to irc.freenode.net (https://freenode.net/) or irc.oftc.net
(https://www.oftc.net/) and join channel #tinc.

File: tinc.info, Node: Authors, Prev: Contact information, Up: About us
@ -2515,7 +2578,8 @@ Concept Index
(line 206)
* KEY_CHANGED: The meta-protocol. (line 63)
* libraries: Libraries. (line 6)
* license: OpenSSL. (line 35)
* LibreSSL: LibreSSL/OpenSSL. (line 6)
* license: LibreSSL/OpenSSL. (line 38)
* LocalDiscovery: Main configuration variables.
(line 212)
* lzo: lzo. (line 6)
@ -2542,7 +2606,7 @@ Concept Index
* Network Administrators Guide: Configuration introduction.
(line 15)
* NODE: Scripts. (line 71)
* OpenSSL: OpenSSL. (line 6)
* OpenSSL: LibreSSL/OpenSSL. (line 6)
* options: Runtime options. (line 9)
* PEM format: Host configuration variables.
(line 69)
@ -2607,6 +2671,7 @@ Concept Index
* SVPN: Security. (line 11)
* switch: Main configuration variables.
(line 243)
* systemd: Linux. (line 6)
* TCP: The meta-connection. (line 10)
* TCPonly: Host configuration variables.
(line 105)
@ -2655,62 +2720,71 @@ Node: Top806
Node: Introduction1105
Node: Virtual Private Networks1915
Node: tinc3639
Node: Supported platforms5166
Node: Preparations5866
Node: Configuring the kernel6122
Node: Configuration of Linux kernels6532
Node: Configuration of FreeBSD kernels7387
Node: Configuration of OpenBSD kernels7852
Node: Configuration of NetBSD kernels8460
Node: Configuration of Solaris kernels8865
Node: Configuration of Darwin (Mac OS X) kernels9527
Node: Configuration of Windows10346
Node: Libraries10860
Node: OpenSSL11248
Node: zlib13536
Node: lzo14564
Node: Installation15546
Node: Building and installing tinc16561
Node: Darwin (Mac OS X) build environment17221
Node: Cygwin (Windows) build environment17803
Node: MinGW (Windows) build environment18391
Node: System files18915
Node: Device files19180
Node: Other files19596
Node: Configuration20209
Node: Configuration introduction20520
Node: Multiple networks21788
Node: How connections work23214
Node: Configuration files24436
Node: Main configuration variables25930
Node: Host configuration variables42187
Node: Scripts47690
Node: How to configure50956
Node: Generating keypairs52214
Node: Network interfaces52713
Node: Example configuration54561
Node: Running tinc59886
Node: Runtime options60476
Node: Signals63778
Node: Debug levels64969
Node: Solving problems65905
Node: Error messages67457
Node: Sending bug reports71466
Node: Technical information72413
Node: The connection72644
Node: The UDP tunnel72956
Node: The meta-connection76017
Node: The meta-protocol77486
Node: Security82503
Node: Authentication protocol83636
Node: Encryption of network packets88681
Node: Security issues90057
Node: Platform specific information91684
Node: Interface configuration91912
Node: Routes94383
Node: About us96397
Node: Contact information96572
Node: Authors96976
Node: Concept Index97381
Node: Supported platforms5167
Node: Preparations5868
Node: Configuring the kernel6124
Node: Configuration of Linux kernels6534
Node: Configuration of FreeBSD kernels7389
Node: Configuration of OpenBSD kernels7854
Node: Configuration of NetBSD kernels8211
Node: Configuration of Solaris kernels8616
Node: Configuration of Darwin (Mac OS X) kernels9279
Node: Configuration of Windows10098
Node: Libraries10638
Node: LibreSSL/OpenSSL11047
Node: zlib13589
Node: lzo14618
Node: Installation15601
Node: Building and installing tinc16511
Node: Darwin (Mac OS X) build environment17171
Node: Cygwin (Windows) build environment17736
Node: MinGW (Windows) build environment18325
Node: System files18919
Node: Device files19184
Node: Other files19600
Node: Configuration20213
Node: Configuration introduction20524
Node: Multiple networks21792
Node: How connections work23218
Node: Configuration files24440
Node: Main configuration variables25934
Node: Host configuration variables42182
Node: Scripts47714
Node: How to configure50980
Node: Generating keypairs52238
Node: Network interfaces52737
Node: Example configuration54585
Node: Running tinc59910
Node: Runtime options60500
Node: Signals64125
Node: Debug levels65316
Node: Solving problems66252
Node: Error messages67804
Node: Sending bug reports71813
Node: Technical information72760
Node: The connection72991
Node: The UDP tunnel73303
Node: The meta-connection76355
Node: The meta-protocol77824
Node: Security82841
Node: Authentication protocol83983
Node: Encryption of network packets89028
Node: Security issues90404
Node: Platform specific information92044
Node: Interface configuration92304
Node: Routes94600
Node: Automatically starting tinc96650
Node: Linux96873
Node: Windows98094
Node: Other platforms98599
Node: About us98881
Node: Contact information99056
Node: Authors99459
Node: Concept Index99864

End Tag Table

Local Variables:
coding: utf-8
End:

View file

@ -15,7 +15,7 @@
This is the info manual for @value{PACKAGE} version @value{VERSION}, a Virtual Private Network daemon.
Copyright @copyright{} 1998-2016 Ivo Timmermans,
Copyright @copyright{} 1998-2019 Ivo Timmermans,
Guus Sliepen <guus@@tinc-vpn.org> and
Wessel Dankers <wsl@@tinc-vpn.org>.
@ -39,7 +39,7 @@ permission notice identical to this one.
@vskip 0pt plus 1filll
This is the info manual for @value{PACKAGE} version @value{VERSION}, a Virtual Private Network daemon.
Copyright @copyright{} 1998-2016 Ivo Timmermans,
Copyright @copyright{} 1998-2019 Ivo Timmermans,
Guus Sliepen <guus@@tinc-vpn.org> and
Wessel Dankers <wsl@@tinc-vpn.org>.
@ -155,7 +155,7 @@ professional package.
@cindex traditional VPNs
@cindex scalability
Tinc also allows more than two sites to connect to eachother and form a single VPN.
Tinc also allows more than two sites to connect to each other and form a single VPN.
Traditionally VPNs are created by making tunnels, which only have two endpoints.
Larger VPNs with more sites are created by adding more tunnels.
Tinc takes another approach: only endpoints are specified,
@ -186,7 +186,7 @@ packets.
@cindex release
For an up to date list of supported platforms, please check the list on
our website:
@uref{http://www.tinc-vpn.org/platforms/}.
@uref{https://www.tinc-vpn.org/platforms/}.
@c
@c
@ -268,12 +268,7 @@ The tap driver can be loaded with @code{kldload if_tap}, or by adding @code{if_t
@node Configuration of OpenBSD kernels
@subsection Configuration of OpenBSD kernels
For OpenBSD version 2.9 and higher,
the tun driver is included in the default kernel configuration.
There is also a kernel patch from @uref{http://diehard.n-r-g.com/stuff/openbsd/}
which adds a tap device to OpenBSD which should work with tinc,
but with recent versions of OpenBSD,
a tun device can act as a tap device by setting the link0 option with ifconfig.
Recent versions of OpenBSD come with both tun and tap devices enabled in the default kernel configuration.
@c ==================================================================
@ -293,7 +288,7 @@ Tunneling IPv6 may not work on NetBSD's tun device.
For Solaris 8 (SunOS 5.8) and higher,
the tun driver may or may not be included in the default kernel configuration.
If it isn't, the source can be downloaded from @uref{http://vtun.sourceforge.net/tun/}.
For x86 and sparc64 architectures, precompiled versions can be found at @uref{http://www.monkey.org/~dugsong/fragroute/}.
For x86 and sparc64 architectures, precompiled versions can be found at @uref{https://www.monkey.org/~dugsong/fragroute/}.
If the @file{net/if_tun.h} header file is missing, install it from the source package.
@ -317,7 +312,7 @@ You can also omit the number, in which case the first free number will be chosen
@subsection Configuration of Windows
You will need to install the latest TAP-Win32 driver from OpenVPN.
You can download it from @uref{http://openvpn.sourceforge.net}.
You can download it from @uref{https://openvpn.net/index.php/open-source/downloads.html}.
Using the Network Connections control panel,
configure the TAP-Win32 network interface in the same way as you would do from the tinc-up script,
as explained in the rest of the documentation.
@ -329,24 +324,25 @@ as explained in the rest of the documentation.
@cindex requirements
@cindex libraries
Before you can configure or build tinc, you need to have the OpenSSL,
Before you can configure or build tinc, you need to have the LibreSSL or OpenSSL,
zlib and lzo libraries installed on your system. If you try to configure tinc without
having them installed, configure will give you an error message, and stop.
@menu
* OpenSSL::
* LibreSSL/OpenSSL::
* zlib::
* lzo::
@end menu
@c ==================================================================
@node OpenSSL
@subsection OpenSSL
@node LibreSSL/OpenSSL
@subsection LibreSSL/OpenSSL
@cindex LibreSSL
@cindex OpenSSL
For all cryptography-related functions, tinc uses the functions provided
by the OpenSSL library.
by the LibreSSL or the OpenSSL library.
If this library is not installed, you will get an error when configuring
tinc for build. Support for running tinc with other cryptographic libraries
@ -356,21 +352,23 @@ You can use your operating system's package manager to install this if
available. Make sure you install the development AND runtime versions
of this package.
If you have to install OpenSSL manually, you can get the source code
from @url{http://www.openssl.org/}. Instructions on how to configure,
build and install this package are included within the package. Please
make sure you build development and runtime libraries (which is the
If your operating system comes neither with LibreSSL or OpenSSL, you have to
install one manually. It is recommended that you get the latest version of
LibreSSL from @url{http://www.libressl.org/}. Instructions on how to
configure, build and install this package are included within the package.
Please make sure you build development and runtime libraries (which is the
default).
If you installed the OpenSSL libraries from source, it may be necessary
If you installed the LibreSSL or OpenSSL libraries from source, it may be necessary
to let configure know where they are, by passing configure one of the
--with-openssl-* parameters.
--with-openssl-* parameters. Note that you even have to use --with-openssl-* if you
are using LibreSSL.
@example
--with-openssl=DIR OpenSSL library and headers prefix
--with-openssl-include=DIR OpenSSL headers directory
--with-openssl=DIR LibreSSL/OpenSSL library and headers prefix
--with-openssl-include=DIR LibreSSL/OpenSSL headers directory
(Default is OPENSSL_DIR/include)
--with-openssl-lib=DIR OpenSSL library directory
--with-openssl-lib=DIR LibreSSL/OpenSSL library directory
(Default is OPENSSL_DIR/lib)
@end example
@ -381,7 +379,7 @@ to let configure know where they are, by passing configure one of the
The complete source code of tinc is covered by the GNU GPL version 2.
Since the license under which OpenSSL is distributed is not directly
compatible with the terms of the GNU GPL
@uref{http://www.openssl.org/support/faq.html#LEGAL2}, we
@uref{https://www.openssl.org/support/faq.html#LEGAL2}, we
include an exemption to the GPL (see also the file COPYING.README) to allow
everyone to create a statically or dynamically linked executable:
@ -397,8 +395,8 @@ we also present the following exemption:
@quotation
Hereby I grant a special exception to the tinc VPN project
(http://www.tinc-vpn.org/) to link the LZO library with the OpenSSL library
(http://www.openssl.org).
(https://www.tinc-vpn.org/) to link the LZO library with the OpenSSL library
(https://www.openssl.org).
Markus F.X.J. Oberhumer
@end quotation
@ -423,7 +421,7 @@ available. Make sure you install the development AND runtime versions
of this package.
If you have to install zlib manually, you can get the source code
from @url{http://www.gzip.org/zlib/}. Instructions on how to configure,
from @url{https://zlib.net/}. Instructions on how to configure,
build and install this package are included within the package. Please
make sure you build development and runtime libraries (which is the
default).
@ -447,7 +445,7 @@ available. Make sure you install the development AND runtime versions
of this package.
If you have to install lzo manually, you can get the source code
from @url{http://www.oberhumer.com/opensource/lzo/}. Instructions on how to configure,
from @url{https://www.oberhumer.com/opensource/lzo/}. Instructions on how to configure,
build and install this package are included within the package. Please
make sure you build development and runtime libraries (which is the
default).
@ -473,9 +471,7 @@ system startup scripts and sample configurations.
If you cannot use one of the precompiled packages, or you want to compile tinc
for yourself, you can use the source. The source is distributed under
the GNU General Public License (GPL). Download the source from the
@uref{http://www.tinc-vpn.org/download/, download page}, which has
the checksums of these files listed; you may wish to check these with
md5sum before continuing.
@uref{https://www.tinc-vpn.org/download/, download page}.
Tinc comes in a convenient autoconf/automake package, which you can just
treat the same as any other package. Which is just untar it, type
@ -512,19 +508,18 @@ The documentation that comes along with your distribution will tell you how to d
@node Darwin (Mac OS X) build environment
@subsection Darwin (Mac OS X) build environment
In order to build tinc on Darwin, you need to install the Mac OS X Developer Tools
from @uref{http://developer.apple.com/tools/macosxtools.html} and
preferably a recent version of Fink from @uref{http://www.finkproject.org/}.
In order to build tinc on Darwin, you need to install Xcode from @uref{https://developer.apple.com/xcode/}.
It might also help to install a recent version of Fink from @uref{http://www.finkproject.org/}.
After installation use fink to download and install the following packages:
autoconf25, automake, dlcompat, m4, openssl, zlib and lzo.
You need to download and install LibreSSL (or OpenSSL) and LZO,
either directly from their websites (see @ref{Libraries}) or using Fink.
@c ==================================================================
@node Cygwin (Windows) build environment
@subsection Cygwin (Windows) build environment
If Cygwin hasn't already been installed, install it directly from
@uref{http://www.cygwin.com/}.
@uref{https://www.cygwin.com/}.
When tinc is compiled in a Cygwin environment, it can only be run in this environment,
but all programs, including those started outside the Cygwin environment, will be able to use the VPN.
@ -535,6 +530,7 @@ It will also support all features.
@subsection MinGW (Windows) build environment
You will need to install the MinGW environment from @uref{http://www.mingw.org}.
You also need to download and install LibreSSL (or OpenSSL) and LZO.
When tinc is compiled using MinGW it runs natively under Windows,
it is not necessary to keep MinGW installed.
@ -864,7 +860,7 @@ Also note that this can cause decrypted VPN packets to be sent out on a real net
@cindex UML
@item uml (not compiled in by default)
Create a UNIX socket with the filename specified by
@var{Device}, or @file{@value{localstatedir}/run/@var{netname}.umlsocket}
@var{Device}, or @file{@value{runstatedir}/@var{netname}.umlsocket}
if not specified.
Tinc will wait for a User Mode Linux instance to connect to this socket.
@ -872,7 +868,7 @@ Tinc will wait for a User Mode Linux instance to connect to this socket.
@item vde (not compiled in by default)
Uses the libvdeplug library to connect to a Virtual Distributed Ethernet switch,
using the UNIX socket specified by
@var{Device}, or @file{@value{localstatedir}/run/vde.ctl}
@var{Device}, or @file{@value{runstatedir}/vde.ctl}
if not specified.
@end table
@ -1147,9 +1143,9 @@ 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.
Any cipher supported by OpenSSL is recognized.
Any cipher supported by LibreSSL or OpenSSL is recognized.
Furthermore, specifying "none" will turn off packet encryption.
It is best to use only those ciphers which support CBC mode.
@ -1166,9 +1162,9 @@ Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib),
10 (fast lzo) and 11 (best lzo).
@cindex Digest
@item Digest = <@var{digest}> (sha1)
@item Digest = <@var{digest}> (sha256)
The digest algorithm used to authenticate UDP packets.
Any digest supported by OpenSSL is recognized.
Any digest supported by LibreSSL or OpenSSL is recognized.
Furthermore, specifying "none" will turn off packet authentication.
@cindex IndirectData
@ -1239,7 +1235,7 @@ MAC addresses are notated like 0:1a:2b:3c:4d:5e.
Prefixlength is the number of bits set to 1 in the netmask part; for
example: netmask 255.255.255.0 would become /24, 255.255.252.0 becomes
/22. This conforms to standard CIDR notation as described in
@uref{http://www.ietf.org/rfc/rfc1519.txt, RFC1519}
@uref{https://www.ietf.org/rfc/rfc1519.txt, RFC1519}
@cindex Subnet weight
A Subnet can be given a weight to indicate its priority over identical Subnets
@ -1734,7 +1730,7 @@ Write log entries to a file instead of to the system logging facility.
If @var{file} is omitted, the default is @file{@value{localstatedir}/log/tinc.@var{netname}.log}.
@item --pidfile=@var{file}
Write PID to @var{file} instead of @file{@value{localstatedir}/run/tinc.@var{netname}.pid}.
Write PID to @var{file} instead of @file{@value{runstatedir}/tinc.@var{netname}.pid}.
@item --bypass-security
Disables encryption and authentication.
@ -1747,10 +1743,14 @@ located (@file{@value{sysconfdir}/tinc/@var{netname}/} as determined by
The chroot is performed after all the initialization is done, after
writing pid files and opening network sockets.
Note that this option alone does not do any good without -U/--user, below.
This option is best used in combination with the -U/--user option described below.
Note also that tinc can't run scripts anymore (such as tinc-down or host-up),
unless it's setup to be runnable inside chroot environment.
You will need to ensure the chroot environment contains all the files necessary
for tinc to run correctly.
Most importantly, for tinc to be able to resolve hostnames inside the chroot environment,
you must copy @file{/etc/resolv.conf} into the chroot directory.
If you want to be able to run scripts other than @file{tinc-up} in the chroot,
you must ensure the appropriate shell is also installed in the chroot, along with all its dependencies.
@item -U, --user=@var{user}
Switch to the given @var{user} after initialization, at the same time as
@ -2075,7 +2075,7 @@ In switch or hub modes ARP does work so the sender already knows the correct des
In those modes every interface should have a unique MAC address, so make sure they are not the same.
Because switch and hub modes rely on MAC addresses to function correctly,
these modes cannot be used on the following operating systems which don't have a `tap' style virtual network device:
OpenBSD, NetBSD, Darwin and Solaris.
NetBSD, Darwin and Solaris.
@c ==================================================================
@ -2254,7 +2254,7 @@ eavesdroppers cannot get and cannot change any information at all from the
packets they can intercept. The encryption algorithm and message authentication
algorithm can be changed in the configuration. The length of the message
authentication codes is also adjustable. The length of the key for the
encryption algorithm is always the default length used by OpenSSL.
encryption algorithm is always the default length used by LibreSSL/OpenSSL.
@menu
* Authentication protocol::
@ -2413,7 +2413,7 @@ the MACLength configuration variable.
In August 2000, we discovered the existence of a security hole in all versions
of tinc up to and including 1.0pre2. This had to do with the way we exchanged
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
tinc as secure as possible. The current version uses the LibreSSL or OpenSSL library and
uses strong authentication with RSA keys.
On the 29th of December 2001, Jerome Etienne posted a security analysis of tinc
@ -2433,7 +2433,7 @@ We will address these issues in tinc 2.0.
Cryptography is a hard thing to get right. We cannot make any
guarantees. Time, review and feedback are the only things that can
prove the security of any cryptographic product. If you wish to review
tinc or give us feedback, you are stronly encouraged to do so.
tinc or give us feedback, you are strongly encouraged to do so.
@c ==================================================================
@ -2443,6 +2443,7 @@ tinc or give us feedback, you are stronly encouraged to do so.
@menu
* Interface configuration::
* Routes::
* Automatically starting tinc::
@end menu
@c ==================================================================
@ -2499,13 +2500,6 @@ For IPv6 addresses:
@tab @code{netsh interface ipv6 add address} @var{interface} @code{static} @var{address}/@var{prefixlength}
@end multitable
On some platforms, when running tinc in switch mode, the VPN interface must be set to tap mode with an ifconfig command:
@multitable {Darwin (Mac OS X)} {ifconfig route add -bla network address netmask netmask prefixlength interface}
@item OpenBSD
@tab @code{ifconfig} @var{interface} @code{link0}
@end multitable
On Linux, it is possible to create a persistent tun/tap interface which will
continue to exist even if tinc quit, although this is normally not required.
It can be useful to set up a tun/tap interface owned by a non-root user, so
@ -2569,6 +2563,66 @@ Adding routes to IPv6 subnets:
@tab @code{netsh interface ipv6 add route} @var{network address}/@var{prefixlength} @var{interface}
@end multitable
@c ==================================================================
@node Automatically starting tinc
@section Automatically starting tinc
@menu
* Linux::
* Windows::
* Other platforms::
@end menu
@c ==================================================================
@node Linux
@subsection Linux
@cindex systemd
There are many Linux distributions, and historically, many of them had their
own way of starting programs at boot time. Today, a number of major Linux
distributions have chosen to use systemd as their init system. Tinc ships with
systemd service files that allow you to start and stop tinc using systemd.
There are two service files: @code{tinc.service} is used to globally enable or
disable all tinc daemons managed by systemd, and
@code{tinc@@@var{netname}.service} is used to enable or disable specific tinc
daemons. So if one has created a tinc network with netname @code{foo}, then
you have to run the following two commands to ensure it is started at boot
time:
@example
systemctl enable tinc
systemctl enable tinc@@foo
@end example
To start the tinc daemon immediately if it wasn't already running, use the
following command:
@example
systemctl start tinc@@foo
@end example
You can also use @samp{systemctl start tinc}, this will start all tinc daemons
that are enabled. You can stop and disable tinc networks in the same way.
If your system is not using systemd, then you have to look up your
distribution's way of starting tinc at boot time.
@c ==================================================================
@node Windows
@subsection Windows
On Windows, if tinc is started without the @code{-D} or @code{--no-detach}
option, it will automatically register itself as a service that is started at
boot time. When tinc is stopped using the @code{-k} or @code{--kill}, it will
also automatically unregister itself. Once tinc is registered as a service, it
is also possible to stop and start tinc using the Windows Services Manager.
@c ==================================================================
@node Other platforms
@subsection Other platforms
On platforms other than the ones mentioned in the earlier sections, you have to
look up your platform's way of starting programs at boot time.
@c ==================================================================
@node About us
@ -2586,14 +2640,14 @@ Adding routes to IPv6 subnets:
@section Contact information
@cindex website
Tinc's website is at @url{http://www.tinc-vpn.org/},
Tinc's website is at @url{https://www.tinc-vpn.org/},
this server is located in the Netherlands.
@cindex IRC
We have an IRC channel on the FreeNode and OFTC IRC networks. Connect to
@uref{http://www.freenode.net/, irc.freenode.net}
@uref{https://freenode.net/, irc.freenode.net}
or
@uref{http://www.oftc.net/, irc.oftc.net}
@uref{https://www.oftc.net/, irc.oftc.net}
and join channel #tinc.

View file

@ -109,7 +109,7 @@ is omitted, the default is
Write PID to
.Ar FILE
instead of
.Pa @localstatedir@/run/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
Disables encryption and authentication of the meta protocol.
@ -190,7 +190,7 @@ This will log all network traffic over the virtual private network.
Directory containing the configuration files tinc uses.
For more information, see
.Xr tinc.conf 5 .
.It Pa @localstatedir@/run/tinc. Ns Ar NETNAME Ns Pa .pid
.It Pa @runstatedir@/tinc. Ns Ar NETNAME Ns Pa .pid
The PID of the currently running
.Nm
is stored in this file.
@ -207,7 +207,7 @@ If you find any bugs, report them to tinc@tinc-vpn.org.
A lot, especially security auditing.
.Sh SEE ALSO
.Xr tinc.conf 5 ,
.Pa http://www.tinc-vpn.org/ ,
.Pa https://www.tinc-vpn.org/ ,
.Pa http://www.cabal.org/ .
.Pp
The full documentation for tinc is maintained as a Texinfo manual.

5
doc/tincinclude.texi Normal file
View file

@ -0,0 +1,5 @@
@set VERSION 1.0.36
@set PACKAGE tinc
@set sysconfdir /etc
@set localstatedir /var
@set runstatedir /run

View file

@ -2,3 +2,4 @@
@set PACKAGE @PACKAGE@
@set sysconfdir @sysconfdir@
@set localstatedir @localstatedir@
@set runstatedir @runstatedir@

View file

@ -1,7 +1,7 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2014-09-12.12; # UTC
scriptversion=2018-03-11.20; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
@ -271,15 +271,18 @@ do
fi
dst=$dst_arg
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
# If destination is a directory, append the input filename.
if test -d "$dst"; then
if test "$is_target_a_directory" = never; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dst=$dstdir/`basename "$src"`
dstbase=`basename "$src"`
case $dst in
*/) dst=$dst$dstbase;;
*) dst=$dst/$dstbase;;
esac
dstdir_status=0
else
dstdir=`dirname "$dst"`
@ -288,6 +291,11 @@ do
fi
fi
case $dstdir in
*/) dstdirslash=$dstdir;;
*) dstdirslash=$dstdir/;;
esac
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
@ -324,14 +332,16 @@ do
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
# $RANDOM is not portable (e.g. dash); use it when possible to
# lower collision chance
# 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
# As "mkdir -p" follows symlinks and we work in /tmp possibly; so
# create the $tmpdir first (and fail if unsuccessful) to make sure
# that nobody tries to guess the $tmpdir name.
# Because "mkdir -p" follows existing symlinks and we likely work
# directly in world-writeable /tmp, make sure that the '$tmpdir'
# directory is successfully created first before we actually test
# 'mkdir -p' feature.
if (umask $mkdir_umask &&
$mkdirprog $mkdir_mode "$tmpdir" &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
@ -434,14 +444,25 @@ do
else
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
dsttmp=${dstdirslash}_inst.$$_
rmtmp=${dstdirslash}_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
(umask $cp_umask &&
{ test -z "$stripcmd" || {
# Create $dsttmp read-write so that cp doesn't create it read-only,
# which would cause strip to fail.
if test -z "$doit"; then
: >"$dsttmp" # No need to fork-exec 'touch'.
else
$doit touch "$dsttmp"
fi
}
} &&
$doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
@ -500,9 +521,9 @@ do
done
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

View file

@ -1,4 +0,0 @@
## Process this file with automake to produce Makefile.in -*-Makefile-*-
EXTRA_DIST = README *.m4

View file

@ -1,8 +0,0 @@
These files are used by a program called aclocal (part of the GNU automake
package). aclocal uses these files to create aclocal.m4 which is in turn
used by autoconf to create the configure script at the the top level in
this distribution.
The Makefile.am file in this directory is automatically generated
from the template file, Makefile.am.in. The generation will fail
if you don't have all the right tools.

69
m4/ax_append_flag.m4 Normal file
View file

@ -0,0 +1,69 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_append_flag.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE])
#
# DESCRIPTION
#
# FLAG is appended to the FLAGS-VARIABLE shell variable, with a space
# added in between.
#
# If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
# CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains
# FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly
# FLAG.
#
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION.
#
# LICENSE
#
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
#
# 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 3 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, see <http://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 2
AC_DEFUN([AX_APPEND_FLAG],
[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX
AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])dnl
AS_VAR_SET_IF(FLAGS,
[case " AS_VAR_GET(FLAGS) " in
*" $1 "*)
AC_RUN_LOG([: FLAGS already contains $1])
;;
*)
AC_RUN_LOG([: FLAGS="$FLAGS $1"])
AS_VAR_SET(FLAGS, ["AS_VAR_GET(FLAGS) $1"])
;;
esac],
[AS_VAR_SET(FLAGS,["$1"])])
AS_VAR_POPDEF([FLAGS])dnl
])dnl AX_APPEND_FLAG

122
m4/ax_cflags_warn_all.m4 Normal file
View file

@ -0,0 +1,122 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_cflags_warn_all.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_CFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])]
# AX_CXXFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])]
# AX_FCFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])]
#
# DESCRIPTION
#
# Try to find a compiler option that enables most reasonable warnings.
#
# For the GNU compiler it will be -Wall (and -ansi -pedantic) The result
# is added to the shellvar being CFLAGS, CXXFLAGS, or FCFLAGS by default.
#
# Currently this macro knows about the GCC, Solaris, Digital Unix, AIX,
# HP-UX, IRIX, NEC SX-5 (Super-UX 10), Cray J90 (Unicos 10.0.0.8), and
# Intel compilers. For a given compiler, the Fortran flags are much more
# experimental than their C equivalents.
#
# - $1 shell-variable-to-add-to : CFLAGS, CXXFLAGS, or FCFLAGS
# - $2 add-value-if-not-found : nothing
# - $3 action-if-found : add value to shellvariable
# - $4 action-if-not-found : nothing
#
# NOTE: These macros depend on AX_APPEND_FLAG.
#
# LICENSE
#
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
# Copyright (c) 2010 Rhys Ulerich <rhys.ulerich@gmail.com>
#
# 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 3 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, see <http://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 15
AC_DEFUN([AX_FLAGS_WARN_ALL],[dnl
AS_VAR_PUSHDEF([FLAGS],[_AC_LANG_PREFIX[]FLAGS])dnl
AS_VAR_PUSHDEF([VAR],[ac_cv_[]_AC_LANG_ABBREV[]flags_warn_all])dnl
AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for maximum warnings],
VAR,[VAR="no, unknown"
ac_save_[]FLAGS="$[]FLAGS"
for ac_arg dnl
in "-warn all % -warn all" dnl Intel
"-pedantic % -Wall" dnl GCC
"-xstrconst % -v" dnl Solaris C
"-std1 % -verbose -w0 -warnprotos" dnl Digital Unix
"-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" dnl AIX
"-ansi -ansiE % -fullwarn" dnl IRIX
"+ESlit % +w1" dnl HP-UX C
"-Xc % -pvctl[,]fullmsg" dnl NEC SX-5 (Super-UX 10)
"-h conform % -h msglevel 2" dnl Cray C (Unicos)
#
do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
[VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
done
FLAGS="$ac_save_[]FLAGS"
])
AS_VAR_POPDEF([FLAGS])dnl
AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
case ".$VAR" in
.ok|.ok,*) m4_ifvaln($3,$3) ;;
.|.no|.no,*) m4_default($4,[m4_ifval($2,[AX_APPEND_FLAG([$2], [$1])])]) ;;
*) m4_default($3,[AX_APPEND_FLAG([$VAR], [$1])]) ;;
esac
AS_VAR_POPDEF([VAR])dnl
])dnl AX_FLAGS_WARN_ALL
dnl implementation tactics:
dnl the for-argument contains a list of options. The first part of
dnl these does only exist to detect the compiler - usually it is
dnl a global option to enable -ansi or -extrawarnings. All other
dnl compilers will fail about it. That was needed since a lot of
dnl compilers will give false positives for some option-syntax
dnl like -Woption or -Xoption as they think of it is a pass-through
dnl to later compile stages or something. The "%" is used as a
dnl delimiter. A non-option comment can be given after "%%" marks
dnl which will be shown but not added to the respective C/CXXFLAGS.
AC_DEFUN([AX_CFLAGS_WARN_ALL],[dnl
AC_LANG_PUSH([C])
AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4])
AC_LANG_POP([C])
])
AC_DEFUN([AX_CXXFLAGS_WARN_ALL],[dnl
AC_LANG_PUSH([C++])
AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4])
AC_LANG_POP([C++])
])
AC_DEFUN([AX_FCFLAGS_WARN_ALL],[dnl
AC_LANG_PUSH([Fortran])
AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4])
AC_LANG_POP([Fortran])
])

37
m4/ax_require_defined.m4 Normal file
View file

@ -0,0 +1,37 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_require_defined.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_REQUIRE_DEFINED(MACRO)
#
# DESCRIPTION
#
# AX_REQUIRE_DEFINED is a simple helper for making sure other macros have
# been defined and thus are available for use. This avoids random issues
# where a macro isn't expanded. Instead the configure script emits a
# non-fatal:
#
# ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found
#
# It's like AC_REQUIRE except it doesn't expand the required macro.
#
# Here's an example:
#
# AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
#
# LICENSE
#
# Copyright (c) 2014 Mike Frysinger <vapier@gentoo.org>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 1
AC_DEFUN([AX_REQUIRE_DEFINED], [dnl
m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])])
])dnl AX_REQUIRE_DEFINED

View file

@ -1,4 +1,4 @@
dnl Check to find the OpenSSL headers/libraries
dnl Check to find the LibreSSL/OpenSSL headers/libraries
AC_DEFUN([tinc_OPENSSL],
[
@ -10,47 +10,49 @@ AC_DEFUN([tinc_OPENSSL],
[],
[AC_CHECK_LIB(dl, dlopen,
[LIBS="$LIBS -ldl"],
[AC_MSG_ERROR([OpenSSL depends on libdl.]); break]
[AC_MSG_ERROR([LibreSSL/OpenSSL depends on libdl.]); break]
)]
)
;;
esac
AC_ARG_WITH(openssl,
AS_HELP_STRING([--with-openssl=DIR], [OpenSSL base directory, or:]),
AS_HELP_STRING([--with-openssl=DIR], [LibreSSL/OpenSSL base directory, or:]),
[openssl="$withval"
CPPFLAGS="$CPPFLAGS -I$withval/include"
LDFLAGS="$LDFLAGS -L$withval/lib"]
)
AC_ARG_WITH(openssl-include,
AS_HELP_STRING([--with-openssl-include=DIR], [OpenSSL headers directory (without trailing /openssl)]),
AS_HELP_STRING([--with-openssl-include=DIR], [LibreSSL/OpenSSL headers directory (without trailing /openssl)]),
[openssl_include="$withval"
CPPFLAGS="$CPPFLAGS -I$withval"]
)
AC_ARG_WITH(openssl-lib,
AS_HELP_STRING([--with-openssl-lib=DIR], [OpenSSL library directory]),
AS_HELP_STRING([--with-openssl-lib=DIR], [LibreSSL/OpenSSL library directory]),
[openssl_lib="$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_MSG_ERROR([OpenSSL header files not found.]); break]
[AC_MSG_ERROR([LibreSSL/OpenSSL header files not found.]); break]
)
AC_CHECK_LIB(crypto, EVP_EncryptInit_ex,
[LIBS="-lcrypto $LIBS"],
[AC_MSG_ERROR([OpenSSL libraries not found.])]
[AC_MSG_ERROR([LibreSSL/OpenSSL libraries not found.])]
)
AC_CHECK_FUNCS([RAND_pseudo_bytes EVP_EncryptInit_ex], ,
[AC_MSG_ERROR([Missing OpenSSL functionality, make sure you have installed the latest version.]); break],
AC_CHECK_FUNCS([RAND_bytes EVP_EncryptInit_ex EVP_CIPHER_CTX_new], ,
[AC_MSG_ERROR([Missing LibreSSL/OpenSSL functionality, make sure you have installed the latest version.]); break],
)
AC_CHECK_DECL([OpenSSL_add_all_algorithms], ,
[AC_MSG_ERROR([Missing OpenSSL functionality, make sure you have installed the latest version.]); break],
AC_CHECK_DECLS([OpenSSL_add_all_algorithms, EVP_aes_256_cfb], ,
[AC_MSG_ERROR([Missing LibreSSL/OpenSSL functionality, make sure you have installed the latest version.]); break],
[#include <openssl/evp.h>]
)
AC_CHECK_FUNCS([BN_GENCB_new RSA_set0_key], , , [#include <openssl/rsa.h>])
])

16
missing
View file

@ -1,9 +1,9 @@
#! /bin/sh
# Common wrapper for a few potentially missing GNU programs.
scriptversion=2013-10-28.13; # UTC
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1996-2014 Free Software Foundation, Inc.
# Copyright (C) 1996-2020 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
@ -17,7 +17,7 @@ scriptversion=2013-10-28.13; # UTC
# 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, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@ -101,9 +101,9 @@ else
exit $st
fi
perl_URL=http://www.perl.org/
flex_URL=http://flex.sourceforge.net/
gnu_software_URL=http://www.gnu.org/software
perl_URL=https://www.perl.org/
flex_URL=https://github.com/westes/flex
gnu_software_URL=https://www.gnu.org/software
program_details ()
{
@ -207,9 +207,9 @@ give_advice "$1" | sed -e '1s/^/WARNING: /' \
exit $st
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

View file

@ -14,7 +14,6 @@ tincd_SOURCES = \
edge.c edge.h \
ethernet.h \
event.c event.h \
fake-gai-errnos.h \
fake-getaddrinfo.c fake-getaddrinfo.h \
fake-getnameinfo.c fake-getnameinfo.h \
graph.c graph.h \
@ -44,8 +43,7 @@ tincd_SOURCES = \
subnet.c subnet.h \
tincd.c \
utils.c utils.h \
xalloc.h \
xmalloc.c
xalloc.h
if !GETOPT
tincd_SOURCES += \
@ -88,4 +86,4 @@ if TUNEMU
LIBS += -lpcap
endif
AM_CPPFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\"
AM_CPPFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DRUNSTATEDIR=\"$(runstatedir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -I $(abs_top_builddir)/

View file

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.15 from Makefile.am.
# Makefile.in generated by automake 1.16.2 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
# 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,
@ -105,8 +105,11 @@ sbin_PROGRAMS = tincd$(EXEEXT)
subdir = src
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/lzo.m4 \
$(top_srcdir)/m4/ax_check_link_flag.m4 \
$(top_srcdir)/m4/ax_require_defined.m4 $(top_srcdir)/m4/lzo.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/zlib.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
@ -121,19 +124,18 @@ PROGRAMS = $(sbin_PROGRAMS)
am__tincd_SOURCES_DIST = have.h system.h avl_tree.c avl_tree.h conf.c \
conf.h connection.c connection.h device.h dropin.c dropin.h \
dummy_device.c edge.c edge.h ethernet.h event.c event.h \
fake-gai-errnos.h fake-getaddrinfo.c fake-getaddrinfo.h \
fake-getnameinfo.c fake-getnameinfo.h graph.c graph.h ipv4.h \
ipv6.h list.c list.h logger.c logger.h meta.c meta.h \
multicast_device.c net.c net.h net_packet.c net_setup.c \
net_socket.c netutl.c netutl.h node.c node.h pidfile.c \
pidfile.h process.c process.h protocol.c protocol.h \
protocol_auth.c protocol_edge.c protocol_misc.c protocol_key.c \
protocol_subnet.c proxy.c proxy.h raw_socket_device.c route.c \
route.h subnet.c subnet.h tincd.c utils.c utils.h xalloc.h \
xmalloc.c getopt.c getopt.h getopt1.c linux/device.c \
bsd/device.c bsd/tunemu.c bsd/tunemu.h solaris/device.c \
mingw/device.c mingw/common.h cygwin/device.c uml_device.c \
vde_device.c
fake-getaddrinfo.c fake-getaddrinfo.h fake-getnameinfo.c \
fake-getnameinfo.h graph.c graph.h ipv4.h ipv6.h list.c list.h \
logger.c logger.h meta.c meta.h multicast_device.c net.c net.h \
net_packet.c net_setup.c net_socket.c netutl.c netutl.h node.c \
node.h pidfile.c pidfile.h process.c process.h protocol.c \
protocol.h protocol_auth.c protocol_edge.c protocol_misc.c \
protocol_key.c protocol_subnet.c proxy.c proxy.h \
raw_socket_device.c route.c route.h subnet.c subnet.h tincd.c \
utils.c utils.h xalloc.h getopt.c getopt.h getopt1.c \
linux/device.c bsd/device.c bsd/tunemu.c bsd/tunemu.h \
solaris/device.c mingw/device.c mingw/common.h cygwin/device.c \
uml_device.c vde_device.c
@GETOPT_FALSE@am__objects_1 = getopt.$(OBJEXT) getopt1.$(OBJEXT)
am__dirstamp = $(am__leading_dot)dirstamp
@LINUX_TRUE@am__objects_2 = linux/device.$(OBJEXT)
@ -156,10 +158,10 @@ am_tincd_OBJECTS = avl_tree.$(OBJEXT) conf.$(OBJEXT) \
protocol_misc.$(OBJEXT) protocol_key.$(OBJEXT) \
protocol_subnet.$(OBJEXT) proxy.$(OBJEXT) \
raw_socket_device.$(OBJEXT) route.$(OBJEXT) subnet.$(OBJEXT) \
tincd.$(OBJEXT) utils.$(OBJEXT) xmalloc.$(OBJEXT) \
$(am__objects_1) $(am__objects_2) $(am__objects_3) \
$(am__objects_4) $(am__objects_5) $(am__objects_6) \
$(am__objects_7) $(am__objects_8) $(am__objects_9)
tincd.$(OBJEXT) utils.$(OBJEXT) $(am__objects_1) \
$(am__objects_2) $(am__objects_3) $(am__objects_4) \
$(am__objects_5) $(am__objects_6) $(am__objects_7) \
$(am__objects_8) $(am__objects_9)
tincd_OBJECTS = $(am_tincd_OBJECTS)
tincd_LDADD = $(LDADD)
AM_V_P = $(am__v_P_@AM_V@)
@ -176,7 +178,29 @@ am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES =
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/avl_tree.Po ./$(DEPDIR)/conf.Po \
./$(DEPDIR)/connection.Po ./$(DEPDIR)/dropin.Po \
./$(DEPDIR)/dummy_device.Po ./$(DEPDIR)/edge.Po \
./$(DEPDIR)/event.Po ./$(DEPDIR)/fake-getaddrinfo.Po \
./$(DEPDIR)/fake-getnameinfo.Po ./$(DEPDIR)/getopt.Po \
./$(DEPDIR)/getopt1.Po ./$(DEPDIR)/graph.Po \
./$(DEPDIR)/list.Po ./$(DEPDIR)/logger.Po ./$(DEPDIR)/meta.Po \
./$(DEPDIR)/multicast_device.Po ./$(DEPDIR)/net.Po \
./$(DEPDIR)/net_packet.Po ./$(DEPDIR)/net_setup.Po \
./$(DEPDIR)/net_socket.Po ./$(DEPDIR)/netutl.Po \
./$(DEPDIR)/node.Po ./$(DEPDIR)/pidfile.Po \
./$(DEPDIR)/process.Po ./$(DEPDIR)/protocol.Po \
./$(DEPDIR)/protocol_auth.Po ./$(DEPDIR)/protocol_edge.Po \
./$(DEPDIR)/protocol_key.Po ./$(DEPDIR)/protocol_misc.Po \
./$(DEPDIR)/protocol_subnet.Po ./$(DEPDIR)/proxy.Po \
./$(DEPDIR)/raw_socket_device.Po ./$(DEPDIR)/route.Po \
./$(DEPDIR)/subnet.Po ./$(DEPDIR)/tincd.Po \
./$(DEPDIR)/uml_device.Po ./$(DEPDIR)/utils.Po \
./$(DEPDIR)/vde_device.Po bsd/$(DEPDIR)/device.Po \
bsd/$(DEPDIR)/tunemu.Po cygwin/$(DEPDIR)/device.Po \
linux/$(DEPDIR)/device.Po mingw/$(DEPDIR)/device.Po \
solaris/$(DEPDIR)/device.Po
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@ -248,7 +272,6 @@ LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@ $(am__append_10)
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
OBJEXT = @OBJEXT@
@ -311,6 +334,7 @@ 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@
@ -318,24 +342,24 @@ top_srcdir = @top_srcdir@
tincd_SOURCES = have.h system.h avl_tree.c avl_tree.h conf.c conf.h \
connection.c connection.h device.h dropin.c dropin.h \
dummy_device.c edge.c edge.h ethernet.h event.c event.h \
fake-gai-errnos.h fake-getaddrinfo.c fake-getaddrinfo.h \
fake-getnameinfo.c fake-getnameinfo.h graph.c graph.h ipv4.h \
ipv6.h list.c list.h logger.c logger.h meta.c meta.h \
multicast_device.c net.c net.h net_packet.c net_setup.c \
net_socket.c netutl.c netutl.h node.c node.h pidfile.c \
pidfile.h process.c process.h protocol.c protocol.h \
protocol_auth.c protocol_edge.c protocol_misc.c protocol_key.c \
protocol_subnet.c proxy.c proxy.h raw_socket_device.c route.c \
route.h subnet.c subnet.h tincd.c utils.c utils.h xalloc.h \
xmalloc.c $(am__append_1) $(am__append_2) $(am__append_3) \
$(am__append_4) $(am__append_5) $(am__append_6) \
$(am__append_7) $(am__append_8) $(am__append_9)
AM_CPPFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\"
fake-getaddrinfo.c fake-getaddrinfo.h fake-getnameinfo.c \
fake-getnameinfo.h graph.c graph.h ipv4.h ipv6.h list.c list.h \
logger.c logger.h meta.c meta.h multicast_device.c net.c net.h \
net_packet.c net_setup.c net_socket.c netutl.c netutl.h node.c \
node.h pidfile.c pidfile.h process.c process.h protocol.c \
protocol.h protocol_auth.c protocol_edge.c protocol_misc.c \
protocol_key.c protocol_subnet.c proxy.c proxy.h \
raw_socket_device.c route.c route.h subnet.c subnet.h tincd.c \
utils.c utils.h xalloc.h $(am__append_1) $(am__append_2) \
$(am__append_3) $(am__append_4) $(am__append_5) \
$(am__append_6) $(am__append_7) $(am__append_8) \
$(am__append_9)
AM_CPPFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DRUNSTATEDIR=\"$(runstatedir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -I $(abs_top_builddir)/
all: all-am
.SUFFIXES:
.SUFFIXES: .c .o .obj
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
@ -352,16 +376,16 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
install-sbinPROGRAMS: $(sbin_PROGRAMS)
@ -480,51 +504,56 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/avl_tree.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connection.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dropin.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dummy_device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edge.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fake-getaddrinfo.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fake-getnameinfo.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/graph.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logger.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/meta.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multicast_device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_packet.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_setup.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_socket.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netutl.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pidfile.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_auth.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_edge.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_key.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_misc.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_subnet.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proxy.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/raw_socket_device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/route.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnet.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tincd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uml_device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vde_device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmalloc.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@bsd/$(DEPDIR)/device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@bsd/$(DEPDIR)/tunemu.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@cygwin/$(DEPDIR)/device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@linux/$(DEPDIR)/device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@mingw/$(DEPDIR)/device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@solaris/$(DEPDIR)/device.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/avl_tree.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connection.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dropin.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dummy_device.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edge.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fake-getaddrinfo.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fake-getnameinfo.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/graph.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logger.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/meta.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multicast_device.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_packet.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_setup.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_socket.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netutl.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pidfile.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_auth.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_edge.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_key.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_misc.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_subnet.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proxy.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/raw_socket_device.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/route.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnet.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tincd.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uml_device.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vde_device.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@bsd/$(DEPDIR)/device.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@bsd/$(DEPDIR)/tunemu.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@cygwin/$(DEPDIR)/device.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@linux/$(DEPDIR)/device.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@mingw/$(DEPDIR)/device.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@solaris/$(DEPDIR)/device.Po@am__quote@ # am--include-marker
$(am__depfiles_remade):
@$(MKDIR_P) $(@D)
@echo '# dummy' >$@-t && $(am__mv) $@-t $@
am--depfiles: $(am__depfiles_remade)
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@ -594,7 +623,10 @@ cscopelist-am: $(am__tagged_files)
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
@ -676,7 +708,50 @@ clean: clean-am
clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR) bsd/$(DEPDIR) cygwin/$(DEPDIR) linux/$(DEPDIR) mingw/$(DEPDIR) solaris/$(DEPDIR)
-rm -f ./$(DEPDIR)/avl_tree.Po
-rm -f ./$(DEPDIR)/conf.Po
-rm -f ./$(DEPDIR)/connection.Po
-rm -f ./$(DEPDIR)/dropin.Po
-rm -f ./$(DEPDIR)/dummy_device.Po
-rm -f ./$(DEPDIR)/edge.Po
-rm -f ./$(DEPDIR)/event.Po
-rm -f ./$(DEPDIR)/fake-getaddrinfo.Po
-rm -f ./$(DEPDIR)/fake-getnameinfo.Po
-rm -f ./$(DEPDIR)/getopt.Po
-rm -f ./$(DEPDIR)/getopt1.Po
-rm -f ./$(DEPDIR)/graph.Po
-rm -f ./$(DEPDIR)/list.Po
-rm -f ./$(DEPDIR)/logger.Po
-rm -f ./$(DEPDIR)/meta.Po
-rm -f ./$(DEPDIR)/multicast_device.Po
-rm -f ./$(DEPDIR)/net.Po
-rm -f ./$(DEPDIR)/net_packet.Po
-rm -f ./$(DEPDIR)/net_setup.Po
-rm -f ./$(DEPDIR)/net_socket.Po
-rm -f ./$(DEPDIR)/netutl.Po
-rm -f ./$(DEPDIR)/node.Po
-rm -f ./$(DEPDIR)/pidfile.Po
-rm -f ./$(DEPDIR)/process.Po
-rm -f ./$(DEPDIR)/protocol.Po
-rm -f ./$(DEPDIR)/protocol_auth.Po
-rm -f ./$(DEPDIR)/protocol_edge.Po
-rm -f ./$(DEPDIR)/protocol_key.Po
-rm -f ./$(DEPDIR)/protocol_misc.Po
-rm -f ./$(DEPDIR)/protocol_subnet.Po
-rm -f ./$(DEPDIR)/proxy.Po
-rm -f ./$(DEPDIR)/raw_socket_device.Po
-rm -f ./$(DEPDIR)/route.Po
-rm -f ./$(DEPDIR)/subnet.Po
-rm -f ./$(DEPDIR)/tincd.Po
-rm -f ./$(DEPDIR)/uml_device.Po
-rm -f ./$(DEPDIR)/utils.Po
-rm -f ./$(DEPDIR)/vde_device.Po
-rm -f bsd/$(DEPDIR)/device.Po
-rm -f bsd/$(DEPDIR)/tunemu.Po
-rm -f cygwin/$(DEPDIR)/device.Po
-rm -f linux/$(DEPDIR)/device.Po
-rm -f mingw/$(DEPDIR)/device.Po
-rm -f solaris/$(DEPDIR)/device.Po
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
@ -722,7 +797,50 @@ install-ps-am:
installcheck-am: installcheck-sbinPROGRAMS
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR) bsd/$(DEPDIR) cygwin/$(DEPDIR) linux/$(DEPDIR) mingw/$(DEPDIR) solaris/$(DEPDIR)
-rm -f ./$(DEPDIR)/avl_tree.Po
-rm -f ./$(DEPDIR)/conf.Po
-rm -f ./$(DEPDIR)/connection.Po
-rm -f ./$(DEPDIR)/dropin.Po
-rm -f ./$(DEPDIR)/dummy_device.Po
-rm -f ./$(DEPDIR)/edge.Po
-rm -f ./$(DEPDIR)/event.Po
-rm -f ./$(DEPDIR)/fake-getaddrinfo.Po
-rm -f ./$(DEPDIR)/fake-getnameinfo.Po
-rm -f ./$(DEPDIR)/getopt.Po
-rm -f ./$(DEPDIR)/getopt1.Po
-rm -f ./$(DEPDIR)/graph.Po
-rm -f ./$(DEPDIR)/list.Po
-rm -f ./$(DEPDIR)/logger.Po
-rm -f ./$(DEPDIR)/meta.Po
-rm -f ./$(DEPDIR)/multicast_device.Po
-rm -f ./$(DEPDIR)/net.Po
-rm -f ./$(DEPDIR)/net_packet.Po
-rm -f ./$(DEPDIR)/net_setup.Po
-rm -f ./$(DEPDIR)/net_socket.Po
-rm -f ./$(DEPDIR)/netutl.Po
-rm -f ./$(DEPDIR)/node.Po
-rm -f ./$(DEPDIR)/pidfile.Po
-rm -f ./$(DEPDIR)/process.Po
-rm -f ./$(DEPDIR)/protocol.Po
-rm -f ./$(DEPDIR)/protocol_auth.Po
-rm -f ./$(DEPDIR)/protocol_edge.Po
-rm -f ./$(DEPDIR)/protocol_key.Po
-rm -f ./$(DEPDIR)/protocol_misc.Po
-rm -f ./$(DEPDIR)/protocol_subnet.Po
-rm -f ./$(DEPDIR)/proxy.Po
-rm -f ./$(DEPDIR)/raw_socket_device.Po
-rm -f ./$(DEPDIR)/route.Po
-rm -f ./$(DEPDIR)/subnet.Po
-rm -f ./$(DEPDIR)/tincd.Po
-rm -f ./$(DEPDIR)/uml_device.Po
-rm -f ./$(DEPDIR)/utils.Po
-rm -f ./$(DEPDIR)/vde_device.Po
-rm -f bsd/$(DEPDIR)/device.Po
-rm -f bsd/$(DEPDIR)/tunemu.Po
-rm -f cygwin/$(DEPDIR)/device.Po
-rm -f linux/$(DEPDIR)/device.Po
-rm -f mingw/$(DEPDIR)/device.Po
-rm -f solaris/$(DEPDIR)/device.Po
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
@ -742,19 +860,19 @@ uninstall-am: uninstall-sbinPROGRAMS
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
clean-sbinPROGRAMS cscopelist-am ctags ctags-am distclean \
distclean-compile distclean-generic distclean-tags distdir dvi \
dvi-am html html-am info info-am install install-am \
install-data install-data-am install-dvi install-dvi-am \
install-exec install-exec-am install-html install-html-am \
install-info install-info-am install-man install-pdf \
install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \
install-strip installcheck installcheck-am \
installcheck-sbinPROGRAMS installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
uninstall-am uninstall-sbinPROGRAMS
.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
clean-generic clean-sbinPROGRAMS cscopelist-am ctags ctags-am \
distclean distclean-compile distclean-generic distclean-tags \
distdir dvi dvi-am html html-am info info-am install \
install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-sbinPROGRAMS install-strip installcheck \
installcheck-am installcheck-sbinPROGRAMS installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
tags tags-am uninstall uninstall-am uninstall-sbinPROGRAMS
.PRECIOUS: Makefile

View file

@ -26,7 +26,7 @@
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 (http://www.tinc-vpn.org/) by
library for inclusion into tinc (https://www.tinc-vpn.org/) by
Guus Sliepen <guus@tinc-vpn.org>.
*/
@ -50,14 +50,14 @@
#endif
#ifndef AVL_DEPTH
static int lg(unsigned int u) __attribute__ ((__const__));
static int lg(unsigned int u) __attribute__((__const__));
static int lg(unsigned int u)
{
static int lg(unsigned int u) {
int r = 1;
if(!u)
if(!u) {
return 0;
}
if(u & 0xffff0000) {
u >>= 16;
@ -79,8 +79,9 @@ static int lg(unsigned int u)
r += 2;
}
if(u & 0x00000002)
if(u & 0x00000002) {
r++;
}
return r;
}
@ -88,8 +89,7 @@ static int lg(unsigned int u)
/* Internal helper functions */
static int avl_check_balance(const avl_node_t *node)
{
static int avl_check_balance(const avl_node_t *node) {
#ifdef AVL_DEPTH
int d;
@ -97,27 +97,28 @@ static int avl_check_balance(const avl_node_t *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 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)
if(r >> pl + 1) {
return 1;
}
if(pl < 2 || r >> pl - 2)
if(pl < 2 || r >> pl - 2) {
return 0;
}
return -1;
#endif
}
static void avl_rebalance(avl_tree_t *tree, avl_node_t *node)
{
static void avl_rebalance(avl_tree_t *tree, avl_node_t *node) {
avl_node_t *child;
avl_node_t *gchild;
avl_node_t *parent;
@ -127,135 +128,154 @@ static void avl_rebalance(avl_tree_t *tree, avl_node_t *node)
parent = node->parent;
superparent =
parent ? node ==
parent->left ? &parent->left : &parent->right : &tree->root;
parent ? node ==
parent->left ? &parent->left : &parent->right : &tree->root;
switch (avl_check_balance(node)) {
case -1:
child = node->left;
switch(avl_check_balance(node)) {
case -1:
child = node->left;
#ifdef AVL_DEPTH
if(L_AVL_DEPTH(child) >= R_AVL_DEPTH(child)) {
if(L_AVL_DEPTH(child) >= R_AVL_DEPTH(child)) {
#else
if(AVL_L_COUNT(child) >= AVL_R_COUNT(child)) {
if(AVL_L_COUNT(child) >= AVL_R_COUNT(child)) {
#endif
node->left = child->right;
if(node->left)
node->left->parent = node;
node->left = child->right;
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
if(node->left) {
node->left->parent = node;
}
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:
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 *avl_alloc_tree(avl_compare_t compare, avl_action_t delete) {
avl_tree_t *tree;
tree = xmalloc_and_zero(sizeof(avl_tree_t));
@ -265,28 +285,25 @@ avl_tree_t *avl_alloc_tree(avl_compare_t compare, avl_action_t delete)
return tree;
}
void avl_free_tree(avl_tree_t *tree)
{
void avl_free_tree(avl_tree_t *tree) {
free(tree);
}
avl_node_t *avl_alloc_node(void)
{
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)
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)
{
void *avl_search(const avl_tree_t *tree, const void *data) {
avl_node_t *node;
node = avl_search_node(tree, data);
@ -294,8 +311,7 @@ void *avl_search(const avl_tree_t *tree, const void *data)
return node ? node->data : NULL;
}
void *avl_search_closest(const avl_tree_t *tree, const void *data, int *result)
{
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);
@ -303,8 +319,7 @@ void *avl_search_closest(const avl_tree_t *tree, const void *data, int *result)
return node ? node->data : NULL;
}
void *avl_search_closest_smaller(const avl_tree_t *tree, const void *data)
{
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);
@ -312,8 +327,7 @@ void *avl_search_closest_smaller(const avl_tree_t *tree, const void *data)
return node ? node->data : NULL;
}
void *avl_search_closest_greater(const avl_tree_t *tree, const void *data)
{
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);
@ -321,8 +335,7 @@ void *avl_search_closest_greater(const avl_tree_t *tree, const void *data)
return node ? node->data : NULL;
}
avl_node_t *avl_search_node(const avl_tree_t *tree, const void *data)
{
avl_node_t *avl_search_node(const avl_tree_t *tree, const void *data) {
avl_node_t *node;
int result;
@ -332,16 +345,17 @@ avl_node_t *avl_search_node(const avl_tree_t *tree, const void *data)
}
avl_node_t *avl_search_closest_node(const avl_tree_t *tree, const void *data,
int *result)
{
int *result) {
avl_node_t *node;
int c;
node = tree->root;
if(!node) {
if(result)
if(result) {
*result = 0;
}
return NULL;
}
@ -349,24 +363,30 @@ avl_node_t *avl_search_closest_node(const avl_tree_t *tree, const void *data,
c = tree->compare(data, node->data);
if(c < 0) {
if(node->left)
if(node->left) {
node = node->left;
else {
if(result)
} else {
if(result) {
*result = -1;
}
break;
}
} else if(c > 0) {
if(node->right)
if(node->right) {
node = node->right;
else {
if(result)
} else {
if(result) {
*result = 1;
}
break;
}
} else {
if(result)
if(result) {
*result = 0;
}
break;
}
}
@ -375,37 +395,36 @@ avl_node_t *avl_search_closest_node(const avl_tree_t *tree, const void *data,
}
avl_node_t *avl_search_closest_smaller_node(const avl_tree_t *tree,
const void *data)
{
const void *data) {
avl_node_t *node;
int result;
node = avl_search_closest_node(tree, data, &result);
if(result < 0)
if(result < 0) {
node = node->prev;
}
return node;
}
avl_node_t *avl_search_closest_greater_node(const avl_tree_t *tree,
const void *data)
{
const void *data) {
avl_node_t *node;
int result;
node = avl_search_closest_node(tree, data, &result);
if(result > 0)
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 *avl_insert(avl_tree_t *tree, void *data) {
avl_node_t *closest, *new;
int result;
@ -416,21 +435,21 @@ avl_node_t *avl_insert(avl_tree_t *tree, void *data)
} 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;
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;
case 1:
new = avl_alloc_node();
new->data = data;
avl_insert_after(tree, closest, new);
break;
default:
return NULL;
default:
return NULL;
}
}
@ -444,27 +463,26 @@ avl_node_t *avl_insert(avl_tree_t *tree, void *data)
return new;
}
avl_node_t *avl_insert_node(avl_tree_t *tree, avl_node_t *node)
{
avl_node_t *avl_insert_node(avl_tree_t *tree, avl_node_t *node) {
avl_node_t *closest;
int result;
if(!tree->root)
if(!tree->root) {
avl_insert_top(tree, node);
else {
} else {
closest = avl_search_closest_node(tree, node->data, &result);
switch (result) {
case -1:
avl_insert_before(tree, closest, node);
break;
switch(result) {
case -1:
avl_insert_before(tree, closest, node);
break;
case 1:
avl_insert_after(tree, closest, node);
break;
case 1:
avl_insert_after(tree, closest, node);
break;
case 0:
return NULL;
case 0:
return NULL;
}
}
@ -478,20 +496,20 @@ avl_node_t *avl_insert_node(avl_tree_t *tree, avl_node_t *node)
return node;
}
void avl_insert_top(avl_tree_t *tree, avl_node_t *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)
{
avl_node_t *node) {
if(!before) {
if(tree->tail)
if(tree->tail) {
avl_insert_after(tree, tree->tail, node);
else
} else {
avl_insert_top(tree, node);
}
return;
}
@ -504,10 +522,11 @@ void avl_insert_before(avl_tree_t *tree, avl_node_t *before,
return;
}
if(before->prev)
if(before->prev) {
before->prev->next = node;
else
} else {
tree->head = node;
}
before->prev = node;
before->left = node;
@ -515,13 +534,14 @@ void avl_insert_before(avl_tree_t *tree, avl_node_t *before,
avl_rebalance(tree, before);
}
void avl_insert_after(avl_tree_t *tree, avl_node_t *after, avl_node_t *node)
{
void avl_insert_after(avl_tree_t *tree, avl_node_t *after, avl_node_t *node) {
if(!after) {
if(tree->head)
if(tree->head) {
avl_insert_before(tree, tree->head, node);
else
} else {
avl_insert_top(tree, node);
}
return;
}
@ -534,10 +554,11 @@ void avl_insert_after(avl_tree_t *tree, avl_node_t *after, avl_node_t *node)
node->parent = after;
node->next = after->next;
if(after->next)
if(after->next) {
after->next->prev = node;
else
} else {
tree->tail = node;
}
after->next = node;
after->right = node;
@ -545,47 +566,51 @@ void avl_insert_after(avl_tree_t *tree, avl_node_t *after, avl_node_t *node)
avl_rebalance(tree, after);
}
avl_node_t *avl_unlink(avl_tree_t *tree, void *data)
{
avl_node_t *avl_unlink(avl_tree_t *tree, void *data) {
avl_node_t *node;
node = avl_search_node(tree, data);
if(node)
if(node) {
avl_unlink_node(tree, node);
}
return node;
}
void avl_unlink_node(avl_tree_t *tree, avl_node_t *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)
if(node->prev) {
node->prev->next = node->next;
else
} else {
tree->head = node->next;
if(node->next)
}
if(node->next) {
node->next->prev = node->prev;
else
} else {
tree->tail = node->prev;
}
parent = node->parent;
superparent =
parent ? node ==
parent->left ? &parent->left : &parent->right : &tree->root;
parent ? node ==
parent->left ? &parent->left : &parent->right : &tree->root;
left = node->left;
right = node->right;
if(!left) {
*superparent = right;
if(right)
if(right) {
right->parent = parent;
}
balnode = parent;
} else if(!right) {
@ -594,8 +619,10 @@ void avl_unlink_node(avl_tree_t *tree, avl_node_t *node)
balnode = parent;
} else {
subst = node->prev;
if(!subst) // This only happens if node is not actually in a tree at all.
if(!subst) { // This only happens if node is not actually in a tree at all.
abort();
}
if(subst == left) {
balnode = subst;
@ -603,8 +630,9 @@ void avl_unlink_node(avl_tree_t *tree, avl_node_t *node)
balnode = subst->parent;
balnode->right = subst->left;
if(balnode->right)
if(balnode->right) {
balnode->right->parent = balnode;
}
subst->left = left;
left->parent = subst;
@ -628,26 +656,24 @@ void avl_unlink_node(avl_tree_t *tree, avl_node_t *node)
#endif
}
void avl_delete_node(avl_tree_t *tree, avl_node_t *node)
{
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)
{
void avl_delete(avl_tree_t *tree, void *data) {
avl_node_t *node;
node = avl_search_node(tree, data);
if(node)
if(node) {
avl_delete_node(tree, node);
}
}
/* Fast tree cleanup */
void avl_delete_tree(avl_tree_t *tree)
{
void avl_delete_tree(avl_tree_t *tree) {
avl_node_t *node, *next;
for(node = tree->head; node; node = next) {
@ -660,8 +686,7 @@ void avl_delete_tree(avl_tree_t *tree)
/* Tree walking */
void avl_foreach(const avl_tree_t *tree, avl_action_t action)
{
void avl_foreach(const avl_tree_t *tree, avl_action_t action) {
avl_node_t *node, *next;
for(node = tree->head; node; node = next) {
@ -670,8 +695,7 @@ void avl_foreach(const avl_tree_t *tree, avl_action_t action)
}
}
void avl_foreach_node(const avl_tree_t *tree, avl_action_t action)
{
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) {
@ -683,13 +707,11 @@ void avl_foreach_node(const avl_tree_t *tree, avl_action_t action)
/* Indexing */
#ifdef AVL_COUNT
unsigned int avl_count(const avl_tree_t *tree)
{
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 *avl_get_node(const avl_tree_t *tree, unsigned int index) {
avl_node_t *node;
unsigned int c;
@ -711,16 +733,17 @@ avl_node_t *avl_get_node(const avl_tree_t *tree, unsigned int index)
return NULL;
}
unsigned int avl_index(const avl_node_t *node)
{
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)
if(node == next->right) {
index += AVL_L_COUNT(next) + 1;
}
node = next;
}
@ -728,8 +751,7 @@ unsigned int avl_index(const avl_node_t *node)
}
#endif
#ifdef AVL_DEPTH
unsigned int avl_depth(const avl_tree_t *tree)
{
unsigned int avl_depth(const avl_tree_t *tree) {
return AVL_NODE_DEPTH(tree->root);
}
#endif

View file

@ -1,3 +1,6 @@
#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
@ -26,14 +29,10 @@
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 (http://www.tinc-vpn.org/) by
library for inclusion into tinc (https://www.tinc-vpn.org/) by
Guus Sliepen <guus@tinc-vpn.org>.
*/
#ifndef __AVL_TREE_H__
#define __AVL_TREE_H__
#ifndef AVL_DEPTH
#ifndef AVL_COUNT
#define AVL_DEPTH
@ -66,9 +65,9 @@ typedef struct avl_node_t {
} avl_node_t;
typedef int (*avl_compare_t)(const void *, const void *);
typedef void (*avl_action_t)(const void *);
typedef void (*avl_action_node_t)(const 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 {
@ -88,56 +87,56 @@ typedef struct avl_tree_t {
/* (De)constructors */
extern avl_tree_t *avl_alloc_tree(avl_compare_t, avl_action_t);
extern void avl_free_tree(avl_tree_t *);
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 *);
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 *, void *);
extern avl_node_t *avl_insert_node(avl_tree_t *, avl_node_t *);
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 *, avl_node_t *);
extern void avl_insert_before(avl_tree_t *, avl_node_t *, avl_node_t *);
extern void avl_insert_after(avl_tree_t *, avl_node_t *, avl_node_t *);
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 *, void *);
extern void avl_unlink_node(avl_tree_t *tree, avl_node_t *);
extern void avl_delete(avl_tree_t *, void *);
extern void avl_delete_node(avl_tree_t *, avl_node_t *);
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 *);
extern void avl_delete_tree(avl_tree_t *tree);
/* Searching */
extern void *avl_search(const avl_tree_t *, const void *);
extern void *avl_search_closest(const avl_tree_t *, const void *, int *);
extern void *avl_search_closest_smaller(const avl_tree_t *, const void *);
extern void *avl_search_closest_greater(const avl_tree_t *, const void *);
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 *, const void *);
extern avl_node_t *avl_search_closest_node(const avl_tree_t *, const void *, int *);
extern avl_node_t *avl_search_closest_smaller_node(const avl_tree_t *, const void *);
extern avl_node_t *avl_search_closest_greater_node(const avl_tree_t *, const void *);
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 *, avl_action_t);
extern void avl_foreach_node(const avl_tree_t *, avl_action_t);
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 *);
extern avl_node_t *avl_get_node(const avl_tree_t *, unsigned int);
extern unsigned int avl_index(const avl_node_t *);
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 *);
extern unsigned int avl_depth(const avl_tree_t *tree);
#endif
#endif /* __AVL_TREE_H__ */
#endif

View file

@ -49,15 +49,13 @@ typedef enum device_type {
#ifdef ENABLE_TUNEMU
DEVICE_TYPE_TUNEMU,
#endif
#ifdef HAVE_NET_IF_UTUN_H
DEVICE_TYPE_UTUN,
#endif
} device_type_t;
int device_fd = -1;
char *device = NULL;
char *iface = NULL;
static char *device_info = NULL;
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)
@ -71,13 +69,15 @@ static device_type_t device_type = DEVICE_TYPE_TUN;
#ifdef HAVE_NET_IF_UTUN_H
static bool setup_utun(void) {
device_fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
if(device_fd == -1) {
logger(LOG_ERR, "Could not open PF_SYSTEM socket: %s\n", strerror(errno));
return false;
}
struct ctl_info info = {};
strlcpy(info.ctl_name, UTUN_CONTROL_NAME, sizeof info.ctl_name);
strlcpy(info.ctl_name, UTUN_CONTROL_NAME, sizeof(info.ctl_name));
if(ioctl(device_fd, CTLIOCGINFO, &info) == -1) {
logger(LOG_ERR, "ioctl(CTLIOCGINFO) failed: %s", strerror(errno));
@ -86,15 +86,18 @@ static bool setup_utun(void) {
int unit = -1;
char *p = strstr(device, "utun"), *e = NULL;
if(p) {
unit = strtol(p + 4, &e, 10);
if(!e)
if(!e) {
unit = -1;
}
}
struct sockaddr_ctl sc = {
.sc_id = info.ctl_id,
.sc_len = sizeof sc,
.sc_len = sizeof(sc),
.sc_family = AF_SYSTEM,
.ss_sysaddr = AF_SYS_CONTROL,
.sc_unit = unit + 1,
@ -106,15 +109,14 @@ static bool setup_utun(void) {
}
char name[64] = "";
socklen_t len = sizeof name;
socklen_t len = sizeof(name);
if(getsockopt(device_fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, name, &len)) {
iface = xstrdup(device);
} else {
iface = xstrdup(name);
}
device_info = "OS X utun device";
logger(LOG_INFO, "%s is a %s", device, device_info);
return true;
@ -125,10 +127,11 @@ static bool setup_device(void) {
// Find out which device file to open
if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
if(routing_mode == RMODE_ROUTER)
if(routing_mode == RMODE_ROUTER) {
device = xstrdup(DEFAULT_TUN_DEVICE);
else
} else {
device = xstrdup(DEFAULT_TAP_DEVICE);
}
}
// Find out if it's supposed to be a tun or a tap device
@ -137,33 +140,40 @@ static bool setup_device(void) {
if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
if(!strcasecmp(type, "tun"))
/* use default */;
/* use default */;
#ifdef ENABLE_TUNEMU
else if(!strcasecmp(type, "tunemu"))
else if(!strcasecmp(type, "tunemu")) {
device_type = DEVICE_TYPE_TUNEMU;
}
#endif
#ifdef HAVE_NET_IF_UTUN_H
else if(!strcasecmp(type, "utun"))
else if(!strcasecmp(type, "utun")) {
device_type = DEVICE_TYPE_UTUN;
}
#endif
else if(!strcasecmp(type, "tunnohead"))
else if(!strcasecmp(type, "tunnohead")) {
device_type = DEVICE_TYPE_TUN;
else if(!strcasecmp(type, "tunifhead"))
} else if(!strcasecmp(type, "tunifhead")) {
device_type = DEVICE_TYPE_TUNIFHEAD;
else if(!strcasecmp(type, "tap"))
} else if(!strcasecmp(type, "tap")) {
device_type = DEVICE_TYPE_TAP;
else {
} else {
logger(LOG_ERR, "Unknown device type %s!", type);
return false;
}
} else {
#ifdef HAVE_NET_IF_UTUN_H
if(strncmp(device, "utun", 4) == 0 || strncmp(device, "/dev/utun", 9) == 0)
if(strncmp(device, "utun", 4) == 0 || strncmp(device, "/dev/utun", 9) == 0) {
device_type = DEVICE_TYPE_UTUN;
else
} else
#endif
if(strstr(device, "tap") || routing_mode != RMODE_ROUTER)
device_type = DEVICE_TYPE_TAP;
if(strstr(device, "tap") || routing_mode != RMODE_ROUTER) {
device_type = DEVICE_TYPE_TAP;
}
}
if(routing_mode == RMODE_SWITCH && device_type != DEVICE_TYPE_TAP) {
@ -175,18 +185,21 @@ static bool setup_device(void) {
switch(device_type) {
#ifdef ENABLE_TUNEMU
case DEVICE_TYPE_TUNEMU: {
char dynamic_name[256] = "";
device_fd = tunemu_open(dynamic_name);
}
break;
case DEVICE_TYPE_TUNEMU: {
char dynamic_name[256] = "";
device_fd = tunemu_open(dynamic_name);
}
break;
#endif
#ifdef HAVE_NET_IF_UTUN_H
case DEVICE_TYPE_UTUN:
return setup_utun();
case DEVICE_TYPE_UTUN:
return setup_utun();
#endif
default:
device_fd = open(device, O_RDWR | O_NONBLOCK);
default:
device_fd = open(device, O_RDWR | O_NONBLOCK);
}
if(device_fd < 0) {
@ -200,92 +213,114 @@ static bool setup_device(void) {
// Guess what the corresponding interface is called
char *realname;
char *realname = NULL;
#if defined(HAVE_FDEVNAME)
realname = fdevname(device_fd) ? : device;
realname = fdevname(device_fd);
#elif defined(HAVE_DEVNAME)
struct stat buf;
if(!fstat(device_fd, &buf))
realname = devname(buf.st_rdev, S_IFCHR) ? : device;
#else
realname = device;
if(!fstat(device_fd, &buf)) {
realname = devname(buf.st_rdev, S_IFCHR);
}
#endif
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
if(!realname) {
realname = device;
}
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) {
iface = xstrdup(strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname);
else if(strcmp(iface, strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname))
} else if(strcmp(iface, strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname)) {
logger(LOG_WARNING, "Warning: Interface does not match Device. $INTERFACE might be set incorrectly.");
}
// Configure the device as best as we can
switch(device_type) {
default:
device_type = DEVICE_TYPE_TUN;
case DEVICE_TYPE_TUN:
default:
device_type = DEVICE_TYPE_TUN;
case DEVICE_TYPE_TUN:
#ifdef TUNSIFHEAD
{
{
const int zero = 0;
if(ioctl(device_fd, TUNSIFHEAD, &zero, sizeof zero) == -1) {
if(ioctl(device_fd, TUNSIFHEAD, &zero, sizeof(zero)) == -1) {
logger(LOG_ERR, "System call `%s' failed: %s", "ioctl", strerror(errno));
return false;
}
}
#endif
#if defined(TUNSIFMODE) && defined(IFF_BROADCAST) && defined(IFF_MULTICAST)
{
const int mode = IFF_BROADCAST | IFF_MULTICAST;
ioctl(device_fd, TUNSIFMODE, &mode, sizeof mode);
ioctl(device_fd, TUNSIFMODE, &mode, sizeof(mode));
}
#endif
device_info = "Generic BSD tun device";
break;
case DEVICE_TYPE_TUNIFHEAD:
device_info = "Generic BSD tun device";
break;
case DEVICE_TYPE_TUNIFHEAD:
#ifdef TUNSIFHEAD
{
const int one = 1;
if(ioctl(device_fd, TUNSIFHEAD, &one, sizeof one) == -1) {
if(ioctl(device_fd, TUNSIFHEAD, &one, sizeof(one)) == -1) {
logger(LOG_ERR, "System call `%s' failed: %s", "ioctl", strerror(errno));
return false;
}
}
#endif
#if defined(TUNSIFMODE) && defined(IFF_BROADCAST) && defined(IFF_MULTICAST)
{
const int mode = IFF_BROADCAST | IFF_MULTICAST;
ioctl(device_fd, TUNSIFMODE, &mode, sizeof mode);
const int mode = IFF_BROADCAST | IFF_MULTICAST;
ioctl(device_fd, TUNSIFMODE, &mode, sizeof(mode));
}
#endif
device_info = "Generic BSD tun device";
break;
case DEVICE_TYPE_TAP:
if(routing_mode == RMODE_ROUTER)
overwrite_mac = true;
device_info = "Generic BSD tap device";
device_info = "Generic BSD tun device";
break;
case DEVICE_TYPE_TAP:
if(routing_mode == RMODE_ROUTER) {
overwrite_mac = true;
}
device_info = "Generic BSD tap device";
#ifdef TAPGIFNAME
{
struct ifreq ifr;
if(ioctl(device_fd, TAPGIFNAME, (void*)&ifr) == 0) {
if(iface)
free(iface);
iface = xstrdup(ifr.ifr_name);
{
struct ifreq ifr;
if(ioctl(device_fd, TAPGIFNAME, (void *)&ifr) == 0) {
if(iface) {
free(iface);
}
iface = xstrdup(ifr.ifr_name);
}
}
#endif
break;
break;
#ifdef ENABLE_TUNEMU
case DEVICE_TYPE_TUNEMU:
device_info = "BSD tunemu device";
break;
case DEVICE_TYPE_TUNEMU:
device_info = "BSD tunemu device";
break;
#endif
}
#ifdef SIOCGIFADDR
if(overwrite_mac)
if(overwrite_mac) {
ioctl(device_fd, SIOCGIFADDR, mymac.x);
}
#endif
logger(LOG_INFO, "%s is a %s", device, device_info);
@ -296,12 +331,14 @@ static bool setup_device(void) {
static void close_device(void) {
switch(device_type) {
#ifdef ENABLE_TUNEMU
case DEVICE_TYPE_TUNEMU:
tunemu_close(device_fd);
break;
case DEVICE_TYPE_TUNEMU:
tunemu_close(device_fd);
break;
#endif
default:
close(device_fd);
default:
close(device_fd);
}
free(device);
@ -312,154 +349,165 @@ static bool read_packet(vpn_packet_t *packet) {
int lenin;
switch(device_type) {
case DEVICE_TYPE_TUN:
case DEVICE_TYPE_TUN:
#ifdef ENABLE_TUNEMU
case DEVICE_TYPE_TUNEMU:
if(device_type == DEVICE_TYPE_TUNEMU)
lenin = tunemu_read(device_fd, packet->data + 14, MTU - 14);
else
case DEVICE_TYPE_TUNEMU:
if(device_type == DEVICE_TYPE_TUNEMU) {
lenin = tunemu_read(device_fd, packet->data + 14, MTU - 14);
} else
#endif
lenin = read(device_fd, packet->data + 14, MTU - 14);
lenin = read(device_fd, packet->data + 14, MTU - 14);
if(lenin <= 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno));
return false;
}
switch(packet->data[14] >> 4) {
case 4:
packet->data[12] = 0x08;
packet->data[13] = 0x00;
break;
case 6:
packet->data[12] = 0x86;
packet->data[13] = 0xDD;
break;
default:
ifdebug(TRAFFIC) logger(LOG_ERR,
"Unknown IP version %d while reading packet from %s %s",
packet->data[14] >> 4, device_info, device);
return false;
}
memset(packet->data, 0, 12);
packet->len = lenin + 14;
break;
case DEVICE_TYPE_UTUN:
case DEVICE_TYPE_TUNIFHEAD: {
if((lenin = read(device_fd, packet->data + 10, MTU - 10)) <= 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno));
return false;
}
switch(packet->data[14] >> 4) {
case 4:
packet->data[12] = 0x08;
packet->data[13] = 0x00;
break;
case 6:
packet->data[12] = 0x86;
packet->data[13] = 0xDD;
break;
default:
ifdebug(TRAFFIC) logger(LOG_ERR,
"Unknown IP version %d while reading packet from %s %s",
packet->data[14] >> 4, device_info, device);
return false;
}
memset(packet->data, 0, 12);
packet->len = lenin + 10;
break;
if(lenin <= 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno));
return false;
}
case DEVICE_TYPE_TAP:
if((lenin = read(device_fd, packet->data, MTU)) <= 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno));
return false;
}
switch(packet->data[14] >> 4) {
case 4:
packet->data[12] = 0x08;
packet->data[13] = 0x00;
break;
packet->len = lenin;
case 6:
packet->data[12] = 0x86;
packet->data[13] = 0xDD;
break;
default:
ifdebug(TRAFFIC) logger(LOG_ERR,
"Unknown IP version %d while reading packet from %s %s",
packet->data[14] >> 4, device_info, device);
return false;
}
memset(packet->data, 0, 12);
packet->len = lenin + 14;
break;
case DEVICE_TYPE_UTUN:
case DEVICE_TYPE_TUNIFHEAD: {
if((lenin = read(device_fd, packet->data + 10, MTU - 10)) <= 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno));
return false;
}
switch(packet->data[14] >> 4) {
case 4:
packet->data[12] = 0x08;
packet->data[13] = 0x00;
break;
case 6:
packet->data[12] = 0x86;
packet->data[13] = 0xDD;
break;
default:
ifdebug(TRAFFIC) logger(LOG_ERR,
"Unknown IP version %d while reading packet from %s %s",
packet->data[14] >> 4, device_info, device);
return false;
}
memset(packet->data, 0, 12);
packet->len = lenin + 10;
break;
}
case DEVICE_TYPE_TAP:
if((lenin = read(device_fd, packet->data, MTU)) <= 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno));
return false;
}
packet->len = lenin;
break;
default:
return false;
}
device_total_in += packet->len;
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s",
packet->len, device_info);
packet->len, device_info);
return true;
}
static bool write_packet(vpn_packet_t *packet) {
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
packet->len, device_info);
packet->len, device_info);
switch(device_type) {
case DEVICE_TYPE_TUN:
if(write(device_fd, packet->data + 14, packet->len - 14) < 0) {
logger(LOG_ERR, "Error while writing to %s %s: %s", device_info,
device, strerror(errno));
return false;
}
break;
case DEVICE_TYPE_UTUN:
case DEVICE_TYPE_TUNIFHEAD: {
int af = (packet->data[12] << 8) + packet->data[13];
uint32_t type;
switch (af) {
case 0x0800:
type = htonl(AF_INET);
break;
case 0x86DD:
type = htonl(AF_INET6);
break;
default:
ifdebug(TRAFFIC) logger(LOG_ERR,
"Unknown address family %x while writing packet to %s %s",
af, device_info, device);
return false;
}
memcpy(packet->data + 10, &type, sizeof type);
if(write(device_fd, packet->data + 10, packet->len - 10) < 0) {
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device,
strerror(errno));
return false;
}
break;
case DEVICE_TYPE_TUN:
if(write(device_fd, packet->data + 14, packet->len - 14) < 0) {
logger(LOG_ERR, "Error while writing to %s %s: %s", device_info,
device, strerror(errno));
return false;
}
case DEVICE_TYPE_TAP:
if(write(device_fd, packet->data, packet->len) < 0) {
logger(LOG_ERR, "Error while writing to %s %s: %s", device_info,
device, strerror(errno));
return false;
}
break;
case DEVICE_TYPE_UTUN:
case DEVICE_TYPE_TUNIFHEAD: {
int af = (packet->data[12] << 8) + packet->data[13];
uint32_t type;
switch(af) {
case 0x0800:
type = htonl(AF_INET);
break;
#ifdef ENABLE_TUNEMU
case DEVICE_TYPE_TUNEMU:
if(tunemu_write(device_fd, packet->data + 14, packet->len - 14) < 0) {
logger(LOG_ERR, "Error while writing to %s %s: %s", device_info,
device, strerror(errno));
return false;
}
case 0x86DD:
type = htonl(AF_INET6);
break;
#endif
default:
ifdebug(TRAFFIC) logger(LOG_ERR,
"Unknown address family %x while writing packet to %s %s",
af, device_info, device);
return false;
}
memcpy(packet->data + 10, &type, sizeof(type));
if(write(device_fd, packet->data + 10, packet->len - 10) < 0) {
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device,
strerror(errno));
return false;
}
break;
}
case DEVICE_TYPE_TAP:
if(write(device_fd, packet->data, packet->len) < 0) {
logger(LOG_ERR, "Error while writing to %s %s: %s", device_info,
device, strerror(errno));
return false;
}
break;
#ifdef ENABLE_TUNEMU
case DEVICE_TYPE_TUNEMU:
if(tunemu_write(device_fd, packet->data + 14, packet->len - 14) < 0) {
logger(LOG_ERR, "Error while writing to %s %s: %s", device_info,
device, strerror(errno));
return false;
}
break;
#endif
default:
return false;
}
device_total_out += packet->len;

View file

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

View file

@ -1,20 +1,20 @@
/*
* tunemu - Tun device emulation for Darwin
* Copyright (C) 2009 Friedrich Schöller <friedrich.schoeller@gmail.com>
*
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*
*/
#ifndef TUNEMU_H

View file

@ -4,7 +4,7 @@
1998-2005 Ivo Timmermans
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
2010-2011 Julien Muchembled <jm@jmuchemb.eu>
2000 Cris van Pelt
2000 Cris van Pelt
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -28,18 +28,18 @@
#include "conf.h"
#include "list.h"
#include "logger.h"
#include "netutl.h" /* for str2address */
#include "netutl.h" /* for str2address */
#include "protocol.h"
#include "utils.h" /* for cp */
#include "utils.h" /* for cp */
#include "xalloc.h"
avl_tree_t *config_tree;
int pinginterval = 0; /* seconds between pings */
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 */
int pinginterval = 0; /* seconds between pings */
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 */
static int config_compare(const config_t *a, const config_t *b) {
@ -47,27 +47,31 @@ static int config_compare(const config_t *a, const config_t *b) {
result = strcasecmp(a->variable, b->variable);
if(result)
if(result) {
return result;
}
/* give priority to command line options */
result = !b->file - !a->file;
if (result)
if(result) {
return result;
}
result = a->line - b->line;
if(result)
if(result) {
return result;
else
} else {
return a->file ? strcmp(a->file, b->file) : 0;
}
}
void init_configuration(avl_tree_t ** config_tree) {
void init_configuration(avl_tree_t **config_tree) {
*config_tree = avl_alloc_tree((avl_compare_t) config_compare, (avl_action_t) free_config);
}
void exit_configuration(avl_tree_t ** config_tree) {
void exit_configuration(avl_tree_t **config_tree) {
avl_delete_tree(*config_tree);
*config_tree = NULL;
}
@ -77,15 +81,9 @@ config_t *new_config(void) {
}
void free_config(config_t *cfg) {
if(cfg->variable)
free(cfg->variable);
if(cfg->value)
free(cfg->value);
if(cfg->file)
free(cfg->file);
free(cfg->variable);
free(cfg->value);
free(cfg->file);
free(cfg);
}
@ -102,11 +100,13 @@ config_t *lookup_config(const avl_tree_t *config_tree, char *variable) {
found = avl_search_closest_greater(config_tree, &cfg);
if(!found)
if(!found) {
return NULL;
}
if(strcasecmp(found->variable, variable))
if(strcasecmp(found->variable, variable)) {
return NULL;
}
return found;
}
@ -121,8 +121,9 @@ config_t *lookup_config_next(const avl_tree_t *config_tree, const config_t *cfg)
if(node->next) {
found = node->next->data;
if(!strcasecmp(found->variable, cfg->variable))
if(!strcasecmp(found->variable, cfg->variable)) {
return found;
}
}
}
@ -130,8 +131,9 @@ config_t *lookup_config_next(const avl_tree_t *config_tree, const config_t *cfg)
}
bool get_config_bool(const config_t *cfg, bool *result) {
if(!cfg)
if(!cfg) {
return false;
}
if(!strcasecmp(cfg->value, "yes")) {
*result = true;
@ -142,27 +144,30 @@ bool get_config_bool(const config_t *cfg, bool *result) {
}
logger(LOG_ERR, "\"yes\" or \"no\" expected for configuration variable %s in %s line %d",
cfg->variable, cfg->file, cfg->line);
cfg->variable, cfg->file, cfg->line);
return false;
}
bool get_config_int(const config_t *cfg, int *result) {
if(!cfg)
if(!cfg) {
return false;
}
if(sscanf(cfg->value, "%d", result) == 1)
if(sscanf(cfg->value, "%d", result) == 1) {
return true;
}
logger(LOG_ERR, "Integer expected for configuration variable %s in %s line %d",
cfg->variable, cfg->file, cfg->line);
cfg->variable, cfg->file, cfg->line);
return false;
}
bool get_config_string(const config_t *cfg, char **result) {
if(!cfg)
if(!cfg) {
return false;
}
*result = xstrdup(cfg->value);
@ -172,8 +177,9 @@ bool get_config_string(const config_t *cfg, char **result) {
bool get_config_address(const config_t *cfg, struct addrinfo **result) {
struct addrinfo *ai;
if(!cfg)
if(!cfg) {
return false;
}
ai = str2addrinfo(cfg->value, NULL, 0);
@ -183,31 +189,32 @@ bool get_config_address(const config_t *cfg, struct addrinfo **result) {
}
logger(LOG_ERR, "Hostname or IP address expected for configuration variable %s in %s line %d",
cfg->variable, cfg->file, cfg->line);
cfg->variable, cfg->file, cfg->line);
return false;
}
bool get_config_subnet(const config_t *cfg, subnet_t ** result) {
subnet_t subnet = {NULL};
bool get_config_subnet(const config_t *cfg, subnet_t **result) {
subnet_t subnet = {0};
if(!cfg)
if(!cfg) {
return false;
}
if(!str2net(&subnet, cfg->value)) {
logger(LOG_ERR, "Subnet expected for configuration variable %s in %s line %d",
cfg->variable, cfg->file, cfg->line);
cfg->variable, cfg->file, cfg->line);
return false;
}
/* Teach newbies what subnets are... */
if(((subnet.type == SUBNET_IPV4)
&& !maskcheck(&subnet.net.ipv4.address, subnet.net.ipv4.prefixlength, sizeof(ipv4_t)))
|| ((subnet.type == SUBNET_IPV6)
&& !maskcheck(&subnet.net.ipv6.address, subnet.net.ipv6.prefixlength, sizeof(ipv6_t)))) {
&& !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);
cfg->variable, cfg->file, cfg->line);
return false;
}
@ -219,26 +226,31 @@ bool get_config_subnet(const config_t *cfg, subnet_t ** result) {
/*
Read exactly one line and strip the trailing newline if any.
*/
static char *readline(FILE * fp, char *buf, size_t buflen) {
static char *readline(FILE *fp, char *buf, size_t buflen) {
char *newline = NULL;
char *p;
if(feof(fp))
if(feof(fp)) {
return NULL;
}
p = fgets(buf, buflen, fp);
if(!p)
if(!p) {
return NULL;
}
newline = strchr(p, '\n');
if(!newline)
if(!newline) {
return buf;
}
*newline = '\0'; /* kill newline */
if(newline > p && newline[-1] == '\r') /* and carriage return if necessary */
*newline = '\0'; /* kill newline */
if(newline > p && newline[-1] == '\r') { /* and carriage return if necessary */
newline[-1] = '\0';
}
return buf;
}
@ -250,26 +262,32 @@ config_t *parse_config_line(char *line, const char *fname, int lineno) {
variable = value = line;
eol = line + strlen(line);
while(strchr("\t ", *--eol))
while(strchr("\t ", *--eol)) {
*eol = '\0';
}
len = strcspn(value, "\t =");
value += len;
value += strspn(value, "\t ");
if(*value == '=') {
value++;
value += strspn(value, "\t ");
}
variable[len] = '\0';
if(!*value) {
const char err[] = "No value for variable";
if (fname)
if(fname)
logger(LOG_ERR, "%s `%s' on line %d while reading config file %s",
err, variable, lineno, fname);
err, variable, lineno, fname);
else
logger(LOG_ERR, "%s `%s' in command line option %d",
err, variable, lineno);
err, variable, lineno);
return NULL;
}
@ -303,33 +321,41 @@ bool read_config_file(avl_tree_t *config_tree, const char *fname) {
}
for(;;) {
line = readline(fp, buffer, sizeof buffer);
line = readline(fp, buffer, sizeof(buffer));
if(!line) {
if(feof(fp))
if(feof(fp)) {
result = true;
}
break;
}
lineno++;
if(!*line || *line == '#')
continue;
if(ignore) {
if(!strncmp(line, "-----END", 8))
ignore = false;
if(!*line || *line == '#') {
continue;
}
if(ignore) {
if(!strncmp(line, "-----END", 8)) {
ignore = false;
}
continue;
}
if(!strncmp(line, "-----BEGIN", 10)) {
ignore = true;
continue;
}
cfg = parse_config_line(line, fname, lineno);
if (!cfg)
if(!cfg) {
break;
}
config_add(config_tree, cfg);
}
@ -339,86 +365,92 @@ bool read_config_file(avl_tree_t *config_tree, const char *fname) {
}
void read_config_options(avl_tree_t *config_tree, const char *prefix) {
list_node_t *node, *next;
size_t prefix_len = prefix ? strlen(prefix) : 0;
for(node = cmdline_conf->tail; node; node = next) {
config_t *orig_cfg, *cfg = (config_t *)node->data;
next = node->prev;
for(const list_node_t *node = cmdline_conf->tail; node; node = node->prev) {
const config_t *cfg = node->data;
if(!prefix) {
if(strchr(cfg->variable, '.'))
if(strchr(cfg->variable, '.')) {
continue;
node->data = NULL;
list_unlink_node(cmdline_conf, node);
}
} else {
if(strncmp(prefix, cfg->variable, prefix_len) ||
cfg->variable[prefix_len] != '.')
cfg->variable[prefix_len] != '.') {
continue;
/* Because host configuration is parsed again when
reconnecting, nodes must not be freed when a prefix
is given. */
orig_cfg = cfg;
cfg = new_config();
cfg->variable = xstrdup(orig_cfg->variable + prefix_len + 1);
cfg->value = xstrdup(orig_cfg->value);
cfg->file = NULL;
cfg->line = orig_cfg->line;
}
}
config_add(config_tree, cfg);
config_t *new = new_config();
if(prefix) {
new->variable = xstrdup(cfg->variable + prefix_len + 1);
} else {
new->variable = xstrdup(cfg->variable);
}
new->value = xstrdup(cfg->value);
new->file = NULL;
new->line = cfg->line;
config_add(config_tree, new);
}
}
bool read_server_config(void) {
char *fname;
char fname[PATH_MAX];
bool x;
read_config_options(config_tree, NULL);
xasprintf(&fname, "%s/tinc.conf", confbase);
snprintf(fname, sizeof(fname), "%s/tinc.conf", confbase);
errno = 0;
x = read_config_file(config_tree, fname);
// We will try to read the conf files in the "conf.d" dir
if (x) {
char * dname;
xasprintf(&dname, "%s/conf.d", confbase);
DIR *dir = opendir (dname);
if(x) {
char dname[PATH_MAX];
snprintf(dname, sizeof(dname), "%s/conf.d", confbase);
DIR *dir = opendir(dname);
// If we can find this dir
if (dir) {
if(dir) {
struct dirent *ep;
// We list all the files in it
while (x && (ep = readdir (dir))) {
while(x && (ep = readdir(dir))) {
size_t l = strlen(ep->d_name);
// And we try to read the ones that end with ".conf"
if (l > 5 && !strcmp(".conf", & ep->d_name[ l - 5 ])) {
free(fname);
xasprintf(&fname, "%s/%s", dname, ep->d_name);
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)) {
logger(LOG_ERR, "Pathname too long: %s/%s", dname, ep->d_name);
return false;
}
x = read_config_file(config_tree, fname);
}
}
closedir (dir);
closedir(dir);
}
free(dname);
}
if(!x) { /* System error: complain */
if(!x && errno) {
logger(LOG_ERR, "Failed to read `%s': %s", fname, strerror(errno));
}
free(fname);
return x;
}
bool read_connection_config(connection_t *c) {
char *fname;
char fname[PATH_MAX];
bool x;
read_config_options(c->config_tree, c->name);
xasprintf(&fname, "%s/hosts/%s", confbase, c->name);
snprintf(fname, sizeof(fname), "%s/hosts/%s", confbase, c->name);
x = read_config_file(c->config_tree, fname);
free(fname);
return x;
}
@ -430,34 +462,43 @@ static void disable_old_keys(const char *filename) {
FILE *r, *w;
r = fopen(filename, "r");
if(!r)
if(!r) {
return;
}
snprintf(tmpfile, sizeof tmpfile, "%s.tmp", filename);
int len = snprintf(tmpfile, sizeof(tmpfile), "%s.tmp", filename);
w = fopen(tmpfile, "w");
if(len < 0 || len >= PATH_MAX) {
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)) {
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)) {
} 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)
if(w) {
fclose(w);
}
fclose(r);
if(!w && disabled) {
@ -469,10 +510,12 @@ static void disable_old_keys(const char *filename) {
#ifdef HAVE_MINGW
// We cannot atomically replace files on Windows.
char bakfile[PATH_MAX] = "";
snprintf(bakfile, sizeof bakfile, "%s.bak", filename);
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");
@ -489,8 +532,9 @@ static void disable_old_keys(const char *filename) {
FILE *ask_and_open(const char *filename, const char *what) {
FILE *r;
char *directory;
char directory[PATH_MAX];
char line[PATH_MAX];
char abspath[PATH_MAX];
const char *fn;
/* Check stdin and stdout */
@ -502,37 +546,43 @@ FILE *ask_and_open(const char *filename, const char *what) {
} else {
/* Ask for a file and/or directory name. */
fprintf(stdout, "Please enter a file to save %s to [%s]: ",
what, filename);
what, filename);
fflush(stdout);
fn = readline(stdin, line, sizeof line);
fn = readline(stdin, line, sizeof(line));
if(!fn) {
fprintf(stderr, "Error while reading stdin: %s\n",
strerror(errno));
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. */
char *p;
getcwd(directory, sizeof(directory));
directory = get_current_dir_name();
xasprintf(&p, "%s/%s", directory, fn);
free(directory);
fn = p;
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 */
umask(0077); /* Disallow everything for group and other */
disable_old_keys(fn);
@ -542,7 +592,7 @@ FILE *ask_and_open(const char *filename, const char *what) {
if(!r) {
fprintf(stderr, "Error opening file `%s': %s\n",
fn, strerror(errno));
fn, strerror(errno));
return NULL;
}

View file

@ -1,3 +1,6 @@
#ifndef TINC_CONF_H
#define TINC_CONF_H
/*
conf.h -- header for conf.c
Copyright (C) 1998-2005 Ivo Timmermans
@ -18,9 +21,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_CONF_H__
#define __TINC_CONF_H__
#include "avl_tree.h"
#include "list.h"
@ -44,25 +44,24 @@ extern char *confbase;
extern char *netname;
extern list_t *cmdline_conf;
extern void init_configuration(avl_tree_t **);
extern void exit_configuration(avl_tree_t **);
extern config_t *new_config(void) __attribute__ ((__malloc__));
extern void free_config(config_t *);
extern void config_add(avl_tree_t *, config_t *);
extern config_t *lookup_config(const avl_tree_t *, char *);
extern config_t *lookup_config_next(const avl_tree_t *, const config_t *);
extern bool get_config_bool(const config_t *, bool *);
extern bool get_config_int(const config_t *, int *);
extern bool get_config_string(const config_t *, char **);
extern bool get_config_address(const config_t *, struct addrinfo **);
extern bool get_config_subnet(const config_t *, struct subnet_t **);
extern void init_configuration(avl_tree_t **config_tree);
extern void exit_configuration(avl_tree_t **config_tree);
extern config_t *new_config(void) __attribute__((__malloc__));
extern void free_config(config_t *cfg);
extern void config_add(avl_tree_t *config_tree, config_t *cfg);
extern config_t *lookup_config(const avl_tree_t *config_tree, char *variable);
extern config_t *lookup_config_next(const avl_tree_t *config_tree, const config_t *cfg);
extern bool get_config_bool(const config_t *cfg, bool *result);
extern bool get_config_int(const config_t *cfg, int *result);
extern bool get_config_string(const config_t *cfg, char **result);
extern bool get_config_address(const config_t *cfg, struct addrinfo **result);
extern bool get_config_subnet(const config_t *cfg, struct subnet_t **result);
extern config_t *parse_config_line(char *, const char *, int);
extern bool read_config_file(avl_tree_t *, const char *);
extern void read_config_options(avl_tree_t *, const char *);
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 void read_config_options(avl_tree_t *config_tree, const char *prefix);
extern bool read_server_config(void);
extern bool read_connection_config(struct connection_t *);
extern FILE *ask_and_open(const char *, const char *);
extern bool is_safe_path(const char *);
extern bool read_connection_config(struct connection_t *c);
extern FILE *ask_and_open(const char *fname, const char *what);
#endif /* __TINC_CONF_H__ */
#endif

View file

@ -1,6 +1,6 @@
/*
connection.c -- connection list management
Copyright (C) 2000-2012 Guus Sliepen <guus@tinc-vpn.org>,
Copyright (C) 2000-2016 Guus Sliepen <guus@tinc-vpn.org>,
2000-2005 Ivo Timmermans
2008 Max Rijevski <maksuf@gmail.com>
@ -28,7 +28,7 @@
#include "utils.h"
#include "xalloc.h"
avl_tree_t *connection_tree; /* Meta connections */
avl_tree_t *connection_tree; /* Meta connections */
connection_t *everyone;
static int connection_compare(const connection_t *a, const connection_t *b) {
@ -52,8 +52,9 @@ connection_t *new_connection(void) {
c = xmalloc_and_zero(sizeof(connection_t));
if(!c)
if(!c) {
return NULL;
}
gettimeofday(&c->start, NULL);
@ -91,15 +92,17 @@ void free_connection_partially(connection_t *c) {
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_cleanup(c->inctx);
EVP_CIPHER_CTX_reset(c->inctx);
free(c->inctx);
c->inctx = NULL;
}
if(c->outctx) {
EVP_CIPHER_CTX_cleanup(c->outctx);
EVP_CIPHER_CTX_reset(c->outctx);
free(c->outctx);
c->outctx = NULL;
}
@ -116,8 +119,9 @@ void free_connection(connection_t *c) {
free(c->name);
free(c->hostname);
if(c->config_tree)
if(c->config_tree) {
exit_configuration(&c->config_tree);
}
free(c);
}
@ -139,8 +143,8 @@ void dump_connections(void) {
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);
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.");

View file

@ -1,6 +1,9 @@
#ifndef TINC_CONNECTION_H
#define TINC_CONNECTION_H
/*
connection.h -- header for connection.c
Copyright (C) 2000-2012 Guus Sliepen <guus@tinc-vpn.org>,
Copyright (C) 2000-2016 Guus Sliepen <guus@tinc-vpn.org>,
2000-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify
@ -18,30 +21,33 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_CONNECTION_H__
#define __TINC_CONNECTION_H__
#include <openssl/rsa.h>
#include <openssl/evp.h>
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#define EVP_CIPHER_CTX_reset(c) EVP_CIPHER_CTX_cleanup(c)
#endif
#include "avl_tree.h"
#define OPTION_INDIRECT 0x0001
#define OPTION_TCPONLY 0x0002
#define OPTION_PMTU_DISCOVERY 0x0004
#define OPTION_CLAMP_MSS 0x0008
#define OPTION_INDIRECT 0x0001
#define OPTION_TCPONLY 0x0002
#define OPTION_PMTU_DISCOVERY 0x0004
#define OPTION_CLAMP_MSS 0x0008
typedef struct connection_status_t {
unsigned int pinged:1; /* sent ping */
unsigned int active:1; /* 1 if active.. */
unsigned int connecting:1; /* 1 if we are waiting for a non-blocking connect() to finish */
unsigned int unused_termreq:1; /* the termination of this connection was requested */
unsigned int remove:1; /* Set to 1 if you want this connection removed */
unsigned int timeout:1; /* 1 if gotten timeout */
unsigned int encryptout:1; /* 1 if we can encrypt outgoing traffic */
unsigned int decryptin:1; /* 1 if we have to decrypt incoming traffic */
unsigned int mst:1; /* 1 if this connection is part of a minimum spanning tree */
unsigned int unused:23;
unsigned int pinged: 1; /* sent ping */
unsigned int active: 1; /* 1 if active.. */
unsigned int connecting: 1; /* 1 if we are waiting for a non-blocking connect() to finish */
unsigned int unused_termreq: 1; /* the termination of this connection was requested */
unsigned int remove: 1; /* Set to 1 if you want this connection removed */
unsigned int timeout: 1; /* 1 if gotten timeout */
unsigned int encryptout: 1; /* 1 if we can encrypt outgoing traffic */
unsigned int decryptin: 1; /* 1 if we have to decrypt incoming traffic */
unsigned int mst: 1; /* 1 if this connection is part of a minimum spanning tree */
unsigned int proxy_passed: 1; /* 1 if we are connecting via a proxy and we have finished talking with it */
unsigned int tarpit: 1; /* 1 if the connection should be added to the tarpit */
unsigned int unused: 21;
} connection_status_t;
#include "edge.h"
@ -49,55 +55,57 @@ typedef struct connection_status_t {
#include "node.h"
typedef struct connection_t {
char *name; /* name he claims to have */
char *name; /* name he claims to have */
union sockaddr_t address; /* his real (internet) ip */
char *hostname; /* the hostname of its real ip */
int protocol_version; /* used protocol */
union sockaddr_t address; /* his real (internet) ip */
char *hostname; /* the hostname of its real ip */
int protocol_version; /* used protocol */
int socket; /* socket used for this connection */
uint32_t options; /* options for this connection */
connection_status_t status; /* status info */
int estimated_weight; /* estimation for the weight of the edge for this connection */
struct timeval start; /* time this connection was started, used for above estimation */
struct outgoing_t *outgoing; /* used to keep track of outgoing connections */
int socket; /* socket used for this connection */
uint32_t options; /* options for this connection */
connection_status_t status; /* status info */
int estimated_weight; /* estimation for the weight of the edge for this connection */
struct timeval start; /* time this connection was started, used for above estimation */
struct outgoing_t *outgoing; /* used to keep track of outgoing connections */
struct node_t *node; /* node associated with the other end */
struct edge_t *edge; /* edge associated with this connection */
struct node_t *node; /* node associated with the other end */
struct edge_t *edge; /* edge associated with this connection */
RSA *rsa_key; /* his public/private key */
const EVP_CIPHER *incipher; /* Cipher he will use to send data to us */
const EVP_CIPHER *outcipher; /* Cipher we will use to send data to him */
EVP_CIPHER_CTX *inctx; /* Context of encrypted meta data that will come from him to us */
EVP_CIPHER_CTX *outctx; /* Context of encrypted meta data that will be sent from us to him */
char *inkey; /* His symmetric meta key + iv */
char *outkey; /* Our symmetric meta key + iv */
int inkeylength; /* Length of his key + iv */
int outkeylength; /* Length of our key + iv */
RSA *rsa_key; /* his public/private key */
const EVP_CIPHER *incipher; /* Cipher he will use to send data to us */
const EVP_CIPHER *outcipher; /* Cipher we will use to send data to him */
EVP_CIPHER_CTX *inctx; /* Context of encrypted meta data that will come from him to us */
EVP_CIPHER_CTX *outctx; /* Context of encrypted meta data that will be sent from us to him */
uint64_t inbudget; /* Encrypted bytes send budget */
uint64_t outbudget; /* Encrypted bytes receive budget */
char *inkey; /* His symmetric meta key + iv */
char *outkey; /* Our symmetric meta key + iv */
int inkeylength; /* Length of his key + iv */
int outkeylength; /* Length of our key + iv */
const EVP_MD *indigest;
const EVP_MD *outdigest;
int inmaclength;
int outmaclength;
int incompression;
int outcompression;
char *mychallenge; /* challenge we received from him */
char *hischallenge; /* challenge we sent to him */
char *mychallenge; /* challenge we received from him */
char *hischallenge; /* challenge we sent to him */
char buffer[MAXBUFSIZE]; /* metadata input buffer */
int buflen; /* bytes read into buffer */
int reqlen; /* length of incoming request */
int tcplen; /* length of incoming TCPpacket */
int allow_request; /* defined if there's only one request possible */
char buffer[MAXBUFSIZE]; /* metadata input buffer */
int buflen; /* bytes read into buffer */
int reqlen; /* length of incoming request */
length_t tcplen; /* length of incoming TCPpacket */
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 */
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_flushed_time; /* last time buffer was empty. Only meaningful if outbuflen > 0 */
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 */
avl_tree_t *config_tree; /* Pointer to configuration tree belonging to him */
} connection_t;
extern avl_tree_t *connection_tree;
@ -105,11 +113,11 @@ extern connection_t *everyone;
extern void init_connections(void);
extern void exit_connections(void);
extern connection_t *new_connection(void) __attribute__ ((__malloc__));
extern void free_connection(connection_t *);
extern void free_connection_partially(connection_t *);
extern void connection_add(connection_t *);
extern void connection_del(connection_t *);
extern connection_t *new_connection(void) __attribute__((__malloc__));
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_del(connection_t *c);
extern void dump_connections(void);
#endif /* __TINC_CONNECTION_H__ */
#endif

View file

@ -37,7 +37,7 @@ int device_fd = -1;
static HANDLE device_handle = INVALID_HANDLE_VALUE;
char *device = NULL;
char *iface = NULL;
static char *device_info = NULL;
static const char *device_info = "Windows tap device";
static uint64_t device_total_in = 0;
static uint64_t device_total_out = 0;
@ -61,8 +61,9 @@ static bool setup_device(void) {
get_config_string(lookup_config(config_tree, "Device"), &device);
get_config_string(lookup_config(config_tree, "Interface"), &iface);
if(device && iface)
if(device && iface) {
logger(LOG_WARNING, "Warning: both Device and Interface specified, results may not be as expected");
}
/* Open registry and look for network adapters */
@ -71,44 +72,51 @@ static bool setup_device(void) {
return false;
}
for (i = 0; ; i++) {
for(i = 0; ; i++) {
len = sizeof(adapterid);
if(RegEnumKeyEx(key, i, adapterid, &len, 0, 0, 0, NULL))
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))
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)
if(err) {
continue;
}
if(device) {
if(!strcmp(device, adapterid)) {
found = true;
break;
} else
} else {
continue;
}
}
if(iface) {
if(!strcmp(iface, adaptername)) {
found = true;
break;
} else
} else {
continue;
}
}
snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
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;
@ -123,14 +131,16 @@ static bool setup_device(void) {
return false;
}
if(!device)
if(!device) {
device = xstrdup(adapterid);
}
if(!iface)
if(!iface) {
iface = xstrdup(adaptername);
}
snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, device);
/* 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. */
@ -141,9 +151,9 @@ static bool setup_device(void) {
}
/* The parent opens the tap device for writing. */
device_handle = CreateFile(tapname, GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM , 0);
device_handle = CreateFile(tapname, GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
if(device_handle == INVALID_HANDLE_VALUE) {
logger(LOG_ERR, "Could not open Windows tap device %s (%s) for writing: %s", device, iface, winerror(GetLastError()));
return false;
@ -174,7 +184,7 @@ static bool setup_device(void) {
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;
@ -205,13 +215,12 @@ static bool setup_device(void) {
}
read(device_fd, &gelukt, 1);
if(gelukt != 1) {
logger(LOG_DEBUG, "Tap reader failed!");
return false;
}
device_info = "Windows tap device";
logger(LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
return true;
@ -233,16 +242,16 @@ static bool read_packet(vpn_packet_t *packet) {
if((lenin = read(sp[0], packet->data, MTU)) <= 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno));
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);
device_info);
return true;
}
@ -251,9 +260,9 @@ 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);
packet->len, device_info);
if(!WriteFile (device_handle, packet->data, packet->len, &lenout, NULL)) {
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;
}

View file

@ -1,3 +1,6 @@
#ifndef TINC_DEVICE_H
#define TINC_DEVICE_H
/*
device.h -- generic header for device.c
Copyright (C) 2001-2005 Ivo Timmermans
@ -18,9 +21,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_DEVICE_H__
#define __TINC_DEVICE_H__
#include "net.h"
extern int device_fd;
@ -31,8 +31,8 @@ extern char *iface;
typedef struct devops_t {
bool (*setup)(void);
void (*close)(void);
bool (*read)(struct vpn_packet_t *);
bool (*write)(struct vpn_packet_t *);
bool (*read)(struct vpn_packet_t *packet);
bool (*write)(struct vpn_packet_t *packet);
void (*dump_stats)(void);
} devops_t;
@ -44,4 +44,4 @@ extern const devops_t uml_devops;
extern const devops_t vde_devops;
extern devops_t devops;
#endif /* __TINC_DEVICE_H__ */
#endif

View file

@ -1,7 +1,7 @@
/*
dropin.c -- a set of drop-in replacements for libc functions
Copyright (C) 2000-2005 Ivo Timmermans,
2000-2011 Guus Sliepen <guus@tinc-vpn.org>
2000-2016 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -25,7 +25,7 @@
#ifndef HAVE_DAEMON
/*
Replacement for the daemon() function.
The daemon() function is for programs wishing to detach themselves
from the controlling terminal and run in the background as system
daemons.
@ -50,8 +50,9 @@ int daemon(int nochdir, int noclose) {
}
/* If we are the parent, terminate */
if(pid)
if(pid) {
exit(0);
}
/* Detach by becoming the new process group leader */
if(setsid() < 0) {
@ -86,40 +87,6 @@ int daemon(int nochdir, int noclose) {
}
#endif
#ifndef HAVE_GET_CURRENT_DIR_NAME
/*
Replacement for the GNU get_current_dir_name function:
get_current_dir_name will malloc(3) an array big enough to hold the
current directory name. If the environment variable PWD is set, and
its value is correct, then that value will be returned.
*/
char *get_current_dir_name(void) {
size_t size;
char *buf;
char *r;
/* Start with 100 bytes. If this turns out to be insufficient to
contain the working directory, double the size. */
size = 100;
buf = xmalloc(size);
errno = 0; /* Success */
r = getcwd(buf, size);
/* getcwd returns NULL and sets errno to ERANGE if the bufferspace
is insufficient to contain the entire working directory. */
while(r == NULL && errno == ERANGE) {
free(buf);
size <<= 1; /* double the size */
buf = xmalloc(size);
r = getcwd(buf, size);
}
return buf;
}
#endif
#ifndef HAVE_ASPRINTF
int asprintf(char **buf, const char *fmt, ...) {
int result;
@ -140,10 +107,12 @@ int vasprintf(char **buf, const char *fmt, va_list ap) {
va_copy(aq, ap);
status = vsnprintf(*buf, len, fmt, aq);
buf[len - 1] = 0;
va_end(aq);
if(status >= 0)
if(status >= 0) {
*buf = xrealloc(*buf, status + 1);
}
if(status > len - 1) {
len = status;

View file

@ -1,3 +1,6 @@
#ifndef TINC_DROPIN_H
#define TINC_DROPIN_H
/*
dropin.h -- header file for dropin.c
Copyright (C) 2000-2005 Ivo Timmermans,
@ -18,14 +21,11 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __DROPIN_H__
#define __DROPIN_H__
#include "fake-getaddrinfo.h"
#include "fake-getnameinfo.h"
#ifndef HAVE_DAEMON
extern int daemon(int, int);
extern int daemon(int nochdir, int noclose);
#endif
#ifndef HAVE_GET_CURRENT_DIR_NAME
@ -33,16 +33,16 @@ extern char *get_current_dir_name(void);
#endif
#ifndef HAVE_ASPRINTF
extern int asprintf(char **, const char *, ...);
extern int vasprintf(char **, const char *, va_list ap);
extern int asprintf(char **buf, const char *fmt, ...);
extern int vasprintf(char **buf, const char *fmt, va_list ap);
#endif
#ifndef HAVE_GETTIMEOFDAY
extern int gettimeofday(struct timeval *, void *);
extern int gettimeofday(struct timeval *tv, void *tz);
#endif
#ifndef HAVE_USLEEP
extern int usleep(long long);
extern int usleep(long long usec);
#endif
#endif /* __DROPIN_H__ */
#endif

View file

@ -22,23 +22,27 @@
#include "device.h"
#include "logger.h"
#include "net.h"
#include "xalloc.h"
static char *device_info = "dummy device";
static const char *device_info = "dummy device";
static uint64_t device_total_in = 0;
static uint64_t device_total_out = 0;
static bool setup_device(void) {
device = "dummy";
iface = "dummy";
device = xstrdup("dummy");
iface = xstrdup("dummy");
logger(LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
return true;
}
static void close_device(void) {
free(device);
free(iface);
}
static bool read_packet(vpn_packet_t *packet) {
(void)packet;
return false;
}

View file

@ -28,7 +28,7 @@
#include "utils.h"
#include "xalloc.h"
avl_tree_t *edge_weight_tree; /* Tree with all edges, sorted on weight */
avl_tree_t *edge_weight_tree; /* Tree with all edges, sorted on weight */
static int edge_compare(const edge_t *a, const edge_t *b) {
return strcmp(a->to->name, b->to->name);
@ -39,13 +39,15 @@ static int edge_weight_compare(const edge_t *a, const edge_t *b) {
result = a->weight - b->weight;
if(result)
if(result) {
return result;
}
result = strcmp(a->from->name, b->from->name);
if(result)
if(result) {
return result;
}
return strcmp(a->to->name, b->to->name);
}
@ -84,13 +86,15 @@ void edge_add(edge_t *e) {
e->reverse = lookup_edge(e->to, e->from);
if(e->reverse)
if(e->reverse) {
e->reverse->reverse = e;
}
}
void edge_del(edge_t *e) {
if(e->reverse)
if(e->reverse) {
e->reverse->reverse = NULL;
}
avl_delete(edge_weight_tree, e);
avl_delete(e->from->edge_tree, e);
@ -98,7 +102,7 @@ void edge_del(edge_t *e) {
edge_t *lookup_edge(node_t *from, node_t *to) {
edge_t v;
v.from = from;
v.to = to;
@ -115,11 +119,12 @@ void dump_edges(void) {
for(node = node_tree->head; node; node = node->next) {
n = node->data;
for(node2 = n->edge_tree->head; node2; node2 = node2->next) {
e = node2->data;
address = sockaddr2hostname(&e->address);
logger(LOG_DEBUG, " %s to %s at %s options %x weight %d",
e->from->name, e->to->name, address, e->options, e->weight);
e->from->name, e->to->name, address, e->options, e->weight);
free(address);
}
}

View file

@ -1,3 +1,6 @@
#ifndef TINC_EDGE_H
#define TINC_EDGE_H
/*
edge.h -- header for edge.c
Copyright (C) 2001-2006 Guus Sliepen <guus@tinc-vpn.org>,
@ -18,9 +21,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_EDGE_H__
#define __TINC_EDGE_H__
#include "avl_tree.h"
#include "connection.h"
#include "net.h"
@ -31,24 +31,24 @@ typedef struct edge_t {
struct node_t *to;
sockaddr_t address;
uint32_t options; /* options turned on for this edge */
int weight; /* weight of this edge */
uint32_t options; /* options turned on for this edge */
int weight; /* weight of this edge */
struct connection_t *connection; /* connection associated with this edge, if available */
struct edge_t *reverse; /* edge in the opposite direction, if available */
struct connection_t *connection; /* connection associated with this edge, if available */
struct edge_t *reverse; /* edge in the opposite direction, if available */
} edge_t;
extern avl_tree_t *edge_weight_tree; /* Tree with all known edges sorted on weight */
extern avl_tree_t *edge_weight_tree; /* Tree with all known edges sorted on weight */
extern void init_edges(void);
extern void exit_edges(void);
extern edge_t *new_edge(void) __attribute__ ((__malloc__));
extern void free_edge(edge_t *);
extern avl_tree_t *new_edge_tree(void) __attribute__ ((__malloc__));
extern void free_edge_tree(avl_tree_t *);
extern void edge_add(edge_t *);
extern void edge_del(edge_t *);
extern edge_t *lookup_edge(struct node_t *, struct node_t *);
extern edge_t *new_edge(void) __attribute__((__malloc__));
extern void free_edge(edge_t *e);
extern avl_tree_t *new_edge_tree(void) __attribute__((__malloc__));
extern void free_edge_tree(avl_tree_t *edge_tree);
extern void edge_add(edge_t *e);
extern void edge_del(edge_t *e);
extern edge_t *lookup_edge(struct node_t *from, struct node_t *to);
extern void dump_edges(void);
#endif /* __TINC_EDGE_H__ */
#endif

View file

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

View file

@ -31,11 +31,13 @@ extern time_t now;
static int id;
static int event_compare(const event_t *a, const event_t *b) {
if(a->time > b->time)
if(a->time > b->time) {
return 1;
}
if(a->time < b->time)
if(a->time < b->time) {
return -1;
}
return a->id - b->id;
}
@ -54,19 +56,22 @@ void expire_events(void) {
time_t diff;
/*
* Make all events appear expired by substracting the difference between
* the expiration time of the last event and the current time.
* Make all events appear expired by subtracting the difference between
* the expiration time of the last event and the current time.
*/
if(!event_tree->tail)
if(!event_tree->tail) {
return;
}
event = event_tree->tail->data;
if(event->time <= now)
if(event->time <= now) {
return;
}
diff = event->time - now;
for(node = event_tree->head; node; node = node->next) {
event = node->data;
event->time -= diff;
@ -108,7 +113,9 @@ event_t *get_expired_event(void) {
}
event_t *peek_next_event(void) {
if (event_tree->head)
if(event_tree->head) {
return event_tree->head->data;
}
return NULL;
}

View file

@ -1,3 +1,6 @@
#ifndef TINC_EVENT_H
#define TINC_EVENT_H
/*
event.h -- header for event.c
Copyright (C) 2002-2009 Guus Sliepen <guus@tinc-vpn.org>,
@ -18,9 +21,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_EVENT_H__
#define __TINC_EVENT_H__
#include "avl_tree.h"
extern avl_tree_t *event_tree;
@ -37,11 +37,11 @@ typedef struct event {
extern void init_events(void);
extern void exit_events(void);
extern void expire_events(void);
extern event_t *new_event(void) __attribute__ ((__malloc__));
extern void free_event(event_t *);
extern void event_add(event_t *);
extern void event_del(event_t *);
extern event_t *new_event(void) __attribute__((__malloc__));
extern void free_event(event_t *event);
extern void event_add(event_t *event);
extern void event_del(event_t *event);
extern event_t *get_expired_event(void);
extern event_t *peek_next_event(void);
#endif /* __TINC_EVENT_H__ */
#endif

View file

@ -1,19 +0,0 @@
/*
* fake library for ssh
*
* This file is included in getaddrinfo.c and getnameinfo.c.
* See getaddrinfo.c and getnameinfo.c.
*/
/* for old netdb.h */
#ifndef EAI_NODATA
#define EAI_NODATA 1
#endif
#ifndef EAI_MEMORY
#define EAI_MEMORY 2
#endif
#ifndef EAI_FAMILY
#define EAI_FAMILY 3
#endif

View file

@ -2,10 +2,10 @@
* fake library for ssh
*
* This file includes getaddrinfo(), freeaddrinfo() and gai_strerror().
* These funtions are defined in rfc2133.
* These functions are defined in rfc2133.
*
* But these functions are not implemented correctly. The minimum subset
* is implemented for ssh use only. For exapmle, this routine assumes
* is implemented for ssh use only. For example, this routine assumes
* that ai_family is AF_INET. Don't use it for another purpose.
*/
@ -17,24 +17,25 @@
#include "xalloc.h"
#if !HAVE_DECL_GAI_STRERROR
char *gai_strerror(int ecode)
{
switch (ecode) {
case EAI_NODATA:
return "No address associated with hostname";
case EAI_MEMORY:
return "Memory allocation failure";
case EAI_FAMILY:
return "Address family not supported";
default:
return "Unknown error";
char *gai_strerror(int ecode) {
switch(ecode) {
case EAI_NODATA:
return "No address associated with hostname";
case EAI_MEMORY:
return "Memory allocation failure";
case EAI_FAMILY:
return "Address family not supported";
default:
return "Unknown error";
}
}
}
#endif /* !HAVE_GAI_STRERROR */
#if !HAVE_DECL_FREEADDRINFO
void freeaddrinfo(struct addrinfo *ai)
{
void freeaddrinfo(struct addrinfo *ai) {
struct addrinfo *next;
while(ai) {
@ -46,56 +47,58 @@ void freeaddrinfo(struct addrinfo *ai)
#endif /* !HAVE_FREEADDRINFO */
#if !HAVE_DECL_GETADDRINFO
static struct addrinfo *malloc_ai(uint16_t port, uint32_t addr)
{
static struct addrinfo *malloc_ai(uint16_t port, uint32_t addr) {
struct addrinfo *ai;
ai = xmalloc_and_zero(sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
ai->ai_addr = (struct sockaddr *)(ai + 1);
ai->ai_addrlen = sizeof(struct sockaddr_in);
ai->ai_addr->sa_family = ai->ai_family = AF_INET;
((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
return ai;
}
int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
{
int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res) {
struct addrinfo *prev = NULL;
struct hostent *hp;
struct in_addr in = {0};
int i;
uint16_t port = 0;
if(hints && hints->ai_family != AF_INET && hints->ai_family != AF_UNSPEC)
if(hints && hints->ai_family != AF_INET && hints->ai_family != AF_UNSPEC) {
return EAI_FAMILY;
}
if (servname)
if(servname) {
port = htons(atoi(servname));
}
if (hints && hints->ai_flags & AI_PASSIVE) {
if(hints && hints->ai_flags & AI_PASSIVE) {
*res = malloc_ai(port, htonl(0x00000000));
return 0;
}
if (!hostname) {
if(!hostname) {
*res = malloc_ai(port, htonl(0x7f000001));
return 0;
}
hp = gethostbyname(hostname);
if(!hp || !hp->h_addr_list || !hp->h_addr_list[0])
if(!hp || !hp->h_addr_list || !hp->h_addr_list[0]) {
return EAI_NODATA;
}
for (i = 0; hp->h_addr_list[i]; i++) {
for(i = 0; hp->h_addr_list[i]; i++) {
*res = malloc_ai(port, ((struct in_addr *)hp->h_addr_list[i])->s_addr);
if(prev)
if(prev) {
prev->ai_next = *res;
}
prev = *res;
}

View file

@ -1,7 +1,17 @@
#ifndef _FAKE_GETADDRINFO_H
#define _FAKE_GETADDRINFO_H
#ifndef TINC_FAKE_GETADDRINFO_H
#define TINC_FAKE_GETADDRINFO_H
#include "fake-gai-errnos.h"
#ifndef EAI_NODATA
#define EAI_NODATA 1
#endif
#ifndef EAI_MEMORY
#define EAI_MEMORY 2
#endif
#ifndef EAI_FAMILY
#define EAI_FAMILY 3
#endif
#ifndef AI_PASSIVE
# define AI_PASSIVE 1
@ -20,19 +30,19 @@
#ifndef HAVE_STRUCT_ADDRINFO
struct addrinfo {
int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
int ai_family; /* PF_xxx */
int ai_socktype; /* SOCK_xxx */
int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
size_t ai_addrlen; /* length of ai_addr */
char *ai_canonname; /* canonical name for hostname */
struct sockaddr *ai_addr; /* binary address */
struct addrinfo *ai_next; /* next structure in linked list */
int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
int ai_family; /* PF_xxx */
int ai_socktype; /* SOCK_xxx */
int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
size_t ai_addrlen; /* length of ai_addr */
char *ai_canonname; /* canonical name for hostname */
struct sockaddr *ai_addr; /* binary address */
struct addrinfo *ai_next; /* next structure in linked list */
};
#endif /* !HAVE_STRUCT_ADDRINFO */
#if !HAVE_DECL_GETADDRINFO
int getaddrinfo(const char *hostname, const char *servname,
int getaddrinfo(const char *hostname, const char *servname,
const struct addrinfo *hints, struct addrinfo **res);
#endif /* !HAVE_GETADDRINFO */
@ -44,4 +54,4 @@ char *gai_strerror(int ecode);
void freeaddrinfo(struct addrinfo *ai);
#endif /* !HAVE_FREEADDRINFO */
#endif /* _FAKE_GETADDRINFO_H */
#endif

View file

@ -2,10 +2,10 @@
* fake library for ssh
*
* This file includes getnameinfo().
* These funtions are defined in rfc2133.
* These functions are defined in rfc2133.
*
* But these functions are not implemented correctly. The minimum subset
* is implemented for ssh use only. For exapmle, this routine assumes
* is implemented for ssh use only. For example, this routine assumes
* that ai_family is AF_INET. Don't use it for another purpose.
*/
@ -16,39 +16,48 @@
#if !HAVE_DECL_GETNAMEINFO
int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags)
{
int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) {
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
struct hostent *hp;
int len;
if(sa->sa_family != AF_INET)
if(sa->sa_family != AF_INET) {
return EAI_FAMILY;
}
if(serv && servlen) {
len = snprintf(serv, servlen, "%d", ntohs(sin->sin_port));
if(len < 0 || len >= servlen)
if(len < 0 || len >= servlen) {
return EAI_MEMORY;
}
}
if(!host || !hostlen)
if(!host || !hostlen) {
return 0;
}
if(flags & NI_NUMERICHOST) {
len = snprintf(host, hostlen, "%s", inet_ntoa(sin->sin_addr));
if(len < 0 || len >= hostlen)
if(len < 0 || len >= hostlen) {
return EAI_MEMORY;
}
return 0;
}
hp = gethostbyaddr((char *)&sin->sin_addr, sizeof(struct in_addr), AF_INET);
if(!hp || !hp->h_name || !hp->h_name[0])
if(!hp || !hp->h_name || !hp->h_name[0]) {
return EAI_NODATA;
}
len = snprintf(host, hostlen, "%s", hp->h_name);
if(len < 0 || len >= hostlen)
if(len < 0 || len >= hostlen) {
return EAI_MEMORY;
}
return 0;
}

View file

@ -1,8 +1,8 @@
#ifndef _FAKE_GETNAMEINFO_H
#define _FAKE_GETNAMEINFO_H
#ifndef TINC_FAKE_GETNAMEINFO_H
#define TINC_FAKE_GETNAMEINFO_H
#if !HAVE_DECL_GETNAMEINFO
int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
size_t hostlen, char *serv, size_t servlen, int flags);
#endif /* !HAVE_GETNAMEINFO */
@ -13,4 +13,4 @@ int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
# define NI_MAXHOST 1025
#endif /* !NI_MAXHOST */
#endif /* _FAKE_GETNAMEINFO_H */
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,6 @@
#ifndef TINC_GETOPT_H
#define TINC_GETOPT_H
/* Declarations for getopt.
Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc.
@ -19,115 +22,111 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef _GETOPT_H
#define _GETOPT_H 1
#ifdef __cplusplus
#ifdef cplusplus
extern "C" {
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns -1, this is the index of the first of the
non-option elements that the caller should itself scan.
When `getopt' returns -1, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
extern int opterr;
/* Set to an option character which was unrecognized. */
/* Set to an option character which was unrecognized. */
extern int optopt;
extern int optopt;
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
struct option {
#if defined (__STDC__) && __STDC__
const char *name;
const char *name;
#else
char *name;
char *name;
#endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
/* Names for the values of the `has_arg' field of `struct option'. */
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#if defined (__STDC__) && __STDC__
#ifdef __GNU_LIBRARY__
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int argc, char *const *argv, const char *shortopts);
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt(int argc, char *const *argv, const char *shortopts);
#else /* not __GNU_LIBRARY__ */
extern int getopt ();
extern int getopt();
#endif /* __GNU_LIBRARY__ */
extern int getopt_long (int argc, char *const *argv, const char *shortopts,
const struct option *longopts, int *longind);
extern int getopt_long_only (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind);
extern int getopt_long(int argc, char *const *argv, const char *shortopts,
const struct option *longopts, int *longind);
extern int getopt_long_only(int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind,
int long_only);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal(int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind,
int long_only);
#else /* not __STDC__ */
extern int getopt ();
extern int getopt_long ();
extern int getopt_long_only ();
extern int getopt();
extern int getopt_long();
extern int getopt_long_only();
extern int _getopt_internal ();
extern int _getopt_internal();
#endif /* __STDC__ */
#ifdef __cplusplus
#ifdef cplusplus
}
#endif
#endif /* _GETOPT_H */
#endif

View file

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

View file

@ -84,8 +84,9 @@ static void mst_kruskal(void) {
/* Do we have something to do at all? */
if(!edge_weight_tree->head)
if(!edge_weight_tree->head) {
return;
}
ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Running Kruskal's algorithm:");
@ -101,6 +102,7 @@ static void mst_kruskal(void) {
for(node = edge_weight_tree->head; node; node = node->next) {
e = node->data;
if(e->from->status.reachable) {
e->from->status.visited = true;
break;
@ -121,16 +123,18 @@ static void mst_kruskal(void) {
e->from->status.visited = true;
e->to->status.visited = true;
if(e->connection)
if(e->connection) {
e->connection->status.mst = true;
}
if(e->reverse->connection)
if(e->reverse->connection) {
e->reverse->connection->status.mst = true;
}
safe_edges++;
ifdebug(SCARY_THINGS) logger(LOG_DEBUG, " Adding edge %s - %s weight %d", e->from->name,
e->to->name, e->weight);
e->to->name, e->weight);
if(skipped) {
skipped = false;
@ -140,7 +144,7 @@ static void mst_kruskal(void) {
}
ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Done, counted %d nodes and %d safe edges.", nodes,
safe_edges);
safe_edges);
}
/* Implementation of a simple breadth-first search algorithm.
@ -180,22 +184,23 @@ static void sssp_bfs(void) {
/* Loop while todo_list is filled */
for(from = todo_list->head; from; from = todonext) { /* "from" is the node from which we start */
for(from = todo_list->head; from; from = todonext) { /* "from" is the node from which we start */
n = from->data;
for(to = n->edge_tree->head; to; to = to->next) { /* "to" is the edge connected to "from" */
for(to = n->edge_tree->head; to; to = to->next) { /* "to" is the edge connected to "from" */
e = to->data;
if(!e->reverse)
if(!e->reverse) {
continue;
}
/* Situation:
/
/
/
/
----->(n)---e-->(e->to)
\
\
\
\
Where e is an edge, (n) and (e->to) are nodes.
n->address is set to the e->address of the edge left of n to n.
@ -209,13 +214,15 @@ static void sssp_bfs(void) {
indirect = n->status.indirect || e->options & OPTION_INDIRECT;
if(e->to->status.visited
&& (!e->to->status.indirect || indirect))
&& (!e->to->status.indirect || indirect)) {
continue;
}
// Only update nexthop the first time we visit this node.
if(!e->to->status.visited)
if(!e->to->status.visited) {
e->to->nexthop = (n->nexthop == myself) ? e->to : n->nexthop;
}
e->to->status.visited = true;
e->to->status.indirect = indirect;
@ -223,8 +230,9 @@ static void sssp_bfs(void) {
e->to->via = indirect ? n->via : e->to;
e->to->options = e->options;
if(e->to->address.sa.sa_family == AF_UNSPEC && e->address.sa.sa_family != AF_UNKNOWN)
if(e->to->address.sa.sa_family == AF_UNSPEC && e->address.sa.sa_family != AF_UNKNOWN) {
update_node_udp(e->to, &e->address);
}
list_insert_tail(todo_list, e->to);
}
@ -246,10 +254,10 @@ static void sssp_bfs(void) {
if(n->status.reachable) {
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Node %s (%s) became reachable",
n->name, n->hostname);
n->name, n->hostname);
} else {
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Node %s (%s) became unreachable",
n->name, n->hostname);
n->name, n->hostname);
}
/* TODO: only clear status.validkey if node is unreachable? */
@ -266,9 +274,9 @@ static void sssp_bfs(void) {
n->mtuevent = NULL;
}
xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
xasprintf(&envp[1], "DEVICE=%s", device ? : "");
xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
xasprintf(&envp[0], "NETNAME=%s", netname ? netname : "");
xasprintf(&envp[1], "DEVICE=%s", device ? device : "");
xasprintf(&envp[2], "INTERFACE=%s", iface ? iface : "");
xasprintf(&envp[3], "NODE=%s", n->name);
sockaddr2str(&n->address, &address, &port);
xasprintf(&envp[4], "REMOTEADDRESS=%s", address);
@ -278,22 +286,23 @@ static void sssp_bfs(void) {
execute_script(n->status.reachable ? "host-up" : "host-down", envp);
xasprintf(&name,
n->status.reachable ? "hosts/%s-up" : "hosts/%s-down",
n->name);
n->status.reachable ? "hosts/%s-up" : "hosts/%s-down",
n->name);
execute_script(name, envp);
free(name);
free(address);
free(port);
for(i = 0; i < 7; i++)
for(i = 0; i < 7; i++) {
free(envp[i]);
}
subnet_update(n, NULL, n->status.reachable);
if(!n->status.reachable) {
update_node_udp(n, NULL);
memset(&n->status, 0, sizeof n->status);
memset(&n->status, 0, sizeof(n->status));
n->options = 0;
} else if(n->connection) {
send_ans_key(n);
@ -312,7 +321,7 @@ void graph(void) {
/* Dump nodes and edges to a graphviz file.
The file can be converted to an image with
dot -Tpng graph_filename -o image_filename.png -Gconcentrate=true
*/
@ -323,14 +332,15 @@ void dump_graph(void) {
edge_t *e;
char *filename = NULL, *tmpname = NULL;
FILE *file, *pipe = NULL;
if(!graph_changed || !get_config_string(lookup_config(config_tree, "GraphDumpFile"), &filename))
if(!graph_changed || !get_config_string(lookup_config(config_tree, "GraphDumpFile"), &filename)) {
return;
}
graph_changed = false;
ifdebug(PROTOCOL) logger(LOG_NOTICE, "Dumping graph");
if(filename[0] == '|') {
file = pipe = popen(filename + 1, "w");
} else {
@ -346,21 +356,21 @@ void dump_graph(void) {
}
fprintf(file, "digraph {\n");
/* dump all nodes first */
for(node = node_tree->head; node; node = node->next) {
n = node->data;
fprintf(file, " %s [label = \"%s\"];\n", n->name, n->name);
fprintf(file, " \"%s\" [label = \"%s\"];\n", n->name, n->name);
}
/* now dump all edges */
for(node = edge_weight_tree->head; node; node = node->next) {
e = node->data;
fprintf(file, " %s -> %s;\n", e->from->name, e->to->name);
fprintf(file, " \"%s\" -> \"%s\";\n", e->from->name, e->to->name);
}
fprintf(file, "}\n");
fprintf(file, "}\n");
if(pipe) {
pclose(pipe);
} else {
@ -368,8 +378,11 @@ void dump_graph(void) {
#ifdef HAVE_MINGW
unlink(filename);
#endif
if(rename(tmpname, filename))
if(rename(tmpname, filename)) {
logger(LOG_ERR, "Could not rename %s to %s: %s\n", tmpname, filename, strerror(errno));
}
free(tmpname);
}

View file

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

View file

@ -1,3 +1,6 @@
#ifndef TINC_HAVE_H
#define TINC_HAVE_H
/*
have.h -- include headers which are known to exist
Copyright (C) 1998-2005 Ivo Timmermans
@ -18,9 +21,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_HAVE_H__
#define __TINC_HAVE_H__
#ifdef HAVE_MINGW
#ifdef WITH_WINDOWS2000
#define WINVER Windows2000
@ -30,15 +30,19 @@
#endif
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <signal.h>
#include <errno.h>
#include <limits.h>
#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
#include <signal.h>
#ifdef HAVE_MINGW
#include <w32api.h>
@ -55,10 +59,6 @@
#include <termios.h>
#endif
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
@ -211,4 +211,4 @@
#include <linux/if_tun.h>
#endif
#endif /* __TINC_SYSTEM_H__ */
#endif

View file

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

View file

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

View file

@ -47,7 +47,7 @@ char *device = NULL;
char *iface = NULL;
static char *type = NULL;
static char ifrname[IFNAMSIZ];
static char *device_info;
static const char *device_info;
static uint64_t device_total_in = 0;
static uint64_t device_total_out = 0;
@ -56,13 +56,16 @@ static bool setup_device(void) {
struct ifreq ifr;
bool t1q = false;
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
device = xstrdup(DEFAULT_DEVICE);
}
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
#ifdef HAVE_LINUX_IF_TUN_H
if (netname != NULL)
if(netname != NULL) {
iface = xstrdup(netname);
}
#else
iface = xstrdup(strrchr(device, '/') ? strrchr(device, '/') + 1 : device);
#endif
@ -94,17 +97,22 @@ static bool setup_device(void) {
device_type = DEVICE_TYPE_TUN;
device_info = "Linux tun/tap device (tun mode)";
} else {
if (routing_mode == RMODE_ROUTER)
if(routing_mode == RMODE_ROUTER) {
overwrite_mac = true;
}
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
device_type = DEVICE_TYPE_TAP;
device_info = "Linux tun/tap device (tap mode)";
}
#ifdef IFF_ONE_QUEUE
/* Set IFF_ONE_QUEUE flag... */
if(get_config_bool(lookup_config(config_tree, "IffOneQueue"), &t1q) && t1q)
if(get_config_bool(lookup_config(config_tree, "IffOneQueue"), &t1q) && t1q) {
ifr.ifr_flags |= IFF_ONE_QUEUE;
}
#endif
if(iface) {
@ -117,6 +125,9 @@ static bool setup_device(void) {
ifrname[IFNAMSIZ - 1] = 0;
free(iface);
iface = xstrdup(ifrname);
} else if(errno == EPERM || errno == EBUSY) {
logger(LOG_ERR, "Error while trying to configure %s: %s", device, strerror(errno));
return false;
} else if(!ioctl(device_fd, (('T' << 8) | 202), &ifr)) {
logger(LOG_WARNING, "Old ioctl() request was needed for %s", device);
strncpy(ifrname, ifr.ifr_name, IFNAMSIZ);
@ -126,16 +137,19 @@ static bool setup_device(void) {
} else
#endif
{
if(routing_mode == RMODE_ROUTER)
if(routing_mode == RMODE_ROUTER) {
overwrite_mac = true;
}
device_info = "Linux ethertap device";
device_type = DEVICE_TYPE_ETHERTAP;
free(iface);
iface = xstrdup(strrchr(device, '/') ? strrchr(device, '/') + 1 : device);
}
if(overwrite_mac && !ioctl(device_fd, SIOCGIFHWADDR, &ifr))
if(overwrite_mac && !ioctl(device_fd, SIOCGIFHWADDR, &ifr)) {
memcpy(mymac.x, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
}
logger(LOG_INFO, "%s is a %s", device, device_info);
@ -152,81 +166,89 @@ static void close_device(void) {
static bool read_packet(vpn_packet_t *packet) {
int lenin;
switch(device_type) {
case DEVICE_TYPE_TUN:
lenin = read(device_fd, packet->data + 10, MTU - 10);
case DEVICE_TYPE_TUN:
lenin = read(device_fd, packet->data + 10, MTU - 10);
if(lenin <= 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s",
device_info, device, strerror(errno));
return false;
}
if(lenin <= 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s",
device_info, device, strerror(errno));
return false;
}
memset(packet->data, 0, 12);
packet->len = lenin + 10;
break;
case DEVICE_TYPE_TAP:
lenin = read(device_fd, packet->data, MTU);
memset(packet->data, 0, 12);
packet->len = lenin + 10;
break;
if(lenin <= 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s",
device_info, device, strerror(errno));
return false;
}
case DEVICE_TYPE_TAP:
lenin = read(device_fd, packet->data, MTU);
packet->len = lenin;
break;
case DEVICE_TYPE_ETHERTAP:
lenin = read(device_fd, packet->data - 2, MTU + 2);
if(lenin <= 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s",
device_info, device, strerror(errno));
return false;
}
if(lenin <= 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s",
device_info, device, strerror(errno));
return false;
}
packet->len = lenin;
break;
packet->len = lenin - 2;
break;
case DEVICE_TYPE_ETHERTAP:
lenin = read(device_fd, packet->data - 2, MTU + 2);
if(lenin <= 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s",
device_info, device, strerror(errno));
return false;
}
packet->len = lenin - 2;
break;
}
device_total_in += packet->len;
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", packet->len,
device_info);
device_info);
return true;
}
static bool write_packet(vpn_packet_t *packet) {
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
packet->len, device_info);
packet->len, device_info);
switch(device_type) {
case DEVICE_TYPE_TUN:
packet->data[10] = packet->data[11] = 0;
if(write(device_fd, packet->data + 10, packet->len - 10) < 0) {
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device,
strerror(errno));
return false;
}
break;
case DEVICE_TYPE_TAP:
if(write(device_fd, packet->data, packet->len) < 0) {
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device,
strerror(errno));
return false;
}
break;
case DEVICE_TYPE_ETHERTAP:
memcpy(packet->data - 2, &packet->len, 2);
case DEVICE_TYPE_TUN:
packet->data[10] = packet->data[11] = 0;
if(write(device_fd, packet->data - 2, packet->len + 2) < 0) {
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device,
strerror(errno));
return false;
}
break;
if(write(device_fd, packet->data + 10, packet->len - 10) < 0) {
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device,
strerror(errno));
return false;
}
break;
case DEVICE_TYPE_TAP:
if(write(device_fd, packet->data, packet->len) < 0) {
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device,
strerror(errno));
return false;
}
break;
case DEVICE_TYPE_ETHERTAP:
memcpy(packet->data - 2, &packet->len, 2);
if(write(device_fd, packet->data - 2, packet->len + 2) < 0) {
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device,
strerror(errno));
return false;
}
break;
}
device_total_out += packet->len;

View file

@ -43,8 +43,9 @@ list_node_t *list_alloc_node(void) {
}
void list_free_node(list_t *list, list_node_t *node) {
if(node->data && list->delete)
if(node->data && list->delete) {
list->delete(node->data);
}
free(node);
}
@ -61,10 +62,11 @@ list_node_t *list_insert_head(list_t *list, void *data) {
node->next = list->head;
list->head = node;
if(node->next)
if(node->next) {
node->next->prev = node;
else
} else {
list->tail = node;
}
list->count++;
@ -81,10 +83,11 @@ list_node_t *list_insert_tail(list_t *list, void *data) {
node->prev = list->tail;
list->tail = node;
if(node->prev)
if(node->prev) {
node->prev->next = node;
else
} else {
list->head = node;
}
list->count++;
@ -92,15 +95,17 @@ list_node_t *list_insert_tail(list_t *list, void *data) {
}
void list_unlink_node(list_t *list, list_node_t *node) {
if(node->prev)
if(node->prev) {
node->prev->next = node->next;
else
} else {
list->head = node->next;
}
if(node->next)
if(node->next) {
node->next->prev = node->prev;
else
} else {
list->tail = node->prev;
}
list->count--;
}
@ -121,17 +126,19 @@ void list_delete_tail(list_t *list) {
/* Head/tail lookup */
void *list_get_head(list_t *list) {
if(list->head)
if(list->head) {
return list->head->data;
else
} else {
return NULL;
}
}
void *list_get_tail(list_t *list) {
if(list->tail)
if(list->tail) {
return list->tail->data;
else
} else {
return NULL;
}
}
/* Fast list deletion */
@ -163,7 +170,9 @@ void list_foreach(list_t *list, list_action_t action) {
for(node = list->head; node; node = next) {
next = node->next;
if(node->data)
if(node->data) {
action(node->data);
}
}
}

View file

@ -1,3 +1,6 @@
#ifndef TINC_LIST_H
#define TINC_LIST_H
/*
list.h -- header file for list.c
Copyright (C) 2000-2005 Ivo Timmermans
@ -18,9 +21,6 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_LIST_H__
#define __TINC_LIST_H__
typedef struct list_node_t {
struct list_node_t *prev;
struct list_node_t *next;
@ -45,34 +45,34 @@ typedef struct list_t {
/* (De)constructors */
extern list_t *list_alloc(list_action_t) __attribute__ ((__malloc__));
extern void list_free(list_t *);
extern list_t *list_alloc(list_action_t) __attribute__((__malloc__));
extern void list_free(list_t *list);
extern list_node_t *list_alloc_node(void);
extern void list_free_node(list_t *, list_node_t *);
extern void list_free_node(list_t *list, list_node_t *node);
/* Insertion and deletion */
extern list_node_t *list_insert_head(list_t *, void *);
extern list_node_t *list_insert_tail(list_t *, void *);
extern list_node_t *list_insert_head(list_t *list, void *data);
extern list_node_t *list_insert_tail(list_t *list, void *data);
extern void list_unlink_node(list_t *, list_node_t *);
extern void list_delete_node(list_t *, list_node_t *);
extern void list_unlink_node(list_t *list, list_node_t *node);
extern void list_delete_node(list_t *list, list_node_t *node);
extern void list_delete_head(list_t *);
extern void list_delete_tail(list_t *);
extern void list_delete_head(list_t *list);
extern void list_delete_tail(list_t *list);
/* Head/tail lookup */
extern void *list_get_head(list_t *);
extern void *list_get_tail(list_t *);
extern void *list_get_head(list_t *list);
extern void *list_get_tail(list_t *list);
/* Fast list deletion */
extern void list_delete_list(list_t *);
extern void list_delete_list(list_t *list);
/* Traversing */
extern void list_foreach(list_t *, list_action_t);
extern void list_foreach_node(list_t *, list_action_node_t);
extern void list_foreach(list_t *list, list_action_t action);
extern void list_foreach_node(list_t *list, list_action_node_t action);
#endif /* __TINC_LIST_H__ */
#endif

View file

@ -1,6 +1,6 @@
/*
logger.c -- logging code
Copyright (C) 2004-2006 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2004-2016 Guus Sliepen <guus@tinc-vpn.org>
2004-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify
@ -36,48 +36,58 @@ static const char *logident = NULL;
void openlogger(const char *ident, logmode_t mode) {
logident = ident;
logmode = mode;
switch(mode) {
case LOGMODE_STDERR:
logpid = getpid();
break;
case LOGMODE_FILE:
logpid = getpid();
logfile = fopen(logfilename, "a");
if(!logfile) {
fprintf(stderr, "Could not open log file %s: %s\n", logfilename, strerror(errno));
logmode = LOGMODE_NULL;
}
break;
case LOGMODE_SYSLOG:
case LOGMODE_STDERR:
logpid = getpid();
break;
case LOGMODE_FILE:
logpid = getpid();
logfile = fopen(logfilename, "a");
if(!logfile) {
fprintf(stderr, "Could not open log file %s: %s\n", logfilename, strerror(errno));
logmode = LOGMODE_NULL;
}
break;
case LOGMODE_SYSLOG:
#ifdef HAVE_MINGW
loghandle = RegisterEventSource(NULL, logident);
if(!loghandle) {
fprintf(stderr, "Could not open log handle!");
logmode = LOGMODE_NULL;
}
break;
loghandle = RegisterEventSource(NULL, logident);
if(!loghandle) {
fprintf(stderr, "Could not open log handle!");
logmode = LOGMODE_NULL;
}
break;
#else
#ifdef HAVE_SYSLOG_H
openlog(logident, LOG_CONS | LOG_PID, LOG_DAEMON);
break;
openlog(logident, LOG_CONS | LOG_PID, LOG_DAEMON);
break;
#endif
#endif
case LOGMODE_NULL:
break;
case LOGMODE_NULL:
break;
}
}
void reopenlogger() {
if(logmode != LOGMODE_FILE)
if(logmode != LOGMODE_FILE) {
return;
}
fflush(logfile);
FILE *newfile = fopen(logfilename, "a");
if(!newfile) {
logger(LOG_ERR, "Unable to reopen log file %s: %s", logfilename, strerror(errno));
return;
}
fclose(logfile);
logfile = newfile;
}
@ -90,43 +100,48 @@ void logger(int priority, const char *format, ...) {
va_start(ap, format);
switch(logmode) {
case LOGMODE_STDERR:
vfprintf(stderr, format, ap);
fprintf(stderr, "\n");
fflush(stderr);
break;
case LOGMODE_FILE:
now = time(NULL);
strftime(timestr, sizeof timestr, "%Y-%m-%d %H:%M:%S", localtime(&now));
fprintf(logfile, "%s %s[%ld]: ", timestr, logident, (long)logpid);
vfprintf(logfile, format, ap);
fprintf(logfile, "\n");
fflush(logfile);
break;
case LOGMODE_SYSLOG:
case LOGMODE_STDERR:
vfprintf(stderr, format, ap);
fprintf(stderr, "\n");
fflush(stderr);
break;
case LOGMODE_FILE:
now = time(NULL);
strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", localtime(&now));
fprintf(logfile, "%s %s[%ld]: ", timestr, logident, (long)logpid);
vfprintf(logfile, format, ap);
fprintf(logfile, "\n");
fflush(logfile);
break;
case LOGMODE_SYSLOG:
#ifdef HAVE_MINGW
{
char message[4096];
const char *messages[] = {message};
vsnprintf(message, sizeof(message), format, ap);
ReportEvent(loghandle, priority, 0, 0, NULL, 1, 0, messages, NULL);
}
{
char message[4096];
const char *messages[] = {message};
vsnprintf(message, sizeof(message), format, ap);
message[sizeof(message) - 1] = 0;
ReportEvent(loghandle, priority, 0, 0, NULL, 1, 0, messages, NULL);
}
#else
#ifdef HAVE_SYSLOG_H
#ifdef HAVE_VSYSLOG
vsyslog(priority, format, ap);
vsyslog(priority, format, ap);
#else
{
char message[4096];
vsnprintf(message, sizeof(message), format, ap);
syslog(priority, "%s", message);
}
{
char message[4096];
vsnprintf(message, sizeof(message), format, ap);
syslog(priority, "%s", message);
}
#endif
break;
break;
#endif
#endif
case LOGMODE_NULL:
break;
case LOGMODE_NULL:
break;
}
va_end(ap);
@ -134,22 +149,23 @@ void logger(int priority, const char *format, ...) {
void closelogger(void) {
switch(logmode) {
case LOGMODE_FILE:
fclose(logfile);
break;
case LOGMODE_SYSLOG:
case LOGMODE_FILE:
fclose(logfile);
break;
case LOGMODE_SYSLOG:
#ifdef HAVE_MINGW
DeregisterEventSource(loghandle);
break;
DeregisterEventSource(loghandle);
break;
#else
#ifdef HAVE_SYSLOG_H
closelog();
break;
closelog();
break;
#endif
#endif
case LOGMODE_NULL:
case LOGMODE_STDERR:
break;
break;
case LOGMODE_NULL:
case LOGMODE_STDERR:
break;
}
}

View file

@ -1,17 +1,36 @@
#ifndef __TINC_LOGGER_H__
#define __TINC_LOGGER_H__
#ifndef TINC_LOGGER_H
#define TINC_LOGGER_H
/*
logger.h -- header file for logger.c
Copyright (C) 2003-2016 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
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.
*/
typedef enum debug_t {
DEBUG_NOTHING = 0, /* Quiet mode, only show starting/stopping of the daemon */
DEBUG_NOTHING = 0, /* Quiet mode, only show starting/stopping of the daemon */
DEBUG_ALWAYS = 0,
DEBUG_CONNECTIONS = 1, /* Show (dis)connects of other tinc daemons via TCP */
DEBUG_ERROR = 2, /* Show error messages received from other hosts */
DEBUG_STATUS = 2, /* Show status messages received from other hosts */
DEBUG_PROTOCOL = 3, /* Show the requests that are sent/received */
DEBUG_META = 4, /* Show contents of every request that is sent/received */
DEBUG_TRAFFIC = 5, /* Show network traffic information */
DEBUG_PACKET = 6, /* Show contents of each packet that is being sent/received */
DEBUG_SCARY_THINGS = 10 /* You have been warned */
DEBUG_CONNECTIONS = 1, /* Show (dis)connects of other tinc daemons via TCP */
DEBUG_ERROR = 2, /* Show error messages received from other hosts */
DEBUG_STATUS = 2, /* Show status messages received from other hosts */
DEBUG_PROTOCOL = 3, /* Show the requests that are sent/received */
DEBUG_META = 4, /* Show contents of every request that is sent/received */
DEBUG_TRAFFIC = 5, /* Show network traffic information */
DEBUG_PACKET = 6, /* Show contents of each packet that is being sent/received */
DEBUG_SCARY_THINGS = 10, /* You have been warned */
} debug_t;
typedef enum logmode_t {
@ -46,11 +65,11 @@ enum {
#endif
extern debug_t debug_level;
extern void openlogger(const char *, logmode_t);
extern void openlogger(const char *ident, logmode_t mode);
extern void reopenlogger(void);
extern void logger(int, const char *, ...) __attribute__ ((__format__(printf, 2, 3)));
extern void logger(int priority, const char *format, ...) __attribute__((__format__(printf, 2, 3)));
extern void closelogger(void);
#define ifdebug(l) if(debug_level >= DEBUG_##l)
#endif /* __TINC_LOGGER_H__ */
#endif

View file

@ -1,6 +1,6 @@
/*
meta.c -- handle the meta communication
Copyright (C) 2000-2015 Guus Sliepen <guus@tinc-vpn.org>,
Copyright (C) 2000-2017 Guus Sliepen <guus@tinc-vpn.org>,
2000-2005 Ivo Timmermans
2006 Scott Lamb <slamb@slamb.org>
@ -38,16 +38,12 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
int outlen;
int result;
if(!c) {
logger(LOG_ERR, "send_meta() called with NULL pointer!");
abort();
}
ifdebug(META) logger(LOG_DEBUG, "Sending %d bytes of metadata to %s (%s)", length,
c->name, c->hostname);
c->name, c->hostname);
if(!c->outbuflen)
if(!c->outbuflen) {
c->last_flushed_time = now;
}
/* Find room in connection's buffer */
if(length + c->outbuflen > c->outbufsize) {
@ -62,16 +58,26 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
/* Add our data to buffer */
if(c->status.encryptout) {
/* Check encryption limits */
if((uint64_t)length > c->outbudget) {
ifdebug(META) logger(LOG_ERR, "Byte limit exceeded for encryption to %s (%s)", c->name, c->hostname);
return false;
} else {
c->outbudget -= length;
}
result = EVP_EncryptUpdate(c->outctx, (unsigned char *)c->outbuf + c->outbufstart + c->outbuflen,
&outlen, (unsigned char *)buffer, length);
&outlen, (unsigned char *)buffer, length);
if(!result || outlen < length) {
logger(LOG_ERR, "Error while encrypting metadata to %s (%s): %s",
c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL));
c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL));
return false;
} else if(outlen > length) {
logger(LOG_EMERG, "Encrypted data too long! Heap corrupted!");
abort();
}
c->outbuflen += outlen;
} else {
memcpy(c->outbuf + c->outbufstart + c->outbuflen, buffer, length);
@ -83,25 +89,26 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
bool flush_meta(connection_t *c) {
int result;
ifdebug(META) logger(LOG_DEBUG, "Flushing %d bytes to %s (%s)",
c->outbuflen, c->name, c->hostname);
c->outbuflen, c->name, c->hostname);
while(c->outbuflen) {
result = send(c->socket, c->outbuf + c->outbufstart, c->outbuflen, 0);
if(result <= 0) {
if(!errno || errno == EPIPE) {
ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Connection closed by %s (%s)",
c->name, c->hostname);
c->name, c->hostname);
} else if(errno == EINTR) {
continue;
} else if(sockwouldblock(sockerrno)) {
ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Flushing %d bytes to %s (%s) would block",
c->outbuflen, c->name, c->hostname);
ifdebug(META) logger(LOG_DEBUG, "Flushing %d bytes to %s (%s) would block",
c->outbuflen, c->name, c->hostname);
return true;
} else {
logger(LOG_ERR, "Flushing meta data to %s (%s) failed: %s", c->name,
c->hostname, sockstrerror(sockerrno));
c->hostname, sockstrerror(sockerrno));
}
return false;
@ -122,8 +129,9 @@ void broadcast_meta(connection_t *from, const char *buffer, int length) {
for(node = connection_tree->head; node; node = node->next) {
c = node->data;
if(c != from && c->status.active)
if(c != from && c->status.active) {
send_meta(c, buffer, length);
}
}
}
@ -147,12 +155,12 @@ bool receive_meta(connection_t *c) {
if(lenin <= 0) {
if(!lenin || !errno) {
ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Connection closed by %s (%s)",
c->name, c->hostname);
} else if(sockwouldblock(sockerrno))
c->name, c->hostname);
} else if(sockwouldblock(sockerrno)) {
return true;
else
} else
logger(LOG_ERR, "Metadata socket read error for %s (%s): %s",
c->name, c->hostname, sockstrerror(sockerrno));
c->name, c->hostname, sockstrerror(sockerrno));
return false;
}
@ -166,21 +174,34 @@ bool receive_meta(connection_t *c) {
/* Is it proxy metadata? */
if(c->allow_request == PROXY) {
reqlen = receive_proxy_meta(c, oldlen, lenin);
if(reqlen < 0)
reqlen = receive_proxy_meta(c);
if(reqlen < 0) {
return false;
}
goto consume;
}
/* Decrypt */
if(c->status.decryptin && !decrypted) {
/* Check decryption limits */
if((uint64_t)lenin > c->inbudget) {
ifdebug(META) logger(LOG_ERR, "Byte limit exceeded for decryption from %s (%s)", c->name, c->hostname);
return false;
} else {
c->inbudget -= lenin;
}
result = EVP_DecryptUpdate(c->inctx, (unsigned char *)inbuf, &lenout, (unsigned char *)c->buffer + oldlen, lenin);
if(!result || lenout != lenin) {
logger(LOG_ERR, "Error while decrypting metadata from %s (%s): %s",
c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL));
c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL));
return false;
}
memcpy(c->buffer + oldlen, inbuf, lenin);
decrypted = true;
}
@ -203,17 +224,19 @@ bool receive_meta(connection_t *c) {
for(i = oldlen; i < c->buflen; i++) {
if(c->buffer[i] == '\n') {
c->buffer[i] = '\0'; /* replace end-of-line by end-of-string so we can use sscanf */
c->buffer[i] = '\0'; /* replace end-of-line by end-of-string so we can use sscanf */
c->reqlen = reqlen = i + 1;
break;
}
}
if(reqlen && !receive_request(c))
if(reqlen && !receive_request(c)) {
return false;
}
}
consume:
if(reqlen) {
c->buflen -= reqlen;
lenin -= reqlen - oldlen;
@ -227,7 +250,7 @@ consume:
if(c->buflen >= MAXBUFSIZE) {
logger(LOG_ERR, "Metadata read buffer overflow for %s (%s)",
c->name, c->hostname);
c->name, c->hostname);
return false;
}

View file

@ -1,3 +1,6 @@
#ifndef TINC_META_H
#define TINC_META_H
/*
meta.h -- header for meta.c
Copyright (C) 2000-2006 Guus Sliepen <guus@tinc-vpn.org>,
@ -18,14 +21,11 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_META_H__
#define __TINC_META_H__
#include "connection.h"
extern bool send_meta(struct connection_t *, const char *, int);
extern void broadcast_meta(struct connection_t *, const char *, int);
extern bool flush_meta(struct connection_t *);
extern bool receive_meta(struct connection_t *);
extern bool send_meta(struct connection_t *c, const char *buffer, int length);
extern void broadcast_meta(struct connection_t *c, const char *buffer, int length);
extern bool flush_meta(struct connection_t *c);
extern bool receive_meta(struct connection_t *c);
#endif /* __TINC_META_H__ */
#endif

View file

@ -37,7 +37,7 @@
//=============
#define TAP_CONTROL_CODE(request,method) \
CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED)
#define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED)

View file

@ -37,7 +37,7 @@ int device_fd = -1;
static HANDLE device_handle = INVALID_HANDLE_VALUE;
char *device = NULL;
char *iface = NULL;
static char *device_info = NULL;
static const char *device_info = "Windows tap device";
static uint64_t device_total_in = 0;
static uint64_t device_total_out = 0;
@ -66,17 +66,21 @@ static DWORD WINAPI tapreader(void *bla) {
if(!status) {
if(GetLastError() == ERROR_IO_PENDING) {
WaitForSingleObject(r_overlapped.hEvent, INFINITE);
if(!GetOverlappedResult(device_handle, &r_overlapped, &len, FALSE))
if(!GetOverlappedResult(device_handle, &r_overlapped, &len, FALSE)) {
continue;
}
} else {
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno));
device, strerror(errno));
errors++;
if(errors >= 10) {
EnterCriticalSection(&mutex);
running = false;
LeaveCriticalSection(&mutex);
}
usleep(1000000);
continue;
}
@ -113,8 +117,9 @@ static bool setup_device(void) {
get_config_string(lookup_config(config_tree, "Device"), &device);
get_config_string(lookup_config(config_tree, "Interface"), &iface);
if(device && iface)
if(device && iface) {
logger(LOG_WARNING, "Warning: both Device and Interface specified, results may not be as expected");
}
/* Open registry and look for network adapters */
@ -123,44 +128,51 @@ static bool setup_device(void) {
return false;
}
for (i = 0; ; i++) {
for(i = 0; ; i++) {
len = sizeof(adapterid);
if(RegEnumKeyEx(key, i, adapterid, &len, 0, 0, 0, NULL))
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))
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2)) {
continue;
}
len = sizeof(adaptername);
err = RegQueryValueEx(key2, "Name", 0, 0, (LPBYTE)adaptername, &len);
RegCloseKey(key2);
if(err)
if(err) {
continue;
}
if(device) {
if(!strcmp(device, adapterid)) {
found = true;
break;
} else
} else {
continue;
}
}
if(iface) {
if(!strcmp(iface, adaptername)) {
found = true;
break;
} else
} else {
continue;
}
}
snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
if(device_handle != INVALID_HANDLE_VALUE) {
found = true;
break;
@ -174,11 +186,13 @@ static bool setup_device(void) {
return false;
}
if(!device)
if(!device) {
device = xstrdup(adapterid);
}
if(!iface)
if(!iface) {
iface = xstrdup(adaptername);
}
/* Try to open the corresponding tap device */
@ -186,7 +200,7 @@ static bool setup_device(void) {
snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, device);
device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
}
if(device_handle == INVALID_HANDLE_VALUE) {
logger(LOG_ERR, "%s (%s) is not a usable Windows tap device: %s", device, iface, winerror(GetLastError()));
return false;
@ -222,8 +236,6 @@ static bool setup_device(void) {
status = true;
DeviceIoControl(device_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, sizeof(status), &status, sizeof(status), &len, NULL);
device_info = "Windows tap device";
logger(LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
return true;
@ -245,18 +257,20 @@ static bool write_packet(vpn_packet_t *packet) {
static vpn_packet_t queue;
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
packet->len, device_info);
packet->len, device_info);
/* Check if there is something in progress */
if(queue.len) {
DWORD size;
BOOL success = GetOverlappedResult(device_handle, &w_overlapped, &size, FALSE);
if(success) {
ResetEvent(&w_overlapped);
queue.len = 0;
} else {
int err = GetLastError();
if(err != ERROR_IO_INCOMPLETE) {
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Error completing previously queued write: %s", winerror(err));
ResetEvent(&w_overlapped);
@ -275,10 +289,12 @@ static bool write_packet(vpn_packet_t *packet) {
if(!WriteFile(device_handle, queue.data, packet->len, &lenout, &w_overlapped)) {
int err = GetLastError();
if(err != ERROR_IO_PENDING) {
logger(LOG_ERR, "Error while writing to %s %s: %s", device_info, device, winerror(err));
return false;
}
// Write is being done asynchronously.
queue.len = packet->len;
} else {

View file

@ -29,7 +29,7 @@
#include "route.h"
#include "xalloc.h"
static char *device_info;
static const char *device_info = "multicast socket";
static uint64_t device_total_in = 0;
static uint64_t device_total_out = 0;
@ -43,8 +43,6 @@ static bool setup_device(void) {
char *space;
int ttl = 1;
device_info = "multicast socket";
get_config_string(lookup_config(config_tree, "Interface"), &iface);
if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
@ -54,6 +52,7 @@ static bool setup_device(void) {
host = xstrdup(device);
space = strchr(host, ' ');
if(!space) {
logger(LOG_ERR, "Port number required for %s", device_info);
free(host);
@ -70,10 +69,14 @@ static bool setup_device(void) {
}
ai = str2addrinfo(host, port, SOCK_DGRAM);
if(!ai)
if(!ai) {
free(host);
return false;
}
device_fd = socket(ai->ai_family, SOCK_DGRAM, IPPROTO_UDP);
if(device_fd < 0) {
logger(LOG_ERR, "Creating socket failed: %s", sockstrerror(sockerrno));
free(host);
@ -85,7 +88,7 @@ static bool setup_device(void) {
#endif
static const int one = 1;
setsockopt(device_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof one);
setsockopt(device_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one));
if(bind(device_fd, ai->ai_addr, ai->ai_addrlen)) {
closesocket(device_fd);
@ -96,54 +99,62 @@ static bool setup_device(void) {
switch(ai->ai_family) {
#ifdef IP_ADD_MEMBERSHIP
case AF_INET: {
struct ip_mreq mreq;
struct sockaddr_in in;
memcpy(&in, ai->ai_addr, sizeof in);
mreq.imr_multiaddr.s_addr = in.sin_addr.s_addr;
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if(setsockopt(device_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof mreq)) {
logger(LOG_ERR, "Cannot join multicast group %s %s: %s", host, port, sockstrerror(sockerrno));
closesocket(device_fd);
free(host);
return false;
}
#ifdef IP_MULTICAST_LOOP
setsockopt(device_fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const void *)&one, sizeof one);
#endif
#ifdef IP_MULTICAST_TTL
setsockopt(device_fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&ttl, sizeof ttl);
#endif
} break;
#endif
#ifdef IPV6_JOIN_GROUP
case AF_INET6: {
struct ipv6_mreq mreq;
struct sockaddr_in6 in6;
memcpy(&in6, ai->ai_addr, sizeof in6);
memcpy(&mreq.ipv6mr_multiaddr, &in6.sin6_addr, sizeof mreq.ipv6mr_multiaddr);
mreq.ipv6mr_interface = in6.sin6_scope_id;
if(setsockopt(device_fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, (void *)&mreq, sizeof mreq)) {
logger(LOG_ERR, "Cannot join multicast group %s %s: %s", host, port, sockstrerror(sockerrno));
closesocket(device_fd);
free(host);
return false;
}
#ifdef IPV6_MULTICAST_LOOP
setsockopt(device_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (const void *)&one, sizeof one);
#endif
#ifdef IPV6_MULTICAST_HOPS
setsockopt(device_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (void *)&ttl, sizeof ttl);
#endif
} break;
#endif
default:
logger(LOG_ERR, "Multicast for address family %x unsupported", ai->ai_family);
case AF_INET: {
struct ip_mreq mreq;
struct sockaddr_in in;
memcpy(&in, ai->ai_addr, sizeof(in));
mreq.imr_multiaddr.s_addr = in.sin_addr.s_addr;
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if(setsockopt(device_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof(mreq))) {
logger(LOG_ERR, "Cannot join multicast group %s %s: %s", host, port, sockstrerror(sockerrno));
closesocket(device_fd);
free(host);
return false;
}
#ifdef IP_MULTICAST_LOOP
setsockopt(device_fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const void *)&one, sizeof(one));
#endif
#ifdef IP_MULTICAST_TTL
setsockopt(device_fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&ttl, sizeof(ttl));
#endif
}
break;
#endif
#ifdef IPV6_JOIN_GROUP
case AF_INET6: {
struct ipv6_mreq mreq;
struct sockaddr_in6 in6;
memcpy(&in6, ai->ai_addr, sizeof(in6));
memcpy(&mreq.ipv6mr_multiaddr, &in6.sin6_addr, sizeof(mreq.ipv6mr_multiaddr));
mreq.ipv6mr_interface = in6.sin6_scope_id;
if(setsockopt(device_fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, (void *)&mreq, sizeof(mreq))) {
logger(LOG_ERR, "Cannot join multicast group %s %s: %s", host, port, sockstrerror(sockerrno));
closesocket(device_fd);
free(host);
return false;
}
#ifdef IPV6_MULTICAST_LOOP
setsockopt(device_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (const void *)&one, sizeof(one));
#endif
#ifdef IPV6_MULTICAST_HOPS
setsockopt(device_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (void *)&ttl, sizeof(ttl));
#endif
}
break;
#endif
default:
logger(LOG_ERR, "Multicast for address family %x unsupported", ai->ai_family);
closesocket(device_fd);
free(host);
return false;
}
free(host);
@ -158,8 +169,9 @@ static void close_device(void) {
free(device);
free(iface);
if(ai)
if(ai) {
freeaddrinfo(ai);
}
}
static bool read_packet(vpn_packet_t *packet) {
@ -167,11 +179,11 @@ static bool read_packet(vpn_packet_t *packet) {
if((lenin = recv(device_fd, (void *)packet->data, MTU, 0)) <= 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno));
device, strerror(errno));
return false;
}
if(!memcmp(&ignore_src, packet->data + 6, sizeof ignore_src)) {
if(!memcmp(&ignore_src, packet->data + 6, sizeof(ignore_src))) {
ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Ignoring loopback packet of %d bytes from %s", lenin, device_info);
packet->len = 0;
return true;
@ -182,24 +194,24 @@ static bool read_packet(vpn_packet_t *packet) {
device_total_in += packet->len;
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", packet->len,
device_info);
device_info);
return true;
}
static bool write_packet(vpn_packet_t *packet) {
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
packet->len, device_info);
packet->len, device_info);
if(sendto(device_fd, (void *)packet->data, packet->len, 0, ai->ai_addr, ai->ai_addrlen) < 0) {
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device,
strerror(errno));
strerror(errno));
return false;
}
device_total_out += packet->len;
memcpy(&ignore_src, packet->data + 6, sizeof ignore_src);
memcpy(&ignore_src, packet->data + 6, sizeof(ignore_src));
return true;
}

198
src/net.c
View file

@ -3,7 +3,7 @@
Copyright (C) 1998-2005 Ivo Timmermans,
2000-2015 Guus Sliepen <guus@tinc-vpn.org>
2006 Scott Lamb <slamb@slamb.org>
2011 Loïc Grenié <loic.grenie@gmail.com>
2011 Loïc Grenié <loic.grenie@gmail.com>
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
@ -70,21 +70,26 @@ static void purge(void) {
if(!n->status.reachable) {
ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Purging node %s (%s)", n->name,
n->hostname);
n->hostname);
for(snode = n->subnet_tree->head; snode; snode = snext) {
snext = snode->next;
s = snode->data;
send_del_subnet(everyone, s);
if(!strictsubnets)
if(!strictsubnets) {
subnet_del(n, s);
}
}
for(enode = n->edge_tree->head; enode; enode = enext) {
enext = enode->next;
e = enode->data;
if(!tunnelserver)
if(!tunnelserver) {
send_del_edge(everyone, e);
}
edge_del(e);
}
}
@ -101,13 +106,16 @@ static void purge(void) {
enext = enode->next;
e = enode->data;
if(e->to == n)
if(e->to == n) {
break;
}
}
if(!enode && (!strictsubnets || !n->subnet_tree->head))
/* in strictsubnets mode do not delete nodes with subnets */
{
node_del(n);
}
}
}
}
@ -130,34 +138,64 @@ static int build_fdset(fd_set *readset, fd_set *writeset) {
if(c->status.remove) {
connection_del(c);
if(!connection_tree->head)
if(!connection_tree->head) {
purge();
}
} else {
FD_SET(c->socket, readset);
if(c->outbuflen > 0 || c->status.connecting)
if(c->outbuflen > 0 || c->status.connecting) {
FD_SET(c->socket, writeset);
if(c->socket > max)
}
if(c->socket > max) {
max = c->socket;
}
}
}
for(i = 0; i < listen_sockets; i++) {
FD_SET(listen_socket[i].tcp, readset);
if(listen_socket[i].tcp > max)
if(listen_socket[i].tcp > max) {
max = listen_socket[i].tcp;
}
FD_SET(listen_socket[i].udp, readset);
if(listen_socket[i].udp > max)
if(listen_socket[i].udp > max) {
max = listen_socket[i].udp;
}
}
if(device_fd >= 0)
if(device_fd >= 0) {
FD_SET(device_fd, readset);
if(device_fd > max)
}
if(device_fd > max) {
max = device_fd;
}
return max;
}
/* Put a misbehaving connection in the tarpit */
void tarpit(int fd) {
static int pits[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
static int next_pit = 0;
if(pits[next_pit] != -1) {
closesocket(pits[next_pit]);
}
pits[next_pit++] = fd;
if(next_pit >= (int)(sizeof pits / sizeof pits[0])) {
next_pit = 0;
}
}
/*
Terminate a connection:
- Close the socket
@ -166,20 +204,27 @@ static int build_fdset(fd_set *readset, fd_set *writeset) {
- Deactivate the host
*/
void terminate_connection(connection_t *c, bool report) {
if(c->status.remove)
if(c->status.remove) {
return;
}
ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Closing connection with %s (%s)",
c->name, c->hostname);
c->name, c->hostname);
c->status.remove = true;
c->status.active = false;
if(c->node)
if(c->node) {
c->node->connection = NULL;
}
if(c->socket)
closesocket(c->socket);
if(c->socket) {
if(c->status.tarpit) {
tarpit(c->socket);
} else {
closesocket(c->socket);
}
}
if(c->edge) {
if(!c->node) {
@ -188,10 +233,12 @@ void terminate_connection(connection_t *c, bool report) {
abort();
}
if(report && !tunnelserver)
if(report && !tunnelserver) {
send_del_edge(everyone, c->edge);
}
edge_del(c->edge);
c->edge = NULL;
/* Run MST and SSSP algorithms */
@ -202,9 +249,12 @@ void terminate_connection(connection_t *c, bool report) {
if(report && !c->node->status.reachable) {
edge_t *e;
e = lookup_edge(c->node, myself);
if(e) {
if(!tunnelserver)
if(!tunnelserver) {
send_del_edge(everyone, e);
}
edge_del(e);
}
}
@ -216,13 +266,14 @@ void terminate_connection(connection_t *c, bool report) {
if(c->outgoing) {
c->status.remove = false;
do_outgoing_connection(c);
do_outgoing_connection(c);
}
#ifndef HAVE_MINGW
/* Clean up dead proxy processes */
while(waitpid(-1, NULL, WNOHANG) > 0);
#endif
}
@ -246,7 +297,7 @@ static void check_dead_connections(void) {
if(c->status.active) {
if(c->status.pinged) {
ifdebug(CONNECTIONS) logger(LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds",
c->name, c->hostname, (long)now - c->last_ping_time);
c->name, c->hostname, (long)(now - c->last_ping_time));
c->status.timeout = true;
terminate_connection(c, true);
} else if(c->last_ping_time + pinginterval <= now) {
@ -255,17 +306,20 @@ static void check_dead_connections(void) {
} else {
if(c->status.remove) {
logger(LOG_WARNING, "Old connection_t for %s (%s) status %04x still lingering, deleting...",
c->name, c->hostname, bitfield_to_int(&c->status, sizeof c->status));
c->name, c->hostname, bitfield_to_int(&c->status, sizeof(c->status)));
connection_del(c);
continue;
}
ifdebug(CONNECTIONS) logger(LOG_WARNING, "Timeout from %s (%s) during authentication",
c->name, c->hostname);
c->name, c->hostname);
if(c->status.connecting) {
c->status.connecting = false;
closesocket(c->socket);
do_outgoing_connection(c);
} else {
c->status.tarpit = true;
terminate_connection(c, false);
}
}
@ -274,8 +328,8 @@ static void check_dead_connections(void) {
if(c->outbuflen > 0 && c->last_flushed_time + pingtimeout <= now) {
if(c->status.active) {
ifdebug(CONNECTIONS) logger(LOG_INFO,
"%s (%s) could not flush for %ld seconds (%d bytes remaining)",
c->name, c->hostname, (long)now - c->last_flushed_time, c->outbuflen);
"%s (%s) could not flush for %ld seconds (%d bytes remaining)",
c->name, c->hostname, (long)(now - c->last_flushed_time), c->outbuflen);
c->status.timeout = true;
terminate_connection(c, true);
}
@ -287,7 +341,7 @@ static void check_dead_connections(void) {
check all connections to see if anything
happened on their sockets
*/
static void check_network_activity(fd_set * readset, fd_set * writeset) {
static void check_network_activity(fd_set *readset, fd_set *writeset) {
connection_t *c;
avl_node_t *node;
int result, i;
@ -306,6 +360,7 @@ static void check_network_activity(fd_set * readset, fd_set * writeset) {
} else {
usleep(errors * 50000);
errors++;
if(errors > 10) {
logger(LOG_ERR, "Too many errors from %s, exiting!", device);
running = false;
@ -317,20 +372,21 @@ static void check_network_activity(fd_set * readset, fd_set * writeset) {
for(node = connection_tree->head; node; node = node->next) {
c = node->data;
if(c->status.remove)
if(c->status.remove) {
continue;
}
if(FD_ISSET(c->socket, writeset)) {
if(c->status.connecting) {
c->status.connecting = false;
getsockopt(c->socket, SOL_SOCKET, SO_ERROR, (void *)&result, &len);
if(!result)
if(!result) {
finish_connecting(c);
else {
} else {
ifdebug(CONNECTIONS) logger(LOG_DEBUG,
"Error while connecting to %s (%s): %s",
c->name, c->hostname, sockstrerror(result));
"Error while connecting to %s (%s): %s",
c->name, c->hostname, sockstrerror(result));
closesocket(c->socket);
do_outgoing_connection(c);
continue;
@ -345,6 +401,7 @@ static void check_network_activity(fd_set * readset, fd_set * writeset) {
if(FD_ISSET(c->socket, readset)) {
if(!receive_meta(c)) {
c->status.tarpit = true;
terminate_connection(c, c->status.active);
continue;
}
@ -352,11 +409,13 @@ static void check_network_activity(fd_set * readset, fd_set * writeset) {
}
for(i = 0; i < listen_sockets; i++) {
if(FD_ISSET(listen_socket[i].udp, readset))
if(FD_ISSET(listen_socket[i].udp, readset)) {
handle_incoming_vpn_data(i);
}
if(FD_ISSET(listen_socket[i].tcp, readset))
if(FD_ISSET(listen_socket[i].tcp, readset)) {
handle_new_meta_connection(listen_socket[i].tcp);
}
}
}
@ -379,12 +438,15 @@ int main_loop(void) {
last_ping_check = now;
last_config_check = now;
last_graph_dump = now;
srand(now);
#ifdef HAVE_PSELECT
if(lookup_config(config_tree, "GraphDumpFile"))
if(lookup_config(config_tree, "GraphDumpFile")) {
graph_dump = true;
}
/* Block SIGHUP & SIGALRM */
sigemptyset(&block_mask);
sigaddset(&block_mask, SIGHUP);
@ -397,16 +459,21 @@ int main_loop(void) {
while(running) {
#ifdef HAVE_PSELECT
next_event = last_ping_check + pingtimeout;
if(graph_dump && next_event > last_graph_dump + 60)
if(graph_dump && next_event > last_graph_dump + 60) {
next_event = last_graph_dump + 60;
}
if((event = peek_next_event()) && next_event > event->time)
if((event = peek_next_event()) && next_event > event->time) {
next_event = event->time;
}
if(next_event <= now)
if(next_event <= now) {
tv.tv_sec = 0;
else
} else {
tv.tv_sec = next_event - now;
}
tv.tv_nsec = 0;
#else
tv.tv_sec = 1;
@ -436,8 +503,9 @@ int main_loop(void) {
}
}
if(r > 0)
if(r > 0) {
check_network_activity(&readset, &writeset);
}
if(do_purge) {
purge();
@ -450,8 +518,9 @@ int main_loop(void) {
check_dead_connections();
last_ping_check = now;
if(routing_mode == RMODE_SWITCH)
if(routing_mode == RMODE_SWITCH) {
age_subnets();
}
age_past_requests();
@ -465,6 +534,7 @@ int main_loop(void) {
for(node = node_tree->head; node; node = node->next) {
n = node->data;
if(n->inkey) {
free(n->inkey);
n->inkey = NULL;
@ -484,12 +554,16 @@ int main_loop(void) {
logger(LOG_WARNING, "Possible node with same Name as us! Sleeping %d seconds.", sleeptime);
usleep(sleeptime * 1000000LL);
sleeptime *= 2;
if(sleeptime < 0)
if(sleeptime < 0) {
sleeptime = 3600;
}
} else {
sleeptime /= 2;
if(sleeptime < 10)
if(sleeptime < 10) {
sleeptime = 10;
}
}
contradicting_add_edge = 0;
@ -500,11 +574,15 @@ int main_loop(void) {
avl_node_t *node;
logger(LOG_INFO, "Flushing event queue");
expire_events();
for(node = connection_tree->head; node; node = node->next) {
connection_t *c = node->data;
if(c->status.active)
if(c->status.active) {
send_ping(c);
}
}
sigalrm = false;
}
@ -518,11 +596,11 @@ int main_loop(void) {
avl_node_t *node, *next;
char *fname;
struct stat s;
sighup = false;
reopenlogger();
/* Reread our own configuration file */
exit_configuration(&config_tree);
@ -552,20 +630,24 @@ int main_loop(void) {
for(list_node_t *node = outgoing_list->head; node; node = node->next) {
outgoing_t *outgoing = node->data;
if(outgoing->event)
if(outgoing->event) {
event_del(outgoing->event);
}
}
list_delete_list(outgoing_list);
/* Close connections to hosts that have a changed or deleted host config file */
for(node = connection_tree->head; node; node = node->next) {
c = node->data;
xasprintf(&fname, "%s/hosts/%s", confbase, c->name);
if(stat(fname, &s) || s.st_mtime > last_config_check)
if(stat(fname, &s) || s.st_mtime > last_config_check) {
terminate_connection(c, c->status.active);
}
free(fname);
}
@ -586,26 +668,32 @@ int main_loop(void) {
for(node = subnet_tree->head; node; node = next) {
next = node->next;
subnet = node->data;
if(subnet->expires == 1) {
send_del_subnet(everyone, subnet);
if(subnet->owner->status.reachable)
if(subnet->owner->status.reachable) {
subnet_update(subnet->owner, subnet, false);
}
subnet_del(subnet->owner, subnet);
} else if(subnet->expires == -1) {
subnet->expires = 0;
} else {
send_add_subnet(everyone, subnet);
if(subnet->owner->status.reachable)
if(subnet->owner->status.reachable) {
subnet_update(subnet->owner, subnet, true);
}
}
}
}
/* Try to make outgoing connections */
try_outgoing_connections();
}
/* Dump graph if wanted every 60 seconds*/
if(last_graph_dump + 60 <= now) {

View file

@ -1,3 +1,6 @@
#ifndef TINC_NET_H
#define TINC_NET_H
/*
net.h -- header for net.c
Copyright (C) 1998-2005 Ivo Timmermans
@ -18,23 +21,20 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __TINC_NET_H__
#define __TINC_NET_H__
#include <openssl/evp.h>
#include "ipv6.h"
#ifdef ENABLE_JUMBOGRAMS
#define MTU 9018 /* 9000 bytes payload + 14 bytes ethernet header + 4 bytes VLAN tag */
#define MTU 9018 /* 9000 bytes payload + 14 bytes ethernet header + 4 bytes VLAN tag */
#else
#define MTU 1518 /* 1500 bytes payload + 14 bytes ethernet header + 4 bytes VLAN tag */
#define MTU 1518 /* 1500 bytes payload + 14 bytes ethernet header + 4 bytes VLAN tag */
#endif
#define MAXSIZE (MTU + 4 + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE + MTU/64 + 20) /* MTU + seqno + padding + HMAC + compressor overhead */
#define MAXBUFSIZE ((MAXSIZE > 2048 ? MAXSIZE : 2048) + 128) /* Enough room for a request with a MAXSIZEd packet or a 8192 bits RSA key */
#define MAXSIZE (MTU + 4 + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE + MTU/64 + 20) /* MTU + seqno + padding + HMAC + compressor overhead */
#define MAXBUFSIZE ((MAXSIZE > 2048 ? MAXSIZE : 2048) + 128) /* Enough room for a request with a MAXSIZEd packet or a 8192 bits RSA key */
#define MAXSOCKETS 128 /* Overkill... */
#define MAXSOCKETS 128 /* Overkill... */
typedef struct mac_t {
uint8_t x[6];
@ -48,7 +48,7 @@ typedef struct ipv6_t {
uint16_t x[8];
} ipv6_t;
typedef short length_t;
typedef uint16_t length_t;
#define AF_UNKNOWN 255
@ -77,9 +77,9 @@ typedef union sockaddr_t {
#endif
typedef struct vpn_packet_t {
length_t len; /* the actual number of bytes in the `data' field */
int priority; /* priority or TOS */
uint32_t seqno; /* 32 bits sequence number (network byte order of course) */
length_t len; /* the actual number of bytes in the `data' field */
int priority; /* priority or TOS */
uint32_t seqno; /* 32 bits sequence number (network byte order of course) */
uint8_t data[MAXSIZE];
} vpn_packet_t;
@ -129,27 +129,28 @@ extern volatile bool running;
#include "connection.h"
#include "node.h"
extern void retry_outgoing(outgoing_t *);
extern void handle_incoming_vpn_data(int);
extern void finish_connecting(struct connection_t *);
extern void do_outgoing_connection(struct connection_t *);
extern bool handle_new_meta_connection(int);
extern int setup_listen_socket(const sockaddr_t *);
extern int setup_vpn_in_socket(const sockaddr_t *);
extern void send_packet(const struct node_t *, vpn_packet_t *);
extern void receive_tcppacket(struct connection_t *, const char *, int);
extern void broadcast_packet(const struct node_t *, vpn_packet_t *);
extern void retry_outgoing(outgoing_t *outgoing);
extern void handle_incoming_vpn_data(int sock);
extern void finish_connecting(struct connection_t *c);
extern void do_outgoing_connection(struct connection_t *c);
extern bool handle_new_meta_connection(int sock);
extern int setup_listen_socket(const sockaddr_t *sa);
extern int setup_vpn_in_socket(const sockaddr_t *sa);
extern void send_packet(const struct node_t *n, vpn_packet_t *packet);
extern void receive_tcppacket(struct connection_t *c, const char *buffer, length_t len);
extern void broadcast_packet(const struct node_t *, vpn_packet_t *packet);
extern char *get_name(void);
extern bool setup_network(void);
extern void setup_outgoing_connection(struct outgoing_t *);
extern void setup_outgoing_connection(struct outgoing_t *outgoing);
extern void try_outgoing_connections(void);
extern void close_network_connections(void);
extern int main_loop(void);
extern void terminate_connection(struct connection_t *, bool);
extern void flush_queue(struct node_t *);
extern bool read_rsa_public_key(struct connection_t *);
extern void send_mtu_probe(struct node_t *);
extern void terminate_connection(struct connection_t *c, bool report);
extern void flush_queue(struct node_t *n);
extern bool read_rsa_public_key(struct connection_t *c);
extern void send_mtu_probe(struct node_t *n);
extern void load_all_subnets(void);
extern void tarpit(int fd);
#ifndef HAVE_MINGW
#define closesocket(s) close(s)
@ -157,4 +158,4 @@ extern void load_all_subnets(void);
extern CRITICAL_SECTION mutex;
#endif
#endif /* __TINC_NET_H__ */
#endif

View file

@ -1,7 +1,7 @@
/*
net_packet.c -- Handles in- and outgoing VPN packets
Copyright (C) 1998-2005 Ivo Timmermans,
2000-2015 Guus Sliepen <guus@tinc-vpn.org>
2000-2016 Guus Sliepen <guus@tinc-vpn.org>
2010 Timothy Redaelli <timothy@redaelli.eu>
2010 Brandon Black <blblack@gmail.com>
@ -85,7 +85,7 @@ void send_mtu_probe(node_t *n) {
vpn_packet_t packet;
int len, i;
int timeout = 1;
n->mtuprobes++;
n->mtuevent = NULL;
@ -114,10 +114,12 @@ void send_mtu_probe(node_t *n) {
}
if(n->mtuprobes == 30 || (n->mtuprobes < 30 && n->minmtu >= n->maxmtu)) {
if(n->minmtu > n->maxmtu)
if(n->minmtu > n->maxmtu) {
n->minmtu = n->maxmtu;
else
} else {
n->maxmtu = n->minmtu;
}
n->mtu = n->minmtu;
ifdebug(TRAFFIC) logger(LOG_INFO, "Fixing MTU of %s (%s) to %d after %d probes", n->name, n->hostname, n->mtu, n->mtuprobes);
n->mtuprobes = 31;
@ -132,8 +134,10 @@ void send_mtu_probe(node_t *n) {
for(i = 0; i < 4 + localdiscovery; i++) {
if(i == 0) {
if(n->mtuprobes < 30 || n->maxmtu + 8 >= MTU)
if(n->mtuprobes < 30 || n->maxmtu + 8 >= MTU) {
continue;
}
len = n->maxmtu + 8;
} else if(n->maxmtu <= n->minmtu) {
len = n->maxmtu;
@ -141,16 +145,19 @@ void send_mtu_probe(node_t *n) {
len = n->minmtu + 1 + rand() % (n->maxmtu - n->minmtu);
}
if(len < 64)
if(len < 64) {
len = 64;
}
memset(packet.data, 0, 14);
RAND_pseudo_bytes(packet.data + 14, len - 14);
RAND_bytes(packet.data + 14, len - 14);
packet.len = len;
if(i >= 4 && n->mtuprobes <= 10)
if(i >= 4 && n->mtuprobes <= 10) {
packet.priority = -1;
else
} else {
packet.priority = 0;
}
ifdebug(TRAFFIC) logger(LOG_INFO, "Sending MTU probe length %d to %s (%s)", len, n->name, n->hostname);
@ -173,23 +180,27 @@ void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) {
send_udppacket(n, packet);
} else {
if(n->mtuprobes > 30) {
if (len == n->maxmtu + 8) {
if(len == n->maxmtu + 8) {
ifdebug(TRAFFIC) logger(LOG_INFO, "Increase in PMTU to %s (%s) detected, restarting PMTU discovery", n->name, n->hostname);
n->maxmtu = MTU;
n->mtuprobes = 10;
return;
}
if(n->minmtu)
if(n->minmtu) {
n->mtuprobes = 30;
else
} else {
n->mtuprobes = 1;
}
}
if(len > n->maxmtu)
if(len > n->maxmtu) {
len = n->maxmtu;
if(n->minmtu < len)
}
if(n->minmtu < len) {
n->minmtu = len;
}
}
}
@ -203,27 +214,28 @@ static length_t compress_packet(uint8_t *dest, const uint8_t *source, length_t l
lzo1x_1_compress(source, len, dest, &lzolen, lzo_wrkmem);
return lzolen;
#else
return -1;
return 0;
#endif
} else if(level < 10) {
#ifdef HAVE_ZLIB
unsigned long destlen = MAXSIZE;
if(compress2(dest, &destlen, source, len, level) == Z_OK)
if(compress2(dest, &destlen, source, len, level) == Z_OK) {
return destlen;
else
} else
#endif
return -1;
return 0;
} else {
#ifdef HAVE_LZO
lzo_uint lzolen = MAXSIZE;
lzo1x_999_compress(source, len, dest, &lzolen, lzo_wrkmem);
return lzolen;
#else
return -1;
return 0;
#endif
}
return -1;
return 0;
}
static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) {
@ -233,20 +245,25 @@ static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t
} else if(level > 9) {
#ifdef HAVE_LZO
lzo_uint lzolen = MAXSIZE;
if(lzo1x_decompress_safe(source, len, dest, &lzolen, NULL) == LZO_E_OK)
if(lzo1x_decompress_safe(source, len, dest, &lzolen, NULL) == LZO_E_OK) {
return lzolen;
else
} else
#endif
return -1;
return 0;
}
#ifdef HAVE_ZLIB
else {
unsigned long destlen = MAXSIZE;
if(uncompress(dest, &destlen, source, len) == Z_OK)
if(uncompress(dest, &destlen, source, len) == Z_OK) {
return destlen;
else
return -1;
} else {
return 0;
}
}
#endif
return -1;
@ -256,7 +273,7 @@ static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t
static void receive_packet(node_t *n, vpn_packet_t *packet) {
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Received packet of %d bytes from %s (%s)",
packet->len, n->name, n->hostname);
packet->len, n->name, n->hostname);
route(n, packet);
}
@ -264,8 +281,9 @@ static void receive_packet(node_t *n, vpn_packet_t *packet) {
static bool try_mac(const node_t *n, const vpn_packet_t *inpkt) {
unsigned char hmac[EVP_MAX_MD_SIZE];
if(!n->indigest || !n->inmaclength || !n->inkey || inpkt->len < sizeof inpkt->seqno + n->inmaclength)
if(!n->indigest || !n->inmaclength || !n->inkey || inpkt->len < sizeof(inpkt->seqno) + n->inmaclength) {
return false;
}
HMAC(n->indigest, n->inkey, n->inkeylength, (unsigned char *) &inpkt->seqno, inpkt->len - n->inmaclength, (unsigned char *)hmac, NULL);
@ -279,11 +297,10 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
vpn_packet_t *outpkt;
int outlen, outpad;
unsigned char hmac[EVP_MAX_MD_SIZE];
int i;
if(!n->inkey) {
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet",
n->name, n->hostname);
n->name, n->hostname);
return;
}
@ -291,7 +308,7 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
if(inpkt->len < sizeof(inpkt->seqno) + n->inmaclength) {
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Got too short packet from %s (%s)",
n->name, n->hostname);
n->name, n->hostname);
return;
}
@ -300,11 +317,11 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
if(n->indigest && n->inmaclength) {
inpkt->len -= n->inmaclength;
HMAC(n->indigest, n->inkey, n->inkeylength,
(unsigned char *) &inpkt->seqno, inpkt->len, (unsigned char *)hmac, NULL);
(unsigned char *) &inpkt->seqno, inpkt->len, (unsigned char *)hmac, NULL);
if(memcmp_constant_time(hmac, (char *) &inpkt->seqno + inpkt->len, n->inmaclength)) {
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Got unauthenticated packet from %s (%s)",
n->name, n->hostname);
n->name, n->hostname);
return;
}
}
@ -314,15 +331,15 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
if(n->incipher) {
outpkt = pkt[nextpkt++];
if(!EVP_DecryptInit_ex(&n->inctx, NULL, NULL, NULL, NULL)
|| !EVP_DecryptUpdate(&n->inctx, (unsigned char *) &outpkt->seqno, &outlen,
(unsigned char *) &inpkt->seqno, inpkt->len)
|| !EVP_DecryptFinal_ex(&n->inctx, (unsigned char *) &outpkt->seqno + outlen, &outpad)) {
if(!EVP_DecryptInit_ex(n->inctx, NULL, NULL, NULL, NULL)
|| !EVP_DecryptUpdate(n->inctx, (unsigned char *) &outpkt->seqno, &outlen,
(unsigned char *) &inpkt->seqno, inpkt->len)
|| !EVP_DecryptFinal_ex(n->inctx, (unsigned char *) &outpkt->seqno + outlen, &outpad)) {
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Error decrypting packet from %s (%s): %s",
n->name, n->hostname, ERR_error_string(ERR_get_error(), NULL));
n->name, n->hostname, ERR_error_string(ERR_get_error(), NULL));
return;
}
outpkt->len = outlen + outpad;
inpkt = outpkt;
}
@ -336,22 +353,24 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
if(inpkt->seqno != n->received_seqno + 1) {
if(inpkt->seqno >= n->received_seqno + replaywin * 8) {
if(n->farfuture++ < replaywin >> 2) {
logger(LOG_WARNING, "Packet from %s (%s) is %d seqs in the future, dropped (%u)",
n->name, n->hostname, inpkt->seqno - n->received_seqno - 1, n->farfuture);
ifdebug(TRAFFIC) logger(LOG_WARNING, "Packet from %s (%s) is %d seqs in the future, dropped (%u)",
n->name, n->hostname, inpkt->seqno - n->received_seqno - 1, n->farfuture);
return;
}
logger(LOG_WARNING, "Lost %d packets from %s (%s)",
inpkt->seqno - n->received_seqno - 1, n->name, n->hostname);
ifdebug(TRAFFIC) logger(LOG_WARNING, "Lost %d packets from %s (%s)",
inpkt->seqno - n->received_seqno - 1, n->name, n->hostname);
memset(n->late, 0, replaywin);
} else if (inpkt->seqno <= n->received_seqno) {
} else if(inpkt->seqno <= n->received_seqno) {
if((n->received_seqno >= replaywin * 8 && inpkt->seqno <= n->received_seqno - replaywin * 8) || !(n->late[(inpkt->seqno / 8) % replaywin] & (1 << inpkt->seqno % 8))) {
logger(LOG_WARNING, "Got late or replayed packet from %s (%s), seqno %d, last received %d",
n->name, n->hostname, inpkt->seqno, n->received_seqno);
ifdebug(TRAFFIC) logger(LOG_WARNING, "Got late or replayed packet from %s (%s), seqno %d, last received %d",
n->name, n->hostname, inpkt->seqno, n->received_seqno);
return;
}
} else {
for(i = n->received_seqno + 1; i < inpkt->seqno; i++)
for(uint32_t i = n->received_seqno + 1; i < inpkt->seqno; i++) {
n->late[(i / 8) % replaywin] |= 1 << i % 8;
}
}
}
@ -359,11 +378,13 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
n->late[(inpkt->seqno / 8) % replaywin] &= ~(1 << inpkt->seqno % 8);
}
if(inpkt->seqno > n->received_seqno)
if(inpkt->seqno > n->received_seqno) {
n->received_seqno = inpkt->seqno;
if(n->received_seqno > MAX_SEQNO)
}
if(n->received_seqno > MAX_SEQNO) {
keyexpires = 0;
}
/* Decompress the packet */
@ -372,36 +393,41 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
if(n->incompression) {
outpkt = pkt[nextpkt++];
if((outpkt->len = uncompress_packet(outpkt->data, inpkt->data, inpkt->len, n->incompression)) < 0) {
if(!(outpkt->len = uncompress_packet(outpkt->data, inpkt->data, inpkt->len, n->incompression))) {
ifdebug(TRAFFIC) logger(LOG_ERR, "Error while uncompressing packet from %s (%s)",
n->name, n->hostname);
n->name, n->hostname);
return;
}
inpkt = outpkt;
origlen -= MTU/64 + 20;
origlen -= MTU / 64 + 20;
}
inpkt->priority = 0;
if(!inpkt->data[12] && !inpkt->data[13])
if(!inpkt->data[12] && !inpkt->data[13]) {
mtu_probe_h(n, inpkt, origlen);
else
} else {
receive_packet(n, inpkt);
}
}
void receive_tcppacket(connection_t *c, const char *buffer, int len) {
void receive_tcppacket(connection_t *c, const char *buffer, length_t len) {
vpn_packet_t outpkt;
if(len > sizeof outpkt.data)
if(len > sizeof(outpkt.data)) {
return;
}
outpkt.len = len;
if(c->options & OPTION_TCPONLY)
if(c->options & OPTION_TCPONLY) {
outpkt.priority = 0;
else
} else {
outpkt.priority = -1;
}
memcpy(outpkt.data, buffer, len);
receive_packet(c->node, &outpkt);
@ -426,8 +452,8 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
if(!n->status.validkey) {
ifdebug(TRAFFIC) logger(LOG_INFO,
"No valid key known yet for %s (%s), forwarding via TCP",
n->name, n->hostname);
"No valid key known yet for %s (%s), forwarding via TCP",
n->name, n->hostname);
if(n->last_req_key + 10 <= now) {
send_req_key(n);
@ -441,13 +467,14 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
if(n->options & OPTION_PMTU_DISCOVERY && inpkt->len > n->minmtu && (inpkt->data[12] | inpkt->data[13])) {
ifdebug(TRAFFIC) logger(LOG_INFO,
"Packet for %s (%s) larger than minimum MTU, forwarding via %s",
n->name, n->hostname, n != n->nexthop ? n->nexthop->name : "TCP");
"Packet for %s (%s) larger than minimum MTU, forwarding via %s",
n->name, n->hostname, n != n->nexthop ? n->nexthop->name : "TCP");
if(n != n->nexthop)
if(n != n->nexthop) {
send_packet(n->nexthop, origpkt);
else
} else {
send_tcppacket(n->nexthop->connection, origpkt);
}
return;
}
@ -460,9 +487,9 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
if(n->outcompression) {
outpkt = pkt[nextpkt++];
if((outpkt->len = compress_packet(outpkt->data, inpkt->data, inpkt->len, n->outcompression)) < 0) {
if(!(outpkt->len = compress_packet(outpkt->data, inpkt->data, inpkt->len, n->outcompression))) {
ifdebug(TRAFFIC) logger(LOG_ERR, "Error while compressing packet to %s (%s)",
n->name, n->hostname);
n->name, n->hostname);
return;
}
@ -479,12 +506,12 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
if(n->outcipher) {
outpkt = pkt[nextpkt++];
if(!EVP_EncryptInit_ex(&n->outctx, NULL, NULL, NULL, NULL)
|| !EVP_EncryptUpdate(&n->outctx, (unsigned char *) &outpkt->seqno, &outlen,
(unsigned char *) &inpkt->seqno, inpkt->len)
|| !EVP_EncryptFinal_ex(&n->outctx, (unsigned char *) &outpkt->seqno + outlen, &outpad)) {
if(!EVP_EncryptInit_ex(n->outctx, NULL, NULL, NULL, NULL)
|| !EVP_EncryptUpdate(n->outctx, (unsigned char *) &outpkt->seqno, &outlen,
(unsigned char *) &inpkt->seqno, inpkt->len)
|| !EVP_EncryptFinal_ex(n->outctx, (unsigned char *) &outpkt->seqno + outlen, &outpad)) {
ifdebug(TRAFFIC) logger(LOG_ERR, "Error while encrypting packet to %s (%s): %s",
n->name, n->hostname, ERR_error_string(ERR_get_error(), NULL));
n->name, n->hostname, ERR_error_string(ERR_get_error(), NULL));
goto end;
}
@ -496,7 +523,7 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
if(n->outdigest && n->outmaclength) {
HMAC(n->outdigest, n->outkey, n->outkeylength, (unsigned char *) &inpkt->seqno,
inpkt->len, (unsigned char *) &inpkt->seqno + inpkt->len, NULL);
inpkt->len, (unsigned char *) &inpkt->seqno + inpkt->len, NULL);
inpkt->len += n->outmaclength;
}
@ -522,7 +549,8 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
if(origpriority == -1 && n->prevedge) {
sock = rand() % listen_sockets;
memset(&broadcast, 0, sizeof broadcast);
memset(&broadcast, 0, sizeof(broadcast));
if(listen_socket[sock].sa.sa.sa_family == AF_INET6) {
broadcast.in6.sin6_family = AF_INET6;
broadcast.in6.sin6_addr.s6_addr[0x0] = 0xff;
@ -535,11 +563,13 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
broadcast.in.sin_addr.s_addr = -1;
broadcast.in.sin_port = n->prevedge->address.in.sin_port;
}
sa = &broadcast.sa;
sl = SALEN(broadcast.sa);
} else {
if(origpriority == -1)
if(origpriority == -1) {
origpriority = 0;
}
sa = &(n->address.sa);
sl = SALEN(n->address.sa);
@ -548,21 +578,31 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
if(priorityinheritance && origpriority != listen_socket[n->sock].priority) {
listen_socket[n->sock].priority = origpriority;
switch(listen_socket[n->sock].sa.sa.sa_family) {
#if defined(SOL_IP) && defined(IP_TOS)
#if defined(IP_TOS)
case AF_INET:
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Setting IPv4 outgoing packet priority to %d", origpriority);
if(setsockopt(listen_socket[n->sock].udp, SOL_IP, IP_TOS, (void *)&origpriority, sizeof(origpriority))) /* SO_PRIORITY doesn't seem to work */
if(setsockopt(listen_socket[n->sock].udp, IPPROTO_IP, IP_TOS, (void *)&origpriority, sizeof(origpriority))) { /* SO_PRIORITY doesn't seem to work */
logger(LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno));
}
break;
#endif
#if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS)
#if defined(IPV6_TCLASS)
case AF_INET6:
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Setting IPv6 outgoing packet priority to %d", origpriority);
if(setsockopt(listen_socket[n->sock].udp, IPPROTO_IPV6, IPV6_TCLASS, (void *)&origpriority, sizeof(origpriority)))
if(setsockopt(listen_socket[n->sock].udp, IPPROTO_IPV6, IPV6_TCLASS, (void *)&origpriority, sizeof(origpriority))) {
logger(LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno));
}
break;
#endif
default:
break;
}
@ -570,12 +610,16 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
if(sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, sa, sl) < 0 && !sockwouldblock(sockerrno)) {
if(sockmsgsize(sockerrno)) {
if(n->maxmtu >= origlen)
if(n->maxmtu >= origlen) {
n->maxmtu = origlen - 1;
if(n->mtu >= origlen)
}
if(n->mtu >= origlen) {
n->mtu = origlen - 1;
} else
}
} else {
ifdebug(TRAFFIC) logger(LOG_WARNING, "Error sending packet to %s (%s): %s", n->name, n->hostname, sockstrerror(sockerrno));
}
}
end:
@ -589,18 +633,20 @@ void send_packet(const node_t *n, vpn_packet_t *packet) {
node_t *via;
if(n == myself) {
if(overwrite_mac)
memcpy(packet->data, mymac.x, ETH_ALEN);
if(overwrite_mac) {
memcpy(packet->data, mymac.x, ETH_ALEN);
}
devops.write(packet);
return;
}
ifdebug(TRAFFIC) logger(LOG_ERR, "Sending packet of %d bytes to %s (%s)",
packet->len, n->name, n->hostname);
packet->len, n->name, n->hostname);
if(!n->status.reachable) {
ifdebug(TRAFFIC) logger(LOG_INFO, "Node %s (%s) is not reachable",
n->name, n->hostname);
n->name, n->hostname);
return;
}
@ -608,13 +654,15 @@ void send_packet(const node_t *n, vpn_packet_t *packet) {
if(via != n)
ifdebug(TRAFFIC) logger(LOG_INFO, "Sending packet to %s via %s (%s)",
n->name, via->name, n->via->hostname);
n->name, via->name, n->via->hostname);
if(packet->priority == -1 || ((myself->options | via->options) & OPTION_TCPONLY)) {
if(!send_tcppacket(via->connection, packet))
if(!send_tcppacket(via->connection, packet)) {
terminate_connection(via->connection, true);
} else
}
} else {
send_udppacket(via, packet);
}
}
/* Broadcast a packet using the minimum spanning tree */
@ -625,47 +673,54 @@ void broadcast_packet(const node_t *from, vpn_packet_t *packet) {
node_t *n;
// Always give ourself a copy of the packet.
if(from != myself)
if(from != myself) {
send_packet(myself, packet);
}
// In TunnelServer mode, do not forward broadcast packets.
// The MST might not be valid and create loops.
if(tunnelserver || broadcast_mode == BMODE_NONE)
// The MST might not be valid and create loops.
if(tunnelserver || broadcast_mode == BMODE_NONE) {
return;
}
ifdebug(TRAFFIC) logger(LOG_INFO, "Broadcasting packet of %d bytes from %s (%s)",
packet->len, from->name, from->hostname);
packet->len, from->name, from->hostname);
switch(broadcast_mode) {
// In MST mode, broadcast packets travel via the Minimum Spanning Tree.
// This guarantees all nodes receive the broadcast packet, and
// usually distributes the sending of broadcast packets over all nodes.
case BMODE_MST:
for(node = connection_tree->head; node; node = node->next) {
c = node->data;
// In MST mode, broadcast packets travel via the Minimum Spanning Tree.
// This guarantees all nodes receive the broadcast packet, and
// usually distributes the sending of broadcast packets over all nodes.
case BMODE_MST:
for(node = connection_tree->head; node; node = node->next) {
c = node->data;
if(c->status.active && c->status.mst && c != from->nexthop->connection)
send_packet(c->node, packet);
if(c->status.active && c->status.mst && c != from->nexthop->connection) {
send_packet(c->node, packet);
}
}
break;
// In direct mode, we send copies to each node we know of.
// However, this only reaches nodes that can be reached in a single hop.
// We don't have enough information to forward broadcast packets in this case.
case BMODE_DIRECT:
if(from != myself) {
break;
}
// In direct mode, we send copies to each node we know of.
// However, this only reaches nodes that can be reached in a single hop.
// We don't have enough information to forward broadcast packets in this case.
case BMODE_DIRECT:
if(from != myself)
break;
for(node = node_udp_tree->head; node; node = node->next) {
n = node->data;
for(node = node_udp_tree->head; node; node = node->next) {
n = node->data;
if(n->status.reachable && n != myself && ((n->via == myself && n->nexthop == n) || n->via == n))
send_packet(n, packet);
if(n->status.reachable && n != myself && ((n->via == myself && n->nexthop == n) || n->via == n)) {
send_packet(n, packet);
}
break;
}
default:
break;
break;
default:
break;
}
}
@ -678,14 +733,17 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) {
for(node = edge_weight_tree->head; node; node = node->next) {
e = node->data;
if(e->to == myself)
if(e->to == myself) {
continue;
}
if(last_hard_try == now && sockaddrcmp_noport(from, &e->address))
if(last_hard_try == now && sockaddrcmp_noport(from, &e->address)) {
continue;
}
if(!try_mac(e->to, pkt))
if(!try_mac(e->to, pkt)) {
continue;
}
n = e->to;
break;
@ -702,30 +760,36 @@ void handle_incoming_vpn_data(int sock) {
socklen_t fromlen = sizeof(from);
node_t *n;
pkt.len = recvfrom(listen_socket[sock].udp, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen);
ssize_t len = recvfrom(listen_socket[sock].udp, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen);
if(pkt.len < 0) {
if(!sockwouldblock(sockerrno))
if(len <= 0 || len > UINT16_MAX) {
if(len >= 0) {
logger(LOG_ERR, "Receiving packet with invalid size");
} else if(!sockwouldblock(sockerrno)) {
logger(LOG_ERR, "Receiving packet failed: %s", sockstrerror(sockerrno));
}
return;
}
sockaddrunmap(&from); /* Some braindead IPv6 implementations do stupid things. */
pkt.len = len;
sockaddrunmap(&from); /* Some braindead IPv6 implementations do stupid things. */
n = lookup_node_udp(&from);
if(!n) {
n = try_harder(&from, &pkt);
if(n)
if(n) {
update_node_udp(n, &from);
else ifdebug(PROTOCOL) {
} else ifdebug(PROTOCOL) {
hostname = sockaddr2hostname(&from);
logger(LOG_WARNING, "Received UDP packet from unknown source %s", hostname);
free(hostname);
return;
}
else
} else {
return;
}
}
n->sock = sock;

View file

@ -1,7 +1,7 @@
/*
net_setup.c -- Setup.
Copyright (C) 1998-2005 Ivo Timmermans,
2000-2015 Guus Sliepen <guus@tinc-vpn.org>
2000-2017 Guus Sliepen <guus@tinc-vpn.org>
2006 Scott Lamb <slamb@slamb.org>
2010 Brandon Black <blblack@gmail.com>
@ -27,6 +27,7 @@
#include <openssl/rand.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/bn.h>
#include "avl_tree.h"
#include "conf.h"
@ -48,11 +49,25 @@
char *myport;
devops_t devops;
#ifndef HAVE_RSA_SET0_KEY
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) {
BN_free(r->n);
r->n = n;
BN_free(r->e);
r->e = e;
BN_free(r->d);
r->d = d;
return 1;
}
#endif
bool read_rsa_public_key(connection_t *c) {
FILE *fp;
char *pubname;
char *hcfname;
char *key;
BIGNUM *n = NULL;
BIGNUM *e = NULL;
if(!c->rsa_key) {
c->rsa_key = RSA_new();
@ -62,12 +77,22 @@ bool read_rsa_public_key(connection_t *c) {
/* First, check for simple PublicKey statement */
if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &key)) {
if(BN_hex2bn(&c->rsa_key->n, key) != strlen(key)) {
if((size_t)BN_hex2bn(&n, key) != strlen(key)) {
free(key);
logger(LOG_ERR, "Invalid PublicKey for %s!", c->name);
return false;
}
BN_hex2bn(&c->rsa_key->e, "FFFF");
free(key);
BN_hex2bn(&e, "FFFF");
if(!n || !e || RSA_set0_key(c->rsa_key, n, e, NULL) != 1) {
BN_free(e);
BN_free(n);
logger(LOG_ERR, "RSA_set0_key() failed with PublicKey for %s!", c->name);
return false;
}
return true;
}
@ -87,7 +112,7 @@ bool read_rsa_public_key(connection_t *c) {
if(c->rsa_key) {
free(pubname);
return true; /* Woohoo. */
return true; /* Woohoo. */
}
/* If it fails, try PEM_read_RSA_PUBKEY. */
@ -147,8 +172,9 @@ bool read_rsa_public_key(connection_t *c) {
// RSA_blinding_on(c->rsa_key, NULL);
fclose(fp);
if(c->rsa_key)
if(c->rsa_key) {
return true;
}
logger(LOG_ERR, "No public key for %s specified!", c->name);
@ -158,38 +184,58 @@ bool read_rsa_public_key(connection_t *c) {
static bool read_rsa_private_key(void) {
FILE *fp;
char *fname, *key, *pubkey;
BIGNUM *n = NULL;
BIGNUM *e = NULL;
BIGNUM *d = NULL;
if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key)) {
myself->connection->rsa_key = RSA_new();
// RSA_blinding_on(myself->connection->rsa_key, NULL);
if(BN_hex2bn(&myself->connection->rsa_key->d, key) != strlen(key)) {
if((size_t)BN_hex2bn(&d, key) != strlen(key)) {
logger(LOG_ERR, "Invalid PrivateKey for myself!");
free(key);
return false;
}
free(key);
if(!get_config_string(lookup_config(config_tree, "PublicKey"), &pubkey)) {
BN_free(d);
logger(LOG_ERR, "PrivateKey used but no PublicKey found!");
return false;
}
if(BN_hex2bn(&myself->connection->rsa_key->n, pubkey) != strlen(pubkey)) {
logger(LOG_ERR, "Invalid PublicKey for myself!");
if((size_t)BN_hex2bn(&n, pubkey) != strlen(pubkey)) {
free(pubkey);
BN_free(d);
logger(LOG_ERR, "Invalid PublicKey for myself!");
return false;
}
free(pubkey);
BN_hex2bn(&myself->connection->rsa_key->e, "FFFF");
BN_hex2bn(&e, "FFFF");
if(!n || !e || !d || RSA_set0_key(myself->connection->rsa_key, n, e, d) != 1) {
BN_free(d);
BN_free(e);
BN_free(n);
logger(LOG_ERR, "RSA_set0_key() failed with PrivateKey for myself!");
return false;
}
return true;
}
if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname))
if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname)) {
xasprintf(&fname, "%s/rsa_key.priv", confbase);
}
fp = fopen(fname, "r");
if(!fp) {
logger(LOG_ERR, "Error reading RSA private key file `%s': %s",
fname, strerror(errno));
fname, strerror(errno));
free(fname);
return false;
}
@ -198,11 +244,13 @@ static bool read_rsa_private_key(void) {
struct stat s;
if(!fstat(fileno(fp), &s)) {
if(s.st_mode & ~0100700)
if(s.st_mode & ~0100700) {
logger(LOG_WARNING, "Warning: insecure file permissions for RSA private key file `%s'!", fname);
}
} else {
logger(LOG_WARNING, "Could not stat RSA private key file `%s': %s'", fname, strerror(errno));
}
#endif
myself->connection->rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
@ -210,7 +258,7 @@ static bool read_rsa_private_key(void) {
if(!myself->connection->rsa_key) {
logger(LOG_ERR, "Reading RSA private key file `%s' failed: %s",
fname, strerror(errno));
fname, strerror(errno));
free(fname);
return false;
}
@ -234,6 +282,7 @@ void load_all_subnets(void) {
xasprintf(&dname, "%s/hosts", confbase);
dir = opendir(dname);
if(!dir) {
logger(LOG_ERR, "Could not open %s: %s", dname, strerror(errno));
free(dname);
@ -241,14 +290,15 @@ void load_all_subnets(void) {
}
while((ent = readdir(dir))) {
if(!check_id(ent->d_name))
if(!check_id(ent->d_name)) {
continue;
}
n = lookup_node(ent->d_name);
#ifdef _DIRENT_HAVE_D_TYPE
#ifdef _DIRENT_HAVE_D_TYPE
//if(ent->d_type != DT_REG)
// continue;
#endif
// continue;
#endif
xasprintf(&fname, "%s/hosts/%s", confbase, ent->d_name);
init_configuration(&config_tree);
@ -263,8 +313,9 @@ void load_all_subnets(void) {
}
for(cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
if(!get_config_subnet(cfg, &s))
if(!get_config_subnet(cfg, &s)) {
continue;
}
if((s2 = lookup_subnet(n, s))) {
s2->expires = -1;
@ -284,31 +335,38 @@ char *get_name(void) {
get_config_string(lookup_config(config_tree, "Name"), &name);
if(!name)
if(!name) {
return NULL;
}
if(*name == '$') {
char *envname = getenv(name + 1);
char hostname[32] = "";
if(!envname) {
if(strcmp(name + 1, "HOST")) {
fprintf(stderr, "Invalid Name: environment variable %s does not exist\n", name + 1);
free(name);
return false;
}
if(gethostname(hostname, sizeof hostname) || !*hostname) {
if(gethostname(hostname, sizeof(hostname)) || !*hostname) {
fprintf(stderr, "Could not get hostname: %s\n", strerror(errno));
free(name);
return false;
}
hostname[31] = 0;
envname = hostname;
}
free(name);
name = xstrdup(envname);
for(char *c = name; *c; c++)
if(!isalnum(*c))
if(!isalnum(*c)) {
*c = '_';
}
}
if(!check_id(name)) {
@ -331,7 +389,7 @@ static bool setup_myself(void) {
char *address = NULL;
char *proxy = NULL;
char *space;
char *envp[5] = {NULL};
char *envp[5] = {0};
struct addrinfo *ai, *aip, hint = {0};
bool choice;
int i, err;
@ -361,29 +419,35 @@ static bool setup_myself(void) {
read_config_file(config_tree, fname);
free(fname);
if(!read_rsa_private_key())
if(!read_rsa_private_key()) {
return false;
}
if(!get_config_string(lookup_config(config_tree, "Port"), &myport))
if(!get_config_string(lookup_config(config_tree, "Port"), &myport)) {
myport = xstrdup("655");
else
} else {
port_specified = true;
}
/* Ensure myport is numeric */
if(!atoi(myport)) {
struct addrinfo *ai = str2addrinfo("localhost", myport, SOCK_DGRAM);
sockaddr_t sa;
if(!ai || !ai->ai_addr)
if(!ai || !ai->ai_addr) {
return false;
}
free(myport);
memcpy(&sa, ai->ai_addr, ai->ai_addrlen);
sockaddr2str(&sa, NULL, &myport);
}
if(get_config_string(lookup_config(config_tree, "Proxy"), &proxy)) {
if((space = strchr(proxy, ' ')))
if((space = strchr(proxy, ' '))) {
*space++ = 0;
}
if(!strcasecmp(proxy, "none")) {
proxytype = PROXY_NONE;
@ -404,42 +468,56 @@ static bool setup_myself(void) {
}
switch(proxytype) {
case PROXY_NONE:
default:
break;
case PROXY_NONE:
default:
break;
case PROXY_EXEC:
if(!space || !*space) {
logger(LOG_ERR, "Argument expected for proxy type exec!");
free(proxy);
return false;
}
proxyhost = xstrdup(space);
break;
case PROXY_EXEC:
if(!space || !*space) {
logger(LOG_ERR, "Argument expected for proxy type exec!");
free(proxy);
return false;
}
case PROXY_SOCKS4:
case PROXY_SOCKS4A:
case PROXY_SOCKS5:
case PROXY_HTTP:
proxyhost = space;
if(space && (space = strchr(space, ' ')))
*space++ = 0, proxyport = space;
if(space && (space = strchr(space, ' ')))
*space++ = 0, proxyuser = space;
if(space && (space = strchr(space, ' ')))
*space++ = 0, proxypass = space;
if(!proxyhost || !*proxyhost || !proxyport || !*proxyport) {
logger(LOG_ERR, "Host and port argument expected for proxy!");
free(proxy);
return false;
}
proxyhost = xstrdup(proxyhost);
proxyport = xstrdup(proxyport);
if(proxyuser && *proxyuser)
proxyuser = xstrdup(proxyuser);
if(proxypass && *proxypass)
proxypass = xstrdup(proxypass);
break;
proxyhost = xstrdup(space);
break;
case PROXY_SOCKS4:
case PROXY_SOCKS4A:
case PROXY_SOCKS5:
case PROXY_HTTP:
proxyhost = space;
if(space && (space = strchr(space, ' '))) {
*space++ = 0, proxyport = space;
}
if(space && (space = strchr(space, ' '))) {
*space++ = 0, proxyuser = space;
}
if(space && (space = strchr(space, ' '))) {
*space++ = 0, proxypass = space;
}
if(!proxyhost || !*proxyhost || !proxyport || !*proxyport) {
logger(LOG_ERR, "Host and port argument expected for proxy!");
free(proxy);
return false;
}
proxyhost = xstrdup(proxyhost);
proxyport = xstrdup(proxyport);
if(proxyuser && *proxyuser) {
proxyuser = xstrdup(proxyuser);
}
if(proxypass && *proxypass) {
proxypass = xstrdup(proxypass);
}
break;
}
free(proxy);
@ -450,8 +528,9 @@ static bool setup_myself(void) {
cfg = lookup_config(config_tree, "Subnet");
while(cfg) {
if(!get_config_subnet(cfg, &subnet))
if(!get_config_subnet(cfg, &subnet)) {
return false;
}
subnet_add(myself, subnet);
@ -460,14 +539,17 @@ static bool setup_myself(void) {
/* Check some options */
if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice) && choice)
if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice) && choice) {
myself->options |= OPTION_INDIRECT;
}
if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice) && choice)
if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice) && choice) {
myself->options |= OPTION_TCPONLY;
}
if(myself->options & OPTION_TCPONLY)
if(myself->options & OPTION_TCPONLY) {
myself->options |= OPTION_INDIRECT;
}
get_config_bool(lookup_config(config_tree, "DirectOnly"), &directonly);
get_config_bool(lookup_config(config_tree, "StrictSubnets"), &strictsubnets);
@ -476,94 +558,112 @@ static bool setup_myself(void) {
strictsubnets |= tunnelserver;
if(get_config_string(lookup_config(config_tree, "Mode"), &mode)) {
if(!strcasecmp(mode, "router"))
if(!strcasecmp(mode, "router")) {
routing_mode = RMODE_ROUTER;
else if(!strcasecmp(mode, "switch"))
} else if(!strcasecmp(mode, "switch")) {
routing_mode = RMODE_SWITCH;
else if(!strcasecmp(mode, "hub"))
} else if(!strcasecmp(mode, "hub")) {
routing_mode = RMODE_HUB;
else {
} else {
logger(LOG_ERR, "Invalid routing mode!");
free(mode);
return false;
}
free(mode);
}
if(get_config_string(lookup_config(config_tree, "Forwarding"), &mode)) {
if(!strcasecmp(mode, "off"))
if(!strcasecmp(mode, "off")) {
forwarding_mode = FMODE_OFF;
else if(!strcasecmp(mode, "internal"))
} else if(!strcasecmp(mode, "internal")) {
forwarding_mode = FMODE_INTERNAL;
else if(!strcasecmp(mode, "kernel"))
} else if(!strcasecmp(mode, "kernel")) {
forwarding_mode = FMODE_KERNEL;
else {
} else {
logger(LOG_ERR, "Invalid forwarding mode!");
free(mode);
return false;
}
free(mode);
}
choice = true;
choice = !(myself->options & OPTION_TCPONLY);
get_config_bool(lookup_config(config_tree, "PMTUDiscovery"), &choice);
if(choice)
if(choice) {
myself->options |= OPTION_PMTU_DISCOVERY;
}
choice = true;
get_config_bool(lookup_config(config_tree, "ClampMSS"), &choice);
if(choice)
if(choice) {
myself->options |= OPTION_CLAMP_MSS;
}
get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance);
get_config_bool(lookup_config(config_tree, "DecrementTTL"), &decrement_ttl);
if(get_config_string(lookup_config(config_tree, "Broadcast"), &mode)) {
if(!strcasecmp(mode, "no"))
if(!strcasecmp(mode, "no")) {
broadcast_mode = BMODE_NONE;
else if(!strcasecmp(mode, "yes") || !strcasecmp(mode, "mst"))
} else if(!strcasecmp(mode, "yes") || !strcasecmp(mode, "mst")) {
broadcast_mode = BMODE_MST;
else if(!strcasecmp(mode, "direct"))
} else if(!strcasecmp(mode, "direct")) {
broadcast_mode = BMODE_DIRECT;
else {
} else {
logger(LOG_ERR, "Invalid broadcast mode!");
free(mode);
return false;
}
free(mode);
}
#if !defined(SOL_IP) || !defined(IP_TOS)
if(priorityinheritance)
if(priorityinheritance) {
logger(LOG_WARNING, "%s not supported on this platform for IPv4 connection", "PriorityInheritance");
}
#endif
#if !defined(IPPROTO_IPV6) || !defined(IPV6_TCLASS)
if(priorityinheritance)
if(priorityinheritance) {
logger(LOG_WARNING, "%s not supported on this platform for IPv6 connection", "PriorityInheritance");
}
#endif
if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire))
if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire)) {
macexpire = 600;
}
if(get_config_int(lookup_config(config_tree, "MaxTimeout"), &maxtimeout)) {
if(maxtimeout <= 0) {
logger(LOG_ERR, "Bogus maximum timeout!");
return false;
}
} else
} else {
maxtimeout = 900;
}
if(get_config_int(lookup_config(config_tree, "MinTimeout"), &mintimeout)) {
if(mintimeout < 0) {
logger(LOG_ERR, "Bogus minimum timeout!");
return false;
}
if(mintimeout > maxtimeout) {
logger(LOG_WARNING, "Minimum timeout (%d s) cannot be larger than maximum timeout (%d s). Correcting !", mintimeout, maxtimeout );
mintimeout=maxtimeout;
}
} else
mintimeout = 0;
if(mintimeout < 0) {
logger(LOG_ERR, "Bogus minimum timeout!");
return false;
}
if(mintimeout > maxtimeout) {
logger(LOG_WARNING, "Minimum timeout (%d s) cannot be larger than maximum timeout (%d s). Correcting !", mintimeout, maxtimeout);
mintimeout = maxtimeout;
}
} else {
mintimeout = 0;
}
if(get_config_int(lookup_config(config_tree, "UDPRcvBuf"), &udp_rcvbuf)) {
if(udp_rcvbuf <= 0) {
@ -584,21 +684,23 @@ static bool setup_myself(void) {
logger(LOG_ERR, "ReplayWindow cannot be negative!");
return false;
}
replaywin = (unsigned)replaywin_int;
}
if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname)) {
if(!strcasecmp(afname, "IPv4"))
if(!strcasecmp(afname, "IPv4")) {
addressfamily = AF_INET;
else if(!strcasecmp(afname, "IPv6"))
} else if(!strcasecmp(afname, "IPv6")) {
addressfamily = AF_INET6;
else if(!strcasecmp(afname, "any"))
} else if(!strcasecmp(afname, "any")) {
addressfamily = AF_UNSPEC;
else {
} else {
logger(LOG_ERR, "Invalid address family!");
free(afname);
return false;
}
free(afname);
}
@ -618,22 +720,42 @@ static bool setup_myself(void) {
return false;
}
}
free(cipher);
} else
myself->incipher = EVP_bf_cbc();
} else {
myself->incipher = EVP_aes_256_cbc();
}
if(myself->incipher)
myself->inkeylength = myself->incipher->key_len + myself->incipher->iv_len;
else
if(myself->incipher) {
myself->inkeylength = EVP_CIPHER_key_length(myself->incipher) + EVP_CIPHER_iv_length(myself->incipher);
} else {
myself->inkeylength = 1;
}
myself->connection->outcipher = EVP_bf_ofb();
/* We need to use a stream mode for the meta protocol. Use AES for this,
but try to match the key size with the one from the cipher selected
by Cipher.
if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime))
If Cipher is set to none, still use a low level of encryption for the
meta protocol.
*/
int keylen = myself->incipher ? EVP_CIPHER_key_length(myself->incipher) : 0;
if(keylen <= 16) {
myself->connection->outcipher = EVP_aes_128_cfb();
} else if(keylen <= 24) {
myself->connection->outcipher = EVP_aes_192_cfb();
} else {
myself->connection->outcipher = EVP_aes_256_cfb();
}
if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime)) {
keylifetime = 3600;
}
keyexpires = now + keylifetime;
/* Check if we want to use message authentication codes... */
if(get_config_string(lookup_config(config_tree, "Digest"), &digest)) {
@ -650,14 +772,15 @@ static bool setup_myself(void) {
}
free(digest);
} else
myself->indigest = EVP_sha1();
} else {
myself->indigest = EVP_sha256();
}
myself->connection->outdigest = EVP_sha1();
myself->connection->outdigest = EVP_sha256();
if(get_config_int(lookup_config(config_tree, "MACLength"), &myself->inmaclength)) {
if(myself->indigest) {
if(myself->inmaclength > myself->indigest->md_size) {
if(myself->inmaclength > EVP_MD_size(myself->indigest)) {
logger(LOG_ERR, "MAC length exceeds size of digest!");
return false;
} else if(myself->inmaclength < 0) {
@ -665,8 +788,9 @@ static bool setup_myself(void) {
return false;
}
}
} else
} else {
myself->inmaclength = 4;
}
myself->connection->outmaclength = 0;
@ -677,8 +801,9 @@ static bool setup_myself(void) {
logger(LOG_ERR, "Bogus compression level!");
return false;
}
} else
} else {
myself->incompression = 0;
}
myself->connection->outcompression = 0;
@ -691,38 +816,46 @@ static bool setup_myself(void) {
graph();
if(strictsubnets)
if(strictsubnets) {
load_all_subnets();
}
/* Open device */
devops = os_devops;
if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
if(!strcasecmp(type, "dummy"))
if(!strcasecmp(type, "dummy")) {
devops = dummy_devops;
else if(!strcasecmp(type, "raw_socket"))
} else if(!strcasecmp(type, "raw_socket")) {
devops = raw_socket_devops;
else if(!strcasecmp(type, "multicast"))
} else if(!strcasecmp(type, "multicast")) {
devops = multicast_devops;
}
#ifdef ENABLE_UML
else if(!strcasecmp(type, "uml"))
else if(!strcasecmp(type, "uml")) {
devops = uml_devops;
}
#endif
#ifdef ENABLE_VDE
else if(!strcasecmp(type, "vde"))
else if(!strcasecmp(type, "vde")) {
devops = vde_devops;
}
#endif
free(type);
}
if(!devops.setup())
if(!devops.setup()) {
return false;
}
/* Run tinc-up script to further initialize the tap interface */
xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
xasprintf(&envp[1], "DEVICE=%s", device ? : "");
xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
xasprintf(&envp[0], "NETNAME=%s", netname ? netname : "");
xasprintf(&envp[1], "DEVICE=%s", device ? device : "");
xasprintf(&envp[2], "INTERFACE=%s", iface ? iface : "");
xasprintf(&envp[3], "NAME=%s", myself->name);
#ifdef HAVE_MINGW
@ -733,8 +866,9 @@ static bool setup_myself(void) {
#endif
execute_script("tinc-up", envp);
for(i = 0; i < 4; i++)
for(i = 0; i < 4; i++) {
free(envp[i]);
}
/* Run subnet-up scripts for our own subnets */
@ -757,7 +891,8 @@ static bool setup_myself(void) {
}
for(i = 0; i < listen_sockets; i++) {
salen = sizeof sa;
salen = sizeof(sa);
if(getsockname(i + 3, &sa.sa, &salen) < 0) {
logger(LOG_ERR, "Could not get address of listen fd %d: %s", i + 3, sockstrerror(errno));
return false;
@ -766,12 +901,14 @@ static bool setup_myself(void) {
listen_socket[i].tcp = i + 3;
#ifdef FD_CLOEXEC
fcntl(i + 3, F_SETFD, FD_CLOEXEC);
fcntl(i + 3, F_SETFD, FD_CLOEXEC);
#endif
listen_socket[i].udp = setup_vpn_in_socket(&sa);
if(listen_socket[i].udp < 0)
if(listen_socket[i].udp < 0) {
return false;
}
ifdebug(CONNECTIONS) {
hostname = sockaddr2hostname(&sa);
@ -787,20 +924,24 @@ static bool setup_myself(void) {
do {
get_config_string(cfg, &address);
if(cfg)
if(cfg) {
cfg = lookup_config_next(config_tree, cfg);
}
char *port = myport;
if(address) {
char *space = strchr(address, ' ');
if(space) {
*space++ = 0;
port = space;
}
if(!strcmp(address, "*"))
if(!strcmp(address, "*")) {
*address = 0;
}
}
hint.ai_family = addressfamily;
@ -817,7 +958,7 @@ static bool setup_myself(void) {
if(err || !ai) {
logger(LOG_ERR, "System call `%s' failed: %s", "getaddrinfo",
gai_strerror(err));
gai_strerror(err));
return false;
}
@ -828,16 +969,18 @@ static bool setup_myself(void) {
}
listen_socket[listen_sockets].tcp =
setup_listen_socket((sockaddr_t *) aip->ai_addr);
setup_listen_socket((sockaddr_t *) aip->ai_addr);
if(listen_socket[listen_sockets].tcp < 0)
if(listen_socket[listen_sockets].tcp < 0) {
continue;
}
listen_socket[listen_sockets].udp =
setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);
setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);
if(listen_socket[listen_sockets].udp < 0)
if(listen_socket[listen_sockets].udp < 0) {
continue;
}
ifdebug(CONNECTIONS) {
hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr);
@ -862,12 +1005,15 @@ static bool setup_myself(void) {
if(!port_specified) {
sockaddr_t sa;
socklen_t salen = sizeof sa;
socklen_t salen = sizeof(sa);
if(!getsockname(listen_socket[0].udp, &sa.sa, &salen)) {
free(myport);
sockaddr2str(&sa, NULL, &myport);
if(!myport)
if(!myport) {
myport = xstrdup("655");
}
}
}
@ -894,19 +1040,25 @@ bool setup_network(void) {
if(pinginterval < 1) {
pinginterval = 86400;
}
} else
} else {
pinginterval = 60;
}
if(!get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout))
if(!get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout)) {
pingtimeout = 5;
if(pingtimeout < 1 || pingtimeout > pinginterval)
}
if(pingtimeout < 1 || pingtimeout > pinginterval) {
pingtimeout = pinginterval;
}
if(!get_config_int(lookup_config(config_tree, "MaxOutputBufferSize"), &maxoutbufsize))
if(!get_config_int(lookup_config(config_tree, "MaxOutputBufferSize"), &maxoutbufsize)) {
maxoutbufsize = 10 * MTU;
}
if(!setup_myself())
if(!setup_myself()) {
return false;
}
return true;
}
@ -917,7 +1069,7 @@ bool setup_network(void) {
void close_network_connections(void) {
avl_node_t *node, *next;
connection_t *c;
char *envp[5] = {NULL};
char *envp[5] = {0};
int i;
for(node = connection_tree->head; node; node = next) {
@ -930,8 +1082,9 @@ void close_network_connections(void) {
for(list_node_t *node = outgoing_list->head; node; node = node->next) {
outgoing_t *outgoing = node->data;
if(outgoing->event)
if(outgoing->event) {
event_del(outgoing->event);
}
}
list_delete_list(outgoing_list);
@ -947,9 +1100,9 @@ void close_network_connections(void) {
close(listen_socket[i].udp);
}
xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
xasprintf(&envp[1], "DEVICE=%s", device ? : "");
xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
xasprintf(&envp[0], "NETNAME=%s", netname ? netname : "");
xasprintf(&envp[1], "DEVICE=%s", device ? device : "");
xasprintf(&envp[2], "INTERFACE=%s", iface ? iface : "");
xasprintf(&envp[3], "NAME=%s", myself->name);
exit_requests();
@ -961,10 +1114,13 @@ void close_network_connections(void) {
execute_script("tinc-down", envp);
if(myport) free(myport);
if(myport) {
free(myport);
}
for(i = 0; i < 4; i++)
for(i = 0; i < 4; i++) {
free(envp[i]);
}
devops.close();

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