Import Upstream version 1.0.33
This commit is contained in:
parent
e0e55285b8
commit
5969674c46
109 changed files with 5599 additions and 5444 deletions
89
ChangeLog
89
ChangeLog
|
@ -1,3 +1,45 @@
|
||||||
|
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
|
Version 1.0.32 September 02 2017
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -183,7 +225,20 @@ VittGam (1):
|
||||||
Version 1.0.24 May 11 2014
|
Version 1.0.24 May 11 2014
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
Guus Sliepen (13):
|
Guus Sliepen (26):
|
||||||
|
Mention in the manual that multiple Address staments are allowed.
|
||||||
|
If no Port is specified, set myport to actual port of first listening socket.
|
||||||
|
Enable compiler hardening flags by default.
|
||||||
|
Update support for Solaris.
|
||||||
|
Include <limits.h> for PATH_MAX.
|
||||||
|
Stricter check for raw socket support.
|
||||||
|
Use hardcoded value for TUNNEWPPA if net/if_tun.h is missing on Solaris.
|
||||||
|
Fix incorrectly merged bits from 80cd2ff73071941a5356555b85a00ee90dfd0e16.
|
||||||
|
Don't enable -fstack-protector-all.
|
||||||
|
Remove or lower the priority of some debug messages.
|
||||||
|
Clarify StrictSubnets.
|
||||||
|
Attribution for various contributors.
|
||||||
|
Handle errors from TAP-Win32/64 adapter in a better way.
|
||||||
Remove useless variable 'hard' from try_harder().
|
Remove useless variable 'hard' from try_harder().
|
||||||
Merge pull request #14 from luckyhacky/master
|
Merge pull request #14 from luckyhacky/master
|
||||||
Add an autoconf check for res_init().
|
Add an autoconf check for res_init().
|
||||||
|
@ -203,40 +258,22 @@ Steffan Karger (3):
|
||||||
Use cryptographically strong random when generating keys.
|
Use cryptographically strong random when generating keys.
|
||||||
Check RAND_bytes() return value, fail when getting random fails.
|
Check RAND_bytes() return value, fail when getting random fails.
|
||||||
|
|
||||||
|
Florent Clairambault (2):
|
||||||
|
Adding "conf.d" configuration dir support.
|
||||||
|
Adding some documentation around the /etc/tinc/$NET/conf.d directory.
|
||||||
|
|
||||||
Armin Fisslthaler (1):
|
Armin Fisslthaler (1):
|
||||||
reload /etc/resolv.conf in SIGALRM handler
|
reload /etc/resolv.conf in SIGALRM handler
|
||||||
|
|
||||||
Loic Dachary (1):
|
Loic Dachary (1):
|
||||||
fix documentation typo
|
fix documentation typo
|
||||||
|
|
||||||
luckyhacky (1):
|
|
||||||
update to openssl version 1.0.1g due to lack of heartbleed bug in prior version of openssl
|
|
||||||
|
|
||||||
refs/tags/1.0.23-android-1 March 11 2014
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Guus Sliepen (13):
|
|
||||||
Mention in the manual that multiple Address staments are allowed.
|
|
||||||
If no Port is specified, set myport to actual port of first listening socket.
|
|
||||||
Enable compiler hardening flags by default.
|
|
||||||
Update support for Solaris.
|
|
||||||
Include <limits.h> for PATH_MAX.
|
|
||||||
Stricter check for raw socket support.
|
|
||||||
Use hardcoded value for TUNNEWPPA if net/if_tun.h is missing on Solaris.
|
|
||||||
Fix incorrectly merged bits from 80cd2ff73071941a5356555b85a00ee90dfd0e16.
|
|
||||||
Don't enable -fstack-protector-all.
|
|
||||||
Remove or lower the priority of some debug messages.
|
|
||||||
Clarify StrictSubnets.
|
|
||||||
Attribution for various contributors.
|
|
||||||
Handle errors from TAP-Win32/64 adapter in a better way.
|
|
||||||
|
|
||||||
Florent Clairambault (2):
|
|
||||||
Adding "conf.d" configuration dir support.
|
|
||||||
Adding some documentation around the /etc/tinc/$NET/conf.d directory.
|
|
||||||
|
|
||||||
Vilbrekin (1):
|
Vilbrekin (1):
|
||||||
Update android build instructions. Disable PIE as this is not supported on some devices.
|
Update android build instructions. Disable PIE as this is not supported on some devices.
|
||||||
|
|
||||||
|
luckyhacky (1):
|
||||||
|
update to openssl version 1.0.1g due to lack of heartbleed bug in prior version of openssl
|
||||||
|
|
||||||
Version 1.0.23 October 19 2013
|
Version 1.0.23 October 19 2013
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
AUTOMAKE_OPTIONS = gnu
|
AUTOMAKE_OPTIONS = gnu
|
||||||
|
|
||||||
SUBDIRS = m4 src doc distro
|
SUBDIRS = src doc distro
|
||||||
|
|
||||||
ACLOCAL_AMFLAGS = -I m4
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
|
||||||
|
@ -10,3 +10,6 @@ EXTRA_DIST = COPYING.README README.android
|
||||||
|
|
||||||
ChangeLog:
|
ChangeLog:
|
||||||
git log > ChangeLog
|
git log > ChangeLog
|
||||||
|
|
||||||
|
astyle:
|
||||||
|
astyle --options=.astylerc -nQ src/*.[ch] src/*/*.[ch]
|
||||||
|
|
14
Makefile.in
14
Makefile.in
|
@ -239,7 +239,6 @@ LDFLAGS = @LDFLAGS@
|
||||||
LIBOBJS = @LIBOBJS@
|
LIBOBJS = @LIBOBJS@
|
||||||
LIBS = @LIBS@
|
LIBS = @LIBS@
|
||||||
LTLIBOBJS = @LTLIBOBJS@
|
LTLIBOBJS = @LTLIBOBJS@
|
||||||
MAINT = @MAINT@
|
|
||||||
MAKEINFO = @MAKEINFO@
|
MAKEINFO = @MAKEINFO@
|
||||||
MKDIR_P = @MKDIR_P@
|
MKDIR_P = @MKDIR_P@
|
||||||
OBJEXT = @OBJEXT@
|
OBJEXT = @OBJEXT@
|
||||||
|
@ -311,7 +310,7 @@ top_build_prefix = @top_build_prefix@
|
||||||
top_builddir = @top_builddir@
|
top_builddir = @top_builddir@
|
||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
AUTOMAKE_OPTIONS = gnu
|
AUTOMAKE_OPTIONS = gnu
|
||||||
SUBDIRS = m4 src doc distro
|
SUBDIRS = src doc distro
|
||||||
ACLOCAL_AMFLAGS = -I m4
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
EXTRA_DIST = COPYING.README README.android
|
EXTRA_DIST = COPYING.README README.android
|
||||||
all: config.h
|
all: config.h
|
||||||
|
@ -320,7 +319,7 @@ all: config.h
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
am--refresh: Makefile
|
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 \
|
@for dep in $?; do \
|
||||||
case '$(am__configure_deps)' in \
|
case '$(am__configure_deps)' in \
|
||||||
*$$dep*) \
|
*$$dep*) \
|
||||||
|
@ -346,9 +345,9 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||||
$(SHELL) ./config.status --recheck
|
$(SHELL) ./config.status --recheck
|
||||||
|
|
||||||
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
$(top_srcdir)/configure: $(am__configure_deps)
|
||||||
$(am__cd) $(srcdir) && $(AUTOCONF)
|
$(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__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
|
||||||
$(am__aclocal_m4_deps):
|
$(am__aclocal_m4_deps):
|
||||||
|
|
||||||
|
@ -359,7 +358,7 @@ config.h: stamp-h1
|
||||||
stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
|
stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
|
||||||
@rm -f stamp-h1
|
@rm -f stamp-h1
|
||||||
cd $(top_builddir) && $(SHELL) ./config.status config.h
|
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))
|
($(am__cd) $(top_srcdir) && $(AUTOHEADER))
|
||||||
rm -f stamp-h1
|
rm -f stamp-h1
|
||||||
touch $@
|
touch $@
|
||||||
|
@ -795,6 +794,9 @@ uninstall-am:
|
||||||
ChangeLog:
|
ChangeLog:
|
||||||
git log > 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.
|
# 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.
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
.NOEXPORT:
|
.NOEXPORT:
|
||||||
|
|
9
NEWS
9
NEWS
|
@ -1,3 +1,12 @@
|
||||||
|
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.
|
||||||
|
|
||||||
Version 1.0.32 September 2 2017
|
Version 1.0.32 September 2 2017
|
||||||
|
|
||||||
* Fix segmentation fault when using Cipher = none.
|
* Fix segmentation fault when using Cipher = none.
|
||||||
|
|
2
README
2
README
|
@ -1,4 +1,4 @@
|
||||||
This is the README file for tinc version 1.0.32. Installation
|
This is the README file for tinc version 1.0.33. Installation
|
||||||
instructions may be found in the INSTALL file.
|
instructions may be found in the INSTALL file.
|
||||||
|
|
||||||
tinc is Copyright (C) 1998-2017 by:
|
tinc is Copyright (C) 1998-2017 by:
|
||||||
|
|
30
THANKS
30
THANKS
|
@ -1,25 +1,36 @@
|
||||||
We would like to thank the following people for their contributions to tinc:
|
We would like to thank the following people for their contributions to tinc:
|
||||||
|
|
||||||
* Alexander Reil and Gemeinde Berg
|
* Alexander Reil and Gemeinde Berg
|
||||||
|
* Alexander Ried
|
||||||
* Alexis Hildebrandt
|
* Alexis Hildebrandt
|
||||||
* Allesandro Gatti
|
* Allesandro Gatti
|
||||||
* Andreas van Cranenburgh
|
* Andreas van Cranenburgh
|
||||||
* Anthony G. Basile
|
* Anthony G. Basile
|
||||||
* Armin Fisslthaler
|
|
||||||
* Armijn Hemel
|
* Armijn Hemel
|
||||||
|
* Armin Fisslthaler
|
||||||
|
* Aron Cowan
|
||||||
|
* Ashish Bajaj
|
||||||
* Baptiste Jonglez
|
* Baptiste Jonglez
|
||||||
* Borg
|
* Borg
|
||||||
* Brandon Black
|
* Brandon Black
|
||||||
|
* Cheng LI
|
||||||
* Cris van Pelt
|
* Cris van Pelt
|
||||||
* Darius Jahandarie
|
* Darius Jahandarie
|
||||||
|
* Dato Simó
|
||||||
* David Pflug
|
* David Pflug
|
||||||
* Delf Eldkraft
|
* Delf Eldkraft
|
||||||
|
* Dennis Joachimsthaler
|
||||||
* dnk
|
* dnk
|
||||||
* Élie Bouttier
|
* Élie Bouttier
|
||||||
* Enrique Zanardi
|
* Enrique Zanardi
|
||||||
|
* Erik Tews
|
||||||
|
* Etienne Dechamps
|
||||||
* Florent Clairambault
|
* Florent Clairambault
|
||||||
|
* Florian Forster
|
||||||
|
* Florian Klink
|
||||||
* Florian Weik
|
* Florian Weik
|
||||||
* Flynn Marquardt
|
* Flynn Marquardt
|
||||||
|
* Franz Pletz
|
||||||
* Gary Kessler and Claudia Gonzalez
|
* Gary Kessler and Claudia Gonzalez
|
||||||
* Grzegorz Dymarek
|
* Grzegorz Dymarek
|
||||||
* Gusariev Oleksandr
|
* Gusariev Oleksandr
|
||||||
|
@ -43,6 +54,7 @@ We would like to thank the following people for their contributions to tinc:
|
||||||
* Loïc Dachary
|
* Loïc Dachary
|
||||||
* Loïc Grenié
|
* Loïc Grenié
|
||||||
* Lubomír Bulej
|
* Lubomír Bulej
|
||||||
|
* luckyhacky
|
||||||
* LunarShaddow
|
* LunarShaddow
|
||||||
* Mads Kiilerich
|
* Mads Kiilerich
|
||||||
* Marc A. Lehmann
|
* Marc A. Lehmann
|
||||||
|
@ -52,6 +64,7 @@ We would like to thank the following people for their contributions to tinc:
|
||||||
* Martin Kihlgren
|
* Martin Kihlgren
|
||||||
* Martin Schobert
|
* Martin Schobert
|
||||||
* Martin Schürrer
|
* Martin Schürrer
|
||||||
|
* Martin Weinelt
|
||||||
* Matias Carrasco
|
* Matias Carrasco
|
||||||
* Max Rijevski
|
* Max Rijevski
|
||||||
* Menno Smits
|
* Menno Smits
|
||||||
|
@ -59,14 +72,21 @@ We would like to thank the following people for their contributions to tinc:
|
||||||
* Michael Tokarev
|
* Michael Tokarev
|
||||||
* Miles Nordin
|
* Miles Nordin
|
||||||
* Nathan Stratton Treadway
|
* Nathan Stratton Treadway
|
||||||
|
* Murat Donmez
|
||||||
* Nick Hibma
|
* Nick Hibma
|
||||||
* Nick Patavalis
|
* Nick Patavalis
|
||||||
* Paul Littlefield
|
* Paul Littlefield
|
||||||
* Philipp Babel
|
* Philipp Babel
|
||||||
|
* Pierre Emeriaud
|
||||||
|
* Pierre-Olivier Mercier
|
||||||
|
* Rafael Sadowski
|
||||||
|
* Rafał Leśniak
|
||||||
* Rhosyn Celyn
|
* Rhosyn Celyn
|
||||||
* Robert van der Meulen
|
* Robert van der Meulen
|
||||||
* Rumko
|
* Rumko
|
||||||
|
* Ryan Miller
|
||||||
* Sam Bryan
|
* Sam Bryan
|
||||||
|
* Samuel Thibault
|
||||||
* Saverio Proto
|
* Saverio Proto
|
||||||
* Scott Lamb
|
* Scott Lamb
|
||||||
* Steffan Karger
|
* Steffan Karger
|
||||||
|
@ -82,12 +102,16 @@ We would like to thank the following people for their contributions to tinc:
|
||||||
* Ulrich Seifert
|
* Ulrich Seifert
|
||||||
* Vil Brekin
|
* Vil Brekin
|
||||||
* Vittorio Gambaletta
|
* Vittorio Gambaletta
|
||||||
|
* Wendy Willard
|
||||||
* Wessel Dankers
|
* Wessel Dankers
|
||||||
|
* William A. Kennington III
|
||||||
* William McArthur
|
* William McArthur
|
||||||
* Wouter van Heyst
|
* Wouter van Heyst
|
||||||
|
* xentec
|
||||||
* 戴 鸣
|
* 戴 鸣
|
||||||
|
|
||||||
And everyone we forgot (if we did, please let us know). Thank you!
|
And everyone we forgot (if we did, please let us know). Thank you!
|
||||||
|
|
||||||
Ivo Timmermans
|
---
|
||||||
Guus Sliepen
|
Ivo Timmermans,
|
||||||
|
Guus Sliepen.
|
||||||
|
|
36
aclocal.m4
vendored
36
aclocal.m4
vendored
|
@ -921,42 +921,6 @@ fi
|
||||||
rmdir .tst 2>/dev/null
|
rmdir .tst 2>/dev/null
|
||||||
AC_SUBST([am__leading_dot])])
|
AC_SUBST([am__leading_dot])])
|
||||||
|
|
||||||
# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
|
|
||||||
# From Jim Meyering
|
|
||||||
|
|
||||||
# Copyright (C) 1996-2017 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 -*-
|
# Check to see how 'make' treats includes. -*- Autoconf -*-
|
||||||
|
|
||||||
# Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
# Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||||
|
|
49
config.h.in
49
config.h.in
|
@ -73,9 +73,6 @@
|
||||||
/* DragonFly */
|
/* DragonFly */
|
||||||
#undef HAVE_DRAGONFLY
|
#undef HAVE_DRAGONFLY
|
||||||
|
|
||||||
/* Define to 1 if you have the `ERR_remove_state' function. */
|
|
||||||
#undef HAVE_ERR_REMOVE_STATE
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `EVP_CIPHER_CTX_new' function. */
|
/* Define to 1 if you have the `EVP_CIPHER_CTX_new' function. */
|
||||||
#undef HAVE_EVP_CIPHER_CTX_NEW
|
#undef HAVE_EVP_CIPHER_CTX_NEW
|
||||||
|
|
||||||
|
@ -97,9 +94,6 @@
|
||||||
/* FreeBSD */
|
/* FreeBSD */
|
||||||
#undef HAVE_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. */
|
/* Define to 1 if you have the <getopt.h> header file. */
|
||||||
#undef HAVE_GETOPT_H
|
#undef HAVE_GETOPT_H
|
||||||
|
|
||||||
|
@ -109,9 +103,6 @@
|
||||||
/* Define to 1 if you have the `gettimeofday' function. */
|
/* Define to 1 if you have the `gettimeofday' function. */
|
||||||
#undef HAVE_GETTIMEOFDAY
|
#undef HAVE_GETTIMEOFDAY
|
||||||
|
|
||||||
/* Define to 1 if you have the `get_current_dir_name' function. */
|
|
||||||
#undef HAVE_GET_CURRENT_DIR_NAME
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||||
#undef HAVE_INTTYPES_H
|
#undef HAVE_INTTYPES_H
|
||||||
|
|
||||||
|
@ -247,9 +238,6 @@
|
||||||
/* Define to 1 if you have the `putenv' function. */
|
/* Define to 1 if you have the `putenv' function. */
|
||||||
#undef HAVE_PUTENV
|
#undef HAVE_PUTENV
|
||||||
|
|
||||||
/* Define to 1 if you have the `random' function. */
|
|
||||||
#undef HAVE_RANDOM
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `RAND_bytes' function. */
|
/* Define to 1 if you have the `RAND_bytes' function. */
|
||||||
#undef HAVE_RAND_BYTES
|
#undef HAVE_RAND_BYTES
|
||||||
|
|
||||||
|
@ -259,30 +247,18 @@
|
||||||
/* Define to 1 if you have the `RSA_set0_key' function. */
|
/* Define to 1 if you have the `RSA_set0_key' function. */
|
||||||
#undef HAVE_RSA_SET0_KEY
|
#undef HAVE_RSA_SET0_KEY
|
||||||
|
|
||||||
/* Define to 1 if you have the `select' function. */
|
|
||||||
#undef HAVE_SELECT
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `socklen_t'. */
|
/* Define to 1 if the system has the type `socklen_t'. */
|
||||||
#undef HAVE_SOCKLEN_T
|
#undef HAVE_SOCKLEN_T
|
||||||
|
|
||||||
/* Solaris/SunOS */
|
/* Solaris/SunOS */
|
||||||
#undef HAVE_SOLARIS
|
#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. */
|
/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
#undef HAVE_STDINT_H
|
#undef HAVE_STDINT_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
#undef HAVE_STDLIB_H
|
#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. */
|
/* Define to 1 if you have the <strings.h> header file. */
|
||||||
#undef HAVE_STRINGS_H
|
#undef HAVE_STRINGS_H
|
||||||
|
|
||||||
|
@ -292,9 +268,6 @@
|
||||||
/* Define to 1 if you have the `strsignal' function. */
|
/* Define to 1 if you have the `strsignal' function. */
|
||||||
#undef HAVE_STRSIGNAL
|
#undef HAVE_STRSIGNAL
|
||||||
|
|
||||||
/* Define to 1 if you have the `strtol' function. */
|
|
||||||
#undef HAVE_STRTOL
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `struct addrinfo'. */
|
/* Define to 1 if the system has the type `struct addrinfo'. */
|
||||||
#undef HAVE_STRUCT_ADDRINFO
|
#undef HAVE_STRUCT_ADDRINFO
|
||||||
|
|
||||||
|
@ -373,9 +346,6 @@
|
||||||
/* Define to 1 if you have the <sys/wait.h> header file. */
|
/* Define to 1 if you have the <sys/wait.h> header file. */
|
||||||
#undef HAVE_SYS_WAIT_H
|
#undef HAVE_SYS_WAIT_H
|
||||||
|
|
||||||
/* 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. */
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
#undef HAVE_UNISTD_H
|
#undef HAVE_UNISTD_H
|
||||||
|
|
||||||
|
@ -388,9 +358,6 @@
|
||||||
/* Define to 1 if you have the `vsyslog' function. */
|
/* Define to 1 if you have the `vsyslog' function. */
|
||||||
#undef HAVE_VSYSLOG
|
#undef HAVE_VSYSLOG
|
||||||
|
|
||||||
/* Define to 1 if you have the `writev' function. */
|
|
||||||
#undef HAVE_WRITEV
|
|
||||||
|
|
||||||
/* have zlib compression support */
|
/* have zlib compression support */
|
||||||
#undef HAVE_ZLIB
|
#undef HAVE_ZLIB
|
||||||
|
|
||||||
|
@ -427,12 +394,6 @@
|
||||||
/* Define to 1 if you have the ANSI C header files. */
|
/* Define to 1 if you have the ANSI C header files. */
|
||||||
#undef STDC_HEADERS
|
#undef STDC_HEADERS
|
||||||
|
|
||||||
/* 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. */
|
/* Enable extensions on AIX 3, Interix. */
|
||||||
#ifndef _ALL_SOURCE
|
#ifndef _ALL_SOURCE
|
||||||
# undef _ALL_SOURCE
|
# undef _ALL_SOURCE
|
||||||
|
@ -477,15 +438,5 @@
|
||||||
/* Defined if the __malloc__ attribute is not supported. */
|
/* Defined if the __malloc__ attribute is not supported. */
|
||||||
#undef __malloc__
|
#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. */
|
/* Define to `int' if <sys/types.h> does not define. */
|
||||||
#undef pid_t
|
#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
|
|
||||||
|
|
417
configure
vendored
417
configure
vendored
|
@ -1,6 +1,6 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Guess values for system-dependent variables and create Makefiles.
|
# Guess values for system-dependent variables and create Makefiles.
|
||||||
# Generated by GNU Autoconf 2.69 for tinc 1.0.32.
|
# Generated by GNU Autoconf 2.69 for tinc 1.0.33.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
||||||
|
@ -577,8 +577,8 @@ MAKEFLAGS=
|
||||||
# Identity of this package.
|
# Identity of this package.
|
||||||
PACKAGE_NAME='tinc'
|
PACKAGE_NAME='tinc'
|
||||||
PACKAGE_TARNAME='tinc'
|
PACKAGE_TARNAME='tinc'
|
||||||
PACKAGE_VERSION='1.0.32'
|
PACKAGE_VERSION='1.0.33'
|
||||||
PACKAGE_STRING='tinc 1.0.32'
|
PACKAGE_STRING='tinc 1.0.33'
|
||||||
PACKAGE_BUGREPORT=''
|
PACKAGE_BUGREPORT=''
|
||||||
PACKAGE_URL=''
|
PACKAGE_URL=''
|
||||||
|
|
||||||
|
@ -675,9 +675,6 @@ CPPFLAGS
|
||||||
LDFLAGS
|
LDFLAGS
|
||||||
CFLAGS
|
CFLAGS
|
||||||
CC
|
CC
|
||||||
MAINT
|
|
||||||
MAINTAINER_MODE_FALSE
|
|
||||||
MAINTAINER_MODE_TRUE
|
|
||||||
AM_BACKSLASH
|
AM_BACKSLASH
|
||||||
AM_DEFAULT_VERBOSITY
|
AM_DEFAULT_VERBOSITY
|
||||||
AM_DEFAULT_V
|
AM_DEFAULT_V
|
||||||
|
@ -748,7 +745,6 @@ ac_subst_files=''
|
||||||
ac_user_opts='
|
ac_user_opts='
|
||||||
enable_option_checking
|
enable_option_checking
|
||||||
enable_silent_rules
|
enable_silent_rules
|
||||||
enable_maintainer_mode
|
|
||||||
enable_dependency_tracking
|
enable_dependency_tracking
|
||||||
enable_uml
|
enable_uml
|
||||||
enable_vde
|
enable_vde
|
||||||
|
@ -1331,7 +1327,7 @@ if test "$ac_init_help" = "long"; then
|
||||||
# Omit some internal or obsolete options to make the list less imposing.
|
# Omit some internal or obsolete options to make the list less imposing.
|
||||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||||
cat <<_ACEOF
|
cat <<_ACEOF
|
||||||
\`configure' configures tinc 1.0.32 to adapt to many kinds of systems.
|
\`configure' configures tinc 1.0.33 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
|
@ -1402,7 +1398,7 @@ fi
|
||||||
|
|
||||||
if test -n "$ac_init_help"; then
|
if test -n "$ac_init_help"; then
|
||||||
case $ac_init_help in
|
case $ac_init_help in
|
||||||
short | recursive ) echo "Configuration of tinc 1.0.32:";;
|
short | recursive ) echo "Configuration of tinc 1.0.33:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
|
@ -1412,9 +1408,6 @@ Optional Features:
|
||||||
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
|
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
|
||||||
--enable-silent-rules less verbose build output (undo: "make V=1")
|
--enable-silent-rules less verbose build output (undo: "make V=1")
|
||||||
--disable-silent-rules verbose build output (undo: "make V=0")
|
--disable-silent-rules verbose build output (undo: "make V=0")
|
||||||
--enable-maintainer-mode
|
|
||||||
enable make rules and dependencies not useful (and
|
|
||||||
sometimes confusing) to the casual installer
|
|
||||||
--enable-dependency-tracking
|
--enable-dependency-tracking
|
||||||
do not reject slow dependency extractors
|
do not reject slow dependency extractors
|
||||||
--disable-dependency-tracking
|
--disable-dependency-tracking
|
||||||
|
@ -1528,7 +1521,7 @@ fi
|
||||||
test -n "$ac_init_help" && exit $ac_status
|
test -n "$ac_init_help" && exit $ac_status
|
||||||
if $ac_init_version; then
|
if $ac_init_version; then
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
tinc configure 1.0.32
|
tinc configure 1.0.33
|
||||||
generated by GNU Autoconf 2.69
|
generated by GNU Autoconf 2.69
|
||||||
|
|
||||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||||
|
@ -1993,7 +1986,7 @@ cat >config.log <<_ACEOF
|
||||||
This file contains any messages produced by compilers while
|
This file contains any messages produced by compilers while
|
||||||
running configure, to aid debugging if configure makes a mistake.
|
running configure, to aid debugging if configure makes a mistake.
|
||||||
|
|
||||||
It was created by tinc $as_me 1.0.32, which was
|
It was created by tinc $as_me 1.0.33, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
|
@ -2857,7 +2850,7 @@ fi
|
||||||
|
|
||||||
# Define the identity of the package.
|
# Define the identity of the package.
|
||||||
PACKAGE='tinc'
|
PACKAGE='tinc'
|
||||||
VERSION='1.0.32'
|
VERSION='1.0.33'
|
||||||
|
|
||||||
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
|
@ -2953,28 +2946,6 @@ fi
|
||||||
ac_config_headers="$ac_config_headers config.h"
|
ac_config_headers="$ac_config_headers config.h"
|
||||||
|
|
||||||
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
|
|
||||||
$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
|
|
||||||
# Check whether --enable-maintainer-mode was given.
|
|
||||||
if test "${enable_maintainer_mode+set}" = set; then :
|
|
||||||
enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
|
|
||||||
else
|
|
||||||
USE_MAINTAINER_MODE=no
|
|
||||||
fi
|
|
||||||
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
|
|
||||||
$as_echo "$USE_MAINTAINER_MODE" >&6; }
|
|
||||||
if test $USE_MAINTAINER_MODE = yes; then
|
|
||||||
MAINTAINER_MODE_TRUE=
|
|
||||||
MAINTAINER_MODE_FALSE='#'
|
|
||||||
else
|
|
||||||
MAINTAINER_MODE_TRUE='#'
|
|
||||||
MAINTAINER_MODE_FALSE=
|
|
||||||
fi
|
|
||||||
|
|
||||||
MAINT=$MAINTAINER_MODE_TRUE
|
|
||||||
|
|
||||||
|
|
||||||
# Check whether --enable-silent-rules was given.
|
# Check whether --enable-silent-rules was given.
|
||||||
if test "${enable_silent_rules+set}" = set; then :
|
if test "${enable_silent_rules+set}" = set; then :
|
||||||
enableval=$enable_silent_rules;
|
enableval=$enable_silent_rules;
|
||||||
|
@ -5786,119 +5757,7 @@ fi;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
|
for ac_header in 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
|
||||||
$as_echo_n "checking for ANSI C header files... " >&6; }
|
|
||||||
if ${ac_cv_header_stdc+:} false; then :
|
|
||||||
$as_echo_n "(cached) " >&6
|
|
||||||
else
|
|
||||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
|
||||||
/* end confdefs.h. */
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <float.h>
|
|
||||||
|
|
||||||
int
|
|
||||||
main ()
|
|
||||||
{
|
|
||||||
|
|
||||||
;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
_ACEOF
|
|
||||||
if ac_fn_c_try_compile "$LINENO"; then :
|
|
||||||
ac_cv_header_stdc=yes
|
|
||||||
else
|
|
||||||
ac_cv_header_stdc=no
|
|
||||||
fi
|
|
||||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
|
||||||
|
|
||||||
if test $ac_cv_header_stdc = yes; then
|
|
||||||
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
|
|
||||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
|
||||||
/* end confdefs.h. */
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
_ACEOF
|
|
||||||
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
|
|
||||||
$EGREP "memchr" >/dev/null 2>&1; then :
|
|
||||||
|
|
||||||
else
|
|
||||||
ac_cv_header_stdc=no
|
|
||||||
fi
|
|
||||||
rm -f conftest*
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test $ac_cv_header_stdc = yes; then
|
|
||||||
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
|
|
||||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
|
||||||
/* end confdefs.h. */
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
_ACEOF
|
|
||||||
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
|
|
||||||
$EGREP "free" >/dev/null 2>&1; then :
|
|
||||||
|
|
||||||
else
|
|
||||||
ac_cv_header_stdc=no
|
|
||||||
fi
|
|
||||||
rm -f conftest*
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test $ac_cv_header_stdc = yes; then
|
|
||||||
# /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
|
|
||||||
if test "$cross_compiling" = yes; then :
|
|
||||||
:
|
|
||||||
else
|
|
||||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
|
||||||
/* end confdefs.h. */
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#if ((' ' & 0x0FF) == 0x020)
|
|
||||||
# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
|
|
||||||
# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
|
|
||||||
#else
|
|
||||||
# define ISLOWER(c) \
|
|
||||||
(('a' <= (c) && (c) <= 'i') \
|
|
||||||
|| ('j' <= (c) && (c) <= 'r') \
|
|
||||||
|| ('s' <= (c) && (c) <= 'z'))
|
|
||||||
# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
|
|
||||||
int
|
|
||||||
main ()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < 256; i++)
|
|
||||||
if (XOR (islower (i), ISLOWER (i))
|
|
||||||
|| toupper (i) != TOUPPER (i))
|
|
||||||
return 2;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
_ACEOF
|
|
||||||
if ac_fn_c_try_run "$LINENO"; then :
|
|
||||||
|
|
||||||
else
|
|
||||||
ac_cv_header_stdc=no
|
|
||||||
fi
|
|
||||||
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
|
|
||||||
conftest.$ac_objext conftest.beam conftest.$ac_ext
|
|
||||||
fi
|
|
||||||
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
|
|
||||||
$as_echo "$ac_cv_header_stdc" >&6; }
|
|
||||||
if test $ac_cv_header_stdc = yes; then
|
|
||||||
|
|
||||||
$as_echo "#define STDC_HEADERS 1" >>confdefs.h
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
for ac_header in 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
|
|
||||||
do :
|
do :
|
||||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||||
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
||||||
|
@ -5914,7 +5773,7 @@ done
|
||||||
for ac_header in 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
|
for ac_header in 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
|
||||||
do :
|
do :
|
||||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||||
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include \"src/have.h\"
|
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include \"$srcdir/src/have.h\"
|
||||||
|
|
||||||
"
|
"
|
||||||
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
|
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
|
||||||
|
@ -5929,7 +5788,7 @@ done
|
||||||
for ac_header in netinet/if_ether.h netinet/ip.h netinet/ip6.h resolv.h
|
for ac_header in netinet/if_ether.h netinet/ip.h netinet/ip6.h resolv.h
|
||||||
do :
|
do :
|
||||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||||
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include \"src/have.h\"
|
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include \"$srcdir/src/have.h\"
|
||||||
|
|
||||||
"
|
"
|
||||||
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
|
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
|
||||||
|
@ -5944,7 +5803,7 @@ done
|
||||||
for ac_header in netinet/tcp.h netinet/ip_icmp.h netinet/icmp6.h
|
for ac_header in netinet/tcp.h netinet/ip_icmp.h netinet/icmp6.h
|
||||||
do :
|
do :
|
||||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||||
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include \"src/have.h\"
|
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include \"$srcdir/src/have.h\"
|
||||||
|
|
||||||
"
|
"
|
||||||
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
|
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
|
||||||
|
@ -5957,121 +5816,6 @@ fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5
|
|
||||||
$as_echo_n "checking for an ANSI C-conforming const... " >&6; }
|
|
||||||
if ${ac_cv_c_const+:} false; then :
|
|
||||||
$as_echo_n "(cached) " >&6
|
|
||||||
else
|
|
||||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
|
||||||
/* end confdefs.h. */
|
|
||||||
|
|
||||||
int
|
|
||||||
main ()
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifndef __cplusplus
|
|
||||||
/* Ultrix mips cc rejects this sort of thing. */
|
|
||||||
typedef int charset[2];
|
|
||||||
const charset cs = { 0, 0 };
|
|
||||||
/* SunOS 4.1.1 cc rejects this. */
|
|
||||||
char const *const *pcpcc;
|
|
||||||
char **ppc;
|
|
||||||
/* NEC SVR4.0.2 mips cc rejects this. */
|
|
||||||
struct point {int x, y;};
|
|
||||||
static struct point const zero = {0,0};
|
|
||||||
/* AIX XL C 1.02.0.0 rejects this.
|
|
||||||
It does not let you subtract one const X* pointer from another in
|
|
||||||
an arm of an if-expression whose if-part is not a constant
|
|
||||||
expression */
|
|
||||||
const char *g = "string";
|
|
||||||
pcpcc = &g + (g ? g-g : 0);
|
|
||||||
/* HPUX 7.0 cc rejects these. */
|
|
||||||
++pcpcc;
|
|
||||||
ppc = (char**) pcpcc;
|
|
||||||
pcpcc = (char const *const *) ppc;
|
|
||||||
{ /* SCO 3.2v4 cc rejects this sort of thing. */
|
|
||||||
char tx;
|
|
||||||
char *t = &tx;
|
|
||||||
char const *s = 0 ? (char *) 0 : (char const *) 0;
|
|
||||||
|
|
||||||
*t++ = 0;
|
|
||||||
if (s) return 0;
|
|
||||||
}
|
|
||||||
{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
|
|
||||||
int x[] = {25, 17};
|
|
||||||
const int *foo = &x[0];
|
|
||||||
++foo;
|
|
||||||
}
|
|
||||||
{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
|
|
||||||
typedef const int *iptr;
|
|
||||||
iptr p = 0;
|
|
||||||
++p;
|
|
||||||
}
|
|
||||||
{ /* AIX XL C 1.02.0.0 rejects this sort of thing, saying
|
|
||||||
"k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
|
|
||||||
struct s { int j; const int *ap[3]; } bx;
|
|
||||||
struct s *b = &bx; b->j = 5;
|
|
||||||
}
|
|
||||||
{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
|
|
||||||
const int foo = 10;
|
|
||||||
if (!foo) return 0;
|
|
||||||
}
|
|
||||||
return !cs[0] && !zero.x;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
_ACEOF
|
|
||||||
if ac_fn_c_try_compile "$LINENO"; then :
|
|
||||||
ac_cv_c_const=yes
|
|
||||||
else
|
|
||||||
ac_cv_c_const=no
|
|
||||||
fi
|
|
||||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
|
||||||
fi
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5
|
|
||||||
$as_echo "$ac_cv_c_const" >&6; }
|
|
||||||
if test $ac_cv_c_const = no; then
|
|
||||||
|
|
||||||
$as_echo "#define const /**/" >>confdefs.h
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working volatile" >&5
|
|
||||||
$as_echo_n "checking for working volatile... " >&6; }
|
|
||||||
if ${ac_cv_c_volatile+:} false; then :
|
|
||||||
$as_echo_n "(cached) " >&6
|
|
||||||
else
|
|
||||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
|
||||||
/* end confdefs.h. */
|
|
||||||
|
|
||||||
int
|
|
||||||
main ()
|
|
||||||
{
|
|
||||||
|
|
||||||
volatile int x;
|
|
||||||
int * volatile y = (int *) 0;
|
|
||||||
return !x && !y;
|
|
||||||
;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
_ACEOF
|
|
||||||
if ac_fn_c_try_compile "$LINENO"; then :
|
|
||||||
ac_cv_c_volatile=yes
|
|
||||||
else
|
|
||||||
ac_cv_c_volatile=no
|
|
||||||
fi
|
|
||||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
|
||||||
fi
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_volatile" >&5
|
|
||||||
$as_echo "$ac_cv_c_volatile" >&6; }
|
|
||||||
if test $ac_cv_c_volatile = no; then
|
|
||||||
|
|
||||||
$as_echo "#define volatile /**/" >>confdefs.h
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default"
|
ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default"
|
||||||
if test "x$ac_cv_type_pid_t" = xyes; then :
|
if test "x$ac_cv_type_pid_t" = xyes; then :
|
||||||
|
|
||||||
|
@ -6081,87 +5825,6 @@ cat >>confdefs.h <<_ACEOF
|
||||||
#define pid_t int
|
#define pid_t int
|
||||||
_ACEOF
|
_ACEOF
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
|
|
||||||
if test "x$ac_cv_type_size_t" = xyes; then :
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
|
||||||
#define size_t unsigned int
|
|
||||||
_ACEOF
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5
|
|
||||||
$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; }
|
|
||||||
if ${ac_cv_header_time+:} false; then :
|
|
||||||
$as_echo_n "(cached) " >&6
|
|
||||||
else
|
|
||||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
|
||||||
/* end confdefs.h. */
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
int
|
|
||||||
main ()
|
|
||||||
{
|
|
||||||
if ((struct tm *) 0)
|
|
||||||
return 0;
|
|
||||||
;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
_ACEOF
|
|
||||||
if ac_fn_c_try_compile "$LINENO"; then :
|
|
||||||
ac_cv_header_time=yes
|
|
||||||
else
|
|
||||||
ac_cv_header_time=no
|
|
||||||
fi
|
|
||||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
|
||||||
fi
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5
|
|
||||||
$as_echo "$ac_cv_header_time" >&6; }
|
|
||||||
if test $ac_cv_header_time = yes; then
|
|
||||||
|
|
||||||
$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5
|
|
||||||
$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; }
|
|
||||||
if ${ac_cv_struct_tm+:} false; then :
|
|
||||||
$as_echo_n "(cached) " >&6
|
|
||||||
else
|
|
||||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
|
||||||
/* end confdefs.h. */
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
int
|
|
||||||
main ()
|
|
||||||
{
|
|
||||||
struct tm tm;
|
|
||||||
int *p = &tm.tm_sec;
|
|
||||||
return !p;
|
|
||||||
;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
_ACEOF
|
|
||||||
if ac_fn_c_try_compile "$LINENO"; then :
|
|
||||||
ac_cv_struct_tm=time.h
|
|
||||||
else
|
|
||||||
ac_cv_struct_tm=sys/time.h
|
|
||||||
fi
|
|
||||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
|
||||||
fi
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5
|
|
||||||
$as_echo "$ac_cv_struct_tm" >&6; }
|
|
||||||
if test $ac_cv_struct_tm = sys/time.h; then
|
|
||||||
|
|
||||||
$as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
@ -6200,7 +5863,7 @@ $as_echo "#define __malloc__ /**/" >>confdefs.h
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" "#include \"src/have.h\"
|
ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" "#include \"$srcdir/src/have.h\"
|
||||||
|
|
||||||
"
|
"
|
||||||
if test "x$ac_cv_type_socklen_t" = xyes; then :
|
if test "x$ac_cv_type_socklen_t" = xyes; then :
|
||||||
|
@ -6211,7 +5874,7 @@ _ACEOF
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
ac_fn_c_check_type "$LINENO" "struct ether_header" "ac_cv_type_struct_ether_header" "#include \"src/have.h\"
|
ac_fn_c_check_type "$LINENO" "struct ether_header" "ac_cv_type_struct_ether_header" "#include \"$srcdir/src/have.h\"
|
||||||
|
|
||||||
"
|
"
|
||||||
if test "x$ac_cv_type_struct_ether_header" = xyes; then :
|
if test "x$ac_cv_type_struct_ether_header" = xyes; then :
|
||||||
|
@ -6222,7 +5885,7 @@ _ACEOF
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
ac_fn_c_check_type "$LINENO" "struct arphdr" "ac_cv_type_struct_arphdr" "#include \"src/have.h\"
|
ac_fn_c_check_type "$LINENO" "struct arphdr" "ac_cv_type_struct_arphdr" "#include \"$srcdir/src/have.h\"
|
||||||
|
|
||||||
"
|
"
|
||||||
if test "x$ac_cv_type_struct_arphdr" = xyes; then :
|
if test "x$ac_cv_type_struct_arphdr" = xyes; then :
|
||||||
|
@ -6233,7 +5896,7 @@ _ACEOF
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
ac_fn_c_check_type "$LINENO" "struct ether_arp" "ac_cv_type_struct_ether_arp" "#include \"src/have.h\"
|
ac_fn_c_check_type "$LINENO" "struct ether_arp" "ac_cv_type_struct_ether_arp" "#include \"$srcdir/src/have.h\"
|
||||||
|
|
||||||
"
|
"
|
||||||
if test "x$ac_cv_type_struct_ether_arp" = xyes; then :
|
if test "x$ac_cv_type_struct_ether_arp" = xyes; then :
|
||||||
|
@ -6244,7 +5907,7 @@ _ACEOF
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
ac_fn_c_check_type "$LINENO" "struct in_addr" "ac_cv_type_struct_in_addr" "#include \"src/have.h\"
|
ac_fn_c_check_type "$LINENO" "struct in_addr" "ac_cv_type_struct_in_addr" "#include \"$srcdir/src/have.h\"
|
||||||
|
|
||||||
"
|
"
|
||||||
if test "x$ac_cv_type_struct_in_addr" = xyes; then :
|
if test "x$ac_cv_type_struct_in_addr" = xyes; then :
|
||||||
|
@ -6255,7 +5918,7 @@ _ACEOF
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
ac_fn_c_check_type "$LINENO" "struct addrinfo" "ac_cv_type_struct_addrinfo" "#include \"src/have.h\"
|
ac_fn_c_check_type "$LINENO" "struct addrinfo" "ac_cv_type_struct_addrinfo" "#include \"$srcdir/src/have.h\"
|
||||||
|
|
||||||
"
|
"
|
||||||
if test "x$ac_cv_type_struct_addrinfo" = xyes; then :
|
if test "x$ac_cv_type_struct_addrinfo" = xyes; then :
|
||||||
|
@ -6266,7 +5929,7 @@ _ACEOF
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
ac_fn_c_check_type "$LINENO" "struct ip" "ac_cv_type_struct_ip" "#include \"src/have.h\"
|
ac_fn_c_check_type "$LINENO" "struct ip" "ac_cv_type_struct_ip" "#include \"$srcdir/src/have.h\"
|
||||||
|
|
||||||
"
|
"
|
||||||
if test "x$ac_cv_type_struct_ip" = xyes; then :
|
if test "x$ac_cv_type_struct_ip" = xyes; then :
|
||||||
|
@ -6277,7 +5940,7 @@ _ACEOF
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
ac_fn_c_check_type "$LINENO" "struct icmp" "ac_cv_type_struct_icmp" "#include \"src/have.h\"
|
ac_fn_c_check_type "$LINENO" "struct icmp" "ac_cv_type_struct_icmp" "#include \"$srcdir/src/have.h\"
|
||||||
|
|
||||||
"
|
"
|
||||||
if test "x$ac_cv_type_struct_icmp" = xyes; then :
|
if test "x$ac_cv_type_struct_icmp" = xyes; then :
|
||||||
|
@ -6288,7 +5951,7 @@ _ACEOF
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
ac_fn_c_check_type "$LINENO" "struct in6_addr" "ac_cv_type_struct_in6_addr" "#include \"src/have.h\"
|
ac_fn_c_check_type "$LINENO" "struct in6_addr" "ac_cv_type_struct_in6_addr" "#include \"$srcdir/src/have.h\"
|
||||||
|
|
||||||
"
|
"
|
||||||
if test "x$ac_cv_type_struct_in6_addr" = xyes; then :
|
if test "x$ac_cv_type_struct_in6_addr" = xyes; then :
|
||||||
|
@ -6299,7 +5962,7 @@ _ACEOF
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
ac_fn_c_check_type "$LINENO" "struct sockaddr_in6" "ac_cv_type_struct_sockaddr_in6" "#include \"src/have.h\"
|
ac_fn_c_check_type "$LINENO" "struct sockaddr_in6" "ac_cv_type_struct_sockaddr_in6" "#include \"$srcdir/src/have.h\"
|
||||||
|
|
||||||
"
|
"
|
||||||
if test "x$ac_cv_type_struct_sockaddr_in6" = xyes; then :
|
if test "x$ac_cv_type_struct_sockaddr_in6" = xyes; then :
|
||||||
|
@ -6310,7 +5973,7 @@ _ACEOF
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
ac_fn_c_check_type "$LINENO" "struct ip6_hdr" "ac_cv_type_struct_ip6_hdr" "#include \"src/have.h\"
|
ac_fn_c_check_type "$LINENO" "struct ip6_hdr" "ac_cv_type_struct_ip6_hdr" "#include \"$srcdir/src/have.h\"
|
||||||
|
|
||||||
"
|
"
|
||||||
if test "x$ac_cv_type_struct_ip6_hdr" = xyes; then :
|
if test "x$ac_cv_type_struct_ip6_hdr" = xyes; then :
|
||||||
|
@ -6321,7 +5984,7 @@ _ACEOF
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
ac_fn_c_check_type "$LINENO" "struct icmp6_hdr" "ac_cv_type_struct_icmp6_hdr" "#include \"src/have.h\"
|
ac_fn_c_check_type "$LINENO" "struct icmp6_hdr" "ac_cv_type_struct_icmp6_hdr" "#include \"$srcdir/src/have.h\"
|
||||||
|
|
||||||
"
|
"
|
||||||
if test "x$ac_cv_type_struct_icmp6_hdr" = xyes; then :
|
if test "x$ac_cv_type_struct_icmp6_hdr" = xyes; then :
|
||||||
|
@ -6332,7 +5995,7 @@ _ACEOF
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
ac_fn_c_check_type "$LINENO" "struct nd_neighbor_solicit" "ac_cv_type_struct_nd_neighbor_solicit" "#include \"src/have.h\"
|
ac_fn_c_check_type "$LINENO" "struct nd_neighbor_solicit" "ac_cv_type_struct_nd_neighbor_solicit" "#include \"$srcdir/src/have.h\"
|
||||||
|
|
||||||
"
|
"
|
||||||
if test "x$ac_cv_type_struct_nd_neighbor_solicit" = xyes; then :
|
if test "x$ac_cv_type_struct_nd_neighbor_solicit" = xyes; then :
|
||||||
|
@ -6343,7 +6006,7 @@ _ACEOF
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
ac_fn_c_check_type "$LINENO" "struct nd_opt_hdr" "ac_cv_type_struct_nd_opt_hdr" "#include \"src/have.h\"
|
ac_fn_c_check_type "$LINENO" "struct nd_opt_hdr" "ac_cv_type_struct_nd_opt_hdr" "#include \"$srcdir/src/have.h\"
|
||||||
|
|
||||||
"
|
"
|
||||||
if test "x$ac_cv_type_struct_nd_opt_hdr" = xyes; then :
|
if test "x$ac_cv_type_struct_nd_opt_hdr" = xyes; then :
|
||||||
|
@ -6389,7 +6052,7 @@ cat >>confdefs.h <<_ACEOF
|
||||||
_ACEOF
|
_ACEOF
|
||||||
|
|
||||||
|
|
||||||
for ac_func in 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
|
for ac_func in asprintf daemon fchmod flock fork gettimeofday mlockall pselect putenv strsignal system unsetenv usleep vsyslog devname fdevname
|
||||||
do :
|
do :
|
||||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||||
|
@ -6528,7 +6191,7 @@ fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
ac_fn_c_check_decl "$LINENO" "freeaddrinfo" "ac_cv_have_decl_freeaddrinfo" "#include \"src/have.h\"
|
ac_fn_c_check_decl "$LINENO" "freeaddrinfo" "ac_cv_have_decl_freeaddrinfo" "#include \"$srcdir/src/have.h\"
|
||||||
|
|
||||||
"
|
"
|
||||||
if test "x$ac_cv_have_decl_freeaddrinfo" = xyes; then :
|
if test "x$ac_cv_have_decl_freeaddrinfo" = xyes; then :
|
||||||
|
@ -6540,7 +6203,7 @@ fi
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
#define HAVE_DECL_FREEADDRINFO $ac_have_decl
|
#define HAVE_DECL_FREEADDRINFO $ac_have_decl
|
||||||
_ACEOF
|
_ACEOF
|
||||||
ac_fn_c_check_decl "$LINENO" "gai_strerror" "ac_cv_have_decl_gai_strerror" "#include \"src/have.h\"
|
ac_fn_c_check_decl "$LINENO" "gai_strerror" "ac_cv_have_decl_gai_strerror" "#include \"$srcdir/src/have.h\"
|
||||||
|
|
||||||
"
|
"
|
||||||
if test "x$ac_cv_have_decl_gai_strerror" = xyes; then :
|
if test "x$ac_cv_have_decl_gai_strerror" = xyes; then :
|
||||||
|
@ -6552,7 +6215,7 @@ fi
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
#define HAVE_DECL_GAI_STRERROR $ac_have_decl
|
#define HAVE_DECL_GAI_STRERROR $ac_have_decl
|
||||||
_ACEOF
|
_ACEOF
|
||||||
ac_fn_c_check_decl "$LINENO" "getaddrinfo" "ac_cv_have_decl_getaddrinfo" "#include \"src/have.h\"
|
ac_fn_c_check_decl "$LINENO" "getaddrinfo" "ac_cv_have_decl_getaddrinfo" "#include \"$srcdir/src/have.h\"
|
||||||
|
|
||||||
"
|
"
|
||||||
if test "x$ac_cv_have_decl_getaddrinfo" = xyes; then :
|
if test "x$ac_cv_have_decl_getaddrinfo" = xyes; then :
|
||||||
|
@ -6564,7 +6227,7 @@ fi
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
#define HAVE_DECL_GETADDRINFO $ac_have_decl
|
#define HAVE_DECL_GETADDRINFO $ac_have_decl
|
||||||
_ACEOF
|
_ACEOF
|
||||||
ac_fn_c_check_decl "$LINENO" "getnameinfo" "ac_cv_have_decl_getnameinfo" "#include \"src/have.h\"
|
ac_fn_c_check_decl "$LINENO" "getnameinfo" "ac_cv_have_decl_getnameinfo" "#include \"$srcdir/src/have.h\"
|
||||||
|
|
||||||
"
|
"
|
||||||
if test "x$ac_cv_have_decl_getnameinfo" = xyes; then :
|
if test "x$ac_cv_have_decl_getnameinfo" = xyes; then :
|
||||||
|
@ -7204,7 +6867,7 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
for ac_func in BN_GENCB_new ERR_remove_state RSA_set0_key
|
for ac_func in BN_GENCB_new RSA_set0_key
|
||||||
do :
|
do :
|
||||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||||
|
@ -7230,7 +6893,12 @@ fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
ac_config_files="$ac_config_files Makefile src/Makefile doc/Makefile m4/Makefile distro/Makefile"
|
if test "x$runstatedir" = "x"; then
|
||||||
|
runstatedir='${localstatedir}/run'
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
ac_config_files="$ac_config_files Makefile src/Makefile doc/Makefile distro/Makefile"
|
||||||
|
|
||||||
|
|
||||||
cat >confcache <<\_ACEOF
|
cat >confcache <<\_ACEOF
|
||||||
|
@ -7358,10 +7026,6 @@ else
|
||||||
am__EXEEXT_FALSE=
|
am__EXEEXT_FALSE=
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
|
|
||||||
as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined.
|
|
||||||
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
|
||||||
fi
|
|
||||||
if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
|
if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
|
||||||
as_fn_error $? "conditional \"AMDEP\" was never defined.
|
as_fn_error $? "conditional \"AMDEP\" was never defined.
|
||||||
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
||||||
|
@ -7807,7 +7471,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||||
# report actual input values of CONFIG_FILES etc. instead of their
|
# report actual input values of CONFIG_FILES etc. instead of their
|
||||||
# values after options handling.
|
# values after options handling.
|
||||||
ac_log="
|
ac_log="
|
||||||
This file was extended by tinc $as_me 1.0.32, which was
|
This file was extended by tinc $as_me 1.0.33, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
|
@ -7873,7 +7537,7 @@ _ACEOF
|
||||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
tinc config.status 1.0.32
|
tinc config.status 1.0.33
|
||||||
configured by $0, generated by GNU Autoconf 2.69,
|
configured by $0, generated by GNU Autoconf 2.69,
|
||||||
with options \\"\$ac_cs_config\\"
|
with options \\"\$ac_cs_config\\"
|
||||||
|
|
||||||
|
@ -8007,7 +7671,6 @@ do
|
||||||
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
|
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
|
||||||
"src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
|
"src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
|
||||||
"doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
|
"doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
|
||||||
"m4/Makefile") CONFIG_FILES="$CONFIG_FILES m4/Makefile" ;;
|
|
||||||
"distro/Makefile") CONFIG_FILES="$CONFIG_FILES distro/Makefile" ;;
|
"distro/Makefile") CONFIG_FILES="$CONFIG_FILES distro/Makefile" ;;
|
||||||
|
|
||||||
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
|
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
|
||||||
|
|
35
configure.ac
35
configure.ac
|
@ -1,11 +1,11 @@
|
||||||
dnl Process this file with autoconf to produce a configure script.
|
dnl Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
AC_PREREQ(2.61)
|
AC_PREREQ(2.61)
|
||||||
AC_INIT([tinc], [1.0.32])
|
AC_INIT([tinc], [1.0.33])
|
||||||
AC_CONFIG_SRCDIR([src/tincd.c])
|
AC_CONFIG_SRCDIR([src/tincd.c])
|
||||||
AM_INIT_AUTOMAKE([1.11 check-news std-options subdir-objects nostdinc silent-rules -Wall])
|
AM_INIT_AUTOMAKE([1.11 check-news std-options subdir-objects nostdinc silent-rules -Wall info-in-builddir])
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
AM_MAINTAINER_MODE
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
AM_SILENT_RULES([yes])
|
AM_SILENT_RULES([yes])
|
||||||
|
|
||||||
# Enable GNU extensions.
|
# Enable GNU extensions.
|
||||||
|
@ -179,36 +179,30 @@ dnl Checks for libraries.
|
||||||
dnl Checks for header files.
|
dnl Checks for header files.
|
||||||
dnl We do this in multiple stages, because unlike Linux all the other operating systems really suck and don't include their own dependencies.
|
dnl We do this in multiple stages, because unlike Linux all the other operating systems really suck and don't include their own dependencies.
|
||||||
|
|
||||||
AC_HEADER_STDC
|
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([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([net/if.h net/if_types.h linux/if_tun.h net/if_tun.h net/if_utun.h net/tun/if_tun.h net/if_tap.h net/tap/if_tap.h net/ethernet.h net/if_arp.h netinet/in_systm.h netinet/in.h netinet/in6.h netpacket/packet.h],
|
AC_CHECK_HEADERS([net/if.h net/if_types.h 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],
|
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],
|
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.
|
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||||
AC_C_CONST
|
|
||||||
AC_C_VOLATILE
|
|
||||||
AC_TYPE_PID_T
|
AC_TYPE_PID_T
|
||||||
AC_TYPE_SIZE_T
|
|
||||||
AC_HEADER_TIME
|
|
||||||
AC_STRUCT_TM
|
|
||||||
|
|
||||||
tinc_ATTRIBUTE(__malloc__)
|
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], , ,
|
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.
|
dnl Checks for library functions.
|
||||||
AC_TYPE_SIGNAL
|
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],
|
AC_CHECK_FUNCS([asprintf daemon fchmod flock fork gettimeofday mlockall pselect putenv strsignal system unsetenv usleep vsyslog devname fdevname],
|
||||||
[], [], [#include "src/have.h"]
|
[], [], [#include "$srcdir/src/have.h"]
|
||||||
)
|
)
|
||||||
|
|
||||||
AC_CHECK_FUNC(getopt_long, [getopt=true; AC_DEFINE(HAVE_GETOPT_LONG, 1, [getopt_long()])], [getopt=false])
|
AC_CHECK_FUNC(getopt_long, [getopt=true; AC_DEFINE(HAVE_GETOPT_LONG, 1, [getopt_long()])], [getopt=false])
|
||||||
|
@ -224,7 +218,7 @@ AC_CHECK_FUNC(gethostbyname, [], [
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_CHECK_DECLS([freeaddrinfo, gai_strerror, getaddrinfo, getnameinfo],
|
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)], [], [
|
AC_CHECK_DECLS([res_init], [AC_CHECK_LIB(resolv, res_init)], [], [
|
||||||
|
@ -248,6 +242,11 @@ AC_ARG_ENABLE(jumbograms,
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile m4/Makefile distro/Makefile])
|
dnl Ensure runstatedir is set if we are using a version of autoconf that does not suppport it
|
||||||
|
if test "x$runstatedir" = "x"; then
|
||||||
|
AC_SUBST([runstatedir], ['${localstatedir}/run'])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile distro/Makefile])
|
||||||
|
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|
|
@ -186,7 +186,6 @@ LDFLAGS = @LDFLAGS@
|
||||||
LIBOBJS = @LIBOBJS@
|
LIBOBJS = @LIBOBJS@
|
||||||
LIBS = @LIBS@
|
LIBS = @LIBS@
|
||||||
LTLIBOBJS = @LTLIBOBJS@
|
LTLIBOBJS = @LTLIBOBJS@
|
||||||
MAINT = @MAINT@
|
|
||||||
MAKEINFO = @MAKEINFO@
|
MAKEINFO = @MAKEINFO@
|
||||||
MKDIR_P = @MKDIR_P@
|
MKDIR_P = @MKDIR_P@
|
||||||
OBJEXT = @OBJEXT@
|
OBJEXT = @OBJEXT@
|
||||||
|
@ -268,7 +267,7 @@ EXTRA_DIST = \
|
||||||
all: all-am
|
all: all-am
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
$(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 \
|
@for dep in $?; do \
|
||||||
case '$(am__configure_deps)' in \
|
case '$(am__configure_deps)' in \
|
||||||
*$$dep*) \
|
*$$dep*) \
|
||||||
|
@ -292,9 +291,9 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
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
|
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
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
$(am__aclocal_m4_deps):
|
$(am__aclocal_m4_deps):
|
||||||
install-systemdsystemunitDATA: $(systemdsystemunit_DATA)
|
install-systemdsystemunitDATA: $(systemdsystemunit_DATA)
|
||||||
|
|
|
@ -4,23 +4,12 @@ info_TEXINFOS = tinc.texi
|
||||||
|
|
||||||
man_MANS = tincd.8 tinc.conf.5
|
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
|
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
|
texi2html: tinc.texi
|
||||||
$(AM_V_GEN)texi2html -split=chapter tinc.texi
|
$(AM_V_GEN)texi2html -split=chapter $<
|
||||||
|
|
||||||
tincd.8.html: tincd.8
|
tincd.8.html: tincd.8
|
||||||
$(AM_V_GEN)w3mman2html $< > $@
|
$(AM_V_GEN)w3mman2html $< > $@
|
||||||
|
@ -32,15 +21,16 @@ substitute = sed \
|
||||||
-e s,'@PACKAGE\@',"$(PACKAGE)",g \
|
-e s,'@PACKAGE\@',"$(PACKAGE)",g \
|
||||||
-e s,'@VERSION\@',"$(VERSION)",g \
|
-e s,'@VERSION\@',"$(VERSION)",g \
|
||||||
-e s,'@sysconfdir\@',"$(sysconfdir)",g \
|
-e s,'@sysconfdir\@',"$(sysconfdir)",g \
|
||||||
|
-e s,'@runstatedir\@',"$(runstatedir)",g \
|
||||||
-e s,'@localstatedir\@',"$(localstatedir)",g
|
-e s,'@localstatedir\@',"$(localstatedir)",g
|
||||||
|
|
||||||
tincd.8: tincd.8.in
|
tincd.8: $(srcdir)/tincd.8.in
|
||||||
$(AM_V_GEN)$(substitute) tincd.8.in > tincd.8
|
$(AM_V_GEN)$(substitute) $< > $@
|
||||||
|
|
||||||
tinc.conf.5: tinc.conf.5.in
|
tinc.conf.5: $(srcdir)/tinc.conf.5.in
|
||||||
$(AM_V_GEN)$(substitute) tinc.conf.5.in > tinc.conf.5
|
$(AM_V_GEN)$(substitute) $< > $@
|
||||||
|
|
||||||
tincinclude.texi: tincinclude.texi.in
|
tincinclude.texi: $(srcdir)/tincinclude.texi.in
|
||||||
$(AM_V_GEN)$(substitute) tincinclude.texi.in > tincinclude.texi
|
$(AM_V_GEN)$(substitute) $< > $@
|
||||||
|
|
||||||
tinc.texi: tincinclude.texi
|
tinc.texi: tincinclude.texi
|
||||||
|
|
|
@ -78,6 +78,7 @@ install_sh_DATA = $(install_sh) -c -m 644
|
||||||
install_sh_PROGRAM = $(install_sh) -c
|
install_sh_PROGRAM = $(install_sh) -c
|
||||||
install_sh_SCRIPT = $(install_sh) -c
|
install_sh_SCRIPT = $(install_sh) -c
|
||||||
INSTALL_HEADER = $(INSTALL_DATA)
|
INSTALL_HEADER = $(INSTALL_DATA)
|
||||||
|
transform = $(program_transform_name)
|
||||||
NORMAL_INSTALL = :
|
NORMAL_INSTALL = :
|
||||||
PRE_INSTALL = :
|
PRE_INSTALL = :
|
||||||
POST_INSTALL = :
|
POST_INSTALL = :
|
||||||
|
@ -145,7 +146,7 @@ AM_V_texidevnull = $(am__v_texidevnull_@AM_V@)
|
||||||
am__v_texidevnull_ = $(am__v_texidevnull_@AM_DEFAULT_V@)
|
am__v_texidevnull_ = $(am__v_texidevnull_@AM_DEFAULT_V@)
|
||||||
am__v_texidevnull_0 = > /dev/null
|
am__v_texidevnull_0 = > /dev/null
|
||||||
am__v_texidevnull_1 =
|
am__v_texidevnull_1 =
|
||||||
INFO_DEPS = $(srcdir)/tinc.info
|
INFO_DEPS = tinc.info
|
||||||
am__TEXINFO_TEX_DIR = $(srcdir)
|
am__TEXINFO_TEX_DIR = $(srcdir)
|
||||||
DVIS = tinc.dvi
|
DVIS = tinc.dvi
|
||||||
PDFS = tinc.pdf
|
PDFS = tinc.pdf
|
||||||
|
@ -198,11 +199,6 @@ MANS = $(man_MANS)
|
||||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||||
am__DIST_COMMON = $(srcdir)/Makefile.in texinfo.tex
|
am__DIST_COMMON = $(srcdir)/Makefile.in texinfo.tex
|
||||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
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@
|
ACLOCAL = @ACLOCAL@
|
||||||
AMTAR = @AMTAR@
|
AMTAR = @AMTAR@
|
||||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||||
|
@ -233,7 +229,6 @@ LDFLAGS = @LDFLAGS@
|
||||||
LIBOBJS = @LIBOBJS@
|
LIBOBJS = @LIBOBJS@
|
||||||
LIBS = @LIBS@
|
LIBS = @LIBS@
|
||||||
LTLIBOBJS = @LTLIBOBJS@
|
LTLIBOBJS = @LTLIBOBJS@
|
||||||
MAINT = @MAINT@
|
|
||||||
MAKEINFO = @MAKEINFO@
|
MAKEINFO = @MAKEINFO@
|
||||||
MKDIR_P = @MKDIR_P@
|
MKDIR_P = @MKDIR_P@
|
||||||
OBJEXT = @OBJEXT@
|
OBJEXT = @OBJEXT@
|
||||||
|
@ -306,19 +301,20 @@ top_builddir = @top_builddir@
|
||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
info_TEXINFOS = tinc.texi
|
info_TEXINFOS = tinc.texi
|
||||||
man_MANS = tincd.8 tinc.conf.5
|
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
|
CLEANFILES = *.html tincd.8 tinc.conf.5 tincinclude.texi
|
||||||
substitute = sed \
|
substitute = sed \
|
||||||
-e s,'@PACKAGE\@',"$(PACKAGE)",g \
|
-e s,'@PACKAGE\@',"$(PACKAGE)",g \
|
||||||
-e s,'@VERSION\@',"$(VERSION)",g \
|
-e s,'@VERSION\@',"$(VERSION)",g \
|
||||||
-e s,'@sysconfdir\@',"$(sysconfdir)",g \
|
-e s,'@sysconfdir\@',"$(sysconfdir)",g \
|
||||||
|
-e s,'@runstatedir\@',"$(runstatedir)",g \
|
||||||
-e s,'@localstatedir\@',"$(localstatedir)",g
|
-e s,'@localstatedir\@',"$(localstatedir)",g
|
||||||
|
|
||||||
all: all-am
|
all: all-am
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
.SUFFIXES: .dvi .html .info .pdf .ps .texi
|
.SUFFIXES: .dvi .ps
|
||||||
$(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 \
|
@for dep in $?; do \
|
||||||
case '$(am__configure_deps)' in \
|
case '$(am__configure_deps)' in \
|
||||||
*$$dep*) \
|
*$$dep*) \
|
||||||
|
@ -342,59 +338,51 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
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
|
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
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
$(am__aclocal_m4_deps):
|
$(am__aclocal_m4_deps):
|
||||||
|
|
||||||
.texi.info:
|
tinc.info: tinc.texi
|
||||||
$(AM_V_MAKEINFO)restore=: && backupdir="$(am__leading_dot)am$$$$" && \
|
$(AM_V_MAKEINFO)restore=: && backupdir="$(am__leading_dot)am$$$$" && \
|
||||||
am__cwd=`pwd` && $(am__cd) $(srcdir) && \
|
|
||||||
rm -rf $$backupdir && mkdir $$backupdir && \
|
rm -rf $$backupdir && mkdir $$backupdir && \
|
||||||
if ($(MAKEINFO) --version) >/dev/null 2>&1; then \
|
if ($(MAKEINFO) --version) >/dev/null 2>&1; then \
|
||||||
for f in $@ $@-[0-9] $@-[0-9][0-9] $(@:.info=).i[0-9] $(@:.info=).i[0-9][0-9]; do \
|
for f in $@ $@-[0-9] $@-[0-9][0-9] $(@:.info=).i[0-9] $(@:.info=).i[0-9][0-9]; do \
|
||||||
if test -f $$f; then mv $$f $$backupdir; restore=mv; else :; fi; \
|
if test -f $$f; then mv $$f $$backupdir; restore=mv; else :; fi; \
|
||||||
done; \
|
done; \
|
||||||
else :; fi && \
|
else :; fi && \
|
||||||
cd "$$am__cwd"; \
|
|
||||||
if $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \
|
if $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \
|
||||||
-o $@ $<; \
|
-o $@ `test -f 'tinc.texi' || echo '$(srcdir)/'`tinc.texi; \
|
||||||
then \
|
then \
|
||||||
rc=0; \
|
rc=0; \
|
||||||
$(am__cd) $(srcdir); \
|
|
||||||
else \
|
else \
|
||||||
rc=$$?; \
|
rc=$$?; \
|
||||||
$(am__cd) $(srcdir) && \
|
|
||||||
$$restore $$backupdir/* `echo "./$@" | sed 's|[^/]*$$||'`; \
|
$$restore $$backupdir/* `echo "./$@" | sed 's|[^/]*$$||'`; \
|
||||||
fi; \
|
fi; \
|
||||||
rm -rf $$backupdir; exit $$rc
|
rm -rf $$backupdir; exit $$rc
|
||||||
|
|
||||||
.texi.dvi:
|
tinc.dvi: tinc.texi
|
||||||
$(AM_V_TEXI2DVI)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
|
$(AM_V_TEXI2DVI)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
|
||||||
MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \
|
MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \
|
||||||
$(TEXI2DVI) $(AM_V_texinfo) --build-dir=$(@:.dvi=.t2d) -o $@ $(AM_V_texidevnull) \
|
$(TEXI2DVI) $(AM_V_texinfo) --build-dir=$(@:.dvi=.t2d) -o $@ $(AM_V_texidevnull) \
|
||||||
$<
|
`test -f 'tinc.texi' || echo '$(srcdir)/'`tinc.texi
|
||||||
|
|
||||||
.texi.pdf:
|
tinc.pdf: tinc.texi
|
||||||
$(AM_V_TEXI2PDF)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
|
$(AM_V_TEXI2PDF)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
|
||||||
MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \
|
MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \
|
||||||
$(TEXI2PDF) $(AM_V_texinfo) --build-dir=$(@:.pdf=.t2p) -o $@ $(AM_V_texidevnull) \
|
$(TEXI2PDF) $(AM_V_texinfo) --build-dir=$(@:.pdf=.t2p) -o $@ $(AM_V_texidevnull) \
|
||||||
$<
|
`test -f 'tinc.texi' || echo '$(srcdir)/'`tinc.texi
|
||||||
|
|
||||||
.texi.html:
|
tinc.html: tinc.texi
|
||||||
$(AM_V_MAKEINFO)rm -rf $(@:.html=.htp)
|
$(AM_V_MAKEINFO)rm -rf $(@:.html=.htp)
|
||||||
$(AM_V_at)if $(MAKEINFOHTML) $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \
|
$(AM_V_at)if $(MAKEINFOHTML) $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \
|
||||||
-o $(@:.html=.htp) $<; \
|
-o $(@:.html=.htp) `test -f 'tinc.texi' || echo '$(srcdir)/'`tinc.texi; \
|
||||||
then \
|
then \
|
||||||
rm -rf $@ && mv $(@:.html=.htp) $@; \
|
rm -rf $@ && mv $(@:.html=.htp) $@; \
|
||||||
else \
|
else \
|
||||||
rm -rf $(@:.html=.htp); exit 1; \
|
rm -rf $(@:.html=.htp); exit 1; \
|
||||||
fi
|
fi
|
||||||
$(srcdir)/tinc.info: tinc.texi
|
|
||||||
tinc.dvi: tinc.texi
|
|
||||||
tinc.pdf: tinc.texi
|
|
||||||
tinc.html: tinc.texi
|
|
||||||
.dvi.ps:
|
.dvi.ps:
|
||||||
$(AM_V_DVIPS)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
|
$(AM_V_DVIPS)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
|
||||||
$(DVIPS) $(AM_V_texinfo) -o $@ $<
|
$(DVIPS) $(AM_V_texinfo) -o $@ $<
|
||||||
|
@ -833,14 +821,8 @@ uninstall-man: uninstall-man5 uninstall-man8
|
||||||
.PRECIOUS: Makefile
|
.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
|
texi2html: tinc.texi
|
||||||
$(AM_V_GEN)texi2html -split=chapter tinc.texi
|
$(AM_V_GEN)texi2html -split=chapter $<
|
||||||
|
|
||||||
tincd.8.html: tincd.8
|
tincd.8.html: tincd.8
|
||||||
$(AM_V_GEN)w3mman2html $< > $@
|
$(AM_V_GEN)w3mman2html $< > $@
|
||||||
|
@ -848,14 +830,14 @@ tincd.8.html: tincd.8
|
||||||
tinc.conf.5.html: tinc.conf.5
|
tinc.conf.5.html: tinc.conf.5
|
||||||
$(AM_V_GEN)w3mman2html $< > $@
|
$(AM_V_GEN)w3mman2html $< > $@
|
||||||
|
|
||||||
tincd.8: tincd.8.in
|
tincd.8: $(srcdir)/tincd.8.in
|
||||||
$(AM_V_GEN)$(substitute) tincd.8.in > tincd.8
|
$(AM_V_GEN)$(substitute) $< > $@
|
||||||
|
|
||||||
tinc.conf.5: tinc.conf.5.in
|
tinc.conf.5: $(srcdir)/tinc.conf.5.in
|
||||||
$(AM_V_GEN)$(substitute) tinc.conf.5.in > tinc.conf.5
|
$(AM_V_GEN)$(substitute) $< > $@
|
||||||
|
|
||||||
tincinclude.texi: tincinclude.texi.in
|
tincinclude.texi: $(srcdir)/tincinclude.texi.in
|
||||||
$(AM_V_GEN)$(substitute) tincinclude.texi.in > tincinclude.texi
|
$(AM_V_GEN)$(substitute) $< > $@
|
||||||
|
|
||||||
tinc.texi: tincinclude.texi
|
tinc.texi: tincinclude.texi
|
||||||
|
|
||||||
|
|
Binary file not shown.
15
doc/sample-config/hosts/alpha
Normal file
15
doc/sample-config/hosts/alpha
Normal 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-----
|
16
doc/sample-config/hosts/beta
Normal file
16
doc/sample-config/hosts/beta
Normal 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-----
|
1
doc/sample-config/rsa_key.priv
Normal file
1
doc/sample-config/rsa_key.priv
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# Generate this file with `tincd -n example -K`
|
4
doc/sample-config/tinc-down
Normal file
4
doc/sample-config/tinc-down
Normal 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
11
doc/sample-config/tinc-up
Normal 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
|
22
doc/sample-config/tinc.conf
Normal file
22
doc/sample-config/tinc.conf
Normal 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
|
|
@ -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
|
Create a UNIX socket with the filename specified by
|
||||||
.Va Device ,
|
.Va Device ,
|
||||||
or
|
or
|
||||||
.Pa @localstatedir@/run/ Ns Ar NETNAME Ns Pa .umlsocket
|
.Pa @runstatedir@/ Ns Ar NETNAME Ns Pa .umlsocket
|
||||||
if not specified.
|
if not specified.
|
||||||
.Nm tinc
|
.Nm tinc
|
||||||
will wait for a User Mode Linux instance to connect to this socket.
|
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
|
using the UNIX socket specified by
|
||||||
.Va Device ,
|
.Va Device ,
|
||||||
or
|
or
|
||||||
.Pa @localstatedir@/run/vde.ctl
|
.Pa @runstatedir@/vde.ctl
|
||||||
if not specified.
|
if not specified.
|
||||||
.El
|
.El
|
||||||
Also, in case tinc does not seem to correctly interpret packets received from the virtual network device,
|
Also, in case tinc does not seem to correctly interpret packets received from the virtual network device,
|
||||||
|
|
148
doc/tinc.info
148
doc/tinc.info
|
@ -1,11 +1,11 @@
|
||||||
This is tinc.info, produced by makeinfo version 6.4.90 from tinc.texi.
|
This is tinc.info, produced by makeinfo version 6.5 from tinc.texi.
|
||||||
|
|
||||||
INFO-DIR-SECTION Networking tools
|
INFO-DIR-SECTION Networking tools
|
||||||
START-INFO-DIR-ENTRY
|
START-INFO-DIR-ENTRY
|
||||||
* tinc: (tinc). The tinc Manual.
|
* tinc: (tinc). The tinc Manual.
|
||||||
END-INFO-DIR-ENTRY
|
END-INFO-DIR-ENTRY
|
||||||
|
|
||||||
This is the info manual for tinc version 1.0.31, a Virtual Private
|
This is the info manual for tinc version 1.0.33, a Virtual Private
|
||||||
Network daemon.
|
Network daemon.
|
||||||
|
|
||||||
Copyright (C) 1998-2017 Ivo Timmermans, Guus Sliepen
|
Copyright (C) 1998-2017 Ivo Timmermans, Guus Sliepen
|
||||||
|
@ -791,13 +791,13 @@ DeviceType = <TYPE> (platform dependent)
|
||||||
|
|
||||||
uml (not compiled in by default)
|
uml (not compiled in by default)
|
||||||
Create a UNIX socket with the filename specified by DEVICE, or
|
Create a UNIX socket with the filename specified by DEVICE, or
|
||||||
'/var/run/NETNAME.umlsocket' if not specified. Tinc will wait
|
'/run/NETNAME.umlsocket' if not specified. Tinc will wait for
|
||||||
for a User Mode Linux instance to connect to this socket.
|
a User Mode Linux instance to connect to this socket.
|
||||||
|
|
||||||
vde (not compiled in by default)
|
vde (not compiled in by default)
|
||||||
Uses the libvdeplug library to connect to a Virtual
|
Uses the libvdeplug library to connect to a Virtual
|
||||||
Distributed Ethernet switch, using the UNIX socket specified
|
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
|
Also, in case tinc does not seem to correctly interpret packets
|
||||||
received from the virtual network device, it can be used to change
|
received from the virtual network device, it can be used to change
|
||||||
|
@ -1597,7 +1597,7 @@ command line options.
|
||||||
'/var/log/tinc.NETNAME.log'.
|
'/var/log/tinc.NETNAME.log'.
|
||||||
|
|
||||||
'--pidfile=FILE'
|
'--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'
|
'--bypass-security'
|
||||||
Disables encryption and authentication. Only useful for debugging.
|
Disables encryption and authentication. Only useful for debugging.
|
||||||
|
@ -1609,12 +1609,16 @@ command line options.
|
||||||
chroot is performed after all the initialization is done, after
|
chroot is performed after all the initialization is done, after
|
||||||
writing pid files and opening network sockets.
|
writing pid files and opening network sockets.
|
||||||
|
|
||||||
Note that this option alone does not do any good without -U/-user,
|
This option is best used in combination with the -U/-user option
|
||||||
below.
|
described below.
|
||||||
|
|
||||||
Note also that tinc can't run scripts anymore (such as tinc-down or
|
You will need to ensure the chroot environment contains all the
|
||||||
host-up), unless it's setup to be runnable inside chroot
|
files necessary for tinc to run correctly. Most importantly, for
|
||||||
environment.
|
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'
|
'-U, --user=USER'
|
||||||
Switch to the given USER after initialization, at the same time as
|
Switch to the given USER after initialization, at the same time as
|
||||||
|
@ -2650,66 +2654,66 @@ Concept Index
|
||||||
|
|
||||||
|
|
||||||
Tag Table:
|
Tag Table:
|
||||||
Node: Top809
|
Node: Top806
|
||||||
Node: Introduction1108
|
Node: Introduction1105
|
||||||
Node: Virtual Private Networks1918
|
Node: Virtual Private Networks1915
|
||||||
Node: tinc3642
|
Node: tinc3639
|
||||||
Node: Supported platforms5169
|
Node: Supported platforms5166
|
||||||
Node: Preparations5870
|
Node: Preparations5867
|
||||||
Node: Configuring the kernel6126
|
Node: Configuring the kernel6123
|
||||||
Node: Configuration of Linux kernels6536
|
Node: Configuration of Linux kernels6533
|
||||||
Node: Configuration of FreeBSD kernels7391
|
Node: Configuration of FreeBSD kernels7388
|
||||||
Node: Configuration of OpenBSD kernels7856
|
Node: Configuration of OpenBSD kernels7853
|
||||||
Node: Configuration of NetBSD kernels8213
|
Node: Configuration of NetBSD kernels8210
|
||||||
Node: Configuration of Solaris kernels8618
|
Node: Configuration of Solaris kernels8615
|
||||||
Node: Configuration of Darwin (Mac OS X) kernels9281
|
Node: Configuration of Darwin (Mac OS X) kernels9278
|
||||||
Node: Configuration of Windows10100
|
Node: Configuration of Windows10097
|
||||||
Node: Libraries10640
|
Node: Libraries10637
|
||||||
Node: LibreSSL/OpenSSL11049
|
Node: LibreSSL/OpenSSL11046
|
||||||
Node: zlib13591
|
Node: zlib13588
|
||||||
Node: lzo14623
|
Node: lzo14620
|
||||||
Node: Installation15606
|
Node: Installation15603
|
||||||
Node: Building and installing tinc16516
|
Node: Building and installing tinc16513
|
||||||
Node: Darwin (Mac OS X) build environment17176
|
Node: Darwin (Mac OS X) build environment17173
|
||||||
Node: Cygwin (Windows) build environment17741
|
Node: Cygwin (Windows) build environment17738
|
||||||
Node: MinGW (Windows) build environment18330
|
Node: MinGW (Windows) build environment18327
|
||||||
Node: System files18924
|
Node: System files18921
|
||||||
Node: Device files19189
|
Node: Device files19186
|
||||||
Node: Other files19605
|
Node: Other files19602
|
||||||
Node: Configuration20218
|
Node: Configuration20215
|
||||||
Node: Configuration introduction20529
|
Node: Configuration introduction20526
|
||||||
Node: Multiple networks21797
|
Node: Multiple networks21794
|
||||||
Node: How connections work23223
|
Node: How connections work23220
|
||||||
Node: Configuration files24445
|
Node: Configuration files24442
|
||||||
Node: Main configuration variables25939
|
Node: Main configuration variables25936
|
||||||
Node: Host configuration variables42195
|
Node: Host configuration variables42184
|
||||||
Node: Scripts47727
|
Node: Scripts47716
|
||||||
Node: How to configure50993
|
Node: How to configure50982
|
||||||
Node: Generating keypairs52251
|
Node: Generating keypairs52240
|
||||||
Node: Network interfaces52750
|
Node: Network interfaces52739
|
||||||
Node: Example configuration54598
|
Node: Example configuration54587
|
||||||
Node: Running tinc59923
|
Node: Running tinc59912
|
||||||
Node: Runtime options60513
|
Node: Runtime options60502
|
||||||
Node: Signals63815
|
Node: Signals64127
|
||||||
Node: Debug levels65006
|
Node: Debug levels65318
|
||||||
Node: Solving problems65942
|
Node: Solving problems66254
|
||||||
Node: Error messages67494
|
Node: Error messages67806
|
||||||
Node: Sending bug reports71503
|
Node: Sending bug reports71815
|
||||||
Node: Technical information72450
|
Node: Technical information72762
|
||||||
Node: The connection72681
|
Node: The connection72993
|
||||||
Node: The UDP tunnel72993
|
Node: The UDP tunnel73305
|
||||||
Node: The meta-connection76054
|
Node: The meta-connection76366
|
||||||
Node: The meta-protocol77523
|
Node: The meta-protocol77835
|
||||||
Node: Security82540
|
Node: Security82852
|
||||||
Node: Authentication protocol83682
|
Node: Authentication protocol83994
|
||||||
Node: Encryption of network packets88727
|
Node: Encryption of network packets89039
|
||||||
Node: Security issues90103
|
Node: Security issues90415
|
||||||
Node: Platform specific information91742
|
Node: Platform specific information92054
|
||||||
Node: Interface configuration91970
|
Node: Interface configuration92282
|
||||||
Node: Routes94441
|
Node: Routes94753
|
||||||
Node: About us96455
|
Node: About us96767
|
||||||
Node: Contact information96630
|
Node: Contact information96942
|
||||||
Node: Authors97033
|
Node: Authors97345
|
||||||
Node: Concept Index97438
|
Node: Concept Index97750
|
||||||
|
|
||||||
End Tag Table
|
End Tag Table
|
||||||
|
|
|
@ -860,7 +860,7 @@ Also note that this can cause decrypted VPN packets to be sent out on a real net
|
||||||
@cindex UML
|
@cindex UML
|
||||||
@item uml (not compiled in by default)
|
@item uml (not compiled in by default)
|
||||||
Create a UNIX socket with the filename specified by
|
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.
|
if not specified.
|
||||||
Tinc will wait for a User Mode Linux instance to connect to this socket.
|
Tinc will wait for a User Mode Linux instance to connect to this socket.
|
||||||
|
|
||||||
|
@ -868,7 +868,7 @@ Tinc will wait for a User Mode Linux instance to connect to this socket.
|
||||||
@item vde (not compiled in by default)
|
@item vde (not compiled in by default)
|
||||||
Uses the libvdeplug library to connect to a Virtual Distributed Ethernet switch,
|
Uses the libvdeplug library to connect to a Virtual Distributed Ethernet switch,
|
||||||
using the UNIX socket specified by
|
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.
|
if not specified.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
@ -1730,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}.
|
If @var{file} is omitted, the default is @file{@value{localstatedir}/log/tinc.@var{netname}.log}.
|
||||||
|
|
||||||
@item --pidfile=@var{file}
|
@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
|
@item --bypass-security
|
||||||
Disables encryption and authentication.
|
Disables encryption and authentication.
|
||||||
|
@ -1743,10 +1743,14 @@ located (@file{@value{sysconfdir}/tinc/@var{netname}/} as determined by
|
||||||
The chroot is performed after all the initialization is done, after
|
The chroot is performed after all the initialization is done, after
|
||||||
writing pid files and opening network sockets.
|
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),
|
You will need to ensure the chroot environment contains all the files necessary
|
||||||
unless it's setup to be runnable inside chroot environment.
|
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}
|
@item -U, --user=@var{user}
|
||||||
Switch to the given @var{user} after initialization, at the same time as
|
Switch to the given @var{user} after initialization, at the same time as
|
||||||
|
|
|
@ -109,7 +109,7 @@ is omitted, the default is
|
||||||
Write PID to
|
Write PID to
|
||||||
.Ar FILE
|
.Ar FILE
|
||||||
instead of
|
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.
|
Under Windows this option will be ignored.
|
||||||
.It Fl -bypass-security
|
.It Fl -bypass-security
|
||||||
Disables encryption and authentication of the meta protocol.
|
Disables encryption and authentication of the meta protocol.
|
||||||
|
@ -190,7 +190,7 @@ This will log all network traffic over the virtual private network.
|
||||||
Directory containing the configuration files tinc uses.
|
Directory containing the configuration files tinc uses.
|
||||||
For more information, see
|
For more information, see
|
||||||
.Xr tinc.conf 5 .
|
.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
|
The PID of the currently running
|
||||||
.Nm
|
.Nm
|
||||||
is stored in this file.
|
is stored in this file.
|
||||||
|
|
|
@ -2,3 +2,4 @@
|
||||||
@set PACKAGE @PACKAGE@
|
@set PACKAGE @PACKAGE@
|
||||||
@set sysconfdir @sysconfdir@
|
@set sysconfdir @sysconfdir@
|
||||||
@set localstatedir @localstatedir@
|
@set localstatedir @localstatedir@
|
||||||
|
@set runstatedir @runstatedir@
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
## Process this file with automake to produce Makefile.in -*-Makefile-*-
|
|
||||||
|
|
||||||
EXTRA_DIST = README *.m4
|
|
||||||
|
|
418
m4/Makefile.in
418
m4/Makefile.in
|
@ -1,418 +0,0 @@
|
||||||
# Makefile.in generated by automake 1.15.1 from Makefile.am.
|
|
||||||
# @configure_input@
|
|
||||||
|
|
||||||
# Copyright (C) 1994-2017 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
# This Makefile.in is free software; the Free Software Foundation
|
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
|
||||||
# with or without modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
|
||||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
# PARTICULAR PURPOSE.
|
|
||||||
|
|
||||||
@SET_MAKE@
|
|
||||||
VPATH = @srcdir@
|
|
||||||
am__is_gnu_make = { \
|
|
||||||
if test -z '$(MAKELEVEL)'; then \
|
|
||||||
false; \
|
|
||||||
elif test -n '$(MAKE_HOST)'; then \
|
|
||||||
true; \
|
|
||||||
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
|
||||||
true; \
|
|
||||||
else \
|
|
||||||
false; \
|
|
||||||
fi; \
|
|
||||||
}
|
|
||||||
am__make_running_with_option = \
|
|
||||||
case $${target_option-} in \
|
|
||||||
?) ;; \
|
|
||||||
*) echo "am__make_running_with_option: internal error: invalid" \
|
|
||||||
"target option '$${target_option-}' specified" >&2; \
|
|
||||||
exit 1;; \
|
|
||||||
esac; \
|
|
||||||
has_opt=no; \
|
|
||||||
sane_makeflags=$$MAKEFLAGS; \
|
|
||||||
if $(am__is_gnu_make); then \
|
|
||||||
sane_makeflags=$$MFLAGS; \
|
|
||||||
else \
|
|
||||||
case $$MAKEFLAGS in \
|
|
||||||
*\\[\ \ ]*) \
|
|
||||||
bs=\\; \
|
|
||||||
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
|
||||||
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
|
||||||
esac; \
|
|
||||||
fi; \
|
|
||||||
skip_next=no; \
|
|
||||||
strip_trailopt () \
|
|
||||||
{ \
|
|
||||||
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
|
||||||
}; \
|
|
||||||
for flg in $$sane_makeflags; do \
|
|
||||||
test $$skip_next = yes && { skip_next=no; continue; }; \
|
|
||||||
case $$flg in \
|
|
||||||
*=*|--*) continue;; \
|
|
||||||
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
|
||||||
-*I?*) strip_trailopt 'I';; \
|
|
||||||
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
|
||||||
-*O?*) strip_trailopt 'O';; \
|
|
||||||
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
|
||||||
-*l?*) strip_trailopt 'l';; \
|
|
||||||
-[dEDm]) skip_next=yes;; \
|
|
||||||
-[JT]) skip_next=yes;; \
|
|
||||||
esac; \
|
|
||||||
case $$flg in \
|
|
||||||
*$$target_option*) has_opt=yes; break;; \
|
|
||||||
esac; \
|
|
||||||
done; \
|
|
||||||
test $$has_opt = yes
|
|
||||||
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
|
||||||
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
|
||||||
pkgdatadir = $(datadir)/@PACKAGE@
|
|
||||||
pkgincludedir = $(includedir)/@PACKAGE@
|
|
||||||
pkglibdir = $(libdir)/@PACKAGE@
|
|
||||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
|
||||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
|
||||||
install_sh_DATA = $(install_sh) -c -m 644
|
|
||||||
install_sh_PROGRAM = $(install_sh) -c
|
|
||||||
install_sh_SCRIPT = $(install_sh) -c
|
|
||||||
INSTALL_HEADER = $(INSTALL_DATA)
|
|
||||||
transform = $(program_transform_name)
|
|
||||||
NORMAL_INSTALL = :
|
|
||||||
PRE_INSTALL = :
|
|
||||||
POST_INSTALL = :
|
|
||||||
NORMAL_UNINSTALL = :
|
|
||||||
PRE_UNINSTALL = :
|
|
||||||
POST_UNINSTALL = :
|
|
||||||
build_triplet = @build@
|
|
||||||
host_triplet = @host@
|
|
||||||
subdir = m4
|
|
||||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
|
||||||
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
|
|
||||||
$(top_srcdir)/m4/ax_append_flag.m4 \
|
|
||||||
$(top_srcdir)/m4/ax_cflags_warn_all.m4 \
|
|
||||||
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
|
|
||||||
$(top_srcdir)/m4/ax_check_link_flag.m4 \
|
|
||||||
$(top_srcdir)/m4/ax_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) \
|
|
||||||
$(ACLOCAL_M4)
|
|
||||||
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
|
|
||||||
mkinstalldirs = $(install_sh) -d
|
|
||||||
CONFIG_HEADER = $(top_builddir)/config.h
|
|
||||||
CONFIG_CLEAN_FILES =
|
|
||||||
CONFIG_CLEAN_VPATH_FILES =
|
|
||||||
AM_V_P = $(am__v_P_@AM_V@)
|
|
||||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
|
||||||
am__v_P_0 = false
|
|
||||||
am__v_P_1 = :
|
|
||||||
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
|
||||||
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
|
||||||
am__v_GEN_0 = @echo " GEN " $@;
|
|
||||||
am__v_GEN_1 =
|
|
||||||
AM_V_at = $(am__v_at_@AM_V@)
|
|
||||||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
|
||||||
am__v_at_0 = @
|
|
||||||
am__v_at_1 =
|
|
||||||
SOURCES =
|
|
||||||
DIST_SOURCES =
|
|
||||||
am__can_run_installinfo = \
|
|
||||||
case $$AM_UPDATE_INFO_DIR in \
|
|
||||||
n|no|NO) false;; \
|
|
||||||
*) (install-info --version) >/dev/null 2>&1;; \
|
|
||||||
esac
|
|
||||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
|
||||||
am__DIST_COMMON = $(srcdir)/Makefile.in README
|
|
||||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
|
||||||
ACLOCAL = @ACLOCAL@
|
|
||||||
AMTAR = @AMTAR@
|
|
||||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
|
||||||
AUTOCONF = @AUTOCONF@
|
|
||||||
AUTOHEADER = @AUTOHEADER@
|
|
||||||
AUTOMAKE = @AUTOMAKE@
|
|
||||||
AWK = @AWK@
|
|
||||||
CC = @CC@
|
|
||||||
CCDEPMODE = @CCDEPMODE@
|
|
||||||
CFLAGS = @CFLAGS@
|
|
||||||
CPP = @CPP@
|
|
||||||
CPPFLAGS = @CPPFLAGS@
|
|
||||||
CYGPATH_W = @CYGPATH_W@
|
|
||||||
DEFS = @DEFS@
|
|
||||||
DEPDIR = @DEPDIR@
|
|
||||||
ECHO_C = @ECHO_C@
|
|
||||||
ECHO_N = @ECHO_N@
|
|
||||||
ECHO_T = @ECHO_T@
|
|
||||||
EGREP = @EGREP@
|
|
||||||
EXEEXT = @EXEEXT@
|
|
||||||
GREP = @GREP@
|
|
||||||
INSTALL = @INSTALL@
|
|
||||||
INSTALL_DATA = @INSTALL_DATA@
|
|
||||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
|
||||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
|
||||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
|
||||||
LDFLAGS = @LDFLAGS@
|
|
||||||
LIBOBJS = @LIBOBJS@
|
|
||||||
LIBS = @LIBS@
|
|
||||||
LTLIBOBJS = @LTLIBOBJS@
|
|
||||||
MAINT = @MAINT@
|
|
||||||
MAKEINFO = @MAKEINFO@
|
|
||||||
MKDIR_P = @MKDIR_P@
|
|
||||||
OBJEXT = @OBJEXT@
|
|
||||||
PACKAGE = @PACKAGE@
|
|
||||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
|
||||||
PACKAGE_NAME = @PACKAGE_NAME@
|
|
||||||
PACKAGE_STRING = @PACKAGE_STRING@
|
|
||||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
|
||||||
PACKAGE_URL = @PACKAGE_URL@
|
|
||||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
|
||||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
|
||||||
PKG_CONFIG = @PKG_CONFIG@
|
|
||||||
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
|
||||||
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
|
||||||
SET_MAKE = @SET_MAKE@
|
|
||||||
SHELL = @SHELL@
|
|
||||||
STRIP = @STRIP@
|
|
||||||
VERSION = @VERSION@
|
|
||||||
abs_builddir = @abs_builddir@
|
|
||||||
abs_srcdir = @abs_srcdir@
|
|
||||||
abs_top_builddir = @abs_top_builddir@
|
|
||||||
abs_top_srcdir = @abs_top_srcdir@
|
|
||||||
ac_ct_CC = @ac_ct_CC@
|
|
||||||
am__include = @am__include@
|
|
||||||
am__leading_dot = @am__leading_dot@
|
|
||||||
am__quote = @am__quote@
|
|
||||||
am__tar = @am__tar@
|
|
||||||
am__untar = @am__untar@
|
|
||||||
bindir = @bindir@
|
|
||||||
build = @build@
|
|
||||||
build_alias = @build_alias@
|
|
||||||
build_cpu = @build_cpu@
|
|
||||||
build_os = @build_os@
|
|
||||||
build_vendor = @build_vendor@
|
|
||||||
builddir = @builddir@
|
|
||||||
datadir = @datadir@
|
|
||||||
datarootdir = @datarootdir@
|
|
||||||
docdir = @docdir@
|
|
||||||
dvidir = @dvidir@
|
|
||||||
exec_prefix = @exec_prefix@
|
|
||||||
host = @host@
|
|
||||||
host_alias = @host_alias@
|
|
||||||
host_cpu = @host_cpu@
|
|
||||||
host_os = @host_os@
|
|
||||||
host_vendor = @host_vendor@
|
|
||||||
htmldir = @htmldir@
|
|
||||||
includedir = @includedir@
|
|
||||||
infodir = @infodir@
|
|
||||||
install_sh = @install_sh@
|
|
||||||
libdir = @libdir@
|
|
||||||
libexecdir = @libexecdir@
|
|
||||||
localedir = @localedir@
|
|
||||||
localstatedir = @localstatedir@
|
|
||||||
mandir = @mandir@
|
|
||||||
mkdir_p = @mkdir_p@
|
|
||||||
oldincludedir = @oldincludedir@
|
|
||||||
pdfdir = @pdfdir@
|
|
||||||
prefix = @prefix@
|
|
||||||
program_transform_name = @program_transform_name@
|
|
||||||
psdir = @psdir@
|
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
|
||||||
sharedstatedir = @sharedstatedir@
|
|
||||||
srcdir = @srcdir@
|
|
||||||
sysconfdir = @sysconfdir@
|
|
||||||
systemdsystemunitdir = @systemdsystemunitdir@
|
|
||||||
target_alias = @target_alias@
|
|
||||||
top_build_prefix = @top_build_prefix@
|
|
||||||
top_builddir = @top_builddir@
|
|
||||||
top_srcdir = @top_srcdir@
|
|
||||||
EXTRA_DIST = README *.m4
|
|
||||||
all: all-am
|
|
||||||
|
|
||||||
.SUFFIXES:
|
|
||||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
|
||||||
@for dep in $?; do \
|
|
||||||
case '$(am__configure_deps)' in \
|
|
||||||
*$$dep*) \
|
|
||||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
|
||||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
|
||||||
exit 1;; \
|
|
||||||
esac; \
|
|
||||||
done; \
|
|
||||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu m4/Makefile'; \
|
|
||||||
$(am__cd) $(top_srcdir) && \
|
|
||||||
$(AUTOMAKE) --gnu m4/Makefile
|
|
||||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
|
||||||
@case '$?' in \
|
|
||||||
*config.status*) \
|
|
||||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
|
||||||
*) \
|
|
||||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
|
||||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
|
||||||
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)
|
|
||||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
|
||||||
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
|
||||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
|
||||||
$(am__aclocal_m4_deps):
|
|
||||||
tags TAGS:
|
|
||||||
|
|
||||||
ctags CTAGS:
|
|
||||||
|
|
||||||
cscope cscopelist:
|
|
||||||
|
|
||||||
|
|
||||||
distdir: $(DISTFILES)
|
|
||||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
|
||||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
|
||||||
list='$(DISTFILES)'; \
|
|
||||||
dist_files=`for file in $$list; do echo $$file; done | \
|
|
||||||
sed -e "s|^$$srcdirstrip/||;t" \
|
|
||||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
|
||||||
case $$dist_files in \
|
|
||||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
|
||||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
|
||||||
sort -u` ;; \
|
|
||||||
esac; \
|
|
||||||
for file in $$dist_files; do \
|
|
||||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
|
||||||
if test -d $$d/$$file; then \
|
|
||||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
|
||||||
if test -d "$(distdir)/$$file"; then \
|
|
||||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
|
||||||
fi; \
|
|
||||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
|
||||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
|
||||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
|
||||||
fi; \
|
|
||||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
|
||||||
else \
|
|
||||||
test -f "$(distdir)/$$file" \
|
|
||||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
|
||||||
|| exit 1; \
|
|
||||||
fi; \
|
|
||||||
done
|
|
||||||
check-am: all-am
|
|
||||||
check: check-am
|
|
||||||
all-am: Makefile
|
|
||||||
installdirs:
|
|
||||||
install: install-am
|
|
||||||
install-exec: install-exec-am
|
|
||||||
install-data: install-data-am
|
|
||||||
uninstall: uninstall-am
|
|
||||||
|
|
||||||
install-am: all-am
|
|
||||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
|
||||||
|
|
||||||
installcheck: installcheck-am
|
|
||||||
install-strip:
|
|
||||||
if test -z '$(STRIP)'; then \
|
|
||||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
|
||||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
|
||||||
install; \
|
|
||||||
else \
|
|
||||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
|
||||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
|
||||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
|
||||||
fi
|
|
||||||
mostlyclean-generic:
|
|
||||||
|
|
||||||
clean-generic:
|
|
||||||
|
|
||||||
distclean-generic:
|
|
||||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
|
||||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
|
||||||
|
|
||||||
maintainer-clean-generic:
|
|
||||||
@echo "This command is intended for maintainers to use"
|
|
||||||
@echo "it deletes files that may require special tools to rebuild."
|
|
||||||
clean: clean-am
|
|
||||||
|
|
||||||
clean-am: clean-generic mostlyclean-am
|
|
||||||
|
|
||||||
distclean: distclean-am
|
|
||||||
-rm -f Makefile
|
|
||||||
distclean-am: clean-am distclean-generic
|
|
||||||
|
|
||||||
dvi: dvi-am
|
|
||||||
|
|
||||||
dvi-am:
|
|
||||||
|
|
||||||
html: html-am
|
|
||||||
|
|
||||||
html-am:
|
|
||||||
|
|
||||||
info: info-am
|
|
||||||
|
|
||||||
info-am:
|
|
||||||
|
|
||||||
install-data-am:
|
|
||||||
|
|
||||||
install-dvi: install-dvi-am
|
|
||||||
|
|
||||||
install-dvi-am:
|
|
||||||
|
|
||||||
install-exec-am:
|
|
||||||
|
|
||||||
install-html: install-html-am
|
|
||||||
|
|
||||||
install-html-am:
|
|
||||||
|
|
||||||
install-info: install-info-am
|
|
||||||
|
|
||||||
install-info-am:
|
|
||||||
|
|
||||||
install-man:
|
|
||||||
|
|
||||||
install-pdf: install-pdf-am
|
|
||||||
|
|
||||||
install-pdf-am:
|
|
||||||
|
|
||||||
install-ps: install-ps-am
|
|
||||||
|
|
||||||
install-ps-am:
|
|
||||||
|
|
||||||
installcheck-am:
|
|
||||||
|
|
||||||
maintainer-clean: maintainer-clean-am
|
|
||||||
-rm -f Makefile
|
|
||||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
|
||||||
|
|
||||||
mostlyclean: mostlyclean-am
|
|
||||||
|
|
||||||
mostlyclean-am: mostlyclean-generic
|
|
||||||
|
|
||||||
pdf: pdf-am
|
|
||||||
|
|
||||||
pdf-am:
|
|
||||||
|
|
||||||
ps: ps-am
|
|
||||||
|
|
||||||
ps-am:
|
|
||||||
|
|
||||||
uninstall-am:
|
|
||||||
|
|
||||||
.MAKE: install-am install-strip
|
|
||||||
|
|
||||||
.PHONY: all all-am check check-am clean clean-generic cscopelist-am \
|
|
||||||
ctags-am distclean distclean-generic distdir dvi dvi-am html \
|
|
||||||
html-am info info-am install install-am install-data \
|
|
||||||
install-data-am install-dvi install-dvi-am install-exec \
|
|
||||||
install-exec-am install-html install-html-am install-info \
|
|
||||||
install-info-am install-man install-pdf install-pdf-am \
|
|
||||||
install-ps install-ps-am install-strip installcheck \
|
|
||||||
installcheck-am installdirs maintainer-clean \
|
|
||||||
maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
|
|
||||||
pdf-am ps ps-am tags-am uninstall uninstall-am
|
|
||||||
|
|
||||||
.PRECIOUS: Makefile
|
|
||||||
|
|
||||||
|
|
||||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
|
||||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
|
||||||
.NOEXPORT:
|
|
|
@ -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.
|
|
|
@ -54,5 +54,5 @@ AC_DEFUN([tinc_OPENSSL],
|
||||||
[#include <openssl/evp.h>]
|
[#include <openssl/evp.h>]
|
||||||
)
|
)
|
||||||
|
|
||||||
AC_CHECK_FUNCS([BN_GENCB_new ERR_remove_state RSA_set0_key], , , [#include <openssl/rsa.h>])
|
AC_CHECK_FUNCS([BN_GENCB_new RSA_set0_key], , , [#include <openssl/rsa.h>])
|
||||||
])
|
])
|
||||||
|
|
|
@ -14,7 +14,6 @@ tincd_SOURCES = \
|
||||||
edge.c edge.h \
|
edge.c edge.h \
|
||||||
ethernet.h \
|
ethernet.h \
|
||||||
event.c event.h \
|
event.c event.h \
|
||||||
fake-gai-errnos.h \
|
|
||||||
fake-getaddrinfo.c fake-getaddrinfo.h \
|
fake-getaddrinfo.c fake-getaddrinfo.h \
|
||||||
fake-getnameinfo.c fake-getnameinfo.h \
|
fake-getnameinfo.c fake-getnameinfo.h \
|
||||||
graph.c graph.h \
|
graph.c graph.h \
|
||||||
|
@ -44,8 +43,7 @@ tincd_SOURCES = \
|
||||||
subnet.c subnet.h \
|
subnet.c subnet.h \
|
||||||
tincd.c \
|
tincd.c \
|
||||||
utils.c utils.h \
|
utils.c utils.h \
|
||||||
xalloc.h \
|
xalloc.h
|
||||||
xmalloc.c
|
|
||||||
|
|
||||||
if !GETOPT
|
if !GETOPT
|
||||||
tincd_SOURCES += \
|
tincd_SOURCES += \
|
||||||
|
@ -88,4 +86,4 @@ if TUNEMU
|
||||||
LIBS += -lpcap
|
LIBS += -lpcap
|
||||||
endif
|
endif
|
||||||
|
|
||||||
AM_CPPFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\"
|
AM_CPPFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DRUNSTATEDIR=\"$(runstatedir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -I $(abs_top_builddir)/
|
||||||
|
|
|
@ -124,19 +124,18 @@ PROGRAMS = $(sbin_PROGRAMS)
|
||||||
am__tincd_SOURCES_DIST = have.h system.h avl_tree.c avl_tree.h conf.c \
|
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 \
|
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 \
|
dummy_device.c edge.c edge.h ethernet.h event.c event.h \
|
||||||
fake-gai-errnos.h fake-getaddrinfo.c fake-getaddrinfo.h \
|
fake-getaddrinfo.c fake-getaddrinfo.h fake-getnameinfo.c \
|
||||||
fake-getnameinfo.c fake-getnameinfo.h graph.c graph.h ipv4.h \
|
fake-getnameinfo.h graph.c graph.h ipv4.h ipv6.h list.c list.h \
|
||||||
ipv6.h list.c list.h logger.c logger.h meta.c meta.h \
|
logger.c logger.h meta.c meta.h multicast_device.c net.c net.h \
|
||||||
multicast_device.c net.c net.h net_packet.c net_setup.c \
|
net_packet.c net_setup.c net_socket.c netutl.c netutl.h node.c \
|
||||||
net_socket.c netutl.c netutl.h node.c node.h pidfile.c \
|
node.h pidfile.c pidfile.h process.c process.h protocol.c \
|
||||||
pidfile.h process.c process.h protocol.c protocol.h \
|
protocol.h protocol_auth.c protocol_edge.c protocol_misc.c \
|
||||||
protocol_auth.c protocol_edge.c protocol_misc.c protocol_key.c \
|
protocol_key.c protocol_subnet.c proxy.c proxy.h \
|
||||||
protocol_subnet.c proxy.c proxy.h raw_socket_device.c route.c \
|
raw_socket_device.c route.c route.h subnet.c subnet.h tincd.c \
|
||||||
route.h subnet.c subnet.h tincd.c utils.c utils.h xalloc.h \
|
utils.c utils.h xalloc.h getopt.c getopt.h getopt1.c \
|
||||||
xmalloc.c getopt.c getopt.h getopt1.c linux/device.c \
|
linux/device.c bsd/device.c bsd/tunemu.c bsd/tunemu.h \
|
||||||
bsd/device.c bsd/tunemu.c bsd/tunemu.h solaris/device.c \
|
solaris/device.c mingw/device.c mingw/common.h cygwin/device.c \
|
||||||
mingw/device.c mingw/common.h cygwin/device.c uml_device.c \
|
uml_device.c vde_device.c
|
||||||
vde_device.c
|
|
||||||
@GETOPT_FALSE@am__objects_1 = getopt.$(OBJEXT) getopt1.$(OBJEXT)
|
@GETOPT_FALSE@am__objects_1 = getopt.$(OBJEXT) getopt1.$(OBJEXT)
|
||||||
am__dirstamp = $(am__leading_dot)dirstamp
|
am__dirstamp = $(am__leading_dot)dirstamp
|
||||||
@LINUX_TRUE@am__objects_2 = linux/device.$(OBJEXT)
|
@LINUX_TRUE@am__objects_2 = linux/device.$(OBJEXT)
|
||||||
|
@ -159,10 +158,10 @@ am_tincd_OBJECTS = avl_tree.$(OBJEXT) conf.$(OBJEXT) \
|
||||||
protocol_misc.$(OBJEXT) protocol_key.$(OBJEXT) \
|
protocol_misc.$(OBJEXT) protocol_key.$(OBJEXT) \
|
||||||
protocol_subnet.$(OBJEXT) proxy.$(OBJEXT) \
|
protocol_subnet.$(OBJEXT) proxy.$(OBJEXT) \
|
||||||
raw_socket_device.$(OBJEXT) route.$(OBJEXT) subnet.$(OBJEXT) \
|
raw_socket_device.$(OBJEXT) route.$(OBJEXT) subnet.$(OBJEXT) \
|
||||||
tincd.$(OBJEXT) utils.$(OBJEXT) xmalloc.$(OBJEXT) \
|
tincd.$(OBJEXT) utils.$(OBJEXT) $(am__objects_1) \
|
||||||
$(am__objects_1) $(am__objects_2) $(am__objects_3) \
|
$(am__objects_2) $(am__objects_3) $(am__objects_4) \
|
||||||
$(am__objects_4) $(am__objects_5) $(am__objects_6) \
|
$(am__objects_5) $(am__objects_6) $(am__objects_7) \
|
||||||
$(am__objects_7) $(am__objects_8) $(am__objects_9)
|
$(am__objects_8) $(am__objects_9)
|
||||||
tincd_OBJECTS = $(am_tincd_OBJECTS)
|
tincd_OBJECTS = $(am_tincd_OBJECTS)
|
||||||
tincd_LDADD = $(LDADD)
|
tincd_LDADD = $(LDADD)
|
||||||
AM_V_P = $(am__v_P_@AM_V@)
|
AM_V_P = $(am__v_P_@AM_V@)
|
||||||
|
@ -251,7 +250,6 @@ LDFLAGS = @LDFLAGS@
|
||||||
LIBOBJS = @LIBOBJS@
|
LIBOBJS = @LIBOBJS@
|
||||||
LIBS = @LIBS@ $(am__append_10)
|
LIBS = @LIBS@ $(am__append_10)
|
||||||
LTLIBOBJS = @LTLIBOBJS@
|
LTLIBOBJS = @LTLIBOBJS@
|
||||||
MAINT = @MAINT@
|
|
||||||
MAKEINFO = @MAKEINFO@
|
MAKEINFO = @MAKEINFO@
|
||||||
MKDIR_P = @MKDIR_P@
|
MKDIR_P = @MKDIR_P@
|
||||||
OBJEXT = @OBJEXT@
|
OBJEXT = @OBJEXT@
|
||||||
|
@ -325,24 +323,24 @@ top_srcdir = @top_srcdir@
|
||||||
tincd_SOURCES = have.h system.h avl_tree.c avl_tree.h conf.c conf.h \
|
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 \
|
connection.c connection.h device.h dropin.c dropin.h \
|
||||||
dummy_device.c edge.c edge.h ethernet.h event.c event.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-getaddrinfo.c fake-getaddrinfo.h fake-getnameinfo.c \
|
||||||
fake-getnameinfo.c fake-getnameinfo.h graph.c graph.h ipv4.h \
|
fake-getnameinfo.h graph.c graph.h ipv4.h ipv6.h list.c list.h \
|
||||||
ipv6.h list.c list.h logger.c logger.h meta.c meta.h \
|
logger.c logger.h meta.c meta.h multicast_device.c net.c net.h \
|
||||||
multicast_device.c net.c net.h net_packet.c net_setup.c \
|
net_packet.c net_setup.c net_socket.c netutl.c netutl.h node.c \
|
||||||
net_socket.c netutl.c netutl.h node.c node.h pidfile.c \
|
node.h pidfile.c pidfile.h process.c process.h protocol.c \
|
||||||
pidfile.h process.c process.h protocol.c protocol.h \
|
protocol.h protocol_auth.c protocol_edge.c protocol_misc.c \
|
||||||
protocol_auth.c protocol_edge.c protocol_misc.c protocol_key.c \
|
protocol_key.c protocol_subnet.c proxy.c proxy.h \
|
||||||
protocol_subnet.c proxy.c proxy.h raw_socket_device.c route.c \
|
raw_socket_device.c route.c route.h subnet.c subnet.h tincd.c \
|
||||||
route.h subnet.c subnet.h tincd.c utils.c utils.h xalloc.h \
|
utils.c utils.h xalloc.h $(am__append_1) $(am__append_2) \
|
||||||
xmalloc.c $(am__append_1) $(am__append_2) $(am__append_3) \
|
$(am__append_3) $(am__append_4) $(am__append_5) \
|
||||||
$(am__append_4) $(am__append_5) $(am__append_6) \
|
$(am__append_6) $(am__append_7) $(am__append_8) \
|
||||||
$(am__append_7) $(am__append_8) $(am__append_9)
|
$(am__append_9)
|
||||||
AM_CPPFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\"
|
AM_CPPFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DRUNSTATEDIR=\"$(runstatedir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -I $(abs_top_builddir)/
|
||||||
all: all-am
|
all: all-am
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
.SUFFIXES: .c .o .obj
|
.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 \
|
@for dep in $?; do \
|
||||||
case '$(am__configure_deps)' in \
|
case '$(am__configure_deps)' in \
|
||||||
*$$dep*) \
|
*$$dep*) \
|
||||||
|
@ -366,9 +364,9 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
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
|
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
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
$(am__aclocal_m4_deps):
|
$(am__aclocal_m4_deps):
|
||||||
install-sbinPROGRAMS: $(sbin_PROGRAMS)
|
install-sbinPROGRAMS: $(sbin_PROGRAMS)
|
||||||
|
@ -525,7 +523,6 @@ distclean-compile:
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uml_device.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)/utils.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vde_device.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)/device.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@bsd/$(DEPDIR)/tunemu.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@cygwin/$(DEPDIR)/device.Po@am__quote@
|
||||||
|
|
228
src/avl_tree.c
228
src/avl_tree.c
|
@ -52,12 +52,12 @@
|
||||||
#ifndef AVL_DEPTH
|
#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;
|
int r = 1;
|
||||||
|
|
||||||
if(!u)
|
if(!u) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if(u & 0xffff0000) {
|
if(u & 0xffff0000) {
|
||||||
u >>= 16;
|
u >>= 16;
|
||||||
|
@ -79,8 +79,9 @@ static int lg(unsigned int u)
|
||||||
r += 2;
|
r += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(u & 0x00000002)
|
if(u & 0x00000002) {
|
||||||
r++;
|
r++;
|
||||||
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -88,8 +89,7 @@ static int lg(unsigned int u)
|
||||||
|
|
||||||
/* Internal helper functions */
|
/* 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
|
#ifdef AVL_DEPTH
|
||||||
int d;
|
int d;
|
||||||
|
|
||||||
|
@ -106,18 +106,19 @@ static int avl_check_balance(const avl_node_t *node)
|
||||||
pl = lg(AVL_L_COUNT(node));
|
pl = lg(AVL_L_COUNT(node));
|
||||||
r = AVL_R_COUNT(node);
|
r = AVL_R_COUNT(node);
|
||||||
|
|
||||||
if(r >> pl + 1)
|
if(r >> pl + 1) {
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if(pl < 2 || r >> pl - 2)
|
if(pl < 2 || r >> pl - 2) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
#endif
|
#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 *child;
|
||||||
avl_node_t *gchild;
|
avl_node_t *gchild;
|
||||||
avl_node_t *parent;
|
avl_node_t *parent;
|
||||||
|
@ -134,13 +135,17 @@ static void avl_rebalance(avl_tree_t *tree, avl_node_t *node)
|
||||||
case -1:
|
case -1:
|
||||||
child = node->left;
|
child = node->left;
|
||||||
#ifdef AVL_DEPTH
|
#ifdef AVL_DEPTH
|
||||||
|
|
||||||
if(L_AVL_DEPTH(child) >= R_AVL_DEPTH(child)) {
|
if(L_AVL_DEPTH(child) >= R_AVL_DEPTH(child)) {
|
||||||
#else
|
#else
|
||||||
|
|
||||||
if(AVL_L_COUNT(child) >= AVL_R_COUNT(child)) {
|
if(AVL_L_COUNT(child) >= AVL_R_COUNT(child)) {
|
||||||
#endif
|
#endif
|
||||||
node->left = child->right;
|
node->left = child->right;
|
||||||
if(node->left)
|
|
||||||
|
if(node->left) {
|
||||||
node->left->parent = node;
|
node->left->parent = node;
|
||||||
|
}
|
||||||
|
|
||||||
child->right = node;
|
child->right = node;
|
||||||
node->parent = child;
|
node->parent = child;
|
||||||
|
@ -158,12 +163,16 @@ static void avl_rebalance(avl_tree_t *tree, avl_node_t *node)
|
||||||
gchild = child->right;
|
gchild = child->right;
|
||||||
node->left = gchild->right;
|
node->left = gchild->right;
|
||||||
|
|
||||||
if(node->left)
|
if(node->left) {
|
||||||
node->left->parent = node;
|
node->left->parent = node;
|
||||||
|
}
|
||||||
|
|
||||||
child->right = gchild->left;
|
child->right = gchild->left;
|
||||||
|
|
||||||
if(child->right)
|
if(child->right) {
|
||||||
child->right->parent = child;
|
child->right->parent = child;
|
||||||
|
}
|
||||||
|
|
||||||
gchild->right = node;
|
gchild->right = node;
|
||||||
|
|
||||||
gchild->right->parent = gchild;
|
gchild->right->parent = gchild;
|
||||||
|
@ -184,18 +193,24 @@ static void avl_rebalance(avl_tree_t *tree, avl_node_t *node)
|
||||||
gchild->depth = AVL_CALC_DEPTH(gchild);
|
gchild->depth = AVL_CALC_DEPTH(gchild);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
child = node->right;
|
child = node->right;
|
||||||
#ifdef AVL_DEPTH
|
#ifdef AVL_DEPTH
|
||||||
|
|
||||||
if(R_AVL_DEPTH(child) >= L_AVL_DEPTH(child)) {
|
if(R_AVL_DEPTH(child) >= L_AVL_DEPTH(child)) {
|
||||||
#else
|
#else
|
||||||
|
|
||||||
if(AVL_R_COUNT(child) >= AVL_L_COUNT(child)) {
|
if(AVL_R_COUNT(child) >= AVL_L_COUNT(child)) {
|
||||||
#endif
|
#endif
|
||||||
node->right = child->left;
|
node->right = child->left;
|
||||||
if(node->right)
|
|
||||||
|
if(node->right) {
|
||||||
node->right->parent = node;
|
node->right->parent = node;
|
||||||
|
}
|
||||||
|
|
||||||
child->left = node;
|
child->left = node;
|
||||||
node->parent = child;
|
node->parent = child;
|
||||||
*superparent = child;
|
*superparent = child;
|
||||||
|
@ -212,12 +227,16 @@ static void avl_rebalance(avl_tree_t *tree, avl_node_t *node)
|
||||||
gchild = child->left;
|
gchild = child->left;
|
||||||
node->right = gchild->left;
|
node->right = gchild->left;
|
||||||
|
|
||||||
if(node->right)
|
if(node->right) {
|
||||||
node->right->parent = node;
|
node->right->parent = node;
|
||||||
|
}
|
||||||
|
|
||||||
child->left = gchild->right;
|
child->left = gchild->right;
|
||||||
|
|
||||||
if(child->left)
|
if(child->left) {
|
||||||
child->left->parent = child;
|
child->left->parent = child;
|
||||||
|
}
|
||||||
|
|
||||||
gchild->left = node;
|
gchild->left = node;
|
||||||
|
|
||||||
gchild->left->parent = gchild;
|
gchild->left->parent = gchild;
|
||||||
|
@ -238,6 +257,7 @@ static void avl_rebalance(avl_tree_t *tree, avl_node_t *node)
|
||||||
gchild->depth = AVL_CALC_DEPTH(gchild);
|
gchild->depth = AVL_CALC_DEPTH(gchild);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -248,14 +268,14 @@ static void avl_rebalance(avl_tree_t *tree, avl_node_t *node)
|
||||||
node->depth = AVL_CALC_DEPTH(node);
|
node->depth = AVL_CALC_DEPTH(node);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
node = parent;
|
node = parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (De)constructors */
|
/* (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;
|
avl_tree_t *tree;
|
||||||
|
|
||||||
tree = xmalloc_and_zero(sizeof(avl_tree_t));
|
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;
|
return tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
void avl_free_tree(avl_tree_t *tree)
|
void avl_free_tree(avl_tree_t *tree) {
|
||||||
{
|
|
||||||
free(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));
|
return xmalloc_and_zero(sizeof(avl_node_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
void avl_free_node(avl_tree_t *tree, avl_node_t *node)
|
void avl_free_node(avl_tree_t *tree, avl_node_t *node) {
|
||||||
{
|
if(node->data && tree->delete) {
|
||||||
if(node->data && tree->delete)
|
|
||||||
tree->delete(node->data);
|
tree->delete(node->data);
|
||||||
|
}
|
||||||
|
|
||||||
free(node);
|
free(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Searching */
|
/* 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;
|
avl_node_t *node;
|
||||||
|
|
||||||
node = avl_search_node(tree, data);
|
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;
|
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;
|
avl_node_t *node;
|
||||||
|
|
||||||
node = avl_search_closest_node(tree, data, result);
|
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;
|
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;
|
avl_node_t *node;
|
||||||
|
|
||||||
node = avl_search_closest_smaller_node(tree, data);
|
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;
|
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;
|
avl_node_t *node;
|
||||||
|
|
||||||
node = avl_search_closest_greater_node(tree, data);
|
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;
|
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;
|
avl_node_t *node;
|
||||||
int result;
|
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,
|
avl_node_t *avl_search_closest_node(const avl_tree_t *tree, const void *data,
|
||||||
int *result)
|
int *result) {
|
||||||
{
|
|
||||||
avl_node_t *node;
|
avl_node_t *node;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
node = tree->root;
|
node = tree->root;
|
||||||
|
|
||||||
if(!node) {
|
if(!node) {
|
||||||
if(result)
|
if(result) {
|
||||||
*result = 0;
|
*result = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
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);
|
c = tree->compare(data, node->data);
|
||||||
|
|
||||||
if(c < 0) {
|
if(c < 0) {
|
||||||
if(node->left)
|
if(node->left) {
|
||||||
node = node->left;
|
node = node->left;
|
||||||
else {
|
} else {
|
||||||
if(result)
|
if(result) {
|
||||||
*result = -1;
|
*result = -1;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if(c > 0) {
|
} else if(c > 0) {
|
||||||
if(node->right)
|
if(node->right) {
|
||||||
node = node->right;
|
node = node->right;
|
||||||
else {
|
} else {
|
||||||
if(result)
|
if(result) {
|
||||||
*result = 1;
|
*result = 1;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(result)
|
if(result) {
|
||||||
*result = 0;
|
*result = 0;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
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,
|
avl_node_t *avl_search_closest_smaller_node(const avl_tree_t *tree,
|
||||||
const void *data)
|
const void *data) {
|
||||||
{
|
|
||||||
avl_node_t *node;
|
avl_node_t *node;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
node = avl_search_closest_node(tree, data, &result);
|
node = avl_search_closest_node(tree, data, &result);
|
||||||
|
|
||||||
if(result < 0)
|
if(result < 0) {
|
||||||
node = node->prev;
|
node = node->prev;
|
||||||
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
avl_node_t *avl_search_closest_greater_node(const avl_tree_t *tree,
|
avl_node_t *avl_search_closest_greater_node(const avl_tree_t *tree,
|
||||||
const void *data)
|
const void *data) {
|
||||||
{
|
|
||||||
avl_node_t *node;
|
avl_node_t *node;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
node = avl_search_closest_node(tree, data, &result);
|
node = avl_search_closest_node(tree, data, &result);
|
||||||
|
|
||||||
if(result > 0)
|
if(result > 0) {
|
||||||
node = node->next;
|
node = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Insertion and deletion */
|
/* 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;
|
avl_node_t *closest, *new;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
|
@ -444,14 +463,13 @@ avl_node_t *avl_insert(avl_tree_t *tree, void *data)
|
||||||
return new;
|
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;
|
avl_node_t *closest;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if(!tree->root)
|
if(!tree->root) {
|
||||||
avl_insert_top(tree, node);
|
avl_insert_top(tree, node);
|
||||||
else {
|
} else {
|
||||||
closest = avl_search_closest_node(tree, node->data, &result);
|
closest = avl_search_closest_node(tree, node->data, &result);
|
||||||
|
|
||||||
switch(result) {
|
switch(result) {
|
||||||
|
@ -478,20 +496,20 @@ avl_node_t *avl_insert_node(avl_tree_t *tree, avl_node_t *node)
|
||||||
return 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;
|
node->prev = node->next = node->parent = NULL;
|
||||||
tree->head = tree->tail = tree->root = node;
|
tree->head = tree->tail = tree->root = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void avl_insert_before(avl_tree_t *tree, avl_node_t *before,
|
void avl_insert_before(avl_tree_t *tree, avl_node_t *before,
|
||||||
avl_node_t *node)
|
avl_node_t *node) {
|
||||||
{
|
|
||||||
if(!before) {
|
if(!before) {
|
||||||
if(tree->tail)
|
if(tree->tail) {
|
||||||
avl_insert_after(tree, tree->tail, node);
|
avl_insert_after(tree, tree->tail, node);
|
||||||
else
|
} else {
|
||||||
avl_insert_top(tree, node);
|
avl_insert_top(tree, node);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,10 +522,11 @@ void avl_insert_before(avl_tree_t *tree, avl_node_t *before,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(before->prev)
|
if(before->prev) {
|
||||||
before->prev->next = node;
|
before->prev->next = node;
|
||||||
else
|
} else {
|
||||||
tree->head = node;
|
tree->head = node;
|
||||||
|
}
|
||||||
|
|
||||||
before->prev = node;
|
before->prev = node;
|
||||||
before->left = node;
|
before->left = node;
|
||||||
|
@ -515,13 +534,14 @@ void avl_insert_before(avl_tree_t *tree, avl_node_t *before,
|
||||||
avl_rebalance(tree, 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(!after) {
|
||||||
if(tree->head)
|
if(tree->head) {
|
||||||
avl_insert_before(tree, tree->head, node);
|
avl_insert_before(tree, tree->head, node);
|
||||||
else
|
} else {
|
||||||
avl_insert_top(tree, node);
|
avl_insert_top(tree, node);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
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->parent = after;
|
||||||
node->next = after->next;
|
node->next = after->next;
|
||||||
|
|
||||||
if(after->next)
|
if(after->next) {
|
||||||
after->next->prev = node;
|
after->next->prev = node;
|
||||||
else
|
} else {
|
||||||
tree->tail = node;
|
tree->tail = node;
|
||||||
|
}
|
||||||
|
|
||||||
after->next = node;
|
after->next = node;
|
||||||
after->right = node;
|
after->right = node;
|
||||||
|
@ -545,33 +566,35 @@ void avl_insert_after(avl_tree_t *tree, avl_node_t *after, avl_node_t *node)
|
||||||
avl_rebalance(tree, after);
|
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;
|
avl_node_t *node;
|
||||||
|
|
||||||
node = avl_search_node(tree, data);
|
node = avl_search_node(tree, data);
|
||||||
|
|
||||||
if(node)
|
if(node) {
|
||||||
avl_unlink_node(tree, node);
|
avl_unlink_node(tree, node);
|
||||||
|
}
|
||||||
|
|
||||||
return 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 *parent;
|
||||||
avl_node_t **superparent;
|
avl_node_t **superparent;
|
||||||
avl_node_t *subst, *left, *right;
|
avl_node_t *subst, *left, *right;
|
||||||
avl_node_t *balnode;
|
avl_node_t *balnode;
|
||||||
|
|
||||||
if(node->prev)
|
if(node->prev) {
|
||||||
node->prev->next = node->next;
|
node->prev->next = node->next;
|
||||||
else
|
} else {
|
||||||
tree->head = node->next;
|
tree->head = node->next;
|
||||||
if(node->next)
|
}
|
||||||
|
|
||||||
|
if(node->next) {
|
||||||
node->next->prev = node->prev;
|
node->next->prev = node->prev;
|
||||||
else
|
} else {
|
||||||
tree->tail = node->prev;
|
tree->tail = node->prev;
|
||||||
|
}
|
||||||
|
|
||||||
parent = node->parent;
|
parent = node->parent;
|
||||||
|
|
||||||
|
@ -581,11 +604,13 @@ void avl_unlink_node(avl_tree_t *tree, avl_node_t *node)
|
||||||
|
|
||||||
left = node->left;
|
left = node->left;
|
||||||
right = node->right;
|
right = node->right;
|
||||||
|
|
||||||
if(!left) {
|
if(!left) {
|
||||||
*superparent = right;
|
*superparent = right;
|
||||||
|
|
||||||
if(right)
|
if(right) {
|
||||||
right->parent = parent;
|
right->parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
balnode = parent;
|
balnode = parent;
|
||||||
} else if(!right) {
|
} else if(!right) {
|
||||||
|
@ -594,8 +619,10 @@ void avl_unlink_node(avl_tree_t *tree, avl_node_t *node)
|
||||||
balnode = parent;
|
balnode = parent;
|
||||||
} else {
|
} else {
|
||||||
subst = node->prev;
|
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();
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
if(subst == left) {
|
if(subst == left) {
|
||||||
balnode = subst;
|
balnode = subst;
|
||||||
|
@ -603,8 +630,9 @@ void avl_unlink_node(avl_tree_t *tree, avl_node_t *node)
|
||||||
balnode = subst->parent;
|
balnode = subst->parent;
|
||||||
balnode->right = subst->left;
|
balnode->right = subst->left;
|
||||||
|
|
||||||
if(balnode->right)
|
if(balnode->right) {
|
||||||
balnode->right->parent = balnode;
|
balnode->right->parent = balnode;
|
||||||
|
}
|
||||||
|
|
||||||
subst->left = left;
|
subst->left = left;
|
||||||
left->parent = subst;
|
left->parent = subst;
|
||||||
|
@ -628,26 +656,24 @@ void avl_unlink_node(avl_tree_t *tree, avl_node_t *node)
|
||||||
#endif
|
#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_unlink_node(tree, node);
|
||||||
avl_free_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;
|
avl_node_t *node;
|
||||||
|
|
||||||
node = avl_search_node(tree, data);
|
node = avl_search_node(tree, data);
|
||||||
|
|
||||||
if(node)
|
if(node) {
|
||||||
avl_delete_node(tree, node);
|
avl_delete_node(tree, node);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Fast tree cleanup */
|
/* Fast tree cleanup */
|
||||||
|
|
||||||
void avl_delete_tree(avl_tree_t *tree)
|
void avl_delete_tree(avl_tree_t *tree) {
|
||||||
{
|
|
||||||
avl_node_t *node, *next;
|
avl_node_t *node, *next;
|
||||||
|
|
||||||
for(node = tree->head; node; node = next) {
|
for(node = tree->head; node; node = next) {
|
||||||
|
@ -660,8 +686,7 @@ void avl_delete_tree(avl_tree_t *tree)
|
||||||
|
|
||||||
/* Tree walking */
|
/* 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;
|
avl_node_t *node, *next;
|
||||||
|
|
||||||
for(node = tree->head; node; 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;
|
avl_node_t *node, *next;
|
||||||
|
|
||||||
for(node = tree->head; node; 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 */
|
/* Indexing */
|
||||||
|
|
||||||
#ifdef AVL_COUNT
|
#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);
|
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;
|
avl_node_t *node;
|
||||||
unsigned int c;
|
unsigned int c;
|
||||||
|
|
||||||
|
@ -711,16 +733,17 @@ avl_node_t *avl_get_node(const avl_tree_t *tree, unsigned int index)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int avl_index(const avl_node_t *node)
|
unsigned int avl_index(const avl_node_t *node) {
|
||||||
{
|
|
||||||
avl_node_t *next;
|
avl_node_t *next;
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
|
|
||||||
index = AVL_L_COUNT(node);
|
index = AVL_L_COUNT(node);
|
||||||
|
|
||||||
while((next = node->parent)) {
|
while((next = node->parent)) {
|
||||||
if(node == next->right)
|
if(node == next->right) {
|
||||||
index += AVL_L_COUNT(next) + 1;
|
index += AVL_L_COUNT(next) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
node = next;
|
node = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,8 +751,7 @@ unsigned int avl_index(const avl_node_t *node)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef AVL_DEPTH
|
#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);
|
return AVL_NODE_DEPTH(tree->root);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_AVL_TREE_H
|
||||||
|
#define TINC_AVL_TREE_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
avl_tree.h -- header file for avl_tree.c
|
avl_tree.h -- header file for avl_tree.c
|
||||||
Copyright (C) 1998 Michael H. Buselli
|
Copyright (C) 1998 Michael H. Buselli
|
||||||
|
@ -30,10 +33,6 @@
|
||||||
Guus Sliepen <guus@tinc-vpn.org>.
|
Guus Sliepen <guus@tinc-vpn.org>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef __AVL_TREE_H__
|
|
||||||
#define __AVL_TREE_H__
|
|
||||||
|
|
||||||
#ifndef AVL_DEPTH
|
#ifndef AVL_DEPTH
|
||||||
#ifndef AVL_COUNT
|
#ifndef AVL_COUNT
|
||||||
#define AVL_DEPTH
|
#define AVL_DEPTH
|
||||||
|
@ -66,9 +65,9 @@ typedef struct avl_node_t {
|
||||||
|
|
||||||
} avl_node_t;
|
} avl_node_t;
|
||||||
|
|
||||||
typedef int (*avl_compare_t)(const void *, const void *);
|
typedef int (*avl_compare_t)(const void *data1, const void *data2);
|
||||||
typedef void (*avl_action_t)(const void *);
|
typedef void (*avl_action_t)(const void *data);
|
||||||
typedef void (*avl_action_node_t)(const avl_node_t *);
|
typedef void (*avl_action_node_t)(const avl_node_t *node);
|
||||||
|
|
||||||
typedef struct avl_tree_t {
|
typedef struct avl_tree_t {
|
||||||
|
|
||||||
|
@ -88,56 +87,56 @@ typedef struct avl_tree_t {
|
||||||
|
|
||||||
/* (De)constructors */
|
/* (De)constructors */
|
||||||
|
|
||||||
extern avl_tree_t *avl_alloc_tree(avl_compare_t, avl_action_t);
|
extern avl_tree_t *avl_alloc_tree(avl_compare_t compare, avl_action_t delete);
|
||||||
extern void avl_free_tree(avl_tree_t *);
|
extern void avl_free_tree(avl_tree_t *tree);
|
||||||
|
|
||||||
extern avl_node_t *avl_alloc_node(void);
|
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 */
|
/* Insertion and deletion */
|
||||||
|
|
||||||
extern avl_node_t *avl_insert(avl_tree_t *, void *);
|
extern avl_node_t *avl_insert(avl_tree_t *tree, void *data);
|
||||||
extern avl_node_t *avl_insert_node(avl_tree_t *, avl_node_t *);
|
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_top(avl_tree_t *tree, avl_node_t *node);
|
||||||
extern void avl_insert_before(avl_tree_t *, avl_node_t *, avl_node_t *);
|
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 *, avl_node_t *, avl_node_t *);
|
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 avl_node_t *avl_unlink(avl_tree_t *tree, void *data);
|
||||||
extern void avl_unlink_node(avl_tree_t *tree, avl_node_t *);
|
extern void avl_unlink_node(avl_tree_t *tree, avl_node_t *node);
|
||||||
extern void avl_delete(avl_tree_t *, void *);
|
extern void avl_delete(avl_tree_t *tree, void *data);
|
||||||
extern void avl_delete_node(avl_tree_t *, avl_node_t *);
|
extern void avl_delete_node(avl_tree_t *tree, avl_node_t *node);
|
||||||
|
|
||||||
/* Fast tree cleanup */
|
/* Fast tree cleanup */
|
||||||
|
|
||||||
extern void avl_delete_tree(avl_tree_t *);
|
extern void avl_delete_tree(avl_tree_t *tree);
|
||||||
|
|
||||||
/* Searching */
|
/* Searching */
|
||||||
|
|
||||||
extern void *avl_search(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 *, const void *, int *);
|
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 *, const void *);
|
extern void *avl_search_closest_smaller(const avl_tree_t *tree, const void *data);
|
||||||
extern void *avl_search_closest_greater(const avl_tree_t *, const void *);
|
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_node(const avl_tree_t *tree, const void *data);
|
||||||
extern avl_node_t *avl_search_closest_node(const avl_tree_t *, const void *, int *);
|
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 *, const void *);
|
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 *, const void *);
|
extern avl_node_t *avl_search_closest_greater_node(const avl_tree_t *tree, const void *data);
|
||||||
|
|
||||||
/* Tree walking */
|
/* Tree walking */
|
||||||
|
|
||||||
extern void avl_foreach(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 *, avl_action_t);
|
extern void avl_foreach_node(const avl_tree_t *tree, avl_action_t action);
|
||||||
|
|
||||||
/* Indexing */
|
/* Indexing */
|
||||||
|
|
||||||
#ifdef AVL_COUNT
|
#ifdef AVL_COUNT
|
||||||
extern unsigned int avl_count(const avl_tree_t *);
|
extern unsigned int avl_count(const avl_tree_t *tree);
|
||||||
extern avl_node_t *avl_get_node(const avl_tree_t *, unsigned int);
|
extern avl_node_t *avl_get_node(const avl_tree_t *tree, unsigned int index);
|
||||||
extern unsigned int avl_index(const avl_node_t *);
|
extern unsigned int avl_index(const avl_node_t *node);
|
||||||
#endif
|
#endif
|
||||||
#ifdef AVL_DEPTH
|
#ifdef AVL_DEPTH
|
||||||
extern unsigned int avl_depth(const avl_tree_t *);
|
extern unsigned int avl_depth(const avl_tree_t *tree);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __AVL_TREE_H__ */
|
#endif
|
||||||
|
|
113
src/bsd/device.c
113
src/bsd/device.c
|
@ -55,7 +55,7 @@ typedef enum device_type {
|
||||||
int device_fd = -1;
|
int device_fd = -1;
|
||||||
char *device = NULL;
|
char *device = NULL;
|
||||||
char *iface = 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_in = 0;
|
||||||
static uint64_t device_total_out = 0;
|
static uint64_t device_total_out = 0;
|
||||||
#if defined(ENABLE_TUNEMU)
|
#if defined(ENABLE_TUNEMU)
|
||||||
|
@ -69,13 +69,15 @@ static device_type_t device_type = DEVICE_TYPE_TUN;
|
||||||
#ifdef HAVE_NET_IF_UTUN_H
|
#ifdef HAVE_NET_IF_UTUN_H
|
||||||
static bool setup_utun(void) {
|
static bool setup_utun(void) {
|
||||||
device_fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
|
device_fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
|
||||||
|
|
||||||
if(device_fd == -1) {
|
if(device_fd == -1) {
|
||||||
logger(LOG_ERR, "Could not open PF_SYSTEM socket: %s\n", strerror(errno));
|
logger(LOG_ERR, "Could not open PF_SYSTEM socket: %s\n", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ctl_info info = {};
|
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) {
|
if(ioctl(device_fd, CTLIOCGINFO, &info) == -1) {
|
||||||
logger(LOG_ERR, "ioctl(CTLIOCGINFO) failed: %s", strerror(errno));
|
logger(LOG_ERR, "ioctl(CTLIOCGINFO) failed: %s", strerror(errno));
|
||||||
|
@ -84,15 +86,18 @@ static bool setup_utun(void) {
|
||||||
|
|
||||||
int unit = -1;
|
int unit = -1;
|
||||||
char *p = strstr(device, "utun"), *e = NULL;
|
char *p = strstr(device, "utun"), *e = NULL;
|
||||||
|
|
||||||
if(p) {
|
if(p) {
|
||||||
unit = strtol(p + 4, &e, 10);
|
unit = strtol(p + 4, &e, 10);
|
||||||
if(!e)
|
|
||||||
|
if(!e) {
|
||||||
unit = -1;
|
unit = -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct sockaddr_ctl sc = {
|
struct sockaddr_ctl sc = {
|
||||||
.sc_id = info.ctl_id,
|
.sc_id = info.ctl_id,
|
||||||
.sc_len = sizeof sc,
|
.sc_len = sizeof(sc),
|
||||||
.sc_family = AF_SYSTEM,
|
.sc_family = AF_SYSTEM,
|
||||||
.ss_sysaddr = AF_SYS_CONTROL,
|
.ss_sysaddr = AF_SYS_CONTROL,
|
||||||
.sc_unit = unit + 1,
|
.sc_unit = unit + 1,
|
||||||
|
@ -104,15 +109,14 @@ static bool setup_utun(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
char name[64] = "";
|
char name[64] = "";
|
||||||
socklen_t len = sizeof name;
|
socklen_t len = sizeof(name);
|
||||||
|
|
||||||
if(getsockopt(device_fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, name, &len)) {
|
if(getsockopt(device_fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, name, &len)) {
|
||||||
iface = xstrdup(device);
|
iface = xstrdup(device);
|
||||||
} else {
|
} else {
|
||||||
iface = xstrdup(name);
|
iface = xstrdup(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
device_info = "OS X utun device";
|
|
||||||
|
|
||||||
logger(LOG_INFO, "%s is a %s", device, device_info);
|
logger(LOG_INFO, "%s is a %s", device, device_info);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -123,11 +127,12 @@ static bool setup_device(void) {
|
||||||
// Find out which device file to open
|
// Find out which device file to open
|
||||||
|
|
||||||
if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
|
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);
|
device = xstrdup(DEFAULT_TUN_DEVICE);
|
||||||
else
|
} else {
|
||||||
device = xstrdup(DEFAULT_TAP_DEVICE);
|
device = xstrdup(DEFAULT_TAP_DEVICE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Find out if it's supposed to be a tun or a tap device
|
// Find out if it's supposed to be a tun or a tap device
|
||||||
|
|
||||||
|
@ -136,33 +141,40 @@ static bool setup_device(void) {
|
||||||
if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
|
if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
|
||||||
if(!strcasecmp(type, "tun"))
|
if(!strcasecmp(type, "tun"))
|
||||||
/* use default */;
|
/* use default */;
|
||||||
|
|
||||||
#ifdef ENABLE_TUNEMU
|
#ifdef ENABLE_TUNEMU
|
||||||
else if(!strcasecmp(type, "tunemu"))
|
else if(!strcasecmp(type, "tunemu")) {
|
||||||
device_type = DEVICE_TYPE_TUNEMU;
|
device_type = DEVICE_TYPE_TUNEMU;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_NET_IF_UTUN_H
|
#ifdef HAVE_NET_IF_UTUN_H
|
||||||
else if(!strcasecmp(type, "utun"))
|
else if(!strcasecmp(type, "utun")) {
|
||||||
device_type = DEVICE_TYPE_UTUN;
|
device_type = DEVICE_TYPE_UTUN;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
else if(!strcasecmp(type, "tunnohead"))
|
else if(!strcasecmp(type, "tunnohead")) {
|
||||||
device_type = DEVICE_TYPE_TUN;
|
device_type = DEVICE_TYPE_TUN;
|
||||||
else if(!strcasecmp(type, "tunifhead"))
|
} else if(!strcasecmp(type, "tunifhead")) {
|
||||||
device_type = DEVICE_TYPE_TUNIFHEAD;
|
device_type = DEVICE_TYPE_TUNIFHEAD;
|
||||||
else if(!strcasecmp(type, "tap"))
|
} else if(!strcasecmp(type, "tap")) {
|
||||||
device_type = DEVICE_TYPE_TAP;
|
device_type = DEVICE_TYPE_TAP;
|
||||||
else {
|
} else {
|
||||||
logger(LOG_ERR, "Unknown device type %s!", type);
|
logger(LOG_ERR, "Unknown device type %s!", type);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#ifdef HAVE_NET_IF_UTUN_H
|
#ifdef HAVE_NET_IF_UTUN_H
|
||||||
if(strncmp(device, "utun", 4) == 0 || strncmp(device, "/dev/utun", 9) == 0)
|
|
||||||
|
if(strncmp(device, "utun", 4) == 0 || strncmp(device, "/dev/utun", 9) == 0) {
|
||||||
device_type = DEVICE_TYPE_UTUN;
|
device_type = DEVICE_TYPE_UTUN;
|
||||||
else
|
} else
|
||||||
#endif
|
#endif
|
||||||
if(strstr(device, "tap") || routing_mode != RMODE_ROUTER)
|
if(strstr(device, "tap") || routing_mode != RMODE_ROUTER) {
|
||||||
device_type = DEVICE_TYPE_TAP;
|
device_type = DEVICE_TYPE_TAP;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(routing_mode == RMODE_SWITCH && device_type != DEVICE_TYPE_TAP) {
|
if(routing_mode == RMODE_SWITCH && device_type != DEVICE_TYPE_TAP) {
|
||||||
logger(LOG_ERR, "Only tap devices support switch mode!");
|
logger(LOG_ERR, "Only tap devices support switch mode!");
|
||||||
|
@ -173,6 +185,7 @@ static bool setup_device(void) {
|
||||||
|
|
||||||
switch(device_type) {
|
switch(device_type) {
|
||||||
#ifdef ENABLE_TUNEMU
|
#ifdef ENABLE_TUNEMU
|
||||||
|
|
||||||
case DEVICE_TYPE_TUNEMU: {
|
case DEVICE_TYPE_TUNEMU: {
|
||||||
char dynamic_name[256] = "";
|
char dynamic_name[256] = "";
|
||||||
device_fd = tunemu_open(dynamic_name);
|
device_fd = tunemu_open(dynamic_name);
|
||||||
|
@ -180,9 +193,11 @@ static bool setup_device(void) {
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_NET_IF_UTUN_H
|
#ifdef HAVE_NET_IF_UTUN_H
|
||||||
|
|
||||||
case DEVICE_TYPE_UTUN:
|
case DEVICE_TYPE_UTUN:
|
||||||
return setup_utun();
|
return setup_utun();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
device_fd = open(device, O_RDWR | O_NONBLOCK);
|
device_fd = open(device, O_RDWR | O_NONBLOCK);
|
||||||
}
|
}
|
||||||
|
@ -204,71 +219,88 @@ static bool setup_device(void) {
|
||||||
realname = fdevname(device_fd);
|
realname = fdevname(device_fd);
|
||||||
#elif defined(HAVE_DEVNAME)
|
#elif defined(HAVE_DEVNAME)
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
if(!fstat(device_fd, &buf))
|
|
||||||
|
if(!fstat(device_fd, &buf)) {
|
||||||
realname = devname(buf.st_rdev, S_IFCHR);
|
realname = devname(buf.st_rdev, S_IFCHR);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(!realname)
|
if(!realname) {
|
||||||
realname = device;
|
realname = device;
|
||||||
|
}
|
||||||
|
|
||||||
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
|
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) {
|
||||||
iface = xstrdup(strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname);
|
iface = xstrdup(strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname);
|
||||||
else if(strcmp(iface, strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname))
|
} else if(strcmp(iface, strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname)) {
|
||||||
logger(LOG_WARNING, "Warning: Interface does not match Device. $INTERFACE might be set incorrectly.");
|
logger(LOG_WARNING, "Warning: Interface does not match Device. $INTERFACE might be set incorrectly.");
|
||||||
|
}
|
||||||
|
|
||||||
// Configure the device as best as we can
|
// Configure the device as best as we can
|
||||||
|
|
||||||
switch(device_type) {
|
switch(device_type) {
|
||||||
default:
|
default:
|
||||||
device_type = DEVICE_TYPE_TUN;
|
device_type = DEVICE_TYPE_TUN;
|
||||||
|
|
||||||
case DEVICE_TYPE_TUN:
|
case DEVICE_TYPE_TUN:
|
||||||
#ifdef TUNSIFHEAD
|
#ifdef TUNSIFHEAD
|
||||||
{
|
{
|
||||||
const int zero = 0;
|
const int zero = 0;
|
||||||
if(ioctl(device_fd, TUNSIFHEAD, &zero, sizeof zero) == -1) {
|
|
||||||
|
if(ioctl(device_fd, TUNSIFHEAD, &zero, sizeof(zero)) == -1) {
|
||||||
logger(LOG_ERR, "System call `%s' failed: %s", "ioctl", strerror(errno));
|
logger(LOG_ERR, "System call `%s' failed: %s", "ioctl", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#if defined(TUNSIFMODE) && defined(IFF_BROADCAST) && defined(IFF_MULTICAST)
|
#if defined(TUNSIFMODE) && defined(IFF_BROADCAST) && defined(IFF_MULTICAST)
|
||||||
{
|
{
|
||||||
const int mode = IFF_BROADCAST | IFF_MULTICAST;
|
const int mode = IFF_BROADCAST | IFF_MULTICAST;
|
||||||
ioctl(device_fd, TUNSIFMODE, &mode, sizeof mode);
|
ioctl(device_fd, TUNSIFMODE, &mode, sizeof(mode));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
device_info = "Generic BSD tun device";
|
device_info = "Generic BSD tun device";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEVICE_TYPE_TUNIFHEAD:
|
case DEVICE_TYPE_TUNIFHEAD:
|
||||||
#ifdef TUNSIFHEAD
|
#ifdef TUNSIFHEAD
|
||||||
{
|
{
|
||||||
const int one = 1;
|
const int one = 1;
|
||||||
if(ioctl(device_fd, TUNSIFHEAD, &one, sizeof one) == -1) {
|
|
||||||
|
if(ioctl(device_fd, TUNSIFHEAD, &one, sizeof(one)) == -1) {
|
||||||
logger(LOG_ERR, "System call `%s' failed: %s", "ioctl", strerror(errno));
|
logger(LOG_ERR, "System call `%s' failed: %s", "ioctl", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#if defined(TUNSIFMODE) && defined(IFF_BROADCAST) && defined(IFF_MULTICAST)
|
#if defined(TUNSIFMODE) && defined(IFF_BROADCAST) && defined(IFF_MULTICAST)
|
||||||
{
|
{
|
||||||
const int mode = IFF_BROADCAST | IFF_MULTICAST;
|
const int mode = IFF_BROADCAST | IFF_MULTICAST;
|
||||||
ioctl(device_fd, TUNSIFMODE, &mode, sizeof mode);
|
ioctl(device_fd, TUNSIFMODE, &mode, sizeof(mode));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
device_info = "Generic BSD tun device";
|
device_info = "Generic BSD tun device";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEVICE_TYPE_TAP:
|
case DEVICE_TYPE_TAP:
|
||||||
if(routing_mode == RMODE_ROUTER)
|
if(routing_mode == RMODE_ROUTER) {
|
||||||
overwrite_mac = true;
|
overwrite_mac = true;
|
||||||
|
}
|
||||||
|
|
||||||
device_info = "Generic BSD tap device";
|
device_info = "Generic BSD tap device";
|
||||||
#ifdef TAPGIFNAME
|
#ifdef TAPGIFNAME
|
||||||
{
|
{
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
|
|
||||||
if(ioctl(device_fd, TAPGIFNAME, (void *)&ifr) == 0) {
|
if(ioctl(device_fd, TAPGIFNAME, (void *)&ifr) == 0) {
|
||||||
if(iface)
|
if(iface) {
|
||||||
free(iface);
|
free(iface);
|
||||||
|
}
|
||||||
|
|
||||||
iface = xstrdup(ifr.ifr_name);
|
iface = xstrdup(ifr.ifr_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -276,6 +308,7 @@ static bool setup_device(void) {
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
#ifdef ENABLE_TUNEMU
|
#ifdef ENABLE_TUNEMU
|
||||||
|
|
||||||
case DEVICE_TYPE_TUNEMU:
|
case DEVICE_TYPE_TUNEMU:
|
||||||
device_info = "BSD tunemu device";
|
device_info = "BSD tunemu device";
|
||||||
break;
|
break;
|
||||||
|
@ -283,8 +316,11 @@ static bool setup_device(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SIOCGIFADDR
|
#ifdef SIOCGIFADDR
|
||||||
if(overwrite_mac)
|
|
||||||
|
if(overwrite_mac) {
|
||||||
ioctl(device_fd, SIOCGIFADDR, mymac.x);
|
ioctl(device_fd, SIOCGIFADDR, mymac.x);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
logger(LOG_INFO, "%s is a %s", device, device_info);
|
logger(LOG_INFO, "%s is a %s", device, device_info);
|
||||||
|
@ -295,10 +331,12 @@ static bool setup_device(void) {
|
||||||
static void close_device(void) {
|
static void close_device(void) {
|
||||||
switch(device_type) {
|
switch(device_type) {
|
||||||
#ifdef ENABLE_TUNEMU
|
#ifdef ENABLE_TUNEMU
|
||||||
|
|
||||||
case DEVICE_TYPE_TUNEMU:
|
case DEVICE_TYPE_TUNEMU:
|
||||||
tunemu_close(device_fd);
|
tunemu_close(device_fd);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
close(device_fd);
|
close(device_fd);
|
||||||
}
|
}
|
||||||
|
@ -314,9 +352,9 @@ static bool read_packet(vpn_packet_t *packet) {
|
||||||
case DEVICE_TYPE_TUN:
|
case DEVICE_TYPE_TUN:
|
||||||
#ifdef ENABLE_TUNEMU
|
#ifdef ENABLE_TUNEMU
|
||||||
case DEVICE_TYPE_TUNEMU:
|
case DEVICE_TYPE_TUNEMU:
|
||||||
if(device_type == DEVICE_TYPE_TUNEMU)
|
if(device_type == DEVICE_TYPE_TUNEMU) {
|
||||||
lenin = tunemu_read(device_fd, packet->data + 14, MTU - 14);
|
lenin = tunemu_read(device_fd, packet->data + 14, MTU - 14);
|
||||||
else
|
} else
|
||||||
#endif
|
#endif
|
||||||
lenin = read(device_fd, packet->data + 14, MTU - 14);
|
lenin = read(device_fd, packet->data + 14, MTU - 14);
|
||||||
|
|
||||||
|
@ -331,10 +369,12 @@ static bool read_packet(vpn_packet_t *packet) {
|
||||||
packet->data[12] = 0x08;
|
packet->data[12] = 0x08;
|
||||||
packet->data[13] = 0x00;
|
packet->data[13] = 0x00;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6:
|
case 6:
|
||||||
packet->data[12] = 0x86;
|
packet->data[12] = 0x86;
|
||||||
packet->data[13] = 0xDD;
|
packet->data[13] = 0xDD;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ifdebug(TRAFFIC) logger(LOG_ERR,
|
ifdebug(TRAFFIC) logger(LOG_ERR,
|
||||||
"Unknown IP version %d while reading packet from %s %s",
|
"Unknown IP version %d while reading packet from %s %s",
|
||||||
|
@ -359,10 +399,12 @@ static bool read_packet(vpn_packet_t *packet) {
|
||||||
packet->data[12] = 0x08;
|
packet->data[12] = 0x08;
|
||||||
packet->data[13] = 0x00;
|
packet->data[13] = 0x00;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6:
|
case 6:
|
||||||
packet->data[12] = 0x86;
|
packet->data[12] = 0x86;
|
||||||
packet->data[13] = 0xDD;
|
packet->data[13] = 0xDD;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ifdebug(TRAFFIC) logger(LOG_ERR,
|
ifdebug(TRAFFIC) logger(LOG_ERR,
|
||||||
"Unknown IP version %d while reading packet from %s %s",
|
"Unknown IP version %d while reading packet from %s %s",
|
||||||
|
@ -408,6 +450,7 @@ static bool write_packet(vpn_packet_t *packet) {
|
||||||
device, strerror(errno));
|
device, strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEVICE_TYPE_UTUN:
|
case DEVICE_TYPE_UTUN:
|
||||||
|
@ -419,9 +462,11 @@ static bool write_packet(vpn_packet_t *packet) {
|
||||||
case 0x0800:
|
case 0x0800:
|
||||||
type = htonl(AF_INET);
|
type = htonl(AF_INET);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x86DD:
|
case 0x86DD:
|
||||||
type = htonl(AF_INET6);
|
type = htonl(AF_INET6);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ifdebug(TRAFFIC) logger(LOG_ERR,
|
ifdebug(TRAFFIC) logger(LOG_ERR,
|
||||||
"Unknown address family %x while writing packet to %s %s",
|
"Unknown address family %x while writing packet to %s %s",
|
||||||
|
@ -429,13 +474,14 @@ static bool write_packet(vpn_packet_t *packet) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(packet->data + 10, &type, sizeof type);
|
memcpy(packet->data + 10, &type, sizeof(type));
|
||||||
|
|
||||||
if(write(device_fd, packet->data + 10, packet->len - 10) < 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,
|
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,15 +491,18 @@ static bool write_packet(vpn_packet_t *packet) {
|
||||||
device, strerror(errno));
|
device, strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef ENABLE_TUNEMU
|
#ifdef ENABLE_TUNEMU
|
||||||
|
|
||||||
case DEVICE_TYPE_TUNEMU:
|
case DEVICE_TYPE_TUNEMU:
|
||||||
if(tunemu_write(device_fd, packet->data + 14, packet->len - 14) < 0) {
|
if(tunemu_write(device_fd, packet->data + 14, packet->len - 14) < 0) {
|
||||||
logger(LOG_ERR, "Error while writing to %s %s: %s", device_info,
|
logger(LOG_ERR, "Error while writing to %s %s: %s", device_info,
|
||||||
device, strerror(errno));
|
device, strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
177
src/bsd/tunemu.c
177
src/bsd/tunemu.c
|
@ -49,24 +49,21 @@
|
||||||
#define PPPIOCCONNECT _IOW('t', 58, int)
|
#define PPPIOCCONNECT _IOW('t', 58, int)
|
||||||
#define PPPIOCGUNIT _IOR('t', 86, int)
|
#define PPPIOCGUNIT _IOR('t', 86, int)
|
||||||
|
|
||||||
struct sockaddr_ppp
|
struct sockaddr_ppp {
|
||||||
{
|
|
||||||
u_int8_t ppp_len;
|
u_int8_t ppp_len;
|
||||||
u_int8_t ppp_family;
|
u_int8_t ppp_family;
|
||||||
u_int16_t ppp_proto;
|
u_int16_t ppp_proto;
|
||||||
u_int32_t ppp_cookie;
|
u_int32_t ppp_cookie;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum NPmode
|
enum NPmode {
|
||||||
{
|
|
||||||
NPMODE_PASS,
|
NPMODE_PASS,
|
||||||
NPMODE_DROP,
|
NPMODE_DROP,
|
||||||
NPMODE_ERROR,
|
NPMODE_ERROR,
|
||||||
NPMODE_QUEUE
|
NPMODE_QUEUE
|
||||||
};
|
};
|
||||||
|
|
||||||
struct npioctl
|
struct npioctl {
|
||||||
{
|
|
||||||
int protocol;
|
int protocol;
|
||||||
enum NPmode mode;
|
enum NPmode mode;
|
||||||
};
|
};
|
||||||
|
@ -83,58 +80,55 @@ static pcap_t *pcap = NULL;
|
||||||
static int data_buffer_length = 0;
|
static int data_buffer_length = 0;
|
||||||
static char *data_buffer = NULL;
|
static char *data_buffer = NULL;
|
||||||
|
|
||||||
static void tun_error(char *format, ...)
|
static void tun_error(char *format, ...) {
|
||||||
{
|
|
||||||
va_list vl;
|
va_list vl;
|
||||||
va_start(vl, format);
|
va_start(vl, format);
|
||||||
vsnprintf(tunemu_error, ERROR_BUFFER_SIZE, format, vl);
|
vsnprintf(tunemu_error, ERROR_BUFFER_SIZE, format, vl);
|
||||||
va_end(vl);
|
va_end(vl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tun_noerror()
|
static void tun_noerror() {
|
||||||
{
|
|
||||||
*tunemu_error = 0;
|
*tunemu_error = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void closeall()
|
static void closeall() {
|
||||||
{
|
|
||||||
int fd = getdtablesize();
|
int fd = getdtablesize();
|
||||||
while (fd--)
|
|
||||||
|
while(fd--) {
|
||||||
close(fd);
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
open("/dev/null", O_RDWR, 0);
|
open("/dev/null", O_RDWR, 0);
|
||||||
dup(0);
|
dup(0);
|
||||||
dup(0);
|
dup(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ppp_load_kext()
|
static int ppp_load_kext() {
|
||||||
{
|
|
||||||
int pid = fork();
|
int pid = fork();
|
||||||
if (pid < 0)
|
|
||||||
{
|
if(pid < 0) {
|
||||||
tun_error("fork for ppp kext: %s", strerror(errno));
|
tun_error("fork for ppp kext: %s", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pid == 0)
|
if(pid == 0) {
|
||||||
{
|
|
||||||
closeall();
|
closeall();
|
||||||
execle("/sbin/kextload", "kextload", PPP_KEXT_PATH, NULL, NULL);
|
execle("/sbin/kextload", "kextload", PPP_KEXT_PATH, NULL, NULL);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int status;
|
int status;
|
||||||
while (waitpid(pid, &status, 0) < 0)
|
|
||||||
{
|
while(waitpid(pid, &status, 0) < 0) {
|
||||||
if (errno == EINTR)
|
if(errno == EINTR) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
tun_error("waitpid for ppp kext: %s", strerror(errno));
|
tun_error("waitpid for ppp kext: %s", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WEXITSTATUS(status) != 0)
|
if(WEXITSTATUS(status) != 0) {
|
||||||
{
|
|
||||||
tun_error("could not load ppp kext \"%s\"", PPP_KEXT_PATH);
|
tun_error("could not load ppp kext \"%s\"", PPP_KEXT_PATH);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -143,18 +137,18 @@ static int ppp_load_kext()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ppp_new_instance()
|
static int ppp_new_instance() {
|
||||||
{
|
|
||||||
// create ppp socket
|
// create ppp socket
|
||||||
int ppp_sockfd = socket(PF_PPP, SOCK_RAW, PPPPROTO_CTL);
|
int ppp_sockfd = socket(PF_PPP, SOCK_RAW, PPPPROTO_CTL);
|
||||||
if (ppp_sockfd < 0)
|
|
||||||
{
|
if(ppp_sockfd < 0) {
|
||||||
if (ppp_load_kext() < 0)
|
if(ppp_load_kext() < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
ppp_sockfd = socket(PF_PPP, SOCK_RAW, PPPPROTO_CTL);
|
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));
|
tun_error("creating ppp socket: %s", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -166,8 +160,8 @@ static int ppp_new_instance()
|
||||||
pppaddr.ppp_family = AF_PPP;
|
pppaddr.ppp_family = AF_PPP;
|
||||||
pppaddr.ppp_proto = PPPPROTO_CTL;
|
pppaddr.ppp_proto = PPPPROTO_CTL;
|
||||||
pppaddr.ppp_cookie = 0;
|
pppaddr.ppp_cookie = 0;
|
||||||
if (connect(ppp_sockfd, (struct sockaddr *)&pppaddr, sizeof(struct sockaddr_ppp)) < 0)
|
|
||||||
{
|
if(connect(ppp_sockfd, (struct sockaddr *)&pppaddr, sizeof(struct sockaddr_ppp)) < 0) {
|
||||||
tun_error("connecting ppp socket: %s", strerror(errno));
|
tun_error("connecting ppp socket: %s", strerror(errno));
|
||||||
close(ppp_sockfd);
|
close(ppp_sockfd);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -177,15 +171,15 @@ static int ppp_new_instance()
|
||||||
return ppp_sockfd;
|
return ppp_sockfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ppp_new_unit(int *unit_number)
|
static int ppp_new_unit(int *unit_number) {
|
||||||
{
|
|
||||||
int fd = ppp_new_instance();
|
int fd = ppp_new_instance();
|
||||||
if (fd < 0)
|
|
||||||
|
if(fd < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// create ppp unit
|
// 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));
|
tun_error("creating ppp unit: %s", strerror(errno));
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -195,12 +189,11 @@ static int ppp_new_unit(int *unit_number)
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ppp_setup_unit(int unit_fd)
|
static int ppp_setup_unit(int unit_fd) {
|
||||||
{
|
|
||||||
// send traffic to program
|
// send traffic to program
|
||||||
int flags = SC_LOOP_TRAFFIC;
|
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));
|
tun_error("setting ppp loopback mode: %s", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -209,8 +202,8 @@ static int ppp_setup_unit(int unit_fd)
|
||||||
struct npioctl npi;
|
struct npioctl npi;
|
||||||
npi.protocol = PPP_IP;
|
npi.protocol = PPP_IP;
|
||||||
npi.mode = NPMODE_PASS;
|
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));
|
tun_error("starting ppp unit: %s", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -219,10 +212,8 @@ static int ppp_setup_unit(int unit_fd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int open_pcap()
|
static int open_pcap() {
|
||||||
{
|
if(pcap != NULL) {
|
||||||
if (pcap != NULL)
|
|
||||||
{
|
|
||||||
pcap_use_count++;
|
pcap_use_count++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -231,8 +222,7 @@ static int open_pcap()
|
||||||
pcap = pcap_open_live("lo0", BUFSIZ, 0, 1, errbuf);
|
pcap = pcap_open_live("lo0", BUFSIZ, 0, 1, errbuf);
|
||||||
pcap_use_count = 1;
|
pcap_use_count = 1;
|
||||||
|
|
||||||
if (pcap == NULL)
|
if(pcap == NULL) {
|
||||||
{
|
|
||||||
tun_error("opening pcap: %s", errbuf);
|
tun_error("opening pcap: %s", errbuf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -241,59 +231,57 @@ static int open_pcap()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void close_pcap()
|
static void close_pcap() {
|
||||||
{
|
if(pcap == NULL) {
|
||||||
if (pcap == NULL)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pcap_use_count--;
|
pcap_use_count--;
|
||||||
if (pcap_use_count == 0)
|
|
||||||
{
|
if(pcap_use_count == 0) {
|
||||||
pcap_close(pcap);
|
pcap_close(pcap);
|
||||||
pcap = NULL;
|
pcap = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void allocate_data_buffer(int size)
|
static void allocate_data_buffer(int size) {
|
||||||
{
|
if(data_buffer_length < size) {
|
||||||
if (data_buffer_length < size)
|
|
||||||
{
|
|
||||||
free(data_buffer);
|
free(data_buffer);
|
||||||
data_buffer_length = size;
|
data_buffer_length = size;
|
||||||
data_buffer = malloc(data_buffer_length);
|
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);
|
snprintf(device, sizeof(tunemu_device), "ppp%d", unit_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_device_name(tunemu_device device)
|
static int check_device_name(tunemu_device device) {
|
||||||
{
|
if(strlen(device) < 4) {
|
||||||
if (strlen(device) < 4)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int unit_number = atoi(device + 3);
|
int unit_number = atoi(device + 3);
|
||||||
if (unit_number < 0 || unit_number > 999)
|
|
||||||
|
if(unit_number < 0 || unit_number > 999) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
tunemu_device compare;
|
tunemu_device compare;
|
||||||
make_device_name(compare, unit_number);
|
make_device_name(compare, unit_number);
|
||||||
|
|
||||||
if (strcmp(device, compare) != 0)
|
if(strcmp(device, compare) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tunemu_open(tunemu_device device)
|
int tunemu_open(tunemu_device device) {
|
||||||
{
|
|
||||||
int ppp_unit_number = -1;
|
int ppp_unit_number = -1;
|
||||||
if (device[0] != 0)
|
|
||||||
{
|
if(device[0] != 0) {
|
||||||
if (check_device_name(device) < 0)
|
if(check_device_name(device) < 0) {
|
||||||
{
|
|
||||||
tun_error("invalid device name \"%s\"", device);
|
tun_error("invalid device name \"%s\"", device);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -302,17 +290,17 @@ int tunemu_open(tunemu_device device)
|
||||||
}
|
}
|
||||||
|
|
||||||
int ppp_unit_fd = ppp_new_unit(&ppp_unit_number);
|
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);
|
close(ppp_unit_fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (open_pcap() < 0)
|
if(open_pcap() < 0) {
|
||||||
{
|
|
||||||
close(ppp_unit_fd);
|
close(ppp_unit_fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -322,39 +310,40 @@ int tunemu_open(tunemu_device device)
|
||||||
return ppp_unit_fd;
|
return ppp_unit_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tunemu_close(int ppp_sockfd)
|
int tunemu_close(int ppp_sockfd) {
|
||||||
{
|
|
||||||
int ret = close(ppp_sockfd);
|
int ret = close(ppp_sockfd);
|
||||||
|
|
||||||
if (ret == 0)
|
if(ret == 0) {
|
||||||
close_pcap();
|
close_pcap();
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
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);
|
allocate_data_buffer(length + 2);
|
||||||
|
|
||||||
length = read(ppp_sockfd, 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));
|
tun_error("reading packet: %s", strerror(errno));
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
tun_noerror();
|
tun_noerror();
|
||||||
|
|
||||||
length -= 2;
|
length -= 2;
|
||||||
if (length < 0)
|
|
||||||
|
if(length < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(buffer, data_buffer + 2, length);
|
memcpy(buffer, data_buffer + 2, length);
|
||||||
|
|
||||||
return 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);
|
allocate_data_buffer(length + 4);
|
||||||
|
|
||||||
data_buffer[0] = 0x02;
|
data_buffer[0] = 0x02;
|
||||||
|
@ -364,23 +353,25 @@ int tunemu_write(int ppp_sockfd, char *buffer, int length)
|
||||||
|
|
||||||
memcpy(data_buffer + 4, buffer, length);
|
memcpy(data_buffer + 4, buffer, length);
|
||||||
|
|
||||||
if (pcap == NULL)
|
if(pcap == NULL) {
|
||||||
{
|
|
||||||
tun_error("pcap not open");
|
tun_error("pcap not open");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
length = pcap_inject(pcap, data_buffer, length + 4);
|
length = pcap_inject(pcap, data_buffer, length + 4);
|
||||||
if (length < 0)
|
|
||||||
{
|
if(length < 0) {
|
||||||
tun_error("injecting packet: %s", pcap_geterr(pcap));
|
tun_error("injecting packet: %s", pcap_geterr(pcap));
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
tun_noerror();
|
tun_noerror();
|
||||||
|
|
||||||
length -= 4;
|
length -= 4;
|
||||||
if (length < 0)
|
|
||||||
|
if(length < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
193
src/conf.c
193
src/conf.c
|
@ -47,21 +47,25 @@ static int config_compare(const config_t *a, const config_t *b) {
|
||||||
|
|
||||||
result = strcasecmp(a->variable, b->variable);
|
result = strcasecmp(a->variable, b->variable);
|
||||||
|
|
||||||
if(result)
|
if(result) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* give priority to command line options */
|
/* give priority to command line options */
|
||||||
result = !b->file - !a->file;
|
result = !b->file - !a->file;
|
||||||
if (result)
|
|
||||||
|
if(result) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
result = a->line - b->line;
|
result = a->line - b->line;
|
||||||
|
|
||||||
if(result)
|
if(result) {
|
||||||
return result;
|
return result;
|
||||||
else
|
} else {
|
||||||
return a->file ? strcmp(a->file, b->file) : 0;
|
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);
|
*config_tree = avl_alloc_tree((avl_compare_t) config_compare, (avl_action_t) free_config);
|
||||||
|
@ -77,14 +81,17 @@ config_t *new_config(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_config(config_t *cfg) {
|
void free_config(config_t *cfg) {
|
||||||
if(cfg->variable)
|
if(cfg->variable) {
|
||||||
free(cfg->variable);
|
free(cfg->variable);
|
||||||
|
}
|
||||||
|
|
||||||
if(cfg->value)
|
if(cfg->value) {
|
||||||
free(cfg->value);
|
free(cfg->value);
|
||||||
|
}
|
||||||
|
|
||||||
if(cfg->file)
|
if(cfg->file) {
|
||||||
free(cfg->file);
|
free(cfg->file);
|
||||||
|
}
|
||||||
|
|
||||||
free(cfg);
|
free(cfg);
|
||||||
}
|
}
|
||||||
|
@ -102,11 +109,13 @@ config_t *lookup_config(const avl_tree_t *config_tree, char *variable) {
|
||||||
|
|
||||||
found = avl_search_closest_greater(config_tree, &cfg);
|
found = avl_search_closest_greater(config_tree, &cfg);
|
||||||
|
|
||||||
if(!found)
|
if(!found) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if(strcasecmp(found->variable, variable))
|
if(strcasecmp(found->variable, variable)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
@ -121,17 +130,19 @@ config_t *lookup_config_next(const avl_tree_t *config_tree, const config_t *cfg)
|
||||||
if(node->next) {
|
if(node->next) {
|
||||||
found = node->next->data;
|
found = node->next->data;
|
||||||
|
|
||||||
if(!strcasecmp(found->variable, cfg->variable))
|
if(!strcasecmp(found->variable, cfg->variable)) {
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get_config_bool(const config_t *cfg, bool *result) {
|
bool get_config_bool(const config_t *cfg, bool *result) {
|
||||||
if(!cfg)
|
if(!cfg) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(!strcasecmp(cfg->value, "yes")) {
|
if(!strcasecmp(cfg->value, "yes")) {
|
||||||
*result = true;
|
*result = true;
|
||||||
|
@ -148,11 +159,13 @@ bool get_config_bool(const config_t *cfg, bool *result) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get_config_int(const config_t *cfg, int *result) {
|
bool get_config_int(const config_t *cfg, int *result) {
|
||||||
if(!cfg)
|
if(!cfg) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(sscanf(cfg->value, "%d", result) == 1)
|
if(sscanf(cfg->value, "%d", result) == 1) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
logger(LOG_ERR, "Integer expected for configuration variable %s in %s line %d",
|
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);
|
||||||
|
@ -161,8 +174,9 @@ bool get_config_int(const config_t *cfg, int *result) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get_config_string(const config_t *cfg, char **result) {
|
bool get_config_string(const config_t *cfg, char **result) {
|
||||||
if(!cfg)
|
if(!cfg) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
*result = xstrdup(cfg->value);
|
*result = xstrdup(cfg->value);
|
||||||
|
|
||||||
|
@ -172,8 +186,9 @@ bool get_config_string(const config_t *cfg, char **result) {
|
||||||
bool get_config_address(const config_t *cfg, struct addrinfo **result) {
|
bool get_config_address(const config_t *cfg, struct addrinfo **result) {
|
||||||
struct addrinfo *ai;
|
struct addrinfo *ai;
|
||||||
|
|
||||||
if(!cfg)
|
if(!cfg) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ai = str2addrinfo(cfg->value, NULL, 0);
|
ai = str2addrinfo(cfg->value, NULL, 0);
|
||||||
|
|
||||||
|
@ -189,10 +204,11 @@ bool get_config_address(const config_t *cfg, struct addrinfo **result) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get_config_subnet(const config_t *cfg, subnet_t **result) {
|
bool get_config_subnet(const config_t *cfg, subnet_t **result) {
|
||||||
subnet_t subnet = {NULL};
|
subnet_t subnet = {};
|
||||||
|
|
||||||
if(!cfg)
|
if(!cfg) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(!str2net(&subnet, cfg->value)) {
|
if(!str2net(&subnet, cfg->value)) {
|
||||||
logger(LOG_ERR, "Subnet expected for configuration variable %s in %s line %d",
|
logger(LOG_ERR, "Subnet expected for configuration variable %s in %s line %d",
|
||||||
|
@ -223,22 +239,27 @@ static char *readline(FILE * fp, char *buf, size_t buflen) {
|
||||||
char *newline = NULL;
|
char *newline = NULL;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
if(feof(fp))
|
if(feof(fp)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
p = fgets(buf, buflen, fp);
|
p = fgets(buf, buflen, fp);
|
||||||
|
|
||||||
if(!p)
|
if(!p) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
newline = strchr(p, '\n');
|
newline = strchr(p, '\n');
|
||||||
|
|
||||||
if(!newline)
|
if(!newline) {
|
||||||
return buf;
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
*newline = '\0'; /* kill newline */
|
*newline = '\0'; /* kill newline */
|
||||||
if(newline > p && newline[-1] == '\r') /* and carriage return if necessary */
|
|
||||||
|
if(newline > p && newline[-1] == '\r') { /* and carriage return if necessary */
|
||||||
newline[-1] = '\0';
|
newline[-1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
@ -250,26 +271,32 @@ config_t *parse_config_line(char *line, const char *fname, int lineno) {
|
||||||
variable = value = line;
|
variable = value = line;
|
||||||
|
|
||||||
eol = line + strlen(line);
|
eol = line + strlen(line);
|
||||||
while(strchr("\t ", *--eol))
|
|
||||||
|
while(strchr("\t ", *--eol)) {
|
||||||
*eol = '\0';
|
*eol = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
len = strcspn(value, "\t =");
|
len = strcspn(value, "\t =");
|
||||||
value += len;
|
value += len;
|
||||||
value += strspn(value, "\t ");
|
value += strspn(value, "\t ");
|
||||||
|
|
||||||
if(*value == '=') {
|
if(*value == '=') {
|
||||||
value++;
|
value++;
|
||||||
value += strspn(value, "\t ");
|
value += strspn(value, "\t ");
|
||||||
}
|
}
|
||||||
|
|
||||||
variable[len] = '\0';
|
variable[len] = '\0';
|
||||||
|
|
||||||
if(!*value) {
|
if(!*value) {
|
||||||
const char err[] = "No value for variable";
|
const char err[] = "No value for variable";
|
||||||
|
|
||||||
if(fname)
|
if(fname)
|
||||||
logger(LOG_ERR, "%s `%s' on line %d while reading config file %s",
|
logger(LOG_ERR, "%s `%s' on line %d while reading config file %s",
|
||||||
err, variable, lineno, fname);
|
err, variable, lineno, fname);
|
||||||
else
|
else
|
||||||
logger(LOG_ERR, "%s `%s' in command line option %d",
|
logger(LOG_ERR, "%s `%s' in command line option %d",
|
||||||
err, variable, lineno);
|
err, variable, lineno);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,22 +330,27 @@ bool read_config_file(avl_tree_t *config_tree, const char *fname) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
line = readline(fp, buffer, sizeof buffer);
|
line = readline(fp, buffer, sizeof(buffer));
|
||||||
|
|
||||||
if(!line) {
|
if(!line) {
|
||||||
if(feof(fp))
|
if(feof(fp)) {
|
||||||
result = true;
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
lineno++;
|
lineno++;
|
||||||
|
|
||||||
if(!*line || *line == '#')
|
if(!*line || *line == '#') {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(ignore) {
|
if(ignore) {
|
||||||
if(!strncmp(line, "-----END", 8))
|
if(!strncmp(line, "-----END", 8)) {
|
||||||
ignore = false;
|
ignore = false;
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,8 +360,11 @@ bool read_config_file(avl_tree_t *config_tree, const char *fname) {
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg = parse_config_line(line, fname, lineno);
|
cfg = parse_config_line(line, fname, lineno);
|
||||||
if (!cfg)
|
|
||||||
|
if(!cfg) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
config_add(config_tree, cfg);
|
config_add(config_tree, cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,86 +374,88 @@ bool read_config_file(avl_tree_t *config_tree, const char *fname) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_config_options(avl_tree_t *config_tree, const char *prefix) {
|
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;
|
size_t prefix_len = prefix ? strlen(prefix) : 0;
|
||||||
|
|
||||||
for(node = cmdline_conf->tail; node; node = next) {
|
for(const list_node_t *node = cmdline_conf->tail; node; node = node->prev) {
|
||||||
config_t *orig_cfg, *cfg = (config_t *)node->data;
|
const config_t *cfg = node->data;
|
||||||
next = node->prev;
|
|
||||||
|
|
||||||
if(!prefix) {
|
if(!prefix) {
|
||||||
if(strchr(cfg->variable, '.'))
|
if(strchr(cfg->variable, '.')) {
|
||||||
continue;
|
continue;
|
||||||
node->data = NULL;
|
}
|
||||||
list_unlink_node(cmdline_conf, node);
|
|
||||||
} else {
|
} else {
|
||||||
if(strncmp(prefix, cfg->variable, prefix_len) ||
|
if(strncmp(prefix, cfg->variable, prefix_len) ||
|
||||||
cfg->variable[prefix_len] != '.')
|
cfg->variable[prefix_len] != '.') {
|
||||||
continue;
|
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) {
|
bool read_server_config(void) {
|
||||||
char *fname;
|
char fname[PATH_MAX];
|
||||||
bool x;
|
bool x;
|
||||||
|
|
||||||
read_config_options(config_tree, NULL);
|
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);
|
x = read_config_file(config_tree, fname);
|
||||||
|
|
||||||
// We will try to read the conf files in the "conf.d" dir
|
// We will try to read the conf files in the "conf.d" dir
|
||||||
if(x) {
|
if(x) {
|
||||||
char * dname;
|
char dname[PATH_MAX];
|
||||||
xasprintf(&dname, "%s/conf.d", confbase);
|
snprintf(dname, sizeof(dname), "%s/conf.d", confbase);
|
||||||
DIR *dir = opendir(dname);
|
DIR *dir = opendir(dname);
|
||||||
|
|
||||||
// If we can find this dir
|
// If we can find this dir
|
||||||
if(dir) {
|
if(dir) {
|
||||||
struct dirent *ep;
|
struct dirent *ep;
|
||||||
|
|
||||||
// We list all the files in it
|
// We list all the files in it
|
||||||
while(x && (ep = readdir(dir))) {
|
while(x && (ep = readdir(dir))) {
|
||||||
size_t l = strlen(ep->d_name);
|
size_t l = strlen(ep->d_name);
|
||||||
|
|
||||||
// And we try to read the ones that end with ".conf"
|
// And we try to read the ones that end with ".conf"
|
||||||
if(l > 5 && !strcmp(".conf", & ep->d_name[ l - 5 ])) {
|
if(l > 5 && !strcmp(".conf", & ep->d_name[ l - 5 ])) {
|
||||||
free(fname);
|
snprintf(fname, sizeof(fname), "%s/%s", dname, ep->d_name);
|
||||||
xasprintf(&fname, "%s/%s", dname, ep->d_name);
|
|
||||||
x = read_config_file(config_tree, fname);
|
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));
|
logger(LOG_ERR, "Failed to read `%s': %s", fname, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
free(fname);
|
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read_connection_config(connection_t *c) {
|
bool read_connection_config(connection_t *c) {
|
||||||
char *fname;
|
char fname[PATH_MAX];
|
||||||
bool x;
|
bool x;
|
||||||
|
|
||||||
read_config_options(c->config_tree, c->name);
|
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);
|
x = read_config_file(c->config_tree, fname);
|
||||||
free(fname);
|
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -430,34 +467,38 @@ static void disable_old_keys(const char *filename) {
|
||||||
FILE *r, *w;
|
FILE *r, *w;
|
||||||
|
|
||||||
r = fopen(filename, "r");
|
r = fopen(filename, "r");
|
||||||
if(!r)
|
|
||||||
return;
|
|
||||||
|
|
||||||
snprintf(tmpfile, sizeof tmpfile, "%s.tmp", filename);
|
if(!r) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(tmpfile, sizeof(tmpfile), "%s.tmp", filename);
|
||||||
|
|
||||||
w = fopen(tmpfile, "w");
|
w = fopen(tmpfile, "w");
|
||||||
|
|
||||||
while(fgets(buf, sizeof buf, r)) {
|
while(fgets(buf, sizeof(buf), r)) {
|
||||||
if(!strncmp(buf, "-----BEGIN RSA", 14)) {
|
if(!strncmp(buf, "-----BEGIN RSA", 14)) {
|
||||||
buf[11] = 'O';
|
buf[11] = 'O';
|
||||||
buf[12] = 'L';
|
buf[12] = 'L';
|
||||||
buf[13] = 'D';
|
buf[13] = 'D';
|
||||||
disabled = true;
|
disabled = true;
|
||||||
}
|
} else if(!strncmp(buf, "-----END RSA", 12)) {
|
||||||
else if(!strncmp(buf, "-----END RSA", 12)) {
|
|
||||||
buf[ 9] = 'O';
|
buf[ 9] = 'O';
|
||||||
buf[10] = 'L';
|
buf[10] = 'L';
|
||||||
buf[11] = 'D';
|
buf[11] = 'D';
|
||||||
disabled = true;
|
disabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(w && fputs(buf, w) < 0) {
|
if(w && fputs(buf, w) < 0) {
|
||||||
disabled = false;
|
disabled = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(w)
|
if(w) {
|
||||||
fclose(w);
|
fclose(w);
|
||||||
|
}
|
||||||
|
|
||||||
fclose(r);
|
fclose(r);
|
||||||
|
|
||||||
if(!w && disabled) {
|
if(!w && disabled) {
|
||||||
|
@ -469,10 +510,12 @@ static void disable_old_keys(const char *filename) {
|
||||||
#ifdef HAVE_MINGW
|
#ifdef HAVE_MINGW
|
||||||
// We cannot atomically replace files on Windows.
|
// We cannot atomically replace files on Windows.
|
||||||
char bakfile[PATH_MAX] = "";
|
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)) {
|
if(rename(filename, bakfile) || rename(tmpfile, filename)) {
|
||||||
rename(bakfile, filename);
|
rename(bakfile, filename);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
if(rename(tmpfile, filename)) {
|
if(rename(tmpfile, filename)) {
|
||||||
#endif
|
#endif
|
||||||
fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n");
|
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 *ask_and_open(const char *filename, const char *what) {
|
||||||
FILE *r;
|
FILE *r;
|
||||||
char *directory;
|
char directory[PATH_MAX];
|
||||||
char line[PATH_MAX];
|
char line[PATH_MAX];
|
||||||
|
char abspath[PATH_MAX];
|
||||||
const char *fn;
|
const char *fn;
|
||||||
|
|
||||||
/* Check stdin and stdout */
|
/* Check stdin and stdout */
|
||||||
|
@ -505,7 +549,7 @@ FILE *ask_and_open(const char *filename, const char *what) {
|
||||||
what, filename);
|
what, filename);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
fn = readline(stdin, line, sizeof line);
|
fn = readline(stdin, line, sizeof(line));
|
||||||
|
|
||||||
if(!fn) {
|
if(!fn) {
|
||||||
fprintf(stderr, "Error while reading stdin: %s\n",
|
fprintf(stderr, "Error while reading stdin: %s\n",
|
||||||
|
@ -515,21 +559,22 @@ FILE *ask_and_open(const char *filename, const char *what) {
|
||||||
|
|
||||||
if(!strlen(fn))
|
if(!strlen(fn))
|
||||||
/* User just pressed enter. */
|
/* User just pressed enter. */
|
||||||
|
{
|
||||||
fn = filename;
|
fn = filename;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_MINGW
|
#ifdef HAVE_MINGW
|
||||||
|
|
||||||
if(fn[0] != '\\' && fn[0] != '/' && !strchr(fn, ':')) {
|
if(fn[0] != '\\' && fn[0] != '/' && !strchr(fn, ':')) {
|
||||||
#else
|
#else
|
||||||
|
|
||||||
if(fn[0] != '/') {
|
if(fn[0] != '/') {
|
||||||
#endif
|
#endif
|
||||||
/* The directory is a relative path or a filename. */
|
/* The directory is a relative path or a filename. */
|
||||||
char *p;
|
getcwd(directory, sizeof(directory));
|
||||||
|
snprintf(abspath, sizeof(abspath), "%s/%s", directory, fn);
|
||||||
directory = get_current_dir_name();
|
fn = abspath;
|
||||||
xasprintf(&p, "%s/%s", directory, fn);
|
|
||||||
free(directory);
|
|
||||||
fn = p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
umask(0077); /* Disallow everything for group and other */
|
umask(0077); /* Disallow everything for group and other */
|
||||||
|
|
41
src/conf.h
41
src/conf.h
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_CONF_H
|
||||||
|
#define TINC_CONF_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
conf.h -- header for conf.c
|
conf.h -- header for conf.c
|
||||||
Copyright (C) 1998-2005 Ivo Timmermans
|
Copyright (C) 1998-2005 Ivo Timmermans
|
||||||
|
@ -18,9 +21,6 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TINC_CONF_H__
|
|
||||||
#define __TINC_CONF_H__
|
|
||||||
|
|
||||||
#include "avl_tree.h"
|
#include "avl_tree.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
|
||||||
|
@ -44,25 +44,24 @@ extern char *confbase;
|
||||||
extern char *netname;
|
extern char *netname;
|
||||||
extern list_t *cmdline_conf;
|
extern list_t *cmdline_conf;
|
||||||
|
|
||||||
extern void init_configuration(avl_tree_t **);
|
extern void init_configuration(avl_tree_t **config_tree);
|
||||||
extern void exit_configuration(avl_tree_t **);
|
extern void exit_configuration(avl_tree_t **config_tree);
|
||||||
extern config_t *new_config(void) __attribute__((__malloc__));
|
extern config_t *new_config(void) __attribute__((__malloc__));
|
||||||
extern void free_config(config_t *);
|
extern void free_config(config_t *cfg);
|
||||||
extern void config_add(avl_tree_t *, config_t *);
|
extern void config_add(avl_tree_t *config_tree, config_t *cfg);
|
||||||
extern config_t *lookup_config(const avl_tree_t *, char *);
|
extern config_t *lookup_config(const avl_tree_t *config_tree, char *variable);
|
||||||
extern config_t *lookup_config_next(const avl_tree_t *, const config_t *);
|
extern config_t *lookup_config_next(const avl_tree_t *config_tree, const config_t *cfg);
|
||||||
extern bool get_config_bool(const config_t *, bool *);
|
extern bool get_config_bool(const config_t *cfg, bool *result);
|
||||||
extern bool get_config_int(const config_t *, int *);
|
extern bool get_config_int(const config_t *cfg, int *result);
|
||||||
extern bool get_config_string(const config_t *, char **);
|
extern bool get_config_string(const config_t *cfg, char **result);
|
||||||
extern bool get_config_address(const config_t *, struct addrinfo **);
|
extern bool get_config_address(const config_t *cfg, struct addrinfo **result);
|
||||||
extern bool get_config_subnet(const config_t *, struct subnet_t **);
|
extern bool get_config_subnet(const config_t *cfg, struct subnet_t **result);
|
||||||
|
|
||||||
extern config_t *parse_config_line(char *, const char *, int);
|
extern config_t *parse_config_line(char *line, const char *fname, int lineno);
|
||||||
extern bool read_config_file(avl_tree_t *, const char *);
|
extern bool read_config_file(avl_tree_t *config_tree, const char *fname);
|
||||||
extern void read_config_options(avl_tree_t *, const char *);
|
extern void read_config_options(avl_tree_t *config_tree, const char *prefix);
|
||||||
extern bool read_server_config(void);
|
extern bool read_server_config(void);
|
||||||
extern bool read_connection_config(struct connection_t *);
|
extern bool read_connection_config(struct connection_t *c);
|
||||||
extern FILE *ask_and_open(const char *, const char *);
|
extern FILE *ask_and_open(const char *fname, const char *what);
|
||||||
extern bool is_safe_path(const char *);
|
|
||||||
|
|
||||||
#endif /* __TINC_CONF_H__ */
|
#endif
|
||||||
|
|
|
@ -52,8 +52,9 @@ connection_t *new_connection(void) {
|
||||||
|
|
||||||
c = xmalloc_and_zero(sizeof(connection_t));
|
c = xmalloc_and_zero(sizeof(connection_t));
|
||||||
|
|
||||||
if(!c)
|
if(!c) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
gettimeofday(&c->start, NULL);
|
gettimeofday(&c->start, NULL);
|
||||||
|
|
||||||
|
@ -118,8 +119,9 @@ void free_connection(connection_t *c) {
|
||||||
free(c->name);
|
free(c->name);
|
||||||
free(c->hostname);
|
free(c->hostname);
|
||||||
|
|
||||||
if(c->config_tree)
|
if(c->config_tree) {
|
||||||
exit_configuration(&c->config_tree);
|
exit_configuration(&c->config_tree);
|
||||||
|
}
|
||||||
|
|
||||||
free(c);
|
free(c);
|
||||||
}
|
}
|
||||||
|
@ -141,7 +143,7 @@ void dump_connections(void) {
|
||||||
for(node = connection_tree->head; node; node = node->next) {
|
for(node = connection_tree->head; node; node = node->next) {
|
||||||
c = node->data;
|
c = node->data;
|
||||||
logger(LOG_DEBUG, " %s at %s options %x socket %d status %04x outbuf %d/%d/%d",
|
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->name, c->hostname, c->options, c->socket, bitfield_to_int(&c->status, sizeof(c->status)),
|
||||||
c->outbufsize, c->outbufstart, c->outbuflen);
|
c->outbufsize, c->outbufstart, c->outbuflen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_CONNECTION_H
|
||||||
|
#define TINC_CONNECTION_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
connection.h -- header for connection.c
|
connection.h -- header for connection.c
|
||||||
Copyright (C) 2000-2016 Guus Sliepen <guus@tinc-vpn.org>,
|
Copyright (C) 2000-2016 Guus Sliepen <guus@tinc-vpn.org>,
|
||||||
|
@ -18,9 +21,6 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TINC_CONNECTION_H__
|
|
||||||
#define __TINC_CONNECTION_H__
|
|
||||||
|
|
||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ typedef struct connection_t {
|
||||||
char buffer[MAXBUFSIZE]; /* metadata input buffer */
|
char buffer[MAXBUFSIZE]; /* metadata input buffer */
|
||||||
int buflen; /* bytes read into buffer */
|
int buflen; /* bytes read into buffer */
|
||||||
int reqlen; /* length of incoming request */
|
int reqlen; /* length of incoming request */
|
||||||
int tcplen; /* length of incoming TCPpacket */
|
length_t tcplen; /* length of incoming TCPpacket */
|
||||||
int allow_request; /* defined if there's only one request possible */
|
int allow_request; /* defined if there's only one request possible */
|
||||||
|
|
||||||
char *outbuf; /* metadata output buffer */
|
char *outbuf; /* metadata output buffer */
|
||||||
|
@ -109,10 +109,10 @@ extern connection_t *everyone;
|
||||||
extern void init_connections(void);
|
extern void init_connections(void);
|
||||||
extern void exit_connections(void);
|
extern void exit_connections(void);
|
||||||
extern connection_t *new_connection(void) __attribute__((__malloc__));
|
extern connection_t *new_connection(void) __attribute__((__malloc__));
|
||||||
extern void free_connection(connection_t *);
|
extern void free_connection(connection_t *c);
|
||||||
extern void free_connection_partially(connection_t *);
|
extern void free_connection_partially(connection_t *c);
|
||||||
extern void connection_add(connection_t *);
|
extern void connection_add(connection_t *c);
|
||||||
extern void connection_del(connection_t *);
|
extern void connection_del(connection_t *c);
|
||||||
extern void dump_connections(void);
|
extern void dump_connections(void);
|
||||||
|
|
||||||
#endif /* __TINC_CONNECTION_H__ */
|
#endif
|
||||||
|
|
|
@ -37,7 +37,7 @@ int device_fd = -1;
|
||||||
static HANDLE device_handle = INVALID_HANDLE_VALUE;
|
static HANDLE device_handle = INVALID_HANDLE_VALUE;
|
||||||
char *device = NULL;
|
char *device = NULL;
|
||||||
char *iface = 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_in = 0;
|
||||||
static uint64_t device_total_out = 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, "Device"), &device);
|
||||||
get_config_string(lookup_config(config_tree, "Interface"), &iface);
|
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");
|
logger(LOG_WARNING, "Warning: both Device and Interface specified, results may not be as expected");
|
||||||
|
}
|
||||||
|
|
||||||
/* Open registry and look for network adapters */
|
/* Open registry and look for network adapters */
|
||||||
|
|
||||||
|
@ -73,42 +74,49 @@ static bool setup_device(void) {
|
||||||
|
|
||||||
for(i = 0; ; i++) {
|
for(i = 0; ; i++) {
|
||||||
len = sizeof(adapterid);
|
len = sizeof(adapterid);
|
||||||
if(RegEnumKeyEx(key, i, adapterid, &len, 0, 0, 0, NULL))
|
|
||||||
|
if(RegEnumKeyEx(key, i, adapterid, &len, 0, 0, 0, NULL)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Find out more about this adapter */
|
/* Find out more about this adapter */
|
||||||
|
|
||||||
snprintf(regpath, sizeof(regpath), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapterid);
|
snprintf(regpath, sizeof(regpath), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapterid);
|
||||||
|
|
||||||
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2))
|
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
len = sizeof(adaptername);
|
len = sizeof(adaptername);
|
||||||
err = RegQueryValueEx(key2, "Name", 0, 0, adaptername, &len);
|
err = RegQueryValueEx(key2, "Name", 0, 0, adaptername, &len);
|
||||||
|
|
||||||
RegCloseKey(key2);
|
RegCloseKey(key2);
|
||||||
|
|
||||||
if(err)
|
if(err) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(device) {
|
if(device) {
|
||||||
if(!strcmp(device, adapterid)) {
|
if(!strcmp(device, adapterid)) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
} else
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(iface) {
|
if(iface) {
|
||||||
if(!strcmp(iface, adaptername)) {
|
if(!strcmp(iface, adaptername)) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
} else
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
|
snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
|
||||||
device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
|
device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
|
||||||
|
|
||||||
if(device_handle != INVALID_HANDLE_VALUE) {
|
if(device_handle != INVALID_HANDLE_VALUE) {
|
||||||
CloseHandle(device_handle);
|
CloseHandle(device_handle);
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -123,11 +131,13 @@ static bool setup_device(void) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!device)
|
if(!device) {
|
||||||
device = xstrdup(adapterid);
|
device = xstrdup(adapterid);
|
||||||
|
}
|
||||||
|
|
||||||
if(!iface)
|
if(!iface) {
|
||||||
iface = xstrdup(adaptername);
|
iface = xstrdup(adaptername);
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, device);
|
snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, device);
|
||||||
|
|
||||||
|
@ -205,13 +215,12 @@ static bool setup_device(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
read(device_fd, &gelukt, 1);
|
read(device_fd, &gelukt, 1);
|
||||||
|
|
||||||
if(gelukt != 1) {
|
if(gelukt != 1) {
|
||||||
logger(LOG_DEBUG, "Tap reader failed!");
|
logger(LOG_DEBUG, "Tap reader failed!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
device_info = "Windows tap device";
|
|
||||||
|
|
||||||
logger(LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
|
logger(LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
12
src/device.h
12
src/device.h
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_DEVICE_H
|
||||||
|
#define TINC_DEVICE_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
device.h -- generic header for device.c
|
device.h -- generic header for device.c
|
||||||
Copyright (C) 2001-2005 Ivo Timmermans
|
Copyright (C) 2001-2005 Ivo Timmermans
|
||||||
|
@ -18,9 +21,6 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TINC_DEVICE_H__
|
|
||||||
#define __TINC_DEVICE_H__
|
|
||||||
|
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
|
||||||
extern int device_fd;
|
extern int device_fd;
|
||||||
|
@ -31,8 +31,8 @@ extern char *iface;
|
||||||
typedef struct devops_t {
|
typedef struct devops_t {
|
||||||
bool (*setup)(void);
|
bool (*setup)(void);
|
||||||
void (*close)(void);
|
void (*close)(void);
|
||||||
bool (*read)(struct vpn_packet_t *);
|
bool (*read)(struct vpn_packet_t *packet);
|
||||||
bool (*write)(struct vpn_packet_t *);
|
bool (*write)(struct vpn_packet_t *packet);
|
||||||
void (*dump_stats)(void);
|
void (*dump_stats)(void);
|
||||||
} devops_t;
|
} devops_t;
|
||||||
|
|
||||||
|
@ -44,4 +44,4 @@ extern const devops_t uml_devops;
|
||||||
extern const devops_t vde_devops;
|
extern const devops_t vde_devops;
|
||||||
extern devops_t devops;
|
extern devops_t devops;
|
||||||
|
|
||||||
#endif /* __TINC_DEVICE_H__ */
|
#endif
|
||||||
|
|
40
src/dropin.c
40
src/dropin.c
|
@ -50,8 +50,9 @@ int daemon(int nochdir, int noclose) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we are the parent, terminate */
|
/* If we are the parent, terminate */
|
||||||
if(pid)
|
if(pid) {
|
||||||
exit(0);
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Detach by becoming the new process group leader */
|
/* Detach by becoming the new process group leader */
|
||||||
if(setsid() < 0) {
|
if(setsid() < 0) {
|
||||||
|
@ -86,40 +87,6 @@ int daemon(int nochdir, int noclose) {
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
#ifndef HAVE_ASPRINTF
|
||||||
int asprintf(char **buf, const char *fmt, ...) {
|
int asprintf(char **buf, const char *fmt, ...) {
|
||||||
int result;
|
int result;
|
||||||
|
@ -143,8 +110,9 @@ int vasprintf(char **buf, const char *fmt, va_list ap) {
|
||||||
buf[len - 1] = 0;
|
buf[len - 1] = 0;
|
||||||
va_end(aq);
|
va_end(aq);
|
||||||
|
|
||||||
if(status >= 0)
|
if(status >= 0) {
|
||||||
*buf = xrealloc(*buf, status + 1);
|
*buf = xrealloc(*buf, status + 1);
|
||||||
|
}
|
||||||
|
|
||||||
if(status > len - 1) {
|
if(status > len - 1) {
|
||||||
len = status;
|
len = status;
|
||||||
|
|
18
src/dropin.h
18
src/dropin.h
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_DROPIN_H
|
||||||
|
#define TINC_DROPIN_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
dropin.h -- header file for dropin.c
|
dropin.h -- header file for dropin.c
|
||||||
Copyright (C) 2000-2005 Ivo Timmermans,
|
Copyright (C) 2000-2005 Ivo Timmermans,
|
||||||
|
@ -18,14 +21,11 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __DROPIN_H__
|
|
||||||
#define __DROPIN_H__
|
|
||||||
|
|
||||||
#include "fake-getaddrinfo.h"
|
#include "fake-getaddrinfo.h"
|
||||||
#include "fake-getnameinfo.h"
|
#include "fake-getnameinfo.h"
|
||||||
|
|
||||||
#ifndef HAVE_DAEMON
|
#ifndef HAVE_DAEMON
|
||||||
extern int daemon(int, int);
|
extern int daemon(int nochdir, int noclose);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_GET_CURRENT_DIR_NAME
|
#ifndef HAVE_GET_CURRENT_DIR_NAME
|
||||||
|
@ -33,16 +33,16 @@ extern char *get_current_dir_name(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_ASPRINTF
|
#ifndef HAVE_ASPRINTF
|
||||||
extern int asprintf(char **, const char *, ...);
|
extern int asprintf(char **buf, const char *fmt, ...);
|
||||||
extern int vasprintf(char **, const char *, va_list ap);
|
extern int vasprintf(char **buf, const char *fmt, va_list ap);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_GETTIMEOFDAY
|
#ifndef HAVE_GETTIMEOFDAY
|
||||||
extern int gettimeofday(struct timeval *, void *);
|
extern int gettimeofday(struct timeval *tv, void *tz);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_USLEEP
|
#ifndef HAVE_USLEEP
|
||||||
extern int usleep(long long);
|
extern int usleep(long long usec);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __DROPIN_H__ */
|
#endif
|
||||||
|
|
|
@ -22,15 +22,16 @@
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "net.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_in = 0;
|
||||||
static uint64_t device_total_out = 0;
|
static uint64_t device_total_out = 0;
|
||||||
|
|
||||||
static bool setup_device(void) {
|
static bool setup_device(void) {
|
||||||
device = "dummy";
|
device = xstrdup("dummy");
|
||||||
iface = "dummy";
|
iface = xstrdup("dummy");
|
||||||
logger(LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
|
logger(LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -39,6 +40,7 @@ static void close_device(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool read_packet(vpn_packet_t *packet) {
|
static bool read_packet(vpn_packet_t *packet) {
|
||||||
|
(void)packet;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
src/edge.c
13
src/edge.c
|
@ -39,13 +39,15 @@ static int edge_weight_compare(const edge_t *a, const edge_t *b) {
|
||||||
|
|
||||||
result = a->weight - b->weight;
|
result = a->weight - b->weight;
|
||||||
|
|
||||||
if(result)
|
if(result) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
result = strcmp(a->from->name, b->from->name);
|
result = strcmp(a->from->name, b->from->name);
|
||||||
|
|
||||||
if(result)
|
if(result) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return strcmp(a->to->name, b->to->name);
|
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);
|
e->reverse = lookup_edge(e->to, e->from);
|
||||||
|
|
||||||
if(e->reverse)
|
if(e->reverse) {
|
||||||
e->reverse->reverse = e;
|
e->reverse->reverse = e;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void edge_del(edge_t *e) {
|
void edge_del(edge_t *e) {
|
||||||
if(e->reverse)
|
if(e->reverse) {
|
||||||
e->reverse->reverse = NULL;
|
e->reverse->reverse = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
avl_delete(edge_weight_tree, e);
|
avl_delete(edge_weight_tree, e);
|
||||||
avl_delete(e->from->edge_tree, e);
|
avl_delete(e->from->edge_tree, e);
|
||||||
|
@ -115,6 +119,7 @@ void dump_edges(void) {
|
||||||
|
|
||||||
for(node = node_tree->head; node; node = node->next) {
|
for(node = node_tree->head; node; node = node->next) {
|
||||||
n = node->data;
|
n = node->data;
|
||||||
|
|
||||||
for(node2 = n->edge_tree->head; node2; node2 = node2->next) {
|
for(node2 = n->edge_tree->head; node2; node2 = node2->next) {
|
||||||
e = node2->data;
|
e = node2->data;
|
||||||
address = sockaddr2hostname(&e->address);
|
address = sockaddr2hostname(&e->address);
|
||||||
|
|
18
src/edge.h
18
src/edge.h
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_EDGE_H
|
||||||
|
#define TINC_EDGE_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
edge.h -- header for edge.c
|
edge.h -- header for edge.c
|
||||||
Copyright (C) 2001-2006 Guus Sliepen <guus@tinc-vpn.org>,
|
Copyright (C) 2001-2006 Guus Sliepen <guus@tinc-vpn.org>,
|
||||||
|
@ -18,9 +21,6 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TINC_EDGE_H__
|
|
||||||
#define __TINC_EDGE_H__
|
|
||||||
|
|
||||||
#include "avl_tree.h"
|
#include "avl_tree.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
@ -43,12 +43,12 @@ extern avl_tree_t *edge_weight_tree; /* Tree with all known edges sorted on weig
|
||||||
extern void init_edges(void);
|
extern void init_edges(void);
|
||||||
extern void exit_edges(void);
|
extern void exit_edges(void);
|
||||||
extern edge_t *new_edge(void) __attribute__((__malloc__));
|
extern edge_t *new_edge(void) __attribute__((__malloc__));
|
||||||
extern void free_edge(edge_t *);
|
extern void free_edge(edge_t *e);
|
||||||
extern avl_tree_t *new_edge_tree(void) __attribute__((__malloc__));
|
extern avl_tree_t *new_edge_tree(void) __attribute__((__malloc__));
|
||||||
extern void free_edge_tree(avl_tree_t *);
|
extern void free_edge_tree(avl_tree_t *edge_tree);
|
||||||
extern void edge_add(edge_t *);
|
extern void edge_add(edge_t *e);
|
||||||
extern void edge_del(edge_t *);
|
extern void edge_del(edge_t *e);
|
||||||
extern edge_t *lookup_edge(struct node_t *, struct node_t *);
|
extern edge_t *lookup_edge(struct node_t *from, struct node_t *to);
|
||||||
extern void dump_edges(void);
|
extern void dump_edges(void);
|
||||||
|
|
||||||
#endif /* __TINC_EDGE_H__ */
|
#endif
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_ETHERNET_H
|
||||||
|
#define TINC_ETHERNET_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ethernet.h -- missing Ethernet related definitions
|
ethernet.h -- missing Ethernet related definitions
|
||||||
Copyright (C) 2005 Ivo Timmermans
|
Copyright (C) 2005 Ivo Timmermans
|
||||||
|
@ -18,9 +21,6 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TINC_ETHERNET_H__
|
|
||||||
#define __TINC_ETHERNET_H__
|
|
||||||
|
|
||||||
#ifndef ETH_ALEN
|
#ifndef ETH_ALEN
|
||||||
#define ETH_ALEN 6
|
#define ETH_ALEN 6
|
||||||
#endif
|
#endif
|
||||||
|
@ -86,4 +86,4 @@ struct ether_arp {
|
||||||
#define arp_op ea_hdr.ar_op
|
#define arp_op ea_hdr.ar_op
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __TINC_ETHERNET_H__ */
|
#endif
|
||||||
|
|
17
src/event.c
17
src/event.c
|
@ -31,11 +31,13 @@ extern time_t now;
|
||||||
static int id;
|
static int id;
|
||||||
|
|
||||||
static int event_compare(const event_t *a, const event_t *b) {
|
static int event_compare(const event_t *a, const event_t *b) {
|
||||||
if(a->time > b->time)
|
if(a->time > b->time) {
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if(a->time < b->time)
|
if(a->time < b->time) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return a->id - b->id;
|
return a->id - b->id;
|
||||||
}
|
}
|
||||||
|
@ -58,12 +60,15 @@ void expire_events(void) {
|
||||||
* the expiration time of the last event and the current time.
|
* the expiration time of the last event and the current time.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if(!event_tree->tail)
|
if(!event_tree->tail) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
event = event_tree->tail->data;
|
event = event_tree->tail->data;
|
||||||
if(event->time <= now)
|
|
||||||
|
if(event->time <= now) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
diff = event->time - now;
|
diff = event->time - now;
|
||||||
|
|
||||||
|
@ -108,7 +113,9 @@ event_t *get_expired_event(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
event_t *peek_next_event(void) {
|
event_t *peek_next_event(void) {
|
||||||
if (event_tree->head)
|
if(event_tree->head) {
|
||||||
return event_tree->head->data;
|
return event_tree->head->data;
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
14
src/event.h
14
src/event.h
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_EVENT_H
|
||||||
|
#define TINC_EVENT_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
event.h -- header for event.c
|
event.h -- header for event.c
|
||||||
Copyright (C) 2002-2009 Guus Sliepen <guus@tinc-vpn.org>,
|
Copyright (C) 2002-2009 Guus Sliepen <guus@tinc-vpn.org>,
|
||||||
|
@ -18,9 +21,6 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TINC_EVENT_H__
|
|
||||||
#define __TINC_EVENT_H__
|
|
||||||
|
|
||||||
#include "avl_tree.h"
|
#include "avl_tree.h"
|
||||||
|
|
||||||
extern avl_tree_t *event_tree;
|
extern avl_tree_t *event_tree;
|
||||||
|
@ -38,10 +38,10 @@ extern void init_events(void);
|
||||||
extern void exit_events(void);
|
extern void exit_events(void);
|
||||||
extern void expire_events(void);
|
extern void expire_events(void);
|
||||||
extern event_t *new_event(void) __attribute__((__malloc__));
|
extern event_t *new_event(void) __attribute__((__malloc__));
|
||||||
extern void free_event(event_t *);
|
extern void free_event(event_t *event);
|
||||||
extern void event_add(event_t *);
|
extern void event_add(event_t *event);
|
||||||
extern void event_del(event_t *);
|
extern void event_del(event_t *event);
|
||||||
extern event_t *get_expired_event(void);
|
extern event_t *get_expired_event(void);
|
||||||
extern event_t *peek_next_event(void);
|
extern event_t *peek_next_event(void);
|
||||||
|
|
||||||
#endif /* __TINC_EVENT_H__ */
|
#endif
|
||||||
|
|
|
@ -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
|
|
|
@ -17,15 +17,17 @@
|
||||||
#include "xalloc.h"
|
#include "xalloc.h"
|
||||||
|
|
||||||
#if !HAVE_DECL_GAI_STRERROR
|
#if !HAVE_DECL_GAI_STRERROR
|
||||||
char *gai_strerror(int ecode)
|
char *gai_strerror(int ecode) {
|
||||||
{
|
|
||||||
switch(ecode) {
|
switch(ecode) {
|
||||||
case EAI_NODATA:
|
case EAI_NODATA:
|
||||||
return "No address associated with hostname";
|
return "No address associated with hostname";
|
||||||
|
|
||||||
case EAI_MEMORY:
|
case EAI_MEMORY:
|
||||||
return "Memory allocation failure";
|
return "Memory allocation failure";
|
||||||
|
|
||||||
case EAI_FAMILY:
|
case EAI_FAMILY:
|
||||||
return "Address family not supported";
|
return "Address family not supported";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return "Unknown error";
|
return "Unknown error";
|
||||||
}
|
}
|
||||||
|
@ -33,8 +35,7 @@ char *gai_strerror(int ecode)
|
||||||
#endif /* !HAVE_GAI_STRERROR */
|
#endif /* !HAVE_GAI_STRERROR */
|
||||||
|
|
||||||
#if !HAVE_DECL_FREEADDRINFO
|
#if !HAVE_DECL_FREEADDRINFO
|
||||||
void freeaddrinfo(struct addrinfo *ai)
|
void freeaddrinfo(struct addrinfo *ai) {
|
||||||
{
|
|
||||||
struct addrinfo *next;
|
struct addrinfo *next;
|
||||||
|
|
||||||
while(ai) {
|
while(ai) {
|
||||||
|
@ -46,8 +47,7 @@ void freeaddrinfo(struct addrinfo *ai)
|
||||||
#endif /* !HAVE_FREEADDRINFO */
|
#endif /* !HAVE_FREEADDRINFO */
|
||||||
|
|
||||||
#if !HAVE_DECL_GETADDRINFO
|
#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;
|
struct addrinfo *ai;
|
||||||
|
|
||||||
ai = xmalloc_and_zero(sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
|
ai = xmalloc_and_zero(sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
|
||||||
|
@ -62,19 +62,20 @@ static struct addrinfo *malloc_ai(uint16_t port, uint32_t addr)
|
||||||
return ai;
|
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 addrinfo *prev = NULL;
|
||||||
struct hostent *hp;
|
struct hostent *hp;
|
||||||
struct in_addr in = {0};
|
struct in_addr in = {0};
|
||||||
int i;
|
int i;
|
||||||
uint16_t port = 0;
|
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;
|
return EAI_FAMILY;
|
||||||
|
}
|
||||||
|
|
||||||
if (servname)
|
if(servname) {
|
||||||
port = htons(atoi(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));
|
*res = malloc_ai(port, htonl(0x00000000));
|
||||||
|
@ -88,14 +89,16 @@ int getaddrinfo(const char *hostname, const char *servname, const struct addrinf
|
||||||
|
|
||||||
hp = gethostbyname(hostname);
|
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;
|
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);
|
*res = malloc_ai(port, ((struct in_addr *)hp->h_addr_list[i])->s_addr);
|
||||||
|
|
||||||
if(prev)
|
if(prev) {
|
||||||
prev->ai_next = *res;
|
prev->ai_next = *res;
|
||||||
|
}
|
||||||
|
|
||||||
prev = *res;
|
prev = *res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,17 @@
|
||||||
#ifndef _FAKE_GETADDRINFO_H
|
#ifndef TINC_FAKE_GETADDRINFO_H
|
||||||
#define _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
|
#ifndef AI_PASSIVE
|
||||||
# define AI_PASSIVE 1
|
# define AI_PASSIVE 1
|
||||||
|
@ -44,4 +54,4 @@ char *gai_strerror(int ecode);
|
||||||
void freeaddrinfo(struct addrinfo *ai);
|
void freeaddrinfo(struct addrinfo *ai);
|
||||||
#endif /* !HAVE_FREEADDRINFO */
|
#endif /* !HAVE_FREEADDRINFO */
|
||||||
|
|
||||||
#endif /* _FAKE_GETADDRINFO_H */
|
#endif
|
||||||
|
|
|
@ -16,39 +16,48 @@
|
||||||
|
|
||||||
#if !HAVE_DECL_GETNAMEINFO
|
#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 sockaddr_in *sin = (struct sockaddr_in *)sa;
|
||||||
struct hostent *hp;
|
struct hostent *hp;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if(sa->sa_family != AF_INET)
|
if(sa->sa_family != AF_INET) {
|
||||||
return EAI_FAMILY;
|
return EAI_FAMILY;
|
||||||
|
}
|
||||||
|
|
||||||
if(serv && servlen) {
|
if(serv && servlen) {
|
||||||
len = snprintf(serv, servlen, "%d", ntohs(sin->sin_port));
|
len = snprintf(serv, servlen, "%d", ntohs(sin->sin_port));
|
||||||
if(len < 0 || len >= servlen)
|
|
||||||
|
if(len < 0 || len >= servlen) {
|
||||||
return EAI_MEMORY;
|
return EAI_MEMORY;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!host || !hostlen)
|
if(!host || !hostlen) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if(flags & NI_NUMERICHOST) {
|
if(flags & NI_NUMERICHOST) {
|
||||||
len = snprintf(host, hostlen, "%s", inet_ntoa(sin->sin_addr));
|
len = snprintf(host, hostlen, "%s", inet_ntoa(sin->sin_addr));
|
||||||
if(len < 0 || len >= hostlen)
|
|
||||||
|
if(len < 0 || len >= hostlen) {
|
||||||
return EAI_MEMORY;
|
return EAI_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
hp = gethostbyaddr((char *)&sin->sin_addr, sizeof(struct in_addr), AF_INET);
|
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;
|
return EAI_NODATA;
|
||||||
|
}
|
||||||
|
|
||||||
len = snprintf(host, hostlen, "%s", hp->h_name);
|
len = snprintf(host, hostlen, "%s", hp->h_name);
|
||||||
if(len < 0 || len >= hostlen)
|
|
||||||
|
if(len < 0 || len >= hostlen) {
|
||||||
return EAI_MEMORY;
|
return EAI_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef _FAKE_GETNAMEINFO_H
|
#ifndef TINC_FAKE_GETNAMEINFO_H
|
||||||
#define _FAKE_GETNAMEINFO_H
|
#define TINC_FAKE_GETNAMEINFO_H
|
||||||
|
|
||||||
#if !HAVE_DECL_GETNAMEINFO
|
#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,
|
||||||
|
@ -13,4 +13,4 @@ int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
|
||||||
# define NI_MAXHOST 1025
|
# define NI_MAXHOST 1025
|
||||||
#endif /* !NI_MAXHOST */
|
#endif /* !NI_MAXHOST */
|
||||||
|
|
||||||
#endif /* _FAKE_GETNAMEINFO_H */
|
#endif
|
||||||
|
|
419
src/getopt.c
419
src/getopt.c
|
@ -34,7 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined (__STDC__) || !__STDC__
|
#if !defined (STDC) || !STDC
|
||||||
/* This is a separate conditional since some stdc systems
|
/* This is a separate conditional since some stdc systems
|
||||||
reject `defined (const)'. */
|
reject `defined (const)'. */
|
||||||
#ifndef const
|
#ifndef const
|
||||||
|
@ -57,7 +57,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
it is simpler to just do this in the source for each such file. */
|
it is simpler to just do this in the source for each such file. */
|
||||||
|
|
||||||
#define GETOPT_INTERFACE_VERSION 2
|
#define GETOPT_INTERFACE_VERSION 2
|
||||||
#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2
|
#if !defined (_LIBC) && defined (GLIBC) && GLIBC >= 2
|
||||||
#include <gnu-versions.h>
|
#include <gnu-versions.h>
|
||||||
#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
|
#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
|
||||||
#define ELIDE_CODE
|
#define ELIDE_CODE
|
||||||
|
@ -68,8 +68,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
|
|
||||||
/* This needs to come after some library #include
|
/* This needs to come after some library #include
|
||||||
to get __GNU_LIBRARY__ defined. */
|
to get GNU_LIBRARY defined. */
|
||||||
#ifdef __GNU_LIBRARY__
|
#ifdef GNU_LIBRARY
|
||||||
/* Don't include stdlib.h for non-GNU C libraries because some of them
|
/* Don't include stdlib.h for non-GNU C libraries because some of them
|
||||||
contain conflicting prototypes for getopt. */
|
contain conflicting prototypes for getopt. */
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -83,7 +83,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (WIN32) && !defined (__CYGWIN32__)
|
#if defined (WIN32) && !defined (CYGWIN32)
|
||||||
/* It's not Unix, really. See? Capital letters. */
|
/* It's not Unix, really. See? Capital letters. */
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#define getpid() GetCurrentProcessId()
|
#define getpid() GetCurrentProcessId()
|
||||||
|
@ -132,7 +132,7 @@ int optind = 1;
|
||||||
causes problems with re-calling getopt as programs generally don't
|
causes problems with re-calling getopt as programs generally don't
|
||||||
know that. */
|
know that. */
|
||||||
|
|
||||||
int __getopt_initialized = 0;
|
int getopt_initialized = 0;
|
||||||
|
|
||||||
/* The next char to be scanned in the option-element
|
/* The next char to be scanned in the option-element
|
||||||
in which the last option character we returned was found.
|
in which the last option character we returned was found.
|
||||||
|
@ -183,15 +183,14 @@ int optopt = '?';
|
||||||
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
|
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
|
||||||
`--' can cause `getopt' to return -1 with `optind' != ARGC. */
|
`--' can cause `getopt' to return -1 with `optind' != ARGC. */
|
||||||
|
|
||||||
static enum
|
static enum {
|
||||||
{
|
|
||||||
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
|
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
|
||||||
} ordering;
|
} ordering;
|
||||||
|
|
||||||
/* Value of POSIXLY_CORRECT environment variable. */
|
/* Value of POSIXLY_CORRECT environment variable. */
|
||||||
static char *posixly_correct;
|
static char *posixly_correct;
|
||||||
|
|
||||||
#ifdef __GNU_LIBRARY__
|
#ifdef GNU_LIBRARY
|
||||||
/* We want to avoid inclusion of string.h with non-GNU libraries
|
/* We want to avoid inclusion of string.h with non-GNU libraries
|
||||||
because there are many ways it can cause trouble.
|
because there are many ways it can cause trouble.
|
||||||
On some systems, it contains special magic macros that don't work
|
On some systems, it contains special magic macros that don't work
|
||||||
|
@ -210,28 +209,30 @@ my_index (str, chr)
|
||||||
const char *str;
|
const char *str;
|
||||||
int chr;
|
int chr;
|
||||||
{
|
{
|
||||||
while (*str)
|
while(*str) {
|
||||||
{
|
if(*str == chr) {
|
||||||
if (*str == chr)
|
|
||||||
return (char *) str;
|
return (char *) str;
|
||||||
|
}
|
||||||
|
|
||||||
str++;
|
str++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If using GCC, we can safely declare strlen this way.
|
/* If using GCC, we can safely declare strlen this way.
|
||||||
If not using GCC, it is ok not to declare it. */
|
If not using GCC, it is ok not to declare it. */
|
||||||
#ifdef __GNUC__
|
#ifdef GNUC
|
||||||
/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
|
/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
|
||||||
That was relevant to code that was here before. */
|
That was relevant to code that was here before. */
|
||||||
#if !defined (__STDC__) || !__STDC__
|
#if !defined (STDC) || !STDC
|
||||||
/* gcc with -traditional declares the built-in strlen to return int,
|
/* gcc with -traditional declares the built-in strlen to return int,
|
||||||
and has done so at least since version 2.4.5. -- rms. */
|
and has done so at least since version 2.4.5. -- rms. */
|
||||||
extern int strlen(const char *);
|
extern int strlen(const char *);
|
||||||
#endif /* not __STDC__ */
|
#endif /* not STDC */
|
||||||
#endif /* __GNUC__ */
|
#endif /* GNUC */
|
||||||
|
|
||||||
#endif /* not __GNU_LIBRARY__ */
|
#endif /* not GNU_LIBRARY */
|
||||||
|
|
||||||
/* Handle permutation of arguments. */
|
/* Handle permutation of arguments. */
|
||||||
|
|
||||||
|
@ -247,7 +248,7 @@ static int last_nonopt;
|
||||||
indicating ARGV elements that should not be considered arguments. */
|
indicating ARGV elements that should not be considered arguments. */
|
||||||
|
|
||||||
/* Defined in getopt_init.c */
|
/* Defined in getopt_init.c */
|
||||||
extern char *__getopt_nonoption_flags;
|
extern char *getopt_nonoption_flags;
|
||||||
|
|
||||||
static int nonoption_flags_max_len;
|
static int nonoption_flags_max_len;
|
||||||
static int nonoption_flags_len;
|
static int nonoption_flags_len;
|
||||||
|
@ -255,28 +256,27 @@ static int nonoption_flags_len;
|
||||||
static int original_argc;
|
static int original_argc;
|
||||||
static char *const *original_argv;
|
static char *const *original_argv;
|
||||||
|
|
||||||
extern pid_t __libc_pid;
|
extern pid_t libc_pid;
|
||||||
|
|
||||||
/* Make sure the environment variable bash 2.0 puts in the environment
|
/* Make sure the environment variable bash 2.0 puts in the environment
|
||||||
is valid for the getopt call we must make sure that the ARGV passed
|
is valid for the getopt call we must make sure that the ARGV passed
|
||||||
to getopt is that one passed to the process. */
|
to getopt is that one passed to the process. */
|
||||||
static void
|
static void
|
||||||
__attribute__((__unused__))
|
__attribute__((__unused__))
|
||||||
store_args_and_env (int argc, char *const *argv)
|
store_args_and_env(int argc, char *const *argv) {
|
||||||
{
|
|
||||||
/* XXX This is no good solution. We should rather copy the args so
|
/* XXX This is no good solution. We should rather copy the args so
|
||||||
that we can compare them later. But we must not use malloc(3). */
|
that we can compare them later. But we must not use malloc(3). */
|
||||||
original_argc = argc;
|
original_argc = argc;
|
||||||
original_argv = argv;
|
original_argv = argv;
|
||||||
}
|
}
|
||||||
text_set_element (__libc_subinit, store_args_and_env);
|
text_set_element(libc_subinit, store_args_and_env);
|
||||||
|
|
||||||
# define SWAP_FLAGS(ch1, ch2) \
|
# define SWAP_FLAGS(ch1, ch2) \
|
||||||
if (nonoption_flags_len > 0) \
|
if (nonoption_flags_len > 0) \
|
||||||
{ \
|
{ \
|
||||||
char __tmp = __getopt_nonoption_flags[ch1]; \
|
char tmp = getopt_nonoption_flags[ch1]; \
|
||||||
__getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
|
getopt_nonoption_flags[ch1] = getopt_nonoption_flags[ch2]; \
|
||||||
__getopt_nonoption_flags[ch2] = __tmp; \
|
getopt_nonoption_flags[ch2] = tmp; \
|
||||||
}
|
}
|
||||||
#else /* !_LIBC */
|
#else /* !_LIBC */
|
||||||
# define SWAP_FLAGS(ch1, ch2)
|
# define SWAP_FLAGS(ch1, ch2)
|
||||||
|
@ -291,7 +291,7 @@ text_set_element (__libc_subinit, store_args_and_env);
|
||||||
`first_nonopt' and `last_nonopt' are relocated so that they describe
|
`first_nonopt' and `last_nonopt' are relocated so that they describe
|
||||||
the new indices of the non-options in ARGV after they are moved. */
|
the new indices of the non-options in ARGV after they are moved. */
|
||||||
|
|
||||||
#if defined (__STDC__) && __STDC__
|
#if defined (STDC) && STDC
|
||||||
static void exchange(char **);
|
static void exchange(char **);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -310,60 +310,57 @@ exchange (argv)
|
||||||
but it consists of two parts that need to be swapped next. */
|
but it consists of two parts that need to be swapped next. */
|
||||||
|
|
||||||
#ifdef _LIBC
|
#ifdef _LIBC
|
||||||
/* First make sure the handling of the `__getopt_nonoption_flags'
|
|
||||||
|
/* First make sure the handling of the `getopt_nonoption_flags'
|
||||||
string can work normally. Our top argument must be in the range
|
string can work normally. Our top argument must be in the range
|
||||||
of the string. */
|
of the string. */
|
||||||
if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
|
if(nonoption_flags_len > 0 && top >= nonoption_flags_max_len) {
|
||||||
{
|
|
||||||
/* We must extend the array. The user plays games with us and
|
/* We must extend the array. The user plays games with us and
|
||||||
presents new arguments. */
|
presents new arguments. */
|
||||||
char *new_str = malloc(top + 1);
|
char *new_str = malloc(top + 1);
|
||||||
if (new_str == NULL)
|
|
||||||
|
if(new_str == NULL) {
|
||||||
nonoption_flags_len = nonoption_flags_max_len = 0;
|
nonoption_flags_len = nonoption_flags_max_len = 0;
|
||||||
else
|
} else {
|
||||||
{
|
memcpy(new_str, getopt_nonoption_flags, nonoption_flags_max_len);
|
||||||
memcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len);
|
|
||||||
memset(&new_str[nonoption_flags_max_len], '\0',
|
memset(&new_str[nonoption_flags_max_len], '\0',
|
||||||
top + 1 - nonoption_flags_max_len);
|
top + 1 - nonoption_flags_max_len);
|
||||||
nonoption_flags_max_len = top + 1;
|
nonoption_flags_max_len = top + 1;
|
||||||
__getopt_nonoption_flags = new_str;
|
getopt_nonoption_flags = new_str;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (top > middle && middle > bottom)
|
while(top > middle && middle > bottom) {
|
||||||
{
|
if(top - middle > middle - bottom) {
|
||||||
if (top - middle > middle - bottom)
|
|
||||||
{
|
|
||||||
/* Bottom segment is the short one. */
|
/* Bottom segment is the short one. */
|
||||||
int len = middle - bottom;
|
int len = middle - bottom;
|
||||||
register int i;
|
register int i;
|
||||||
|
|
||||||
/* Swap it with the top part of the top segment. */
|
/* Swap it with the top part of the top segment. */
|
||||||
for (i = 0; i < len; i++)
|
for(i = 0; i < len; i++) {
|
||||||
{
|
|
||||||
tem = argv[bottom + i];
|
tem = argv[bottom + i];
|
||||||
argv[bottom + i] = argv[top - (middle - bottom) + i];
|
argv[bottom + i] = argv[top - (middle - bottom) + i];
|
||||||
argv[top - (middle - bottom) + i] = tem;
|
argv[top - (middle - bottom) + i] = tem;
|
||||||
SWAP_FLAGS(bottom + i, top - (middle - bottom) + i);
|
SWAP_FLAGS(bottom + i, top - (middle - bottom) + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Exclude the moved bottom segment from further swapping. */
|
/* Exclude the moved bottom segment from further swapping. */
|
||||||
top -= len;
|
top -= len;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Top segment is the short one. */
|
/* Top segment is the short one. */
|
||||||
int len = top - middle;
|
int len = top - middle;
|
||||||
register int i;
|
register int i;
|
||||||
|
|
||||||
/* Swap it with the bottom part of the bottom segment. */
|
/* Swap it with the bottom part of the bottom segment. */
|
||||||
for (i = 0; i < len; i++)
|
for(i = 0; i < len; i++) {
|
||||||
{
|
|
||||||
tem = argv[bottom + i];
|
tem = argv[bottom + i];
|
||||||
argv[bottom + i] = argv[middle + i];
|
argv[bottom + i] = argv[middle + i];
|
||||||
argv[middle + i] = tem;
|
argv[middle + i] = tem;
|
||||||
SWAP_FLAGS(bottom + i, middle + i);
|
SWAP_FLAGS(bottom + i, middle + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Exclude the moved top segment from further swapping. */
|
/* Exclude the moved top segment from further swapping. */
|
||||||
bottom += len;
|
bottom += len;
|
||||||
}
|
}
|
||||||
|
@ -377,7 +374,7 @@ exchange (argv)
|
||||||
|
|
||||||
/* Initialize the internal data when the first call is made. */
|
/* Initialize the internal data when the first call is made. */
|
||||||
|
|
||||||
#if defined (__STDC__) && __STDC__
|
#if defined (STDC) && STDC
|
||||||
static const char *_getopt_initialize(int, char *const *, const char *);
|
static const char *_getopt_initialize(int, char *const *, const char *);
|
||||||
#endif
|
#endif
|
||||||
static const char *
|
static const char *
|
||||||
|
@ -398,52 +395,52 @@ _getopt_initialize (argc, argv, optstring)
|
||||||
|
|
||||||
/* Determine how to handle the ordering of options and nonoptions. */
|
/* Determine how to handle the ordering of options and nonoptions. */
|
||||||
|
|
||||||
if (optstring[0] == '-')
|
if(optstring[0] == '-') {
|
||||||
{
|
|
||||||
ordering = RETURN_IN_ORDER;
|
ordering = RETURN_IN_ORDER;
|
||||||
++optstring;
|
++optstring;
|
||||||
}
|
} else if(optstring[0] == '+') {
|
||||||
else if (optstring[0] == '+')
|
|
||||||
{
|
|
||||||
ordering = REQUIRE_ORDER;
|
ordering = REQUIRE_ORDER;
|
||||||
++optstring;
|
++optstring;
|
||||||
}
|
} else if(posixly_correct != NULL) {
|
||||||
else if (posixly_correct != NULL)
|
|
||||||
ordering = REQUIRE_ORDER;
|
ordering = REQUIRE_ORDER;
|
||||||
else
|
} else {
|
||||||
ordering = PERMUTE;
|
ordering = PERMUTE;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _LIBC
|
#ifdef _LIBC
|
||||||
|
|
||||||
if(posixly_correct == NULL
|
if(posixly_correct == NULL
|
||||||
&& argc == original_argc && argv == original_argv)
|
&& argc == original_argc && argv == original_argv) {
|
||||||
{
|
if(nonoption_flags_max_len == 0) {
|
||||||
if (nonoption_flags_max_len == 0)
|
if(getopt_nonoption_flags == NULL
|
||||||
{
|
|| getopt_nonoption_flags[0] == '\0') {
|
||||||
if (__getopt_nonoption_flags == NULL
|
|
||||||
|| __getopt_nonoption_flags[0] == '\0')
|
|
||||||
nonoption_flags_max_len = -1;
|
nonoption_flags_max_len = -1;
|
||||||
else
|
} else {
|
||||||
{
|
const char *orig_str = getopt_nonoption_flags;
|
||||||
const char *orig_str = __getopt_nonoption_flags;
|
|
||||||
int len = nonoption_flags_max_len = strlen(orig_str);
|
int len = nonoption_flags_max_len = strlen(orig_str);
|
||||||
if (nonoption_flags_max_len < argc)
|
|
||||||
|
if(nonoption_flags_max_len < argc) {
|
||||||
nonoption_flags_max_len = argc;
|
nonoption_flags_max_len = argc;
|
||||||
__getopt_nonoption_flags =
|
}
|
||||||
|
|
||||||
|
getopt_nonoption_flags =
|
||||||
(char *) malloc(nonoption_flags_max_len);
|
(char *) malloc(nonoption_flags_max_len);
|
||||||
if (__getopt_nonoption_flags == NULL)
|
|
||||||
|
if(getopt_nonoption_flags == NULL) {
|
||||||
nonoption_flags_max_len = -1;
|
nonoption_flags_max_len = -1;
|
||||||
else
|
} else {
|
||||||
{
|
memcpy(getopt_nonoption_flags, orig_str, len);
|
||||||
memcpy (__getopt_nonoption_flags, orig_str, len);
|
memset(&getopt_nonoption_flags[len], '\0',
|
||||||
memset (&__getopt_nonoption_flags[len], '\0',
|
|
||||||
nonoption_flags_max_len - len);
|
nonoption_flags_max_len - len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nonoption_flags_len = nonoption_flags_max_len;
|
nonoption_flags_len = nonoption_flags_max_len;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
nonoption_flags_len = 0;
|
nonoption_flags_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return optstring;
|
return optstring;
|
||||||
|
@ -516,12 +513,13 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
|
||||||
{
|
{
|
||||||
optarg = NULL;
|
optarg = NULL;
|
||||||
|
|
||||||
if (optind == 0 || !__getopt_initialized)
|
if(optind == 0 || !getopt_initialized) {
|
||||||
{
|
if(optind == 0) {
|
||||||
if (optind == 0)
|
|
||||||
optind = 1; /* Don't scan ARGV[0], the program name. */
|
optind = 1; /* Don't scan ARGV[0], the program name. */
|
||||||
|
}
|
||||||
|
|
||||||
optstring = _getopt_initialize(argc, argv, optstring);
|
optstring = _getopt_initialize(argc, argv, optstring);
|
||||||
__getopt_initialized = 1;
|
getopt_initialized = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test whether ARGV[optind] points to a non-option argument.
|
/* Test whether ARGV[optind] points to a non-option argument.
|
||||||
|
@ -531,37 +529,41 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
|
||||||
#ifdef _LIBC
|
#ifdef _LIBC
|
||||||
#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
|
#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
|
||||||
|| (optind < nonoption_flags_len \
|
|| (optind < nonoption_flags_len \
|
||||||
&& __getopt_nonoption_flags[optind] == '1'))
|
&& getopt_nonoption_flags[optind] == '1'))
|
||||||
#else
|
#else
|
||||||
#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
|
#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (nextchar == NULL || *nextchar == '\0')
|
if(nextchar == NULL || *nextchar == '\0') {
|
||||||
{
|
|
||||||
/* Advance to the next ARGV-element. */
|
/* Advance to the next ARGV-element. */
|
||||||
|
|
||||||
/* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
|
/* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
|
||||||
moved back by the user (who may also have changed the arguments). */
|
moved back by the user (who may also have changed the arguments). */
|
||||||
if (last_nonopt > optind)
|
if(last_nonopt > optind) {
|
||||||
last_nonopt = optind;
|
last_nonopt = optind;
|
||||||
if (first_nonopt > optind)
|
}
|
||||||
first_nonopt = optind;
|
|
||||||
|
|
||||||
if (ordering == PERMUTE)
|
if(first_nonopt > optind) {
|
||||||
{
|
first_nonopt = optind;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ordering == PERMUTE) {
|
||||||
/* If we have just processed some options following some non-options,
|
/* If we have just processed some options following some non-options,
|
||||||
exchange them so that the options come first. */
|
exchange them so that the options come first. */
|
||||||
|
|
||||||
if (first_nonopt != last_nonopt && last_nonopt != optind)
|
if(first_nonopt != last_nonopt && last_nonopt != optind) {
|
||||||
exchange((char **) argv);
|
exchange((char **) argv);
|
||||||
else if (last_nonopt != optind)
|
} else if(last_nonopt != optind) {
|
||||||
first_nonopt = optind;
|
first_nonopt = optind;
|
||||||
|
}
|
||||||
|
|
||||||
/* Skip any additional non-options
|
/* Skip any additional non-options
|
||||||
and extend the range of non-options previously skipped. */
|
and extend the range of non-options previously skipped. */
|
||||||
|
|
||||||
while (optind < argc && NONOPTION_P)
|
while(optind < argc && NONOPTION_P) {
|
||||||
optind++;
|
optind++;
|
||||||
|
}
|
||||||
|
|
||||||
last_nonopt = optind;
|
last_nonopt = optind;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,14 +572,15 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
|
||||||
then exchange with previous non-options as if it were an option,
|
then exchange with previous non-options as if it were an option,
|
||||||
then skip everything else like a non-option. */
|
then skip everything else like a non-option. */
|
||||||
|
|
||||||
if (optind != argc && !strcmp (argv[optind], "--"))
|
if(optind != argc && !strcmp(argv[optind], "--")) {
|
||||||
{
|
|
||||||
optind++;
|
optind++;
|
||||||
|
|
||||||
if (first_nonopt != last_nonopt && last_nonopt != optind)
|
if(first_nonopt != last_nonopt && last_nonopt != optind) {
|
||||||
exchange((char **) argv);
|
exchange((char **) argv);
|
||||||
else if (first_nonopt == last_nonopt)
|
} else if(first_nonopt == last_nonopt) {
|
||||||
first_nonopt = optind;
|
first_nonopt = optind;
|
||||||
|
}
|
||||||
|
|
||||||
last_nonopt = argc;
|
last_nonopt = argc;
|
||||||
|
|
||||||
optind = argc;
|
optind = argc;
|
||||||
|
@ -586,22 +589,24 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
|
||||||
/* If we have done all the ARGV-elements, stop the scan
|
/* If we have done all the ARGV-elements, stop the scan
|
||||||
and back over any non-options that we skipped and permuted. */
|
and back over any non-options that we skipped and permuted. */
|
||||||
|
|
||||||
if (optind == argc)
|
if(optind == argc) {
|
||||||
{
|
|
||||||
/* Set the next-arg-index to point at the non-options
|
/* Set the next-arg-index to point at the non-options
|
||||||
that we previously skipped, so the caller will digest them. */
|
that we previously skipped, so the caller will digest them. */
|
||||||
if (first_nonopt != last_nonopt)
|
if(first_nonopt != last_nonopt) {
|
||||||
optind = first_nonopt;
|
optind = first_nonopt;
|
||||||
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we have come to a non-option and did not permute it,
|
/* If we have come to a non-option and did not permute it,
|
||||||
either stop the scan or describe it to the caller and pass it by. */
|
either stop the scan or describe it to the caller and pass it by. */
|
||||||
|
|
||||||
if (NONOPTION_P)
|
if(NONOPTION_P) {
|
||||||
{
|
if(ordering == REQUIRE_ORDER) {
|
||||||
if (ordering == REQUIRE_ORDER)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
optarg = argv[optind++];
|
optarg = argv[optind++];
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -630,8 +635,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
|
||||||
|
|
||||||
if(longopts != NULL
|
if(longopts != NULL
|
||||||
&& (argv[optind][1] == '-'
|
&& (argv[optind][1] == '-'
|
||||||
|| (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
|
|| (long_only && (argv[optind][2] || !my_index(optstring, argv[optind][1]))))) {
|
||||||
{
|
|
||||||
char *nameend;
|
char *nameend;
|
||||||
const struct option *p;
|
const struct option *p;
|
||||||
const struct option *pfound = NULL;
|
const struct option *pfound = NULL;
|
||||||
|
@ -646,53 +650,47 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
|
||||||
/* Test all long options for either exact match
|
/* Test all long options for either exact match
|
||||||
or abbreviated matches. */
|
or abbreviated matches. */
|
||||||
for(p = longopts, option_index = 0; p->name; p++, option_index++)
|
for(p = longopts, option_index = 0; p->name; p++, option_index++)
|
||||||
if (!strncmp (p->name, nextchar, nameend - nextchar))
|
if(!strncmp(p->name, nextchar, nameend - nextchar)) {
|
||||||
{
|
|
||||||
if((unsigned int)(nameend - nextchar)
|
if((unsigned int)(nameend - nextchar)
|
||||||
== (unsigned int) strlen (p->name))
|
== (unsigned int) strlen(p->name)) {
|
||||||
{
|
|
||||||
/* Exact match found. */
|
/* Exact match found. */
|
||||||
pfound = p;
|
pfound = p;
|
||||||
indfound = option_index;
|
indfound = option_index;
|
||||||
exact = 1;
|
exact = 1;
|
||||||
break;
|
break;
|
||||||
}
|
} else if(pfound == NULL) {
|
||||||
else if (pfound == NULL)
|
|
||||||
{
|
|
||||||
/* First nonexact match found. */
|
/* First nonexact match found. */
|
||||||
pfound = p;
|
pfound = p;
|
||||||
indfound = option_index;
|
indfound = option_index;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
/* Second or later nonexact match found. */
|
/* Second or later nonexact match found. */
|
||||||
|
{
|
||||||
ambig = 1;
|
ambig = 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ambig && !exact)
|
if(ambig && !exact) {
|
||||||
{
|
|
||||||
if(opterr)
|
if(opterr)
|
||||||
fprintf(stderr, "%s: option `%s' is ambiguous\n",
|
fprintf(stderr, "%s: option `%s' is ambiguous\n",
|
||||||
argv[0], argv[optind]);
|
argv[0], argv[optind]);
|
||||||
|
|
||||||
nextchar += strlen(nextchar);
|
nextchar += strlen(nextchar);
|
||||||
optind++;
|
optind++;
|
||||||
optopt = 0;
|
optopt = 0;
|
||||||
return '?';
|
return '?';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pfound != NULL)
|
if(pfound != NULL) {
|
||||||
{
|
|
||||||
option_index = indfound;
|
option_index = indfound;
|
||||||
optind++;
|
optind++;
|
||||||
if (*nameend)
|
|
||||||
{
|
if(*nameend) {
|
||||||
/* Don't test has_arg with >, because some C compilers don't
|
/* Don't test has_arg with >, because some C compilers don't
|
||||||
allow it to be used on enums. */
|
allow it to be used on enums. */
|
||||||
if (pfound->has_arg)
|
if(pfound->has_arg) {
|
||||||
optarg = nameend + 1;
|
optarg = nameend + 1;
|
||||||
else
|
} else {
|
||||||
{
|
if(opterr) {
|
||||||
if (opterr)
|
|
||||||
{
|
|
||||||
if(argv[optind - 1][1] == '-')
|
if(argv[optind - 1][1] == '-')
|
||||||
/* --option */
|
/* --option */
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
|
@ -710,30 +708,32 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
|
||||||
optopt = pfound->val;
|
optopt = pfound->val;
|
||||||
return '?';
|
return '?';
|
||||||
}
|
}
|
||||||
}
|
} else if(pfound->has_arg == 1) {
|
||||||
else if (pfound->has_arg == 1)
|
if(optind < argc) {
|
||||||
{
|
|
||||||
if (optind < argc)
|
|
||||||
optarg = argv[optind++];
|
optarg = argv[optind++];
|
||||||
else
|
} else {
|
||||||
{
|
|
||||||
if(opterr)
|
if(opterr)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%s: option `%s' requires an argument\n",
|
"%s: option `%s' requires an argument\n",
|
||||||
argv[0], argv[optind - 1]);
|
argv[0], argv[optind - 1]);
|
||||||
|
|
||||||
nextchar += strlen(nextchar);
|
nextchar += strlen(nextchar);
|
||||||
optopt = pfound->val;
|
optopt = pfound->val;
|
||||||
return optstring[0] == ':' ? ':' : '?';
|
return optstring[0] == ':' ? ':' : '?';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nextchar += strlen(nextchar);
|
nextchar += strlen(nextchar);
|
||||||
if (longind != NULL)
|
|
||||||
|
if(longind != NULL) {
|
||||||
*longind = option_index;
|
*longind = option_index;
|
||||||
if (pfound->flag)
|
}
|
||||||
{
|
|
||||||
|
if(pfound->flag) {
|
||||||
*(pfound->flag) = pfound->val;
|
*(pfound->flag) = pfound->val;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pfound->val;
|
return pfound->val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -742,10 +742,8 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
|
||||||
option, then it's an error.
|
option, then it's an error.
|
||||||
Otherwise interpret it as a short option. */
|
Otherwise interpret it as a short option. */
|
||||||
if(!long_only || argv[optind][1] == '-'
|
if(!long_only || argv[optind][1] == '-'
|
||||||
|| my_index (optstring, *nextchar) == NULL)
|
|| my_index(optstring, *nextchar) == NULL) {
|
||||||
{
|
if(opterr) {
|
||||||
if (opterr)
|
|
||||||
{
|
|
||||||
if(argv[optind][1] == '-')
|
if(argv[optind][1] == '-')
|
||||||
/* --option */
|
/* --option */
|
||||||
fprintf(stderr, "%s: unrecognized option `--%s'\n",
|
fprintf(stderr, "%s: unrecognized option `--%s'\n",
|
||||||
|
@ -755,6 +753,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
|
||||||
fprintf(stderr, "%s: unrecognized option `%c%s'\n",
|
fprintf(stderr, "%s: unrecognized option `%c%s'\n",
|
||||||
argv[0], argv[optind][0], nextchar);
|
argv[0], argv[optind][0], nextchar);
|
||||||
}
|
}
|
||||||
|
|
||||||
nextchar = (char *) "";
|
nextchar = (char *) "";
|
||||||
optind++;
|
optind++;
|
||||||
optopt = 0;
|
optopt = 0;
|
||||||
|
@ -769,13 +768,12 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
|
||||||
char *temp = my_index(optstring, c);
|
char *temp = my_index(optstring, c);
|
||||||
|
|
||||||
/* Increment `optind' when we start to process its last character. */
|
/* Increment `optind' when we start to process its last character. */
|
||||||
if (*nextchar == '\0')
|
if(*nextchar == '\0') {
|
||||||
++optind;
|
++optind;
|
||||||
|
}
|
||||||
|
|
||||||
if (temp == NULL || c == ':')
|
if(temp == NULL || c == ':') {
|
||||||
{
|
if(opterr) {
|
||||||
if (opterr)
|
|
||||||
{
|
|
||||||
if(posixly_correct)
|
if(posixly_correct)
|
||||||
/* 1003.2 specifies the format of this message. */
|
/* 1003.2 specifies the format of this message. */
|
||||||
fprintf(stderr, "%s: illegal option -- %c\n",
|
fprintf(stderr, "%s: illegal option -- %c\n",
|
||||||
|
@ -784,12 +782,13 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
|
||||||
fprintf(stderr, "%s: invalid option -- %c\n",
|
fprintf(stderr, "%s: invalid option -- %c\n",
|
||||||
argv[0], c);
|
argv[0], c);
|
||||||
}
|
}
|
||||||
|
|
||||||
optopt = c;
|
optopt = c;
|
||||||
return '?';
|
return '?';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convenience. Treat POSIX -W foo same as long option --foo */
|
/* Convenience. Treat POSIX -W foo same as long option --foo */
|
||||||
if (temp[0] == 'W' && temp[1] == ';')
|
if(temp[0] == 'W' && temp[1] == ';') {
|
||||||
{
|
|
||||||
char *nameend;
|
char *nameend;
|
||||||
const struct option *p;
|
const struct option *p;
|
||||||
const struct option *pfound = NULL;
|
const struct option *pfound = NULL;
|
||||||
|
@ -799,32 +798,33 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
|
||||||
int option_index;
|
int option_index;
|
||||||
|
|
||||||
/* This is an option that requires an argument. */
|
/* This is an option that requires an argument. */
|
||||||
if (*nextchar != '\0')
|
if(*nextchar != '\0') {
|
||||||
{
|
|
||||||
optarg = nextchar;
|
optarg = nextchar;
|
||||||
/* If we end this ARGV-element by taking the rest as an arg,
|
/* If we end this ARGV-element by taking the rest as an arg,
|
||||||
we must advance to the next element now. */
|
we must advance to the next element now. */
|
||||||
optind++;
|
optind++;
|
||||||
}
|
} else if(optind == argc) {
|
||||||
else if (optind == argc)
|
if(opterr) {
|
||||||
{
|
|
||||||
if (opterr)
|
|
||||||
{
|
|
||||||
/* 1003.2 specifies the format of this message. */
|
/* 1003.2 specifies the format of this message. */
|
||||||
fprintf(stderr, "%s: option requires an argument -- %c\n",
|
fprintf(stderr, "%s: option requires an argument -- %c\n",
|
||||||
argv[0], c);
|
argv[0], c);
|
||||||
}
|
}
|
||||||
|
|
||||||
optopt = c;
|
optopt = c;
|
||||||
if (optstring[0] == ':')
|
|
||||||
|
if(optstring[0] == ':') {
|
||||||
c = ':';
|
c = ':';
|
||||||
else
|
} else {
|
||||||
c = '?';
|
c = '?';
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
return c;
|
||||||
|
} else
|
||||||
/* We already incremented `optind' once;
|
/* We already incremented `optind' once;
|
||||||
increment it again when taking next ARGV-elt as argument. */
|
increment it again when taking next ARGV-elt as argument. */
|
||||||
|
{
|
||||||
optarg = argv[optind++];
|
optarg = argv[optind++];
|
||||||
|
}
|
||||||
|
|
||||||
/* optarg is now the argument, see if it's in the
|
/* optarg is now the argument, see if it's in the
|
||||||
table of longopts. */
|
table of longopts. */
|
||||||
|
@ -835,46 +835,43 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
|
||||||
/* Test all long options for either exact match
|
/* Test all long options for either exact match
|
||||||
or abbreviated matches. */
|
or abbreviated matches. */
|
||||||
for(p = longopts, option_index = 0; p->name; p++, option_index++)
|
for(p = longopts, option_index = 0; p->name; p++, option_index++)
|
||||||
if (!strncmp (p->name, nextchar, nameend - nextchar))
|
if(!strncmp(p->name, nextchar, nameend - nextchar)) {
|
||||||
{
|
if((unsigned int)(nameend - nextchar) == strlen(p->name)) {
|
||||||
if ((unsigned int) (nameend - nextchar) == strlen (p->name))
|
|
||||||
{
|
|
||||||
/* Exact match found. */
|
/* Exact match found. */
|
||||||
pfound = p;
|
pfound = p;
|
||||||
indfound = option_index;
|
indfound = option_index;
|
||||||
exact = 1;
|
exact = 1;
|
||||||
break;
|
break;
|
||||||
}
|
} else if(pfound == NULL) {
|
||||||
else if (pfound == NULL)
|
|
||||||
{
|
|
||||||
/* First nonexact match found. */
|
/* First nonexact match found. */
|
||||||
pfound = p;
|
pfound = p;
|
||||||
indfound = option_index;
|
indfound = option_index;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
/* Second or later nonexact match found. */
|
/* Second or later nonexact match found. */
|
||||||
|
{
|
||||||
ambig = 1;
|
ambig = 1;
|
||||||
}
|
}
|
||||||
if (ambig && !exact)
|
}
|
||||||
{
|
|
||||||
|
if(ambig && !exact) {
|
||||||
if(opterr)
|
if(opterr)
|
||||||
fprintf(stderr, "%s: option `-W %s' is ambiguous\n",
|
fprintf(stderr, "%s: option `-W %s' is ambiguous\n",
|
||||||
argv[0], argv[optind]);
|
argv[0], argv[optind]);
|
||||||
|
|
||||||
nextchar += strlen(nextchar);
|
nextchar += strlen(nextchar);
|
||||||
optind++;
|
optind++;
|
||||||
return '?';
|
return '?';
|
||||||
}
|
}
|
||||||
if (pfound != NULL)
|
|
||||||
{
|
if(pfound != NULL) {
|
||||||
option_index = indfound;
|
option_index = indfound;
|
||||||
if (*nameend)
|
|
||||||
{
|
if(*nameend) {
|
||||||
/* Don't test has_arg with >, because some C compilers don't
|
/* Don't test has_arg with >, because some C compilers don't
|
||||||
allow it to be used on enums. */
|
allow it to be used on enums. */
|
||||||
if (pfound->has_arg)
|
if(pfound->has_arg) {
|
||||||
optarg = nameend + 1;
|
optarg = nameend + 1;
|
||||||
else
|
} else {
|
||||||
{
|
|
||||||
if(opterr)
|
if(opterr)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%s: option `-W %s' doesn't allow an argument\n",
|
"%s: option `-W %s' doesn't allow an argument\n",
|
||||||
|
@ -883,80 +880,82 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
|
||||||
nextchar += strlen(nextchar);
|
nextchar += strlen(nextchar);
|
||||||
return '?';
|
return '?';
|
||||||
}
|
}
|
||||||
}
|
} else if(pfound->has_arg == 1) {
|
||||||
else if (pfound->has_arg == 1)
|
if(optind < argc) {
|
||||||
{
|
|
||||||
if (optind < argc)
|
|
||||||
optarg = argv[optind++];
|
optarg = argv[optind++];
|
||||||
else
|
} else {
|
||||||
{
|
|
||||||
if(opterr)
|
if(opterr)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%s: option `%s' requires an argument\n",
|
"%s: option `%s' requires an argument\n",
|
||||||
argv[0], argv[optind - 1]);
|
argv[0], argv[optind - 1]);
|
||||||
|
|
||||||
nextchar += strlen(nextchar);
|
nextchar += strlen(nextchar);
|
||||||
return optstring[0] == ':' ? ':' : '?';
|
return optstring[0] == ':' ? ':' : '?';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nextchar += strlen(nextchar);
|
nextchar += strlen(nextchar);
|
||||||
if (longind != NULL)
|
|
||||||
|
if(longind != NULL) {
|
||||||
*longind = option_index;
|
*longind = option_index;
|
||||||
if (pfound->flag)
|
}
|
||||||
{
|
|
||||||
|
if(pfound->flag) {
|
||||||
*(pfound->flag) = pfound->val;
|
*(pfound->flag) = pfound->val;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pfound->val;
|
return pfound->val;
|
||||||
}
|
}
|
||||||
|
|
||||||
nextchar = NULL;
|
nextchar = NULL;
|
||||||
return 'W'; /* Let the application handle it. */
|
return 'W'; /* Let the application handle it. */
|
||||||
}
|
}
|
||||||
if (temp[1] == ':')
|
|
||||||
{
|
if(temp[1] == ':') {
|
||||||
if (temp[2] == ':')
|
if(temp[2] == ':') {
|
||||||
{
|
|
||||||
/* This is an option that accepts an argument optionally. */
|
/* This is an option that accepts an argument optionally. */
|
||||||
if (*nextchar != '\0')
|
if(*nextchar != '\0') {
|
||||||
{
|
|
||||||
optarg = nextchar;
|
optarg = nextchar;
|
||||||
optind++;
|
optind++;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
optarg = NULL;
|
optarg = NULL;
|
||||||
nextchar = NULL;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
nextchar = NULL;
|
||||||
|
} else {
|
||||||
/* This is an option that requires an argument. */
|
/* This is an option that requires an argument. */
|
||||||
if (*nextchar != '\0')
|
if(*nextchar != '\0') {
|
||||||
{
|
|
||||||
optarg = nextchar;
|
optarg = nextchar;
|
||||||
/* If we end this ARGV-element by taking the rest as an arg,
|
/* If we end this ARGV-element by taking the rest as an arg,
|
||||||
we must advance to the next element now. */
|
we must advance to the next element now. */
|
||||||
optind++;
|
optind++;
|
||||||
}
|
} else if(optind == argc) {
|
||||||
else if (optind == argc)
|
if(opterr) {
|
||||||
{
|
|
||||||
if (opterr)
|
|
||||||
{
|
|
||||||
/* 1003.2 specifies the format of this message. */
|
/* 1003.2 specifies the format of this message. */
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%s: option requires an argument -- %c\n",
|
"%s: option requires an argument -- %c\n",
|
||||||
argv[0], c);
|
argv[0], c);
|
||||||
}
|
}
|
||||||
|
|
||||||
optopt = c;
|
optopt = c;
|
||||||
if (optstring[0] == ':')
|
|
||||||
|
if(optstring[0] == ':') {
|
||||||
c = ':';
|
c = ':';
|
||||||
else
|
} else {
|
||||||
c = '?';
|
c = '?';
|
||||||
}
|
}
|
||||||
else
|
} else
|
||||||
/* We already incremented `optind' once;
|
/* We already incremented `optind' once;
|
||||||
increment it again when taking next ARGV-elt as argument. */
|
increment it again when taking next ARGV-elt as argument. */
|
||||||
|
{
|
||||||
optarg = argv[optind++];
|
optarg = argv[optind++];
|
||||||
|
}
|
||||||
|
|
||||||
nextchar = NULL;
|
nextchar = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -988,16 +987,16 @@ main (argc, argv)
|
||||||
int c;
|
int c;
|
||||||
int digit_optind = 0;
|
int digit_optind = 0;
|
||||||
|
|
||||||
while (1)
|
while(1) {
|
||||||
{
|
|
||||||
int this_option_optind = optind ? optind : 1;
|
int this_option_optind = optind ? optind : 1;
|
||||||
|
|
||||||
c = getopt(argc, argv, "abc:d:0123456789");
|
c = getopt(argc, argv, "abc:d:0123456789");
|
||||||
if (c == -1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
switch (c)
|
if(c == -1) {
|
||||||
{
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(c) {
|
||||||
case '0':
|
case '0':
|
||||||
case '1':
|
case '1':
|
||||||
case '2':
|
case '2':
|
||||||
|
@ -1008,8 +1007,10 @@ main (argc, argv)
|
||||||
case '7':
|
case '7':
|
||||||
case '8':
|
case '8':
|
||||||
case '9':
|
case '9':
|
||||||
if (digit_optind != 0 && digit_optind != this_option_optind)
|
if(digit_optind != 0 && digit_optind != this_option_optind) {
|
||||||
printf("digits occur in two different argv-elements.\n");
|
printf("digits occur in two different argv-elements.\n");
|
||||||
|
}
|
||||||
|
|
||||||
digit_optind = this_option_optind;
|
digit_optind = this_option_optind;
|
||||||
printf("option %c\n", c);
|
printf("option %c\n", c);
|
||||||
break;
|
break;
|
||||||
|
@ -1034,11 +1035,13 @@ main (argc, argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optind < argc)
|
if(optind < argc) {
|
||||||
{
|
|
||||||
printf("non-option ARGV-elements: ");
|
printf("non-option ARGV-elements: ");
|
||||||
while (optind < argc)
|
|
||||||
|
while(optind < argc) {
|
||||||
printf("%s ", argv[optind++]);
|
printf("%s ", argv[optind++]);
|
||||||
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
29
src/getopt.h
29
src/getopt.h
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_GETOPT_H
|
||||||
|
#define TINC_GETOPT_H
|
||||||
|
|
||||||
/* Declarations for getopt.
|
/* Declarations for getopt.
|
||||||
Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc.
|
Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
@ -19,10 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _GETOPT_H
|
#ifdef cplusplus
|
||||||
#define _GETOPT_H 1
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -78,9 +78,8 @@ extern int optopt;
|
||||||
one). For long options that have a zero `flag' field, `getopt'
|
one). For long options that have a zero `flag' field, `getopt'
|
||||||
returns the contents of the `val' field. */
|
returns the contents of the `val' field. */
|
||||||
|
|
||||||
struct option
|
struct option {
|
||||||
{
|
#if defined (STDC) && STDC
|
||||||
#if defined (__STDC__) && __STDC__
|
|
||||||
const char *name;
|
const char *name;
|
||||||
#else
|
#else
|
||||||
char *name;
|
char *name;
|
||||||
|
@ -98,15 +97,15 @@ struct option
|
||||||
#define required_argument 1
|
#define required_argument 1
|
||||||
#define optional_argument 2
|
#define optional_argument 2
|
||||||
|
|
||||||
#if defined (__STDC__) && __STDC__
|
#if defined (STDC) && STDC
|
||||||
#ifdef __GNU_LIBRARY__
|
#ifdef GNU_LIBRARY
|
||||||
/* Many other libraries have conflicting prototypes for getopt, with
|
/* Many other libraries have conflicting prototypes for getopt, with
|
||||||
differences in the consts, in stdlib.h. To avoid compilation
|
differences in the consts, in stdlib.h. To avoid compilation
|
||||||
errors, only prototype getopt for the GNU C library. */
|
errors, only prototype getopt for the GNU C library. */
|
||||||
extern int getopt(int argc, char *const *argv, const char *shortopts);
|
extern int getopt(int argc, char *const *argv, const char *shortopts);
|
||||||
#else /* not __GNU_LIBRARY__ */
|
#else /* not GNU_LIBRARY */
|
||||||
extern int getopt();
|
extern int getopt();
|
||||||
#endif /* __GNU_LIBRARY__ */
|
#endif /* GNU_LIBRARY */
|
||||||
extern int getopt_long(int argc, char *const *argv, const char *shortopts,
|
extern int getopt_long(int argc, char *const *argv, const char *shortopts,
|
||||||
const struct option *longopts, int *longind);
|
const struct option *longopts, int *longind);
|
||||||
extern int getopt_long_only(int argc, char *const *argv,
|
extern int getopt_long_only(int argc, char *const *argv,
|
||||||
|
@ -118,16 +117,16 @@ extern int _getopt_internal (int argc, char *const *argv,
|
||||||
const char *shortopts,
|
const char *shortopts,
|
||||||
const struct option *longopts, int *longind,
|
const struct option *longopts, int *longind,
|
||||||
int long_only);
|
int long_only);
|
||||||
#else /* not __STDC__ */
|
#else /* not STDC */
|
||||||
extern int getopt();
|
extern int getopt();
|
||||||
extern int getopt_long();
|
extern int getopt_long();
|
||||||
extern int getopt_long_only();
|
extern int getopt_long_only();
|
||||||
|
|
||||||
extern int _getopt_internal();
|
extern int _getopt_internal();
|
||||||
#endif /* __STDC__ */
|
#endif /* STDC */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _GETOPT_H */
|
#endif
|
||||||
|
|
|
@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
#include "getopt.h"
|
#include "getopt.h"
|
||||||
|
|
||||||
#if !defined (__STDC__) || !__STDC__
|
#if !defined (STDC) || !STDC
|
||||||
/* This is a separate conditional since some stdc systems
|
/* This is a separate conditional since some stdc systems
|
||||||
reject `defined (const)'. */
|
reject `defined (const)'. */
|
||||||
#ifndef const
|
#ifndef const
|
||||||
|
@ -44,7 +44,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
it is simpler to just do this in the source for each such file. */
|
it is simpler to just do this in the source for each such file. */
|
||||||
|
|
||||||
#define GETOPT_INTERFACE_VERSION 2
|
#define GETOPT_INTERFACE_VERSION 2
|
||||||
#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2
|
#if !defined (_LIBC) && defined (GLIBC) && GLIBC >= 2
|
||||||
#include <gnu-versions.h>
|
#include <gnu-versions.h>
|
||||||
#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
|
#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
|
||||||
#define ELIDE_CODE
|
#define ELIDE_CODE
|
||||||
|
@ -55,8 +55,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
|
|
||||||
/* This needs to come after some library #include
|
/* This needs to come after some library #include
|
||||||
to get __GNU_LIBRARY__ defined. */
|
to get GNU_LIBRARY defined. */
|
||||||
#ifdef __GNU_LIBRARY__
|
#ifdef GNU_LIBRARY
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -106,12 +106,10 @@ main (argc, argv)
|
||||||
int c;
|
int c;
|
||||||
int digit_optind = 0;
|
int digit_optind = 0;
|
||||||
|
|
||||||
while (1)
|
while(1) {
|
||||||
{
|
|
||||||
int this_option_optind = optind ? optind : 1;
|
int this_option_optind = optind ? optind : 1;
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
static struct option long_options[] =
|
static struct option long_options[] = {
|
||||||
{
|
|
||||||
{"add", 1, 0, 0},
|
{"add", 1, 0, 0},
|
||||||
{"append", 0, 0, 0},
|
{"append", 0, 0, 0},
|
||||||
{"delete", 1, 0, 0},
|
{"delete", 1, 0, 0},
|
||||||
|
@ -123,15 +121,19 @@ main (argc, argv)
|
||||||
|
|
||||||
c = getopt_long(argc, argv, "abc:d:0123456789",
|
c = getopt_long(argc, argv, "abc:d:0123456789",
|
||||||
long_options, &option_index);
|
long_options, &option_index);
|
||||||
if (c == -1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
switch (c)
|
if(c == -1) {
|
||||||
{
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(c) {
|
||||||
case 0:
|
case 0:
|
||||||
printf("option %s", long_options[option_index].name);
|
printf("option %s", long_options[option_index].name);
|
||||||
if (optarg)
|
|
||||||
|
if(optarg) {
|
||||||
printf(" with arg %s", optarg);
|
printf(" with arg %s", optarg);
|
||||||
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -145,8 +147,10 @@ main (argc, argv)
|
||||||
case '7':
|
case '7':
|
||||||
case '8':
|
case '8':
|
||||||
case '9':
|
case '9':
|
||||||
if (digit_optind != 0 && digit_optind != this_option_optind)
|
if(digit_optind != 0 && digit_optind != this_option_optind) {
|
||||||
printf("digits occur in two different argv-elements.\n");
|
printf("digits occur in two different argv-elements.\n");
|
||||||
|
}
|
||||||
|
|
||||||
digit_optind = this_option_optind;
|
digit_optind = this_option_optind;
|
||||||
printf("option %c\n", c);
|
printf("option %c\n", c);
|
||||||
break;
|
break;
|
||||||
|
@ -175,11 +179,13 @@ main (argc, argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optind < argc)
|
if(optind < argc) {
|
||||||
{
|
|
||||||
printf("non-option ARGV-elements: ");
|
printf("non-option ARGV-elements: ");
|
||||||
while (optind < argc)
|
|
||||||
|
while(optind < argc) {
|
||||||
printf("%s ", argv[optind++]);
|
printf("%s ", argv[optind++]);
|
||||||
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
35
src/graph.c
35
src/graph.c
|
@ -84,8 +84,9 @@ static void mst_kruskal(void) {
|
||||||
|
|
||||||
/* Do we have something to do at all? */
|
/* Do we have something to do at all? */
|
||||||
|
|
||||||
if(!edge_weight_tree->head)
|
if(!edge_weight_tree->head) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Running Kruskal's algorithm:");
|
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) {
|
for(node = edge_weight_tree->head; node; node = node->next) {
|
||||||
e = node->data;
|
e = node->data;
|
||||||
|
|
||||||
if(e->from->status.reachable) {
|
if(e->from->status.reachable) {
|
||||||
e->from->status.visited = true;
|
e->from->status.visited = true;
|
||||||
break;
|
break;
|
||||||
|
@ -121,11 +123,13 @@ static void mst_kruskal(void) {
|
||||||
e->from->status.visited = true;
|
e->from->status.visited = true;
|
||||||
e->to->status.visited = true;
|
e->to->status.visited = true;
|
||||||
|
|
||||||
if(e->connection)
|
if(e->connection) {
|
||||||
e->connection->status.mst = true;
|
e->connection->status.mst = true;
|
||||||
|
}
|
||||||
|
|
||||||
if(e->reverse->connection)
|
if(e->reverse->connection) {
|
||||||
e->reverse->connection->status.mst = true;
|
e->reverse->connection->status.mst = true;
|
||||||
|
}
|
||||||
|
|
||||||
safe_edges++;
|
safe_edges++;
|
||||||
|
|
||||||
|
@ -186,8 +190,9 @@ static void sssp_bfs(void) {
|
||||||
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;
|
e = to->data;
|
||||||
|
|
||||||
if(!e->reverse)
|
if(!e->reverse) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Situation:
|
/* Situation:
|
||||||
|
|
||||||
|
@ -209,13 +214,15 @@ static void sssp_bfs(void) {
|
||||||
indirect = n->status.indirect || e->options & OPTION_INDIRECT;
|
indirect = n->status.indirect || e->options & OPTION_INDIRECT;
|
||||||
|
|
||||||
if(e->to->status.visited
|
if(e->to->status.visited
|
||||||
&& (!e->to->status.indirect || indirect))
|
&& (!e->to->status.indirect || indirect)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Only update nexthop the first time we visit this node.
|
// 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->nexthop = (n->nexthop == myself) ? e->to : n->nexthop;
|
||||||
|
}
|
||||||
|
|
||||||
e->to->status.visited = true;
|
e->to->status.visited = true;
|
||||||
e->to->status.indirect = indirect;
|
e->to->status.indirect = indirect;
|
||||||
|
@ -223,8 +230,9 @@ static void sssp_bfs(void) {
|
||||||
e->to->via = indirect ? n->via : e->to;
|
e->to->via = indirect ? n->via : e->to;
|
||||||
e->to->options = e->options;
|
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);
|
update_node_udp(e->to, &e->address);
|
||||||
|
}
|
||||||
|
|
||||||
list_insert_tail(todo_list, e->to);
|
list_insert_tail(todo_list, e->to);
|
||||||
}
|
}
|
||||||
|
@ -286,14 +294,15 @@ static void sssp_bfs(void) {
|
||||||
free(address);
|
free(address);
|
||||||
free(port);
|
free(port);
|
||||||
|
|
||||||
for(i = 0; i < 7; i++)
|
for(i = 0; i < 7; i++) {
|
||||||
free(envp[i]);
|
free(envp[i]);
|
||||||
|
}
|
||||||
|
|
||||||
subnet_update(n, NULL, n->status.reachable);
|
subnet_update(n, NULL, n->status.reachable);
|
||||||
|
|
||||||
if(!n->status.reachable) {
|
if(!n->status.reachable) {
|
||||||
update_node_udp(n, NULL);
|
update_node_udp(n, NULL);
|
||||||
memset(&n->status, 0, sizeof n->status);
|
memset(&n->status, 0, sizeof(n->status));
|
||||||
n->options = 0;
|
n->options = 0;
|
||||||
} else if(n->connection) {
|
} else if(n->connection) {
|
||||||
send_ans_key(n);
|
send_ans_key(n);
|
||||||
|
@ -324,8 +333,9 @@ void dump_graph(void) {
|
||||||
char *filename = NULL, *tmpname = NULL;
|
char *filename = NULL, *tmpname = NULL;
|
||||||
FILE *file, *pipe = 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;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
graph_changed = false;
|
graph_changed = false;
|
||||||
|
|
||||||
|
@ -368,8 +378,11 @@ void dump_graph(void) {
|
||||||
#ifdef HAVE_MINGW
|
#ifdef HAVE_MINGW
|
||||||
unlink(filename);
|
unlink(filename);
|
||||||
#endif
|
#endif
|
||||||
if(rename(tmpname, filename))
|
|
||||||
|
if(rename(tmpname, filename)) {
|
||||||
logger(LOG_ERR, "Could not rename %s to %s: %s\n", tmpname, filename, strerror(errno));
|
logger(LOG_ERR, "Could not rename %s to %s: %s\n", tmpname, filename, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
free(tmpname);
|
free(tmpname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_GRAPH_H
|
||||||
|
#define TINC_GRAPH_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
graph.h -- header for graph.c
|
graph.h -- header for graph.c
|
||||||
Copyright (C) 2001-2012 Guus Sliepen <guus@tinc-vpn.org>,
|
Copyright (C) 2001-2012 Guus Sliepen <guus@tinc-vpn.org>,
|
||||||
|
@ -18,10 +21,7 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TINC_GRAPH_H__
|
|
||||||
#define __TINC_GRAPH_H__
|
|
||||||
|
|
||||||
extern void graph(void);
|
extern void graph(void);
|
||||||
extern void dump_graph(void);
|
extern void dump_graph(void);
|
||||||
|
|
||||||
#endif /* __TINC_GRAPH_H__ */
|
#endif
|
||||||
|
|
20
src/have.h
20
src/have.h
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_HAVE_H
|
||||||
|
#define TINC_HAVE_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
have.h -- include headers which are known to exist
|
have.h -- include headers which are known to exist
|
||||||
Copyright (C) 1998-2005 Ivo Timmermans
|
Copyright (C) 1998-2005 Ivo Timmermans
|
||||||
|
@ -18,9 +21,6 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TINC_HAVE_H__
|
|
||||||
#define __TINC_HAVE_H__
|
|
||||||
|
|
||||||
#ifdef HAVE_MINGW
|
#ifdef HAVE_MINGW
|
||||||
#ifdef WITH_WINDOWS2000
|
#ifdef WITH_WINDOWS2000
|
||||||
#define WINVER Windows2000
|
#define WINVER Windows2000
|
||||||
|
@ -30,15 +30,19 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <limits.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#ifdef HAVE_MINGW
|
#ifdef HAVE_MINGW
|
||||||
#include <w32api.h>
|
#include <w32api.h>
|
||||||
|
@ -55,10 +59,6 @@
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_INTTYPES_H
|
|
||||||
#include <inttypes.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_ALLOCA_H
|
#ifdef HAVE_ALLOCA_H
|
||||||
#include <alloca.h>
|
#include <alloca.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -211,4 +211,4 @@
|
||||||
#include <linux/if_tun.h>
|
#include <linux/if_tun.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __TINC_SYSTEM_H__ */
|
#endif
|
||||||
|
|
10
src/ipv4.h
10
src/ipv4.h
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_IPV4_H
|
||||||
|
#define TINC_IPV4_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ipv4.h -- missing IPv4 related definitions
|
ipv4.h -- missing IPv4 related definitions
|
||||||
Copyright (C) 2005 Ivo Timmermans
|
Copyright (C) 2005 Ivo Timmermans
|
||||||
|
@ -18,9 +21,6 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TINC_IPV4_H__
|
|
||||||
#define __TINC_IPV4_H__
|
|
||||||
|
|
||||||
#ifndef AF_INET
|
#ifndef AF_INET
|
||||||
#define AF_INET 2
|
#define AF_INET 2
|
||||||
#endif
|
#endif
|
||||||
|
@ -63,7 +63,7 @@
|
||||||
|
|
||||||
#ifndef HAVE_STRUCT_IP
|
#ifndef HAVE_STRUCT_IP
|
||||||
struct ip {
|
struct ip {
|
||||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||||
unsigned int ip_hl: 4;
|
unsigned int ip_hl: 4;
|
||||||
unsigned int ip_v: 4;
|
unsigned int ip_v: 4;
|
||||||
#else
|
#else
|
||||||
|
@ -146,4 +146,4 @@ struct icmp {
|
||||||
} __attribute__((__packed__));
|
} __attribute__((__packed__));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __TINC_IPV4_H__ */
|
#endif
|
||||||
|
|
14
src/ipv6.h
14
src/ipv6.h
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_IPV6_H
|
||||||
|
#define TINC_IPV6_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ipv6.h -- missing IPv6 related definitions
|
ipv6.h -- missing IPv6 related definitions
|
||||||
Copyright (C) 2005 Ivo Timmermans
|
Copyright (C) 2005 Ivo Timmermans
|
||||||
|
@ -18,9 +21,6 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TINC_IPV6_H__
|
|
||||||
#define __TINC_IPV6_H__
|
|
||||||
|
|
||||||
#ifndef AF_INET6
|
#ifndef AF_INET6
|
||||||
#define AF_INET6 10
|
#define AF_INET6 10
|
||||||
#endif
|
#endif
|
||||||
|
@ -54,9 +54,9 @@ struct sockaddr_in6 {
|
||||||
|
|
||||||
#ifndef IN6_IS_ADDR_V4MAPPED
|
#ifndef IN6_IS_ADDR_V4MAPPED
|
||||||
#define IN6_IS_ADDR_V4MAPPED(a) \
|
#define IN6_IS_ADDR_V4MAPPED(a) \
|
||||||
((((__const uint32_t *) (a))[0] == 0) \
|
((((const uint32_t *) (a))[0] == 0) \
|
||||||
&& (((__const uint32_t *) (a))[1] == 0) \
|
&& (((const uint32_t *) (a))[1] == 0) \
|
||||||
&& (((__const uint32_t *) (a))[2] == htonl (0xffff)))
|
&& (((const uint32_t *) (a))[2] == htonl (0xffff)))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_STRUCT_IP6_HDR
|
#ifndef HAVE_STRUCT_IP6_HDR
|
||||||
|
@ -127,4 +127,4 @@ struct nd_opt_hdr {
|
||||||
} __attribute__((__packed__));
|
} __attribute__((__packed__));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __TINC_IPV6_H__ */
|
#endif
|
||||||
|
|
|
@ -47,7 +47,7 @@ char *device = NULL;
|
||||||
char *iface = NULL;
|
char *iface = NULL;
|
||||||
static char *type = NULL;
|
static char *type = NULL;
|
||||||
static char ifrname[IFNAMSIZ];
|
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_in = 0;
|
||||||
static uint64_t device_total_out = 0;
|
static uint64_t device_total_out = 0;
|
||||||
|
@ -56,13 +56,16 @@ static bool setup_device(void) {
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
bool t1q = false;
|
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);
|
device = xstrdup(DEFAULT_DEVICE);
|
||||||
|
}
|
||||||
|
|
||||||
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
|
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
|
||||||
#ifdef HAVE_LINUX_IF_TUN_H
|
#ifdef HAVE_LINUX_IF_TUN_H
|
||||||
if (netname != NULL)
|
if(netname != NULL) {
|
||||||
iface = xstrdup(netname);
|
iface = xstrdup(netname);
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
iface = xstrdup(strrchr(device, '/') ? strrchr(device, '/') + 1 : device);
|
iface = xstrdup(strrchr(device, '/') ? strrchr(device, '/') + 1 : device);
|
||||||
#endif
|
#endif
|
||||||
|
@ -94,17 +97,22 @@ static bool setup_device(void) {
|
||||||
device_type = DEVICE_TYPE_TUN;
|
device_type = DEVICE_TYPE_TUN;
|
||||||
device_info = "Linux tun/tap device (tun mode)";
|
device_info = "Linux tun/tap device (tun mode)";
|
||||||
} else {
|
} else {
|
||||||
if (routing_mode == RMODE_ROUTER)
|
if(routing_mode == RMODE_ROUTER) {
|
||||||
overwrite_mac = true;
|
overwrite_mac = true;
|
||||||
|
}
|
||||||
|
|
||||||
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
|
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
|
||||||
device_type = DEVICE_TYPE_TAP;
|
device_type = DEVICE_TYPE_TAP;
|
||||||
device_info = "Linux tun/tap device (tap mode)";
|
device_info = "Linux tun/tap device (tap mode)";
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef IFF_ONE_QUEUE
|
#ifdef IFF_ONE_QUEUE
|
||||||
|
|
||||||
/* Set IFF_ONE_QUEUE flag... */
|
/* 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;
|
ifr.ifr_flags |= IFF_ONE_QUEUE;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(iface) {
|
if(iface) {
|
||||||
|
@ -117,6 +125,9 @@ static bool setup_device(void) {
|
||||||
ifrname[IFNAMSIZ - 1] = 0;
|
ifrname[IFNAMSIZ - 1] = 0;
|
||||||
free(iface);
|
free(iface);
|
||||||
iface = xstrdup(ifrname);
|
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)) {
|
} else if(!ioctl(device_fd, (('T' << 8) | 202), &ifr)) {
|
||||||
logger(LOG_WARNING, "Old ioctl() request was needed for %s", device);
|
logger(LOG_WARNING, "Old ioctl() request was needed for %s", device);
|
||||||
strncpy(ifrname, ifr.ifr_name, IFNAMSIZ);
|
strncpy(ifrname, ifr.ifr_name, IFNAMSIZ);
|
||||||
|
@ -126,16 +137,19 @@ static bool setup_device(void) {
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if(routing_mode == RMODE_ROUTER)
|
if(routing_mode == RMODE_ROUTER) {
|
||||||
overwrite_mac = true;
|
overwrite_mac = true;
|
||||||
|
}
|
||||||
|
|
||||||
device_info = "Linux ethertap device";
|
device_info = "Linux ethertap device";
|
||||||
device_type = DEVICE_TYPE_ETHERTAP;
|
device_type = DEVICE_TYPE_ETHERTAP;
|
||||||
free(iface);
|
free(iface);
|
||||||
iface = xstrdup(strrchr(device, '/') ? strrchr(device, '/') + 1 : device);
|
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);
|
memcpy(mymac.x, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
|
||||||
|
}
|
||||||
|
|
||||||
logger(LOG_INFO, "%s is a %s", device, device_info);
|
logger(LOG_INFO, "%s is a %s", device, device_info);
|
||||||
|
|
||||||
|
@ -166,6 +180,7 @@ static bool read_packet(vpn_packet_t *packet) {
|
||||||
memset(packet->data, 0, 12);
|
memset(packet->data, 0, 12);
|
||||||
packet->len = lenin + 10;
|
packet->len = lenin + 10;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEVICE_TYPE_TAP:
|
case DEVICE_TYPE_TAP:
|
||||||
lenin = read(device_fd, packet->data, MTU);
|
lenin = read(device_fd, packet->data, MTU);
|
||||||
|
|
||||||
|
@ -177,6 +192,7 @@ static bool read_packet(vpn_packet_t *packet) {
|
||||||
|
|
||||||
packet->len = lenin;
|
packet->len = lenin;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEVICE_TYPE_ETHERTAP:
|
case DEVICE_TYPE_ETHERTAP:
|
||||||
lenin = read(device_fd, packet->data - 2, MTU + 2);
|
lenin = read(device_fd, packet->data - 2, MTU + 2);
|
||||||
|
|
||||||
|
@ -205,19 +221,24 @@ static bool write_packet(vpn_packet_t *packet) {
|
||||||
switch(device_type) {
|
switch(device_type) {
|
||||||
case DEVICE_TYPE_TUN:
|
case DEVICE_TYPE_TUN:
|
||||||
packet->data[10] = packet->data[11] = 0;
|
packet->data[10] = packet->data[11] = 0;
|
||||||
|
|
||||||
if(write(device_fd, packet->data + 10, packet->len - 10) < 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,
|
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEVICE_TYPE_TAP:
|
case DEVICE_TYPE_TAP:
|
||||||
if(write(device_fd, packet->data, packet->len) < 0) {
|
if(write(device_fd, packet->data, packet->len) < 0) {
|
||||||
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device,
|
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEVICE_TYPE_ETHERTAP:
|
case DEVICE_TYPE_ETHERTAP:
|
||||||
memcpy(packet->data - 2, &packet->len, 2);
|
memcpy(packet->data - 2, &packet->len, 2);
|
||||||
|
|
||||||
|
@ -226,6 +247,7 @@ static bool write_packet(vpn_packet_t *packet) {
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
37
src/list.c
37
src/list.c
|
@ -43,8 +43,9 @@ list_node_t *list_alloc_node(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void list_free_node(list_t *list, list_node_t *node) {
|
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);
|
list->delete(node->data);
|
||||||
|
}
|
||||||
|
|
||||||
free(node);
|
free(node);
|
||||||
}
|
}
|
||||||
|
@ -61,10 +62,11 @@ list_node_t *list_insert_head(list_t *list, void *data) {
|
||||||
node->next = list->head;
|
node->next = list->head;
|
||||||
list->head = node;
|
list->head = node;
|
||||||
|
|
||||||
if(node->next)
|
if(node->next) {
|
||||||
node->next->prev = node;
|
node->next->prev = node;
|
||||||
else
|
} else {
|
||||||
list->tail = node;
|
list->tail = node;
|
||||||
|
}
|
||||||
|
|
||||||
list->count++;
|
list->count++;
|
||||||
|
|
||||||
|
@ -81,10 +83,11 @@ list_node_t *list_insert_tail(list_t *list, void *data) {
|
||||||
node->prev = list->tail;
|
node->prev = list->tail;
|
||||||
list->tail = node;
|
list->tail = node;
|
||||||
|
|
||||||
if(node->prev)
|
if(node->prev) {
|
||||||
node->prev->next = node;
|
node->prev->next = node;
|
||||||
else
|
} else {
|
||||||
list->head = node;
|
list->head = node;
|
||||||
|
}
|
||||||
|
|
||||||
list->count++;
|
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) {
|
void list_unlink_node(list_t *list, list_node_t *node) {
|
||||||
if(node->prev)
|
if(node->prev) {
|
||||||
node->prev->next = node->next;
|
node->prev->next = node->next;
|
||||||
else
|
} else {
|
||||||
list->head = node->next;
|
list->head = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
if(node->next)
|
if(node->next) {
|
||||||
node->next->prev = node->prev;
|
node->next->prev = node->prev;
|
||||||
else
|
} else {
|
||||||
list->tail = node->prev;
|
list->tail = node->prev;
|
||||||
|
}
|
||||||
|
|
||||||
list->count--;
|
list->count--;
|
||||||
}
|
}
|
||||||
|
@ -121,18 +126,20 @@ void list_delete_tail(list_t *list) {
|
||||||
/* Head/tail lookup */
|
/* Head/tail lookup */
|
||||||
|
|
||||||
void *list_get_head(list_t *list) {
|
void *list_get_head(list_t *list) {
|
||||||
if(list->head)
|
if(list->head) {
|
||||||
return list->head->data;
|
return list->head->data;
|
||||||
else
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void *list_get_tail(list_t *list) {
|
void *list_get_tail(list_t *list) {
|
||||||
if(list->tail)
|
if(list->tail) {
|
||||||
return list->tail->data;
|
return list->tail->data;
|
||||||
else
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Fast list deletion */
|
/* Fast list deletion */
|
||||||
|
|
||||||
|
@ -163,7 +170,9 @@ void list_foreach(list_t *list, list_action_t action) {
|
||||||
|
|
||||||
for(node = list->head; node; node = next) {
|
for(node = list->head; node; node = next) {
|
||||||
next = node->next;
|
next = node->next;
|
||||||
if(node->data)
|
|
||||||
|
if(node->data) {
|
||||||
action(node->data);
|
action(node->data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
34
src/list.h
34
src/list.h
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_LIST_H
|
||||||
|
#define TINC_LIST_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
list.h -- header file for list.c
|
list.h -- header file for list.c
|
||||||
Copyright (C) 2000-2005 Ivo Timmermans
|
Copyright (C) 2000-2005 Ivo Timmermans
|
||||||
|
@ -18,9 +21,6 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TINC_LIST_H__
|
|
||||||
#define __TINC_LIST_H__
|
|
||||||
|
|
||||||
typedef struct list_node_t {
|
typedef struct list_node_t {
|
||||||
struct list_node_t *prev;
|
struct list_node_t *prev;
|
||||||
struct list_node_t *next;
|
struct list_node_t *next;
|
||||||
|
@ -46,33 +46,33 @@ typedef struct list_t {
|
||||||
/* (De)constructors */
|
/* (De)constructors */
|
||||||
|
|
||||||
extern list_t *list_alloc(list_action_t) __attribute__((__malloc__));
|
extern list_t *list_alloc(list_action_t) __attribute__((__malloc__));
|
||||||
extern void list_free(list_t *);
|
extern void list_free(list_t *list);
|
||||||
extern list_node_t *list_alloc_node(void);
|
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 */
|
/* Insertion and deletion */
|
||||||
|
|
||||||
extern list_node_t *list_insert_head(list_t *, void *);
|
extern list_node_t *list_insert_head(list_t *list, void *data);
|
||||||
extern list_node_t *list_insert_tail(list_t *, void *);
|
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_unlink_node(list_t *list, list_node_t *node);
|
||||||
extern void list_delete_node(list_t *, list_node_t *);
|
extern void list_delete_node(list_t *list, list_node_t *node);
|
||||||
|
|
||||||
extern void list_delete_head(list_t *);
|
extern void list_delete_head(list_t *list);
|
||||||
extern void list_delete_tail(list_t *);
|
extern void list_delete_tail(list_t *list);
|
||||||
|
|
||||||
/* Head/tail lookup */
|
/* Head/tail lookup */
|
||||||
|
|
||||||
extern void *list_get_head(list_t *);
|
extern void *list_get_head(list_t *list);
|
||||||
extern void *list_get_tail(list_t *);
|
extern void *list_get_tail(list_t *list);
|
||||||
|
|
||||||
/* Fast list deletion */
|
/* Fast list deletion */
|
||||||
|
|
||||||
extern void list_delete_list(list_t *);
|
extern void list_delete_list(list_t *list);
|
||||||
|
|
||||||
/* Traversing */
|
/* Traversing */
|
||||||
|
|
||||||
extern void list_foreach(list_t *, list_action_t);
|
extern void list_foreach(list_t *list, list_action_t action);
|
||||||
extern void list_foreach_node(list_t *, list_action_node_t);
|
extern void list_foreach_node(list_t *list, list_action_node_t action);
|
||||||
|
|
||||||
#endif /* __TINC_LIST_H__ */
|
#endif
|
||||||
|
|
22
src/logger.c
22
src/logger.c
|
@ -41,21 +41,27 @@ void openlogger(const char *ident, logmode_t mode) {
|
||||||
case LOGMODE_STDERR:
|
case LOGMODE_STDERR:
|
||||||
logpid = getpid();
|
logpid = getpid();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LOGMODE_FILE:
|
case LOGMODE_FILE:
|
||||||
logpid = getpid();
|
logpid = getpid();
|
||||||
logfile = fopen(logfilename, "a");
|
logfile = fopen(logfilename, "a");
|
||||||
|
|
||||||
if(!logfile) {
|
if(!logfile) {
|
||||||
fprintf(stderr, "Could not open log file %s: %s\n", logfilename, strerror(errno));
|
fprintf(stderr, "Could not open log file %s: %s\n", logfilename, strerror(errno));
|
||||||
logmode = LOGMODE_NULL;
|
logmode = LOGMODE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LOGMODE_SYSLOG:
|
case LOGMODE_SYSLOG:
|
||||||
#ifdef HAVE_MINGW
|
#ifdef HAVE_MINGW
|
||||||
loghandle = RegisterEventSource(NULL, logident);
|
loghandle = RegisterEventSource(NULL, logident);
|
||||||
|
|
||||||
if(!loghandle) {
|
if(!loghandle) {
|
||||||
fprintf(stderr, "Could not open log handle!");
|
fprintf(stderr, "Could not open log handle!");
|
||||||
logmode = LOGMODE_NULL;
|
logmode = LOGMODE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
#else
|
#else
|
||||||
#ifdef HAVE_SYSLOG_H
|
#ifdef HAVE_SYSLOG_H
|
||||||
|
@ -63,21 +69,25 @@ void openlogger(const char *ident, logmode_t mode) {
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case LOGMODE_NULL:
|
case LOGMODE_NULL:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void reopenlogger() {
|
void reopenlogger() {
|
||||||
if(logmode != LOGMODE_FILE)
|
if(logmode != LOGMODE_FILE) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fflush(logfile);
|
fflush(logfile);
|
||||||
FILE *newfile = fopen(logfilename, "a");
|
FILE *newfile = fopen(logfilename, "a");
|
||||||
|
|
||||||
if(!newfile) {
|
if(!newfile) {
|
||||||
logger(LOG_ERR, "Unable to reopen log file %s: %s", logfilename, strerror(errno));
|
logger(LOG_ERR, "Unable to reopen log file %s: %s", logfilename, strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(logfile);
|
fclose(logfile);
|
||||||
logfile = newfile;
|
logfile = newfile;
|
||||||
}
|
}
|
||||||
|
@ -95,23 +105,26 @@ void logger(int priority, const char *format, ...) {
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LOGMODE_FILE:
|
case LOGMODE_FILE:
|
||||||
now = time(NULL);
|
now = time(NULL);
|
||||||
strftime(timestr, sizeof timestr, "%Y-%m-%d %H:%M:%S", localtime(&now));
|
strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", localtime(&now));
|
||||||
fprintf(logfile, "%s %s[%ld]: ", timestr, logident, (long)logpid);
|
fprintf(logfile, "%s %s[%ld]: ", timestr, logident, (long)logpid);
|
||||||
vfprintf(logfile, format, ap);
|
vfprintf(logfile, format, ap);
|
||||||
fprintf(logfile, "\n");
|
fprintf(logfile, "\n");
|
||||||
fflush(logfile);
|
fflush(logfile);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LOGMODE_SYSLOG:
|
case LOGMODE_SYSLOG:
|
||||||
#ifdef HAVE_MINGW
|
#ifdef HAVE_MINGW
|
||||||
{
|
{
|
||||||
char message[4096];
|
char message[4096];
|
||||||
const char *messages[] = {message};
|
const char *messages[] = {message};
|
||||||
vsnprintf(message, sizeof(message), format, ap);
|
vsnprintf(message, sizeof(message), format, ap);
|
||||||
message[sizeof message - 1] = 0;
|
message[sizeof(message) - 1] = 0;
|
||||||
ReportEvent(loghandle, priority, 0, 0, NULL, 1, 0, messages, NULL);
|
ReportEvent(loghandle, priority, 0, 0, NULL, 1, 0, messages, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#ifdef HAVE_SYSLOG_H
|
#ifdef HAVE_SYSLOG_H
|
||||||
#ifdef HAVE_VSYSLOG
|
#ifdef HAVE_VSYSLOG
|
||||||
|
@ -126,6 +139,7 @@ void logger(int priority, const char *format, ...) {
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case LOGMODE_NULL:
|
case LOGMODE_NULL:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -138,6 +152,7 @@ void closelogger(void) {
|
||||||
case LOGMODE_FILE:
|
case LOGMODE_FILE:
|
||||||
fclose(logfile);
|
fclose(logfile);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LOGMODE_SYSLOG:
|
case LOGMODE_SYSLOG:
|
||||||
#ifdef HAVE_MINGW
|
#ifdef HAVE_MINGW
|
||||||
DeregisterEventSource(loghandle);
|
DeregisterEventSource(loghandle);
|
||||||
|
@ -148,6 +163,7 @@ void closelogger(void) {
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case LOGMODE_NULL:
|
case LOGMODE_NULL:
|
||||||
case LOGMODE_STDERR:
|
case LOGMODE_STDERR:
|
||||||
break;
|
break;
|
||||||
|
|
31
src/logger.h
31
src/logger.h
|
@ -1,5 +1,24 @@
|
||||||
#ifndef __TINC_LOGGER_H__
|
#ifndef TINC_LOGGER_H
|
||||||
#define __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 {
|
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 */
|
||||||
|
@ -11,7 +30,7 @@ typedef enum debug_t {
|
||||||
DEBUG_META = 4, /* Show contents of every request that is sent/received */
|
DEBUG_META = 4, /* Show contents of every request that is sent/received */
|
||||||
DEBUG_TRAFFIC = 5, /* Show network traffic information */
|
DEBUG_TRAFFIC = 5, /* Show network traffic information */
|
||||||
DEBUG_PACKET = 6, /* Show contents of each packet that is being sent/received */
|
DEBUG_PACKET = 6, /* Show contents of each packet that is being sent/received */
|
||||||
DEBUG_SCARY_THINGS = 10 /* You have been warned */
|
DEBUG_SCARY_THINGS = 10, /* You have been warned */
|
||||||
} debug_t;
|
} debug_t;
|
||||||
|
|
||||||
typedef enum logmode_t {
|
typedef enum logmode_t {
|
||||||
|
@ -46,11 +65,11 @@ enum {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern debug_t debug_level;
|
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 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);
|
extern void closelogger(void);
|
||||||
|
|
||||||
#define ifdebug(l) if(debug_level >= DEBUG_##l)
|
#define ifdebug(l) if(debug_level >= DEBUG_##l)
|
||||||
|
|
||||||
#endif /* __TINC_LOGGER_H__ */
|
#endif
|
||||||
|
|
35
src/meta.c
35
src/meta.c
|
@ -38,16 +38,12 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
|
||||||
int outlen;
|
int outlen;
|
||||||
int result;
|
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,
|
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;
|
c->last_flushed_time = now;
|
||||||
|
}
|
||||||
|
|
||||||
/* Find room in connection's buffer */
|
/* Find room in connection's buffer */
|
||||||
if(length + c->outbuflen > c->outbufsize) {
|
if(length + c->outbuflen > c->outbufsize) {
|
||||||
|
@ -63,7 +59,7 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
|
||||||
/* Add our data to buffer */
|
/* Add our data to buffer */
|
||||||
if(c->status.encryptout) {
|
if(c->status.encryptout) {
|
||||||
/* Check encryption limits */
|
/* Check encryption limits */
|
||||||
if(length > c->outbudget) {
|
if((uint64_t)length > c->outbudget) {
|
||||||
ifdebug(META) logger(LOG_ERR, "Byte limit exceeded for encryption to %s (%s)", c->name, c->hostname);
|
ifdebug(META) logger(LOG_ERR, "Byte limit exceeded for encryption to %s (%s)", c->name, c->hostname);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -72,6 +68,7 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
|
||||||
|
|
||||||
result = EVP_EncryptUpdate(c->outctx, (unsigned char *)c->outbuf + c->outbufstart + c->outbuflen,
|
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) {
|
if(!result || outlen < length) {
|
||||||
logger(LOG_ERR, "Error while encrypting metadata to %s (%s): %s",
|
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));
|
||||||
|
@ -80,6 +77,7 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
|
||||||
logger(LOG_EMERG, "Encrypted data too long! Heap corrupted!");
|
logger(LOG_EMERG, "Encrypted data too long! Heap corrupted!");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
c->outbuflen += outlen;
|
c->outbuflen += outlen;
|
||||||
} else {
|
} else {
|
||||||
memcpy(c->outbuf + c->outbufstart + c->outbuflen, buffer, length);
|
memcpy(c->outbuf + c->outbufstart + c->outbuflen, buffer, length);
|
||||||
|
@ -97,6 +95,7 @@ bool flush_meta(connection_t *c) {
|
||||||
|
|
||||||
while(c->outbuflen) {
|
while(c->outbuflen) {
|
||||||
result = send(c->socket, c->outbuf + c->outbufstart, c->outbuflen, 0);
|
result = send(c->socket, c->outbuf + c->outbufstart, c->outbuflen, 0);
|
||||||
|
|
||||||
if(result <= 0) {
|
if(result <= 0) {
|
||||||
if(!errno || errno == EPIPE) {
|
if(!errno || errno == EPIPE) {
|
||||||
ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Connection closed by %s (%s)",
|
ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Connection closed by %s (%s)",
|
||||||
|
@ -130,10 +129,11 @@ void broadcast_meta(connection_t *from, const char *buffer, int length) {
|
||||||
for(node = connection_tree->head; node; node = node->next) {
|
for(node = connection_tree->head; node; node = node->next) {
|
||||||
c = node->data;
|
c = node->data;
|
||||||
|
|
||||||
if(c != from && c->status.active)
|
if(c != from && c->status.active) {
|
||||||
send_meta(c, buffer, length);
|
send_meta(c, buffer, length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool receive_meta(connection_t *c) {
|
bool receive_meta(connection_t *c) {
|
||||||
int oldlen, i, result;
|
int oldlen, i, result;
|
||||||
|
@ -156,9 +156,9 @@ bool receive_meta(connection_t *c) {
|
||||||
if(!lenin || !errno) {
|
if(!lenin || !errno) {
|
||||||
ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Connection closed by %s (%s)",
|
ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Connection closed by %s (%s)",
|
||||||
c->name, c->hostname);
|
c->name, c->hostname);
|
||||||
} else if(sockwouldblock(sockerrno))
|
} else if(sockwouldblock(sockerrno)) {
|
||||||
return true;
|
return true;
|
||||||
else
|
} else
|
||||||
logger(LOG_ERR, "Metadata socket read error for %s (%s): %s",
|
logger(LOG_ERR, "Metadata socket read error for %s (%s): %s",
|
||||||
c->name, c->hostname, sockstrerror(sockerrno));
|
c->name, c->hostname, sockstrerror(sockerrno));
|
||||||
|
|
||||||
|
@ -174,9 +174,12 @@ bool receive_meta(connection_t *c) {
|
||||||
/* Is it proxy metadata? */
|
/* Is it proxy metadata? */
|
||||||
|
|
||||||
if(c->allow_request == PROXY) {
|
if(c->allow_request == PROXY) {
|
||||||
reqlen = receive_proxy_meta(c, oldlen, lenin);
|
reqlen = receive_proxy_meta(c);
|
||||||
if(reqlen < 0)
|
|
||||||
|
if(reqlen < 0) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
goto consume;
|
goto consume;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +187,7 @@ bool receive_meta(connection_t *c) {
|
||||||
|
|
||||||
if(c->status.decryptin && !decrypted) {
|
if(c->status.decryptin && !decrypted) {
|
||||||
/* Check decryption limits */
|
/* Check decryption limits */
|
||||||
if(lenin > c->inbudget) {
|
if((uint64_t)lenin > c->inbudget) {
|
||||||
ifdebug(META) logger(LOG_ERR, "Byte limit exceeded for decryption from %s (%s)", c->name, c->hostname);
|
ifdebug(META) logger(LOG_ERR, "Byte limit exceeded for decryption from %s (%s)", c->name, c->hostname);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -192,11 +195,13 @@ bool receive_meta(connection_t *c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
result = EVP_DecryptUpdate(c->inctx, (unsigned char *)inbuf, &lenout, (unsigned char *)c->buffer + oldlen, lenin);
|
result = EVP_DecryptUpdate(c->inctx, (unsigned char *)inbuf, &lenout, (unsigned char *)c->buffer + oldlen, lenin);
|
||||||
|
|
||||||
if(!result || lenout != lenin) {
|
if(!result || lenout != lenin) {
|
||||||
logger(LOG_ERR, "Error while decrypting metadata from %s (%s): %s",
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(c->buffer + oldlen, inbuf, lenin);
|
memcpy(c->buffer + oldlen, inbuf, lenin);
|
||||||
decrypted = true;
|
decrypted = true;
|
||||||
}
|
}
|
||||||
|
@ -225,11 +230,13 @@ bool receive_meta(connection_t *c) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(reqlen && !receive_request(c))
|
if(reqlen && !receive_request(c)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
consume:
|
consume:
|
||||||
|
|
||||||
if(reqlen) {
|
if(reqlen) {
|
||||||
c->buflen -= reqlen;
|
c->buflen -= reqlen;
|
||||||
lenin -= reqlen - oldlen;
|
lenin -= reqlen - oldlen;
|
||||||
|
|
16
src/meta.h
16
src/meta.h
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_META_H
|
||||||
|
#define TINC_META_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
meta.h -- header for meta.c
|
meta.h -- header for meta.c
|
||||||
Copyright (C) 2000-2006 Guus Sliepen <guus@tinc-vpn.org>,
|
Copyright (C) 2000-2006 Guus Sliepen <guus@tinc-vpn.org>,
|
||||||
|
@ -18,14 +21,11 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TINC_META_H__
|
|
||||||
#define __TINC_META_H__
|
|
||||||
|
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
|
||||||
extern bool send_meta(struct connection_t *, const char *, int);
|
extern bool send_meta(struct connection_t *c, const char *buffer, int length);
|
||||||
extern void broadcast_meta(struct connection_t *, const char *, int);
|
extern void broadcast_meta(struct connection_t *c, const char *buffer, int length);
|
||||||
extern bool flush_meta(struct connection_t *);
|
extern bool flush_meta(struct connection_t *c);
|
||||||
extern bool receive_meta(struct connection_t *);
|
extern bool receive_meta(struct connection_t *c);
|
||||||
|
|
||||||
#endif /* __TINC_META_H__ */
|
#endif
|
||||||
|
|
|
@ -37,7 +37,7 @@ int device_fd = -1;
|
||||||
static HANDLE device_handle = INVALID_HANDLE_VALUE;
|
static HANDLE device_handle = INVALID_HANDLE_VALUE;
|
||||||
char *device = NULL;
|
char *device = NULL;
|
||||||
char *iface = 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_in = 0;
|
||||||
static uint64_t device_total_out = 0;
|
static uint64_t device_total_out = 0;
|
||||||
|
@ -66,17 +66,21 @@ static DWORD WINAPI tapreader(void *bla) {
|
||||||
if(!status) {
|
if(!status) {
|
||||||
if(GetLastError() == ERROR_IO_PENDING) {
|
if(GetLastError() == ERROR_IO_PENDING) {
|
||||||
WaitForSingleObject(r_overlapped.hEvent, INFINITE);
|
WaitForSingleObject(r_overlapped.hEvent, INFINITE);
|
||||||
if(!GetOverlappedResult(device_handle, &r_overlapped, &len, FALSE))
|
|
||||||
|
if(!GetOverlappedResult(device_handle, &r_overlapped, &len, FALSE)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info,
|
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info,
|
||||||
device, strerror(errno));
|
device, strerror(errno));
|
||||||
errors++;
|
errors++;
|
||||||
|
|
||||||
if(errors >= 10) {
|
if(errors >= 10) {
|
||||||
EnterCriticalSection(&mutex);
|
EnterCriticalSection(&mutex);
|
||||||
running = false;
|
running = false;
|
||||||
LeaveCriticalSection(&mutex);
|
LeaveCriticalSection(&mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
usleep(1000000);
|
usleep(1000000);
|
||||||
continue;
|
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, "Device"), &device);
|
||||||
get_config_string(lookup_config(config_tree, "Interface"), &iface);
|
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");
|
logger(LOG_WARNING, "Warning: both Device and Interface specified, results may not be as expected");
|
||||||
|
}
|
||||||
|
|
||||||
/* Open registry and look for network adapters */
|
/* Open registry and look for network adapters */
|
||||||
|
|
||||||
|
@ -125,42 +130,49 @@ static bool setup_device(void) {
|
||||||
|
|
||||||
for(i = 0; ; i++) {
|
for(i = 0; ; i++) {
|
||||||
len = sizeof(adapterid);
|
len = sizeof(adapterid);
|
||||||
if(RegEnumKeyEx(key, i, adapterid, &len, 0, 0, 0, NULL))
|
|
||||||
|
if(RegEnumKeyEx(key, i, adapterid, &len, 0, 0, 0, NULL)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Find out more about this adapter */
|
/* Find out more about this adapter */
|
||||||
|
|
||||||
snprintf(regpath, sizeof(regpath), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapterid);
|
snprintf(regpath, sizeof(regpath), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapterid);
|
||||||
|
|
||||||
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2))
|
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
len = sizeof(adaptername);
|
len = sizeof(adaptername);
|
||||||
err = RegQueryValueEx(key2, "Name", 0, 0, (LPBYTE)adaptername, &len);
|
err = RegQueryValueEx(key2, "Name", 0, 0, (LPBYTE)adaptername, &len);
|
||||||
|
|
||||||
RegCloseKey(key2);
|
RegCloseKey(key2);
|
||||||
|
|
||||||
if(err)
|
if(err) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(device) {
|
if(device) {
|
||||||
if(!strcmp(device, adapterid)) {
|
if(!strcmp(device, adapterid)) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
} else
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(iface) {
|
if(iface) {
|
||||||
if(!strcmp(iface, adaptername)) {
|
if(!strcmp(iface, adaptername)) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
} else
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
|
snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
|
||||||
device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
|
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) {
|
if(device_handle != INVALID_HANDLE_VALUE) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
|
@ -174,11 +186,13 @@ static bool setup_device(void) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!device)
|
if(!device) {
|
||||||
device = xstrdup(adapterid);
|
device = xstrdup(adapterid);
|
||||||
|
}
|
||||||
|
|
||||||
if(!iface)
|
if(!iface) {
|
||||||
iface = xstrdup(adaptername);
|
iface = xstrdup(adaptername);
|
||||||
|
}
|
||||||
|
|
||||||
/* Try to open the corresponding tap device */
|
/* Try to open the corresponding tap device */
|
||||||
|
|
||||||
|
@ -222,8 +236,6 @@ static bool setup_device(void) {
|
||||||
status = true;
|
status = true;
|
||||||
DeviceIoControl(device_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, sizeof(status), &status, sizeof(status), &len, NULL);
|
DeviceIoControl(device_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, sizeof(status), &status, sizeof(status), &len, NULL);
|
||||||
|
|
||||||
device_info = "Windows tap device";
|
|
||||||
|
|
||||||
logger(LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
|
logger(LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -252,11 +264,13 @@ static bool write_packet(vpn_packet_t *packet) {
|
||||||
if(queue.len) {
|
if(queue.len) {
|
||||||
DWORD size;
|
DWORD size;
|
||||||
BOOL success = GetOverlappedResult(device_handle, &w_overlapped, &size, FALSE);
|
BOOL success = GetOverlappedResult(device_handle, &w_overlapped, &size, FALSE);
|
||||||
|
|
||||||
if(success) {
|
if(success) {
|
||||||
ResetEvent(&w_overlapped);
|
ResetEvent(&w_overlapped);
|
||||||
queue.len = 0;
|
queue.len = 0;
|
||||||
} else {
|
} else {
|
||||||
int err = GetLastError();
|
int err = GetLastError();
|
||||||
|
|
||||||
if(err != ERROR_IO_INCOMPLETE) {
|
if(err != ERROR_IO_INCOMPLETE) {
|
||||||
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Error completing previously queued write: %s", winerror(err));
|
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Error completing previously queued write: %s", winerror(err));
|
||||||
ResetEvent(&w_overlapped);
|
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)) {
|
if(!WriteFile(device_handle, queue.data, packet->len, &lenout, &w_overlapped)) {
|
||||||
int err = GetLastError();
|
int err = GetLastError();
|
||||||
|
|
||||||
if(err != ERROR_IO_PENDING) {
|
if(err != ERROR_IO_PENDING) {
|
||||||
logger(LOG_ERR, "Error while writing to %s %s: %s", device_info, device, winerror(err));
|
logger(LOG_ERR, "Error while writing to %s %s: %s", device_info, device, winerror(err));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write is being done asynchronously.
|
// Write is being done asynchronously.
|
||||||
queue.len = packet->len;
|
queue.len = packet->len;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
#include "route.h"
|
#include "route.h"
|
||||||
#include "xalloc.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_in = 0;
|
||||||
static uint64_t device_total_out = 0;
|
static uint64_t device_total_out = 0;
|
||||||
|
@ -43,8 +43,6 @@ static bool setup_device(void) {
|
||||||
char *space;
|
char *space;
|
||||||
int ttl = 1;
|
int ttl = 1;
|
||||||
|
|
||||||
device_info = "multicast socket";
|
|
||||||
|
|
||||||
get_config_string(lookup_config(config_tree, "Interface"), &iface);
|
get_config_string(lookup_config(config_tree, "Interface"), &iface);
|
||||||
|
|
||||||
if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
|
if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
|
||||||
|
@ -54,6 +52,7 @@ static bool setup_device(void) {
|
||||||
|
|
||||||
host = xstrdup(device);
|
host = xstrdup(device);
|
||||||
space = strchr(host, ' ');
|
space = strchr(host, ' ');
|
||||||
|
|
||||||
if(!space) {
|
if(!space) {
|
||||||
logger(LOG_ERR, "Port number required for %s", device_info);
|
logger(LOG_ERR, "Port number required for %s", device_info);
|
||||||
free(host);
|
free(host);
|
||||||
|
@ -70,10 +69,14 @@ static bool setup_device(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ai = str2addrinfo(host, port, SOCK_DGRAM);
|
ai = str2addrinfo(host, port, SOCK_DGRAM);
|
||||||
if(!ai)
|
|
||||||
|
if(!ai) {
|
||||||
|
free(host);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
device_fd = socket(ai->ai_family, SOCK_DGRAM, IPPROTO_UDP);
|
device_fd = socket(ai->ai_family, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
|
||||||
if(device_fd < 0) {
|
if(device_fd < 0) {
|
||||||
logger(LOG_ERR, "Creating socket failed: %s", sockstrerror(sockerrno));
|
logger(LOG_ERR, "Creating socket failed: %s", sockstrerror(sockerrno));
|
||||||
free(host);
|
free(host);
|
||||||
|
@ -85,7 +88,7 @@ static bool setup_device(void) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const int one = 1;
|
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)) {
|
if(bind(device_fd, ai->ai_addr, ai->ai_addrlen)) {
|
||||||
closesocket(device_fd);
|
closesocket(device_fd);
|
||||||
|
@ -96,47 +99,55 @@ static bool setup_device(void) {
|
||||||
|
|
||||||
switch(ai->ai_family) {
|
switch(ai->ai_family) {
|
||||||
#ifdef IP_ADD_MEMBERSHIP
|
#ifdef IP_ADD_MEMBERSHIP
|
||||||
|
|
||||||
case AF_INET: {
|
case AF_INET: {
|
||||||
struct ip_mreq mreq;
|
struct ip_mreq mreq;
|
||||||
struct sockaddr_in in;
|
struct sockaddr_in in;
|
||||||
memcpy(&in, ai->ai_addr, sizeof in);
|
memcpy(&in, ai->ai_addr, sizeof(in));
|
||||||
mreq.imr_multiaddr.s_addr = in.sin_addr.s_addr;
|
mreq.imr_multiaddr.s_addr = in.sin_addr.s_addr;
|
||||||
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
||||||
if(setsockopt(device_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof mreq)) {
|
|
||||||
|
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));
|
logger(LOG_ERR, "Cannot join multicast group %s %s: %s", host, port, sockstrerror(sockerrno));
|
||||||
closesocket(device_fd);
|
closesocket(device_fd);
|
||||||
free(host);
|
free(host);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef IP_MULTICAST_LOOP
|
#ifdef IP_MULTICAST_LOOP
|
||||||
setsockopt(device_fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const void *)&one, sizeof one);
|
setsockopt(device_fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const void *)&one, sizeof(one));
|
||||||
#endif
|
#endif
|
||||||
#ifdef IP_MULTICAST_TTL
|
#ifdef IP_MULTICAST_TTL
|
||||||
setsockopt(device_fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&ttl, sizeof ttl);
|
setsockopt(device_fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&ttl, sizeof(ttl));
|
||||||
#endif
|
#endif
|
||||||
} break;
|
}
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef IPV6_JOIN_GROUP
|
#ifdef IPV6_JOIN_GROUP
|
||||||
|
|
||||||
case AF_INET6: {
|
case AF_INET6: {
|
||||||
struct ipv6_mreq mreq;
|
struct ipv6_mreq mreq;
|
||||||
struct sockaddr_in6 in6;
|
struct sockaddr_in6 in6;
|
||||||
memcpy(&in6, ai->ai_addr, sizeof in6);
|
memcpy(&in6, ai->ai_addr, sizeof(in6));
|
||||||
memcpy(&mreq.ipv6mr_multiaddr, &in6.sin6_addr, sizeof mreq.ipv6mr_multiaddr);
|
memcpy(&mreq.ipv6mr_multiaddr, &in6.sin6_addr, sizeof(mreq.ipv6mr_multiaddr));
|
||||||
mreq.ipv6mr_interface = in6.sin6_scope_id;
|
mreq.ipv6mr_interface = in6.sin6_scope_id;
|
||||||
if(setsockopt(device_fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, (void *)&mreq, sizeof mreq)) {
|
|
||||||
|
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));
|
logger(LOG_ERR, "Cannot join multicast group %s %s: %s", host, port, sockstrerror(sockerrno));
|
||||||
closesocket(device_fd);
|
closesocket(device_fd);
|
||||||
free(host);
|
free(host);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef IPV6_MULTICAST_LOOP
|
#ifdef IPV6_MULTICAST_LOOP
|
||||||
setsockopt(device_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (const void *)&one, sizeof one);
|
setsockopt(device_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (const void *)&one, sizeof(one));
|
||||||
#endif
|
#endif
|
||||||
#ifdef IPV6_MULTICAST_HOPS
|
#ifdef IPV6_MULTICAST_HOPS
|
||||||
setsockopt(device_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (void *)&ttl, sizeof ttl);
|
setsockopt(device_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (void *)&ttl, sizeof(ttl));
|
||||||
#endif
|
#endif
|
||||||
} break;
|
}
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -158,9 +169,10 @@ static void close_device(void) {
|
||||||
free(device);
|
free(device);
|
||||||
free(iface);
|
free(iface);
|
||||||
|
|
||||||
if(ai)
|
if(ai) {
|
||||||
freeaddrinfo(ai);
|
freeaddrinfo(ai);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool read_packet(vpn_packet_t *packet) {
|
static bool read_packet(vpn_packet_t *packet) {
|
||||||
int lenin;
|
int lenin;
|
||||||
|
@ -171,7 +183,7 @@ static bool read_packet(vpn_packet_t *packet) {
|
||||||
return false;
|
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);
|
ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Ignoring loopback packet of %d bytes from %s", lenin, device_info);
|
||||||
packet->len = 0;
|
packet->len = 0;
|
||||||
return true;
|
return true;
|
||||||
|
@ -199,7 +211,7 @@ static bool write_packet(vpn_packet_t *packet) {
|
||||||
|
|
||||||
device_total_out += packet->len;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
139
src/net.c
139
src/net.c
|
@ -76,15 +76,20 @@ static void purge(void) {
|
||||||
snext = snode->next;
|
snext = snode->next;
|
||||||
s = snode->data;
|
s = snode->data;
|
||||||
send_del_subnet(everyone, s);
|
send_del_subnet(everyone, s);
|
||||||
if(!strictsubnets)
|
|
||||||
|
if(!strictsubnets) {
|
||||||
subnet_del(n, s);
|
subnet_del(n, s);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(enode = n->edge_tree->head; enode; enode = enext) {
|
for(enode = n->edge_tree->head; enode; enode = enext) {
|
||||||
enext = enode->next;
|
enext = enode->next;
|
||||||
e = enode->data;
|
e = enode->data;
|
||||||
if(!tunnelserver)
|
|
||||||
|
if(!tunnelserver) {
|
||||||
send_del_edge(everyone, e);
|
send_del_edge(everyone, e);
|
||||||
|
}
|
||||||
|
|
||||||
edge_del(e);
|
edge_del(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,16 +106,19 @@ static void purge(void) {
|
||||||
enext = enode->next;
|
enext = enode->next;
|
||||||
e = enode->data;
|
e = enode->data;
|
||||||
|
|
||||||
if(e->to == n)
|
if(e->to == n) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!enode && (!strictsubnets || !n->subnet_tree->head))
|
if(!enode && (!strictsubnets || !n->subnet_tree->head))
|
||||||
/* in strictsubnets mode do not delete nodes with subnets */
|
/* in strictsubnets mode do not delete nodes with subnets */
|
||||||
|
{
|
||||||
node_del(n);
|
node_del(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
put all file descriptors in an fd_set array
|
put all file descriptors in an fd_set array
|
||||||
|
@ -130,30 +138,44 @@ static int build_fdset(fd_set *readset, fd_set *writeset) {
|
||||||
|
|
||||||
if(c->status.remove) {
|
if(c->status.remove) {
|
||||||
connection_del(c);
|
connection_del(c);
|
||||||
if(!connection_tree->head)
|
|
||||||
|
if(!connection_tree->head) {
|
||||||
purge();
|
purge();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
FD_SET(c->socket, readset);
|
FD_SET(c->socket, readset);
|
||||||
if(c->outbuflen > 0 || c->status.connecting)
|
|
||||||
|
if(c->outbuflen > 0 || c->status.connecting) {
|
||||||
FD_SET(c->socket, writeset);
|
FD_SET(c->socket, writeset);
|
||||||
if(c->socket > max)
|
}
|
||||||
|
|
||||||
|
if(c->socket > max) {
|
||||||
max = c->socket;
|
max = c->socket;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(i = 0; i < listen_sockets; i++) {
|
for(i = 0; i < listen_sockets; i++) {
|
||||||
FD_SET(listen_socket[i].tcp, readset);
|
FD_SET(listen_socket[i].tcp, readset);
|
||||||
if(listen_socket[i].tcp > max)
|
|
||||||
|
if(listen_socket[i].tcp > max) {
|
||||||
max = listen_socket[i].tcp;
|
max = listen_socket[i].tcp;
|
||||||
FD_SET(listen_socket[i].udp, readset);
|
|
||||||
if(listen_socket[i].udp > max)
|
|
||||||
max = listen_socket[i].udp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(device_fd >= 0)
|
FD_SET(listen_socket[i].udp, readset);
|
||||||
|
|
||||||
|
if(listen_socket[i].udp > max) {
|
||||||
|
max = listen_socket[i].udp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(device_fd >= 0) {
|
||||||
FD_SET(device_fd, readset);
|
FD_SET(device_fd, readset);
|
||||||
if(device_fd > max)
|
}
|
||||||
|
|
||||||
|
if(device_fd > max) {
|
||||||
max = device_fd;
|
max = device_fd;
|
||||||
|
}
|
||||||
|
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
@ -166,8 +188,9 @@ static int build_fdset(fd_set *readset, fd_set *writeset) {
|
||||||
- Deactivate the host
|
- Deactivate the host
|
||||||
*/
|
*/
|
||||||
void terminate_connection(connection_t *c, bool report) {
|
void terminate_connection(connection_t *c, bool report) {
|
||||||
if(c->status.remove)
|
if(c->status.remove) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Closing connection with %s (%s)",
|
ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Closing connection with %s (%s)",
|
||||||
c->name, c->hostname);
|
c->name, c->hostname);
|
||||||
|
@ -175,11 +198,13 @@ void terminate_connection(connection_t *c, bool report) {
|
||||||
c->status.remove = true;
|
c->status.remove = true;
|
||||||
c->status.active = false;
|
c->status.active = false;
|
||||||
|
|
||||||
if(c->node)
|
if(c->node) {
|
||||||
c->node->connection = NULL;
|
c->node->connection = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if(c->socket)
|
if(c->socket) {
|
||||||
closesocket(c->socket);
|
closesocket(c->socket);
|
||||||
|
}
|
||||||
|
|
||||||
if(c->edge) {
|
if(c->edge) {
|
||||||
if(!c->node) {
|
if(!c->node) {
|
||||||
|
@ -188,8 +213,9 @@ void terminate_connection(connection_t *c, bool report) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(report && !tunnelserver)
|
if(report && !tunnelserver) {
|
||||||
send_del_edge(everyone, c->edge);
|
send_del_edge(everyone, c->edge);
|
||||||
|
}
|
||||||
|
|
||||||
edge_del(c->edge);
|
edge_del(c->edge);
|
||||||
|
|
||||||
|
@ -202,9 +228,12 @@ void terminate_connection(connection_t *c, bool report) {
|
||||||
if(report && !c->node->status.reachable) {
|
if(report && !c->node->status.reachable) {
|
||||||
edge_t *e;
|
edge_t *e;
|
||||||
e = lookup_edge(c->node, myself);
|
e = lookup_edge(c->node, myself);
|
||||||
|
|
||||||
if(e) {
|
if(e) {
|
||||||
if(!tunnelserver)
|
if(!tunnelserver) {
|
||||||
send_del_edge(everyone, e);
|
send_del_edge(everyone, e);
|
||||||
|
}
|
||||||
|
|
||||||
edge_del(e);
|
edge_del(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -223,6 +252,7 @@ void terminate_connection(connection_t *c, bool report) {
|
||||||
/* Clean up dead proxy processes */
|
/* Clean up dead proxy processes */
|
||||||
|
|
||||||
while(waitpid(-1, NULL, WNOHANG) > 0);
|
while(waitpid(-1, NULL, WNOHANG) > 0);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,12 +285,14 @@ static void check_dead_connections(void) {
|
||||||
} else {
|
} else {
|
||||||
if(c->status.remove) {
|
if(c->status.remove) {
|
||||||
logger(LOG_WARNING, "Old connection_t for %s (%s) status %04x still lingering, deleting...",
|
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);
|
connection_del(c);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ifdebug(CONNECTIONS) logger(LOG_WARNING, "Timeout from %s (%s) during authentication",
|
ifdebug(CONNECTIONS) logger(LOG_WARNING, "Timeout from %s (%s) during authentication",
|
||||||
c->name, c->hostname);
|
c->name, c->hostname);
|
||||||
|
|
||||||
if(c->status.connecting) {
|
if(c->status.connecting) {
|
||||||
c->status.connecting = false;
|
c->status.connecting = false;
|
||||||
closesocket(c->socket);
|
closesocket(c->socket);
|
||||||
|
@ -306,6 +338,7 @@ static void check_network_activity(fd_set * readset, fd_set * writeset) {
|
||||||
} else {
|
} else {
|
||||||
usleep(errors * 50000);
|
usleep(errors * 50000);
|
||||||
errors++;
|
errors++;
|
||||||
|
|
||||||
if(errors > 10) {
|
if(errors > 10) {
|
||||||
logger(LOG_ERR, "Too many errors from %s, exiting!", device);
|
logger(LOG_ERR, "Too many errors from %s, exiting!", device);
|
||||||
running = false;
|
running = false;
|
||||||
|
@ -317,17 +350,18 @@ static void check_network_activity(fd_set * readset, fd_set * writeset) {
|
||||||
for(node = connection_tree->head; node; node = node->next) {
|
for(node = connection_tree->head; node; node = node->next) {
|
||||||
c = node->data;
|
c = node->data;
|
||||||
|
|
||||||
if(c->status.remove)
|
if(c->status.remove) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(FD_ISSET(c->socket, writeset)) {
|
if(FD_ISSET(c->socket, writeset)) {
|
||||||
if(c->status.connecting) {
|
if(c->status.connecting) {
|
||||||
c->status.connecting = false;
|
c->status.connecting = false;
|
||||||
getsockopt(c->socket, SOL_SOCKET, SO_ERROR, (void *)&result, &len);
|
getsockopt(c->socket, SOL_SOCKET, SO_ERROR, (void *)&result, &len);
|
||||||
|
|
||||||
if(!result)
|
if(!result) {
|
||||||
finish_connecting(c);
|
finish_connecting(c);
|
||||||
else {
|
} else {
|
||||||
ifdebug(CONNECTIONS) logger(LOG_DEBUG,
|
ifdebug(CONNECTIONS) logger(LOG_DEBUG,
|
||||||
"Error while connecting to %s (%s): %s",
|
"Error while connecting to %s (%s): %s",
|
||||||
c->name, c->hostname, sockstrerror(result));
|
c->name, c->hostname, sockstrerror(result));
|
||||||
|
@ -352,13 +386,15 @@ static void check_network_activity(fd_set * readset, fd_set * writeset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; i < listen_sockets; i++) {
|
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);
|
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);
|
handle_new_meta_connection(listen_socket[i].tcp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
this is where it all happens...
|
this is where it all happens...
|
||||||
|
@ -383,8 +419,11 @@ int main_loop(void) {
|
||||||
srand(now);
|
srand(now);
|
||||||
|
|
||||||
#ifdef HAVE_PSELECT
|
#ifdef HAVE_PSELECT
|
||||||
if(lookup_config(config_tree, "GraphDumpFile"))
|
|
||||||
|
if(lookup_config(config_tree, "GraphDumpFile")) {
|
||||||
graph_dump = true;
|
graph_dump = true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Block SIGHUP & SIGALRM */
|
/* Block SIGHUP & SIGALRM */
|
||||||
sigemptyset(&block_mask);
|
sigemptyset(&block_mask);
|
||||||
sigaddset(&block_mask, SIGHUP);
|
sigaddset(&block_mask, SIGHUP);
|
||||||
|
@ -397,16 +436,21 @@ int main_loop(void) {
|
||||||
while(running) {
|
while(running) {
|
||||||
#ifdef HAVE_PSELECT
|
#ifdef HAVE_PSELECT
|
||||||
next_event = last_ping_check + pingtimeout;
|
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;
|
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;
|
next_event = event->time;
|
||||||
|
}
|
||||||
|
|
||||||
if(next_event <= now)
|
if(next_event <= now) {
|
||||||
tv.tv_sec = 0;
|
tv.tv_sec = 0;
|
||||||
else
|
} else {
|
||||||
tv.tv_sec = next_event - now;
|
tv.tv_sec = next_event - now;
|
||||||
|
}
|
||||||
|
|
||||||
tv.tv_nsec = 0;
|
tv.tv_nsec = 0;
|
||||||
#else
|
#else
|
||||||
tv.tv_sec = 1;
|
tv.tv_sec = 1;
|
||||||
|
@ -436,8 +480,9 @@ int main_loop(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(r > 0)
|
if(r > 0) {
|
||||||
check_network_activity(&readset, &writeset);
|
check_network_activity(&readset, &writeset);
|
||||||
|
}
|
||||||
|
|
||||||
if(do_purge) {
|
if(do_purge) {
|
||||||
purge();
|
purge();
|
||||||
|
@ -450,8 +495,9 @@ int main_loop(void) {
|
||||||
check_dead_connections();
|
check_dead_connections();
|
||||||
last_ping_check = now;
|
last_ping_check = now;
|
||||||
|
|
||||||
if(routing_mode == RMODE_SWITCH)
|
if(routing_mode == RMODE_SWITCH) {
|
||||||
age_subnets();
|
age_subnets();
|
||||||
|
}
|
||||||
|
|
||||||
age_past_requests();
|
age_past_requests();
|
||||||
|
|
||||||
|
@ -465,6 +511,7 @@ int main_loop(void) {
|
||||||
|
|
||||||
for(node = node_tree->head; node; node = node->next) {
|
for(node = node_tree->head; node; node = node->next) {
|
||||||
n = node->data;
|
n = node->data;
|
||||||
|
|
||||||
if(n->inkey) {
|
if(n->inkey) {
|
||||||
free(n->inkey);
|
free(n->inkey);
|
||||||
n->inkey = NULL;
|
n->inkey = NULL;
|
||||||
|
@ -484,13 +531,17 @@ int main_loop(void) {
|
||||||
logger(LOG_WARNING, "Possible node with same Name as us! Sleeping %d seconds.", sleeptime);
|
logger(LOG_WARNING, "Possible node with same Name as us! Sleeping %d seconds.", sleeptime);
|
||||||
usleep(sleeptime * 1000000LL);
|
usleep(sleeptime * 1000000LL);
|
||||||
sleeptime *= 2;
|
sleeptime *= 2;
|
||||||
if(sleeptime < 0)
|
|
||||||
|
if(sleeptime < 0) {
|
||||||
sleeptime = 3600;
|
sleeptime = 3600;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
sleeptime /= 2;
|
sleeptime /= 2;
|
||||||
if(sleeptime < 10)
|
|
||||||
|
if(sleeptime < 10) {
|
||||||
sleeptime = 10;
|
sleeptime = 10;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
contradicting_add_edge = 0;
|
contradicting_add_edge = 0;
|
||||||
contradicting_del_edge = 0;
|
contradicting_del_edge = 0;
|
||||||
|
@ -500,11 +551,15 @@ int main_loop(void) {
|
||||||
avl_node_t *node;
|
avl_node_t *node;
|
||||||
logger(LOG_INFO, "Flushing event queue");
|
logger(LOG_INFO, "Flushing event queue");
|
||||||
expire_events();
|
expire_events();
|
||||||
|
|
||||||
for(node = connection_tree->head; node; node = node->next) {
|
for(node = connection_tree->head; node; node = node->next) {
|
||||||
connection_t *c = node->data;
|
connection_t *c = node->data;
|
||||||
if(c->status.active)
|
|
||||||
|
if(c->status.active) {
|
||||||
send_ping(c);
|
send_ping(c);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sigalrm = false;
|
sigalrm = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,9 +607,10 @@ int main_loop(void) {
|
||||||
for(list_node_t *node = outgoing_list->head; node; node = node->next) {
|
for(list_node_t *node = outgoing_list->head; node; node = node->next) {
|
||||||
outgoing_t *outgoing = node->data;
|
outgoing_t *outgoing = node->data;
|
||||||
|
|
||||||
if(outgoing->event)
|
if(outgoing->event) {
|
||||||
event_del(outgoing->event);
|
event_del(outgoing->event);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
list_delete_list(outgoing_list);
|
list_delete_list(outgoing_list);
|
||||||
|
|
||||||
|
@ -564,8 +620,11 @@ int main_loop(void) {
|
||||||
c = node->data;
|
c = node->data;
|
||||||
|
|
||||||
xasprintf(&fname, "%s/hosts/%s", confbase, c->name);
|
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);
|
terminate_connection(c, c->status.active);
|
||||||
|
}
|
||||||
|
|
||||||
free(fname);
|
free(fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -586,20 +645,26 @@ int main_loop(void) {
|
||||||
for(node = subnet_tree->head; node; node = next) {
|
for(node = subnet_tree->head; node; node = next) {
|
||||||
next = node->next;
|
next = node->next;
|
||||||
subnet = node->data;
|
subnet = node->data;
|
||||||
|
|
||||||
if(subnet->expires == 1) {
|
if(subnet->expires == 1) {
|
||||||
send_del_subnet(everyone, subnet);
|
send_del_subnet(everyone, subnet);
|
||||||
if(subnet->owner->status.reachable)
|
|
||||||
|
if(subnet->owner->status.reachable) {
|
||||||
subnet_update(subnet->owner, subnet, false);
|
subnet_update(subnet->owner, subnet, false);
|
||||||
|
}
|
||||||
|
|
||||||
subnet_del(subnet->owner, subnet);
|
subnet_del(subnet->owner, subnet);
|
||||||
} else if(subnet->expires == -1) {
|
} else if(subnet->expires == -1) {
|
||||||
subnet->expires = 0;
|
subnet->expires = 0;
|
||||||
} else {
|
} else {
|
||||||
send_add_subnet(everyone, subnet);
|
send_add_subnet(everyone, subnet);
|
||||||
if(subnet->owner->status.reachable)
|
|
||||||
|
if(subnet->owner->status.reachable) {
|
||||||
subnet_update(subnet->owner, subnet, true);
|
subnet_update(subnet->owner, subnet, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Try to make outgoing connections */
|
/* Try to make outgoing connections */
|
||||||
|
|
||||||
|
|
40
src/net.h
40
src/net.h
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_NET_H
|
||||||
|
#define TINC_NET_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
net.h -- header for net.c
|
net.h -- header for net.c
|
||||||
Copyright (C) 1998-2005 Ivo Timmermans
|
Copyright (C) 1998-2005 Ivo Timmermans
|
||||||
|
@ -18,9 +21,6 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TINC_NET_H__
|
|
||||||
#define __TINC_NET_H__
|
|
||||||
|
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
#include "ipv6.h"
|
#include "ipv6.h"
|
||||||
|
@ -48,7 +48,7 @@ typedef struct ipv6_t {
|
||||||
uint16_t x[8];
|
uint16_t x[8];
|
||||||
} ipv6_t;
|
} ipv6_t;
|
||||||
|
|
||||||
typedef short length_t;
|
typedef uint16_t length_t;
|
||||||
|
|
||||||
#define AF_UNKNOWN 255
|
#define AF_UNKNOWN 255
|
||||||
|
|
||||||
|
@ -129,26 +129,26 @@ extern volatile bool running;
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
|
|
||||||
extern void retry_outgoing(outgoing_t *);
|
extern void retry_outgoing(outgoing_t *outgoing);
|
||||||
extern void handle_incoming_vpn_data(int);
|
extern void handle_incoming_vpn_data(int sock);
|
||||||
extern void finish_connecting(struct connection_t *);
|
extern void finish_connecting(struct connection_t *c);
|
||||||
extern void do_outgoing_connection(struct connection_t *);
|
extern void do_outgoing_connection(struct connection_t *c);
|
||||||
extern bool handle_new_meta_connection(int);
|
extern bool handle_new_meta_connection(int sock);
|
||||||
extern int setup_listen_socket(const sockaddr_t *);
|
extern int setup_listen_socket(const sockaddr_t *sa);
|
||||||
extern int setup_vpn_in_socket(const sockaddr_t *);
|
extern int setup_vpn_in_socket(const sockaddr_t *sa);
|
||||||
extern void send_packet(const struct node_t *, vpn_packet_t *);
|
extern void send_packet(const struct node_t *n, vpn_packet_t *packet);
|
||||||
extern void receive_tcppacket(struct connection_t *, const char *, int);
|
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 *);
|
extern void broadcast_packet(const struct node_t *, vpn_packet_t *packet);
|
||||||
extern char *get_name(void);
|
extern char *get_name(void);
|
||||||
extern bool setup_network(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 try_outgoing_connections(void);
|
||||||
extern void close_network_connections(void);
|
extern void close_network_connections(void);
|
||||||
extern int main_loop(void);
|
extern int main_loop(void);
|
||||||
extern void terminate_connection(struct connection_t *, bool);
|
extern void terminate_connection(struct connection_t *c, bool report);
|
||||||
extern void flush_queue(struct node_t *);
|
extern void flush_queue(struct node_t *n);
|
||||||
extern bool read_rsa_public_key(struct connection_t *);
|
extern bool read_rsa_public_key(struct connection_t *c);
|
||||||
extern void send_mtu_probe(struct node_t *);
|
extern void send_mtu_probe(struct node_t *n);
|
||||||
extern void load_all_subnets(void);
|
extern void load_all_subnets(void);
|
||||||
|
|
||||||
#ifndef HAVE_MINGW
|
#ifndef HAVE_MINGW
|
||||||
|
@ -157,4 +157,4 @@ extern void load_all_subnets(void);
|
||||||
extern CRITICAL_SECTION mutex;
|
extern CRITICAL_SECTION mutex;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __TINC_NET_H__ */
|
#endif
|
||||||
|
|
188
src/net_packet.c
188
src/net_packet.c
|
@ -114,10 +114,12 @@ void send_mtu_probe(node_t *n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(n->mtuprobes == 30 || (n->mtuprobes < 30 && n->minmtu >= n->maxmtu)) {
|
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;
|
n->minmtu = n->maxmtu;
|
||||||
else
|
} else {
|
||||||
n->maxmtu = n->minmtu;
|
n->maxmtu = n->minmtu;
|
||||||
|
}
|
||||||
|
|
||||||
n->mtu = 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);
|
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;
|
n->mtuprobes = 31;
|
||||||
|
@ -132,8 +134,10 @@ void send_mtu_probe(node_t *n) {
|
||||||
|
|
||||||
for(i = 0; i < 4 + localdiscovery; i++) {
|
for(i = 0; i < 4 + localdiscovery; i++) {
|
||||||
if(i == 0) {
|
if(i == 0) {
|
||||||
if(n->mtuprobes < 30 || n->maxmtu + 8 >= MTU)
|
if(n->mtuprobes < 30 || n->maxmtu + 8 >= MTU) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
len = n->maxmtu + 8;
|
len = n->maxmtu + 8;
|
||||||
} else if(n->maxmtu <= n->minmtu) {
|
} else if(n->maxmtu <= n->minmtu) {
|
||||||
len = n->maxmtu;
|
len = n->maxmtu;
|
||||||
|
@ -141,16 +145,19 @@ void send_mtu_probe(node_t *n) {
|
||||||
len = n->minmtu + 1 + rand() % (n->maxmtu - n->minmtu);
|
len = n->minmtu + 1 + rand() % (n->maxmtu - n->minmtu);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(len < 64)
|
if(len < 64) {
|
||||||
len = 64;
|
len = 64;
|
||||||
|
}
|
||||||
|
|
||||||
memset(packet.data, 0, 14);
|
memset(packet.data, 0, 14);
|
||||||
RAND_bytes(packet.data + 14, len - 14);
|
RAND_bytes(packet.data + 14, len - 14);
|
||||||
packet.len = len;
|
packet.len = len;
|
||||||
if(i >= 4 && n->mtuprobes <= 10)
|
|
||||||
|
if(i >= 4 && n->mtuprobes <= 10) {
|
||||||
packet.priority = -1;
|
packet.priority = -1;
|
||||||
else
|
} else {
|
||||||
packet.priority = 0;
|
packet.priority = 0;
|
||||||
|
}
|
||||||
|
|
||||||
ifdebug(TRAFFIC) logger(LOG_INFO, "Sending MTU probe length %d to %s (%s)", len, n->name, n->hostname);
|
ifdebug(TRAFFIC) logger(LOG_INFO, "Sending MTU probe length %d to %s (%s)", len, n->name, n->hostname);
|
||||||
|
|
||||||
|
@ -180,18 +187,22 @@ void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(n->minmtu)
|
if(n->minmtu) {
|
||||||
n->mtuprobes = 30;
|
n->mtuprobes = 30;
|
||||||
else
|
} else {
|
||||||
n->mtuprobes = 1;
|
n->mtuprobes = 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(len > n->maxmtu)
|
if(len > n->maxmtu) {
|
||||||
len = n->maxmtu;
|
len = n->maxmtu;
|
||||||
if(n->minmtu < len)
|
}
|
||||||
|
|
||||||
|
if(n->minmtu < len) {
|
||||||
n->minmtu = len;
|
n->minmtu = len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static length_t compress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) {
|
static length_t compress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) {
|
||||||
if(level == 0) {
|
if(level == 0) {
|
||||||
|
@ -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);
|
lzo1x_1_compress(source, len, dest, &lzolen, lzo_wrkmem);
|
||||||
return lzolen;
|
return lzolen;
|
||||||
#else
|
#else
|
||||||
return -1;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
} else if(level < 10) {
|
} else if(level < 10) {
|
||||||
#ifdef HAVE_ZLIB
|
#ifdef HAVE_ZLIB
|
||||||
unsigned long destlen = MAXSIZE;
|
unsigned long destlen = MAXSIZE;
|
||||||
if(compress2(dest, &destlen, source, len, level) == Z_OK)
|
|
||||||
|
if(compress2(dest, &destlen, source, len, level) == Z_OK) {
|
||||||
return destlen;
|
return destlen;
|
||||||
else
|
} else
|
||||||
#endif
|
#endif
|
||||||
return -1;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
#ifdef HAVE_LZO
|
#ifdef HAVE_LZO
|
||||||
lzo_uint lzolen = MAXSIZE;
|
lzo_uint lzolen = MAXSIZE;
|
||||||
lzo1x_999_compress(source, len, dest, &lzolen, lzo_wrkmem);
|
lzo1x_999_compress(source, len, dest, &lzolen, lzo_wrkmem);
|
||||||
return lzolen;
|
return lzolen;
|
||||||
#else
|
#else
|
||||||
return -1;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) {
|
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) {
|
} else if(level > 9) {
|
||||||
#ifdef HAVE_LZO
|
#ifdef HAVE_LZO
|
||||||
lzo_uint lzolen = MAXSIZE;
|
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;
|
return lzolen;
|
||||||
else
|
} else
|
||||||
#endif
|
#endif
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_ZLIB
|
#ifdef HAVE_ZLIB
|
||||||
else {
|
else {
|
||||||
unsigned long destlen = MAXSIZE;
|
unsigned long destlen = MAXSIZE;
|
||||||
if(uncompress(dest, &destlen, source, len) == Z_OK)
|
|
||||||
|
if(uncompress(dest, &destlen, source, len) == Z_OK) {
|
||||||
return destlen;
|
return destlen;
|
||||||
else
|
} else {
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -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) {
|
static bool try_mac(const node_t *n, const vpn_packet_t *inpkt) {
|
||||||
unsigned char hmac[EVP_MAX_MD_SIZE];
|
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;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
HMAC(n->indigest, n->inkey, n->inkeylength, (unsigned char *) &inpkt->seqno, inpkt->len - n->inmaclength, (unsigned char *)hmac, NULL);
|
HMAC(n->indigest, n->inkey, n->inkeylength, (unsigned char *) &inpkt->seqno, inpkt->len - n->inmaclength, (unsigned char *)hmac, NULL);
|
||||||
|
|
||||||
|
@ -279,7 +297,6 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
|
||||||
vpn_packet_t *outpkt;
|
vpn_packet_t *outpkt;
|
||||||
int outlen, outpad;
|
int outlen, outpad;
|
||||||
unsigned char hmac[EVP_MAX_MD_SIZE];
|
unsigned char hmac[EVP_MAX_MD_SIZE];
|
||||||
int i;
|
|
||||||
|
|
||||||
if(!n->inkey) {
|
if(!n->inkey) {
|
||||||
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet",
|
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet",
|
||||||
|
@ -340,6 +357,7 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
|
||||||
n->name, n->hostname, inpkt->seqno - n->received_seqno - 1, n->farfuture);
|
n->name, n->hostname, inpkt->seqno - n->received_seqno - 1, n->farfuture);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ifdebug(TRAFFIC) logger(LOG_WARNING, "Lost %d packets from %s (%s)",
|
ifdebug(TRAFFIC) logger(LOG_WARNING, "Lost %d packets from %s (%s)",
|
||||||
inpkt->seqno - n->received_seqno - 1, n->name, n->hostname);
|
inpkt->seqno - n->received_seqno - 1, n->name, n->hostname);
|
||||||
memset(n->late, 0, replaywin);
|
memset(n->late, 0, replaywin);
|
||||||
|
@ -350,20 +368,23 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} 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;
|
n->late[(i / 8) % replaywin] |= 1 << i % 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
n->farfuture = 0;
|
n->farfuture = 0;
|
||||||
n->late[(inpkt->seqno / 8) % replaywin] &= ~(1 << inpkt->seqno % 8);
|
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;
|
n->received_seqno = inpkt->seqno;
|
||||||
|
}
|
||||||
|
|
||||||
if(n->received_seqno > MAX_SEQNO)
|
if(n->received_seqno > MAX_SEQNO) {
|
||||||
keyexpires = 0;
|
keyexpires = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Decompress the packet */
|
/* Decompress the packet */
|
||||||
|
|
||||||
|
@ -372,7 +393,7 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
|
||||||
if(n->incompression) {
|
if(n->incompression) {
|
||||||
outpkt = pkt[nextpkt++];
|
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)",
|
ifdebug(TRAFFIC) logger(LOG_ERR, "Error while uncompressing packet from %s (%s)",
|
||||||
n->name, n->hostname);
|
n->name, n->hostname);
|
||||||
return;
|
return;
|
||||||
|
@ -385,23 +406,28 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
|
||||||
|
|
||||||
inpkt->priority = 0;
|
inpkt->priority = 0;
|
||||||
|
|
||||||
if(!inpkt->data[12] && !inpkt->data[13])
|
if(!inpkt->data[12] && !inpkt->data[13]) {
|
||||||
mtu_probe_h(n, inpkt, origlen);
|
mtu_probe_h(n, inpkt, origlen);
|
||||||
else
|
} else {
|
||||||
receive_packet(n, inpkt);
|
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;
|
vpn_packet_t outpkt;
|
||||||
|
|
||||||
if(len > sizeof outpkt.data)
|
if(len > sizeof(outpkt.data)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
outpkt.len = len;
|
outpkt.len = len;
|
||||||
if(c->options & OPTION_TCPONLY)
|
|
||||||
|
if(c->options & OPTION_TCPONLY) {
|
||||||
outpkt.priority = 0;
|
outpkt.priority = 0;
|
||||||
else
|
} else {
|
||||||
outpkt.priority = -1;
|
outpkt.priority = -1;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(outpkt.data, buffer, len);
|
memcpy(outpkt.data, buffer, len);
|
||||||
|
|
||||||
receive_packet(c->node, &outpkt);
|
receive_packet(c->node, &outpkt);
|
||||||
|
@ -444,10 +470,11 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
|
||||||
"Packet for %s (%s) larger than minimum MTU, forwarding via %s",
|
"Packet for %s (%s) larger than minimum MTU, forwarding via %s",
|
||||||
n->name, n->hostname, n != n->nexthop ? n->nexthop->name : "TCP");
|
n->name, n->hostname, n != n->nexthop ? n->nexthop->name : "TCP");
|
||||||
|
|
||||||
if(n != n->nexthop)
|
if(n != n->nexthop) {
|
||||||
send_packet(n->nexthop, origpkt);
|
send_packet(n->nexthop, origpkt);
|
||||||
else
|
} else {
|
||||||
send_tcppacket(n->nexthop->connection, origpkt);
|
send_tcppacket(n->nexthop->connection, origpkt);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -460,7 +487,7 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
|
||||||
if(n->outcompression) {
|
if(n->outcompression) {
|
||||||
outpkt = pkt[nextpkt++];
|
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)",
|
ifdebug(TRAFFIC) logger(LOG_ERR, "Error while compressing packet to %s (%s)",
|
||||||
n->name, n->hostname);
|
n->name, n->hostname);
|
||||||
return;
|
return;
|
||||||
|
@ -522,7 +549,8 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
|
||||||
|
|
||||||
if(origpriority == -1 && n->prevedge) {
|
if(origpriority == -1 && n->prevedge) {
|
||||||
sock = rand() % listen_sockets;
|
sock = rand() % listen_sockets;
|
||||||
memset(&broadcast, 0, sizeof broadcast);
|
memset(&broadcast, 0, sizeof(broadcast));
|
||||||
|
|
||||||
if(listen_socket[sock].sa.sa.sa_family == AF_INET6) {
|
if(listen_socket[sock].sa.sa.sa_family == AF_INET6) {
|
||||||
broadcast.in6.sin6_family = AF_INET6;
|
broadcast.in6.sin6_family = AF_INET6;
|
||||||
broadcast.in6.sin6_addr.s6_addr[0x0] = 0xff;
|
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_addr.s_addr = -1;
|
||||||
broadcast.in.sin_port = n->prevedge->address.in.sin_port;
|
broadcast.in.sin_port = n->prevedge->address.in.sin_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
sa = &broadcast.sa;
|
sa = &broadcast.sa;
|
||||||
sl = SALEN(broadcast.sa);
|
sl = SALEN(broadcast.sa);
|
||||||
} else {
|
} else {
|
||||||
if(origpriority == -1)
|
if(origpriority == -1) {
|
||||||
origpriority = 0;
|
origpriority = 0;
|
||||||
|
}
|
||||||
|
|
||||||
sa = &(n->address.sa);
|
sa = &(n->address.sa);
|
||||||
sl = SALEN(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) {
|
if(priorityinheritance && origpriority != listen_socket[n->sock].priority) {
|
||||||
listen_socket[n->sock].priority = origpriority;
|
listen_socket[n->sock].priority = origpriority;
|
||||||
|
|
||||||
switch(listen_socket[n->sock].sa.sa.sa_family) {
|
switch(listen_socket[n->sock].sa.sa.sa_family) {
|
||||||
#if defined(SOL_IP) && defined(IP_TOS)
|
#if defined(SOL_IP) && defined(IP_TOS)
|
||||||
|
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Setting IPv4 outgoing packet priority to %d", origpriority);
|
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, SOL_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));
|
logger(LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS)
|
#if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS)
|
||||||
|
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Setting IPv6 outgoing packet priority to %d", origpriority);
|
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));
|
logger(LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -570,13 +610,17 @@ 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(sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, sa, sl) < 0 && !sockwouldblock(sockerrno)) {
|
||||||
if(sockmsgsize(sockerrno)) {
|
if(sockmsgsize(sockerrno)) {
|
||||||
if(n->maxmtu >= origlen)
|
if(n->maxmtu >= origlen) {
|
||||||
n->maxmtu = origlen - 1;
|
n->maxmtu = origlen - 1;
|
||||||
if(n->mtu >= origlen)
|
}
|
||||||
|
|
||||||
|
if(n->mtu >= origlen) {
|
||||||
n->mtu = origlen - 1;
|
n->mtu = origlen - 1;
|
||||||
} else
|
}
|
||||||
|
} else {
|
||||||
ifdebug(TRAFFIC) logger(LOG_WARNING, "Error sending packet to %s (%s): %s", n->name, n->hostname, sockstrerror(sockerrno));
|
ifdebug(TRAFFIC) logger(LOG_WARNING, "Error sending packet to %s (%s): %s", n->name, n->hostname, sockstrerror(sockerrno));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
origpkt->len = origlen;
|
origpkt->len = origlen;
|
||||||
|
@ -589,8 +633,10 @@ void send_packet(const node_t *n, vpn_packet_t *packet) {
|
||||||
node_t *via;
|
node_t *via;
|
||||||
|
|
||||||
if(n == myself) {
|
if(n == myself) {
|
||||||
if(overwrite_mac)
|
if(overwrite_mac) {
|
||||||
memcpy(packet->data, mymac.x, ETH_ALEN);
|
memcpy(packet->data, mymac.x, ETH_ALEN);
|
||||||
|
}
|
||||||
|
|
||||||
devops.write(packet);
|
devops.write(packet);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -611,11 +657,13 @@ void send_packet(const node_t *n, vpn_packet_t *packet) {
|
||||||
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(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);
|
terminate_connection(via->connection, true);
|
||||||
} else
|
}
|
||||||
|
} else {
|
||||||
send_udppacket(via, packet);
|
send_udppacket(via, packet);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Broadcast a packet using the minimum spanning tree */
|
/* Broadcast a packet using the minimum spanning tree */
|
||||||
|
|
||||||
|
@ -625,13 +673,15 @@ void broadcast_packet(const node_t *from, vpn_packet_t *packet) {
|
||||||
node_t *n;
|
node_t *n;
|
||||||
|
|
||||||
// Always give ourself a copy of the packet.
|
// Always give ourself a copy of the packet.
|
||||||
if(from != myself)
|
if(from != myself) {
|
||||||
send_packet(myself, packet);
|
send_packet(myself, packet);
|
||||||
|
}
|
||||||
|
|
||||||
// In TunnelServer mode, do not forward broadcast packets.
|
// In TunnelServer mode, do not forward broadcast packets.
|
||||||
// The MST might not be valid and create loops.
|
// The MST might not be valid and create loops.
|
||||||
if(tunnelserver || broadcast_mode == BMODE_NONE)
|
if(tunnelserver || broadcast_mode == BMODE_NONE) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ifdebug(TRAFFIC) logger(LOG_INFO, "Broadcasting packet of %d bytes from %s (%s)",
|
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);
|
||||||
|
@ -644,24 +694,29 @@ void broadcast_packet(const node_t *from, vpn_packet_t *packet) {
|
||||||
for(node = connection_tree->head; node; node = node->next) {
|
for(node = connection_tree->head; node; node = node->next) {
|
||||||
c = node->data;
|
c = node->data;
|
||||||
|
|
||||||
if(c->status.active && c->status.mst && c != from->nexthop->connection)
|
if(c->status.active && c->status.mst && c != from->nexthop->connection) {
|
||||||
send_packet(c->node, packet);
|
send_packet(c->node, packet);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// In direct mode, we send copies to each node we know of.
|
// 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.
|
// 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.
|
// We don't have enough information to forward broadcast packets in this case.
|
||||||
case BMODE_DIRECT:
|
case BMODE_DIRECT:
|
||||||
if(from != myself)
|
if(from != myself) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
for(node = node_udp_tree->head; node; node = node->next) {
|
for(node = node_udp_tree->head; node; node = node->next) {
|
||||||
n = node->data;
|
n = node->data;
|
||||||
|
|
||||||
if(n->status.reachable && n != myself && ((n->via == myself && n->nexthop == n) || n->via == n))
|
if(n->status.reachable && n != myself && ((n->via == myself && n->nexthop == n) || n->via == n)) {
|
||||||
send_packet(n, packet);
|
send_packet(n, packet);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -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) {
|
for(node = edge_weight_tree->head; node; node = node->next) {
|
||||||
e = node->data;
|
e = node->data;
|
||||||
|
|
||||||
if(e->to == myself)
|
if(e->to == myself) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(last_hard_try == now && sockaddrcmp_noport(from, &e->address))
|
if(last_hard_try == now && sockaddrcmp_noport(from, &e->address)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(!try_mac(e->to, pkt))
|
if(!try_mac(e->to, pkt)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
n = e->to;
|
n = e->to;
|
||||||
break;
|
break;
|
||||||
|
@ -702,31 +760,37 @@ void handle_incoming_vpn_data(int sock) {
|
||||||
socklen_t fromlen = sizeof(from);
|
socklen_t fromlen = sizeof(from);
|
||||||
node_t *n;
|
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(len <= 0 || len > UINT16_MAX) {
|
||||||
if(!sockwouldblock(sockerrno))
|
if(len >= 0) {
|
||||||
|
logger(LOG_ERR, "Receiving packet with invalid size");
|
||||||
|
} else if(!sockwouldblock(sockerrno)) {
|
||||||
logger(LOG_ERR, "Receiving packet failed: %s", sockstrerror(sockerrno));
|
logger(LOG_ERR, "Receiving packet failed: %s", sockstrerror(sockerrno));
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pkt.len = len;
|
||||||
sockaddrunmap(&from); /* Some braindead IPv6 implementations do stupid things. */
|
sockaddrunmap(&from); /* Some braindead IPv6 implementations do stupid things. */
|
||||||
|
|
||||||
n = lookup_node_udp(&from);
|
n = lookup_node_udp(&from);
|
||||||
|
|
||||||
if(!n) {
|
if(!n) {
|
||||||
n = try_harder(&from, &pkt);
|
n = try_harder(&from, &pkt);
|
||||||
if(n)
|
|
||||||
|
if(n) {
|
||||||
update_node_udp(n, &from);
|
update_node_udp(n, &from);
|
||||||
else ifdebug(PROTOCOL) {
|
} else ifdebug(PROTOCOL) {
|
||||||
hostname = sockaddr2hostname(&from);
|
hostname = sockaddr2hostname(&from);
|
||||||
logger(LOG_WARNING, "Received UDP packet from unknown source %s", hostname);
|
logger(LOG_WARNING, "Received UDP packet from unknown source %s", hostname);
|
||||||
free(hostname);
|
free(hostname);
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
n->sock = sock;
|
n->sock = sock;
|
||||||
|
|
||||||
|
|
299
src/net_setup.c
299
src/net_setup.c
|
@ -50,9 +50,12 @@ devops_t devops;
|
||||||
|
|
||||||
#ifndef HAVE_RSA_SET0_KEY
|
#ifndef HAVE_RSA_SET0_KEY
|
||||||
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) {
|
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) {
|
||||||
BN_free(r->n); r->n = n;
|
BN_free(r->n);
|
||||||
BN_free(r->e); r->e = e;
|
r->n = n;
|
||||||
BN_free(r->d); r->d = d;
|
BN_free(r->e);
|
||||||
|
r->e = e;
|
||||||
|
BN_free(r->d);
|
||||||
|
r->d = d;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -73,19 +76,22 @@ bool read_rsa_public_key(connection_t *c) {
|
||||||
/* First, check for simple PublicKey statement */
|
/* First, check for simple PublicKey statement */
|
||||||
|
|
||||||
if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &key)) {
|
if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &key)) {
|
||||||
if(BN_hex2bn(&n, key) != strlen(key)) {
|
if((size_t)BN_hex2bn(&n, key) != strlen(key)) {
|
||||||
free(key);
|
free(key);
|
||||||
logger(LOG_ERR, "Invalid PublicKey for %s!", c->name);
|
logger(LOG_ERR, "Invalid PublicKey for %s!", c->name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(key);
|
free(key);
|
||||||
BN_hex2bn(&e, "FFFF");
|
BN_hex2bn(&e, "FFFF");
|
||||||
|
|
||||||
if(!n || !e || RSA_set0_key(c->rsa_key, n, e, NULL) != 1) {
|
if(!n || !e || RSA_set0_key(c->rsa_key, n, e, NULL) != 1) {
|
||||||
BN_free(e);
|
BN_free(e);
|
||||||
BN_free(n);
|
BN_free(n);
|
||||||
logger(LOG_ERR, "RSA_set0_key() failed with PublicKey for %s!", c->name);
|
logger(LOG_ERR, "RSA_set0_key() failed with PublicKey for %s!", c->name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,8 +171,9 @@ bool read_rsa_public_key(connection_t *c) {
|
||||||
// RSA_blinding_on(c->rsa_key, NULL);
|
// RSA_blinding_on(c->rsa_key, NULL);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
if(c->rsa_key)
|
if(c->rsa_key) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
logger(LOG_ERR, "No public key for %s specified!", c->name);
|
logger(LOG_ERR, "No public key for %s specified!", c->name);
|
||||||
|
|
||||||
|
@ -182,26 +189,32 @@ static bool read_rsa_private_key(void) {
|
||||||
|
|
||||||
if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key)) {
|
if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key)) {
|
||||||
myself->connection->rsa_key = RSA_new();
|
myself->connection->rsa_key = RSA_new();
|
||||||
|
|
||||||
// RSA_blinding_on(myself->connection->rsa_key, NULL);
|
// RSA_blinding_on(myself->connection->rsa_key, NULL);
|
||||||
if(BN_hex2bn(&d, key) != strlen(key)) {
|
if((size_t)BN_hex2bn(&d, key) != strlen(key)) {
|
||||||
logger(LOG_ERR, "Invalid PrivateKey for myself!");
|
logger(LOG_ERR, "Invalid PrivateKey for myself!");
|
||||||
free(key);
|
free(key);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(key);
|
free(key);
|
||||||
|
|
||||||
if(!get_config_string(lookup_config(config_tree, "PublicKey"), &pubkey)) {
|
if(!get_config_string(lookup_config(config_tree, "PublicKey"), &pubkey)) {
|
||||||
BN_free(d);
|
BN_free(d);
|
||||||
logger(LOG_ERR, "PrivateKey used but no PublicKey found!");
|
logger(LOG_ERR, "PrivateKey used but no PublicKey found!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(BN_hex2bn(&n, pubkey) != strlen(pubkey)) {
|
|
||||||
|
if((size_t)BN_hex2bn(&n, pubkey) != strlen(pubkey)) {
|
||||||
free(pubkey);
|
free(pubkey);
|
||||||
BN_free(d);
|
BN_free(d);
|
||||||
logger(LOG_ERR, "Invalid PublicKey for myself!");
|
logger(LOG_ERR, "Invalid PublicKey for myself!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(pubkey);
|
free(pubkey);
|
||||||
BN_hex2bn(&e, "FFFF");
|
BN_hex2bn(&e, "FFFF");
|
||||||
|
|
||||||
if(!n || !e || !d || RSA_set0_key(myself->connection->rsa_key, n, e, d) != 1) {
|
if(!n || !e || !d || RSA_set0_key(myself->connection->rsa_key, n, e, d) != 1) {
|
||||||
BN_free(d);
|
BN_free(d);
|
||||||
BN_free(e);
|
BN_free(e);
|
||||||
|
@ -209,11 +222,13 @@ static bool read_rsa_private_key(void) {
|
||||||
logger(LOG_ERR, "RSA_set0_key() failed with PrivateKey for myself!");
|
logger(LOG_ERR, "RSA_set0_key() failed with PrivateKey for myself!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
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);
|
xasprintf(&fname, "%s/rsa_key.priv", confbase);
|
||||||
|
}
|
||||||
|
|
||||||
fp = fopen(fname, "r");
|
fp = fopen(fname, "r");
|
||||||
|
|
||||||
|
@ -228,11 +243,13 @@ static bool read_rsa_private_key(void) {
|
||||||
struct stat s;
|
struct stat s;
|
||||||
|
|
||||||
if(!fstat(fileno(fp), &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);
|
logger(LOG_WARNING, "Warning: insecure file permissions for RSA private key file `%s'!", fname);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
logger(LOG_WARNING, "Could not stat RSA private key file `%s': %s'", fname, strerror(errno));
|
logger(LOG_WARNING, "Could not stat RSA private key file `%s': %s'", fname, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
myself->connection->rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
|
myself->connection->rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
|
||||||
|
@ -264,6 +281,7 @@ void load_all_subnets(void) {
|
||||||
|
|
||||||
xasprintf(&dname, "%s/hosts", confbase);
|
xasprintf(&dname, "%s/hosts", confbase);
|
||||||
dir = opendir(dname);
|
dir = opendir(dname);
|
||||||
|
|
||||||
if(!dir) {
|
if(!dir) {
|
||||||
logger(LOG_ERR, "Could not open %s: %s", dname, strerror(errno));
|
logger(LOG_ERR, "Could not open %s: %s", dname, strerror(errno));
|
||||||
free(dname);
|
free(dname);
|
||||||
|
@ -271,8 +289,9 @@ void load_all_subnets(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
while((ent = readdir(dir))) {
|
while((ent = readdir(dir))) {
|
||||||
if(!check_id(ent->d_name))
|
if(!check_id(ent->d_name)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
n = lookup_node(ent->d_name);
|
n = lookup_node(ent->d_name);
|
||||||
#ifdef _DIRENT_HAVE_D_TYPE
|
#ifdef _DIRENT_HAVE_D_TYPE
|
||||||
|
@ -293,8 +312,9 @@ void load_all_subnets(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for(cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
|
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;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if((s2 = lookup_subnet(n, s))) {
|
if((s2 = lookup_subnet(n, s))) {
|
||||||
s2->expires = -1;
|
s2->expires = -1;
|
||||||
|
@ -314,32 +334,39 @@ char *get_name(void) {
|
||||||
|
|
||||||
get_config_string(lookup_config(config_tree, "Name"), &name);
|
get_config_string(lookup_config(config_tree, "Name"), &name);
|
||||||
|
|
||||||
if(!name)
|
if(!name) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if(*name == '$') {
|
if(*name == '$') {
|
||||||
char *envname = getenv(name + 1);
|
char *envname = getenv(name + 1);
|
||||||
char hostname[32] = "";
|
char hostname[32] = "";
|
||||||
|
|
||||||
if(!envname) {
|
if(!envname) {
|
||||||
if(strcmp(name + 1, "HOST")) {
|
if(strcmp(name + 1, "HOST")) {
|
||||||
fprintf(stderr, "Invalid Name: environment variable %s does not exist\n", name + 1);
|
fprintf(stderr, "Invalid Name: environment variable %s does not exist\n", name + 1);
|
||||||
free(name);
|
free(name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(gethostname(hostname, sizeof hostname) || !*hostname) {
|
|
||||||
|
if(gethostname(hostname, sizeof(hostname)) || !*hostname) {
|
||||||
fprintf(stderr, "Could not get hostname: %s\n", strerror(errno));
|
fprintf(stderr, "Could not get hostname: %s\n", strerror(errno));
|
||||||
free(name);
|
free(name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
hostname[31] = 0;
|
hostname[31] = 0;
|
||||||
envname = hostname;
|
envname = hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(name);
|
free(name);
|
||||||
name = xstrdup(envname);
|
name = xstrdup(envname);
|
||||||
|
|
||||||
for(char *c = name; *c; c++)
|
for(char *c = name; *c; c++)
|
||||||
if(!isalnum(*c))
|
if(!isalnum(*c)) {
|
||||||
*c = '_';
|
*c = '_';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!check_id(name)) {
|
if(!check_id(name)) {
|
||||||
logger(LOG_ERR, "Invalid name for myself!");
|
logger(LOG_ERR, "Invalid name for myself!");
|
||||||
|
@ -361,8 +388,8 @@ static bool setup_myself(void) {
|
||||||
char *address = NULL;
|
char *address = NULL;
|
||||||
char *proxy = NULL;
|
char *proxy = NULL;
|
||||||
char *space;
|
char *space;
|
||||||
char *envp[5] = {NULL};
|
char *envp[5] = {};
|
||||||
struct addrinfo *ai, *aip, hint = {0};
|
struct addrinfo *ai, *aip, hint = {};
|
||||||
bool choice;
|
bool choice;
|
||||||
int i, err;
|
int i, err;
|
||||||
int replaywin_int;
|
int replaywin_int;
|
||||||
|
@ -391,29 +418,35 @@ static bool setup_myself(void) {
|
||||||
read_config_file(config_tree, fname);
|
read_config_file(config_tree, fname);
|
||||||
free(fname);
|
free(fname);
|
||||||
|
|
||||||
if(!read_rsa_private_key())
|
if(!read_rsa_private_key()) {
|
||||||
return false;
|
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");
|
myport = xstrdup("655");
|
||||||
else
|
} else {
|
||||||
port_specified = true;
|
port_specified = true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Ensure myport is numeric */
|
/* Ensure myport is numeric */
|
||||||
|
|
||||||
if(!atoi(myport)) {
|
if(!atoi(myport)) {
|
||||||
struct addrinfo *ai = str2addrinfo("localhost", myport, SOCK_DGRAM);
|
struct addrinfo *ai = str2addrinfo("localhost", myport, SOCK_DGRAM);
|
||||||
sockaddr_t sa;
|
sockaddr_t sa;
|
||||||
if(!ai || !ai->ai_addr)
|
|
||||||
|
if(!ai || !ai->ai_addr) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
free(myport);
|
free(myport);
|
||||||
memcpy(&sa, ai->ai_addr, ai->ai_addrlen);
|
memcpy(&sa, ai->ai_addr, ai->ai_addrlen);
|
||||||
sockaddr2str(&sa, NULL, &myport);
|
sockaddr2str(&sa, NULL, &myport);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(get_config_string(lookup_config(config_tree, "Proxy"), &proxy)) {
|
if(get_config_string(lookup_config(config_tree, "Proxy"), &proxy)) {
|
||||||
if((space = strchr(proxy, ' ')))
|
if((space = strchr(proxy, ' '))) {
|
||||||
*space++ = 0;
|
*space++ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if(!strcasecmp(proxy, "none")) {
|
if(!strcasecmp(proxy, "none")) {
|
||||||
proxytype = PROXY_NONE;
|
proxytype = PROXY_NONE;
|
||||||
|
@ -444,6 +477,7 @@ static bool setup_myself(void) {
|
||||||
free(proxy);
|
free(proxy);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
proxyhost = xstrdup(space);
|
proxyhost = xstrdup(space);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -452,23 +486,36 @@ static bool setup_myself(void) {
|
||||||
case PROXY_SOCKS5:
|
case PROXY_SOCKS5:
|
||||||
case PROXY_HTTP:
|
case PROXY_HTTP:
|
||||||
proxyhost = space;
|
proxyhost = space;
|
||||||
if(space && (space = strchr(space, ' ')))
|
|
||||||
|
if(space && (space = strchr(space, ' '))) {
|
||||||
*space++ = 0, proxyport = space;
|
*space++ = 0, proxyport = space;
|
||||||
if(space && (space = strchr(space, ' ')))
|
}
|
||||||
|
|
||||||
|
if(space && (space = strchr(space, ' '))) {
|
||||||
*space++ = 0, proxyuser = space;
|
*space++ = 0, proxyuser = space;
|
||||||
if(space && (space = strchr(space, ' ')))
|
}
|
||||||
|
|
||||||
|
if(space && (space = strchr(space, ' '))) {
|
||||||
*space++ = 0, proxypass = space;
|
*space++ = 0, proxypass = space;
|
||||||
|
}
|
||||||
|
|
||||||
if(!proxyhost || !*proxyhost || !proxyport || !*proxyport) {
|
if(!proxyhost || !*proxyhost || !proxyport || !*proxyport) {
|
||||||
logger(LOG_ERR, "Host and port argument expected for proxy!");
|
logger(LOG_ERR, "Host and port argument expected for proxy!");
|
||||||
free(proxy);
|
free(proxy);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
proxyhost = xstrdup(proxyhost);
|
proxyhost = xstrdup(proxyhost);
|
||||||
proxyport = xstrdup(proxyport);
|
proxyport = xstrdup(proxyport);
|
||||||
if(proxyuser && *proxyuser)
|
|
||||||
|
if(proxyuser && *proxyuser) {
|
||||||
proxyuser = xstrdup(proxyuser);
|
proxyuser = xstrdup(proxyuser);
|
||||||
if(proxypass && *proxypass)
|
}
|
||||||
|
|
||||||
|
if(proxypass && *proxypass) {
|
||||||
proxypass = xstrdup(proxypass);
|
proxypass = xstrdup(proxypass);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,8 +527,9 @@ static bool setup_myself(void) {
|
||||||
cfg = lookup_config(config_tree, "Subnet");
|
cfg = lookup_config(config_tree, "Subnet");
|
||||||
|
|
||||||
while(cfg) {
|
while(cfg) {
|
||||||
if(!get_config_subnet(cfg, &subnet))
|
if(!get_config_subnet(cfg, &subnet)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
subnet_add(myself, subnet);
|
subnet_add(myself, subnet);
|
||||||
|
|
||||||
|
@ -490,14 +538,17 @@ static bool setup_myself(void) {
|
||||||
|
|
||||||
/* Check some options */
|
/* 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;
|
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;
|
myself->options |= OPTION_TCPONLY;
|
||||||
|
}
|
||||||
|
|
||||||
if(myself->options & OPTION_TCPONLY)
|
if(myself->options & OPTION_TCPONLY) {
|
||||||
myself->options |= OPTION_INDIRECT;
|
myself->options |= OPTION_INDIRECT;
|
||||||
|
}
|
||||||
|
|
||||||
get_config_bool(lookup_config(config_tree, "DirectOnly"), &directonly);
|
get_config_bool(lookup_config(config_tree, "DirectOnly"), &directonly);
|
||||||
get_config_bool(lookup_config(config_tree, "StrictSubnets"), &strictsubnets);
|
get_config_bool(lookup_config(config_tree, "StrictSubnets"), &strictsubnets);
|
||||||
|
@ -506,94 +557,112 @@ static bool setup_myself(void) {
|
||||||
strictsubnets |= tunnelserver;
|
strictsubnets |= tunnelserver;
|
||||||
|
|
||||||
if(get_config_string(lookup_config(config_tree, "Mode"), &mode)) {
|
if(get_config_string(lookup_config(config_tree, "Mode"), &mode)) {
|
||||||
if(!strcasecmp(mode, "router"))
|
if(!strcasecmp(mode, "router")) {
|
||||||
routing_mode = RMODE_ROUTER;
|
routing_mode = RMODE_ROUTER;
|
||||||
else if(!strcasecmp(mode, "switch"))
|
} else if(!strcasecmp(mode, "switch")) {
|
||||||
routing_mode = RMODE_SWITCH;
|
routing_mode = RMODE_SWITCH;
|
||||||
else if(!strcasecmp(mode, "hub"))
|
} else if(!strcasecmp(mode, "hub")) {
|
||||||
routing_mode = RMODE_HUB;
|
routing_mode = RMODE_HUB;
|
||||||
else {
|
} else {
|
||||||
logger(LOG_ERR, "Invalid routing mode!");
|
logger(LOG_ERR, "Invalid routing mode!");
|
||||||
free(mode);
|
free(mode);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(mode);
|
free(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(get_config_string(lookup_config(config_tree, "Forwarding"), &mode)) {
|
if(get_config_string(lookup_config(config_tree, "Forwarding"), &mode)) {
|
||||||
if(!strcasecmp(mode, "off"))
|
if(!strcasecmp(mode, "off")) {
|
||||||
forwarding_mode = FMODE_OFF;
|
forwarding_mode = FMODE_OFF;
|
||||||
else if(!strcasecmp(mode, "internal"))
|
} else if(!strcasecmp(mode, "internal")) {
|
||||||
forwarding_mode = FMODE_INTERNAL;
|
forwarding_mode = FMODE_INTERNAL;
|
||||||
else if(!strcasecmp(mode, "kernel"))
|
} else if(!strcasecmp(mode, "kernel")) {
|
||||||
forwarding_mode = FMODE_KERNEL;
|
forwarding_mode = FMODE_KERNEL;
|
||||||
else {
|
} else {
|
||||||
logger(LOG_ERR, "Invalid forwarding mode!");
|
logger(LOG_ERR, "Invalid forwarding mode!");
|
||||||
free(mode);
|
free(mode);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(mode);
|
free(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
choice = true;
|
choice = !(myself->options & OPTION_TCPONLY);
|
||||||
get_config_bool(lookup_config(config_tree, "PMTUDiscovery"), &choice);
|
get_config_bool(lookup_config(config_tree, "PMTUDiscovery"), &choice);
|
||||||
if(choice)
|
|
||||||
|
if(choice) {
|
||||||
myself->options |= OPTION_PMTU_DISCOVERY;
|
myself->options |= OPTION_PMTU_DISCOVERY;
|
||||||
|
}
|
||||||
|
|
||||||
choice = true;
|
choice = true;
|
||||||
get_config_bool(lookup_config(config_tree, "ClampMSS"), &choice);
|
get_config_bool(lookup_config(config_tree, "ClampMSS"), &choice);
|
||||||
if(choice)
|
|
||||||
|
if(choice) {
|
||||||
myself->options |= OPTION_CLAMP_MSS;
|
myself->options |= OPTION_CLAMP_MSS;
|
||||||
|
}
|
||||||
|
|
||||||
get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance);
|
get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance);
|
||||||
get_config_bool(lookup_config(config_tree, "DecrementTTL"), &decrement_ttl);
|
get_config_bool(lookup_config(config_tree, "DecrementTTL"), &decrement_ttl);
|
||||||
|
|
||||||
if(get_config_string(lookup_config(config_tree, "Broadcast"), &mode)) {
|
if(get_config_string(lookup_config(config_tree, "Broadcast"), &mode)) {
|
||||||
if(!strcasecmp(mode, "no"))
|
if(!strcasecmp(mode, "no")) {
|
||||||
broadcast_mode = BMODE_NONE;
|
broadcast_mode = BMODE_NONE;
|
||||||
else if(!strcasecmp(mode, "yes") || !strcasecmp(mode, "mst"))
|
} else if(!strcasecmp(mode, "yes") || !strcasecmp(mode, "mst")) {
|
||||||
broadcast_mode = BMODE_MST;
|
broadcast_mode = BMODE_MST;
|
||||||
else if(!strcasecmp(mode, "direct"))
|
} else if(!strcasecmp(mode, "direct")) {
|
||||||
broadcast_mode = BMODE_DIRECT;
|
broadcast_mode = BMODE_DIRECT;
|
||||||
else {
|
} else {
|
||||||
logger(LOG_ERR, "Invalid broadcast mode!");
|
logger(LOG_ERR, "Invalid broadcast mode!");
|
||||||
free(mode);
|
free(mode);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(mode);
|
free(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(SOL_IP) || !defined(IP_TOS)
|
#if !defined(SOL_IP) || !defined(IP_TOS)
|
||||||
if(priorityinheritance)
|
|
||||||
|
if(priorityinheritance) {
|
||||||
logger(LOG_WARNING, "%s not supported on this platform for IPv4 connection", "PriorityInheritance");
|
logger(LOG_WARNING, "%s not supported on this platform for IPv4 connection", "PriorityInheritance");
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(IPPROTO_IPV6) || !defined(IPV6_TCLASS)
|
#if !defined(IPPROTO_IPV6) || !defined(IPV6_TCLASS)
|
||||||
if(priorityinheritance)
|
|
||||||
|
if(priorityinheritance) {
|
||||||
logger(LOG_WARNING, "%s not supported on this platform for IPv6 connection", "PriorityInheritance");
|
logger(LOG_WARNING, "%s not supported on this platform for IPv6 connection", "PriorityInheritance");
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire))
|
if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire)) {
|
||||||
macexpire = 600;
|
macexpire = 600;
|
||||||
|
}
|
||||||
|
|
||||||
if(get_config_int(lookup_config(config_tree, "MaxTimeout"), &maxtimeout)) {
|
if(get_config_int(lookup_config(config_tree, "MaxTimeout"), &maxtimeout)) {
|
||||||
if(maxtimeout <= 0) {
|
if(maxtimeout <= 0) {
|
||||||
logger(LOG_ERR, "Bogus maximum timeout!");
|
logger(LOG_ERR, "Bogus maximum timeout!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
maxtimeout = 900;
|
maxtimeout = 900;
|
||||||
|
}
|
||||||
|
|
||||||
if(get_config_int(lookup_config(config_tree, "MinTimeout"), &mintimeout)) {
|
if(get_config_int(lookup_config(config_tree, "MinTimeout"), &mintimeout)) {
|
||||||
if(mintimeout < 0) {
|
if(mintimeout < 0) {
|
||||||
logger(LOG_ERR, "Bogus minimum timeout!");
|
logger(LOG_ERR, "Bogus minimum timeout!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mintimeout > maxtimeout) {
|
if(mintimeout > maxtimeout) {
|
||||||
logger(LOG_WARNING, "Minimum timeout (%d s) cannot be larger than maximum timeout (%d s). Correcting !", mintimeout, maxtimeout);
|
logger(LOG_WARNING, "Minimum timeout (%d s) cannot be larger than maximum timeout (%d s). Correcting !", mintimeout, maxtimeout);
|
||||||
mintimeout = maxtimeout;
|
mintimeout = maxtimeout;
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
mintimeout = 0;
|
mintimeout = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if(get_config_int(lookup_config(config_tree, "UDPRcvBuf"), &udp_rcvbuf)) {
|
if(get_config_int(lookup_config(config_tree, "UDPRcvBuf"), &udp_rcvbuf)) {
|
||||||
if(udp_rcvbuf <= 0) {
|
if(udp_rcvbuf <= 0) {
|
||||||
|
@ -614,21 +683,23 @@ static bool setup_myself(void) {
|
||||||
logger(LOG_ERR, "ReplayWindow cannot be negative!");
|
logger(LOG_ERR, "ReplayWindow cannot be negative!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
replaywin = (unsigned)replaywin_int;
|
replaywin = (unsigned)replaywin_int;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname)) {
|
if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname)) {
|
||||||
if(!strcasecmp(afname, "IPv4"))
|
if(!strcasecmp(afname, "IPv4")) {
|
||||||
addressfamily = AF_INET;
|
addressfamily = AF_INET;
|
||||||
else if(!strcasecmp(afname, "IPv6"))
|
} else if(!strcasecmp(afname, "IPv6")) {
|
||||||
addressfamily = AF_INET6;
|
addressfamily = AF_INET6;
|
||||||
else if(!strcasecmp(afname, "any"))
|
} else if(!strcasecmp(afname, "any")) {
|
||||||
addressfamily = AF_UNSPEC;
|
addressfamily = AF_UNSPEC;
|
||||||
else {
|
} else {
|
||||||
logger(LOG_ERR, "Invalid address family!");
|
logger(LOG_ERR, "Invalid address family!");
|
||||||
free(afname);
|
free(afname);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(afname);
|
free(afname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -648,14 +719,17 @@ static bool setup_myself(void) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(cipher);
|
|
||||||
} else
|
|
||||||
myself->incipher = EVP_aes_256_cbc();
|
|
||||||
|
|
||||||
if(myself->incipher)
|
free(cipher);
|
||||||
|
} else {
|
||||||
|
myself->incipher = EVP_aes_256_cbc();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(myself->incipher) {
|
||||||
myself->inkeylength = EVP_CIPHER_key_length(myself->incipher) + EVP_CIPHER_iv_length(myself->incipher);
|
myself->inkeylength = EVP_CIPHER_key_length(myself->incipher) + EVP_CIPHER_iv_length(myself->incipher);
|
||||||
else
|
} else {
|
||||||
myself->inkeylength = 1;
|
myself->inkeylength = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* We need to use a stream mode for the meta protocol. Use AES for this,
|
/* 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
|
but try to match the key size with the one from the cipher selected
|
||||||
|
@ -666,15 +740,18 @@ static bool setup_myself(void) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int keylen = myself->incipher ? EVP_CIPHER_key_length(myself->incipher) : 0;
|
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))
|
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;
|
keylifetime = 3600;
|
||||||
|
}
|
||||||
|
|
||||||
keyexpires = now + keylifetime;
|
keyexpires = now + keylifetime;
|
||||||
|
|
||||||
|
@ -694,8 +771,9 @@ static bool setup_myself(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
free(digest);
|
free(digest);
|
||||||
} else
|
} else {
|
||||||
myself->indigest = EVP_sha256();
|
myself->indigest = EVP_sha256();
|
||||||
|
}
|
||||||
|
|
||||||
myself->connection->outdigest = EVP_sha256();
|
myself->connection->outdigest = EVP_sha256();
|
||||||
|
|
||||||
|
@ -709,8 +787,9 @@ static bool setup_myself(void) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
myself->inmaclength = 4;
|
myself->inmaclength = 4;
|
||||||
|
}
|
||||||
|
|
||||||
myself->connection->outmaclength = 0;
|
myself->connection->outmaclength = 0;
|
||||||
|
|
||||||
|
@ -721,8 +800,9 @@ static bool setup_myself(void) {
|
||||||
logger(LOG_ERR, "Bogus compression level!");
|
logger(LOG_ERR, "Bogus compression level!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
myself->incompression = 0;
|
myself->incompression = 0;
|
||||||
|
}
|
||||||
|
|
||||||
myself->connection->outcompression = 0;
|
myself->connection->outcompression = 0;
|
||||||
|
|
||||||
|
@ -735,33 +815,41 @@ static bool setup_myself(void) {
|
||||||
|
|
||||||
graph();
|
graph();
|
||||||
|
|
||||||
if(strictsubnets)
|
if(strictsubnets) {
|
||||||
load_all_subnets();
|
load_all_subnets();
|
||||||
|
}
|
||||||
|
|
||||||
/* Open device */
|
/* Open device */
|
||||||
|
|
||||||
devops = os_devops;
|
devops = os_devops;
|
||||||
|
|
||||||
if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
|
if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
|
||||||
if(!strcasecmp(type, "dummy"))
|
if(!strcasecmp(type, "dummy")) {
|
||||||
devops = dummy_devops;
|
devops = dummy_devops;
|
||||||
else if(!strcasecmp(type, "raw_socket"))
|
} else if(!strcasecmp(type, "raw_socket")) {
|
||||||
devops = raw_socket_devops;
|
devops = raw_socket_devops;
|
||||||
else if(!strcasecmp(type, "multicast"))
|
} else if(!strcasecmp(type, "multicast")) {
|
||||||
devops = multicast_devops;
|
devops = multicast_devops;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_UML
|
#ifdef ENABLE_UML
|
||||||
else if(!strcasecmp(type, "uml"))
|
else if(!strcasecmp(type, "uml")) {
|
||||||
devops = uml_devops;
|
devops = uml_devops;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_VDE
|
#ifdef ENABLE_VDE
|
||||||
else if(!strcasecmp(type, "vde"))
|
else if(!strcasecmp(type, "vde")) {
|
||||||
devops = vde_devops;
|
devops = vde_devops;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
free(type);
|
free(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!devops.setup())
|
if(!devops.setup()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Run tinc-up script to further initialize the tap interface */
|
/* Run tinc-up script to further initialize the tap interface */
|
||||||
xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
|
xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
|
||||||
|
@ -777,8 +865,9 @@ static bool setup_myself(void) {
|
||||||
#endif
|
#endif
|
||||||
execute_script("tinc-up", envp);
|
execute_script("tinc-up", envp);
|
||||||
|
|
||||||
for(i = 0; i < 4; i++)
|
for(i = 0; i < 4; i++) {
|
||||||
free(envp[i]);
|
free(envp[i]);
|
||||||
|
}
|
||||||
|
|
||||||
/* Run subnet-up scripts for our own subnets */
|
/* Run subnet-up scripts for our own subnets */
|
||||||
|
|
||||||
|
@ -801,7 +890,8 @@ static bool setup_myself(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; i < listen_sockets; i++) {
|
for(i = 0; i < listen_sockets; i++) {
|
||||||
salen = sizeof sa;
|
salen = sizeof(sa);
|
||||||
|
|
||||||
if(getsockname(i + 3, &sa.sa, &salen) < 0) {
|
if(getsockname(i + 3, &sa.sa, &salen) < 0) {
|
||||||
logger(LOG_ERR, "Could not get address of listen fd %d: %s", i + 3, sockstrerror(errno));
|
logger(LOG_ERR, "Could not get address of listen fd %d: %s", i + 3, sockstrerror(errno));
|
||||||
return false;
|
return false;
|
||||||
|
@ -814,8 +904,10 @@ static bool setup_myself(void) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
listen_socket[i].udp = setup_vpn_in_socket(&sa);
|
listen_socket[i].udp = setup_vpn_in_socket(&sa);
|
||||||
if(listen_socket[i].udp < 0)
|
|
||||||
|
if(listen_socket[i].udp < 0) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ifdebug(CONNECTIONS) {
|
ifdebug(CONNECTIONS) {
|
||||||
hostname = sockaddr2hostname(&sa);
|
hostname = sockaddr2hostname(&sa);
|
||||||
|
@ -831,21 +923,25 @@ static bool setup_myself(void) {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
get_config_string(cfg, &address);
|
get_config_string(cfg, &address);
|
||||||
if(cfg)
|
|
||||||
|
if(cfg) {
|
||||||
cfg = lookup_config_next(config_tree, cfg);
|
cfg = lookup_config_next(config_tree, cfg);
|
||||||
|
}
|
||||||
|
|
||||||
char *port = myport;
|
char *port = myport;
|
||||||
|
|
||||||
if(address) {
|
if(address) {
|
||||||
char *space = strchr(address, ' ');
|
char *space = strchr(address, ' ');
|
||||||
|
|
||||||
if(space) {
|
if(space) {
|
||||||
*space++ = 0;
|
*space++ = 0;
|
||||||
port = space;
|
port = space;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!strcmp(address, "*"))
|
if(!strcmp(address, "*")) {
|
||||||
*address = 0;
|
*address = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hint.ai_family = addressfamily;
|
hint.ai_family = addressfamily;
|
||||||
hint.ai_socktype = SOCK_STREAM;
|
hint.ai_socktype = SOCK_STREAM;
|
||||||
|
@ -874,14 +970,16 @@ static bool setup_myself(void) {
|
||||||
listen_socket[listen_sockets].tcp =
|
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;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
listen_socket[listen_sockets].udp =
|
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;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ifdebug(CONNECTIONS) {
|
ifdebug(CONNECTIONS) {
|
||||||
hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr);
|
hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr);
|
||||||
|
@ -906,14 +1004,17 @@ static bool setup_myself(void) {
|
||||||
|
|
||||||
if(!port_specified) {
|
if(!port_specified) {
|
||||||
sockaddr_t sa;
|
sockaddr_t sa;
|
||||||
socklen_t salen = sizeof sa;
|
socklen_t salen = sizeof(sa);
|
||||||
|
|
||||||
if(!getsockname(listen_socket[0].udp, &sa.sa, &salen)) {
|
if(!getsockname(listen_socket[0].udp, &sa.sa, &salen)) {
|
||||||
free(myport);
|
free(myport);
|
||||||
sockaddr2str(&sa, NULL, &myport);
|
sockaddr2str(&sa, NULL, &myport);
|
||||||
if(!myport)
|
|
||||||
|
if(!myport) {
|
||||||
myport = xstrdup("655");
|
myport = xstrdup("655");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Done. */
|
/* Done. */
|
||||||
|
|
||||||
|
@ -938,19 +1039,25 @@ bool setup_network(void) {
|
||||||
if(pinginterval < 1) {
|
if(pinginterval < 1) {
|
||||||
pinginterval = 86400;
|
pinginterval = 86400;
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
pinginterval = 60;
|
pinginterval = 60;
|
||||||
|
}
|
||||||
|
|
||||||
if(!get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout))
|
if(!get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout)) {
|
||||||
pingtimeout = 5;
|
pingtimeout = 5;
|
||||||
if(pingtimeout < 1 || pingtimeout > pinginterval)
|
}
|
||||||
|
|
||||||
|
if(pingtimeout < 1 || pingtimeout > pinginterval) {
|
||||||
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;
|
maxoutbufsize = 10 * MTU;
|
||||||
|
}
|
||||||
|
|
||||||
if(!setup_myself())
|
if(!setup_myself()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -961,7 +1068,7 @@ bool setup_network(void) {
|
||||||
void close_network_connections(void) {
|
void close_network_connections(void) {
|
||||||
avl_node_t *node, *next;
|
avl_node_t *node, *next;
|
||||||
connection_t *c;
|
connection_t *c;
|
||||||
char *envp[5] = {NULL};
|
char *envp[5] = {};
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for(node = connection_tree->head; node; node = next) {
|
for(node = connection_tree->head; node; node = next) {
|
||||||
|
@ -974,9 +1081,10 @@ void close_network_connections(void) {
|
||||||
for(list_node_t *node = outgoing_list->head; node; node = node->next) {
|
for(list_node_t *node = outgoing_list->head; node; node = node->next) {
|
||||||
outgoing_t *outgoing = node->data;
|
outgoing_t *outgoing = node->data;
|
||||||
|
|
||||||
if(outgoing->event)
|
if(outgoing->event) {
|
||||||
event_del(outgoing->event);
|
event_del(outgoing->event);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
list_delete_list(outgoing_list);
|
list_delete_list(outgoing_list);
|
||||||
|
|
||||||
|
@ -1005,10 +1113,13 @@ void close_network_connections(void) {
|
||||||
|
|
||||||
execute_script("tinc-down", envp);
|
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]);
|
free(envp[i]);
|
||||||
|
}
|
||||||
|
|
||||||
devops.close();
|
devops.close();
|
||||||
|
|
||||||
|
|
108
src/net_socket.c
108
src/net_socket.c
|
@ -62,12 +62,14 @@ static void configure_tcp(connection_t *c) {
|
||||||
if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0) {
|
if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0) {
|
||||||
logger(LOG_ERR, "fcntl for %s: %s", c->hostname, strerror(errno));
|
logger(LOG_ERR, "fcntl for %s: %s", c->hostname, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(WIN32)
|
#elif defined(WIN32)
|
||||||
unsigned long arg = 1;
|
unsigned long arg = 1;
|
||||||
|
|
||||||
if(ioctlsocket(c->socket, FIONBIO, &arg) != 0) {
|
if(ioctlsocket(c->socket, FIONBIO, &arg) != 0) {
|
||||||
logger(LOG_ERR, "ioctlsocket for %s: %s", c->hostname, sockstrerror(sockerrno));
|
logger(LOG_ERR, "ioctlsocket for %s: %s", c->hostname, sockstrerror(sockerrno));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SOL_TCP) && defined(TCP_NODELAY)
|
#if defined(SOL_TCP) && defined(TCP_NODELAY)
|
||||||
|
@ -94,8 +96,9 @@ static bool bind_to_interface(int sd) {
|
||||||
int status;
|
int status;
|
||||||
#endif /* defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) */
|
#endif /* defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) */
|
||||||
|
|
||||||
if(!get_config_string(lookup_config (config_tree, "BindToInterface"), &iface))
|
if(!get_config_string(lookup_config(config_tree, "BindToInterface"), &iface)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
|
#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
|
||||||
memset(&ifr, 0, sizeof(ifr));
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
|
@ -104,6 +107,7 @@ static bool bind_to_interface(int sd) {
|
||||||
free(iface);
|
free(iface);
|
||||||
|
|
||||||
status = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr));
|
status = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr));
|
||||||
|
|
||||||
if(status) {
|
if(status) {
|
||||||
logger(LOG_ERR, "Can't bind to interface %s: %s", ifr.ifr_ifrn.ifrn_name, strerror(errno));
|
logger(LOG_ERR, "Can't bind to interface %s: %s", ifr.ifr_ifrn.ifrn_name, strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
|
@ -139,8 +143,11 @@ int setup_listen_socket(const sockaddr_t *sa) {
|
||||||
setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option));
|
setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option));
|
||||||
|
|
||||||
#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
|
#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
|
||||||
if(sa->sa.sa_family == AF_INET6)
|
|
||||||
setsockopt(nfd, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
|
if(sa->sa.sa_family == AF_INET6) {
|
||||||
|
setsockopt(nfd, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof(option));
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(get_config_string(lookup_config(config_tree, "BindToInterface"), &iface)) {
|
if(get_config_string(lookup_config(config_tree, "BindToInterface"), &iface)) {
|
||||||
|
@ -210,6 +217,7 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
|
||||||
#elif defined(WIN32)
|
#elif defined(WIN32)
|
||||||
{
|
{
|
||||||
unsigned long arg = 1;
|
unsigned long arg = 1;
|
||||||
|
|
||||||
if(ioctlsocket(nfd, FIONBIO, &arg) != 0) {
|
if(ioctlsocket(nfd, FIONBIO, &arg) != 0) {
|
||||||
closesocket(nfd);
|
closesocket(nfd);
|
||||||
logger(LOG_ERR, "Call to `%s' failed: %s", "ioctlsocket", sockstrerror(sockerrno));
|
logger(LOG_ERR, "Call to `%s' failed: %s", "ioctlsocket", sockstrerror(sockerrno));
|
||||||
|
@ -222,15 +230,20 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
|
||||||
setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option));
|
setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option));
|
||||||
setsockopt(nfd, SOL_SOCKET, SO_BROADCAST, (void *)&option, sizeof(option));
|
setsockopt(nfd, SOL_SOCKET, SO_BROADCAST, (void *)&option, sizeof(option));
|
||||||
|
|
||||||
if(udp_rcvbuf && setsockopt(nfd, SOL_SOCKET, SO_RCVBUF, (void *)&udp_rcvbuf, sizeof(udp_rcvbuf)))
|
if(udp_rcvbuf && setsockopt(nfd, SOL_SOCKET, SO_RCVBUF, (void *)&udp_rcvbuf, sizeof(udp_rcvbuf))) {
|
||||||
logger(LOG_WARNING, "Can't set UDP SO_RCVBUF to %i: %s", udp_rcvbuf, strerror(errno));
|
logger(LOG_WARNING, "Can't set UDP SO_RCVBUF to %i: %s", udp_rcvbuf, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
if(udp_sndbuf && setsockopt(nfd, SOL_SOCKET, SO_SNDBUF, (void *)&udp_sndbuf, sizeof(udp_sndbuf)))
|
if(udp_sndbuf && setsockopt(nfd, SOL_SOCKET, SO_SNDBUF, (void *)&udp_sndbuf, sizeof(udp_sndbuf))) {
|
||||||
logger(LOG_WARNING, "Can't set UDP SO_SNDBUF to %i: %s", udp_sndbuf, strerror(errno));
|
logger(LOG_WARNING, "Can't set UDP SO_SNDBUF to %i: %s", udp_sndbuf, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
|
#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
|
||||||
if(sa->sa.sa_family == AF_INET6)
|
|
||||||
setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
|
if(sa->sa.sa_family == AF_INET6) {
|
||||||
|
setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof(option));
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(IP_DONTFRAG) && !defined(IP_DONTFRAGMENT)
|
#if defined(IP_DONTFRAG) && !defined(IP_DONTFRAGMENT)
|
||||||
|
@ -238,27 +251,35 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SOL_IP) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
|
#if defined(SOL_IP) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
|
||||||
|
|
||||||
if(myself->options & OPTION_PMTU_DISCOVERY) {
|
if(myself->options & OPTION_PMTU_DISCOVERY) {
|
||||||
option = IP_PMTUDISC_DO;
|
option = IP_PMTUDISC_DO;
|
||||||
setsockopt(nfd, SOL_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option));
|
setsockopt(nfd, SOL_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option));
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(IPPROTO_IP) && defined(IP_DONTFRAGMENT)
|
#elif defined(IPPROTO_IP) && defined(IP_DONTFRAGMENT)
|
||||||
|
|
||||||
if(myself->options & OPTION_PMTU_DISCOVERY) {
|
if(myself->options & OPTION_PMTU_DISCOVERY) {
|
||||||
option = 1;
|
option = 1;
|
||||||
setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, (void *)&option, sizeof(option));
|
setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, (void *)&option, sizeof(option));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SOL_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
|
#if defined(SOL_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
|
||||||
|
|
||||||
if(myself->options & OPTION_PMTU_DISCOVERY) {
|
if(myself->options & OPTION_PMTU_DISCOVERY) {
|
||||||
option = IPV6_PMTUDISC_DO;
|
option = IPV6_PMTUDISC_DO;
|
||||||
setsockopt(nfd, SOL_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option));
|
setsockopt(nfd, SOL_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option));
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(IPPROTO_IPV6) && defined(IPV6_DONTFRAG)
|
#elif defined(IPPROTO_IPV6) && defined(IPV6_DONTFRAG)
|
||||||
|
|
||||||
if(myself->options & OPTION_PMTU_DISCOVERY) {
|
if(myself->options & OPTION_PMTU_DISCOVERY) {
|
||||||
option = 1;
|
option = 1;
|
||||||
setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, (void *)&option, sizeof(option));
|
setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, (void *)&option, sizeof(option));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(!bind_to_interface(nfd)) {
|
if(!bind_to_interface(nfd)) {
|
||||||
|
@ -280,14 +301,18 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
|
||||||
void retry_outgoing(outgoing_t *outgoing) {
|
void retry_outgoing(outgoing_t *outgoing) {
|
||||||
outgoing->timeout += 5;
|
outgoing->timeout += 5;
|
||||||
|
|
||||||
if(outgoing->timeout < mintimeout)
|
if(outgoing->timeout < mintimeout) {
|
||||||
outgoing->timeout = mintimeout;
|
outgoing->timeout = mintimeout;
|
||||||
|
}
|
||||||
|
|
||||||
if(outgoing->timeout > maxtimeout)
|
if(outgoing->timeout > maxtimeout) {
|
||||||
outgoing->timeout = maxtimeout;
|
outgoing->timeout = maxtimeout;
|
||||||
|
}
|
||||||
|
|
||||||
if(outgoing->event)
|
if(outgoing->event) {
|
||||||
event_del(outgoing->event);
|
event_del(outgoing->event);
|
||||||
|
}
|
||||||
|
|
||||||
outgoing->event = new_event();
|
outgoing->event = new_event();
|
||||||
outgoing->event->handler = (event_handler_t) setup_outgoing_connection;
|
outgoing->event->handler = (event_handler_t) setup_outgoing_connection;
|
||||||
outgoing->event->time = now + outgoing->timeout;
|
outgoing->event->time = now + outgoing->timeout;
|
||||||
|
@ -340,14 +365,19 @@ static void do_outgoing_pipe(connection_t *c, char *command) {
|
||||||
setenv("REMOTEPORT", port, true);
|
setenv("REMOTEPORT", port, true);
|
||||||
setenv("NODE", c->name, true);
|
setenv("NODE", c->name, true);
|
||||||
setenv("NAME", myself->name, true);
|
setenv("NAME", myself->name, true);
|
||||||
if(netname)
|
|
||||||
|
if(netname) {
|
||||||
setenv("NETNAME", netname, true);
|
setenv("NETNAME", netname, true);
|
||||||
|
}
|
||||||
|
|
||||||
int result = system(command);
|
int result = system(command);
|
||||||
if(result < 0)
|
|
||||||
|
if(result < 0) {
|
||||||
logger(LOG_ERR, "Could not execute %s: %s\n", command, strerror(errno));
|
logger(LOG_ERR, "Could not execute %s: %s\n", command, strerror(errno));
|
||||||
else if(result)
|
} else if(result) {
|
||||||
logger(LOG_ERR, "%s exited with non-zero status %d", command, result);
|
logger(LOG_ERR, "%s exited with non-zero status %d", command, result);
|
||||||
|
}
|
||||||
|
|
||||||
exit(result);
|
exit(result);
|
||||||
#else
|
#else
|
||||||
logger(LOG_ERR, "Proxy type exec not supported on this platform!");
|
logger(LOG_ERR, "Proxy type exec not supported on this platform!");
|
||||||
|
@ -357,12 +387,14 @@ static void do_outgoing_pipe(connection_t *c, char *command) {
|
||||||
|
|
||||||
static bool is_valid_host_port(const char *host, const char *port) {
|
static bool is_valid_host_port(const char *host, const char *port) {
|
||||||
for(const char *p = host; *p; p++)
|
for(const char *p = host; *p; p++)
|
||||||
if(!isalnum(*p) && *p != '-' && *p != '.')
|
if(!isalnum(*p) && *p != '-' && *p != '.') {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for(const char *p = port; *p; p++)
|
for(const char *p = port; *p; p++)
|
||||||
if(!isalnum(*p))
|
if(!isalnum(*p)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -377,6 +409,7 @@ void do_outgoing_connection(connection_t *c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
begin:
|
begin:
|
||||||
|
|
||||||
if(!c->outgoing->ai) {
|
if(!c->outgoing->ai) {
|
||||||
if(!c->outgoing->cfg) {
|
if(!c->outgoing->cfg) {
|
||||||
ifdebug(CONNECTIONS) logger(LOG_ERR, "Could not set up a meta connection to %s",
|
ifdebug(CONNECTIONS) logger(LOG_ERR, "Could not set up a meta connection to %s",
|
||||||
|
@ -392,19 +425,21 @@ begin:
|
||||||
get_config_string(c->outgoing->cfg, &address);
|
get_config_string(c->outgoing->cfg, &address);
|
||||||
|
|
||||||
space = strchr(address, ' ');
|
space = strchr(address, ' ');
|
||||||
|
|
||||||
if(space) {
|
if(space) {
|
||||||
port = xstrdup(space + 1);
|
port = xstrdup(space + 1);
|
||||||
*space = 0;
|
*space = 0;
|
||||||
} else {
|
} else {
|
||||||
if(!get_config_string(lookup_config(c->config_tree, "Port"), &port))
|
if(!get_config_string(lookup_config(c->config_tree, "Port"), &port)) {
|
||||||
port = xstrdup("655");
|
port = xstrdup("655");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
c->outgoing->ai = str2addrinfo(address, port, SOCK_STREAM);
|
c->outgoing->ai = str2addrinfo(address, port, SOCK_STREAM);
|
||||||
|
|
||||||
// If we cannot resolve the address, maybe we are using a proxy that can?
|
// If we cannot resolve the address, maybe we are using a proxy that can?
|
||||||
if(!c->outgoing->ai && proxytype != PROXY_NONE && is_valid_host_port(address, port)) {
|
if(!c->outgoing->ai && proxytype != PROXY_NONE && is_valid_host_port(address, port)) {
|
||||||
memset(&c->address, 0, sizeof c->address);
|
memset(&c->address, 0, sizeof(c->address));
|
||||||
c->address.sa.sa_family = AF_UNKNOWN;
|
c->address.sa.sa_family = AF_UNKNOWN;
|
||||||
c->address.unknown.address = address;
|
c->address.unknown.address = address;
|
||||||
c->address.unknown.port = port;
|
c->address.unknown.port = port;
|
||||||
|
@ -416,13 +451,16 @@ begin:
|
||||||
c->outgoing->aip = c->outgoing->ai;
|
c->outgoing->aip = c->outgoing->ai;
|
||||||
c->outgoing->cfg = lookup_config_next(c->config_tree, c->outgoing->cfg);
|
c->outgoing->cfg = lookup_config_next(c->config_tree, c->outgoing->cfg);
|
||||||
|
|
||||||
if(!c->outgoing->ai && proxytype != PROXY_NONE)
|
if(!c->outgoing->ai && proxytype != PROXY_NONE) {
|
||||||
goto connect;
|
goto connect;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!c->outgoing->aip) {
|
if(!c->outgoing->aip) {
|
||||||
if(c->outgoing->ai)
|
if(c->outgoing->ai) {
|
||||||
freeaddrinfo(c->outgoing->ai);
|
freeaddrinfo(c->outgoing->ai);
|
||||||
|
}
|
||||||
|
|
||||||
c->outgoing->ai = NULL;
|
c->outgoing->ai = NULL;
|
||||||
goto begin;
|
goto begin;
|
||||||
}
|
}
|
||||||
|
@ -431,8 +469,10 @@ begin:
|
||||||
c->outgoing->aip = c->outgoing->aip->ai_next;
|
c->outgoing->aip = c->outgoing->aip->ai_next;
|
||||||
|
|
||||||
connect:
|
connect:
|
||||||
if(c->hostname)
|
|
||||||
|
if(c->hostname) {
|
||||||
free(c->hostname);
|
free(c->hostname);
|
||||||
|
}
|
||||||
|
|
||||||
c->hostname = sockaddr2hostname(&c->address);
|
c->hostname = sockaddr2hostname(&c->address);
|
||||||
|
|
||||||
|
@ -446,8 +486,11 @@ connect:
|
||||||
do_outgoing_pipe(c, proxyhost);
|
do_outgoing_pipe(c, proxyhost);
|
||||||
} else {
|
} else {
|
||||||
proxyai = str2addrinfo(proxyhost, proxyport, SOCK_STREAM);
|
proxyai = str2addrinfo(proxyhost, proxyport, SOCK_STREAM);
|
||||||
if(!proxyai)
|
|
||||||
|
if(!proxyai) {
|
||||||
goto begin;
|
goto begin;
|
||||||
|
}
|
||||||
|
|
||||||
ifdebug(CONNECTIONS) logger(LOG_INFO, "Using proxy at %s port %s", proxyhost, proxyport);
|
ifdebug(CONNECTIONS) logger(LOG_INFO, "Using proxy at %s port %s", proxyhost, proxyport);
|
||||||
c->socket = socket(proxyai->ai_family, SOCK_STREAM, IPPROTO_TCP);
|
c->socket = socket(proxyai->ai_family, SOCK_STREAM, IPPROTO_TCP);
|
||||||
}
|
}
|
||||||
|
@ -457,8 +500,9 @@ connect:
|
||||||
goto begin;
|
goto begin;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(proxytype != PROXY_EXEC)
|
if(proxytype != PROXY_EXEC) {
|
||||||
configure_tcp(c);
|
configure_tcp(c);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef FD_CLOEXEC
|
#ifdef FD_CLOEXEC
|
||||||
fcntl(c->socket, F_SETFD, FD_CLOEXEC);
|
fcntl(c->socket, F_SETFD, FD_CLOEXEC);
|
||||||
|
@ -467,8 +511,11 @@ connect:
|
||||||
if(proxytype != PROXY_EXEC) {
|
if(proxytype != PROXY_EXEC) {
|
||||||
#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
|
#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
|
||||||
int option = 1;
|
int option = 1;
|
||||||
if(c->address.sa.sa_family == AF_INET6)
|
|
||||||
setsockopt(c->socket, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
|
if(c->address.sa.sa_family == AF_INET6) {
|
||||||
|
setsockopt(c->socket, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof(option));
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bind_to_interface(c->socket);
|
bind_to_interface(c->socket);
|
||||||
|
@ -488,10 +535,12 @@ connect:
|
||||||
|
|
||||||
if(b != -1) {
|
if(b != -1) {
|
||||||
sockaddr_t sa = listen_socket[b].sa;
|
sockaddr_t sa = listen_socket[b].sa;
|
||||||
if(sa.sa.sa_family == AF_INET)
|
|
||||||
|
if(sa.sa.sa_family == AF_INET) {
|
||||||
sa.in.sin_port = 0;
|
sa.in.sin_port = 0;
|
||||||
else if(sa.sa.sa_family == AF_INET6)
|
} else if(sa.sa.sa_family == AF_INET6) {
|
||||||
sa.in6.sin6_port = 0;
|
sa.in6.sin6_port = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if(bind(c->socket, &sa.sa, SALEN(sa.sa))) {
|
if(bind(c->socket, &sa.sa, SALEN(sa.sa))) {
|
||||||
char *addrstr = sockaddr2hostname(&sa);
|
char *addrstr = sockaddr2hostname(&sa);
|
||||||
|
@ -557,6 +606,7 @@ void setup_outgoing_connection(outgoing_t *outgoing) {
|
||||||
c->outcompression = myself->connection->outcompression;
|
c->outcompression = myself->connection->outcompression;
|
||||||
|
|
||||||
init_configuration(&c->config_tree);
|
init_configuration(&c->config_tree);
|
||||||
|
|
||||||
if(!read_connection_config(c)) {
|
if(!read_connection_config(c)) {
|
||||||
free_connection(c);
|
free_connection(c);
|
||||||
outgoing->timeout = maxtimeout;
|
outgoing->timeout = maxtimeout;
|
||||||
|
@ -626,11 +676,13 @@ bool handle_new_meta_connection(int sock) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_outgoing(outgoing_t *outgoing) {
|
static void free_outgoing(outgoing_t *outgoing) {
|
||||||
if(outgoing->ai)
|
if(outgoing->ai) {
|
||||||
freeaddrinfo(outgoing->ai);
|
freeaddrinfo(outgoing->ai);
|
||||||
|
}
|
||||||
|
|
||||||
if(outgoing->name)
|
if(outgoing->name) {
|
||||||
free(outgoing->name);
|
free(outgoing->name);
|
||||||
|
}
|
||||||
|
|
||||||
free(outgoing);
|
free(outgoing);
|
||||||
}
|
}
|
||||||
|
|
68
src/netutl.c
68
src/netutl.c
|
@ -33,7 +33,7 @@ bool hostnames = false;
|
||||||
Return NULL on failure.
|
Return NULL on failure.
|
||||||
*/
|
*/
|
||||||
struct addrinfo *str2addrinfo(const char *address, const char *service, int socktype) {
|
struct addrinfo *str2addrinfo(const char *address, const char *service, int socktype) {
|
||||||
struct addrinfo *ai = NULL, hint = {0};
|
struct addrinfo *ai = NULL, hint = {};
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
hint.ai_family = addressfamily;
|
hint.ai_family = addressfamily;
|
||||||
|
@ -55,7 +55,7 @@ struct addrinfo *str2addrinfo(const char *address, const char *service, int sock
|
||||||
}
|
}
|
||||||
|
|
||||||
sockaddr_t str2sockaddr(const char *address, const char *port) {
|
sockaddr_t str2sockaddr(const char *address, const char *port) {
|
||||||
struct addrinfo *ai = NULL, hint = {0};
|
struct addrinfo *ai = NULL, hint = {};
|
||||||
sockaddr_t result;
|
sockaddr_t result;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -87,10 +87,14 @@ void sockaddr2str(const sockaddr_t *sa, char **addrstr, char **portstr) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if(sa->sa.sa_family == AF_UNKNOWN) {
|
if(sa->sa.sa_family == AF_UNKNOWN) {
|
||||||
if(addrstr)
|
if(addrstr) {
|
||||||
*addrstr = xstrdup(sa->unknown.address);
|
*addrstr = xstrdup(sa->unknown.address);
|
||||||
if(portstr)
|
}
|
||||||
|
|
||||||
|
if(portstr) {
|
||||||
*portstr = xstrdup(sa->unknown.port);
|
*portstr = xstrdup(sa->unknown.port);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,14 +108,18 @@ void sockaddr2str(const sockaddr_t *sa, char **addrstr, char **portstr) {
|
||||||
|
|
||||||
scopeid = strchr(address, '%');
|
scopeid = strchr(address, '%');
|
||||||
|
|
||||||
if(scopeid)
|
if(scopeid) {
|
||||||
*scopeid = '\0'; /* Descope. */
|
*scopeid = '\0'; /* Descope. */
|
||||||
|
}
|
||||||
|
|
||||||
if(addrstr)
|
if(addrstr) {
|
||||||
*addrstr = xstrdup(address);
|
*addrstr = xstrdup(address);
|
||||||
if(portstr)
|
}
|
||||||
|
|
||||||
|
if(portstr) {
|
||||||
*portstr = xstrdup(port);
|
*portstr = xstrdup(port);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char *sockaddr2hostname(const sockaddr_t *sa) {
|
char *sockaddr2hostname(const sockaddr_t *sa) {
|
||||||
char *str;
|
char *str;
|
||||||
|
@ -126,6 +134,7 @@ char *sockaddr2hostname(const sockaddr_t *sa) {
|
||||||
|
|
||||||
err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port),
|
err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port),
|
||||||
hostnames ? 0 : (NI_NUMERICHOST | NI_NUMERICSERV));
|
hostnames ? 0 : (NI_NUMERICHOST | NI_NUMERICSERV));
|
||||||
|
|
||||||
if(err) {
|
if(err) {
|
||||||
logger(LOG_ERR, "Error while looking up hostname: %s",
|
logger(LOG_ERR, "Error while looking up hostname: %s",
|
||||||
gai_strerror(err));
|
gai_strerror(err));
|
||||||
|
@ -141,8 +150,9 @@ int sockaddrcmp_noport(const sockaddr_t *a, const sockaddr_t *b) {
|
||||||
|
|
||||||
result = a->sa.sa_family - b->sa.sa_family;
|
result = a->sa.sa_family - b->sa.sa_family;
|
||||||
|
|
||||||
if(result)
|
if(result) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
switch(a->sa.sa_family) {
|
switch(a->sa.sa_family) {
|
||||||
case AF_UNSPEC:
|
case AF_UNSPEC:
|
||||||
|
@ -169,8 +179,9 @@ int sockaddrcmp(const sockaddr_t *a, const sockaddr_t *b) {
|
||||||
|
|
||||||
result = a->sa.sa_family - b->sa.sa_family;
|
result = a->sa.sa_family - b->sa.sa_family;
|
||||||
|
|
||||||
if(result)
|
if(result) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
switch(a->sa.sa_family) {
|
switch(a->sa.sa_family) {
|
||||||
case AF_UNSPEC:
|
case AF_UNSPEC:
|
||||||
|
@ -179,24 +190,27 @@ int sockaddrcmp(const sockaddr_t *a, const sockaddr_t *b) {
|
||||||
case AF_UNKNOWN:
|
case AF_UNKNOWN:
|
||||||
result = strcmp(a->unknown.address, b->unknown.address);
|
result = strcmp(a->unknown.address, b->unknown.address);
|
||||||
|
|
||||||
if(result)
|
if(result) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return strcmp(a->unknown.port, b->unknown.port);
|
return strcmp(a->unknown.port, b->unknown.port);
|
||||||
|
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
result = memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof(a->in.sin_addr));
|
result = memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof(a->in.sin_addr));
|
||||||
|
|
||||||
if(result)
|
if(result) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return memcmp(&a->in.sin_port, &b->in.sin_port, sizeof(a->in.sin_port));
|
return memcmp(&a->in.sin_port, &b->in.sin_port, sizeof(a->in.sin_port));
|
||||||
|
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
result = memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr));
|
result = memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr));
|
||||||
|
|
||||||
if(result)
|
if(result) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return memcmp(&a->in6.sin6_port, &b->in6.sin6_port, sizeof(a->in6.sin6_port));
|
return memcmp(&a->in6.sin6_port, &b->in6.sin6_port, sizeof(a->in6.sin6_port));
|
||||||
|
|
||||||
|
@ -233,18 +247,24 @@ void sockaddrunmap(sockaddr_t *sa) {
|
||||||
|
|
||||||
void sockaddr_setport(sockaddr_t *sa, const char *port) {
|
void sockaddr_setport(sockaddr_t *sa, const char *port) {
|
||||||
uint16_t portnum = htons(atoi(port));
|
uint16_t portnum = htons(atoi(port));
|
||||||
if(!portnum)
|
|
||||||
|
if(!portnum) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch(sa->sa.sa_family) {
|
switch(sa->sa.sa_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
sa->in.sin_port = portnum;
|
sa->in.sin_port = portnum;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
sa->in6.sin6_port = portnum;
|
sa->in6.sin6_port = portnum;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AF_UNKNOWN:
|
case AF_UNKNOWN:
|
||||||
free(sa->unknown.port);
|
free(sa->unknown.port);
|
||||||
sa->unknown.port = xstrdup(port);
|
sa->unknown.port = xstrdup(port);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -259,9 +279,11 @@ int maskcmp(const void *va, const void *vb, int masklen) {
|
||||||
|
|
||||||
for(m = masklen, i = 0; m >= 8; m -= 8, i++) {
|
for(m = masklen, i = 0; m >= 8; m -= 8, i++) {
|
||||||
result = a[i] - b[i];
|
result = a[i] - b[i];
|
||||||
if(result)
|
|
||||||
|
if(result) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(m)
|
if(m)
|
||||||
return (a[i] & (0x100 - (1 << (8 - m)))) -
|
return (a[i] & (0x100 - (1 << (8 - m)))) -
|
||||||
|
@ -277,29 +299,33 @@ void mask(void *va, int masklen, int len) {
|
||||||
i = masklen / 8;
|
i = masklen / 8;
|
||||||
masklen %= 8;
|
masklen %= 8;
|
||||||
|
|
||||||
if(masklen)
|
if(masklen) {
|
||||||
a[i++] &= (0x100 - (1 << (8 - masklen)));
|
a[i++] &= (0x100 - (1 << (8 - masklen)));
|
||||||
|
}
|
||||||
|
|
||||||
for(; i < len; i++)
|
for(; i < len; i++) {
|
||||||
a[i] = 0;
|
a[i] = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void maskcpy(void *va, const void *vb, int masklen, int len) {
|
void maskcpy(void *va, const void *vb, int masklen, int len) {
|
||||||
int i, m;
|
int i, m;
|
||||||
char *a = va;
|
char *a = va;
|
||||||
const char *b = vb;
|
const char *b = vb;
|
||||||
|
|
||||||
for(m = masklen, i = 0; m >= 8; m -= 8, i++)
|
for(m = masklen, i = 0; m >= 8; m -= 8, i++) {
|
||||||
a[i] = b[i];
|
a[i] = b[i];
|
||||||
|
}
|
||||||
|
|
||||||
if(m) {
|
if(m) {
|
||||||
a[i] = b[i] & (0x100 - (1 << (8 - m)));
|
a[i] = b[i] & (0x100 - (1 << (8 - m)));
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(; i < len; i++)
|
for(; i < len; i++) {
|
||||||
a[i] = 0;
|
a[i] = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool maskcheck(const void *va, int masklen, int len) {
|
bool maskcheck(const void *va, int masklen, int len) {
|
||||||
int i;
|
int i;
|
||||||
|
@ -308,12 +334,14 @@ bool maskcheck(const void *va, int masklen, int len) {
|
||||||
i = masklen / 8;
|
i = masklen / 8;
|
||||||
masklen %= 8;
|
masklen %= 8;
|
||||||
|
|
||||||
if(masklen && a[i++] & (0xff >> masklen))
|
if(masklen && a[i++] & (0xff >> masklen)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for(; i < len; i++)
|
for(; i < len; i++)
|
||||||
if(a[i] != 0)
|
if(a[i] != 0) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
36
src/netutl.h
36
src/netutl.h
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_NETUTL_H
|
||||||
|
#define TINC_NETUTL_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
netutl.h -- header file for netutl.c
|
netutl.h -- header file for netutl.c
|
||||||
Copyright (C) 1998-2005 Ivo Timmermans
|
Copyright (C) 1998-2005 Ivo Timmermans
|
||||||
|
@ -18,26 +21,23 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TINC_NETUTL_H__
|
|
||||||
#define __TINC_NETUTL_H__
|
|
||||||
|
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
|
||||||
extern bool hostnames;
|
extern bool hostnames;
|
||||||
|
|
||||||
extern struct addrinfo *str2addrinfo(const char *, const char *, int);
|
extern struct addrinfo *str2addrinfo(const char *address, const char *service, int socktype);
|
||||||
extern sockaddr_t str2sockaddr(const char *, const char *);
|
extern sockaddr_t str2sockaddr(const char *address, const char *port);
|
||||||
extern void sockaddr2str(const sockaddr_t *, char **, char **);
|
extern void sockaddr2str(const sockaddr_t *sa, char **addrstr, char **portstr);
|
||||||
extern char *sockaddr2hostname(const sockaddr_t *);
|
extern char *sockaddr2hostname(const sockaddr_t *sa);
|
||||||
extern int sockaddrcmp(const sockaddr_t *, const sockaddr_t *);
|
extern int sockaddrcmp(const sockaddr_t *a, const sockaddr_t *b);
|
||||||
extern int sockaddrcmp_noport(const sockaddr_t *, const sockaddr_t *);
|
extern int sockaddrcmp_noport(const sockaddr_t *a, const sockaddr_t *b);
|
||||||
extern void sockaddrunmap(sockaddr_t *);
|
extern void sockaddrunmap(sockaddr_t *sa);
|
||||||
extern void sockaddrfree(sockaddr_t *);
|
extern void sockaddrfree(sockaddr_t *sa);
|
||||||
extern void sockaddrcpy(sockaddr_t *, const sockaddr_t *);
|
extern void sockaddrcpy(sockaddr_t *dest, const sockaddr_t *src);
|
||||||
extern void sockaddr_setport(sockaddr_t *, const char *);
|
extern void sockaddr_setport(sockaddr_t *sa, const char *port);
|
||||||
extern int maskcmp(const void *, const void *, int);
|
extern int maskcmp(const void *a, const void *b, int masklen);
|
||||||
extern void maskcpy(void *, const void *, int, int);
|
extern void maskcpy(void *dest, const void *src, int masklen, int len);
|
||||||
extern void mask(void *, int, int);
|
extern void mask(void *mask, int masklen, int len);
|
||||||
extern bool maskcheck(const void *, int, int);
|
extern bool maskcheck(const void *mask, int masklen, int len);
|
||||||
|
|
||||||
#endif /* __TINC_NETUTL_H__ */
|
#endif
|
||||||
|
|
45
src/node.c
45
src/node.c
|
@ -54,13 +54,19 @@ void exit_nodes(void) {
|
||||||
node_t *new_node(void) {
|
node_t *new_node(void) {
|
||||||
node_t *n = xmalloc_and_zero(sizeof(*n));
|
node_t *n = xmalloc_and_zero(sizeof(*n));
|
||||||
|
|
||||||
if(replaywin) n->late = xmalloc_and_zero(replaywin);
|
if(replaywin) {
|
||||||
|
n->late = xmalloc_and_zero(replaywin);
|
||||||
|
}
|
||||||
|
|
||||||
n->subnet_tree = new_subnet_tree();
|
n->subnet_tree = new_subnet_tree();
|
||||||
n->edge_tree = new_edge_tree();
|
n->edge_tree = new_edge_tree();
|
||||||
n->inctx = EVP_CIPHER_CTX_new();
|
n->inctx = EVP_CIPHER_CTX_new();
|
||||||
n->outctx = EVP_CIPHER_CTX_new();
|
n->outctx = EVP_CIPHER_CTX_new();
|
||||||
if(!n->inctx || !n->outctx)
|
|
||||||
|
if(!n->inctx || !n->outctx) {
|
||||||
abort();
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
n->mtu = MTU;
|
n->mtu = MTU;
|
||||||
n->maxmtu = MTU;
|
n->maxmtu = MTU;
|
||||||
|
|
||||||
|
@ -68,34 +74,42 @@ node_t *new_node(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_node(node_t *n) {
|
void free_node(node_t *n) {
|
||||||
if(n->inkey)
|
if(n->inkey) {
|
||||||
free(n->inkey);
|
free(n->inkey);
|
||||||
|
}
|
||||||
|
|
||||||
if(n->outkey)
|
if(n->outkey) {
|
||||||
free(n->outkey);
|
free(n->outkey);
|
||||||
|
}
|
||||||
|
|
||||||
if(n->subnet_tree)
|
if(n->subnet_tree) {
|
||||||
free_subnet_tree(n->subnet_tree);
|
free_subnet_tree(n->subnet_tree);
|
||||||
|
}
|
||||||
|
|
||||||
if(n->edge_tree)
|
if(n->edge_tree) {
|
||||||
free_edge_tree(n->edge_tree);
|
free_edge_tree(n->edge_tree);
|
||||||
|
}
|
||||||
|
|
||||||
sockaddrfree(&n->address);
|
sockaddrfree(&n->address);
|
||||||
|
|
||||||
EVP_CIPHER_CTX_free(n->outctx);
|
EVP_CIPHER_CTX_free(n->outctx);
|
||||||
EVP_CIPHER_CTX_free(n->inctx);
|
EVP_CIPHER_CTX_free(n->inctx);
|
||||||
|
|
||||||
if(n->mtuevent)
|
if(n->mtuevent) {
|
||||||
event_del(n->mtuevent);
|
event_del(n->mtuevent);
|
||||||
|
}
|
||||||
|
|
||||||
if(n->hostname)
|
if(n->hostname) {
|
||||||
free(n->hostname);
|
free(n->hostname);
|
||||||
|
}
|
||||||
|
|
||||||
if(n->name)
|
if(n->name) {
|
||||||
free(n->name);
|
free(n->name);
|
||||||
|
}
|
||||||
|
|
||||||
if(n->late)
|
if(n->late) {
|
||||||
free(n->late);
|
free(n->late);
|
||||||
|
}
|
||||||
|
|
||||||
free(n);
|
free(n);
|
||||||
}
|
}
|
||||||
|
@ -126,7 +140,7 @@ void node_del(node_t *n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
node_t *lookup_node(char *name) {
|
node_t *lookup_node(char *name) {
|
||||||
node_t n = {NULL};
|
node_t n = {};
|
||||||
|
|
||||||
n.name = name;
|
n.name = name;
|
||||||
|
|
||||||
|
@ -134,7 +148,7 @@ node_t *lookup_node(char *name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
node_t *lookup_node_udp(const sockaddr_t *sa) {
|
node_t *lookup_node_udp(const sockaddr_t *sa) {
|
||||||
node_t n = {NULL};
|
node_t n = {};
|
||||||
|
|
||||||
n.address = *sa;
|
n.address = *sa;
|
||||||
n.name = NULL;
|
n.name = NULL;
|
||||||
|
@ -150,8 +164,9 @@ void update_node_udp(node_t *n, const sockaddr_t *sa) {
|
||||||
|
|
||||||
avl_delete(node_udp_tree, n);
|
avl_delete(node_udp_tree, n);
|
||||||
|
|
||||||
if(n->hostname)
|
if(n->hostname) {
|
||||||
free(n->hostname);
|
free(n->hostname);
|
||||||
|
}
|
||||||
|
|
||||||
if(sa) {
|
if(sa) {
|
||||||
n->address = *sa;
|
n->address = *sa;
|
||||||
|
@ -159,7 +174,7 @@ void update_node_udp(node_t *n, const sockaddr_t *sa) {
|
||||||
avl_insert(node_udp_tree, n);
|
avl_insert(node_udp_tree, n);
|
||||||
ifdebug(PROTOCOL) logger(LOG_DEBUG, "UDP address of %s set to %s", n->name, n->hostname);
|
ifdebug(PROTOCOL) logger(LOG_DEBUG, "UDP address of %s set to %s", n->name, n->hostname);
|
||||||
} else {
|
} else {
|
||||||
memset(&n->address, 0, sizeof n->address);
|
memset(&n->address, 0, sizeof(n->address));
|
||||||
n->hostname = NULL;
|
n->hostname = NULL;
|
||||||
ifdebug(PROTOCOL) logger(LOG_DEBUG, "UDP address of %s cleared", n->name);
|
ifdebug(PROTOCOL) logger(LOG_DEBUG, "UDP address of %s cleared", n->name);
|
||||||
}
|
}
|
||||||
|
@ -176,7 +191,7 @@ void dump_nodes(void) {
|
||||||
logger(LOG_DEBUG, " %s at %s cipher %d digest %d maclength %d compression %d options %x status %04x nexthop %s via %s pmtu %d (min %d max %d)",
|
logger(LOG_DEBUG, " %s at %s cipher %d digest %d maclength %d compression %d options %x status %04x nexthop %s via %s pmtu %d (min %d max %d)",
|
||||||
n->name, n->hostname, n->outcipher ? EVP_CIPHER_nid(n->outcipher) : 0,
|
n->name, n->hostname, n->outcipher ? EVP_CIPHER_nid(n->outcipher) : 0,
|
||||||
n->outdigest ? EVP_MD_type(n->outdigest) : 0, n->outmaclength, n->outcompression,
|
n->outdigest ? EVP_MD_type(n->outdigest) : 0, n->outmaclength, n->outcompression,
|
||||||
n->options, bitfield_to_int(&n->status, sizeof n->status), n->nexthop ? n->nexthop->name : "-",
|
n->options, bitfield_to_int(&n->status, sizeof(n->status)), n->nexthop ? n->nexthop->name : "-",
|
||||||
n->via ? n->via->name : "-", n->mtu, n->minmtu, n->maxmtu);
|
n->via ? n->via->name : "-", n->mtu, n->minmtu, n->maxmtu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
20
src/node.h
20
src/node.h
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_NODE_H
|
||||||
|
#define TINC_NODE_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
node.h -- header for node.c
|
node.h -- header for node.c
|
||||||
Copyright (C) 2001-2016 Guus Sliepen <guus@tinc-vpn.org>,
|
Copyright (C) 2001-2016 Guus Sliepen <guus@tinc-vpn.org>,
|
||||||
|
@ -18,9 +21,6 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TINC_NODE_H__
|
|
||||||
#define __TINC_NODE_H__
|
|
||||||
|
|
||||||
#include "avl_tree.h"
|
#include "avl_tree.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
|
@ -95,12 +95,12 @@ extern avl_tree_t *node_udp_tree;
|
||||||
extern void init_nodes(void);
|
extern void init_nodes(void);
|
||||||
extern void exit_nodes(void);
|
extern void exit_nodes(void);
|
||||||
extern node_t *new_node(void) __attribute__((__malloc__));
|
extern node_t *new_node(void) __attribute__((__malloc__));
|
||||||
extern void free_node(node_t *);
|
extern void free_node(node_t *n);
|
||||||
extern void node_add(node_t *);
|
extern void node_add(node_t *n);
|
||||||
extern void node_del(node_t *);
|
extern void node_del(node_t *n);
|
||||||
extern node_t *lookup_node(char *);
|
extern node_t *lookup_node(char *name);
|
||||||
extern node_t *lookup_node_udp(const sockaddr_t *);
|
extern node_t *lookup_node_udp(const sockaddr_t *sa);
|
||||||
extern void update_node_udp(node_t *, const sockaddr_t *);
|
extern void update_node_udp(node_t *n, const sockaddr_t *sa);
|
||||||
extern void dump_nodes(void);
|
extern void dump_nodes(void);
|
||||||
|
|
||||||
#endif /* __TINC_NODE_H__ */
|
#endif
|
||||||
|
|
|
@ -36,15 +36,18 @@
|
||||||
* 0 is returned if either there's no pidfile, it's empty
|
* 0 is returned if either there's no pidfile, it's empty
|
||||||
* or no pid can be read.
|
* or no pid can be read.
|
||||||
*/
|
*/
|
||||||
pid_t read_pid (const char *pidfile)
|
pid_t read_pid(const char *pidfile) {
|
||||||
{
|
|
||||||
FILE *f;
|
FILE *f;
|
||||||
long pid;
|
long pid;
|
||||||
|
|
||||||
if (!(f=fopen(pidfile,"r")))
|
if(!(f = fopen(pidfile, "r"))) {
|
||||||
return 0;
|
return 0;
|
||||||
if(fscanf(f,"%20ld", &pid) != 1)
|
}
|
||||||
|
|
||||||
|
if(fscanf(f, "%20ld", &pid) != 1) {
|
||||||
pid = 0;
|
pid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return (pid_t)pid;
|
return (pid_t)pid;
|
||||||
}
|
}
|
||||||
|
@ -55,13 +58,13 @@ pid_t read_pid (const char *pidfile)
|
||||||
* table (using /proc) to determine if the process already exists. If
|
* table (using /proc) to determine if the process already exists. If
|
||||||
* so the pid is returned, otherwise 0.
|
* so the pid is returned, otherwise 0.
|
||||||
*/
|
*/
|
||||||
pid_t check_pid (const char *pidfile)
|
pid_t check_pid(const char *pidfile) {
|
||||||
{
|
|
||||||
pid_t pid = read_pid(pidfile);
|
pid_t pid = read_pid(pidfile);
|
||||||
|
|
||||||
/* Amazing ! _I_ am already holding the pid file... */
|
/* Amazing ! _I_ am already holding the pid file... */
|
||||||
if ((!pid) || (pid == getpid ()))
|
if((!pid) || (pid == getpid())) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The 'standard' method of doing this is to try and do a 'fake' kill
|
* The 'standard' method of doing this is to try and do a 'fake' kill
|
||||||
|
@ -70,8 +73,10 @@ pid_t check_pid (const char *pidfile)
|
||||||
*/
|
*/
|
||||||
/* But... errno is usually changed only on error.. */
|
/* But... errno is usually changed only on error.. */
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (kill(pid, 0) && errno == ESRCH)
|
|
||||||
|
if(kill(pid, 0) && errno == ESRCH) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
@ -81,8 +86,7 @@ pid_t check_pid (const char *pidfile)
|
||||||
* Writes the pid to the specified file. If that fails 0 is
|
* Writes the pid to the specified file. If that fails 0 is
|
||||||
* returned, otherwise the pid.
|
* returned, otherwise the pid.
|
||||||
*/
|
*/
|
||||||
pid_t write_pid (const char *pidfile)
|
pid_t write_pid(const char *pidfile) {
|
||||||
{
|
|
||||||
FILE *f;
|
FILE *f;
|
||||||
int fd;
|
int fd;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
@ -97,24 +101,30 @@ pid_t write_pid (const char *pidfile)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_FLOCK
|
#ifdef HAVE_FLOCK
|
||||||
|
|
||||||
if(flock(fd, LOCK_EX | LOCK_NB) == -1) {
|
if(flock(fd, LOCK_EX | LOCK_NB) == -1) {
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pid = getpid();
|
pid = getpid();
|
||||||
|
|
||||||
if(!fprintf(f, "%ld\n", (long)pid)) {
|
if(!fprintf(f, "%ld\n", (long)pid)) {
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fflush(f);
|
fflush(f);
|
||||||
|
|
||||||
#ifdef HAVE_FLOCK
|
#ifdef HAVE_FLOCK
|
||||||
|
|
||||||
if(flock(fd, LOCK_UN) == -1) {
|
if(flock(fd, LOCK_UN) == -1) {
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
|
@ -126,8 +136,7 @@ pid_t write_pid (const char *pidfile)
|
||||||
* Remove the the specified file. The result from unlink(2)
|
* Remove the the specified file. The result from unlink(2)
|
||||||
* is returned
|
* is returned
|
||||||
*/
|
*/
|
||||||
int remove_pid (const char *pidfile)
|
int remove_pid(const char *pidfile) {
|
||||||
{
|
|
||||||
return unlink(pidfile);
|
return unlink(pidfile);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_PIDFILE_H
|
||||||
|
#define TINC_PIDFILE_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pidfile.h - interact with pidfiles
|
pidfile.h - interact with pidfiles
|
||||||
Copyright (c) 1995 Martin Schulze <Martin.Schulze@Linux.DE>
|
Copyright (c) 1995 Martin Schulze <Martin.Schulze@Linux.DE>
|
||||||
|
@ -50,3 +53,5 @@ extern pid_t write_pid (const char *pidfile);
|
||||||
*/
|
*/
|
||||||
extern int remove_pid(const char *pidfile);
|
extern int remove_pid(const char *pidfile);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
139
src/process.c
139
src/process.c
|
@ -47,11 +47,6 @@ extern bool use_logfile;
|
||||||
static sigset_t emptysigset;
|
static sigset_t emptysigset;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void memory_full(int size) {
|
|
||||||
logger(LOG_ERR, "Memory exhausted (couldn't allocate %d bytes), exitting.", size);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Some functions the less gifted operating systems might lack... */
|
/* Some functions the less gifted operating systems might lack... */
|
||||||
|
|
||||||
#ifdef HAVE_MINGW
|
#ifdef HAVE_MINGW
|
||||||
|
@ -71,31 +66,34 @@ bool install_service(void) {
|
||||||
SERVICE_DESCRIPTION description = {"Virtual Private Network daemon"};
|
SERVICE_DESCRIPTION description = {"Virtual Private Network daemon"};
|
||||||
|
|
||||||
manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
||||||
|
|
||||||
if(!manager) {
|
if(!manager) {
|
||||||
logger(LOG_ERR, "Could not open service manager: %s", winerror(GetLastError()));
|
logger(LOG_ERR, "Could not open service manager: %s", winerror(GetLastError()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!strchr(program_name, '\\')) {
|
if(!strchr(program_name, '\\')) {
|
||||||
GetCurrentDirectory(sizeof command - 1, command + 1);
|
GetCurrentDirectory(sizeof(command) - 1, command + 1);
|
||||||
strncat(command, "\\", sizeof command - strlen(command));
|
strncat(command, "\\", sizeof(command) - strlen(command));
|
||||||
}
|
}
|
||||||
|
|
||||||
strncat(command, program_name, sizeof command - strlen(command));
|
strncat(command, program_name, sizeof(command) - strlen(command));
|
||||||
|
|
||||||
strncat(command, "\"", sizeof command - strlen(command));
|
strncat(command, "\"", sizeof(command) - strlen(command));
|
||||||
|
|
||||||
for(argp = g_argv + 1; *argp; argp++) {
|
for(argp = g_argv + 1; *argp; argp++) {
|
||||||
space = strchr(*argp, ' ');
|
space = strchr(*argp, ' ');
|
||||||
strncat(command, " ", sizeof command - strlen(command));
|
strncat(command, " ", sizeof(command) - strlen(command));
|
||||||
|
|
||||||
if(space)
|
if(space) {
|
||||||
strncat(command, "\"", sizeof command - strlen(command));
|
strncat(command, "\"", sizeof(command) - strlen(command));
|
||||||
|
}
|
||||||
|
|
||||||
strncat(command, *argp, sizeof command - strlen(command));
|
strncat(command, *argp, sizeof(command) - strlen(command));
|
||||||
|
|
||||||
if(space)
|
if(space) {
|
||||||
strncat(command, "\"", sizeof command - strlen(command));
|
strncat(command, "\"", sizeof(command) - strlen(command));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
service = CreateService(manager, identname, identname,
|
service = CreateService(manager, identname, identname,
|
||||||
|
@ -105,9 +103,11 @@ bool install_service(void) {
|
||||||
if(!service) {
|
if(!service) {
|
||||||
DWORD lasterror = GetLastError();
|
DWORD lasterror = GetLastError();
|
||||||
logger(LOG_ERR, "Could not create %s service: %s", identname, winerror(lasterror));
|
logger(LOG_ERR, "Could not create %s service: %s", identname, winerror(lasterror));
|
||||||
if(lasterror != ERROR_SERVICE_EXISTS)
|
|
||||||
|
if(lasterror != ERROR_SERVICE_EXISTS) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(service) {
|
if(service) {
|
||||||
ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &description);
|
ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &description);
|
||||||
|
@ -116,16 +116,18 @@ bool install_service(void) {
|
||||||
service = OpenService(manager, identname, SERVICE_ALL_ACCESS);
|
service = OpenService(manager, identname, SERVICE_ALL_ACCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!StartService(service, 0, NULL))
|
if(!StartService(service, 0, NULL)) {
|
||||||
logger(LOG_WARNING, "Could not start %s service: %s", identname, winerror(GetLastError()));
|
logger(LOG_WARNING, "Could not start %s service: %s", identname, winerror(GetLastError()));
|
||||||
else
|
} else {
|
||||||
logger(LOG_INFO, "%s service started", identname);
|
logger(LOG_INFO, "%s service started", identname);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool remove_service(void) {
|
bool remove_service(void) {
|
||||||
manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
||||||
|
|
||||||
if(!manager) {
|
if(!manager) {
|
||||||
logger(LOG_ERR, "Could not open service manager: %s", winerror(GetLastError()));
|
logger(LOG_ERR, "Could not open service manager: %s", winerror(GetLastError()));
|
||||||
return false;
|
return false;
|
||||||
|
@ -138,10 +140,11 @@ bool remove_service(void) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ControlService(service, SERVICE_CONTROL_STOP, &status))
|
if(!ControlService(service, SERVICE_CONTROL_STOP, &status)) {
|
||||||
logger(LOG_ERR, "Could not stop %s service: %s", identname, winerror(GetLastError()));
|
logger(LOG_ERR, "Could not stop %s service: %s", identname, winerror(GetLastError()));
|
||||||
else
|
} else {
|
||||||
logger(LOG_INFO, "%s service stopped", identname);
|
logger(LOG_INFO, "%s service stopped", identname);
|
||||||
|
}
|
||||||
|
|
||||||
if(!DeleteService(service)) {
|
if(!DeleteService(service)) {
|
||||||
logger(LOG_ERR, "Could not remove %s service: %s", identname, winerror(GetLastError()));
|
logger(LOG_ERR, "Could not remove %s service: %s", identname, winerror(GetLastError()));
|
||||||
|
@ -158,12 +161,15 @@ DWORD WINAPI controlhandler(DWORD request, DWORD type, LPVOID boe, LPVOID bah) {
|
||||||
case SERVICE_CONTROL_INTERROGATE:
|
case SERVICE_CONTROL_INTERROGATE:
|
||||||
SetServiceStatus(statushandle, &status);
|
SetServiceStatus(statushandle, &status);
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
|
|
||||||
case SERVICE_CONTROL_STOP:
|
case SERVICE_CONTROL_STOP:
|
||||||
logger(LOG_NOTICE, "Got %s request", "SERVICE_CONTROL_STOP");
|
logger(LOG_NOTICE, "Got %s request", "SERVICE_CONTROL_STOP");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SERVICE_CONTROL_SHUTDOWN:
|
case SERVICE_CONTROL_SHUTDOWN:
|
||||||
logger(LOG_NOTICE, "Got %s request", "SERVICE_CONTROL_SHUTDOWN");
|
logger(LOG_NOTICE, "Got %s request", "SERVICE_CONTROL_SHUTDOWN");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
logger(LOG_WARNING, "Got unexpected request %d", (int)request);
|
logger(LOG_WARNING, "Got unexpected request %d", (int)request);
|
||||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||||
|
@ -225,10 +231,10 @@ bool init_service(void) {
|
||||||
if(!StartServiceCtrlDispatcher(services)) {
|
if(!StartServiceCtrlDispatcher(services)) {
|
||||||
if(GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
|
if(GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
|
||||||
return false;
|
return false;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
logger(LOG_ERR, "System call `%s' failed: %s", "StartServiceCtrlDispatcher", winerror(GetLastError()));
|
logger(LOG_ERR, "System call `%s' failed: %s", "StartServiceCtrlDispatcher", winerror(GetLastError()));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -247,8 +253,10 @@ static bool write_pidfile(void) {
|
||||||
if(netname)
|
if(netname)
|
||||||
fprintf(stderr, "A tincd is already running for net `%s' with pid %ld.\n",
|
fprintf(stderr, "A tincd is already running for net `%s' with pid %ld.\n",
|
||||||
netname, (long)pid);
|
netname, (long)pid);
|
||||||
else
|
else {
|
||||||
fprintf(stderr, "A tincd is already running with pid %ld.\n", (long)pid);
|
fprintf(stderr, "A tincd is already running with pid %ld.\n", (long)pid);
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,8 +283,10 @@ bool kill_other(int signal) {
|
||||||
if(netname)
|
if(netname)
|
||||||
fprintf(stderr, "No other tincd is running for net `%s'.\n",
|
fprintf(stderr, "No other tincd is running for net `%s'.\n",
|
||||||
netname);
|
netname);
|
||||||
else
|
else {
|
||||||
fprintf(stderr, "No other tincd is running.\n");
|
fprintf(stderr, "No other tincd is running.\n");
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,8 +297,9 @@ bool kill_other(int signal) {
|
||||||
if(netname)
|
if(netname)
|
||||||
fprintf(stderr, "The tincd for net `%s' is no longer running. ",
|
fprintf(stderr, "The tincd for net `%s' is no longer running. ",
|
||||||
netname);
|
netname);
|
||||||
else
|
else {
|
||||||
fprintf(stderr, "The tincd is no longer running. ");
|
fprintf(stderr, "The tincd is no longer running. ");
|
||||||
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Removing stale lock file.\n");
|
fprintf(stderr, "Removing stale lock file.\n");
|
||||||
remove_pid(pidfilename);
|
remove_pid(pidfilename);
|
||||||
|
@ -309,8 +320,10 @@ bool detach(void) {
|
||||||
/* First check if we can open a fresh new pidfile */
|
/* First check if we can open a fresh new pidfile */
|
||||||
|
|
||||||
#ifndef HAVE_MINGW
|
#ifndef HAVE_MINGW
|
||||||
if(!write_pidfile())
|
|
||||||
|
if(!write_pidfile()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* If we succeeded in doing that, detach */
|
/* If we succeeded in doing that, detach */
|
||||||
|
|
||||||
|
@ -319,6 +332,7 @@ bool detach(void) {
|
||||||
|
|
||||||
if(do_detach) {
|
if(do_detach) {
|
||||||
#ifndef HAVE_MINGW
|
#ifndef HAVE_MINGW
|
||||||
|
|
||||||
if(daemon(0, 0)) {
|
if(daemon(0, 0)) {
|
||||||
fprintf(stderr, "Couldn't detach from terminal: %s",
|
fprintf(stderr, "Couldn't detach from terminal: %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
@ -331,9 +345,13 @@ bool detach(void) {
|
||||||
fprintf(stderr, "Could not write pid file %s: %s\n", pidfilename, strerror(errno));
|
fprintf(stderr, "Could not write pid file %s: %s\n", pidfilename, strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
if(!statushandle)
|
|
||||||
|
if(!statushandle) {
|
||||||
exit(install_service());
|
exit(install_service());
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,16 +360,17 @@ bool detach(void) {
|
||||||
logger(LOG_NOTICE, "tincd %s starting, debug level %d",
|
logger(LOG_NOTICE, "tincd %s starting, debug level %d",
|
||||||
VERSION, debug_level);
|
VERSION, debug_level);
|
||||||
|
|
||||||
xalloc_fail_func = memory_full;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_PUTENV
|
#ifdef HAVE_PUTENV
|
||||||
void unputenv(char *p) {
|
void unputenv(char *p) {
|
||||||
char *e = strchr(p, '=');
|
char *e = strchr(p, '=');
|
||||||
if(!e)
|
|
||||||
|
if(!e) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int len = e - p;
|
int len = e - p;
|
||||||
#ifndef HAVE_UNSETENV
|
#ifndef HAVE_UNSETENV
|
||||||
#ifdef HAVE_MINGW
|
#ifdef HAVE_MINGW
|
||||||
|
@ -368,13 +387,16 @@ void unputenv(char *p) {
|
||||||
// We must keep what we putenv() around in memory.
|
// We must keep what we putenv() around in memory.
|
||||||
// To do this without memory leaks, keep things in a list and reuse if possible.
|
// To do this without memory leaks, keep things in a list and reuse if possible.
|
||||||
static list_t list = {};
|
static list_t list = {};
|
||||||
|
|
||||||
for(list_node_t *node = list.head; node; node = node->next) {
|
for(list_node_t *node = list.head; node; node = node->next) {
|
||||||
char *data = node->data;
|
char *data = node->data;
|
||||||
|
|
||||||
if(!strcmp(data, var)) {
|
if(!strcmp(data, var)) {
|
||||||
putenv(data);
|
putenv(data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *data = xstrdup(var);
|
char *data = xstrdup(var);
|
||||||
list_insert_tail(&list, data);
|
list_insert_tail(&list, data);
|
||||||
putenv(data);
|
putenv(data);
|
||||||
|
@ -396,13 +418,18 @@ bool execute_script(const char *name, char **envp) {
|
||||||
#ifndef HAVE_MINGW
|
#ifndef HAVE_MINGW
|
||||||
len = xasprintf(&scriptname, "\"%s/%s\"", confbase, name);
|
len = xasprintf(&scriptname, "\"%s/%s\"", confbase, name);
|
||||||
#else
|
#else
|
||||||
if(cfg_interpreter)
|
|
||||||
|
if(cfg_interpreter) {
|
||||||
len = xasprintf(&scriptname, "\"%s/%s\"", confbase, name);
|
len = xasprintf(&scriptname, "\"%s/%s\"", confbase, name);
|
||||||
else
|
} else {
|
||||||
len = xasprintf(&scriptname, "\"%s/%s.bat\"", confbase, name);
|
len = xasprintf(&scriptname, "\"%s/%s.bat\"", confbase, name);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
if(len < 0)
|
|
||||||
|
if(len < 0) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
scriptname[len - 1] = '\0';
|
scriptname[len - 1] = '\0';
|
||||||
|
|
||||||
|
@ -418,16 +445,19 @@ bool execute_script(const char *name, char **envp) {
|
||||||
free(scriptname);
|
free(scriptname);
|
||||||
len = xasprintf(&scriptname, "%s \"%s/%s\"", interpreter, confbase, name);
|
len = xasprintf(&scriptname, "%s \"%s/%s\"", interpreter, confbase, name);
|
||||||
free(interpreter);
|
free(interpreter);
|
||||||
if(len < 0)
|
|
||||||
|
if(len < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ifdebug(STATUS) logger(LOG_INFO, "Executing script %s", name);
|
ifdebug(STATUS) logger(LOG_INFO, "Executing script %s", name);
|
||||||
|
|
||||||
/* Set environment */
|
/* Set environment */
|
||||||
|
|
||||||
for(i = 0; envp[i]; i++)
|
for(i = 0; envp[i]; i++) {
|
||||||
putenv(envp[i]);
|
putenv(envp[i]);
|
||||||
|
}
|
||||||
|
|
||||||
scriptname[len - 1] = '\"';
|
scriptname[len - 1] = '\"';
|
||||||
status = system(scriptname);
|
status = system(scriptname);
|
||||||
|
@ -436,11 +466,13 @@ bool execute_script(const char *name, char **envp) {
|
||||||
|
|
||||||
/* Unset environment */
|
/* Unset environment */
|
||||||
|
|
||||||
for(i = 0; envp[i]; i++)
|
for(i = 0; envp[i]; i++) {
|
||||||
unputenv(envp[i]);
|
unputenv(envp[i]);
|
||||||
|
}
|
||||||
|
|
||||||
if(status != -1) {
|
if(status != -1) {
|
||||||
#ifdef WEXITSTATUS
|
#ifdef WEXITSTATUS
|
||||||
|
|
||||||
if(WIFEXITED(status)) { /* Child exited by itself */
|
if(WIFEXITED(status)) { /* Child exited by itself */
|
||||||
if(WEXITSTATUS(status)) {
|
if(WEXITSTATUS(status)) {
|
||||||
logger(LOG_ERR, "Script %s exited with non-zero status %d",
|
logger(LOG_ERR, "Script %s exited with non-zero status %d",
|
||||||
|
@ -455,11 +487,13 @@ bool execute_script(const char *name, char **envp) {
|
||||||
logger(LOG_ERR, "Script %s terminated abnormally", name);
|
logger(LOG_ERR, "Script %s terminated abnormally", name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
logger(LOG_ERR, "System call `%s' failed: %s", "system", strerror(errno));
|
logger(LOG_ERR, "System call `%s' failed: %s", "system", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -471,20 +505,26 @@ bool execute_script(const char *name, char **envp) {
|
||||||
|
|
||||||
#ifndef HAVE_MINGW
|
#ifndef HAVE_MINGW
|
||||||
static RETSIGTYPE sigterm_handler(int a) {
|
static RETSIGTYPE sigterm_handler(int a) {
|
||||||
|
(void)a;
|
||||||
logger(LOG_NOTICE, "Got %s signal", "TERM");
|
logger(LOG_NOTICE, "Got %s signal", "TERM");
|
||||||
if(running)
|
|
||||||
|
if(running) {
|
||||||
running = false;
|
running = false;
|
||||||
else
|
} else {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static RETSIGTYPE sigquit_handler(int a) {
|
static RETSIGTYPE sigquit_handler(int a) {
|
||||||
|
(void)a;
|
||||||
logger(LOG_NOTICE, "Got %s signal", "QUIT");
|
logger(LOG_NOTICE, "Got %s signal", "QUIT");
|
||||||
if(running)
|
|
||||||
|
if(running) {
|
||||||
running = false;
|
running = false;
|
||||||
else
|
} else {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static RETSIGTYPE fatal_signal_square(int a) {
|
static RETSIGTYPE fatal_signal_square(int a) {
|
||||||
logger(LOG_ERR, "Got another fatal signal %d (%s): not restarting.", a,
|
logger(LOG_ERR, "Got another fatal signal %d (%s): not restarting.", a,
|
||||||
|
@ -515,11 +555,13 @@ static RETSIGTYPE fatal_signal_handler(int a) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static RETSIGTYPE sighup_handler(int a) {
|
static RETSIGTYPE sighup_handler(int a) {
|
||||||
|
(void)a;
|
||||||
logger(LOG_NOTICE, "Got %s signal", "HUP");
|
logger(LOG_NOTICE, "Got %s signal", "HUP");
|
||||||
sighup = true;
|
sighup = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RETSIGTYPE sigint_handler(int a) {
|
static RETSIGTYPE sigint_handler(int a) {
|
||||||
|
(void)a;
|
||||||
static int saved_debug_level = -1;
|
static int saved_debug_level = -1;
|
||||||
|
|
||||||
logger(LOG_NOTICE, "Got %s signal", "INT");
|
logger(LOG_NOTICE, "Got %s signal", "INT");
|
||||||
|
@ -539,15 +581,18 @@ static RETSIGTYPE sigint_handler(int a) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static RETSIGTYPE sigalrm_handler(int a) {
|
static RETSIGTYPE sigalrm_handler(int a) {
|
||||||
|
(void)a;
|
||||||
logger(LOG_NOTICE, "Got %s signal", "ALRM");
|
logger(LOG_NOTICE, "Got %s signal", "ALRM");
|
||||||
sigalrm = true;
|
sigalrm = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RETSIGTYPE sigusr1_handler(int a) {
|
static RETSIGTYPE sigusr1_handler(int a) {
|
||||||
|
(void)a;
|
||||||
dump_connections();
|
dump_connections();
|
||||||
}
|
}
|
||||||
|
|
||||||
static RETSIGTYPE sigusr2_handler(int a) {
|
static RETSIGTYPE sigusr2_handler(int a) {
|
||||||
|
(void)a;
|
||||||
devops.dump_stats();
|
devops.dump_stats();
|
||||||
dump_nodes();
|
dump_nodes();
|
||||||
dump_edges();
|
dump_edges();
|
||||||
|
@ -555,14 +600,17 @@ static RETSIGTYPE sigusr2_handler(int a) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static RETSIGTYPE sigwinch_handler(int a) {
|
static RETSIGTYPE sigwinch_handler(int a) {
|
||||||
|
(void)a;
|
||||||
do_purge = true;
|
do_purge = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RETSIGTYPE unexpected_signal_handler(int a) {
|
static RETSIGTYPE unexpected_signal_handler(int a) {
|
||||||
|
(void)a;
|
||||||
logger(LOG_WARNING, "Got unexpected signal %d (%s)", a, strsignal(a));
|
logger(LOG_WARNING, "Got unexpected signal %d (%s)", a, strsignal(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
static RETSIGTYPE ignore_signal_handler(int a) {
|
static RETSIGTYPE ignore_signal_handler(int a) {
|
||||||
|
(void)a;
|
||||||
ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Ignored signal %d (%s)", a, strsignal(a));
|
ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Ignored signal %d (%s)", a, strsignal(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -601,25 +649,30 @@ void setup_signals(void) {
|
||||||
/* Set a default signal handler for every signal, errors will be
|
/* Set a default signal handler for every signal, errors will be
|
||||||
ignored. */
|
ignored. */
|
||||||
for(i = 1; i < NSIG; i++) {
|
for(i = 1; i < NSIG; i++) {
|
||||||
if(!do_detach)
|
if(!do_detach) {
|
||||||
act.sa_handler = SIG_DFL;
|
act.sa_handler = SIG_DFL;
|
||||||
else
|
} else {
|
||||||
act.sa_handler = unexpected_signal_handler;
|
act.sa_handler = unexpected_signal_handler;
|
||||||
|
}
|
||||||
|
|
||||||
sigaction(i, &act, NULL);
|
sigaction(i, &act, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we didn't detach, allow coredumps */
|
/* If we didn't detach, allow coredumps */
|
||||||
if(!do_detach)
|
if(!do_detach) {
|
||||||
sighandlers[3].handler = SIG_DFL;
|
sighandlers[3].handler = SIG_DFL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Then, for each known signal that we want to catch, assign a
|
/* Then, for each known signal that we want to catch, assign a
|
||||||
handler to the signal, with error checking this time. */
|
handler to the signal, with error checking this time. */
|
||||||
for(i = 0; sighandlers[i].signal; i++) {
|
for(i = 0; sighandlers[i].signal; i++) {
|
||||||
act.sa_handler = sighandlers[i].handler;
|
act.sa_handler = sighandlers[i].handler;
|
||||||
|
|
||||||
if(sigaction(sighandlers[i].signal, &act, NULL) < 0)
|
if(sigaction(sighandlers[i].signal, &act, NULL) < 0)
|
||||||
fprintf(stderr, "Installing signal handler for signal %d (%s) failed: %s\n",
|
fprintf(stderr, "Installing signal handler for signal %d (%s) failed: %s\n",
|
||||||
sighandlers[i].signal, strsignal(sighandlers[i].signal),
|
sighandlers[i].signal, strsignal(sighandlers[i].signal),
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_PROCESS_H
|
||||||
|
#define TINC_PROCESS_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
process.h -- header file for process.c
|
process.h -- header file for process.c
|
||||||
Copyright (C) 1999-2005 Ivo Timmermans,
|
Copyright (C) 1999-2005 Ivo Timmermans,
|
||||||
|
@ -18,20 +21,17 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TINC_PROCESS_H__
|
|
||||||
#define __TINC_PROCESS_H__
|
|
||||||
|
|
||||||
extern bool do_detach;
|
extern bool do_detach;
|
||||||
extern bool sighup;
|
extern bool sighup;
|
||||||
extern bool sigalrm;
|
extern bool sigalrm;
|
||||||
|
|
||||||
extern void setup_signals(void);
|
extern void setup_signals(void);
|
||||||
extern bool execute_script(const char *, char **);
|
extern bool execute_script(const char *name, char **envp);
|
||||||
extern bool detach(void);
|
extern bool detach(void);
|
||||||
extern bool kill_other(int);
|
extern bool kill_other(int signal);
|
||||||
|
|
||||||
#ifdef HAVE_MINGW
|
#ifdef HAVE_MINGW
|
||||||
extern bool init_service(void);
|
extern bool init_service(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __TINC_PROCESS_H__ */
|
#endif
|
||||||
|
|
|
@ -35,7 +35,7 @@ bool strictsubnets = false;
|
||||||
|
|
||||||
static bool (*request_handlers[])(connection_t *) = {
|
static bool (*request_handlers[])(connection_t *) = {
|
||||||
id_h, metakey_h, challenge_h, chal_reply_h, ack_h,
|
id_h, metakey_h, challenge_h, chal_reply_h, ack_h,
|
||||||
status_h, error_h, termreq_h,
|
NULL, NULL, NULL,
|
||||||
ping_h, pong_h,
|
ping_h, pong_h,
|
||||||
add_subnet_h, del_subnet_h,
|
add_subnet_h, del_subnet_h,
|
||||||
add_edge_h, del_edge_h,
|
add_edge_h, del_edge_h,
|
||||||
|
@ -56,8 +56,9 @@ static avl_tree_t *past_request_tree;
|
||||||
|
|
||||||
bool check_id(const char *id) {
|
bool check_id(const char *id) {
|
||||||
for(; *id; id++)
|
for(; *id; id++)
|
||||||
if(!isalnum(*id) && *id != '_')
|
if(!isalnum(*id) && *id != '_') {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -75,11 +76,11 @@ bool send_request(connection_t *c, const char *format, ...) {
|
||||||
input buffer anyway */
|
input buffer anyway */
|
||||||
|
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
len = vsnprintf(buffer, sizeof buffer, format, args);
|
len = vsnprintf(buffer, sizeof(buffer), format, args);
|
||||||
buffer[sizeof buffer - 1] = 0;
|
buffer[sizeof(buffer) - 1] = 0;
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
if(len < 0 || len > sizeof buffer - 1) {
|
if(len < 0 || (size_t)len > sizeof(buffer) - 1) {
|
||||||
logger(LOG_ERR, "Output buffer overflow while sending request to %s (%s)",
|
logger(LOG_ERR, "Output buffer overflow while sending request to %s (%s)",
|
||||||
c->name, c->hostname);
|
c->name, c->hostname);
|
||||||
return false;
|
return false;
|
||||||
|
@ -100,9 +101,10 @@ bool send_request(connection_t *c, const char *format, ...) {
|
||||||
if(c == everyone) {
|
if(c == everyone) {
|
||||||
broadcast_meta(NULL, buffer, len);
|
broadcast_meta(NULL, buffer, len);
|
||||||
return true;
|
return true;
|
||||||
} else
|
} else {
|
||||||
return send_meta(c, buffer, len);
|
return send_meta(c, buffer, len);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void forward_request(connection_t *from) {
|
void forward_request(connection_t *from) {
|
||||||
int request;
|
int request;
|
||||||
|
@ -175,8 +177,9 @@ static int past_request_compare(const past_request_t *a, const past_request_t *b
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_past_request(past_request_t *r) {
|
static void free_past_request(past_request_t *r) {
|
||||||
if(r->request)
|
if(r->request) {
|
||||||
free(r->request);
|
free(r->request);
|
||||||
|
}
|
||||||
|
|
||||||
free(r);
|
free(r);
|
||||||
}
|
}
|
||||||
|
@ -190,7 +193,7 @@ void exit_requests(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool seen_request(char *request) {
|
bool seen_request(char *request) {
|
||||||
past_request_t *new, p = {NULL};
|
past_request_t *new, p = {};
|
||||||
|
|
||||||
p.request = request;
|
p.request = request;
|
||||||
|
|
||||||
|
@ -215,11 +218,12 @@ void age_past_requests(void) {
|
||||||
next = node->next;
|
next = node->next;
|
||||||
p = node->data;
|
p = node->data;
|
||||||
|
|
||||||
if(p->firstseen + pinginterval <= now)
|
if(p->firstseen + pinginterval <= now) {
|
||||||
avl_delete_node(past_request_tree, node), deleted++;
|
avl_delete_node(past_request_tree, node), deleted++;
|
||||||
else
|
} else {
|
||||||
left++;
|
left++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(left || deleted)
|
if(left || deleted)
|
||||||
ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Aging past requests: deleted %d, left %d",
|
ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Aging past requests: deleted %d, left %d",
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_PROTOCOL_H
|
||||||
|
#define TINC_PROTOCOL_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
protocol.h -- header for protocol.c
|
protocol.h -- header for protocol.c
|
||||||
Copyright (C) 1999-2005 Ivo Timmermans,
|
Copyright (C) 1999-2005 Ivo Timmermans,
|
||||||
|
@ -18,9 +21,6 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TINC_PROTOCOL_H__
|
|
||||||
#define __TINC_PROTOCOL_H__
|
|
||||||
|
|
||||||
/* Protocol version. Different versions are incompatible,
|
/* Protocol version. Different versions are incompatible,
|
||||||
incompatible version have different protocols.
|
incompatible version have different protocols.
|
||||||
*/
|
*/
|
||||||
|
@ -71,56 +71,50 @@ extern bool strictsubnets;
|
||||||
|
|
||||||
/* Basic functions */
|
/* Basic functions */
|
||||||
|
|
||||||
extern bool send_request(struct connection_t *, const char *, ...) __attribute__ ((__format__(printf, 2, 3)));
|
extern bool send_request(struct connection_t *c, const char *format, ...) __attribute__((__format__(printf, 2, 3)));
|
||||||
extern void forward_request(struct connection_t *);
|
extern void forward_request(struct connection_t *c);
|
||||||
extern bool receive_request(struct connection_t *);
|
extern bool receive_request(struct connection_t *c);
|
||||||
extern bool check_id(const char *);
|
extern bool check_id(const char *name);
|
||||||
|
|
||||||
extern void init_requests(void);
|
extern void init_requests(void);
|
||||||
extern void exit_requests(void);
|
extern void exit_requests(void);
|
||||||
extern bool seen_request(char *);
|
extern bool seen_request(char *request);
|
||||||
extern void age_past_requests(void);
|
extern void age_past_requests(void);
|
||||||
|
|
||||||
/* Requests */
|
/* Requests */
|
||||||
|
|
||||||
extern bool send_id(struct connection_t *);
|
extern bool send_id(struct connection_t *c);
|
||||||
extern bool send_metakey(struct connection_t *);
|
extern bool send_metakey(struct connection_t *c);
|
||||||
extern bool send_challenge(struct connection_t *);
|
extern bool send_challenge(struct connection_t *c);
|
||||||
extern bool send_chal_reply(struct connection_t *);
|
extern bool send_chal_reply(struct connection_t *c);
|
||||||
extern bool send_ack(struct connection_t *);
|
extern bool send_ack(struct connection_t *c);
|
||||||
extern bool send_status(struct connection_t *, int, const char *);
|
extern bool send_ping(struct connection_t *c);
|
||||||
extern bool send_error(struct connection_t *, int,const char *);
|
extern bool send_pong(struct connection_t *c);
|
||||||
extern bool send_termreq(struct connection_t *);
|
extern bool send_add_subnet(struct connection_t *c, const struct subnet_t *subnet);
|
||||||
extern bool send_ping(struct connection_t *);
|
extern bool send_del_subnet(struct connection_t *c, const struct subnet_t *subnet);
|
||||||
extern bool send_pong(struct connection_t *);
|
extern bool send_add_edge(struct connection_t *c, const struct edge_t *e);
|
||||||
extern bool send_add_subnet(struct connection_t *, const struct subnet_t *);
|
extern bool send_del_edge(struct connection_t *c, const struct edge_t *e);
|
||||||
extern bool send_del_subnet(struct connection_t *, const struct subnet_t *);
|
|
||||||
extern bool send_add_edge(struct connection_t *, const struct edge_t *);
|
|
||||||
extern bool send_del_edge(struct connection_t *, const struct edge_t *);
|
|
||||||
extern void send_key_changed(void);
|
extern void send_key_changed(void);
|
||||||
extern bool send_req_key(struct node_t *);
|
extern bool send_req_key(struct node_t *n);
|
||||||
extern bool send_ans_key(struct node_t *);
|
extern bool send_ans_key(struct node_t *n);
|
||||||
extern bool send_tcppacket(struct connection_t *, const struct vpn_packet_t *);
|
extern bool send_tcppacket(struct connection_t *c, const struct vpn_packet_t *packet);
|
||||||
|
|
||||||
/* Request handlers */
|
/* Request handlers */
|
||||||
|
|
||||||
extern bool id_h(struct connection_t *);
|
extern bool id_h(struct connection_t *c);
|
||||||
extern bool metakey_h(struct connection_t *);
|
extern bool metakey_h(struct connection_t *c);
|
||||||
extern bool challenge_h(struct connection_t *);
|
extern bool challenge_h(struct connection_t *c);
|
||||||
extern bool chal_reply_h(struct connection_t *);
|
extern bool chal_reply_h(struct connection_t *c);
|
||||||
extern bool ack_h(struct connection_t *);
|
extern bool ack_h(struct connection_t *c);
|
||||||
extern bool status_h(struct connection_t *);
|
extern bool ping_h(struct connection_t *c);
|
||||||
extern bool error_h(struct connection_t *);
|
extern bool pong_h(struct connection_t *c);
|
||||||
extern bool termreq_h(struct connection_t *);
|
extern bool add_subnet_h(struct connection_t *c);
|
||||||
extern bool ping_h(struct connection_t *);
|
extern bool del_subnet_h(struct connection_t *c);
|
||||||
extern bool pong_h(struct connection_t *);
|
extern bool add_edge_h(struct connection_t *c);
|
||||||
extern bool add_subnet_h(struct connection_t *);
|
extern bool del_edge_h(struct connection_t *c);
|
||||||
extern bool del_subnet_h(struct connection_t *);
|
extern bool key_changed_h(struct connection_t *c);
|
||||||
extern bool add_edge_h(struct connection_t *);
|
extern bool req_key_h(struct connection_t *c);
|
||||||
extern bool del_edge_h(struct connection_t *);
|
extern bool ans_key_h(struct connection_t *c);
|
||||||
extern bool key_changed_h(struct connection_t *);
|
extern bool tcppacket_h(struct connection_t *c);
|
||||||
extern bool req_key_h(struct connection_t *);
|
|
||||||
extern bool ans_key_h(struct connection_t *);
|
|
||||||
extern bool tcppacket_h(struct connection_t *);
|
|
||||||
|
|
||||||
#endif /* __TINC_PROTOCOL_H__ */
|
#endif
|
||||||
|
|
|
@ -41,8 +41,9 @@
|
||||||
#include "xalloc.h"
|
#include "xalloc.h"
|
||||||
|
|
||||||
bool send_id(connection_t *c) {
|
bool send_id(connection_t *c) {
|
||||||
if(proxytype && c->outgoing && !c->status.proxy_passed)
|
if(proxytype && c->outgoing && !c->status.proxy_passed) {
|
||||||
return send_proxyrequest(c);
|
return send_proxyrequest(c);
|
||||||
|
}
|
||||||
|
|
||||||
return send_request(c, "%d %s %d", ID, myself->connection->name,
|
return send_request(c, "%d %s %d", ID, myself->connection->name,
|
||||||
myself->connection->protocol_version);
|
myself->connection->protocol_version);
|
||||||
|
@ -74,8 +75,10 @@ bool id_h(connection_t *c) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(c->name)
|
if(c->name) {
|
||||||
free(c->name);
|
free(c->name);
|
||||||
|
}
|
||||||
|
|
||||||
c->name = xstrdup(name);
|
c->name = xstrdup(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,8 +91,10 @@ bool id_h(connection_t *c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bypass_security) {
|
if(bypass_security) {
|
||||||
if(!c->config_tree)
|
if(!c->config_tree) {
|
||||||
init_configuration(&c->config_tree);
|
init_configuration(&c->config_tree);
|
||||||
|
}
|
||||||
|
|
||||||
c->allow_request = ACK;
|
c->allow_request = ACK;
|
||||||
return send_ack(c);
|
return send_ack(c);
|
||||||
}
|
}
|
||||||
|
@ -141,9 +146,11 @@ bool send_metakey(connection_t *c) {
|
||||||
|
|
||||||
if(!c->outctx) {
|
if(!c->outctx) {
|
||||||
c->outctx = EVP_CIPHER_CTX_new();
|
c->outctx = EVP_CIPHER_CTX_new();
|
||||||
if(!c->outctx)
|
|
||||||
|
if(!c->outctx) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy random data to the buffer */
|
/* Copy random data to the buffer */
|
||||||
|
|
||||||
|
@ -232,7 +239,7 @@ bool metakey_h(connection_t *c) {
|
||||||
|
|
||||||
/* Check if the length of the meta key is all right */
|
/* Check if the length of the meta key is all right */
|
||||||
|
|
||||||
if(strlen(buffer) != len * 2) {
|
if(strlen(buffer) != (size_t)len * 2) {
|
||||||
logger(LOG_ERR, "Possible intruder %s (%s): %s", c->name, c->hostname, "wrong keylength");
|
logger(LOG_ERR, "Possible intruder %s (%s): %s", c->name, c->hostname, "wrong keylength");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -243,9 +250,11 @@ bool metakey_h(connection_t *c) {
|
||||||
|
|
||||||
if(!c->inctx) {
|
if(!c->inctx) {
|
||||||
c->inctx = EVP_CIPHER_CTX_new();
|
c->inctx = EVP_CIPHER_CTX_new();
|
||||||
if(!c->inctx)
|
|
||||||
|
if(!c->inctx) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Convert the challenge from hexadecimal back to binary */
|
/* Convert the challenge from hexadecimal back to binary */
|
||||||
|
|
||||||
|
@ -363,7 +372,7 @@ bool challenge_h(connection_t *c) {
|
||||||
|
|
||||||
/* Check if the length of the challenge is all right */
|
/* Check if the length of the challenge is all right */
|
||||||
|
|
||||||
if(strlen(buffer) != len * 2) {
|
if(strlen(buffer) != (size_t)len * 2) {
|
||||||
logger(LOG_ERR, "Possible intruder %s (%s): %s", c->name,
|
logger(LOG_ERR, "Possible intruder %s (%s): %s", c->name,
|
||||||
c->hostname, "wrong challenge length");
|
c->hostname, "wrong challenge length");
|
||||||
return false;
|
return false;
|
||||||
|
@ -394,8 +403,10 @@ bool send_chal_reply(connection_t *c) {
|
||||||
/* Calculate the hash from the challenge we received */
|
/* Calculate the hash from the challenge we received */
|
||||||
|
|
||||||
ctx = EVP_MD_CTX_create();
|
ctx = EVP_MD_CTX_create();
|
||||||
if(!ctx)
|
|
||||||
|
if(!ctx) {
|
||||||
abort();
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
if(!EVP_DigestInit(ctx, c->indigest)
|
if(!EVP_DigestInit(ctx, c->indigest)
|
||||||
|| !EVP_DigestUpdate(ctx, c->mychallenge, RSA_size(myself->connection->rsa_key))
|
|| !EVP_DigestUpdate(ctx, c->mychallenge, RSA_size(myself->connection->rsa_key))
|
||||||
|
@ -431,7 +442,7 @@ bool chal_reply_h(connection_t *c) {
|
||||||
|
|
||||||
/* Check if the length of the hash is all right */
|
/* Check if the length of the hash is all right */
|
||||||
|
|
||||||
if(strlen(hishash) != EVP_MD_size(c->outdigest) * 2) {
|
if(strlen(hishash) != (size_t)EVP_MD_size(c->outdigest) * 2) {
|
||||||
logger(LOG_ERR, "Possible intruder %s (%s): %s", c->name,
|
logger(LOG_ERR, "Possible intruder %s (%s): %s", c->name,
|
||||||
c->hostname, "wrong challenge reply length");
|
c->hostname, "wrong challenge reply length");
|
||||||
return false;
|
return false;
|
||||||
|
@ -447,8 +458,10 @@ bool chal_reply_h(connection_t *c) {
|
||||||
/* Calculate the hash from the challenge we sent */
|
/* Calculate the hash from the challenge we sent */
|
||||||
|
|
||||||
ctx = EVP_MD_CTX_create();
|
ctx = EVP_MD_CTX_create();
|
||||||
if(!ctx)
|
|
||||||
|
if(!ctx) {
|
||||||
abort();
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
if(!EVP_DigestInit(ctx, c->outdigest)
|
if(!EVP_DigestInit(ctx, c->outdigest)
|
||||||
|| !EVP_DigestUpdate(ctx, c->hischallenge, RSA_size(c->rsa_key))
|
|| !EVP_DigestUpdate(ctx, c->hischallenge, RSA_size(c->rsa_key))
|
||||||
|
@ -499,19 +512,24 @@ bool send_ack(connection_t *c) {
|
||||||
|
|
||||||
/* Check some options */
|
/* Check some options */
|
||||||
|
|
||||||
if((get_config_bool(lookup_config(c->config_tree, "IndirectData"), &choice) && choice) || myself->options & OPTION_INDIRECT)
|
if((get_config_bool(lookup_config(c->config_tree, "IndirectData"), &choice) && choice) || myself->options & OPTION_INDIRECT) {
|
||||||
c->options |= OPTION_INDIRECT;
|
c->options |= OPTION_INDIRECT;
|
||||||
|
}
|
||||||
|
|
||||||
if((get_config_bool(lookup_config(c->config_tree, "TCPOnly"), &choice) && choice) || myself->options & OPTION_TCPONLY)
|
if((get_config_bool(lookup_config(c->config_tree, "TCPOnly"), &choice) && choice) || myself->options & OPTION_TCPONLY) {
|
||||||
c->options |= OPTION_TCPONLY | OPTION_INDIRECT;
|
c->options |= OPTION_TCPONLY | OPTION_INDIRECT;
|
||||||
|
}
|
||||||
|
|
||||||
if(myself->options & OPTION_PMTU_DISCOVERY)
|
if(myself->options & OPTION_PMTU_DISCOVERY && !(c->options & OPTION_TCPONLY)) {
|
||||||
c->options |= OPTION_PMTU_DISCOVERY;
|
c->options |= OPTION_PMTU_DISCOVERY;
|
||||||
|
}
|
||||||
|
|
||||||
choice = myself->options & OPTION_CLAMP_MSS;
|
choice = myself->options & OPTION_CLAMP_MSS;
|
||||||
get_config_bool(lookup_config(c->config_tree, "ClampMSS"), &choice);
|
get_config_bool(lookup_config(c->config_tree, "ClampMSS"), &choice);
|
||||||
if(choice)
|
|
||||||
|
if(choice) {
|
||||||
c->options |= OPTION_CLAMP_MSS;
|
c->options |= OPTION_CLAMP_MSS;
|
||||||
|
}
|
||||||
|
|
||||||
get_config_int(lookup_config(c->config_tree, "Weight"), &c->estimated_weight);
|
get_config_int(lookup_config(c->config_tree, "Weight"), &c->estimated_weight);
|
||||||
|
|
||||||
|
@ -584,24 +602,29 @@ bool ack_h(connection_t *c) {
|
||||||
|
|
||||||
n->connection = c;
|
n->connection = c;
|
||||||
c->node = n;
|
c->node = n;
|
||||||
|
|
||||||
if(!(c->options & options & OPTION_PMTU_DISCOVERY)) {
|
if(!(c->options & options & OPTION_PMTU_DISCOVERY)) {
|
||||||
c->options &= ~OPTION_PMTU_DISCOVERY;
|
c->options &= ~OPTION_PMTU_DISCOVERY;
|
||||||
options &= ~OPTION_PMTU_DISCOVERY;
|
options &= ~OPTION_PMTU_DISCOVERY;
|
||||||
}
|
}
|
||||||
|
|
||||||
c->options |= options;
|
c->options |= options;
|
||||||
|
|
||||||
if(get_config_int(lookup_config(c->config_tree, "PMTU"), &mtu) && mtu < n->mtu)
|
if(get_config_int(lookup_config(c->config_tree, "PMTU"), &mtu) && mtu < n->mtu) {
|
||||||
n->mtu = mtu;
|
n->mtu = mtu;
|
||||||
|
}
|
||||||
|
|
||||||
if(get_config_int(lookup_config(config_tree, "PMTU"), &mtu) && mtu < n->mtu)
|
if(get_config_int(lookup_config(config_tree, "PMTU"), &mtu) && mtu < n->mtu) {
|
||||||
n->mtu = mtu;
|
n->mtu = mtu;
|
||||||
|
}
|
||||||
|
|
||||||
if(get_config_bool(lookup_config(c->config_tree, "ClampMSS"), &choice)) {
|
if(get_config_bool(lookup_config(c->config_tree, "ClampMSS"), &choice)) {
|
||||||
if(choice)
|
if(choice) {
|
||||||
c->options |= OPTION_CLAMP_MSS;
|
c->options |= OPTION_CLAMP_MSS;
|
||||||
else
|
} else {
|
||||||
c->options &= ~OPTION_CLAMP_MSS;
|
c->options &= ~OPTION_CLAMP_MSS;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Activate this connection */
|
/* Activate this connection */
|
||||||
|
|
||||||
|
@ -630,10 +653,11 @@ bool ack_h(connection_t *c) {
|
||||||
|
|
||||||
/* Notify everyone of the new edge */
|
/* Notify everyone of the new edge */
|
||||||
|
|
||||||
if(tunnelserver)
|
if(tunnelserver) {
|
||||||
send_add_edge(c, c->edge);
|
send_add_edge(c, c->edge);
|
||||||
else
|
} else {
|
||||||
send_add_edge(everyone, c->edge);
|
send_add_edge(everyone, c->edge);
|
||||||
|
}
|
||||||
|
|
||||||
/* Run MST and SSSP algorithms */
|
/* Run MST and SSSP algorithms */
|
||||||
|
|
||||||
|
|
|
@ -76,8 +76,9 @@ bool add_edge_h(connection_t *c) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(seen_request(c->buffer))
|
if(seen_request(c->buffer)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Lookup nodes */
|
/* Lookup nodes */
|
||||||
|
|
||||||
|
@ -126,10 +127,12 @@ bool add_edge_h(connection_t *c) {
|
||||||
ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) which does not match existing entry",
|
ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) which does not match existing entry",
|
||||||
"ADD_EDGE", c->name, c->hostname);
|
"ADD_EDGE", c->name, c->hostname);
|
||||||
e->options = options;
|
e->options = options;
|
||||||
|
|
||||||
if(sockaddrcmp(&e->address, &address)) {
|
if(sockaddrcmp(&e->address, &address)) {
|
||||||
sockaddrfree(&e->address);
|
sockaddrfree(&e->address);
|
||||||
e->address = address;
|
e->address = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(e->weight != weight) {
|
if(e->weight != weight) {
|
||||||
avl_node_t *node = avl_unlink(edge_weight_tree, e);
|
avl_node_t *node = avl_unlink(edge_weight_tree, e);
|
||||||
e->weight = weight;
|
e->weight = weight;
|
||||||
|
@ -138,8 +141,9 @@ bool add_edge_h(connection_t *c) {
|
||||||
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
} else if(from == myself) {
|
} else if(from == myself) {
|
||||||
ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for ourself which does not exist",
|
ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for ourself which does not exist",
|
||||||
"ADD_EDGE", c->name, c->hostname);
|
"ADD_EDGE", c->name, c->hostname);
|
||||||
|
@ -163,8 +167,9 @@ bool add_edge_h(connection_t *c) {
|
||||||
done:
|
done:
|
||||||
/* Tell the rest about the new edge */
|
/* Tell the rest about the new edge */
|
||||||
|
|
||||||
if(!tunnelserver)
|
if(!tunnelserver) {
|
||||||
forward_request(c);
|
forward_request(c);
|
||||||
|
}
|
||||||
|
|
||||||
/* Run MST before or after we tell the rest? */
|
/* Run MST before or after we tell the rest? */
|
||||||
|
|
||||||
|
@ -198,8 +203,9 @@ bool del_edge_h(connection_t *c) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(seen_request(c->buffer))
|
if(seen_request(c->buffer)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Lookup nodes */
|
/* Lookup nodes */
|
||||||
|
|
||||||
|
@ -248,8 +254,9 @@ bool del_edge_h(connection_t *c) {
|
||||||
|
|
||||||
/* Tell the rest about the deleted edge */
|
/* Tell the rest about the deleted edge */
|
||||||
|
|
||||||
if(!tunnelserver)
|
if(!tunnelserver) {
|
||||||
forward_request(c);
|
forward_request(c);
|
||||||
|
}
|
||||||
|
|
||||||
/* Delete the edge */
|
/* Delete the edge */
|
||||||
|
|
||||||
|
@ -263,9 +270,12 @@ bool del_edge_h(connection_t *c) {
|
||||||
|
|
||||||
if(!to->status.reachable) {
|
if(!to->status.reachable) {
|
||||||
e = lookup_edge(to, myself);
|
e = lookup_edge(to, myself);
|
||||||
|
|
||||||
if(e) {
|
if(e) {
|
||||||
if(!tunnelserver)
|
if(!tunnelserver) {
|
||||||
send_del_edge(everyone, e);
|
send_del_edge(everyone, e);
|
||||||
|
}
|
||||||
|
|
||||||
edge_del(e);
|
edge_del(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,10 +46,12 @@ void send_key_changed(void) {
|
||||||
|
|
||||||
for(node = connection_tree->head; node; node = node->next) {
|
for(node = connection_tree->head; node; node = node->next) {
|
||||||
c = node->data;
|
c = node->data;
|
||||||
if(c->status.active && c->node && c->node->status.reachable)
|
|
||||||
|
if(c->status.active && c->node && c->node->status.reachable) {
|
||||||
send_ans_key(c->node);
|
send_ans_key(c->node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool key_changed_h(connection_t *c) {
|
bool key_changed_h(connection_t *c) {
|
||||||
char name[MAX_STRING_SIZE];
|
char name[MAX_STRING_SIZE];
|
||||||
|
@ -66,8 +68,9 @@ bool key_changed_h(connection_t *c) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(seen_request(c->buffer))
|
if(seen_request(c->buffer)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
n = lookup_node(name);
|
n = lookup_node(name);
|
||||||
|
|
||||||
|
@ -82,8 +85,9 @@ bool key_changed_h(connection_t *c) {
|
||||||
|
|
||||||
/* Tell the others */
|
/* Tell the others */
|
||||||
|
|
||||||
if(!tunnelserver)
|
if(!tunnelserver) {
|
||||||
forward_request(c);
|
forward_request(c);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -127,11 +131,13 @@ bool req_key_h(connection_t *c) {
|
||||||
/* Check if this key request is for us */
|
/* Check if this key request is for us */
|
||||||
|
|
||||||
if(to == myself) { /* Yes, send our own key back */
|
if(to == myself) { /* Yes, send our own key back */
|
||||||
if (!send_ans_key(from))
|
if(!send_ans_key(from)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if(tunnelserver)
|
if(tunnelserver) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if(!to->status.reachable) {
|
if(!to->status.reachable) {
|
||||||
logger(LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
|
logger(LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
|
||||||
|
@ -163,13 +169,17 @@ bool send_ans_key(node_t *to) {
|
||||||
return false; // Do not send insecure keys, let connection attempt fail.
|
return false; // Do not send insecure keys, let connection attempt fail.
|
||||||
}
|
}
|
||||||
|
|
||||||
if(to->incipher)
|
if(to->incipher) {
|
||||||
EVP_DecryptInit_ex(to->inctx, to->incipher, NULL, (unsigned char *)to->inkey, (unsigned char *)to->inkey + EVP_CIPHER_key_length(to->incipher));
|
EVP_DecryptInit_ex(to->inctx, to->incipher, NULL, (unsigned char *)to->inkey, (unsigned char *)to->inkey + EVP_CIPHER_key_length(to->incipher));
|
||||||
|
}
|
||||||
|
|
||||||
// Reset sequence number and late packet window
|
// Reset sequence number and late packet window
|
||||||
mykeyused = true;
|
mykeyused = true;
|
||||||
to->received_seqno = 0;
|
to->received_seqno = 0;
|
||||||
if(replaywin) memset(to->late, 0, replaywin);
|
|
||||||
|
if(replaywin) {
|
||||||
|
memset(to->late, 0, replaywin);
|
||||||
|
}
|
||||||
|
|
||||||
// Convert to hexadecimal and send
|
// Convert to hexadecimal and send
|
||||||
char key[2 * to->inkeylength + 1];
|
char key[2 * to->inkeylength + 1];
|
||||||
|
@ -224,8 +234,9 @@ bool ans_key_h(connection_t *c) {
|
||||||
/* Forward it if necessary */
|
/* Forward it if necessary */
|
||||||
|
|
||||||
if(to != myself) {
|
if(to != myself) {
|
||||||
if(tunnelserver)
|
if(tunnelserver) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if(!to->status.reachable) {
|
if(!to->status.reachable) {
|
||||||
logger(LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
|
logger(LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
|
||||||
|
@ -252,6 +263,7 @@ bool ans_key_h(connection_t *c) {
|
||||||
/* Update our copy of the origin's packet key */
|
/* Update our copy of the origin's packet key */
|
||||||
from->outkey = xrealloc(from->outkey, strlen(key) / 2);
|
from->outkey = xrealloc(from->outkey, strlen(key) / 2);
|
||||||
from->outkeylength = strlen(key) / 2;
|
from->outkeylength = strlen(key) / 2;
|
||||||
|
|
||||||
if(!hex2bin(key, from->outkey, from->outkeylength)) {
|
if(!hex2bin(key, from->outkey, from->outkeylength)) {
|
||||||
logger(LOG_ERR, "Got bad %s from %s(%s): %s", "ANS_KEY", from->name, from->hostname, "invalid key");
|
logger(LOG_ERR, "Got bad %s from %s(%s): %s", "ANS_KEY", from->name, from->hostname, "invalid key");
|
||||||
return true;
|
return true;
|
||||||
|
@ -320,8 +332,9 @@ bool ans_key_h(connection_t *c) {
|
||||||
update_node_udp(from, &sa);
|
update_node_udp(from, &sa);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(from->options & OPTION_PMTU_DISCOVERY && !from->mtuevent)
|
if(from->options & OPTION_PMTU_DISCOVERY && !from->mtuevent) {
|
||||||
send_mtu_probe(from);
|
send_mtu_probe(from);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,66 +31,6 @@
|
||||||
|
|
||||||
int maxoutbufsize = 0;
|
int maxoutbufsize = 0;
|
||||||
|
|
||||||
/* Status and error notification routines */
|
|
||||||
|
|
||||||
bool send_status(connection_t *c, int statusno, const char *statusstring) {
|
|
||||||
if(!statusstring)
|
|
||||||
statusstring = "Status";
|
|
||||||
|
|
||||||
return send_request(c, "%d %d %s", STATUS, statusno, statusstring);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool status_h(connection_t *c) {
|
|
||||||
int statusno;
|
|
||||||
char statusstring[MAX_STRING_SIZE];
|
|
||||||
|
|
||||||
if(sscanf(c->buffer, "%*d %d " MAX_STRING, &statusno, statusstring) != 2) {
|
|
||||||
logger(LOG_ERR, "Got bad %s from %s (%s)", "STATUS",
|
|
||||||
c->name, c->hostname);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ifdebug(STATUS) logger(LOG_NOTICE, "Status message from %s (%s): %d: %s",
|
|
||||||
c->name, c->hostname, statusno, statusstring);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool send_error(connection_t *c, int err, const char *errstring) {
|
|
||||||
if(!errstring)
|
|
||||||
errstring = "Error";
|
|
||||||
|
|
||||||
return send_request(c, "%d %d %s", ERROR, err, errstring);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool error_h(connection_t *c) {
|
|
||||||
int err;
|
|
||||||
char errorstring[MAX_STRING_SIZE];
|
|
||||||
|
|
||||||
if(sscanf(c->buffer, "%*d %d " MAX_STRING, &err, errorstring) != 2) {
|
|
||||||
logger(LOG_ERR, "Got bad %s from %s (%s)", "ERROR",
|
|
||||||
c->name, c->hostname);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ifdebug(ERROR) logger(LOG_NOTICE, "Error message from %s (%s): %d: %s",
|
|
||||||
c->name, c->hostname, err, errorstring);
|
|
||||||
|
|
||||||
terminate_connection(c, c->status.active);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool send_termreq(connection_t *c) {
|
|
||||||
return send_request(c, "%d", TERMREQ);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool termreq_h(connection_t *c) {
|
|
||||||
terminate_connection(c, c->status.active);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool send_ping(connection_t *c) {
|
bool send_ping(connection_t *c) {
|
||||||
c->status.pinged = true;
|
c->status.pinged = true;
|
||||||
c->last_ping_time = now;
|
c->last_ping_time = now;
|
||||||
|
@ -114,8 +54,11 @@ bool pong_h(connection_t *c) {
|
||||||
if(c->outgoing) {
|
if(c->outgoing) {
|
||||||
c->outgoing->timeout = 0;
|
c->outgoing->timeout = 0;
|
||||||
c->outgoing->cfg = NULL;
|
c->outgoing->cfg = NULL;
|
||||||
if(c->outgoing->ai)
|
|
||||||
|
if(c->outgoing->ai) {
|
||||||
freeaddrinfo(c->outgoing->ai);
|
freeaddrinfo(c->outgoing->ai);
|
||||||
|
}
|
||||||
|
|
||||||
c->outgoing->ai = NULL;
|
c->outgoing->ai = NULL;
|
||||||
c->outgoing->aip = NULL;
|
c->outgoing->aip = NULL;
|
||||||
}
|
}
|
||||||
|
@ -129,19 +72,21 @@ bool send_tcppacket(connection_t *c, const vpn_packet_t *packet) {
|
||||||
/* If there already is a lot of data in the outbuf buffer, discard this packet.
|
/* If there already is a lot of data in the outbuf buffer, discard this packet.
|
||||||
We use a very simple Random Early Drop algorithm. */
|
We use a very simple Random Early Drop algorithm. */
|
||||||
|
|
||||||
if(2.0 * c->outbuflen / (float)maxoutbufsize - 1 > (float)rand()/(float)RAND_MAX)
|
if(2.0 * c->outbuflen / (float)maxoutbufsize - 1 > (float)rand() / (float)RAND_MAX) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if(!send_request(c, "%d %hd", PACKET, packet->len))
|
if(!send_request(c, "%d %hd", PACKET, packet->len)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return send_meta(c, (char *)packet->data, packet->len) && flush_meta(c);
|
return send_meta(c, (char *)packet->data, packet->len) && flush_meta(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tcppacket_h(connection_t *c) {
|
bool tcppacket_h(connection_t *c) {
|
||||||
short int len;
|
length_t len;
|
||||||
|
|
||||||
if(sscanf(c->buffer, "%*d %hd", &len) != 1) {
|
if(sscanf(c->buffer, "%*d %hu", &len) != 1) {
|
||||||
logger(LOG_ERR, "Got bad %s from %s (%s)", "PACKET", c->name,
|
logger(LOG_ERR, "Got bad %s from %s (%s)", "PACKET", c->name,
|
||||||
c->hostname);
|
c->hostname);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -35,8 +35,9 @@
|
||||||
bool send_add_subnet(connection_t *c, const subnet_t *subnet) {
|
bool send_add_subnet(connection_t *c, const subnet_t *subnet) {
|
||||||
char netstr[MAXNETSTR];
|
char netstr[MAXNETSTR];
|
||||||
|
|
||||||
if(!net2str(netstr, sizeof netstr, subnet))
|
if(!net2str(netstr, sizeof(netstr), subnet)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return send_request(c, "%d %x %s %s", ADD_SUBNET, rand(), subnet->owner->name, netstr);
|
return send_request(c, "%d %x %s %s", ADD_SUBNET, rand(), subnet->owner->name, netstr);
|
||||||
}
|
}
|
||||||
|
@ -45,7 +46,7 @@ bool add_subnet_h(connection_t *c) {
|
||||||
char subnetstr[MAX_STRING_SIZE];
|
char subnetstr[MAX_STRING_SIZE];
|
||||||
char name[MAX_STRING_SIZE];
|
char name[MAX_STRING_SIZE];
|
||||||
node_t *owner;
|
node_t *owner;
|
||||||
subnet_t s = {NULL}, *new, *old;
|
subnet_t s = {}, *new, *old;
|
||||||
|
|
||||||
if(sscanf(c->buffer, "%*d %*x " MAX_STRING " " MAX_STRING, name, subnetstr) != 2) {
|
if(sscanf(c->buffer, "%*d %*x " MAX_STRING " " MAX_STRING, name, subnetstr) != 2) {
|
||||||
logger(LOG_ERR, "Got bad %s from %s (%s)", "ADD_SUBNET", c->name,
|
logger(LOG_ERR, "Got bad %s from %s (%s)", "ADD_SUBNET", c->name,
|
||||||
|
@ -69,8 +70,9 @@ bool add_subnet_h(connection_t *c) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(seen_request(c->buffer))
|
if(seen_request(c->buffer)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if the owner of the new subnet is in the connection list */
|
/* Check if the owner of the new subnet is in the connection list */
|
||||||
|
|
||||||
|
@ -91,8 +93,9 @@ bool add_subnet_h(connection_t *c) {
|
||||||
|
|
||||||
/* Check if we already know this subnet */
|
/* Check if we already know this subnet */
|
||||||
|
|
||||||
if(lookup_subnet(owner, &s))
|
if(lookup_subnet(owner, &s)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* If we don't know this subnet, but we are the owner, retaliate with a DEL_SUBNET */
|
/* If we don't know this subnet, but we are the owner, retaliate with a DEL_SUBNET */
|
||||||
|
|
||||||
|
@ -126,8 +129,9 @@ bool add_subnet_h(connection_t *c) {
|
||||||
*(new = new_subnet()) = s;
|
*(new = new_subnet()) = s;
|
||||||
subnet_add(owner, new);
|
subnet_add(owner, new);
|
||||||
|
|
||||||
if(owner->status.reachable)
|
if(owner->status.reachable) {
|
||||||
subnet_update(owner, new, true);
|
subnet_update(owner, new, true);
|
||||||
|
}
|
||||||
|
|
||||||
/* Tell the rest */
|
/* Tell the rest */
|
||||||
|
|
||||||
|
@ -135,8 +139,9 @@ bool add_subnet_h(connection_t *c) {
|
||||||
|
|
||||||
/* Fast handoff of roaming MAC addresses */
|
/* Fast handoff of roaming MAC addresses */
|
||||||
|
|
||||||
if(s.type == SUBNET_MAC && owner != myself && (old = lookup_subnet(myself, &s)) && old->expires)
|
if(s.type == SUBNET_MAC && owner != myself && (old = lookup_subnet(myself, &s)) && old->expires) {
|
||||||
old->expires = now;
|
old->expires = now;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -144,8 +149,9 @@ bool add_subnet_h(connection_t *c) {
|
||||||
bool send_del_subnet(connection_t *c, const subnet_t *s) {
|
bool send_del_subnet(connection_t *c, const subnet_t *s) {
|
||||||
char netstr[MAXNETSTR];
|
char netstr[MAXNETSTR];
|
||||||
|
|
||||||
if(!net2str(netstr, sizeof netstr, s))
|
if(!net2str(netstr, sizeof(netstr), s)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return send_request(c, "%d %x %s %s", DEL_SUBNET, rand(), s->owner->name, netstr);
|
return send_request(c, "%d %x %s %s", DEL_SUBNET, rand(), s->owner->name, netstr);
|
||||||
}
|
}
|
||||||
|
@ -154,7 +160,7 @@ bool del_subnet_h(connection_t *c) {
|
||||||
char subnetstr[MAX_STRING_SIZE];
|
char subnetstr[MAX_STRING_SIZE];
|
||||||
char name[MAX_STRING_SIZE];
|
char name[MAX_STRING_SIZE];
|
||||||
node_t *owner;
|
node_t *owner;
|
||||||
subnet_t s = {NULL}, *find;
|
subnet_t s = {}, *find;
|
||||||
|
|
||||||
if(sscanf(c->buffer, "%*d %*x " MAX_STRING " " MAX_STRING, name, subnetstr) != 2) {
|
if(sscanf(c->buffer, "%*d %*x " MAX_STRING " " MAX_STRING, name, subnetstr) != 2) {
|
||||||
logger(LOG_ERR, "Got bad %s from %s (%s)", "DEL_SUBNET", c->name,
|
logger(LOG_ERR, "Got bad %s from %s (%s)", "DEL_SUBNET", c->name,
|
||||||
|
@ -178,8 +184,9 @@ bool del_subnet_h(connection_t *c) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(seen_request(c->buffer))
|
if(seen_request(c->buffer)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if the owner of the subnet being deleted is in the connection list */
|
/* Check if the owner of the subnet being deleted is in the connection list */
|
||||||
|
|
||||||
|
@ -207,8 +214,11 @@ bool del_subnet_h(connection_t *c) {
|
||||||
if(!find) {
|
if(!find) {
|
||||||
ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for %s which does not appear in his subnet tree",
|
ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for %s which does not appear in his subnet tree",
|
||||||
"DEL_SUBNET", c->name, c->hostname, name);
|
"DEL_SUBNET", c->name, c->hostname, name);
|
||||||
if(strictsubnets)
|
|
||||||
|
if(strictsubnets) {
|
||||||
forward_request(c);
|
forward_request(c);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,19 +231,23 @@ bool del_subnet_h(connection_t *c) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tunnelserver)
|
if(tunnelserver) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Tell the rest */
|
/* Tell the rest */
|
||||||
|
|
||||||
forward_request(c);
|
forward_request(c);
|
||||||
if(strictsubnets)
|
|
||||||
|
if(strictsubnets) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Finally, delete it. */
|
/* Finally, delete it. */
|
||||||
|
|
||||||
if(owner->status.reachable)
|
if(owner->status.reachable) {
|
||||||
subnet_update(owner, find, false);
|
subnet_update(owner, find, false);
|
||||||
|
}
|
||||||
|
|
||||||
subnet_del(owner, find);
|
subnet_del(owner, find);
|
||||||
|
|
||||||
|
|
136
src/proxy.c
136
src/proxy.c
|
@ -35,29 +35,41 @@ char *proxypass;
|
||||||
|
|
||||||
static void update_address_ipv4(connection_t *c, void *address, void *port) {
|
static void update_address_ipv4(connection_t *c, void *address, void *port) {
|
||||||
sockaddrfree(&c->address);
|
sockaddrfree(&c->address);
|
||||||
memset(&c->address, 0, sizeof c->address);
|
memset(&c->address, 0, sizeof(c->address));
|
||||||
c->address.sa.sa_family = AF_INET;
|
c->address.sa.sa_family = AF_INET;
|
||||||
if(address)
|
|
||||||
|
if(address) {
|
||||||
memcpy(&c->address.in.sin_addr, address, sizeof(ipv4_t));
|
memcpy(&c->address.in.sin_addr, address, sizeof(ipv4_t));
|
||||||
if(port)
|
}
|
||||||
|
|
||||||
|
if(port) {
|
||||||
memcpy(&c->address.in.sin_port, port, sizeof(uint16_t));
|
memcpy(&c->address.in.sin_port, port, sizeof(uint16_t));
|
||||||
|
}
|
||||||
|
|
||||||
// OpenSSH -D returns all zero address, set it to 0.0.0.1 to prevent spamming ourselves.
|
// OpenSSH -D returns all zero address, set it to 0.0.0.1 to prevent spamming ourselves.
|
||||||
if(!memcmp(&c->address.in.sin_addr, "\0\0\0\0", 4))
|
if(!memcmp(&c->address.in.sin_addr, "\0\0\0\0", 4)) {
|
||||||
memcpy(&c->address.in.sin_addr, "\0\0\0\01", 4);
|
memcpy(&c->address.in.sin_addr, "\0\0\0\01", 4);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void update_address_ipv6(connection_t *c, void *address, void *port) {
|
static void update_address_ipv6(connection_t *c, void *address, void *port) {
|
||||||
sockaddrfree(&c->address);
|
sockaddrfree(&c->address);
|
||||||
memset(&c->address, 0, sizeof c->address);
|
memset(&c->address, 0, sizeof(c->address));
|
||||||
c->address.sa.sa_family = AF_INET6;
|
c->address.sa.sa_family = AF_INET6;
|
||||||
if(address)
|
|
||||||
|
if(address) {
|
||||||
memcpy(&c->address.in6.sin6_addr, address, sizeof(ipv6_t));
|
memcpy(&c->address.in6.sin6_addr, address, sizeof(ipv6_t));
|
||||||
if(port)
|
}
|
||||||
|
|
||||||
|
if(port) {
|
||||||
memcpy(&c->address.in6.sin6_port, port, sizeof(uint16_t));
|
memcpy(&c->address.in6.sin6_port, port, sizeof(uint16_t));
|
||||||
|
}
|
||||||
|
|
||||||
// OpenSSH -D returns all zero address, set it to 0100:: to prevent spamming ourselves.
|
// OpenSSH -D returns all zero address, set it to 0100:: to prevent spamming ourselves.
|
||||||
if(!memcmp(&c->address.in6.sin6_addr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16))
|
if(!memcmp(&c->address.in6.sin6_addr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16)) {
|
||||||
memcpy(&c->address.in6.sin6_addr, "\01\0\0\0\0\0\0\0", 8);
|
memcpy(&c->address.in6.sin6_addr, "\01\0\0\0\0\0\0\0", 8);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool send_proxyrequest(connection_t *c) {
|
bool send_proxyrequest(connection_t *c) {
|
||||||
switch(proxytype) {
|
switch(proxytype) {
|
||||||
|
@ -66,19 +78,28 @@ bool send_proxyrequest(connection_t *c) {
|
||||||
logger(LOG_ERR, "Can only connect to numeric IPv4 addresses through a SOCKS 4 proxy!");
|
logger(LOG_ERR, "Can only connect to numeric IPv4 addresses through a SOCKS 4 proxy!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fallthrough
|
||||||
case PROXY_SOCKS4A: {
|
case PROXY_SOCKS4A: {
|
||||||
if(c->address.sa.sa_family != AF_INET && c->address.sa.sa_family != AF_UNKNOWN) {
|
if(c->address.sa.sa_family != AF_INET && c->address.sa.sa_family != AF_UNKNOWN) {
|
||||||
logger(LOG_ERR, "Can only connect to IPv4 addresses or hostnames through a SOCKS 4a proxy!");
|
logger(LOG_ERR, "Can only connect to IPv4 addresses or hostnames through a SOCKS 4a proxy!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int len = 9;
|
int len = 9;
|
||||||
if(proxyuser)
|
|
||||||
|
if(proxyuser) {
|
||||||
len += strlen(proxyuser);
|
len += strlen(proxyuser);
|
||||||
if(c->address.sa.sa_family == AF_UNKNOWN)
|
}
|
||||||
|
|
||||||
|
if(c->address.sa.sa_family == AF_UNKNOWN) {
|
||||||
len += 1 + strlen(c->address.unknown.address);
|
len += 1 + strlen(c->address.unknown.address);
|
||||||
|
}
|
||||||
|
|
||||||
char s4req[len];
|
char s4req[len];
|
||||||
s4req[0] = 4;
|
s4req[0] = 4;
|
||||||
s4req[1] = 1;
|
s4req[1] = 1;
|
||||||
|
|
||||||
if(c->address.sa.sa_family == AF_INET) {
|
if(c->address.sa.sa_family == AF_INET) {
|
||||||
memcpy(s4req + 2, &c->address.in.sin_port, 2);
|
memcpy(s4req + 2, &c->address.in.sin_port, 2);
|
||||||
memcpy(s4req + 4, &c->address.in.sin_addr, 4);
|
memcpy(s4req + 4, &c->address.in.sin_addr, 4);
|
||||||
|
@ -88,17 +109,21 @@ bool send_proxyrequest(connection_t *c) {
|
||||||
memcpy(s4req + 4, "\0\0\0\1", 4);
|
memcpy(s4req + 4, "\0\0\0\1", 4);
|
||||||
strcpy(s4req + (9 + (proxyuser ? strlen(proxyuser) : 0)), c->address.unknown.address);
|
strcpy(s4req + (9 + (proxyuser ? strlen(proxyuser) : 0)), c->address.unknown.address);
|
||||||
}
|
}
|
||||||
if(proxyuser)
|
|
||||||
|
if(proxyuser) {
|
||||||
strcpy(s4req + 8, proxyuser);
|
strcpy(s4req + 8, proxyuser);
|
||||||
else
|
} else {
|
||||||
s4req[8] = 0;
|
s4req[8] = 0;
|
||||||
s4req[sizeof s4req - 1] = 0;
|
}
|
||||||
|
|
||||||
|
s4req[sizeof(s4req) - 1] = 0;
|
||||||
c->allow_request = PROXY;
|
c->allow_request = PROXY;
|
||||||
return send_meta(c, s4req, sizeof s4req);
|
return send_meta(c, s4req, sizeof(s4req));
|
||||||
}
|
}
|
||||||
|
|
||||||
case PROXY_SOCKS5: {
|
case PROXY_SOCKS5: {
|
||||||
int len = 3 + 6;
|
int len = 3 + 6;
|
||||||
|
|
||||||
if(c->address.sa.sa_family == AF_INET) {
|
if(c->address.sa.sa_family == AF_INET) {
|
||||||
len += 4;
|
len += 4;
|
||||||
} else if(c->address.sa.sa_family == AF_INET6) {
|
} else if(c->address.sa.sa_family == AF_INET6) {
|
||||||
|
@ -109,12 +134,16 @@ bool send_proxyrequest(connection_t *c) {
|
||||||
logger(LOG_ERR, "Address family %x not supported for SOCKS 5 proxies!", c->address.sa.sa_family);
|
logger(LOG_ERR, "Address family %x not supported for SOCKS 5 proxies!", c->address.sa.sa_family);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(proxypass)
|
|
||||||
|
if(proxypass) {
|
||||||
len += 3 + strlen(proxyuser) + strlen(proxypass);
|
len += 3 + strlen(proxyuser) + strlen(proxypass);
|
||||||
|
}
|
||||||
|
|
||||||
char s5req[len];
|
char s5req[len];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
s5req[i++] = 5;
|
s5req[i++] = 5;
|
||||||
s5req[i++] = 1;
|
s5req[i++] = 1;
|
||||||
|
|
||||||
if(proxypass) {
|
if(proxypass) {
|
||||||
s5req[i++] = 2;
|
s5req[i++] = 2;
|
||||||
s5req[i++] = 1;
|
s5req[i++] = 1;
|
||||||
|
@ -127,9 +156,11 @@ bool send_proxyrequest(connection_t *c) {
|
||||||
} else {
|
} else {
|
||||||
s5req[i++] = 0;
|
s5req[i++] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s5req[i++] = 5;
|
s5req[i++] = 5;
|
||||||
s5req[i++] = 1;
|
s5req[i++] = 1;
|
||||||
s5req[i++] = 0;
|
s5req[i++] = 0;
|
||||||
|
|
||||||
if(c->address.sa.sa_family == AF_INET) {
|
if(c->address.sa.sa_family == AF_INET) {
|
||||||
s5req[i++] = 1;
|
s5req[i++] = 1;
|
||||||
memcpy(s5req + i, &c->address.in.sin_addr, 4);
|
memcpy(s5req + i, &c->address.in.sin_addr, 4);
|
||||||
|
@ -155,10 +186,13 @@ bool send_proxyrequest(connection_t *c) {
|
||||||
logger(LOG_ERR, "Unknown address family while trying to connect to SOCKS5 proxy");
|
logger(LOG_ERR, "Unknown address family while trying to connect to SOCKS5 proxy");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(i > len)
|
|
||||||
|
if(i > len) {
|
||||||
abort();
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
c->allow_request = PROXY;
|
c->allow_request = PROXY;
|
||||||
return send_meta(c, s5req, sizeof s5req);
|
return send_meta(c, s5req, sizeof(s5req));
|
||||||
}
|
}
|
||||||
|
|
||||||
case PROXY_HTTP: {
|
case PROXY_HTTP: {
|
||||||
|
@ -182,15 +216,18 @@ bool send_proxyrequest(connection_t *c) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int receive_proxy_meta(connection_t *c, int start, int lenin) {
|
int receive_proxy_meta(connection_t *c) {
|
||||||
switch(proxytype) {
|
switch(proxytype) {
|
||||||
case PROXY_SOCKS4:
|
case PROXY_SOCKS4:
|
||||||
case PROXY_SOCKS4A:
|
case PROXY_SOCKS4A:
|
||||||
if(c->buflen < 8)
|
if(c->buflen < 8) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if(c->buffer[0] == 0 && c->buffer[1] == 0x5a) {
|
if(c->buffer[0] == 0 && c->buffer[1] == 0x5a) {
|
||||||
if(c->address.sa.sa_family == AF_UNKNOWN)
|
if(c->address.sa.sa_family == AF_UNKNOWN) {
|
||||||
update_address_ipv4(c, c->buffer + 4, c->buffer + 2);
|
update_address_ipv4(c, c->buffer + 4, c->buffer + 2);
|
||||||
|
}
|
||||||
|
|
||||||
ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Proxy request granted");
|
ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Proxy request granted");
|
||||||
c->allow_request = ID;
|
c->allow_request = ID;
|
||||||
|
@ -203,49 +240,71 @@ int receive_proxy_meta(connection_t *c, int start, int lenin) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case PROXY_SOCKS5:
|
case PROXY_SOCKS5:
|
||||||
if(c->buflen < 2)
|
if(c->buflen < 2) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if(c->buffer[0] != 0x05 || c->buffer[1] == (char)0xff) {
|
if(c->buffer[0] != 0x05 || c->buffer[1] == (char)0xff) {
|
||||||
logger(LOG_ERR, "Proxy authentication method rejected");
|
logger(LOG_ERR, "Proxy authentication method rejected");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int offset = 2;
|
int offset = 2;
|
||||||
|
|
||||||
if(c->buffer[1] == 0x02) {
|
if(c->buffer[1] == 0x02) {
|
||||||
if(c->buflen < 4)
|
if(c->buflen < 4) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if(c->buffer[2] != 0x05 || c->buffer[3] != 0x00) {
|
if(c->buffer[2] != 0x05 || c->buffer[3] != 0x00) {
|
||||||
logger(LOG_ERR, "Proxy username/password rejected");
|
logger(LOG_ERR, "Proxy username/password rejected");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += 2;
|
offset += 2;
|
||||||
}
|
}
|
||||||
if(c->buflen - offset < 7)
|
|
||||||
|
if(c->buflen - offset < 7) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if(c->buffer[offset] != 0x05 || c->buffer[offset + 1] != 0x00) {
|
if(c->buffer[offset] != 0x05 || c->buffer[offset + 1] != 0x00) {
|
||||||
logger(LOG_ERR, "Proxy request rejected");
|
logger(LOG_ERR, "Proxy request rejected");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int replen = offset + 6;
|
int replen = offset + 6;
|
||||||
|
|
||||||
switch(c->buffer[offset + 3]) {
|
switch(c->buffer[offset + 3]) {
|
||||||
case 0x01: // IPv4
|
case 0x01: // IPv4
|
||||||
if(c->address.sa.sa_family == AF_UNKNOWN)
|
if(c->address.sa.sa_family == AF_UNKNOWN) {
|
||||||
update_address_ipv4(c, c->buffer + offset + 4, c->buffer + offset + 8);
|
update_address_ipv4(c, c->buffer + offset + 4, c->buffer + offset + 8);
|
||||||
|
}
|
||||||
|
|
||||||
replen += 4;
|
replen += 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03: // Hostname
|
case 0x03: // Hostname
|
||||||
if(c->address.sa.sa_family == AF_UNKNOWN)
|
if(c->address.sa.sa_family == AF_UNKNOWN) {
|
||||||
update_address_ipv4(c, "\0\0\0\1", "\0\0");
|
update_address_ipv4(c, "\0\0\0\1", "\0\0");
|
||||||
|
}
|
||||||
|
|
||||||
replen += ((uint8_t *)c->buffer)[offset + 4];
|
replen += ((uint8_t *)c->buffer)[offset + 4];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x04: // IPv6
|
case 0x04: // IPv6
|
||||||
if(c->address.sa.sa_family == AF_UNKNOWN)
|
if(c->address.sa.sa_family == AF_UNKNOWN) {
|
||||||
update_address_ipv6(c, c->buffer + offset + 4, c->buffer + offset + 20);
|
update_address_ipv6(c, c->buffer + offset + 4, c->buffer + offset + 20);
|
||||||
|
}
|
||||||
|
|
||||||
replen += 16;
|
replen += 16;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
logger(LOG_ERR, "Proxy reply malformed");
|
logger(LOG_ERR, "Proxy reply malformed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(c->buflen < replen) {
|
if(c->buflen < replen) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -258,24 +317,31 @@ int receive_proxy_meta(connection_t *c, int start, int lenin) {
|
||||||
|
|
||||||
case PROXY_HTTP: {
|
case PROXY_HTTP: {
|
||||||
char *p = memchr(c->buffer, '\n', c->buflen);
|
char *p = memchr(c->buffer, '\n', c->buflen);
|
||||||
if(!p || p - c->buffer >= c->buflen)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
while((p = memchr(p + 1, '\n', c->buflen - (p + 1 - c->buffer)))) {
|
if(!p || p - c->buffer >= c->buflen) {
|
||||||
if(p > c->buffer + 3 && !memcmp(p - 3, "\r\n\r\n", 4))
|
return 0;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!p)
|
while((p = memchr(p + 1, '\n', c->buflen - (p + 1 - c->buffer)))) {
|
||||||
return 0;
|
if(p > c->buffer + 3 && !memcmp(p - 3, "\r\n\r\n", 4)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(c->buflen < 9)
|
if(!p) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(c->buflen < 9) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if(!strncasecmp(c->buffer, "HTTP/1.1 ", 9)) {
|
if(!strncasecmp(c->buffer, "HTTP/1.1 ", 9)) {
|
||||||
if(!strncmp(c->buffer + 9, "200", 3)) {
|
if(!strncmp(c->buffer + 9, "200", 3)) {
|
||||||
if(c->address.sa.sa_family == AF_UNKNOWN)
|
if(c->address.sa.sa_family == AF_UNKNOWN) {
|
||||||
update_address_ipv4(c, "\0\0\0\1", "\0\0");
|
update_address_ipv4(c, "\0\0\0\1", "\0\0");
|
||||||
|
}
|
||||||
|
|
||||||
logger(LOG_DEBUG, "Proxy request granted");
|
logger(LOG_DEBUG, "Proxy request granted");
|
||||||
replen = p + 1 - c->buffer;
|
replen = p + 1 - c->buffer;
|
||||||
c->allow_request = ID;
|
c->allow_request = ID;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_PROXY_H
|
||||||
|
#define TINC_PROXY_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
proxy.h -- header for proxy.c
|
proxy.h -- header for proxy.c
|
||||||
Copyright (C) 2015 Guus Sliepen <guus@tinc-vpn.org>
|
Copyright (C) 2015 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
@ -17,9 +20,6 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TINC_PROXY_H__
|
|
||||||
#define __TINC_PROXY_H__
|
|
||||||
|
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
|
||||||
typedef enum proxytype_t {
|
typedef enum proxytype_t {
|
||||||
|
@ -38,6 +38,6 @@ extern char *proxyuser;
|
||||||
extern char *proxypass;
|
extern char *proxypass;
|
||||||
|
|
||||||
extern bool send_proxyrequest(struct connection_t *c);
|
extern bool send_proxyrequest(struct connection_t *c);
|
||||||
extern int receive_proxy_meta(struct connection_t *c, int start, int lenin);
|
extern int receive_proxy_meta(struct connection_t *c);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
#include "xalloc.h"
|
#include "xalloc.h"
|
||||||
|
|
||||||
#if defined(PF_PACKET) && defined(ETH_P_ALL) && defined(AF_PACKET) && defined(SIOCGIFINDEX)
|
#if defined(PF_PACKET) && defined(ETH_P_ALL) && defined(AF_PACKET) && defined(SIOCGIFINDEX)
|
||||||
static char *device_info;
|
static const char *device_info = "raw_socket";
|
||||||
|
|
||||||
static uint64_t device_total_in = 0;
|
static uint64_t device_total_in = 0;
|
||||||
static uint64_t device_total_out = 0;
|
static uint64_t device_total_out = 0;
|
||||||
|
@ -42,13 +42,13 @@ static bool setup_device(void) {
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
struct sockaddr_ll sa;
|
struct sockaddr_ll sa;
|
||||||
|
|
||||||
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
|
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) {
|
||||||
iface = xstrdup("eth0");
|
iface = xstrdup("eth0");
|
||||||
|
}
|
||||||
|
|
||||||
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
|
if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
|
||||||
device = xstrdup(iface);
|
device = xstrdup(iface);
|
||||||
|
}
|
||||||
device_info = "raw socket";
|
|
||||||
|
|
||||||
if((device_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {
|
if((device_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {
|
||||||
logger(LOG_ERR, "Could not open %s: %s", device_info,
|
logger(LOG_ERR, "Could not open %s: %s", device_info,
|
||||||
|
|
254
src/route.c
254
src/route.c
|
@ -69,11 +69,13 @@ static uint16_t inet_checksum(void *data, int len, uint16_t prevsum) {
|
||||||
len -= 2;
|
len -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(len)
|
if(len) {
|
||||||
checksum += *(uint8_t *)p;
|
checksum += *(uint8_t *)p;
|
||||||
|
}
|
||||||
|
|
||||||
while(checksum >> 16)
|
while(checksum >> 16) {
|
||||||
checksum = (checksum & 0xFFFF) + (checksum >> 16);
|
checksum = (checksum & 0xFFFF) + (checksum >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
return ~checksum;
|
return ~checksum;
|
||||||
}
|
}
|
||||||
|
@ -83,8 +85,9 @@ static bool ratelimit(int frequency) {
|
||||||
static int count = 0;
|
static int count = 0;
|
||||||
|
|
||||||
if(lasttime == now) {
|
if(lasttime == now) {
|
||||||
if(count >= frequency)
|
if(count >= frequency) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
lasttime = now;
|
lasttime = now;
|
||||||
count = 0;
|
count = 0;
|
||||||
|
@ -98,29 +101,31 @@ static bool checklength(node_t *source, vpn_packet_t *packet, length_t length) {
|
||||||
if(packet->len < length) {
|
if(packet->len < length) {
|
||||||
ifdebug(TRAFFIC) logger(LOG_WARNING, "Got too short packet from %s (%s)", source->name, source->hostname);
|
ifdebug(TRAFFIC) logger(LOG_WARNING, "Got too short packet from %s (%s)", source->name, source->hostname);
|
||||||
return false;
|
return false;
|
||||||
} else
|
} else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void swap_mac_addresses(vpn_packet_t *packet) {
|
static void swap_mac_addresses(vpn_packet_t *packet) {
|
||||||
mac_t tmp;
|
mac_t tmp;
|
||||||
memcpy(&tmp, &packet->data[0], sizeof tmp);
|
memcpy(&tmp, &packet->data[0], sizeof(tmp));
|
||||||
memcpy(&packet->data[0], &packet->data[6], sizeof tmp);
|
memcpy(&packet->data[0], &packet->data[6], sizeof(tmp));
|
||||||
memcpy(&packet->data[6], &tmp, sizeof tmp);
|
memcpy(&packet->data[6], &tmp, sizeof(tmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RFC 792 */
|
/* RFC 792 */
|
||||||
|
|
||||||
static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, length_t ether_size, uint8_t type, uint8_t code) {
|
static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, length_t ether_size, uint8_t type, uint8_t code) {
|
||||||
struct ip ip = {0};
|
struct ip ip = {};
|
||||||
struct icmp icmp = {0};
|
struct icmp icmp = {};
|
||||||
|
|
||||||
struct in_addr ip_src;
|
struct in_addr ip_src;
|
||||||
struct in_addr ip_dst;
|
struct in_addr ip_dst;
|
||||||
uint32_t oldlen;
|
uint32_t oldlen;
|
||||||
|
|
||||||
if(ratelimit(3))
|
if(ratelimit(3)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Swap Ethernet source and destination addresses */
|
/* Swap Ethernet source and destination addresses */
|
||||||
|
|
||||||
|
@ -139,30 +144,36 @@ static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, length_
|
||||||
|
|
||||||
if(type == ICMP_TIME_EXCEEDED && code == ICMP_EXC_TTL) {
|
if(type == ICMP_TIME_EXCEEDED && code == ICMP_EXC_TTL) {
|
||||||
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
|
||||||
if(sockfd != -1) {
|
if(sockfd != -1) {
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_addr = ip.ip_src;
|
addr.sin_addr = ip.ip_src;
|
||||||
|
|
||||||
if(!connect(sockfd, (const struct sockaddr *) &addr, sizeof(addr))) {
|
if(!connect(sockfd, (const struct sockaddr *) &addr, sizeof(addr))) {
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
socklen_t addrlen = sizeof(addr);
|
socklen_t addrlen = sizeof(addr);
|
||||||
|
|
||||||
if(!getsockname(sockfd, (struct sockaddr *) &addr, &addrlen) && addrlen <= sizeof(addr)) {
|
if(!getsockname(sockfd, (struct sockaddr *) &addr, &addrlen) && addrlen <= sizeof(addr)) {
|
||||||
ip_dst = addr.sin_addr;
|
ip_dst = addr.sin_addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close(sockfd);
|
close(sockfd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
oldlen = packet->len - ether_size;
|
oldlen = packet->len - ether_size;
|
||||||
|
|
||||||
if(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
|
if(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
|
||||||
icmp.icmp_nextmtu = htons(packet->len - ether_size);
|
icmp.icmp_nextmtu = htons(packet->len - ether_size);
|
||||||
|
}
|
||||||
|
|
||||||
if(oldlen >= IP_MSS - ip_size - icmp_size)
|
if(oldlen >= IP_MSS - ip_size - icmp_size) {
|
||||||
oldlen = IP_MSS - ip_size - icmp_size;
|
oldlen = IP_MSS - ip_size - icmp_size;
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy first part of original contents to ICMP message */
|
/* Copy first part of original contents to ICMP message */
|
||||||
|
|
||||||
|
@ -207,7 +218,7 @@ static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, length_
|
||||||
|
|
||||||
static void route_ipv6_unreachable(node_t *source, vpn_packet_t *packet, length_t ether_size, uint8_t type, uint8_t code) {
|
static void route_ipv6_unreachable(node_t *source, vpn_packet_t *packet, length_t ether_size, uint8_t type, uint8_t code) {
|
||||||
struct ip6_hdr ip6;
|
struct ip6_hdr ip6;
|
||||||
struct icmp6_hdr icmp6 = {0};
|
struct icmp6_hdr icmp6 = {};
|
||||||
uint16_t checksum;
|
uint16_t checksum;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -217,8 +228,9 @@ static void route_ipv6_unreachable(node_t *source, vpn_packet_t *packet, length_
|
||||||
uint32_t next;
|
uint32_t next;
|
||||||
} pseudo;
|
} pseudo;
|
||||||
|
|
||||||
if(ratelimit(3))
|
if(ratelimit(3)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Swap Ethernet source and destination addresses */
|
/* Swap Ethernet source and destination addresses */
|
||||||
|
|
||||||
|
@ -237,30 +249,36 @@ static void route_ipv6_unreachable(node_t *source, vpn_packet_t *packet, length_
|
||||||
|
|
||||||
if(type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT) {
|
if(type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT) {
|
||||||
int sockfd = socket(AF_INET6, SOCK_DGRAM, 0);
|
int sockfd = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||||
|
|
||||||
if(sockfd != -1) {
|
if(sockfd != -1) {
|
||||||
struct sockaddr_in6 addr;
|
struct sockaddr_in6 addr;
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
addr.sin6_family = AF_INET6;
|
addr.sin6_family = AF_INET6;
|
||||||
addr.sin6_addr = ip6.ip6_src;
|
addr.sin6_addr = ip6.ip6_src;
|
||||||
|
|
||||||
if(!connect(sockfd, (const struct sockaddr *) &addr, sizeof(addr))) {
|
if(!connect(sockfd, (const struct sockaddr *) &addr, sizeof(addr))) {
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
addr.sin6_family = AF_INET6;
|
addr.sin6_family = AF_INET6;
|
||||||
socklen_t addrlen = sizeof(addr);
|
socklen_t addrlen = sizeof(addr);
|
||||||
|
|
||||||
if(!getsockname(sockfd, (struct sockaddr *) &addr, &addrlen) && addrlen <= sizeof(addr)) {
|
if(!getsockname(sockfd, (struct sockaddr *) &addr, &addrlen) && addrlen <= sizeof(addr)) {
|
||||||
pseudo.ip6_src = addr.sin6_addr;
|
pseudo.ip6_src = addr.sin6_addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close(sockfd);
|
close(sockfd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pseudo.length = packet->len - ether_size;
|
pseudo.length = packet->len - ether_size;
|
||||||
|
|
||||||
if(type == ICMP6_PACKET_TOO_BIG)
|
if(type == ICMP6_PACKET_TOO_BIG) {
|
||||||
icmp6.icmp6_mtu = htonl(pseudo.length);
|
icmp6.icmp6_mtu = htonl(pseudo.length);
|
||||||
|
}
|
||||||
|
|
||||||
if(pseudo.length >= IP_MSS - ip6_size - icmp6_size)
|
if(pseudo.length >= IP_MSS - ip6_size - icmp6_size) {
|
||||||
pseudo.length = IP_MSS - ip6_size - icmp6_size;
|
pseudo.length = IP_MSS - ip6_size - icmp6_size;
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy first part of original contents to ICMP message */
|
/* Copy first part of original contents to ICMP message */
|
||||||
|
|
||||||
|
@ -315,12 +333,15 @@ static bool do_decrement_ttl(node_t *source, vpn_packet_t *packet) {
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case ETH_P_IP:
|
case ETH_P_IP:
|
||||||
if(!checklength(source, packet, ethlen + ip_size))
|
if(!checklength(source, packet, ethlen + ip_size)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(packet->data[ethlen + 8] <= 1) {
|
if(packet->data[ethlen + 8] <= 1) {
|
||||||
if(packet->data[ethlen + 11] != IPPROTO_ICMP || packet->data[ethlen + 32] != ICMP_TIME_EXCEEDED)
|
if(packet->data[ethlen + 11] != IPPROTO_ICMP || packet->data[ethlen + 32] != ICMP_TIME_EXCEEDED) {
|
||||||
route_ipv4_unreachable(source, packet, ethlen, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL);
|
route_ipv4_unreachable(source, packet, ethlen, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL);
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,20 +351,26 @@ static bool do_decrement_ttl(node_t *source, vpn_packet_t *packet) {
|
||||||
|
|
||||||
uint32_t checksum = packet->data[ethlen + 10] << 8 | packet->data[ethlen + 11];
|
uint32_t checksum = packet->data[ethlen + 10] << 8 | packet->data[ethlen + 11];
|
||||||
checksum += old + (~new & 0xFFFF);
|
checksum += old + (~new & 0xFFFF);
|
||||||
while(checksum >> 16)
|
|
||||||
|
while(checksum >> 16) {
|
||||||
checksum = (checksum & 0xFFFF) + (checksum >> 16);
|
checksum = (checksum & 0xFFFF) + (checksum >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
packet->data[ethlen + 10] = checksum >> 8;
|
packet->data[ethlen + 10] = checksum >> 8;
|
||||||
packet->data[ethlen + 11] = checksum & 0xff;
|
packet->data[ethlen + 11] = checksum & 0xff;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case ETH_P_IPV6:
|
case ETH_P_IPV6:
|
||||||
if(!checklength(source, packet, ethlen + ip6_size))
|
if(!checklength(source, packet, ethlen + ip6_size)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(packet->data[ethlen + 7] <= 1) {
|
if(packet->data[ethlen + 7] <= 1) {
|
||||||
if(packet->data[ethlen + 6] != IPPROTO_ICMPV6 || packet->data[ethlen + 40] != ICMP6_TIME_EXCEEDED)
|
if(packet->data[ethlen + 6] != IPPROTO_ICMPV6 || packet->data[ethlen + 40] != ICMP6_TIME_EXCEEDED) {
|
||||||
route_ipv6_unreachable(source, packet, ethlen, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT);
|
route_ipv6_unreachable(source, packet, ethlen, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT);
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,12 +384,15 @@ static bool do_decrement_ttl(node_t *source, vpn_packet_t *packet) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *packet) {
|
static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *packet) {
|
||||||
if(!source || !via || !(via->options & OPTION_CLAMP_MSS))
|
if(!source || !via || !(via->options & OPTION_CLAMP_MSS)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t mtu = source->mtu;
|
uint16_t mtu = source->mtu;
|
||||||
if(via != myself && via->mtu < mtu)
|
|
||||||
|
if(via != myself && via->mtu < mtu) {
|
||||||
mtu = via->mtu;
|
mtu = via->mtu;
|
||||||
|
}
|
||||||
|
|
||||||
/* Find TCP header */
|
/* Find TCP header */
|
||||||
int start = ether_size;
|
int start = ether_size;
|
||||||
|
@ -373,52 +403,61 @@ static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *pac
|
||||||
type = packet->data[16] << 8 | packet->data[17];
|
type = packet->data[16] << 8 | packet->data[17];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type == ETH_P_IP && packet->data[start + 9] == 6)
|
if(type == ETH_P_IP && packet->data[start + 9] == 6) {
|
||||||
start += (packet->data[start] & 0xf) * 4;
|
start += (packet->data[start] & 0xf) * 4;
|
||||||
else if(type == ETH_P_IPV6 && packet->data[start + 6] == 6)
|
} else if(type == ETH_P_IPV6 && packet->data[start + 6] == 6) {
|
||||||
start += 40;
|
start += 40;
|
||||||
else
|
} else {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(packet->len <= start + 20)
|
if(packet->len <= start + 20) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Use data offset field to calculate length of options field */
|
/* Use data offset field to calculate length of options field */
|
||||||
int len = ((packet->data[start + 12] >> 4) - 5) * 4;
|
int len = ((packet->data[start + 12] >> 4) - 5) * 4;
|
||||||
|
|
||||||
if(packet->len < start + 20 + len)
|
if(packet->len < start + 20 + len) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Search for MSS option header */
|
/* Search for MSS option header */
|
||||||
for(int i = 0; i < len;) {
|
for(int i = 0; i < len;) {
|
||||||
if(packet->data[start + 20 + i] == 0)
|
if(packet->data[start + 20 + i] == 0) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if(packet->data[start + 20 + i] == 1) {
|
if(packet->data[start + 20 + i] == 1) {
|
||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(i > len - 2 || i > len - packet->data[start + 21 + i])
|
if(i > len - 2 || i > len - packet->data[start + 21 + i]) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if(packet->data[start + 20 + i] != 2) {
|
if(packet->data[start + 20 + i] != 2) {
|
||||||
if(packet->data[start + 21 + i] < 2)
|
if(packet->data[start + 21 + i] < 2) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
i += packet->data[start + 21 + i];
|
i += packet->data[start + 21 + i];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(packet->data[start + 21] != 4)
|
if(packet->data[start + 21] != 4) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Found it */
|
/* Found it */
|
||||||
uint16_t oldmss = packet->data[start + 22 + i] << 8 | packet->data[start + 23 + i];
|
uint16_t oldmss = packet->data[start + 22 + i] << 8 | packet->data[start + 23 + i];
|
||||||
uint16_t newmss = mtu - start - 20;
|
uint16_t newmss = mtu - start - 20;
|
||||||
uint32_t csum = packet->data[start + 16] << 8 | packet->data[start + 17];
|
uint32_t csum = packet->data[start + 16] << 8 | packet->data[start + 17];
|
||||||
|
|
||||||
if(oldmss <= newmss)
|
if(oldmss <= newmss) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ifdebug(TRAFFIC) logger(LOG_INFO, "Clamping MSS of packet from %s to %s to %d", source->name, via->name, newmss);
|
ifdebug(TRAFFIC) logger(LOG_INFO, "Clamping MSS of packet from %s to %s to %d", source->name, via->name, newmss);
|
||||||
|
|
||||||
|
@ -463,14 +502,17 @@ static void learn_mac(mac_t *address) {
|
||||||
|
|
||||||
for(node = connection_tree->head; node; node = node->next) {
|
for(node = connection_tree->head; node; node = node->next) {
|
||||||
c = node->data;
|
c = node->data;
|
||||||
if(c->status.active)
|
|
||||||
|
if(c->status.active) {
|
||||||
send_add_subnet(c, subnet);
|
send_add_subnet(c, subnet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(subnet->expires)
|
if(subnet->expires) {
|
||||||
subnet->expires = now + macexpire;
|
subnet->expires = now + macexpire;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void age_subnets(void) {
|
void age_subnets(void) {
|
||||||
subnet_t *s;
|
subnet_t *s;
|
||||||
|
@ -480,18 +522,23 @@ void age_subnets(void) {
|
||||||
for(node = myself->subnet_tree->head; node; node = next) {
|
for(node = myself->subnet_tree->head; node; node = next) {
|
||||||
next = node->next;
|
next = node->next;
|
||||||
s = node->data;
|
s = node->data;
|
||||||
|
|
||||||
if(s->expires && s->expires <= now) {
|
if(s->expires && s->expires <= now) {
|
||||||
ifdebug(TRAFFIC) {
|
ifdebug(TRAFFIC) {
|
||||||
char netstr[MAXNETSTR];
|
char netstr[MAXNETSTR];
|
||||||
if(net2str(netstr, sizeof netstr, s))
|
|
||||||
|
if(net2str(netstr, sizeof(netstr), s)) {
|
||||||
logger(LOG_INFO, "Subnet %s expired", netstr);
|
logger(LOG_INFO, "Subnet %s expired", netstr);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(node2 = connection_tree->head; node2; node2 = node2->next) {
|
for(node2 = connection_tree->head; node2; node2 = node2->next) {
|
||||||
c = node2->data;
|
c = node2->data;
|
||||||
if(c->status.active)
|
|
||||||
|
if(c->status.active) {
|
||||||
send_del_subnet(c, s);
|
send_del_subnet(c, s);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
subnet_update(myself, s, false);
|
subnet_update(myself, s, false);
|
||||||
subnet_del(myself, s);
|
subnet_del(myself, s);
|
||||||
|
@ -501,8 +548,9 @@ void age_subnets(void) {
|
||||||
|
|
||||||
static void route_broadcast(node_t *source, vpn_packet_t *packet) {
|
static void route_broadcast(node_t *source, vpn_packet_t *packet) {
|
||||||
if(decrement_ttl && source != myself)
|
if(decrement_ttl && source != myself)
|
||||||
if(!do_decrement_ttl(source, packet))
|
if(!do_decrement_ttl(source, packet)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
broadcast_packet(source, packet);
|
broadcast_packet(source, packet);
|
||||||
}
|
}
|
||||||
|
@ -519,8 +567,9 @@ static void fragment_ipv4_packet(node_t *dest, vpn_packet_t *packet, length_t et
|
||||||
memcpy(&ip, packet->data + ether_size, ip_size);
|
memcpy(&ip, packet->data + ether_size, ip_size);
|
||||||
fragment.priority = packet->priority;
|
fragment.priority = packet->priority;
|
||||||
|
|
||||||
if(ip.ip_hl != ip_size / 4)
|
if(ip.ip_hl != ip_size / 4) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
todo = ntohs(ip.ip_len) - ip_size;
|
todo = ntohs(ip.ip_len) - ip_size;
|
||||||
|
|
||||||
|
@ -562,7 +611,7 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) {
|
||||||
node_t *via;
|
node_t *via;
|
||||||
ipv4_t dest;
|
ipv4_t dest;
|
||||||
|
|
||||||
memcpy(&dest, &packet->data[30], sizeof dest);
|
memcpy(&dest, &packet->data[30], sizeof(dest));
|
||||||
subnet = lookup_subnet_ipv4(&dest);
|
subnet = lookup_subnet_ipv4(&dest);
|
||||||
|
|
||||||
if(!subnet) {
|
if(!subnet) {
|
||||||
|
@ -582,18 +631,22 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!subnet->owner->status.reachable)
|
if(!subnet->owner->status.reachable) {
|
||||||
return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_UNREACH);
|
return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_UNREACH);
|
||||||
|
}
|
||||||
|
|
||||||
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
|
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself) {
|
||||||
return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_ANO);
|
return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_ANO);
|
||||||
|
}
|
||||||
|
|
||||||
if(decrement_ttl && source != myself && subnet->owner != myself)
|
if(decrement_ttl && source != myself && subnet->owner != myself)
|
||||||
if(!do_decrement_ttl(source, packet))
|
if(!do_decrement_ttl(source, packet)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(priorityinheritance)
|
if(priorityinheritance) {
|
||||||
packet->priority = packet->data[15];
|
packet->priority = packet->data[15];
|
||||||
|
}
|
||||||
|
|
||||||
via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
|
via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
|
||||||
|
|
||||||
|
@ -602,11 +655,13 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(directonly && subnet->owner != via)
|
if(directonly && subnet->owner != via) {
|
||||||
return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_ANO);
|
return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_ANO);
|
||||||
|
}
|
||||||
|
|
||||||
if(via && packet->len > MAX(via->mtu, 590) && via != myself) {
|
if(via && packet->len > MAX(via->mtu, 590) && via != myself) {
|
||||||
ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
|
ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
|
||||||
|
|
||||||
if(packet->data[20] & 0x40) {
|
if(packet->data[20] & 0x40) {
|
||||||
packet->len = MAX(via->mtu, 590);
|
packet->len = MAX(via->mtu, 590);
|
||||||
route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED);
|
route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED);
|
||||||
|
@ -623,25 +678,27 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void route_ipv4(node_t *source, vpn_packet_t *packet) {
|
static void route_ipv4(node_t *source, vpn_packet_t *packet) {
|
||||||
if(!checklength(source, packet, ether_size + ip_size))
|
if(!checklength(source, packet, ether_size + ip_size)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(broadcast_mode && (((packet->data[30] & 0xf0) == 0xe0) || (
|
if(broadcast_mode && (((packet->data[30] & 0xf0) == 0xe0) || (
|
||||||
packet->data[30] == 255 &&
|
packet->data[30] == 255 &&
|
||||||
packet->data[31] == 255 &&
|
packet->data[31] == 255 &&
|
||||||
packet->data[32] == 255 &&
|
packet->data[32] == 255 &&
|
||||||
packet->data[33] == 255)))
|
packet->data[33] == 255))) {
|
||||||
route_broadcast(source, packet);
|
route_broadcast(source, packet);
|
||||||
else
|
} else {
|
||||||
route_ipv4_unicast(source, packet);
|
route_ipv4_unicast(source, packet);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) {
|
static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) {
|
||||||
subnet_t *subnet;
|
subnet_t *subnet;
|
||||||
node_t *via;
|
node_t *via;
|
||||||
ipv6_t dest;
|
ipv6_t dest;
|
||||||
|
|
||||||
memcpy(&dest, &packet->data[38], sizeof dest);
|
memcpy(&dest, &packet->data[38], sizeof(dest));
|
||||||
subnet = lookup_subnet_ipv6(&dest);
|
subnet = lookup_subnet_ipv6(&dest);
|
||||||
|
|
||||||
if(!subnet) {
|
if(!subnet) {
|
||||||
|
@ -665,18 +722,22 @@ static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!subnet->owner->status.reachable)
|
if(!subnet->owner->status.reachable) {
|
||||||
return route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE);
|
return route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE);
|
||||||
|
}
|
||||||
|
|
||||||
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
|
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself) {
|
||||||
return route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN);
|
return route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN);
|
||||||
|
}
|
||||||
|
|
||||||
if(decrement_ttl && source != myself && subnet->owner != myself)
|
if(decrement_ttl && source != myself && subnet->owner != myself)
|
||||||
if(!do_decrement_ttl(source, packet))
|
if(!do_decrement_ttl(source, packet)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(priorityinheritance)
|
if(priorityinheritance) {
|
||||||
packet->priority = ((packet->data[14] & 0x0f) << 4) | (packet->data[15] >> 4);
|
packet->priority = ((packet->data[14] & 0x0f) << 4) | (packet->data[15] >> 4);
|
||||||
|
}
|
||||||
|
|
||||||
via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
|
via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
|
||||||
|
|
||||||
|
@ -685,8 +746,9 @@ static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(directonly && subnet->owner != via)
|
if(directonly && subnet->owner != via) {
|
||||||
return route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN);
|
return route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN);
|
||||||
|
}
|
||||||
|
|
||||||
if(via && packet->len > MAX(via->mtu, 1294) && via != myself) {
|
if(via && packet->len > MAX(via->mtu, 1294) && via != myself) {
|
||||||
ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
|
ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
|
||||||
|
@ -717,8 +779,9 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet) {
|
||||||
uint32_t next;
|
uint32_t next;
|
||||||
} pseudo;
|
} pseudo;
|
||||||
|
|
||||||
if(!checklength(source, packet, ether_size + ip6_size + ns_size))
|
if(!checklength(source, packet, ether_size + ip6_size + ns_size)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
has_opt = packet->len >= ether_size + ip6_size + ns_size + opt_size + ETH_ALEN;
|
has_opt = packet->len >= ether_size + ip6_size + ns_size + opt_size + ETH_ALEN;
|
||||||
|
|
||||||
|
@ -731,13 +794,16 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet) {
|
||||||
|
|
||||||
memcpy(&ip6, packet->data + ether_size, ip6_size);
|
memcpy(&ip6, packet->data + ether_size, ip6_size);
|
||||||
memcpy(&ns, packet->data + ether_size + ip6_size, ns_size);
|
memcpy(&ns, packet->data + ether_size + ip6_size, ns_size);
|
||||||
if(has_opt)
|
|
||||||
|
if(has_opt) {
|
||||||
memcpy(&opt, packet->data + ether_size + ip6_size + ns_size, opt_size);
|
memcpy(&opt, packet->data + ether_size + ip6_size + ns_size, opt_size);
|
||||||
|
}
|
||||||
|
|
||||||
/* First, snatch the source address from the neighbor solicitation packet */
|
/* First, snatch the source address from the neighbor solicitation packet */
|
||||||
|
|
||||||
if(overwrite_mac)
|
if(overwrite_mac) {
|
||||||
memcpy(mymac.x, packet->data + ETH_ALEN, ETH_ALEN);
|
memcpy(mymac.x, packet->data + ETH_ALEN, ETH_ALEN);
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if this is a valid neighbor solicitation request */
|
/* Check if this is a valid neighbor solicitation request */
|
||||||
|
|
||||||
|
@ -751,16 +817,20 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet) {
|
||||||
|
|
||||||
pseudo.ip6_src = ip6.ip6_src;
|
pseudo.ip6_src = ip6.ip6_src;
|
||||||
pseudo.ip6_dst = ip6.ip6_dst;
|
pseudo.ip6_dst = ip6.ip6_dst;
|
||||||
if(has_opt)
|
|
||||||
|
if(has_opt) {
|
||||||
pseudo.length = htonl(ns_size + opt_size + ETH_ALEN);
|
pseudo.length = htonl(ns_size + opt_size + ETH_ALEN);
|
||||||
else
|
} else {
|
||||||
pseudo.length = htonl(ns_size);
|
pseudo.length = htonl(ns_size);
|
||||||
|
}
|
||||||
|
|
||||||
pseudo.next = htonl(IPPROTO_ICMPV6);
|
pseudo.next = htonl(IPPROTO_ICMPV6);
|
||||||
|
|
||||||
/* Generate checksum */
|
/* Generate checksum */
|
||||||
|
|
||||||
checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
|
checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
|
||||||
checksum = inet_checksum(&ns, ns_size, checksum);
|
checksum = inet_checksum(&ns, ns_size, checksum);
|
||||||
|
|
||||||
if(has_opt) {
|
if(has_opt) {
|
||||||
checksum = inet_checksum(&opt, opt_size, checksum);
|
checksum = inet_checksum(&opt, opt_size, checksum);
|
||||||
checksum = inet_checksum(packet->data + ether_size + ip6_size + ns_size + opt_size, ETH_ALEN, checksum);
|
checksum = inet_checksum(packet->data + ether_size + ip6_size + ns_size + opt_size, ETH_ALEN, checksum);
|
||||||
|
@ -791,12 +861,14 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet) {
|
||||||
|
|
||||||
/* Check if it is for our own subnet */
|
/* Check if it is for our own subnet */
|
||||||
|
|
||||||
if(subnet->owner == myself)
|
if(subnet->owner == myself) {
|
||||||
return; /* silently ignore */
|
return; /* silently ignore */
|
||||||
|
}
|
||||||
|
|
||||||
if(decrement_ttl)
|
if(decrement_ttl)
|
||||||
if(!do_decrement_ttl(source, packet))
|
if(!do_decrement_ttl(source, packet)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create neighbor advertation reply */
|
/* Create neighbor advertation reply */
|
||||||
|
|
||||||
|
@ -806,8 +878,9 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet) {
|
||||||
ip6.ip6_dst = ip6.ip6_src; /* swap destination and source protocoll address */
|
ip6.ip6_dst = ip6.ip6_src; /* swap destination and source protocoll address */
|
||||||
ip6.ip6_src = ns.nd_ns_target;
|
ip6.ip6_src = ns.nd_ns_target;
|
||||||
|
|
||||||
if(has_opt)
|
if(has_opt) {
|
||||||
memcpy(packet->data + ether_size + ip6_size + ns_size + opt_size, packet->data + ETH_ALEN, ETH_ALEN); /* add fake source hard addr */
|
memcpy(packet->data + ether_size + ip6_size + ns_size + opt_size, packet->data + ETH_ALEN, ETH_ALEN); /* add fake source hard addr */
|
||||||
|
}
|
||||||
|
|
||||||
ns.nd_ns_cksum = 0;
|
ns.nd_ns_cksum = 0;
|
||||||
ns.nd_ns_type = ND_NEIGHBOR_ADVERT;
|
ns.nd_ns_type = ND_NEIGHBOR_ADVERT;
|
||||||
|
@ -818,16 +891,20 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet) {
|
||||||
|
|
||||||
pseudo.ip6_src = ip6.ip6_src;
|
pseudo.ip6_src = ip6.ip6_src;
|
||||||
pseudo.ip6_dst = ip6.ip6_dst;
|
pseudo.ip6_dst = ip6.ip6_dst;
|
||||||
if(has_opt)
|
|
||||||
|
if(has_opt) {
|
||||||
pseudo.length = htonl(ns_size + opt_size + ETH_ALEN);
|
pseudo.length = htonl(ns_size + opt_size + ETH_ALEN);
|
||||||
else
|
} else {
|
||||||
pseudo.length = htonl(ns_size);
|
pseudo.length = htonl(ns_size);
|
||||||
|
}
|
||||||
|
|
||||||
pseudo.next = htonl(IPPROTO_ICMPV6);
|
pseudo.next = htonl(IPPROTO_ICMPV6);
|
||||||
|
|
||||||
/* Generate checksum */
|
/* Generate checksum */
|
||||||
|
|
||||||
checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
|
checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
|
||||||
checksum = inet_checksum(&ns, ns_size, checksum);
|
checksum = inet_checksum(&ns, ns_size, checksum);
|
||||||
|
|
||||||
if(has_opt) {
|
if(has_opt) {
|
||||||
checksum = inet_checksum(&opt, opt_size, checksum);
|
checksum = inet_checksum(&opt, opt_size, checksum);
|
||||||
checksum = inet_checksum(packet->data + ether_size + ip6_size + ns_size + opt_size, ETH_ALEN, checksum);
|
checksum = inet_checksum(packet->data + ether_size + ip6_size + ns_size + opt_size, ETH_ALEN, checksum);
|
||||||
|
@ -839,26 +916,30 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet) {
|
||||||
|
|
||||||
memcpy(packet->data + ether_size, &ip6, ip6_size);
|
memcpy(packet->data + ether_size, &ip6, ip6_size);
|
||||||
memcpy(packet->data + ether_size + ip6_size, &ns, ns_size);
|
memcpy(packet->data + ether_size + ip6_size, &ns, ns_size);
|
||||||
if(has_opt)
|
|
||||||
|
if(has_opt) {
|
||||||
memcpy(packet->data + ether_size + ip6_size + ns_size, &opt, opt_size);
|
memcpy(packet->data + ether_size + ip6_size + ns_size, &opt, opt_size);
|
||||||
|
}
|
||||||
|
|
||||||
send_packet(source, packet);
|
send_packet(source, packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void route_ipv6(node_t *source, vpn_packet_t *packet) {
|
static void route_ipv6(node_t *source, vpn_packet_t *packet) {
|
||||||
if(!checklength(source, packet, ether_size + ip6_size))
|
if(!checklength(source, packet, ether_size + ip6_size)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(packet->data[20] == IPPROTO_ICMPV6 && checklength(source, packet, ether_size + ip6_size + icmp6_size) && packet->data[54] == ND_NEIGHBOR_SOLICIT) {
|
if(packet->data[20] == IPPROTO_ICMPV6 && checklength(source, packet, ether_size + ip6_size + icmp6_size) && packet->data[54] == ND_NEIGHBOR_SOLICIT) {
|
||||||
route_neighborsol(source, packet);
|
route_neighborsol(source, packet);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(broadcast_mode && packet->data[38] == 255)
|
if(broadcast_mode && packet->data[38] == 255) {
|
||||||
route_broadcast(source, packet);
|
route_broadcast(source, packet);
|
||||||
else
|
} else {
|
||||||
route_ipv6_unicast(source, packet);
|
route_ipv6_unicast(source, packet);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* RFC 826 */
|
/* RFC 826 */
|
||||||
|
|
||||||
|
@ -867,8 +948,9 @@ static void route_arp(node_t *source, vpn_packet_t *packet) {
|
||||||
subnet_t *subnet;
|
subnet_t *subnet;
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
|
|
||||||
if(!checklength(source, packet, ether_size + arp_size))
|
if(!checklength(source, packet, ether_size + arp_size)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(source != myself) {
|
if(source != myself) {
|
||||||
ifdebug(TRAFFIC) logger(LOG_WARNING, "Got ARP request from %s (%s) while in router mode!", source->name, source->hostname);
|
ifdebug(TRAFFIC) logger(LOG_WARNING, "Got ARP request from %s (%s) while in router mode!", source->name, source->hostname);
|
||||||
|
@ -877,8 +959,9 @@ static void route_arp(node_t *source, vpn_packet_t *packet) {
|
||||||
|
|
||||||
/* First, snatch the source address from the ARP packet */
|
/* First, snatch the source address from the ARP packet */
|
||||||
|
|
||||||
if(overwrite_mac)
|
if(overwrite_mac) {
|
||||||
memcpy(mymac.x, packet->data + ETH_ALEN, ETH_ALEN);
|
memcpy(mymac.x, packet->data + ETH_ALEN, ETH_ALEN);
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy headers from packet to structs on the stack */
|
/* Copy headers from packet to structs on the stack */
|
||||||
|
|
||||||
|
@ -905,12 +988,14 @@ static void route_arp(node_t *source, vpn_packet_t *packet) {
|
||||||
|
|
||||||
/* Check if it is for our own subnet */
|
/* Check if it is for our own subnet */
|
||||||
|
|
||||||
if(subnet->owner == myself)
|
if(subnet->owner == myself) {
|
||||||
return; /* silently ignore */
|
return; /* silently ignore */
|
||||||
|
}
|
||||||
|
|
||||||
if(decrement_ttl)
|
if(decrement_ttl)
|
||||||
if(!do_decrement_ttl(source, packet))
|
if(!do_decrement_ttl(source, packet)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(packet->data, packet->data + ETH_ALEN, ETH_ALEN); /* copy destination address */
|
memcpy(packet->data, packet->data + ETH_ALEN, ETH_ALEN); /* copy destination address */
|
||||||
packet->data[ETH_ALEN * 2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
|
packet->data[ETH_ALEN * 2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
|
||||||
|
@ -938,13 +1023,13 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
|
||||||
|
|
||||||
if(source == myself) {
|
if(source == myself) {
|
||||||
mac_t src;
|
mac_t src;
|
||||||
memcpy(&src, &packet->data[6], sizeof src);
|
memcpy(&src, &packet->data[6], sizeof(src));
|
||||||
learn_mac(&src);
|
learn_mac(&src);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lookup destination address */
|
/* Lookup destination address */
|
||||||
|
|
||||||
memcpy(&dest, &packet->data[0], sizeof dest);
|
memcpy(&dest, &packet->data[0], sizeof(dest));
|
||||||
subnet = lookup_subnet_mac(NULL, &dest);
|
subnet = lookup_subnet_mac(NULL, &dest);
|
||||||
|
|
||||||
if(!subnet) {
|
if(!subnet) {
|
||||||
|
@ -957,28 +1042,32 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
|
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(decrement_ttl && source != myself && subnet->owner != myself)
|
if(decrement_ttl && source != myself && subnet->owner != myself)
|
||||||
if(!do_decrement_ttl(source, packet))
|
if(!do_decrement_ttl(source, packet)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t type = packet->data[12] << 8 | packet->data[13];
|
uint16_t type = packet->data[12] << 8 | packet->data[13];
|
||||||
|
|
||||||
if(priorityinheritance) {
|
if(priorityinheritance) {
|
||||||
if(type == ETH_P_IP && packet->len >= ether_size + ip_size)
|
if(type == ETH_P_IP && packet->len >= ether_size + ip_size) {
|
||||||
packet->priority = packet->data[15];
|
packet->priority = packet->data[15];
|
||||||
else if(type == ETH_P_IPV6 && packet->len >= ether_size + ip6_size)
|
} else if(type == ETH_P_IPV6 && packet->len >= ether_size + ip6_size) {
|
||||||
packet->priority = ((packet->data[14] & 0x0f) << 4) | (packet->data[15] >> 4);
|
packet->priority = ((packet->data[14] & 0x0f) << 4) | (packet->data[15] >> 4);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handle packets larger than PMTU
|
// Handle packets larger than PMTU
|
||||||
|
|
||||||
node_t *via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
|
node_t *via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
|
||||||
|
|
||||||
if(directonly && subnet->owner != via)
|
if(directonly && subnet->owner != via) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(via && packet->len > via->mtu && via != myself) {
|
if(via && packet->len > via->mtu && via != myself) {
|
||||||
ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
|
ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
|
||||||
|
@ -996,6 +1085,7 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
|
||||||
} else {
|
} else {
|
||||||
fragment_ipv4_packet(via, packet, ethlen);
|
fragment_ipv4_packet(via, packet, ethlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else if(type == ETH_P_IPV6 && packet->len > 1280 + ethlen) {
|
} else if(type == ETH_P_IPV6 && packet->len > 1280 + ethlen) {
|
||||||
packet->len = via->mtu;
|
packet->len = via->mtu;
|
||||||
|
@ -1015,12 +1105,12 @@ void route(node_t *source, vpn_packet_t *packet) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!checklength(source, packet, ether_size))
|
if(!checklength(source, packet, ether_size)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch(routing_mode) {
|
switch(routing_mode) {
|
||||||
case RMODE_ROUTER:
|
case RMODE_ROUTER: {
|
||||||
{
|
|
||||||
uint16_t type = packet->data[12] << 8 | packet->data[13];
|
uint16_t type = packet->data[12] << 8 | packet->data[13];
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
|
|
10
src/route.h
10
src/route.h
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_ROUTE_H
|
||||||
|
#define TINC_ROUTE_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
route.h -- header file for route.c
|
route.h -- header file for route.c
|
||||||
Copyright (C) 2000-2005 Ivo Timmermans
|
Copyright (C) 2000-2005 Ivo Timmermans
|
||||||
|
@ -18,9 +21,6 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TINC_ROUTE_H__
|
|
||||||
#define __TINC_ROUTE_H__
|
|
||||||
|
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
|
|
||||||
|
@ -54,6 +54,6 @@ extern int macexpire;
|
||||||
extern mac_t mymac;
|
extern mac_t mymac;
|
||||||
|
|
||||||
extern void age_subnets(void);
|
extern void age_subnets(void);
|
||||||
extern void route(struct node_t *, struct vpn_packet_t *);
|
extern void route(struct node_t *source, struct vpn_packet_t *packet);
|
||||||
|
|
||||||
#endif /* __TINC_ROUTE_H__ */
|
#endif
|
||||||
|
|
|
@ -53,7 +53,7 @@ static int if_fd = -1;
|
||||||
static int ip_fd = -1;
|
static int ip_fd = -1;
|
||||||
char *device = NULL;
|
char *device = NULL;
|
||||||
char *iface = NULL;
|
char *iface = NULL;
|
||||||
static char *device_info = NULL;
|
static const char *device_info = NULL;
|
||||||
|
|
||||||
uint64_t device_total_in = 0;
|
uint64_t device_total_in = 0;
|
||||||
uint64_t device_total_out = 0;
|
uint64_t device_total_out = 0;
|
||||||
|
@ -62,33 +62,37 @@ static bool setup_device(void) {
|
||||||
char *type;
|
char *type;
|
||||||
|
|
||||||
if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
|
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);
|
device = xstrdup(DEFAULT_TUN_DEVICE);
|
||||||
else
|
} else {
|
||||||
device = xstrdup(DEFAULT_TAP_DEVICE);
|
device = xstrdup(DEFAULT_TAP_DEVICE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
|
if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
|
||||||
if(!strcasecmp(type, "tun"))
|
if(!strcasecmp(type, "tun"))
|
||||||
/* use default */;
|
/* use default */;
|
||||||
else if(!strcasecmp(type, "tap"))
|
else if(!strcasecmp(type, "tap")) {
|
||||||
device_type = DEVICE_TYPE_TAP;
|
device_type = DEVICE_TYPE_TAP;
|
||||||
else {
|
} else {
|
||||||
logger(LOG_ERR, "Unknown device type %s!", type);
|
logger(LOG_ERR, "Unknown device type %s!", type);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(strstr(device, "tap") || routing_mode != RMODE_ROUTER)
|
if(strstr(device, "tap") || routing_mode != RMODE_ROUTER) {
|
||||||
device_type = DEVICE_TYPE_TAP;
|
device_type = DEVICE_TYPE_TAP;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(device_type == DEVICE_TYPE_TUN)
|
if(device_type == DEVICE_TYPE_TUN) {
|
||||||
device_info = "Solaris tun device";
|
device_info = "Solaris tun device";
|
||||||
else
|
} else {
|
||||||
device_info = "Solaris tap device";
|
device_info = "Solaris tap device";
|
||||||
|
}
|
||||||
|
|
||||||
if(device_type == DEVICE_TYPE_TAP && routing_mode == RMODE_ROUTER)
|
if(device_type == DEVICE_TYPE_TAP && routing_mode == RMODE_ROUTER) {
|
||||||
overwrite_mac = true;
|
overwrite_mac = true;
|
||||||
|
}
|
||||||
|
|
||||||
/* The following is black magic copied from OpenVPN. */
|
/* The following is black magic copied from OpenVPN. */
|
||||||
|
|
||||||
|
@ -107,29 +111,35 @@ static bool setup_device(void) {
|
||||||
char *ptr = device;
|
char *ptr = device;
|
||||||
get_config_string(lookup_config(config_tree, "Interface"), &ptr);
|
get_config_string(lookup_config(config_tree, "Interface"), &ptr);
|
||||||
|
|
||||||
while(*ptr && !isdigit(*ptr))
|
while(*ptr && !isdigit(*ptr)) {
|
||||||
ptr++;
|
ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
int ppa = atoi(ptr);
|
int ppa = atoi(ptr);
|
||||||
|
|
||||||
/* Assign a new PPA and get its unit number. */
|
/* Assign a new PPA and get its unit number. */
|
||||||
|
|
||||||
struct strioctl strioc_ppa = {
|
struct strioctl strioc_ppa = {
|
||||||
.ic_cmd = TUNNEWPPA,
|
.ic_cmd = TUNNEWPPA,
|
||||||
.ic_len = sizeof ppa,
|
.ic_len = sizeof(ppa),
|
||||||
.ic_dp = (char *) &ppa,
|
.ic_dp = (char *) &ppa,
|
||||||
};
|
};
|
||||||
|
|
||||||
if(!*ptr) { /* no number given, try dynamic */
|
if(!*ptr) { /* no number given, try dynamic */
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
while(!found && ppa < 64) {
|
while(!found && ppa < 64) {
|
||||||
int new_ppa = ioctl(device_fd, I_STR, &strioc_ppa);
|
int new_ppa = ioctl(device_fd, I_STR, &strioc_ppa);
|
||||||
|
|
||||||
if(new_ppa >= 0) {
|
if(new_ppa >= 0) {
|
||||||
ppa = new_ppa;
|
ppa = new_ppa;
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ppa++;
|
ppa++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!found) {
|
if(!found) {
|
||||||
logger(LOG_ERR, "Could not find free PPA for %s %s!", device_info, device);
|
logger(LOG_ERR, "Could not find free PPA for %s %s!", device_info, device);
|
||||||
return false;
|
return false;
|
||||||
|
@ -156,7 +166,8 @@ static bool setup_device(void) {
|
||||||
{
|
{
|
||||||
/* Remove muxes just in case they are left over from a crashed tincd */
|
/* Remove muxes just in case they are left over from a crashed tincd */
|
||||||
struct lifreq ifr = {};
|
struct lifreq ifr = {};
|
||||||
strncpy(ifr.lifr_name, iface, sizeof ifr.lifr_name);
|
strncpy(ifr.lifr_name, iface, sizeof(ifr.lifr_name));
|
||||||
|
|
||||||
if(ioctl(ip_fd, SIOCGLIFMUXID, &ifr) >= 0) {
|
if(ioctl(ip_fd, SIOCGLIFMUXID, &ifr) >= 0) {
|
||||||
int muxid = ifr.lifr_arp_muxid;
|
int muxid = ifr.lifr_arp_muxid;
|
||||||
ioctl(ip_fd, I_PUNLINK, muxid);
|
ioctl(ip_fd, I_PUNLINK, muxid);
|
||||||
|
@ -191,6 +202,7 @@ static bool setup_device(void) {
|
||||||
logger(LOG_ERR, "Could not set PPA %d on %s %s!", ppa, device_info, device);
|
logger(LOG_ERR, "Could not set PPA %d on %s %s!", ppa, device_info, device);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0) {
|
if(ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0) {
|
||||||
logger(LOG_ERR, "Could not set flags on %s %s!", device_info, device);
|
logger(LOG_ERR, "Could not set flags on %s %s!", device_info, device);
|
||||||
return false;
|
return false;
|
||||||
|
@ -204,9 +216,10 @@ static bool setup_device(void) {
|
||||||
|
|
||||||
/* Pop any modules on the stream */
|
/* Pop any modules on the stream */
|
||||||
while(true) {
|
while(true) {
|
||||||
if(ioctl(ip_fd, I_POP, NULL) < 0)
|
if(ioctl(ip_fd, I_POP, NULL) < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Push arp module to ip_fd */
|
/* Push arp module to ip_fd */
|
||||||
if(ioctl(ip_fd, I_PUSH, "arp") < 0) {
|
if(ioctl(ip_fd, I_PUSH, "arp") < 0) {
|
||||||
|
@ -229,7 +242,7 @@ static bool setup_device(void) {
|
||||||
/* Set ifname to arp */
|
/* Set ifname to arp */
|
||||||
struct strioctl strioc_if = {
|
struct strioctl strioc_if = {
|
||||||
.ic_cmd = SIOCSLIFNAME,
|
.ic_cmd = SIOCSLIFNAME,
|
||||||
.ic_len = sizeof ifr,
|
.ic_len = sizeof(ifr),
|
||||||
.ic_dp = (char *) &ifr,
|
.ic_dp = (char *) &ifr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -251,12 +264,16 @@ static bool setup_device(void) {
|
||||||
logger(LOG_ERR, "Could not link %s %s to ARP", device_info, device);
|
logger(LOG_ERR, "Could not link %s %s to ARP", device_info, device);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(arp_fd);
|
close(arp_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct lifreq ifr = {};
|
struct lifreq ifr = {};
|
||||||
|
|
||||||
strncpy(ifr.lifr_name, iface, sizeof(ifr.lifr_name));
|
strncpy(ifr.lifr_name, iface, sizeof(ifr.lifr_name));
|
||||||
|
|
||||||
ifr.lifr_ip_muxid = ip_muxid;
|
ifr.lifr_ip_muxid = ip_muxid;
|
||||||
|
|
||||||
if(device_type == DEVICE_TYPE_TAP) {
|
if(device_type == DEVICE_TYPE_TAP) {
|
||||||
ifr.lifr_arp_muxid = arp_muxid;
|
ifr.lifr_arp_muxid = arp_muxid;
|
||||||
}
|
}
|
||||||
|
@ -265,6 +282,7 @@ static bool setup_device(void) {
|
||||||
if(device_type == DEVICE_TYPE_TAP) {
|
if(device_type == DEVICE_TYPE_TAP) {
|
||||||
ioctl(ip_fd, I_PUNLINK, arp_muxid);
|
ioctl(ip_fd, I_PUNLINK, arp_muxid);
|
||||||
}
|
}
|
||||||
|
|
||||||
ioctl(ip_fd, I_PUNLINK, ip_muxid);
|
ioctl(ip_fd, I_PUNLINK, ip_muxid);
|
||||||
logger(LOG_ERR, "Could not set multiplexor id for %s %s", device_info, device);
|
logger(LOG_ERR, "Could not set multiplexor id for %s %s", device_info, device);
|
||||||
return false;
|
return false;
|
||||||
|
@ -285,7 +303,8 @@ static bool setup_device(void) {
|
||||||
static void close_device(void) {
|
static void close_device(void) {
|
||||||
if(iface) {
|
if(iface) {
|
||||||
struct lifreq ifr = {};
|
struct lifreq ifr = {};
|
||||||
strncpy(ifr.lifr_name, iface, sizeof ifr.lifr_name);
|
strncpy(ifr.lifr_name, iface, sizeof(ifr.lifr_name));
|
||||||
|
|
||||||
if(ioctl(ip_fd, SIOCGLIFMUXID, &ifr) >= 0) {
|
if(ioctl(ip_fd, SIOCGLIFMUXID, &ifr) >= 0) {
|
||||||
int muxid = ifr.lifr_arp_muxid;
|
int muxid = ifr.lifr_arp_muxid;
|
||||||
ioctl(ip_fd, I_PUNLINK, muxid);
|
ioctl(ip_fd, I_PUNLINK, muxid);
|
||||||
|
@ -321,10 +340,12 @@ static bool read_packet(vpn_packet_t *packet) {
|
||||||
packet->data[12] = 0x08;
|
packet->data[12] = 0x08;
|
||||||
packet->data[13] = 0x00;
|
packet->data[13] = 0x00;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6:
|
case 6:
|
||||||
packet->data[12] = 0x86;
|
packet->data[12] = 0x86;
|
||||||
packet->data[13] = 0xDD;
|
packet->data[13] = 0xDD;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ifdebug(TRAFFIC) logger(LOG_ERR, "Unknown IP version %d while reading packet from %s %s", packet->data[14] >> 4, device_info, device);
|
ifdebug(TRAFFIC) logger(LOG_ERR, "Unknown IP version %d while reading packet from %s %s", packet->data[14] >> 4, device_info, device);
|
||||||
return false;
|
return false;
|
||||||
|
@ -371,6 +392,7 @@ static bool write_packet(vpn_packet_t *packet) {
|
||||||
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno));
|
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEVICE_TYPE_TAP:
|
case DEVICE_TYPE_TAP:
|
||||||
|
@ -381,6 +403,7 @@ static bool write_packet(vpn_packet_t *packet) {
|
||||||
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno));
|
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
191
src/subnet.c
191
src/subnet.c
|
@ -65,13 +65,15 @@ static int subnet_compare_mac(const subnet_t *a, const subnet_t *b) {
|
||||||
|
|
||||||
result = memcmp(&a->net.mac.address, &b->net.mac.address, sizeof(mac_t));
|
result = memcmp(&a->net.mac.address, &b->net.mac.address, sizeof(mac_t));
|
||||||
|
|
||||||
if(result)
|
if(result) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
result = a->weight - b->weight;
|
result = a->weight - b->weight;
|
||||||
|
|
||||||
if(result || !a->owner || !b->owner)
|
if(result || !a->owner || !b->owner) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return strcmp(a->owner->name, b->owner->name);
|
return strcmp(a->owner->name, b->owner->name);
|
||||||
}
|
}
|
||||||
|
@ -81,18 +83,21 @@ static int subnet_compare_ipv4(const subnet_t *a, const subnet_t *b) {
|
||||||
|
|
||||||
result = b->net.ipv4.prefixlength - a->net.ipv4.prefixlength;
|
result = b->net.ipv4.prefixlength - a->net.ipv4.prefixlength;
|
||||||
|
|
||||||
if(result)
|
if(result) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
result = memcmp(&a->net.ipv4.address, &b->net.ipv4.address, sizeof(ipv4_t));
|
result = memcmp(&a->net.ipv4.address, &b->net.ipv4.address, sizeof(ipv4_t));
|
||||||
|
|
||||||
if(result)
|
if(result) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
result = a->weight - b->weight;
|
result = a->weight - b->weight;
|
||||||
|
|
||||||
if(result || !a->owner || !b->owner)
|
if(result || !a->owner || !b->owner) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return strcmp(a->owner->name, b->owner->name);
|
return strcmp(a->owner->name, b->owner->name);
|
||||||
}
|
}
|
||||||
|
@ -102,18 +107,21 @@ static int subnet_compare_ipv6(const subnet_t *a, const subnet_t *b) {
|
||||||
|
|
||||||
result = b->net.ipv6.prefixlength - a->net.ipv6.prefixlength;
|
result = b->net.ipv6.prefixlength - a->net.ipv6.prefixlength;
|
||||||
|
|
||||||
if(result)
|
if(result) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
result = memcmp(&a->net.ipv6.address, &b->net.ipv6.address, sizeof(ipv6_t));
|
result = memcmp(&a->net.ipv6.address, &b->net.ipv6.address, sizeof(ipv6_t));
|
||||||
|
|
||||||
if(result)
|
if(result) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
result = a->weight - b->weight;
|
result = a->weight - b->weight;
|
||||||
|
|
||||||
if(result || !a->owner || !b->owner)
|
if(result || !a->owner || !b->owner) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return strcmp(a->owner->name, b->owner->name);
|
return strcmp(a->owner->name, b->owner->name);
|
||||||
}
|
}
|
||||||
|
@ -123,16 +131,20 @@ int subnet_compare(const subnet_t *a, const subnet_t *b) {
|
||||||
|
|
||||||
result = a->type - b->type;
|
result = a->type - b->type;
|
||||||
|
|
||||||
if(result)
|
if(result) {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
switch(a->type) {
|
switch(a->type) {
|
||||||
case SUBNET_MAC:
|
case SUBNET_MAC:
|
||||||
return subnet_compare_mac(a, b);
|
return subnet_compare_mac(a, b);
|
||||||
|
|
||||||
case SUBNET_IPV4:
|
case SUBNET_IPV4:
|
||||||
return subnet_compare_ipv4(a, b);
|
return subnet_compare_ipv4(a, b);
|
||||||
|
|
||||||
case SUBNET_IPV6:
|
case SUBNET_IPV6:
|
||||||
return subnet_compare_ipv6(a, b);
|
return subnet_compare_ipv6(a, b);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
logger(LOG_ERR, "subnet_compare() was called with unknown subnet type %d, exitting!",
|
logger(LOG_ERR, "subnet_compare() was called with unknown subnet type %d, exitting!",
|
||||||
a->type);
|
a->type);
|
||||||
|
@ -199,16 +211,19 @@ bool str2net(subnet_t *subnet, const char *subnetstr) {
|
||||||
|
|
||||||
if(sscanf(subnetstr, "%hu.%hu.%hu.%hu/%d#%d",
|
if(sscanf(subnetstr, "%hu.%hu.%hu.%hu/%d#%d",
|
||||||
&x[0], &x[1], &x[2], &x[3], &l, &weight) >= 5) {
|
&x[0], &x[1], &x[2], &x[3], &l, &weight) >= 5) {
|
||||||
if(l < 0 || l > 32)
|
if(l < 0 || l > 32) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
subnet->type = SUBNET_IPV4;
|
subnet->type = SUBNET_IPV4;
|
||||||
subnet->net.ipv4.prefixlength = l;
|
subnet->net.ipv4.prefixlength = l;
|
||||||
subnet->weight = weight;
|
subnet->weight = weight;
|
||||||
|
|
||||||
for(i = 0; i < 4; i++) {
|
for(i = 0; i < 4; i++) {
|
||||||
if(x[i] > 255)
|
if(x[i] > 255) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
subnet->net.ipv4.address.x[i] = x[i];
|
subnet->net.ipv4.address.x[i] = x[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,15 +233,17 @@ bool str2net(subnet_t *subnet, const char *subnetstr) {
|
||||||
if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d#%d",
|
if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d#%d",
|
||||||
&x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
|
&x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
|
||||||
&l, &weight) >= 9) {
|
&l, &weight) >= 9) {
|
||||||
if(l < 0 || l > 128)
|
if(l < 0 || l > 128) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
subnet->type = SUBNET_IPV6;
|
subnet->type = SUBNET_IPV6;
|
||||||
subnet->net.ipv6.prefixlength = l;
|
subnet->net.ipv6.prefixlength = l;
|
||||||
subnet->weight = weight;
|
subnet->weight = weight;
|
||||||
|
|
||||||
for(i = 0; i < 8; i++)
|
for(i = 0; i < 8; i++) {
|
||||||
subnet->net.ipv6.address.x[i] = htons(x[i]);
|
subnet->net.ipv6.address.x[i] = htons(x[i]);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -237,8 +254,10 @@ bool str2net(subnet_t *subnet, const char *subnetstr) {
|
||||||
subnet->weight = weight;
|
subnet->weight = weight;
|
||||||
|
|
||||||
for(i = 0; i < 4; i++) {
|
for(i = 0; i < 4; i++) {
|
||||||
if(x[i] > 255)
|
if(x[i] > 255) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
subnet->net.ipv4.address.x[i] = x[i];
|
subnet->net.ipv4.address.x[i] = x[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,8 +270,9 @@ bool str2net(subnet_t *subnet, const char *subnetstr) {
|
||||||
subnet->net.ipv6.prefixlength = 128;
|
subnet->net.ipv6.prefixlength = 128;
|
||||||
subnet->weight = weight;
|
subnet->weight = weight;
|
||||||
|
|
||||||
for(i = 0; i < 8; i++)
|
for(i = 0; i < 8; i++) {
|
||||||
subnet->net.ipv6.address.x[i] = htons(x[i]);
|
subnet->net.ipv6.address.x[i] = htons(x[i]);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -262,8 +282,9 @@ bool str2net(subnet_t *subnet, const char *subnetstr) {
|
||||||
subnet->type = SUBNET_MAC;
|
subnet->type = SUBNET_MAC;
|
||||||
subnet->weight = weight;
|
subnet->weight = weight;
|
||||||
|
|
||||||
for(i = 0; i < 6; i++)
|
for(i = 0; i < 6; i++) {
|
||||||
subnet->net.mac.address.x[i] = x[i];
|
subnet->net.mac.address.x[i] = x[i];
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -276,66 +297,87 @@ bool str2net(subnet_t *subnet, const char *subnetstr) {
|
||||||
|
|
||||||
// Count number of colons
|
// Count number of colons
|
||||||
for(p = subnetstr; *p; p++)
|
for(p = subnetstr; *p; p++)
|
||||||
if(*p == ':')
|
if(*p == ':') {
|
||||||
colons++;
|
colons++;
|
||||||
|
}
|
||||||
|
|
||||||
if(colons > 7)
|
if(colons > 7) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Scan numbers before the double colon
|
// Scan numbers before the double colon
|
||||||
p = subnetstr;
|
p = subnetstr;
|
||||||
|
|
||||||
for(i = 0; i < colons; i++) {
|
for(i = 0; i < colons; i++) {
|
||||||
if(*p == ':')
|
if(*p == ':') {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
x[i] = strtoul(p, &q, 0x10);
|
x[i] = strtoul(p, &q, 0x10);
|
||||||
if(!q || p == q || *q != ':')
|
|
||||||
|
if(!q || p == q || *q != ':') {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
p = ++q;
|
p = ++q;
|
||||||
}
|
}
|
||||||
|
|
||||||
p++;
|
p++;
|
||||||
colons -= i;
|
colons -= i;
|
||||||
|
|
||||||
if(!i) {
|
if(!i) {
|
||||||
p++;
|
p++;
|
||||||
colons--;
|
colons--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!*p || *p == '/' || *p == '#')
|
if(!*p || *p == '/' || *p == '#') {
|
||||||
colons--;
|
colons--;
|
||||||
|
}
|
||||||
|
|
||||||
// Fill in the blanks
|
// Fill in the blanks
|
||||||
for(; i < 8 - colons; i++)
|
for(; i < 8 - colons; i++) {
|
||||||
x[i] = 0;
|
x[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Scan the remaining numbers
|
// Scan the remaining numbers
|
||||||
for(; i < 8; i++) {
|
for(; i < 8; i++) {
|
||||||
x[i] = strtoul(p, &q, 0x10);
|
x[i] = strtoul(p, &q, 0x10);
|
||||||
if(!q || p == q)
|
|
||||||
|
if(!q || p == q) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(i == 7) {
|
if(i == 7) {
|
||||||
p = q;
|
p = q;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(*q != ':')
|
|
||||||
|
if(*q != ':') {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
p = ++q;
|
p = ++q;
|
||||||
}
|
}
|
||||||
|
|
||||||
l = 128;
|
l = 128;
|
||||||
if(*p == '/')
|
|
||||||
sscanf(p, "/%d#%d", &l, &weight);
|
|
||||||
else if(*p == '#')
|
|
||||||
sscanf(p, "#%d", &weight);
|
|
||||||
|
|
||||||
if(l < 0 || l > 128)
|
if(*p == '/') {
|
||||||
|
sscanf(p, "/%d#%d", &l, &weight);
|
||||||
|
} else if(*p == '#') {
|
||||||
|
sscanf(p, "#%d", &weight);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(l < 0 || l > 128) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
subnet->type = SUBNET_IPV6;
|
subnet->type = SUBNET_IPV6;
|
||||||
subnet->net.ipv6.prefixlength = l;
|
subnet->net.ipv6.prefixlength = l;
|
||||||
subnet->weight = weight;
|
subnet->weight = weight;
|
||||||
|
|
||||||
for(i = 0; i < 8; i++)
|
for(i = 0; i < 8; i++) {
|
||||||
subnet->net.ipv6.address.x[i] = htons(x[i]);
|
subnet->net.ipv6.address.x[i] = htons(x[i]);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -409,33 +451,41 @@ subnet_t *lookup_subnet_mac(const node_t *owner, const mac_t *address) {
|
||||||
// Check if this address is cached
|
// Check if this address is cached
|
||||||
|
|
||||||
for(i = 0; i < 2; i++) {
|
for(i = 0; i < 2; i++) {
|
||||||
if(!cache_mac_valid[i])
|
if(!cache_mac_valid[i]) {
|
||||||
continue;
|
continue;
|
||||||
if(owner && cache_mac_subnet[i] && cache_mac_subnet[i]->owner != owner)
|
}
|
||||||
|
|
||||||
|
if(owner && cache_mac_subnet[i] && cache_mac_subnet[i]->owner != owner) {
|
||||||
continue;
|
continue;
|
||||||
if(!memcmp(address, &cache_mac_address[i], sizeof *address))
|
}
|
||||||
|
|
||||||
|
if(!memcmp(address, &cache_mac_address[i], sizeof(*address))) {
|
||||||
return cache_mac_subnet[i];
|
return cache_mac_subnet[i];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Search all subnets for a matching one
|
// Search all subnets for a matching one
|
||||||
|
|
||||||
for(n = owner ? owner->subnet_tree->head : subnet_tree->head; n; n = n->next) {
|
for(n = owner ? owner->subnet_tree->head : subnet_tree->head; n; n = n->next) {
|
||||||
p = n->data;
|
p = n->data;
|
||||||
|
|
||||||
if(!p || p->type != SUBNET_MAC)
|
if(!p || p->type != SUBNET_MAC) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(!memcmp(address, &p->net.mac.address, sizeof *address)) {
|
if(!memcmp(address, &p->net.mac.address, sizeof(*address))) {
|
||||||
r = p;
|
r = p;
|
||||||
if(p->owner->status.reachable)
|
|
||||||
|
if(p->owner->status.reachable) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Cache the result
|
// Cache the result
|
||||||
|
|
||||||
cache_mac_slot = !cache_mac_slot;
|
cache_mac_slot = !cache_mac_slot;
|
||||||
memcpy(&cache_mac_address[cache_mac_slot], address, sizeof *address);
|
memcpy(&cache_mac_address[cache_mac_slot], address, sizeof(*address));
|
||||||
cache_mac_subnet[cache_mac_slot] = r;
|
cache_mac_subnet[cache_mac_slot] = r;
|
||||||
cache_mac_valid[cache_mac_slot] = true;
|
cache_mac_valid[cache_mac_slot] = true;
|
||||||
|
|
||||||
|
@ -450,31 +500,37 @@ subnet_t *lookup_subnet_ipv4(const ipv4_t *address) {
|
||||||
// Check if this address is cached
|
// Check if this address is cached
|
||||||
|
|
||||||
for(i = 0; i < 2; i++) {
|
for(i = 0; i < 2; i++) {
|
||||||
if(!cache_ipv4_valid[i])
|
if(!cache_ipv4_valid[i]) {
|
||||||
continue;
|
continue;
|
||||||
if(!memcmp(address, &cache_ipv4_address[i], sizeof *address))
|
}
|
||||||
|
|
||||||
|
if(!memcmp(address, &cache_ipv4_address[i], sizeof(*address))) {
|
||||||
return cache_ipv4_subnet[i];
|
return cache_ipv4_subnet[i];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Search all subnets for a matching one
|
// Search all subnets for a matching one
|
||||||
|
|
||||||
for(n = subnet_tree->head; n; n = n->next) {
|
for(n = subnet_tree->head; n; n = n->next) {
|
||||||
p = n->data;
|
p = n->data;
|
||||||
|
|
||||||
if(!p || p->type != SUBNET_IPV4)
|
if(!p || p->type != SUBNET_IPV4) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(!maskcmp(address, &p->net.ipv4.address, p->net.ipv4.prefixlength)) {
|
if(!maskcmp(address, &p->net.ipv4.address, p->net.ipv4.prefixlength)) {
|
||||||
r = p;
|
r = p;
|
||||||
if(p->owner->status.reachable)
|
|
||||||
|
if(p->owner->status.reachable) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Cache the result
|
// Cache the result
|
||||||
|
|
||||||
cache_ipv4_slot = !cache_ipv4_slot;
|
cache_ipv4_slot = !cache_ipv4_slot;
|
||||||
memcpy(&cache_ipv4_address[cache_ipv4_slot], address, sizeof *address);
|
memcpy(&cache_ipv4_address[cache_ipv4_slot], address, sizeof(*address));
|
||||||
cache_ipv4_subnet[cache_ipv4_slot] = r;
|
cache_ipv4_subnet[cache_ipv4_slot] = r;
|
||||||
cache_ipv4_valid[cache_ipv4_slot] = true;
|
cache_ipv4_valid[cache_ipv4_slot] = true;
|
||||||
|
|
||||||
|
@ -489,31 +545,37 @@ subnet_t *lookup_subnet_ipv6(const ipv6_t *address) {
|
||||||
// Check if this address is cached
|
// Check if this address is cached
|
||||||
|
|
||||||
for(i = 0; i < 2; i++) {
|
for(i = 0; i < 2; i++) {
|
||||||
if(!cache_ipv6_valid[i])
|
if(!cache_ipv6_valid[i]) {
|
||||||
continue;
|
continue;
|
||||||
if(!memcmp(address, &cache_ipv6_address[i], sizeof *address))
|
}
|
||||||
|
|
||||||
|
if(!memcmp(address, &cache_ipv6_address[i], sizeof(*address))) {
|
||||||
return cache_ipv6_subnet[i];
|
return cache_ipv6_subnet[i];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Search all subnets for a matching one
|
// Search all subnets for a matching one
|
||||||
|
|
||||||
for(n = subnet_tree->head; n; n = n->next) {
|
for(n = subnet_tree->head; n; n = n->next) {
|
||||||
p = n->data;
|
p = n->data;
|
||||||
|
|
||||||
if(!p || p->type != SUBNET_IPV6)
|
if(!p || p->type != SUBNET_IPV6) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(!maskcmp(address, &p->net.ipv6.address, p->net.ipv6.prefixlength)) {
|
if(!maskcmp(address, &p->net.ipv6.address, p->net.ipv6.prefixlength)) {
|
||||||
r = p;
|
r = p;
|
||||||
if(p->owner->status.reachable)
|
|
||||||
|
if(p->owner->status.reachable) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Cache the result
|
// Cache the result
|
||||||
|
|
||||||
cache_ipv6_slot = !cache_ipv6_slot;
|
cache_ipv6_slot = !cache_ipv6_slot;
|
||||||
memcpy(&cache_ipv6_address[cache_ipv6_slot], address, sizeof *address);
|
memcpy(&cache_ipv6_address[cache_ipv6_slot], address, sizeof(*address));
|
||||||
cache_ipv6_subnet[cache_ipv6_slot] = r;
|
cache_ipv6_subnet[cache_ipv6_slot] = r;
|
||||||
cache_ipv6_valid[cache_ipv6_slot] = true;
|
cache_ipv6_valid[cache_ipv6_slot] = true;
|
||||||
|
|
||||||
|
@ -550,33 +612,44 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) {
|
||||||
if(!subnet) {
|
if(!subnet) {
|
||||||
for(node = owner->subnet_tree->head; node; node = node->next) {
|
for(node = owner->subnet_tree->head; node; node = node->next) {
|
||||||
subnet = node->data;
|
subnet = node->data;
|
||||||
if(!net2str(netstr, sizeof netstr, subnet))
|
|
||||||
|
if(!net2str(netstr, sizeof(netstr), subnet)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Strip the weight from the subnet, and put it in its own environment variable
|
// Strip the weight from the subnet, and put it in its own environment variable
|
||||||
char *weight = strchr(netstr, '#');
|
char *weight = strchr(netstr, '#');
|
||||||
if(weight)
|
|
||||||
|
if(weight) {
|
||||||
*weight++ = 0;
|
*weight++ = 0;
|
||||||
else
|
} else {
|
||||||
weight = empty;
|
weight = empty;
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare the SUBNET and WEIGHT variables
|
// Prepare the SUBNET and WEIGHT variables
|
||||||
if(envp[5])
|
if(envp[5]) {
|
||||||
free(envp[5]);
|
free(envp[5]);
|
||||||
if(envp[6])
|
}
|
||||||
|
|
||||||
|
if(envp[6]) {
|
||||||
free(envp[6]);
|
free(envp[6]);
|
||||||
|
}
|
||||||
|
|
||||||
xasprintf(&envp[5], "SUBNET=%s", netstr);
|
xasprintf(&envp[5], "SUBNET=%s", netstr);
|
||||||
xasprintf(&envp[6], "WEIGHT=%s", weight);
|
xasprintf(&envp[6], "WEIGHT=%s", weight);
|
||||||
|
|
||||||
execute_script(name, envp);
|
execute_script(name, envp);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(net2str(netstr, sizeof netstr, subnet)) {
|
if(net2str(netstr, sizeof(netstr), subnet)) {
|
||||||
// Strip the weight from the subnet, and put it in its own environment variable
|
// Strip the weight from the subnet, and put it in its own environment variable
|
||||||
char *weight = strchr(netstr, '#');
|
char *weight = strchr(netstr, '#');
|
||||||
if(weight)
|
|
||||||
|
if(weight) {
|
||||||
*weight++ = 0;
|
*weight++ = 0;
|
||||||
else
|
} else {
|
||||||
weight = empty;
|
weight = empty;
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare the SUBNET and WEIGHT variables
|
// Prepare the SUBNET and WEIGHT variables
|
||||||
xasprintf(&envp[5], "SUBNET=%s", netstr);
|
xasprintf(&envp[5], "SUBNET=%s", netstr);
|
||||||
|
@ -586,9 +659,10 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; envp[i] && i < 9; i++)
|
for(i = 0; envp[i] && i < 9; i++) {
|
||||||
free(envp[i]);
|
free(envp[i]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void dump_subnets(void) {
|
void dump_subnets(void) {
|
||||||
char netstr[MAXNETSTR];
|
char netstr[MAXNETSTR];
|
||||||
|
@ -599,8 +673,11 @@ void dump_subnets(void) {
|
||||||
|
|
||||||
for(node = subnet_tree->head; node; node = node->next) {
|
for(node = subnet_tree->head; node; node = node->next) {
|
||||||
subnet = node->data;
|
subnet = node->data;
|
||||||
if(!net2str(netstr, sizeof netstr, subnet))
|
|
||||||
|
if(!net2str(netstr, sizeof(netstr), subnet)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
logger(LOG_DEBUG, " %s owner %s", netstr, subnet->owner->name);
|
logger(LOG_DEBUG, " %s owner %s", netstr, subnet->owner->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
33
src/subnet.h
33
src/subnet.h
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_SUBNET_H
|
||||||
|
#define TINC_SUBNET_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
subnet.h -- header for subnet.c
|
subnet.h -- header for subnet.c
|
||||||
Copyright (C) 2000-2009 Guus Sliepen <guus@tinc-vpn.org>,
|
Copyright (C) 2000-2009 Guus Sliepen <guus@tinc-vpn.org>,
|
||||||
|
@ -18,16 +21,13 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TINC_SUBNET_H__
|
|
||||||
#define __TINC_SUBNET_H__
|
|
||||||
|
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
|
||||||
typedef enum subnet_type_t {
|
typedef enum subnet_type_t {
|
||||||
SUBNET_MAC = 0,
|
SUBNET_MAC = 0,
|
||||||
SUBNET_IPV4,
|
SUBNET_IPV4,
|
||||||
SUBNET_IPV6,
|
SUBNET_IPV6,
|
||||||
SUBNET_TYPES /* Guardian */
|
SUBNET_TYPES, /* Guardian */
|
||||||
} subnet_type_t;
|
} subnet_type_t;
|
||||||
|
|
||||||
typedef struct subnet_mac_t {
|
typedef struct subnet_mac_t {
|
||||||
|
@ -66,23 +66,22 @@ typedef struct subnet_t {
|
||||||
|
|
||||||
extern avl_tree_t *subnet_tree;
|
extern avl_tree_t *subnet_tree;
|
||||||
|
|
||||||
extern int subnet_compare(const struct subnet_t *, const struct subnet_t *);
|
|
||||||
extern subnet_t *new_subnet(void) __attribute__((__malloc__));
|
extern subnet_t *new_subnet(void) __attribute__((__malloc__));
|
||||||
extern void free_subnet(subnet_t *);
|
extern void free_subnet(subnet_t *subnet);
|
||||||
extern void init_subnets(void);
|
extern void init_subnets(void);
|
||||||
extern void exit_subnets(void);
|
extern void exit_subnets(void);
|
||||||
extern avl_tree_t *new_subnet_tree(void) __attribute__((__malloc__));
|
extern avl_tree_t *new_subnet_tree(void) __attribute__((__malloc__));
|
||||||
extern void free_subnet_tree(avl_tree_t *);
|
extern void free_subnet_tree(avl_tree_t *subnet_tree);
|
||||||
extern void subnet_add(struct node_t *, subnet_t *);
|
extern void subnet_add(struct node_t *owner, subnet_t *subnet);
|
||||||
extern void subnet_del(struct node_t *, subnet_t *);
|
extern void subnet_del(struct node_t *owner, subnet_t *subnet);
|
||||||
extern void subnet_update(struct node_t *, subnet_t *, bool);
|
extern void subnet_update(struct node_t *owner, subnet_t *subnet, bool up);
|
||||||
extern bool net2str(char *, int, const subnet_t *);
|
extern bool net2str(char *netstr, int len, const subnet_t *subnet);
|
||||||
extern bool str2net(subnet_t *, const char *);
|
extern bool str2net(subnet_t *subnet, const char *netstr);
|
||||||
extern subnet_t *lookup_subnet(const struct node_t *, const subnet_t *);
|
extern subnet_t *lookup_subnet(const struct node_t *owner, const subnet_t *subnet);
|
||||||
extern subnet_t *lookup_subnet_mac(const struct node_t *, const mac_t *);
|
extern subnet_t *lookup_subnet_mac(const struct node_t *owner, const mac_t *address);
|
||||||
extern subnet_t *lookup_subnet_ipv4(const ipv4_t *);
|
extern subnet_t *lookup_subnet_ipv4(const ipv4_t *address);
|
||||||
extern subnet_t *lookup_subnet_ipv6(const ipv6_t *);
|
extern subnet_t *lookup_subnet_ipv6(const ipv6_t *address);
|
||||||
extern void dump_subnets(void);
|
extern void dump_subnets(void);
|
||||||
extern void subnet_cache_flush(void);
|
extern void subnet_cache_flush(void);
|
||||||
|
|
||||||
#endif /* __TINC_SUBNET_H__ */
|
#endif
|
||||||
|
|
16
src/system.h
16
src/system.h
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef TINC_SYSTEM_H
|
||||||
|
#define TINC_SYSTEM_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
system.h -- system headers
|
system.h -- system headers
|
||||||
Copyright (C) 1998-2005 Ivo Timmermans
|
Copyright (C) 1998-2005 Ivo Timmermans
|
||||||
|
@ -18,19 +21,10 @@
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TINC_SYSTEM_H__
|
#include "config.h"
|
||||||
#define __TINC_SYSTEM_H__
|
|
||||||
|
|
||||||
#include "../config.h"
|
|
||||||
|
|
||||||
#include "have.h"
|
#include "have.h"
|
||||||
|
|
||||||
#ifndef HAVE_STDBOOL_H
|
|
||||||
typedef int bool;
|
|
||||||
#define true 1
|
|
||||||
#define false 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef HAVE_STRSIGNAL
|
#ifndef HAVE_STRSIGNAL
|
||||||
# define strsignal(p) ""
|
# define strsignal(p) ""
|
||||||
#endif
|
#endif
|
||||||
|
@ -43,4 +37,4 @@ typedef int bool;
|
||||||
typedef int socklen_t;
|
typedef int socklen_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __TINC_SYSTEM_H__ */
|
#endif
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue