diff --git a/COPYING b/COPYING index 91365f3..513da31 100644 --- a/COPYING +++ b/COPYING @@ -1,4 +1,4 @@ -Copyright (C) 1998-2015 Ivo Timmermans, Guus Sliepen and others. +Copyright (C) 1998-2016 Ivo Timmermans, Guus Sliepen and others. See the AUTHORS file for a complete list. This program is free software; you can redistribute it and/or modify it under diff --git a/ChangeLog b/ChangeLog index efc25dc..753bfc1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,53 @@ +Version 1.0.27 April 10 2016 +------------------------------------------------------------------------ + +Guus Sliepen (26): + Add missing AM_PROG_CC_C_O to configure.ac. + Attribution for various contributors. + Update "now" after connect() when making outgoing connections. + Add ability to use proxies to connect to hostnames when there is no nameserver. + Only add a reflexive address when we're sure it's working. + Fix compatibility with TAP-Win32 9.0.0.21 and later. + Fix warnings from the Clang Static Analyzer. + Improve performance of edge updates. + Clarify that scripts are called synchronously. + Small fixes for the documentation. + Add warnings for bad combinations of Device and Interface. + Fix forwarding of edge updates. + Don't compile getopt*.c if the system provides getopt_long(). + Update .gitignore. + Update THANKS. + Use iface instead of interface. + Update copyright notices. + Remove use of __DATE__ and __TIME__ to facilitate reproducible builds. + Cast 0xff to char before comparing it to another char. + Get rid of a warning when compiling tinc using MinGW. + Every BSD flavor has a tap device nowadays. + Use devname() if available to support devfs cloning on BSD. + Use SIOCGIFADDR on BSDs that support it. + Enable silent builds by default. + Add support for OS X utun interfaces. + Releasing 1.0.27. + +Vittorio Gambaletta (VittGam) (6): + Fix DecrementTTL option. + Fix source IP address for ICMP unreachable packets generated by tinc. + Try to reply with node address only when decrementing the TTL. + Fix DecrementTTL option for packets destined to the local node. + s/broadcast_packet_helper/route_broadcast/ + Remove forward declaration for do_decrement_ttl. + +LunarShaddow (3): + fix typo + re-arrange include sequence to avoid a mingw introduced bug. + Proofing README. + +Florian Weik (1): + Fix NAME variable in subnet-* scripts for local subnets. + +Nathan Stratton Treadway (1): + Fix invalid checksum generation. + Version 1.0.26 July 05 2015 ------------------------------------------------------------------------ diff --git a/Makefile.in b/Makefile.in index a057ac8..d4dec4d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -14,7 +14,17 @@ @SET_MAKE@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -78,11 +88,6 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = . -DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \ - $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/configure $(am__configure_deps) \ - $(srcdir)/config.h.in COPYING THANKS compile config.guess \ - config.sub depcomp install-sh missing ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ $(top_srcdir)/m4/ax_check_compile_flag.m4 \ @@ -91,6 +96,8 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d @@ -154,6 +161,9 @@ ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in AUTHORS \ + COPYING ChangeLog INSTALL NEWS README THANKS compile \ + config.guess config.sub depcomp install-sh missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) @@ -284,6 +294,7 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -315,7 +326,6 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -543,15 +553,15 @@ dist-xz: distdir $(am__post_remove_distdir) dist-tarZ: distdir - @echo WARNING: "Support for shar distribution archives is" \ - "deprecated." >&2 + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir - @echo WARNING: "Support for distribution archives compressed with" \ - "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) @@ -587,17 +597,17 @@ distcheck: dist esac chmod -R a-w $(distdir) chmod u+w $(distdir) - mkdir $(distdir)/_build $(distdir)/_inst + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ - && $(am__cd) $(distdir)/_build \ - && ../configure \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ - --srcdir=.. --prefix="$$dc_install_base" \ + --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ @@ -772,6 +782,8 @@ uninstall-am: mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am +.PRECIOUS: Makefile + ChangeLog: git log > ChangeLog diff --git a/NEWS b/NEWS index eb35583..cc5cafa 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,24 @@ +Version 1.0.27 April 10 2016 + + * When using Proxy, let the proxy resolve hostnames if tinc can't. + + * Fixes and improvements of the DecrementTTL option. + + * Fixed the $NAME variable in subnet-up/down scripts for the local Subnets. + + * Fixed potentially wrong checksum generation when clamping the MSS. + + * Properly choose between the system's or our own copy of getopt. + + * Fixed compiling tinc for Cygwin with MinGW installed. + + * Added support for OS X utun interfaces. + + * Documentation updates and minor fixes. + +Thanks to Vittorio Gambaletta, LunarShaddow, Florian Weik and Nathan Stratton +Treadway for their contributions to this version of tinc. + Version 1.0.26 July 5 2015 * Tinc now forces glibc to reload /etc/resolv.conf for every hostname lookup. diff --git a/README b/README index 69497d6..bf4c6c4 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ -This is the README file for tinc version 1.0.26. Installation +This is the README file for tinc version 1.0.27. Installation instructions may be found in the INSTALL file. -tinc is Copyright (C) 1998-2015 by: +tinc is Copyright (C) 1998-2016 by: Ivo Timmermans, Guus Sliepen , @@ -42,7 +42,7 @@ issues are being addressed in the tinc 1.1 branch. Cryptography is a hard thing to get right. We cannot make any guarantees. Time, review and feedback are the only things that can prove the security of any cryptographic product. If you wish to review -tinc or give us feedback, you are stronly encouraged to do so. +tinc or give us feedback, you are strongly encouraged to do so. Changes to configuration file format since 1.0pre5 @@ -55,7 +55,7 @@ should be changed into "Device", and "Device" should be changed into Compatibility ------------- -Version 1.0.26 is compatible with 1.0pre8, 1.0 and later, but not with older +Version 1.0.27 is compatible with 1.0pre8, 1.0 and later, but not with older versions of tinc. @@ -106,14 +106,14 @@ Linux, FreeBSD and Windows. The algorithms used for encryption and generating message authentication codes can now be changed in the configuration files. All cipher and digest algorithms supported by OpenSSL can be used. Useful ciphers are "blowfish" (default), -"bf-ofb", "des", "des3", etcetera. Useful digests are "sha1" (default), "md5", -etcetera. +"bf-ofb", "des", "des3", et cetera. Useful digests are "sha1" (default), "md5", +et cetera. Support for routing IPv6 packets has been added. Just add Subnet lines with IPv6 addresses (without using :: abbreviations) and use ifconfig or ip (from the iproute package) to give the virtual network interface corresponding IPv6 -addresses. tinc does not provide autoconfiguration for IPv6 hosts, if you need -it use radvd or zebra. +addresses. tinc does not provide autoconfiguration for IPv6 hosts. Consider +using radvd or zebra if you need it. It is also possible to make tunnels to other tinc daemons over IPv6 networks, if the operating system supports IPv6. tinc will automatically use both IPv6 @@ -121,7 +121,7 @@ and IPv4 when available, but this can be changed by adding the option "AddressFamily = ipv4" or "AddressFamily = ipv6" to the tinc.conf file. Normally, when started tinc will detach and run in the background. In a native -Windows environment this means tinc will intall itself as a service, which will +Windows environment this means tinc will install itself as a service, which will restart after reboots. To prevent tinc from detaching or running as a service, use the -D option. diff --git a/THANKS b/THANKS index 7a8521a..4be771c 100644 --- a/THANKS +++ b/THANKS @@ -17,10 +17,12 @@ We would like to thank the following people for their contributions to tinc: * dnk * Enrique Zanardi * Florent Clairambault +* Florian Weik * Flynn Marquardt * Gary Kessler and Claudia Gonzalez * Grzegorz Dymarek * Hans Bayle +* Harvest * Ivo van Dong * James Cook * James MacLean @@ -38,6 +40,7 @@ We would like to thank the following people for their contributions to tinc: * Loïc Dachary * Loïc Grenié * Lubomír Bulej +* LunarShaddow * Mads Kiilerich * Marc A. Lehmann * Mark Glines @@ -52,16 +55,19 @@ We would like to thank the following people for their contributions to tinc: * Mesar Hameed * Michael Tokarev * Miles Nordin +* Nathan Stratton Treadway * Nick Hibma * Nick Patavalis * Paul Littlefield * Philipp Babel +* Rhosyn Celyn * Robert van der Meulen * Rumko * Sam Bryan * Saverio Proto * Scott Lamb * Steffan Karger +* Stig Fagrell * Sven-Haegar Koch * Teemu Kiviniemi * Thomas Tsiakalakis @@ -70,6 +76,7 @@ We would like to thank the following people for their contributions to tinc: * Tomislav Čohar * Tommy Arnkværn * Tonnerre Lombard +* Ulrich Seifert * Vil Brekin * Vittorio Gambaletta * Wessel Dankers diff --git a/compile b/compile index 531136b..a85b723 100755 --- a/compile +++ b/compile @@ -3,7 +3,7 @@ scriptversion=2012-10-14.11; # UTC -# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Copyright (C) 1999-2014 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify diff --git a/config.guess b/config.guess index 1f5c50c..1659250 100755 --- a/config.guess +++ b/config.guess @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2014 Free Software Foundation, Inc. +# Copyright 1992-2015 Free Software Foundation, Inc. -timestamp='2014-03-23' +timestamp='2015-08-20' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -24,12 +24,12 @@ timestamp='2014-03-23' # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # -# Originally written by Per Bothner. +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD # -# Please send patches with a ChangeLog entry to config-patches@gnu.org. +# Please send patches to . me=`echo "$0" | sed -e 's,.*/,,'` @@ -50,7 +50,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2014 Free Software Foundation, Inc. +Copyright 1992-2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -168,20 +168,27 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + /sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || \ + echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; + earmv*) + arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` + machine=${arch}${endian}-unknown + ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in - arm*|i386|m68k|ns32k|sh3*|sparc|vax) + arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ @@ -197,6 +204,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in os=netbsd ;; esac + # Determine ABI tags. + case "${UNAME_MACHINE_ARCH}" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` + ;; + esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need @@ -207,13 +221,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in release='-gnu' ;; *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" + echo "${machine}-${os}${release}${abi}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` @@ -235,6 +249,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; + *:Sortix:*:*) + echo ${UNAME_MACHINE}-unknown-sortix + exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) @@ -579,8 +596,9 @@ EOF else IBM_ARCH=powerpc fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi @@ -932,6 +950,9 @@ EOF crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; + e2k:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; @@ -1020,7 +1041,7 @@ EOF echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} diff --git a/config.h.in b/config.h.in index 0d7685a..2cf904a 100644 --- a/config.h.in +++ b/config.h.in @@ -53,6 +53,9 @@ don't. */ #undef HAVE_DECL_RES_INIT +/* Define to 1 if you have the `devname' function. */ +#undef HAVE_DEVNAME + /* Define to 1 if you have the header file. */ #undef HAVE_DIRENT_H @@ -65,6 +68,9 @@ /* Define to 1 if you have the `fchmod' function. */ #undef HAVE_FCHMOD +/* Define to 1 if you have the `fdevname' function. */ +#undef HAVE_FDEVNAME + /* Define to 1 if you have the `flock' function. */ #undef HAVE_FLOCK @@ -77,6 +83,12 @@ /* Define to 1 if you have the `ftime' function. */ #undef HAVE_FTIME +/* Define to 1 if you have the header file. */ +#undef HAVE_GETOPT_H + +/* getopt_long() */ +#undef HAVE_GETOPT_LONG + /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY @@ -179,6 +191,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NET_IF_TYPES_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_IF_UTUN_H + /* Define to 1 if you have the header file. */ #undef HAVE_NET_TAP_IF_TAP_H diff --git a/config.sub b/config.sub index bba4efb..1acc966 100755 --- a/config.sub +++ b/config.sub @@ -1,8 +1,8 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2014 Free Software Foundation, Inc. +# Copyright 1992-2015 Free Software Foundation, Inc. -timestamp='2014-09-11' +timestamp='2015-08-20' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -25,7 +25,7 @@ timestamp='2014-09-11' # of the GNU General Public License, version 3 ("GPLv3"). -# Please send patches with a ChangeLog entry to config-patches@gnu.org. +# Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. @@ -68,7 +68,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright 1992-2014 Free Software Foundation, Inc. +Copyright 1992-2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -117,7 +117,7 @@ maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os @@ -255,12 +255,13 @@ case $basic_machine in | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ + | ba \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ - | epiphany \ - | fido | fr30 | frv \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ @@ -305,7 +306,7 @@ case $basic_machine in | riscv32 | riscv64 \ | rl78 | rx \ | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ @@ -313,6 +314,7 @@ case $basic_machine in | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) @@ -327,6 +329,9 @@ case $basic_machine in c6x) basic_machine=tic6x-unknown ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none @@ -372,12 +377,13 @@ case $basic_machine in | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ + | ba-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ + | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ @@ -424,12 +430,13 @@ case $basic_machine in | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ + | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ @@ -437,6 +444,7 @@ case $basic_machine in | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ + | visium-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ @@ -513,6 +521,9 @@ case $basic_machine in basic_machine=i386-pc os=-aros ;; + asmjs) + basic_machine=asmjs-unknown + ;; aux) basic_machine=m68k-apple os=-aux @@ -774,6 +785,9 @@ case $basic_machine in basic_machine=m68k-isi os=-sysv ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` + ;; m68knommu) basic_machine=m68k-unknown os=-linux @@ -1365,7 +1379,7 @@ case $os in | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ diff --git a/configure b/configure index ccbe0f1..edd1c12 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for tinc 1.0.26. +# Generated by GNU Autoconf 2.69 for tinc 1.0.27. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -577,8 +577,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='tinc' PACKAGE_TARNAME='tinc' -PACKAGE_VERSION='1.0.26' -PACKAGE_STRING='tinc 1.0.26' +PACKAGE_VERSION='1.0.27' +PACKAGE_STRING='tinc 1.0.27' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -623,6 +623,8 @@ ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS +GETOPT_FALSE +GETOPT_TRUE TUNEMU_FALSE TUNEMU_TRUE VDE_FALSE @@ -1308,7 +1310,7 @@ if test "$ac_init_help" = "long"; then # 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. cat <<_ACEOF -\`configure' configures tinc 1.0.26 to adapt to many kinds of systems. +\`configure' configures tinc 1.0.27 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1378,7 +1380,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of tinc 1.0.26:";; + short | recursive ) echo "Configuration of tinc 1.0.27:";; esac cat <<\_ACEOF @@ -1497,7 +1499,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -tinc configure 1.0.26 +tinc configure 1.0.27 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1962,7 +1964,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by tinc $as_me 1.0.26, which was +It was created by tinc $as_me 1.0.27, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2826,7 +2828,7 @@ fi # Define the identity of the package. PACKAGE='tinc' - VERSION='1.0.26' + VERSION='1.0.27' cat >>confdefs.h <<_ACEOF @@ -2944,6 +2946,45 @@ fi MAINT=$MAINTAINER_MODE_TRUE +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=0;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + # Enable GNU extensions. # Define this here, not in acconfig's @TOP@ section, since definitions @@ -4768,6 +4809,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu + + # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 @@ -5598,7 +5641,7 @@ $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 +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 : 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" @@ -5611,7 +5654,7 @@ fi done -for ac_header in net/if.h net/if_types.h linux/if_tun.h net/if_tun.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 : 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\" @@ -6089,7 +6132,7 @@ cat >>confdefs.h <<_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 +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 do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -6102,6 +6145,24 @@ fi done +ac_fn_c_check_func "$LINENO" "getopt_long" "ac_cv_func_getopt_long" +if test "x$ac_cv_func_getopt_long" = xyes; then : + getopt=true; +$as_echo "#define HAVE_GETOPT_LONG 1" >>confdefs.h + +else + getopt=false +fi + + if test "$getopt" = true; then + GETOPT_TRUE= + GETOPT_FALSE='#' +else + GETOPT_TRUE='#' + GETOPT_FALSE= +fi + + ac_fn_c_check_func "$LINENO" "socket" "ac_cv_func_socket" if test "x$ac_cv_func_socket" = xyes; then : @@ -7045,6 +7106,10 @@ if test -z "${TUNEMU_TRUE}" && test -z "${TUNEMU_FALSE}"; then as_fn_error $? "conditional \"TUNEMU\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${GETOPT_TRUE}" && test -z "${GETOPT_FALSE}"; then + as_fn_error $? "conditional \"GETOPT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 @@ -7442,7 +7507,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by tinc $as_me 1.0.26, which was +This file was extended by tinc $as_me 1.0.27, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -7508,7 +7573,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -tinc config.status 1.0.26 +tinc config.status 1.0.27 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 41ddc6c..332b863 100644 --- a/configure.ac +++ b/configure.ac @@ -1,11 +1,12 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) -AC_INIT([tinc], [1.0.26]) +AC_INIT([tinc], [1.0.27]) AC_CONFIG_SRCDIR([src/tincd.c]) -AM_INIT_AUTOMAKE([1.11 check-news std-options subdir-objects nostdinc -Wall]) +AM_INIT_AUTOMAKE([1.11 check-news std-options subdir-objects nostdinc silent-rules -Wall]) AC_CONFIG_HEADERS([config.h]) AM_MAINTAINER_MODE +AM_SILENT_RULES([yes]) # Enable GNU extensions. # Define this here, not in acconfig's @TOP@ section, since definitions @@ -18,6 +19,8 @@ AC_PROG_CC_C99 AC_PROG_CPP AC_PROG_INSTALL +AM_PROG_CC_C_O + dnl Check and set OS AC_CANONICAL_HOST @@ -158,8 +161,8 @@ dnl Checks for header files. dnl We do this in multiple stages, because unlike Linux all the other operating systems really suck and don't include their own dependencies. AC_HEADER_STDC -AC_CHECK_HEADERS([stdbool.h syslog.h sys/file.h sys/ioctl.h sys/mman.h sys/param.h sys/resource.h sys/socket.h sys/time.h time.h sys/uio.h sys/wait.h netdb.h arpa/inet.h arpa/nameser.h dirent.h]) -AC_CHECK_HEADERS([net/if.h net/if_types.h linux/if_tun.h net/if_tun.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([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], [], [], [#include "src/have.h"] ) AC_CHECK_HEADERS([netinet/if_ether.h netinet/ip.h netinet/ip6.h resolv.h], @@ -185,10 +188,13 @@ AC_CHECK_TYPES([socklen_t, struct ether_header, struct arphdr, struct ether_arp, dnl Checks for library functions. AC_TYPE_SIGNAL -AC_CHECK_FUNCS([asprintf daemon fchmod flock ftime fork get_current_dir_name gettimeofday mlockall pselect putenv random select strdup strerror strsignal strtol system unsetenv usleep vsyslog writev], +AC_CHECK_FUNCS([asprintf daemon fchmod flock ftime fork get_current_dir_name gettimeofday mlockall pselect putenv random select strdup strerror strsignal strtol system unsetenv usleep vsyslog writev devname fdevname], [], [], [#include "src/have.h"] ) +AC_CHECK_FUNC(getopt_long, [getopt=true; AC_DEFINE(HAVE_GETOPT_LONG, 1, [getopt_long()])], [getopt=false]) +AM_CONDITIONAL(GETOPT, test "$getopt" = true) + dnl Support for SunOS AC_CHECK_FUNC(socket, [], [ diff --git a/debian/NEWS b/debian/NEWS new file mode 100644 index 0000000..b3eb367 --- /dev/null +++ b/debian/NEWS @@ -0,0 +1,14 @@ +tinc (1.0.27-1) unstable; urgency=medium + + This package now provides native systemd service files, allowing multiple + instances of tinc to be managed. Existing networks listed in + /etc/tinc/nets.boot will be converted to service instances once during this + upgrade. Afterwards, you can enable and disable networks using: + + systemctl enable tinc@ + systemctl disable tinc@ + + If you do not have systemd installed, the SysV init script will continue to + work as usual. For more information, see README.Debian. + + -- Guus Sliepen Sun, 10 Apr 2016 01:33:55 +0200 diff --git a/debian/README.Debian b/debian/README.Debian index 0572a79..d911295 100644 --- a/debian/README.Debian +++ b/debian/README.Debian @@ -1,17 +1,54 @@ tinc for Debian ----------------------- +--------------- The manual for tinc is also available as info pages, type `info tinc' to read it. -The system startup script for tinc, /etc/init.d/tinc, uses the file -/etc/tinc/nets.boot to find out which networks have to be started. +There are several ways in which tinc may be automatically started at boot: -Alternatively, you can create a stanza in /etc/network/interfaces, and add a -line with "tinc-net ". This will cause a tincd to be started which -uses the configuration from /etc/tinc/. You can use an inet static -(with address and netmask options) or inet dhcp stanza, in which case the ifup -will configure the VPN interface and you do not need to have a tinc-up script. +Systemd +------- + +Since 1.0.27-1, the tinc package comes with native systemd service files. +To enable and start a net, call: + +systemctl enable tinc@ +systemctl start tinc@ + +This will cause a tincd to be started which uses the configuration from +/etc/tinc/, and also makes sure that it will be started next time your +system boots. + +Apart from controlling individual instances, you can also start/stop/reload all +enabled instances simultaneously by omitting @, for example: + +systemctl reload tinc + +Note that when you have systemd installed on your system, the file +/etc/tinc/nets.boot will not be used anymore to automatically start tinc +daemons. If the variable EXTRA is defined in /etc/default/tinc, it will be +passed on to tinc. The variable LIMITS is however not used. + +The service files that come with this package start tinc unconditionally. +However, tinc does support socket activation. If you wish to write a socket +unit for tinc, use the ListenStream option to specify on which port(s) and +address(es) tinc should listen. + +SysVinit +-------- + +The system startup script for tinc, /etc/init.d/tinc, uses the file +/etc/tinc/nets.boot to find out which networks have to be started. Use one +netname per line. Lines starting with a # are ignored. + +/etc/network/interfaces +----------------------- + +You can create a stanza in /etc/network/interfaces, and add a line with +"tinc-net ". This will cause a tincd to be started which uses the +configuration from /etc/tinc/. You can use an inet static (with +address and netmask options) or inet dhcp stanza, in which case the ifup will +configure the VPN interface and you do not need to have a tinc-up script. The following options are also recognized and map directly to the corresponding command line options for tincd: @@ -37,7 +74,7 @@ iface vpn inet static This will start a tinc daemon that reads its configuration from /etc/tinc/myvpn, logs at debug level 1, locks itself in RAM, runs as user -nobody, writes the PID to /tmp/tinc.pid, and creates a network interface called -"vpn". Ifup then sets the address and netmask on that interface. +nobody, and creates a network interface called "vpn". Ifup then sets the +address and netmask on that interface. - -- Guus Sliepen , Fri, 25 June 2012, 20:28:35 +0200 + -- Guus Sliepen , Sun, 10 April 2016, 01:38:08 +0200 diff --git a/debian/changelog b/debian/changelog index 7083e60..7c2041c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,13 @@ +tinc (1.0.27-1) unstable; urgency=medium + + * New upstream release. + * Bump Standards-Version. + * Add native systemd unit files. + * Automatically convert networks listed in nets.boot to systemd service + instances on upgrade. + + -- Guus Sliepen Sun, 10 Apr 2016 01:39:16 +0200 + tinc (1.0.26-1) unstable; urgency=medium * New upstream release. diff --git a/debian/control b/debian/control index 7de8773..13b5e41 100644 --- a/debian/control +++ b/debian/control @@ -2,8 +2,8 @@ Source: tinc Section: net Priority: optional Maintainer: Guus Sliepen -Standards-Version: 3.9.6 -Build-Depends: libssl-dev, debhelper (>= 9), gettext, texinfo, zlib1g-dev, liblzo2-dev, libvdeplug-dev +Standards-Version: 3.9.7 +Build-Depends: libssl-dev, debhelper (>= 9), gettext, texinfo, zlib1g-dev, liblzo2-dev, libvdeplug-dev, dh-systemd Homepage: http://www.tinc-vpn.org/ Package: tinc diff --git a/debian/preinst b/debian/preinst new file mode 100644 index 0000000..721a2bd --- /dev/null +++ b/debian/preinst @@ -0,0 +1,28 @@ +#!/bin/sh + +NETSFILE="/etc/tinc/nets.boot" +SYSTEM="/lib/systemd/system" +WANTS="/etc/systemd/system/multi-user.target.wants" + +set -e + +case "$1" in + upgrade) + if dpkg --compare-versions "$2" '<<' "1.0.27-1"; then + if [ -f "$NETSFILE" ]; then + echo -n "Creating systemd service instances from nets.boot:" + mkdir -p "$WANTS" + egrep '^[ ]*[a-zA-Z0-9_-]+' $NETSFILE | while read net args; do + echo -n " $net" + ln -s "$SYSTEM/tinc@.service" "$WANTS/tinc@$net.service" 2>/dev/null || true + done + echo "." + fi + fi + ;; + + *) + ;; +esac + +#DEBHELPER# diff --git a/debian/rules b/debian/rules index 2aaaef9..e692096 100755 --- a/debian/rules +++ b/debian/rules @@ -1,16 +1,7 @@ #!/usr/bin/make -f -# -*- makefile -*- -# Sample debian/rules that uses debhelper. -# This file was originally written by Joey Hess and Craig Small. -# As a special exception, when this file is copied by dh-make into a -# dh-make output file, you may use that output file without restriction. -# This special exception was added by Craig Small in version 0.37 of dh-make. - -# Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 %: - dh $@ --parallel + dh $@ --parallel --with systemd override_dh_auto_configure: dh_auto_configure -- --enable-uml --enable-vde @@ -22,7 +13,7 @@ override_dh_auto_install: override_dh_installinit: dh_installinit -R + dh_installinit --name=tinc@ --noscripts -override_dh_clean: - dh_clean - rm -f src/device.c +override_dh_systemd_start: + dh_systemd_start --restart-after-upgrade diff --git a/debian/tinc.service b/debian/tinc.service new file mode 100644 index 0000000..1f015f0 --- /dev/null +++ b/debian/tinc.service @@ -0,0 +1,16 @@ +# This is a mostly empty service, but allows commands like stop, start, reload +# to propagate to all tinc@ service instances. + +[Unit] +Description=Tinc VPN +After=network.target + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/bin/true +ExecReload=/bin/true +WorkingDirectory=/etc/tinc + +[Install] +WantedBy=multi-user.target diff --git a/debian/tinc@.service b/debian/tinc@.service new file mode 100644 index 0000000..de5c1b1 --- /dev/null +++ b/debian/tinc@.service @@ -0,0 +1,17 @@ +[Unit] +Description=Tinc net %i +PartOf=tinc.service +ReloadPropagatedFrom=tinc.service + +[Service] +Type=simple +WorkingDirectory=/etc/tinc/%i +ExecStart=/usr/sbin/tinc -n %i start -D +ExecReload=/usr/sbin/tinc -n %i reload +ExecStop=/usr/sbin/tinc -n %i stop +TimeoutStopSec=5 +Restart=always +RestartSec=60 + +[Install] +WantedBy=tinc.service diff --git a/depcomp b/depcomp index 4ebd5b3..fc98710 100755 --- a/depcomp +++ b/depcomp @@ -3,7 +3,7 @@ scriptversion=2013-05-30.07; # UTC -# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Copyright (C) 1999-2014 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/doc/Makefile.am b/doc/Makefile.am index 8e854bc..91b5b8d 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -17,16 +17,16 @@ transform = s/ginstall/install/; @program_transform_name@ # see GNUmakefile and Makefile.maint. sample-config.tar.gz: sample-config - GZIP=$(GZIP_ENV) $(AMTAR) chozf sample-config.tar.gz --exclude .svn sample-config + $(AM_V_GEN)GZIP=$(GZIP_ENV) $(AMTAR) chozf sample-config.tar.gz --exclude .svn sample-config texi2html: tinc.texi - texi2html -split=chapter tinc.texi + $(AM_V_GEN)texi2html -split=chapter tinc.texi tincd.8.html: tincd.8 - w3mman2html $< > $@ + $(AM_V_GEN)w3mman2html $< > $@ tinc.conf.5.html: tinc.conf.5 - w3mman2html $< > $@ + $(AM_V_GEN)w3mman2html $< > $@ substitute = sed \ -e s,'@PACKAGE\@',"$(PACKAGE)",g \ @@ -35,12 +35,12 @@ substitute = sed \ -e s,'@localstatedir\@',"$(localstatedir)",g tincd.8: tincd.8.in - $(substitute) tincd.8.in > tincd.8 + $(AM_V_GEN)$(substitute) tincd.8.in > tincd.8 tinc.conf.5: tinc.conf.5.in - $(substitute) tinc.conf.5.in > tinc.conf.5 + $(AM_V_GEN)$(substitute) tinc.conf.5.in > tinc.conf.5 tincinclude.texi: tincinclude.texi.in - $(substitute) tincinclude.texi.in > tincinclude.texi + $(AM_V_GEN)$(substitute) tincinclude.texi.in > tincinclude.texi tinc.texi: tincinclude.texi diff --git a/doc/Makefile.in b/doc/Makefile.in index dbee0d9..1630d9b 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -14,7 +14,17 @@ @SET_MAKE@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -77,7 +87,6 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = doc -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am texinfo.tex ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ $(top_srcdir)/m4/ax_check_compile_flag.m4 \ @@ -86,6 +95,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.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 = @@ -183,6 +193,7 @@ man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man_MANS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in texinfo.tex DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) # Use `ginstall' in the definition of man_MANS to avoid @@ -277,6 +288,7 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -311,7 +323,6 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu doc/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -812,30 +823,32 @@ uninstall-man: uninstall-man5 uninstall-man8 uninstall-html-am uninstall-info-am uninstall-man \ uninstall-man5 uninstall-man8 uninstall-pdf-am uninstall-ps-am +.PRECIOUS: Makefile + # For additional rules usually of interest only to the maintainer, # see GNUmakefile and Makefile.maint. sample-config.tar.gz: sample-config - GZIP=$(GZIP_ENV) $(AMTAR) chozf sample-config.tar.gz --exclude .svn sample-config + $(AM_V_GEN)GZIP=$(GZIP_ENV) $(AMTAR) chozf sample-config.tar.gz --exclude .svn sample-config texi2html: tinc.texi - texi2html -split=chapter tinc.texi + $(AM_V_GEN)texi2html -split=chapter tinc.texi tincd.8.html: tincd.8 - w3mman2html $< > $@ + $(AM_V_GEN)w3mman2html $< > $@ tinc.conf.5.html: tinc.conf.5 - w3mman2html $< > $@ + $(AM_V_GEN)w3mman2html $< > $@ tincd.8: tincd.8.in - $(substitute) tincd.8.in > tincd.8 + $(AM_V_GEN)$(substitute) tincd.8.in > tincd.8 tinc.conf.5: tinc.conf.5.in - $(substitute) tinc.conf.5.in > tinc.conf.5 + $(AM_V_GEN)$(substitute) tinc.conf.5.in > tinc.conf.5 tincinclude.texi: tincinclude.texi.in - $(substitute) tincinclude.texi.in > tincinclude.texi + $(AM_V_GEN)$(substitute) tincinclude.texi.in > tincinclude.texi tinc.texi: tincinclude.texi diff --git a/doc/sample-config.tar.gz b/doc/sample-config.tar.gz index e6875ef..e960bec 100644 Binary files a/doc/sample-config.tar.gz and b/doc/sample-config.tar.gz differ diff --git a/doc/tinc.conf.5.in b/doc/tinc.conf.5.in index d1b2673..e5b59d7 100644 --- a/doc/tinc.conf.5.in +++ b/doc/tinc.conf.5.in @@ -1,4 +1,4 @@ -.Dd 2014-05-11 +.Dd 2016-04-10 .Dt TINC.CONF 5 .\" Manual page created by: .\" Ivo Timmermans @@ -54,7 +54,7 @@ But it is highly recommended that you use this feature of because it will be so much clearer whom your daemon talks to. Hence, we will assume that you use it. .Sh NAMES -Each tinc daemon should have a name that is unique in the network which it will be part of. +Each tinc daemon must have a name that is unique in the network which it will be part of. The name will be used by other tinc daemons for identification. The name has to be declared in the .Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf @@ -250,6 +250,10 @@ Tinc will expect packets read from the virtual network device to start with a four byte header containing the address family, followed by an IP header. This mode should support both IPv4 and IPv6 packets. +.It utun Pq OS X +Set type to utun. +This is only supported on OS X version 10.6.8 and higher, but doesn't require the tuntaposx module. +This mode should support both IPv4 and IPv6 packets. .It tap Pq BSD and Linux Set type to tap. Tinc will expect packets read from the virtual network device @@ -362,7 +366,7 @@ If .Va Name is .Li $HOST , -but no such environment variable exist, the hostname will be read using the gethostnname() system call. +but no such environment variable exist, the hostname will be read using the gethostname() system call. .It Va PingInterval Li = Ar seconds Pq 60 The number of seconds of inactivity that .Nm tinc @@ -556,7 +560,15 @@ UDP is possible or not. .Sh SCRIPTS Apart from reading the server and host configuration files, tinc can also run scripts at certain moments. -Under Windows (not Cygwin), the scripts should have the extension +Below is a list of filenames of scripts and a description of when they are run. +A script is only run if it exists and if it is executable. +.Pp +Scripts are run synchronously; +this means that tinc will temporarily stop processing packets until the called script finishes executing. +This guarantees that scripts will execute in the exact same order as the events that trigger them. +If you need to run commands asynchronously, you have to ensure yourself that they are being run in the background. +.Pp +Under Windows (not Cygwin), the scripts must have the extension .Pa .bat . .Bl -tag -width indent .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up @@ -564,6 +576,7 @@ This is the most important script. If it is present it will be executed right after the tinc daemon has been started and has connected to the virtual network device. It should be used to set up the corresponding network interface, but can also be used to start other things. +.Pp Under Windows you can use the Network Connections control panel instead of creating this script. .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-down This script is started right before the tinc daemon quits. diff --git a/doc/tinc.info b/doc/tinc.info index 1604bc4..0dcb528 100644 --- a/doc/tinc.info +++ b/doc/tinc.info @@ -1,14 +1,14 @@ -This is tinc.info, produced by makeinfo version 5.2 from tinc.texi. +This is tinc.info, produced by makeinfo version 6.1 from tinc.texi. INFO-DIR-SECTION Networking tools START-INFO-DIR-ENTRY * tinc: (tinc). The tinc Manual. END-INFO-DIR-ENTRY -This is the info manual for tinc version 1.0.25, a Virtual Private +This is the info manual for tinc version 1.0.27, a Virtual Private Network daemon. - Copyright (C) 1998-2014 Ivo Timmermans, Guus Sliepen + Copyright (C) 1998-2016 Ivo Timmermans, Guus Sliepen and Wessel Dankers . Permission is granted to make and distribute verbatim copies of this @@ -257,10 +257,16 @@ File: tinc.info, Node: Configuration of Darwin (Mac OS X) kernels, Next: Confi ------------------------------------------------ Tinc on Darwin relies on a tunnel driver for its data acquisition from -the kernel. Tinc supports either the driver from +the kernel. OS X version 10.6.8 and later have a built-in tun driver +called "utun". Tinc also supports the driver from , which supports both tun and tap style devices. + By default, tinc expects the tuntaposx driver to be installed. To +use the utun driver, set add 'Device = utunX' to 'tinc.conf', where X is +the desired number for the utun interface. You can also omit the +number, in which case the first free number will be chosen. +  File: tinc.info, Node: Configuration of Windows, Prev: Configuration of Darwin (Mac OS X) kernels, Up: Configuring the kernel @@ -816,6 +822,11 @@ DeviceType = (platform dependent) followed by an IP header. This mode should support both IPv4 and IPv6 packets. + utun (OS X) + Set type to utun. This is only supported on OS X version + 10.6.8 and higher, but doesn't require the tuntaposx module. + This mode should support both IPv4 and IPv6 packets. + tap (BSD and Linux) Set type to tap. Tinc will expect packets read from the virtual network device to start with an Ethernet header. @@ -931,15 +942,15 @@ Mode = (router) routing table is managed. Name = [required] - This is a symbolic name for this connection. The name should - consist only of alphanumeric and underscore characters (a-z, A-Z, - 0-9 and _). + This is a symbolic name for this connection. The name must consist + only of alphanumeric and underscore characters (a-z, A-Z, 0-9 and + _). If Name starts with a $, then the contents of the environment variable that follows will be used. In that case, invalid characters will be converted to underscores. If Name is $HOST, but no such environment variable exist, the hostname will be read using - the gethostnname() system call. + the gethostname() system call. PingInterval = (60) The number of seconds of inactivity that tinc will wait before @@ -972,7 +983,7 @@ ProcessPriority = adjusted. Increasing the priority may help to reduce latency and packet loss on the VPN. -Proxy = socks4 | socks5 | http | exec ... [experimental] +Proxy = socks4 | socks5 | http | exec ... [experimental] Use a proxy when making outgoing connections. The following proxy types are currently supported: @@ -1152,16 +1163,27 @@ File: tinc.info, Node: Scripts, Next: How to configure, Prev: Host configurat ------------- Apart from reading the server and host configuration files, tinc can -also run scripts at certain moments. Under Windows (not Cygwin), the -scripts should have the extension .bat. +also run scripts at certain moments. Below is a list of filenames of +scripts and a description of when they are run. A script is only run if +it exists and if it is executable. + + Scripts are run synchronously; this means that tinc will temporarily +stop processing packets until the called script finishes executing. +This guarantees that scripts will execute in the exact same order as the +events that trigger them. If you need to run commands asynchronously, +you have to ensure yourself that they are being run in the background. + + Under Windows (not Cygwin), the scripts must have the extension .bat. '/etc/tinc/NETNAME/tinc-up' This is the most important script. If it is present it will be executed right after the tinc daemon has been started and has connected to the virtual network device. It should be used to set up the corresponding network interface, but can also be used to - start other things. Under Windows you can use the Network - Connections control panel instead of creating this script. + start other things. + + Under Windows you can use the Network Connections control panel + instead of creating this script. '/etc/tinc/NETNAME/tinc-down' This script is started right before the tinc daemon quits. @@ -2449,86 +2471,86 @@ Concept Index * DEL_SUBNET: The meta-protocol. (line 46) * Device: Main configuration variables. (line 73) -* DEVICE: Scripts. (line 53) +* DEVICE: Scripts. (line 64) * device files: Device files. (line 6) * DeviceType: Main configuration variables. (line 79) * Digest: Host configuration variables. (line 31) * DirectOnly: Main configuration variables. - (line 144) + (line 149) * dummy: Main configuration variables. (line 86) * encapsulating: The UDP tunnel. (line 30) * encryption: Encryption of network packets. (line 6) -* environment variables: Scripts. (line 42) +* environment variables: Scripts. (line 53) * example: Example configuration. (line 6) * exec: Main configuration variables. - (line 314) + (line 319) * Forwarding: Main configuration variables. - (line 151) + (line 156) * frame type: The UDP tunnel. (line 6) * GraphDumpFile: Main configuration variables. - (line 171) + (line 176) * Hostnames: Main configuration variables. - (line 179) + (line 184) * http: Main configuration variables. - (line 311) + (line 316) * hub: Main configuration variables. - (line 249) + (line 254) * ID: Authentication protocol. (line 10) * IffOneQueue: Main configuration variables. - (line 190) + (line 195) * IndirectData: Host configuration variables. (line 36) * Interface: Main configuration variables. - (line 193) -* INTERFACE: Scripts. (line 56) + (line 198) +* INTERFACE: Scripts. (line 67) * IRC: Contact information. (line 9) * key generation: Generating keypairs. (line 6) * KeyExpire: Main configuration variables. - (line 201) + (line 206) * KEY_CHANGED: The meta-protocol. (line 63) * libraries: Libraries. (line 6) * license: OpenSSL. (line 35) * LocalDiscovery: Main configuration variables. - (line 207) + (line 212) * lzo: lzo. (line 6) * MACExpire: Main configuration variables. - (line 218) + (line 223) * MACLength: Host configuration variables. (line 44) * MaxTimeout: Main configuration variables. - (line 223) + (line 228) * meta-protocol: The meta-connection. (line 18) * META_KEY: Authentication protocol. (line 10) * Mode: Main configuration variables. - (line 227) + (line 232) * multicast: Main configuration variables. (line 98) * multiple networks: Multiple networks. (line 6) * Name: Main configuration variables. - (line 254) -* NAME: Scripts. (line 50) + (line 259) +* NAME: Scripts. (line 61) * netmask: Network interfaces. (line 33) * netname: Multiple networks. (line 6) -* NETNAME: Scripts. (line 47) +* NETNAME: Scripts. (line 58) * Network Administrators Guide: Configuration introduction. (line 15) -* NODE: Scripts. (line 60) +* NODE: Scripts. (line 71) * OpenSSL: OpenSSL. (line 6) * options: Runtime options. (line 9) * PEM format: Host configuration variables. (line 69) * PING: The meta-protocol. (line 88) * PingInterval: Main configuration variables. - (line 265) + (line 270) * PingTimeout: Main configuration variables. - (line 269) + (line 274) * platforms: Supported platforms. (line 6) * PMTU: Host configuration variables. (line 49) @@ -2539,17 +2561,17 @@ Concept Index (line 57) * port numbers: Other files. (line 17) * PriorityInheritance: Main configuration variables. - (line 275) + (line 280) * private: Virtual Private Networks. (line 10) * PrivateKey: Main configuration variables. - (line 280) + (line 285) * PrivateKeyFile: Main configuration variables. - (line 286) -* ProcessPriority: Main configuration variables. (line 291) -* Proxy: Main configuration variables. +* ProcessPriority: Main configuration variables. (line 296) +* Proxy: Main configuration variables. + (line 301) * PublicKey: Host configuration variables. (line 61) * PublicKeyFile: Host configuration variables. @@ -2557,14 +2579,14 @@ Concept Index * raw_socket: Main configuration variables. (line 91) * release: Supported platforms. (line 14) -* REMOTEADDRESS: Scripts. (line 65) -* REMOTEPORT: Scripts. (line 68) +* REMOTEADDRESS: Scripts. (line 76) +* REMOTEPORT: Scripts. (line 79) * ReplayWindow: Main configuration variables. - (line 319) + (line 324) * requirements: Libraries. (line 6) * REQ_KEY: The meta-protocol. (line 63) * router: Main configuration variables. - (line 230) + (line 235) * runtime options: Runtime options. (line 9) * scalability: tinc. (line 19) * scripts: Scripts. (line 6) @@ -2572,46 +2594,48 @@ Concept Index (line 18) * signals: Signals. (line 6) * socks4: Main configuration variables. - (line 300) -* socks5: Main configuration variables. (line 305) +* socks5: Main configuration variables. + (line 310) * StrictSubnets: Main configuration variables. - (line 330) + (line 335) * Subnet: Host configuration variables. (line 76) -* SUBNET: Scripts. (line 72) +* SUBNET: Scripts. (line 83) * Subnet weight: Host configuration variables. (line 98) * SVPN: Security. (line 11) * switch: Main configuration variables. - (line 238) + (line 243) * TCP: The meta-connection. (line 10) * TCPonly: Host configuration variables. (line 105) * tinc: Introduction. (line 6) * TINC: Security. (line 6) -* tinc-down: Scripts. (line 18) -* tinc-up: Scripts. (line 10) +* tinc-down: Scripts. (line 29) +* tinc-up: Scripts. (line 19) * tinc-up <1>: Network interfaces. (line 19) * tincd: tinc. (line 14) * traditional VPNs: tinc. (line 19) * tunifhead: Main configuration variables. (line 133) * TunnelServer: Main configuration variables. - (line 337) + (line 342) * tunnohead: Main configuration variables. (line 127) * UDP: The UDP tunnel. (line 30) * UDP <1>: Encryption of network packets. (line 12) * UDPRcvBuf: Main configuration variables. - (line 344) -* UDPSndBuf: Main configuration variables. (line 349) +* UDPSndBuf: Main configuration variables. + (line 354) * UML: Main configuration variables. (line 109) * Universal tun/tap: Configuration of Linux kernels. (line 6) +* utun: Main configuration variables. + (line 140) * VDE: Main configuration variables. (line 114) * virtual: Virtual Private Networks. @@ -2621,7 +2645,7 @@ Concept Index (line 6) * vpnd: tinc. (line 6) * website: Contact information. (line 6) -* WEIGHT: Scripts. (line 75) +* WEIGHT: Scripts. (line 86) * zlib: zlib. (line 6) @@ -2640,53 +2664,53 @@ Node: Configuration of OpenBSD kernels7852 Node: Configuration of NetBSD kernels8460 Node: Configuration of Solaris kernels8865 Node: Configuration of Darwin (Mac OS X) kernels9527 -Node: Configuration of Windows10005 -Node: Libraries10519 -Node: OpenSSL10907 -Node: zlib13195 -Node: lzo14223 -Node: Installation15205 -Node: Building and installing tinc16220 -Node: Darwin (Mac OS X) build environment16880 -Node: Cygwin (Windows) build environment17462 -Node: MinGW (Windows) build environment18050 -Node: System files18574 -Node: Device files18839 -Node: Other files19255 -Node: Configuration19868 -Node: Configuration introduction20179 -Node: Multiple networks21447 -Node: How connections work22873 -Node: Configuration files24095 -Node: Main configuration variables25589 -Node: Host configuration variables41628 -Node: Scripts47131 -Node: How to configure49894 -Node: Generating keypairs51152 -Node: Network interfaces51651 -Node: Example configuration53499 -Node: Running tinc58824 -Node: Runtime options59414 -Node: Signals62716 -Node: Debug levels63907 -Node: Solving problems64843 -Node: Error messages66395 -Node: Sending bug reports70404 -Node: Technical information71351 -Node: The connection71582 -Node: The UDP tunnel71894 -Node: The meta-connection74955 -Node: The meta-protocol76424 -Node: Security81441 -Node: Authentication protocol82574 -Node: Encryption of network packets87619 -Node: Security issues88995 -Node: Platform specific information90622 -Node: Interface configuration90850 -Node: Routes93321 -Node: About us95335 -Node: Contact information95510 -Node: Authors95914 -Node: Concept Index96319 +Node: Configuration of Windows10346 +Node: Libraries10860 +Node: OpenSSL11248 +Node: zlib13536 +Node: lzo14564 +Node: Installation15546 +Node: Building and installing tinc16561 +Node: Darwin (Mac OS X) build environment17221 +Node: Cygwin (Windows) build environment17803 +Node: MinGW (Windows) build environment18391 +Node: System files18915 +Node: Device files19180 +Node: Other files19596 +Node: Configuration20209 +Node: Configuration introduction20520 +Node: Multiple networks21788 +Node: How connections work23214 +Node: Configuration files24436 +Node: Main configuration variables25930 +Node: Host configuration variables42187 +Node: Scripts47690 +Node: How to configure50956 +Node: Generating keypairs52214 +Node: Network interfaces52713 +Node: Example configuration54561 +Node: Running tinc59886 +Node: Runtime options60476 +Node: Signals63778 +Node: Debug levels64969 +Node: Solving problems65905 +Node: Error messages67457 +Node: Sending bug reports71466 +Node: Technical information72413 +Node: The connection72644 +Node: The UDP tunnel72956 +Node: The meta-connection76017 +Node: The meta-protocol77486 +Node: Security82503 +Node: Authentication protocol83636 +Node: Encryption of network packets88681 +Node: Security issues90057 +Node: Platform specific information91684 +Node: Interface configuration91912 +Node: Routes94383 +Node: About us96397 +Node: Contact information96572 +Node: Authors96976 +Node: Concept Index97381  End Tag Table diff --git a/doc/tinc.texi b/doc/tinc.texi index 608077f..414c0ca 100644 --- a/doc/tinc.texi +++ b/doc/tinc.texi @@ -15,7 +15,7 @@ This is the info manual for @value{PACKAGE} version @value{VERSION}, a Virtual Private Network daemon. -Copyright @copyright{} 1998-2014 Ivo Timmermans, +Copyright @copyright{} 1998-2016 Ivo Timmermans, Guus Sliepen and Wessel Dankers . @@ -39,7 +39,7 @@ permission notice identical to this one. @vskip 0pt plus 1filll This is the info manual for @value{PACKAGE} version @value{VERSION}, a Virtual Private Network daemon. -Copyright @copyright{} 1998-2014 Ivo Timmermans, +Copyright @copyright{} 1998-2016 Ivo Timmermans, Guus Sliepen and Wessel Dankers . @@ -302,9 +302,15 @@ If the @file{net/if_tun.h} header file is missing, install it from the source pa @subsection Configuration of Darwin (Mac OS X) kernels Tinc on Darwin relies on a tunnel driver for its data acquisition from the kernel. -Tinc supports either the driver from @uref{http://tuntaposx.sourceforge.net/}, +OS X version 10.6.8 and later have a built-in tun driver called "utun". +Tinc also supports the driver from @uref{http://tuntaposx.sourceforge.net/}, which supports both tun and tap style devices. +By default, tinc expects the tuntaposx driver to be installed. +To use the utun driver, set add @code{Device = utunX} to @file{tinc.conf}, +where X is the desired number for the utun interface. +You can also omit the number, in which case the first free number will be chosen. + @c ================================================================== @node Configuration of Windows @@ -892,6 +898,12 @@ to start with a four byte header containing the address family, followed by an IP header. This mode should support both IPv4 and IPv6 packets. +@cindex utun +@item utun (OS X) +Set type to utun. +This is only supported on OS X version 10.6.8 and higher, but doesn't require the tuntaposx module. +This mode should support both IPv4 and IPv6 packets. + @item tap (BSD and Linux) Set type to tap. Tinc will expect packets read from the virtual network device @@ -1014,12 +1026,12 @@ while no routing table is managed. @cindex Name @item Name = <@var{name}> [required] This is a symbolic name for this connection. -The name should consist only of alphanumeric and underscore characters (a-z, A-Z, 0-9 and _). +The name must consist only of alphanumeric and underscore characters (a-z, A-Z, 0-9 and _). If Name starts with a $, then the contents of the environment variable that follows will be used. In that case, invalid characters will be converted to underscores. If Name is $HOST, but no such environment variable exist, -the hostname will be read using the gethostnname() system call. +the hostname will be read using the gethostname() system call. @cindex PingInterval @item PingInterval = <@var{seconds}> (60) @@ -1256,7 +1268,15 @@ UDP is possible or not. @cindex scripts Apart from reading the server and host configuration files, tinc can also run scripts at certain moments. -Under Windows (not Cygwin), the scripts should have the extension .bat. +Below is a list of filenames of scripts and a description of when they are run. +A script is only run if it exists and if it is executable. + +Scripts are run synchronously; +this means that tinc will temporarily stop processing packets until the called script finishes executing. +This guarantees that scripts will execute in the exact same order as the events that trigger them. +If you need to run commands asynchronously, you have to ensure yourself that they are being run in the background. + +Under Windows (not Cygwin), the scripts must have the extension .bat. @table @file @cindex tinc-up @@ -1266,6 +1286,7 @@ If it is present it will be executed right after the tinc daemon has been started and has connected to the virtual network device. It should be used to set up the corresponding network interface, but can also be used to start other things. + Under Windows you can use the Network Connections control panel instead of creating this script. @cindex tinc-down diff --git a/install-sh b/install-sh index 377bb86..59990a1 100755 --- a/install-sh +++ b/install-sh @@ -1,7 +1,7 @@ #!/bin/sh # install - install a program, script, or datafile -scriptversion=2011-11-20.07; # UTC +scriptversion=2014-09-12.12; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the @@ -41,19 +41,15 @@ scriptversion=2011-11-20.07; # UTC # This script is compatible with the BSD install script, but was written # from scratch. +tab=' ' nl=' ' -IFS=" "" $nl" +IFS=" $tab$nl" -# set DOITPROG to echo to test this script +# Set DOITPROG to "echo" to test this script. -# Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} -if test -z "$doit"; then - doit_exec=exec -else - doit_exec=$doit -fi +doit_exec=${doit:-exec} # Put in absolute file names if you don't have them in your path; # or use environment vars. @@ -68,17 +64,6 @@ mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} -posix_glob='?' -initialize_posix_glob=' - test "$posix_glob" != "?" || { - if (set -f) 2>/dev/null; then - posix_glob= - else - posix_glob=: - fi - } -' - posix_mkdir= # Desired mode of installed file. @@ -97,7 +82,7 @@ dir_arg= dst_arg= copy_on_change=false -no_target_directory= +is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE @@ -137,46 +122,57 @@ while test $# -ne 0; do -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" - shift;; + shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 - case $mode in - *' '* | *' '* | *' -'* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - shift;; + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; -o) chowncmd="$chownprog $2" - shift;; + shift;; -s) stripcmd=$stripprog;; - -t) dst_arg=$2 - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - shift;; + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; - -T) no_target_directory=true;; + -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; - --) shift - break;; + --) shift + break;; - -*) echo "$0: invalid option: $1" >&2 - exit 1;; + -*) echo "$0: invalid option: $1" >&2 + exit 1;; *) break;; esac shift done +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. @@ -207,6 +203,15 @@ if test $# -eq 0; then exit 0 fi +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 @@ -223,16 +228,16 @@ if test -z "$dir_arg"; then *[0-7]) if test -z "$stripcmd"; then - u_plus_rw= + u_plus_rw= else - u_plus_rw='% 200' + u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then - u_plus_rw= + u_plus_rw= else - u_plus_rw=,u+rw + u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac @@ -269,41 +274,15 @@ do # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dst_arg: Is a directory" >&2 - exit 1 + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else - # Prefer dirname, but fall back on a substitute if dirname fails. - dstdir=` - (dirname "$dst") 2>/dev/null || - expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$dst" : 'X\(//\)[^/]' \| \ - X"$dst" : 'X\(//\)$' \| \ - X"$dst" : 'X\(/\)' \| . 2>/dev/null || - echo X"$dst" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q' - ` - + dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi @@ -314,74 +293,81 @@ do if test $dstdir_status != 0; then case $posix_mkdir in '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac - # With -d, create the new directory with the user-specified mode. - # Otherwise, rely on $mkdir_umask. - if test -n "$dir_arg"; then - mkdir_mode=-m$mode - else - mkdir_mode= - fi + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi - posix_mkdir=false - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + # $RANDOM is not portable (e.g. dash); use it when possible to + # lower collision chance + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 - if (umask $mkdir_umask && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - ls_ld_tmpdir=`ls -ld "$tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/d" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null - fi - trap '' 0;; - esac;; + # As "mkdir -p" follows symlinks and we work in /tmp possibly; so + # create the $tmpdir first (and fail if unsuccessful) to make sure + # that nobody tries to guess the $tmpdir name. + if (umask $mkdir_umask && + $mkdirprog $mkdir_mode "$tmpdir" && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + test_tmpdir="$tmpdir/a" + ls_ld_tmpdir=`ls -ld "$test_tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null + fi + trap '' 0;; + esac;; esac if $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else @@ -391,53 +377,51 @@ do # directory the slow way, step by step, checking for races as we go. case $dstdir in - /*) prefix='/';; - [-=\(\)!]*) prefix='./';; - *) prefix='';; + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; esac - eval "$initialize_posix_glob" - oIFS=$IFS IFS=/ - $posix_glob set -f + set -f set fnord $dstdir shift - $posix_glob set +f + set +f IFS=$oIFS prefixes= for d do - test X"$d" = X && continue + test X"$d" = X && continue - prefix=$prefix$d - if test -d "$prefix"; then - prefixes= - else - if $posix_mkdir; then - (umask=$mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break - # Don't fail if two instances are running concurrently. - test -d "$prefix" || exit 1 - else - case $prefix in - *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; - *) qprefix=$prefix;; - esac - prefixes="$prefixes '$qprefix'" - fi - fi - prefix=$prefix/ + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ done if test -n "$prefixes"; then - # Don't fail if two instances are running concurrently. - (umask $mkdir_umask && - eval "\$doit_exec \$mkdirprog $prefixes") || - test -d "$dstdir" || exit 1 - obsolete_mkdir_used=true + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true fi fi fi @@ -472,15 +456,12 @@ do # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && - old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && - new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && - - eval "$initialize_posix_glob" && - $posix_glob set -f && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && - $posix_glob set +f && - + set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then @@ -493,24 +474,24 @@ do # to itself, or perhaps because mv is so ancient that it does not # support -f. { - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - test ! -f "$dst" || - $doit $rmcmd -f "$dst" 2>/dev/null || - { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } - } || - { echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - } && + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 diff --git a/m4/Makefile.in b/m4/Makefile.in index 866a7d4..ef5c2d8 100644 --- a/m4/Makefile.in +++ b/m4/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -14,7 +14,17 @@ @SET_MAKE@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -78,7 +88,6 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = m4 -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am README ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ $(top_srcdir)/m4/ax_check_compile_flag.m4 \ @@ -87,6 +96,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.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 = @@ -111,6 +121,7 @@ am__can_run_installinfo = \ *) (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@ @@ -200,6 +211,7 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -224,7 +236,6 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu m4/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu m4/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -392,6 +403,8 @@ uninstall-am: 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. diff --git a/missing b/missing index db98974..f62bbae 100755 --- a/missing +++ b/missing @@ -3,7 +3,7 @@ scriptversion=2013-10-28.13; # UTC -# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Copyright (C) 1996-2014 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify diff --git a/src/Makefile.am b/src/Makefile.am index 937800d..a5a9692 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -17,8 +17,6 @@ tincd_SOURCES = \ fake-gai-errnos.h \ fake-getaddrinfo.c fake-getaddrinfo.h \ fake-getnameinfo.c fake-getnameinfo.h \ - getopt.c getopt.h \ - getopt1.c \ graph.c graph.h \ ipv4.h \ ipv6.h \ @@ -40,6 +38,7 @@ tincd_SOURCES = \ protocol_misc.c \ protocol_key.c \ protocol_subnet.c \ + proxy.c proxy.h \ raw_socket_device.c \ route.c route.h \ subnet.c subnet.h \ @@ -48,6 +47,12 @@ tincd_SOURCES = \ xalloc.h \ xmalloc.c +if !GETOPT +tincd_SOURCES += \ + getopt.c getopt.h \ + getopt1.c +endif + if LINUX tincd_SOURCES += linux/device.c endif diff --git a/src/Makefile.in b/src/Makefile.in index 96f170d..bfff5d3 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -15,7 +15,17 @@ @SET_MAKE@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -79,18 +89,20 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ sbin_PROGRAMS = tincd$(EXEEXT) -@LINUX_TRUE@am__append_1 = linux/device.c -@BSD_TRUE@am__append_2 = bsd/device.c -@BSD_TRUE@@TUNEMU_TRUE@am__append_3 = bsd/tunemu.c bsd/tunemu.h -@SOLARIS_TRUE@am__append_4 = solaris/device.c -@MINGW_TRUE@am__append_5 = mingw/device.c mingw/common.h -@CYGWIN_TRUE@am__append_6 = cygwin/device.c -@UML_TRUE@am__append_7 = uml_device.c -@VDE_TRUE@am__append_8 = vde_device.c -@TUNEMU_TRUE@am__append_9 = -lpcap +@GETOPT_FALSE@am__append_1 = \ +@GETOPT_FALSE@ getopt.c getopt.h \ +@GETOPT_FALSE@ getopt1.c + +@LINUX_TRUE@am__append_2 = linux/device.c +@BSD_TRUE@am__append_3 = bsd/device.c +@BSD_TRUE@@TUNEMU_TRUE@am__append_4 = bsd/tunemu.c bsd/tunemu.h +@SOLARIS_TRUE@am__append_5 = solaris/device.c +@MINGW_TRUE@am__append_6 = mingw/device.c mingw/common.h +@CYGWIN_TRUE@am__append_7 = cygwin/device.c +@UML_TRUE@am__append_8 = uml_device.c +@VDE_TRUE@am__append_9 = vde_device.c +@TUNEMU_TRUE@am__append_10 = -lpcap subdir = src -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ $(top_srcdir)/m4/ax_check_compile_flag.m4 \ @@ -99,6 +111,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.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 = @@ -109,42 +122,44 @@ am__tincd_SOURCES_DIST = have.h system.h avl_tree.c avl_tree.h conf.c \ conf.h connection.c connection.h device.h dropin.c dropin.h \ dummy_device.c edge.c edge.h ethernet.h event.c event.h \ fake-gai-errnos.h fake-getaddrinfo.c fake-getaddrinfo.h \ - fake-getnameinfo.c fake-getnameinfo.h getopt.c getopt.h \ - getopt1.c graph.c graph.h ipv4.h ipv6.h list.c list.h logger.c \ - logger.h meta.c meta.h multicast_device.c net.c net.h \ - net_packet.c net_setup.c net_socket.c netutl.c netutl.h node.c \ - node.h pidfile.c pidfile.h process.c process.h protocol.c \ - protocol.h protocol_auth.c protocol_edge.c protocol_misc.c \ - protocol_key.c protocol_subnet.c raw_socket_device.c route.c \ + fake-getnameinfo.c fake-getnameinfo.h graph.c graph.h ipv4.h \ + ipv6.h list.c list.h logger.c logger.h meta.c meta.h \ + multicast_device.c net.c net.h net_packet.c net_setup.c \ + net_socket.c netutl.c netutl.h node.c node.h pidfile.c \ + pidfile.h process.c process.h protocol.c protocol.h \ + protocol_auth.c protocol_edge.c protocol_misc.c protocol_key.c \ + protocol_subnet.c proxy.c proxy.h raw_socket_device.c route.c \ route.h subnet.c subnet.h tincd.c utils.c utils.h xalloc.h \ - xmalloc.c linux/device.c bsd/device.c bsd/tunemu.c \ - bsd/tunemu.h solaris/device.c mingw/device.c mingw/common.h \ - cygwin/device.c uml_device.c vde_device.c + xmalloc.c getopt.c getopt.h getopt1.c linux/device.c \ + bsd/device.c bsd/tunemu.c bsd/tunemu.h solaris/device.c \ + mingw/device.c mingw/common.h cygwin/device.c uml_device.c \ + vde_device.c +@GETOPT_FALSE@am__objects_1 = getopt.$(OBJEXT) getopt1.$(OBJEXT) am__dirstamp = $(am__leading_dot)dirstamp -@LINUX_TRUE@am__objects_1 = linux/device.$(OBJEXT) -@BSD_TRUE@am__objects_2 = bsd/device.$(OBJEXT) -@BSD_TRUE@@TUNEMU_TRUE@am__objects_3 = bsd/tunemu.$(OBJEXT) -@SOLARIS_TRUE@am__objects_4 = solaris/device.$(OBJEXT) -@MINGW_TRUE@am__objects_5 = mingw/device.$(OBJEXT) -@CYGWIN_TRUE@am__objects_6 = cygwin/device.$(OBJEXT) -@UML_TRUE@am__objects_7 = uml_device.$(OBJEXT) -@VDE_TRUE@am__objects_8 = vde_device.$(OBJEXT) +@LINUX_TRUE@am__objects_2 = linux/device.$(OBJEXT) +@BSD_TRUE@am__objects_3 = bsd/device.$(OBJEXT) +@BSD_TRUE@@TUNEMU_TRUE@am__objects_4 = bsd/tunemu.$(OBJEXT) +@SOLARIS_TRUE@am__objects_5 = solaris/device.$(OBJEXT) +@MINGW_TRUE@am__objects_6 = mingw/device.$(OBJEXT) +@CYGWIN_TRUE@am__objects_7 = cygwin/device.$(OBJEXT) +@UML_TRUE@am__objects_8 = uml_device.$(OBJEXT) +@VDE_TRUE@am__objects_9 = vde_device.$(OBJEXT) am_tincd_OBJECTS = avl_tree.$(OBJEXT) conf.$(OBJEXT) \ connection.$(OBJEXT) dropin.$(OBJEXT) dummy_device.$(OBJEXT) \ edge.$(OBJEXT) event.$(OBJEXT) fake-getaddrinfo.$(OBJEXT) \ - fake-getnameinfo.$(OBJEXT) getopt.$(OBJEXT) getopt1.$(OBJEXT) \ - graph.$(OBJEXT) list.$(OBJEXT) logger.$(OBJEXT) meta.$(OBJEXT) \ - multicast_device.$(OBJEXT) net.$(OBJEXT) net_packet.$(OBJEXT) \ - net_setup.$(OBJEXT) net_socket.$(OBJEXT) netutl.$(OBJEXT) \ - node.$(OBJEXT) pidfile.$(OBJEXT) process.$(OBJEXT) \ - protocol.$(OBJEXT) protocol_auth.$(OBJEXT) \ - protocol_edge.$(OBJEXT) protocol_misc.$(OBJEXT) \ - protocol_key.$(OBJEXT) protocol_subnet.$(OBJEXT) \ + fake-getnameinfo.$(OBJEXT) graph.$(OBJEXT) list.$(OBJEXT) \ + logger.$(OBJEXT) meta.$(OBJEXT) multicast_device.$(OBJEXT) \ + net.$(OBJEXT) net_packet.$(OBJEXT) net_setup.$(OBJEXT) \ + net_socket.$(OBJEXT) netutl.$(OBJEXT) node.$(OBJEXT) \ + pidfile.$(OBJEXT) process.$(OBJEXT) protocol.$(OBJEXT) \ + protocol_auth.$(OBJEXT) protocol_edge.$(OBJEXT) \ + protocol_misc.$(OBJEXT) protocol_key.$(OBJEXT) \ + protocol_subnet.$(OBJEXT) proxy.$(OBJEXT) \ raw_socket_device.$(OBJEXT) route.$(OBJEXT) subnet.$(OBJEXT) \ tincd.$(OBJEXT) utils.$(OBJEXT) xmalloc.$(OBJEXT) \ $(am__objects_1) $(am__objects_2) $(am__objects_3) \ $(am__objects_4) $(am__objects_5) $(am__objects_6) \ - $(am__objects_7) $(am__objects_8) + $(am__objects_7) $(am__objects_8) $(am__objects_9) tincd_OBJECTS = $(am_tincd_OBJECTS) tincd_LDADD = $(LDADD) AM_V_P = $(am__v_P_@AM_V@) @@ -201,6 +216,7 @@ am__define_uniq_tagged_files = \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -230,7 +246,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ $(am__append_9) +LIBS = @LIBS@ $(am__append_10) LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ @@ -290,6 +306,7 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -302,17 +319,17 @@ tincd_SOURCES = have.h system.h avl_tree.c avl_tree.h conf.c conf.h \ connection.c connection.h device.h dropin.c dropin.h \ dummy_device.c edge.c edge.h ethernet.h event.c event.h \ fake-gai-errnos.h fake-getaddrinfo.c fake-getaddrinfo.h \ - fake-getnameinfo.c fake-getnameinfo.h getopt.c getopt.h \ - getopt1.c graph.c graph.h ipv4.h ipv6.h list.c list.h logger.c \ - logger.h meta.c meta.h multicast_device.c net.c net.h \ - net_packet.c net_setup.c net_socket.c netutl.c netutl.h node.c \ - node.h pidfile.c pidfile.h process.c process.h protocol.c \ - protocol.h protocol_auth.c protocol_edge.c protocol_misc.c \ - protocol_key.c protocol_subnet.c raw_socket_device.c route.c \ + fake-getnameinfo.c fake-getnameinfo.h graph.c graph.h ipv4.h \ + ipv6.h list.c list.h logger.c logger.h meta.c meta.h \ + multicast_device.c net.c net.h net_packet.c net_setup.c \ + net_socket.c netutl.c netutl.h node.c node.h pidfile.c \ + pidfile.h process.c process.h protocol.c protocol.h \ + protocol_auth.c protocol_edge.c protocol_misc.c protocol_key.c \ + protocol_subnet.c proxy.c proxy.h raw_socket_device.c route.c \ route.h subnet.c subnet.h tincd.c utils.c utils.h xalloc.h \ xmalloc.c $(am__append_1) $(am__append_2) $(am__append_3) \ $(am__append_4) $(am__append_5) $(am__append_6) \ - $(am__append_7) $(am__append_8) + $(am__append_7) $(am__append_8) $(am__append_9) AM_CPPFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" all: all-am @@ -330,7 +347,6 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -494,6 +510,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_key.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_misc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_subnet.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proxy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/raw_socket_device.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/route.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnet.Po@am__quote@ @@ -739,6 +756,8 @@ uninstall-am: uninstall-sbinPROGRAMS mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-sbinPROGRAMS +.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. diff --git a/src/avl_tree.c b/src/avl_tree.c index 6b85516..a4103ac 100644 --- a/src/avl_tree.c +++ b/src/avl_tree.c @@ -2,7 +2,7 @@ avl_tree.c -- avl_ tree and linked list convenience Copyright (C) 1998 Michael H. Buselli 2000-2005 Ivo Timmermans, - 2000-2014 Guus Sliepen + 2000-2015 Guus Sliepen 2000-2005 Wessel Dankers This program is free software; you can redistribute it and/or modify @@ -123,8 +123,6 @@ static void avl_rebalance(avl_tree_t *tree, avl_node_t *node) avl_node_t *parent; avl_node_t **superparent; - parent = node; - while(node) { parent = node->parent; diff --git a/src/bsd/device.c b/src/bsd/device.c index 3e9cfb2..e3148bd 100644 --- a/src/bsd/device.c +++ b/src/bsd/device.c @@ -1,7 +1,7 @@ /* device.c -- Interaction BSD tun/tap device Copyright (C) 2001-2005 Ivo Timmermans, - 2001-2014 Guus Sliepen + 2001-2016 Guus Sliepen 2009 Grzegorz Dymarek This program is free software; you can redistribute it and/or modify @@ -33,13 +33,15 @@ #include "tunemu.h" #endif -#define DEFAULT_TUN_DEVICE "/dev/tun0" -#if defined(HAVE_FREEBSD) || defined(HAVE_NETBSD) || defined(HAVE_DARWIN) -#define DEFAULT_TAP_DEVICE "/dev/tap0" -#else -#define DEFAULT_TAP_DEVICE "/dev/tun0" +#ifdef HAVE_NET_IF_UTUN_H +#include +#include +#include #endif +#define DEFAULT_TUN_DEVICE "/dev/tun0" +#define DEFAULT_TAP_DEVICE "/dev/tap0" + typedef enum device_type { DEVICE_TYPE_TUN, DEVICE_TYPE_TUNIFHEAD, @@ -47,6 +49,9 @@ typedef enum device_type { #ifdef ENABLE_TUNEMU DEVICE_TYPE_TUNEMU, #endif +#ifdef HAVE_NET_IF_UTUN_H + DEVICE_TYPE_UTUN, +#endif } device_type_t; int device_fd = -1; @@ -63,8 +68,61 @@ static device_type_t device_type = DEVICE_TYPE_TUNIFHEAD; static device_type_t device_type = DEVICE_TYPE_TUN; #endif +#ifdef HAVE_NET_IF_UTUN_H +static bool setup_utun(void) { + device_fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL); + if(device_fd == -1) { + logger(LOG_ERR, "Could not open PF_SYSTEM socket: %s\n", strerror(errno)); + return false; + } + + struct ctl_info info = {}; + strlcpy(info.ctl_name, UTUN_CONTROL_NAME, sizeof info.ctl_name); + + if(ioctl(device_fd, CTLIOCGINFO, &info) == -1) { + logger(LOG_ERR, "ioctl(CTLIOCGINFO) failed: %s", strerror(errno)); + return false; + } + + int unit = -1; + char *p = strstr(device, "utun"), *e = NULL; + if(p) { + unit = strtol(p + 4, &e, 10); + if(!e) + unit = -1; + } + + struct sockaddr_ctl sc = { + .sc_id = info.ctl_id, + .sc_len = sizeof sc, + .sc_family = AF_SYSTEM, + .ss_sysaddr = AF_SYS_CONTROL, + .sc_unit = unit + 1, + }; + + if(connect(device_fd, (struct sockaddr *)&sc, sizeof(sc)) == -1) { + logger(LOG_ERR, "Could not connect utun socket: %s\n", strerror(errno)); + return false; + } + + char name[64] = ""; + socklen_t len = sizeof name; + if(getsockopt(device_fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, name, &len)) { + iface = xstrdup(device); + } else { + iface = xstrdup(name); + } + + device_info = "OS X utun device"; + + logger(LOG_INFO, "%s is a %s", device, device_info); + + return true; +} +#endif + static bool setup_device(void) { - char *type; + // Find out which device file to open if(!get_config_string(lookup_config(config_tree, "Device"), &device)) { if(routing_mode == RMODE_ROUTER) @@ -73,8 +131,9 @@ static bool setup_device(void) { device = xstrdup(DEFAULT_TAP_DEVICE); } - if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) - iface = xstrdup(strrchr(device, '/') ? strrchr(device, '/') + 1 : device); + // Find out if it's supposed to be a tun or a tap device + + char *type; if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) { if(!strcasecmp(type, "tun")) @@ -82,6 +141,10 @@ static bool setup_device(void) { #ifdef ENABLE_TUNEMU else if(!strcasecmp(type, "tunemu")) device_type = DEVICE_TYPE_TUNEMU; +#endif +#ifdef HAVE_NET_IF_UTUN_H + else if(!strcasecmp(type, "utun")) + device_type = DEVICE_TYPE_UTUN; #endif else if(!strcasecmp(type, "tunnohead")) device_type = DEVICE_TYPE_TUN; @@ -94,10 +157,22 @@ static bool setup_device(void) { return false; } } else { +#ifdef HAVE_NET_IF_UTUN_H + if(strncmp(device, "utun", 4) == 0 || strncmp(device, "/dev/utun", 9) == 0) + device_type = DEVICE_TYPE_UTUN; + else +#endif if(strstr(device, "tap") || routing_mode != RMODE_ROUTER) device_type = DEVICE_TYPE_TAP; } + if(routing_mode == RMODE_SWITCH && device_type != DEVICE_TYPE_TAP) { + logger(LOG_ERR, "Only tap devices support switch mode!"); + return false; + } + + // Open the device + switch(device_type) { #ifdef ENABLE_TUNEMU case DEVICE_TYPE_TUNEMU: { @@ -105,6 +180,10 @@ static bool setup_device(void) { device_fd = tunemu_open(dynamic_name); } break; +#endif +#ifdef HAVE_NET_IF_UTUN_H + case DEVICE_TYPE_UTUN: + return setup_utun(); #endif default: device_fd = open(device, O_RDWR | O_NONBLOCK); @@ -119,6 +198,27 @@ static bool setup_device(void) { fcntl(device_fd, F_SETFD, FD_CLOEXEC); #endif + // Guess what the corresponding interface is called + + char *realname; + +#if defined(HAVE_FDEVNAME) + realname = fdevname(device_fd) ? : device; +#elif defined(HAVE_DEVNAME) + struct stat buf; + if(!fstat(device_fd, &buf)) + realname = devname(buf.st_rdev, S_IFCHR) ? : device; +#else + realname = device; +#endif + + if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) + iface = xstrdup(strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname); + else if(strcmp(iface, strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname)) + logger(LOG_WARNING, "Warning: Interface does not match Device. $INTERFACE might be set incorrectly."); + + // Configure the device as best as we can + switch(device_type) { default: device_type = DEVICE_TYPE_TUN; @@ -183,6 +283,11 @@ static bool setup_device(void) { #endif } +#ifdef SIOCGIFADDR + if(overwrite_mac) + ioctl(device_fd, SIOCGIFADDR, mymac.x); +#endif + logger(LOG_INFO, "%s is a %s", device, device_info); return true; @@ -242,31 +347,27 @@ static bool read_packet(vpn_packet_t *packet) { packet->len = lenin + 14; break; + case DEVICE_TYPE_UTUN: case DEVICE_TYPE_TUNIFHEAD: { - u_int32_t type; - struct iovec vector[2] = {{&type, sizeof(type)}, {packet->data + 14, MTU - 14}}; - - if((lenin = readv(device_fd, vector, 2)) <= 0) { + if((lenin = read(device_fd, packet->data + 10, MTU - 10)) <= 0) { logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, device, strerror(errno)); return false; } - switch (ntohl(type)) { - case AF_INET: + switch(packet->data[14] >> 4) { + case 4: packet->data[12] = 0x08; packet->data[13] = 0x00; break; - - case AF_INET6: + case 6: packet->data[12] = 0x86; packet->data[13] = 0xDD; break; - default: ifdebug(TRAFFIC) logger(LOG_ERR, - "Unknown address family %x while reading packet from %s %s", - ntohl(type), device_info, device); + "Unknown IP version %d while reading packet from %s %s", + packet->data[14] >> 4, device_info, device); return false; } @@ -310,12 +411,10 @@ static bool write_packet(vpn_packet_t *packet) { } break; + case DEVICE_TYPE_UTUN: case DEVICE_TYPE_TUNIFHEAD: { - u_int32_t type; - struct iovec vector[2] = {{&type, sizeof(type)}, {packet->data + 14, packet->len - 14}}; - int af; - - af = (packet->data[12] << 8) + packet->data[13]; + int af = (packet->data[12] << 8) + packet->data[13]; + uint32_t type; switch (af) { case 0x0800: @@ -331,7 +430,9 @@ static bool write_packet(vpn_packet_t *packet) { return false; } - if(writev(device_fd, vector, 2) < 0) { + memcpy(packet->data + 10, &type, sizeof type); + + if(write(device_fd, packet->data + 10, packet->len - 10) < 0) { logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno)); return false; diff --git a/src/cygwin/device.c b/src/cygwin/device.c index b582a6a..9fce9be 100644 --- a/src/cygwin/device.c +++ b/src/cygwin/device.c @@ -1,7 +1,7 @@ /* device.c -- Interaction with Windows tap driver in a Cygwin environment Copyright (C) 2002-2005 Ivo Timmermans, - 2002-2011 Guus Sliepen + 2002-2016 Guus Sliepen 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 @@ -19,6 +19,7 @@ */ #include "../system.h" +#include "../net.h" #include #include @@ -26,7 +27,6 @@ #include "../conf.h" #include "../device.h" #include "../logger.h" -#include "../net.h" #include "../route.h" #include "../utils.h" #include "../xalloc.h" @@ -61,6 +61,9 @@ static bool setup_device(void) { get_config_string(lookup_config(config_tree, "Device"), &device); get_config_string(lookup_config(config_tree, "Interface"), &iface); + if(device && iface) + logger(LOG_WARNING, "Warning: both Device and Interface specified, results may not be as expected"); + /* Open registry and look for network adapters */ if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &key)) { diff --git a/src/meta.c b/src/meta.c index e62c3b7..06ab96e 100644 --- a/src/meta.c +++ b/src/meta.c @@ -1,6 +1,6 @@ /* meta.c -- handle the meta communication - Copyright (C) 2000-2014 Guus Sliepen , + Copyright (C) 2000-2015 Guus Sliepen , 2000-2005 Ivo Timmermans 2006 Scott Lamb @@ -30,6 +30,7 @@ #include "meta.h" #include "net.h" #include "protocol.h" +#include "proxy.h" #include "utils.h" #include "xalloc.h" @@ -160,6 +161,17 @@ bool receive_meta(connection_t *c) { c->buflen += lenin; while(lenin > 0) { + reqlen = 0; + + /* Is it proxy metadata? */ + + if(c->allow_request == PROXY) { + reqlen = receive_proxy_meta(c, oldlen, lenin); + if(reqlen < 0) + return false; + goto consume; + } + /* Decrypt */ if(c->status.decryptin && !decrypted) { @@ -177,74 +189,32 @@ bool receive_meta(connection_t *c) { if(c->tcplen) { if(c->tcplen <= c->buflen) { - if(!c->node) { - if(c->outgoing && proxytype == PROXY_SOCKS4 && c->allow_request == ID) { - if(c->buffer[0] == 0 && c->buffer[1] == 0x5a) { - ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Proxy request granted"); - } else { - logger(LOG_ERR, "Proxy request rejected"); - return false; - } - } else if(c->outgoing && proxytype == PROXY_SOCKS5 && c->allow_request == ID) { - if(c->buffer[0] != 5) { - logger(LOG_ERR, "Invalid response from proxy server"); - return false; - } - if(c->buffer[1] == (char)0xff) { - logger(LOG_ERR, "Proxy request rejected: unsuitable authentication method"); - return false; - } - if(c->buffer[2] != 5) { - logger(LOG_ERR, "Invalid response from proxy server"); - return false; - } - if(c->buffer[3] == 0) { - ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Proxy request granted"); - } else { - logger(LOG_ERR, "Proxy request rejected"); - return false; - } - } else { - logger(LOG_ERR, "c->tcplen set but c->node is NULL!"); - abort(); - } - } else { - if(c->allow_request == ALL) { - receive_tcppacket(c, c->buffer, c->tcplen); - } else { - logger(LOG_ERR, "Got unauthorized TCP packet from %s (%s)", c->name, c->hostname); - return false; - } + if(c->allow_request != ALL) { + logger(LOG_ERR, "Got unauthorized TCP packet from %s (%s)", c->name, c->hostname); + return false; } - c->buflen -= c->tcplen; - lenin -= c->tcplen - oldlen; - memmove(c->buffer, c->buffer + c->tcplen, c->buflen); - oldlen = 0; + receive_tcppacket(c, c->buffer, c->tcplen); + reqlen = c->tcplen; c->tcplen = 0; - continue; - } else { - break; } - } + } else { + /* Otherwise we are waiting for a request */ - /* Otherwise we are waiting for a request */ - - reqlen = 0; - - for(i = oldlen; i < c->buflen; i++) { - if(c->buffer[i] == '\n') { - c->buffer[i] = '\0'; /* replace end-of-line by end-of-string so we can use sscanf */ - reqlen = i + 1; - break; + for(i = oldlen; i < c->buflen; i++) { + if(c->buffer[i] == '\n') { + c->buffer[i] = '\0'; /* replace end-of-line by end-of-string so we can use sscanf */ + c->reqlen = reqlen = i + 1; + break; + } } - } - if(reqlen) { - c->reqlen = reqlen; - if(!receive_request(c)) + if(reqlen && !receive_request(c)) return false; + } +consume: + if(reqlen) { c->buflen -= reqlen; lenin -= reqlen - oldlen; memmove(c->buffer, c->buffer + reqlen, c->buflen); diff --git a/src/mingw/device.c b/src/mingw/device.c index 235e0fd..3ff6759 100644 --- a/src/mingw/device.c +++ b/src/mingw/device.c @@ -1,7 +1,7 @@ /* device.c -- Interaction with Windows tap driver in a MinGW environment Copyright (C) 2002-2005 Ivo Timmermans, - 2002-2014 Guus Sliepen + 2002-2016 Guus Sliepen 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 @@ -43,11 +43,12 @@ static uint64_t device_total_in = 0; static uint64_t device_total_out = 0; extern char *myport; +OVERLAPPED r_overlapped; +OVERLAPPED w_overlapped; static DWORD WINAPI tapreader(void *bla) { int status; DWORD len; - OVERLAPPED overlapped; vpn_packet_t packet; int errors = 0; @@ -55,19 +56,17 @@ static DWORD WINAPI tapreader(void *bla) { /* Read from tap device and send to parent */ - overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + r_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); for(;;) { - overlapped.Offset = 0; - overlapped.OffsetHigh = 0; - ResetEvent(overlapped.hEvent); + ResetEvent(r_overlapped.hEvent); - status = ReadFile(device_handle, packet.data, MTU, &len, &overlapped); + status = ReadFile(device_handle, packet.data, MTU, &len, &r_overlapped); if(!status) { if(GetLastError() == ERROR_IO_PENDING) { - WaitForSingleObject(overlapped.hEvent, INFINITE); - if(!GetOverlappedResult(device_handle, &overlapped, &len, FALSE)) + WaitForSingleObject(r_overlapped.hEvent, INFINITE); + if(!GetOverlappedResult(device_handle, &r_overlapped, &len, FALSE)) continue; } else { logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, @@ -114,6 +113,9 @@ static bool setup_device(void) { get_config_string(lookup_config(config_tree, "Device"), &device); get_config_string(lookup_config(config_tree, "Interface"), &iface); + if(device && iface) + logger(LOG_WARNING, "Warning: both Device and Interface specified, results may not be as expected"); + /* Open registry and look for network adapters */ if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &key)) { @@ -201,6 +203,11 @@ static bool setup_device(void) { overwrite_mac = 1; } + /* Create overlapped events for tap I/O */ + + r_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + w_overlapped.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + /* Start the tap reader */ thread = CreateThread(NULL, 0, tapreader, NULL, 0, NULL); @@ -235,14 +242,48 @@ static bool read_packet(vpn_packet_t *packet) { static bool write_packet(vpn_packet_t *packet) { DWORD lenout; - OVERLAPPED overlapped = {0}; + static vpn_packet_t queue; ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s", packet->len, device_info); - if(!WriteFile(device_handle, packet->data, packet->len, &lenout, &overlapped)) { - logger(LOG_ERR, "Error while writing to %s %s: %s", device_info, device, winerror(GetLastError())); - return false; + /* Check if there is something in progress */ + + if(queue.len) { + DWORD size; + BOOL success = GetOverlappedResult(device_handle, &w_overlapped, &size, FALSE); + if(success) { + ResetEvent(&w_overlapped); + queue.len = 0; + } else { + int err = GetLastError(); + if(err != ERROR_IO_INCOMPLETE) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Error completing previously queued write: %s", winerror(err)); + ResetEvent(&w_overlapped); + queue.len = 0; + } else { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Previous overlapped write still in progress"); + // drop this packet + return true; + } + } + } + + /* Otherwise, try to write. */ + + memcpy(queue.data, packet->data, packet->len); + + if(!WriteFile(device_handle, queue.data, packet->len, &lenout, &w_overlapped)) { + int err = GetLastError(); + if(err != ERROR_IO_PENDING) { + logger(LOG_ERR, "Error while writing to %s %s: %s", device_info, device, winerror(err)); + return false; + } + // Write is being done asynchronously. + queue.len = packet->len; + } else { + // Write was completed immediately. + ResetEvent(&w_overlapped); } device_total_out += packet->len; diff --git a/src/net.h b/src/net.h index 0982020..e251ebd 100644 --- a/src/net.h +++ b/src/net.h @@ -1,7 +1,7 @@ /* net.h -- header for net.c Copyright (C) 1998-2005 Ivo Timmermans - 2000-2012 Guus Sliepen + 2000-2015 Guus Sliepen 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 @@ -123,20 +123,6 @@ extern time_t now; extern int contradicting_add_edge; extern int contradicting_del_edge; -extern char *proxyhost; -extern char *proxyport; -extern char *proxyuser; -extern char *proxypass; -typedef enum proxytype_t { - PROXY_NONE = 0, - PROXY_SOCKS4, - PROXY_SOCKS4A, - PROXY_SOCKS5, - PROXY_HTTP, - PROXY_EXEC, -} proxytype_t; -extern proxytype_t proxytype; - extern volatile bool running; /* Yes, very strange placement indeed, but otherwise the typedefs get all tangled up */ diff --git a/src/net_packet.c b/src/net_packet.c index e67857c..5f6d9d5 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -1,7 +1,7 @@ /* net_packet.c -- Handles in- and outgoing VPN packets Copyright (C) 1998-2005 Ivo Timmermans, - 2000-2014 Guus Sliepen + 2000-2015 Guus Sliepen 2010 Timothy Redaelli 2010 Brandon Black @@ -276,7 +276,7 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) { vpn_packet_t pkt1, pkt2; vpn_packet_t *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 }; int nextpkt = 0; - vpn_packet_t *outpkt = pkt[0]; + vpn_packet_t *outpkt; int outlen, outpad; unsigned char hmac[EVP_MAX_MD_SIZE]; int i; @@ -552,14 +552,14 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { #if defined(SOL_IP) && defined(IP_TOS) case AF_INET: ifdebug(TRAFFIC) logger(LOG_DEBUG, "Setting IPv4 outgoing packet priority to %d", origpriority); - if(setsockopt(listen_socket[n->sock].udp, SOL_IP, IP_TOS, &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)); break; #endif #if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS) case AF_INET6: ifdebug(TRAFFIC) logger(LOG_DEBUG, "Setting IPv6 outgoing packet priority to %d", origpriority); - if(setsockopt(listen_socket[n->sock].udp, IPPROTO_IPV6, IPV6_TCLASS, &origpriority, sizeof(origpriority))) + if(setsockopt(listen_socket[n->sock].udp, IPPROTO_IPV6, IPV6_TCLASS, (void *)&origpriority, sizeof(origpriority))) logger(LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno)); break; #endif diff --git a/src/net_setup.c b/src/net_setup.c index 863616b..50d5680 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -39,6 +39,7 @@ #include "netutl.h" #include "process.h" #include "protocol.h" +#include "proxy.h" #include "route.h" #include "subnet.h" #include "utils.h" @@ -47,12 +48,6 @@ char *myport; devops_t devops; -char *proxyhost; -char *proxyport; -char *proxyuser; -char *proxypass; -proxytype_t proxytype; - bool read_rsa_public_key(connection_t *c) { FILE *fp; char *pubname; diff --git a/src/net_socket.c b/src/net_socket.c index cb27106..a4c7f07 100644 --- a/src/net_socket.c +++ b/src/net_socket.c @@ -1,7 +1,7 @@ /* net_socket.c -- Handle various kinds of sockets. Copyright (C) 1998-2005 Ivo Timmermans, - 2000-2014 Guus Sliepen + 2000-2015 Guus Sliepen 2006 Scott Lamb 2009 Florian Forster @@ -31,6 +31,7 @@ #include "net.h" #include "netutl.h" #include "protocol.h" +#include "proxy.h" #include "utils.h" #include "xalloc.h" @@ -354,8 +355,19 @@ static void do_outgoing_pipe(connection_t *c, char *command) { #endif } +static bool is_valid_host_port(const char *host, const char *port) { + for(const char *p = host; *p; p++) + if(!isalnum(*p) && *p != '-' && *p != '.') + return false; + + for(const char *p = port; *p; p++) + if(!isalnum(*p)) + return false; + + return true; +} + void do_outgoing_connection(connection_t *c) { - char *address, *port, *space; struct addrinfo *proxyai = NULL; int result; @@ -375,6 +387,8 @@ begin: return; } + char *address, *port, *space; + get_config_string(c->outgoing->cfg, &address); space = strchr(address, ' '); @@ -387,11 +401,23 @@ begin: } c->outgoing->ai = str2addrinfo(address, port, SOCK_STREAM); - free(address); - free(port); + + // 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)) { + memset(&c->address, 0, sizeof c->address); + c->address.sa.sa_family = AF_UNKNOWN; + c->address.unknown.address = address; + c->address.unknown.port = port; + } else { + free(address); + free(port); + } c->outgoing->aip = c->outgoing->ai; c->outgoing->cfg = lookup_config_next(c->config_tree, c->outgoing->cfg); + + if(!c->outgoing->ai && proxytype != PROXY_NONE) + goto connect; } if(!c->outgoing->aip) { @@ -404,6 +430,7 @@ begin: memcpy(&c->address, c->outgoing->aip->ai_addr, c->outgoing->aip->ai_addrlen); c->outgoing->aip = c->outgoing->aip->ai_next; +connect: if(c->hostname) free(c->hostname); @@ -457,8 +484,11 @@ begin: freeaddrinfo(proxyai); } + now = time(NULL); + if(result == -1) { if(sockinprogress(sockerrno)) { + c->last_ping_time = now; c->status.connecting = true; return; } diff --git a/src/netutl.c b/src/netutl.c index 275c64f..2abbe86 100644 --- a/src/netutl.c +++ b/src/netutl.c @@ -33,7 +33,7 @@ bool hostnames = false; Return NULL on failure. */ struct addrinfo *str2addrinfo(const char *address, const char *service, int socktype) { - struct addrinfo *ai, hint = {0}; + struct addrinfo *ai = NULL, hint = {0}; int err; 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) { - struct addrinfo *ai, hint = {0}; + struct addrinfo *ai = NULL, hint = {0}; sockaddr_t result; int err; diff --git a/src/protocol.c b/src/protocol.c index b385fbc..5b8b7ba 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -1,7 +1,7 @@ /* protocol.c -- handle the meta-protocol, basic functions Copyright (C) 1999-2005 Ivo Timmermans, - 2000-2013 Guus Sliepen + 2000-2015 Guus Sliepen 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 @@ -125,20 +125,6 @@ void forward_request(connection_t *from) { bool receive_request(connection_t *c) { int request; - if(c->outgoing && proxytype == PROXY_HTTP && c->allow_request == ID) { - if(!c->buffer[0] || c->buffer[0] == '\r') - return true; - if(!strncasecmp(c->buffer, "HTTP/1.1 ", 9)) { - if(!strncmp(c->buffer + 9, "200", 3)) { - logger(LOG_DEBUG, "Proxy request granted"); - return true; - } else { - logger(LOG_DEBUG, "Proxy request rejected: %s", c->buffer + 9); - return false; - } - } - } - if(sscanf(c->buffer, "%d", &request) == 1) { if((request < 0) || (request >= LAST) || !request_handlers[request]) { ifdebug(META) diff --git a/src/protocol.h b/src/protocol.h index 6c46c72..147475a 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -1,7 +1,7 @@ /* protocol.h -- header for protocol.c Copyright (C) 1999-2005 Ivo Timmermans, - 2000-2009 Guus Sliepen + 2000-2015 Guus Sliepen 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 @@ -36,6 +36,7 @@ /* Request numbers */ typedef enum request_t { + PROXY = -2, ALL = -1, /* Guardian for allow_request */ ID = 0, METAKEY, CHALLENGE, CHAL_REPLY, ACK, STATUS, ERROR, TERMREQ, diff --git a/src/protocol_auth.c b/src/protocol_auth.c index 971341f..8fa9b93 100644 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@ -1,7 +1,7 @@ /* protocol_auth.c -- handle the meta-protocol, authentication Copyright (C) 1999-2005 Ivo Timmermans, - 2000-2014 Guus Sliepen + 2000-2015 Guus Sliepen 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 @@ -36,95 +36,10 @@ #include "netutl.h" #include "node.h" #include "protocol.h" +#include "proxy.h" #include "utils.h" #include "xalloc.h" -static bool send_proxyrequest(connection_t *c) { - switch(proxytype) { - case PROXY_HTTP: { - char *host; - char *port; - - sockaddr2str(&c->address, &host, &port); - send_request(c, "CONNECT %s:%s HTTP/1.1\r\n\r", host, port); - free(host); - free(port); - return true; - } - case PROXY_SOCKS4: { - if(c->address.sa.sa_family != AF_INET) { - logger(LOG_ERR, "Cannot connect to an IPv6 host through a SOCKS 4 proxy!"); - return false; - } - char s4req[9 + (proxyuser ? strlen(proxyuser) : 0)]; - s4req[0] = 4; - s4req[1] = 1; - memcpy(s4req + 2, &c->address.in.sin_port, 2); - memcpy(s4req + 4, &c->address.in.sin_addr, 4); - if(proxyuser) - strcpy(s4req + 8, proxyuser); - s4req[sizeof s4req - 1] = 0; - c->tcplen = 8; - return send_meta(c, s4req, sizeof s4req); - } - case PROXY_SOCKS5: { - int len = 3 + 6 + (c->address.sa.sa_family == AF_INET ? 4 : 16); - c->tcplen = 2; - if(proxypass) - len += 3 + strlen(proxyuser) + strlen(proxypass); - char s5req[len]; - int i = 0; - s5req[i++] = 5; - s5req[i++] = 1; - if(proxypass) { - s5req[i++] = 2; - s5req[i++] = 1; - s5req[i++] = strlen(proxyuser); - strcpy(s5req + i, proxyuser); - i += strlen(proxyuser); - s5req[i++] = strlen(proxypass); - strcpy(s5req + i, proxypass); - i += strlen(proxypass); - c->tcplen += 2; - } else { - s5req[i++] = 0; - } - s5req[i++] = 5; - s5req[i++] = 1; - s5req[i++] = 0; - if(c->address.sa.sa_family == AF_INET) { - s5req[i++] = 1; - memcpy(s5req + i, &c->address.in.sin_addr, 4); - i += 4; - memcpy(s5req + i, &c->address.in.sin_port, 2); - i += 2; - c->tcplen += 10; - } else if(c->address.sa.sa_family == AF_INET6) { - s5req[i++] = 3; - memcpy(s5req + i, &c->address.in6.sin6_addr, 16); - i += 16; - memcpy(s5req + i, &c->address.in6.sin6_port, 2); - i += 2; - c->tcplen += 22; - } else { - logger(LOG_ERR, "Address family %x not supported for SOCKS 5 proxies!", c->address.sa.sa_family); - return false; - } - if(i > len) - abort(); - return send_meta(c, s5req, sizeof s5req); - } - case PROXY_SOCKS4A: - logger(LOG_ERR, "Proxy type not implemented yet"); - return false; - case PROXY_EXEC: - return true; - default: - logger(LOG_ERR, "Unknown proxy type"); - return false; - } -} - bool send_id(connection_t *c) { if(proxytype && c->outgoing) if(!send_proxyrequest(c)) diff --git a/src/protocol_edge.c b/src/protocol_edge.c index 3dfff05..f58fe1a 100644 --- a/src/protocol_edge.c +++ b/src/protocol_edge.c @@ -1,7 +1,7 @@ /* protocol_edge.c -- handle the meta-protocol, edges Copyright (C) 1999-2005 Ivo Timmermans, - 2000-2012 Guus Sliepen + 2000-2016 Guus Sliepen 2009 Michael Tokarev This program is free software; you can redistribute it and/or modify @@ -125,8 +125,18 @@ bool add_edge_h(connection_t *c) { } else { ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) which does not match existing entry", "ADD_EDGE", c->name, c->hostname); - edge_del(e); - graph(); + e->options = options; + if(sockaddrcmp(&e->address, &address)) { + sockaddrfree(&e->address); + e->address = address; + } + if(e->weight != weight) { + avl_node_t *node = avl_unlink(edge_weight_tree, e); + e->weight = weight; + avl_insert_node(edge_weight_tree, node); + } + + goto done; } } else return true; @@ -150,6 +160,7 @@ bool add_edge_h(connection_t *c) { e->weight = weight; edge_add(e); +done: /* Tell the rest about the new edge */ if(!tunnelserver) diff --git a/src/protocol_key.c b/src/protocol_key.c index 301ead5..4f1e1b7 100644 --- a/src/protocol_key.c +++ b/src/protocol_key.c @@ -1,7 +1,7 @@ /* protocol_key.c -- handle the meta-protocol, key exchange Copyright (C) 1999-2005 Ivo Timmermans, - 2000-2014 Guus Sliepen + 2000-2016 Guus Sliepen 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 @@ -233,7 +233,7 @@ bool ans_key_h(connection_t *c) { return true; } - if(!*address && from->address.sa.sa_family != AF_UNSPEC) { + if(!*address && from->address.sa.sa_family != AF_UNSPEC && to->minmtu) { char *address, *port; ifdebug(PROTOCOL) logger(LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name); sockaddr2str(&from->address, &address, &port); diff --git a/src/proxy.c b/src/proxy.c new file mode 100644 index 0000000..e30c1fb --- /dev/null +++ b/src/proxy.c @@ -0,0 +1,287 @@ +/* + proxy.c -- Proxy handling functions. + Copyright (C) 2015 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "system.h" + +#include "connection.h" +#include "logger.h" +#include "meta.h" +#include "netutl.h" +#include "protocol.h" +#include "proxy.h" +#include "utils.h" // + +proxytype_t proxytype; +char *proxyhost; +char *proxyport; +char *proxyuser; +char *proxypass; + +static void update_address_ipv4(connection_t *c, void *address, void *port) { + sockaddrfree(&c->address); + memset(&c->address, 0, sizeof c->address); + c->address.sa.sa_family = AF_INET; + if(address) + memcpy(&c->address.in.sin_addr, address, sizeof(ipv4_t)); + if(port) + 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. + if(!memcmp(&c->address.in.sin_addr, "\0\0\0\0", 4)) + memcpy(&c->address.in.sin_addr, "\0\0\0\01", 4); +} + +static void update_address_ipv6(connection_t *c, void *address, void *port) { + sockaddrfree(&c->address); + memset(&c->address, 0, sizeof c->address); + c->address.sa.sa_family = AF_INET6; + if(address) + memcpy(&c->address.in6.sin6_addr, address, sizeof(ipv6_t)); + if(port) + memcpy(&c->address.in6.sin6_port, port, sizeof(uint16_t)); + // 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)) + memcpy(&c->address.in6.sin6_addr, "\01\0\0\0\0\0\0\0", 8); +} + +bool send_proxyrequest(connection_t *c) { + switch(proxytype) { + case PROXY_SOCKS4: + if(c->address.sa.sa_family != AF_INET) { + logger(LOG_ERR, "Can only connect to numeric IPv4 addresses through a SOCKS 4 proxy!"); + return false; + } + case PROXY_SOCKS4A: { + 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!"); + return false; + } + int len = 9; + if(proxyuser) + len += strlen(proxyuser); + if(c->address.sa.sa_family == AF_UNKNOWN) + len += 1 + strlen(c->address.unknown.address); + char s4req[len]; + s4req[0] = 4; + s4req[1] = 1; + if(c->address.sa.sa_family == AF_INET) { + memcpy(s4req + 2, &c->address.in.sin_port, 2); + memcpy(s4req + 4, &c->address.in.sin_addr, 4); + } else { + uint16_t port = htons(atoi(c->address.unknown.port)); + memcpy(s4req + 2, &port, 2); + memcpy(s4req + 4, "\0\0\0\1", 4); + strcpy(s4req + (9 + (proxyuser ? strlen(proxyuser) : 0)), c->address.unknown.address); + } + if(proxyuser) + strcpy(s4req + 8, proxyuser); + else + s4req[8] = 0; + s4req[sizeof s4req - 1] = 0; + c->allow_request = PROXY; + return send_meta(c, s4req, sizeof s4req); + } + + case PROXY_SOCKS5: { + int len = 3 + 6; + if(c->address.sa.sa_family == AF_INET) { + len += 4; + } else if(c->address.sa.sa_family == AF_INET6) { + len += 16; + } else if(c->address.sa.sa_family == AF_UNKNOWN) { + len += 1 + strlen(c->address.unknown.address); + } else { + logger(LOG_ERR, "Address family %x not supported for SOCKS 5 proxies!", c->address.sa.sa_family); + return false; + } + if(proxypass) + len += 3 + strlen(proxyuser) + strlen(proxypass); + char s5req[len]; + int i = 0; + s5req[i++] = 5; + s5req[i++] = 1; + if(proxypass) { + s5req[i++] = 2; + s5req[i++] = 1; + s5req[i++] = strlen(proxyuser); + strcpy(s5req + i, proxyuser); + i += strlen(proxyuser); + s5req[i++] = strlen(proxypass); + strcpy(s5req + i, proxypass); + i += strlen(proxypass); + } else { + s5req[i++] = 0; + } + s5req[i++] = 5; + s5req[i++] = 1; + s5req[i++] = 0; + if(c->address.sa.sa_family == AF_INET) { + s5req[i++] = 1; + memcpy(s5req + i, &c->address.in.sin_addr, 4); + i += 4; + memcpy(s5req + i, &c->address.in.sin_port, 2); + i += 2; + } else if(c->address.sa.sa_family == AF_INET6) { + s5req[i++] = 4; + memcpy(s5req + i, &c->address.in6.sin6_addr, 16); + i += 16; + memcpy(s5req + i, &c->address.in6.sin6_port, 2); + i += 2; + } else if(c->address.sa.sa_family == AF_UNKNOWN) { + s5req[i++] = 3; + int len = strlen(c->address.unknown.address); + s5req[i++] = len; + memcpy(s5req + i, c->address.unknown.address, len); + i += len; + uint16_t port = htons(atoi(c->address.unknown.port)); + memcpy(s5req + i, &port, 2); + i += 2; + } else { + logger(LOG_ERR, "Unknown address family while trying to connect to SOCKS5 proxy"); + return false; + } + if(i > len) + abort(); + c->allow_request = PROXY; + return send_meta(c, s5req, sizeof s5req); + } + + case PROXY_HTTP: { + char *host; + char *port; + + sockaddr2str(&c->address, &host, &port); + send_request(c, "CONNECT %s:%s HTTP/1.1\r\n\r", host, port); + free(host); + free(port); + c->allow_request = PROXY; + return true; + } + + case PROXY_EXEC: + return true; + + default: + logger(LOG_ERR, "Unknown proxy type"); + return false; + } +} + +int receive_proxy_meta(connection_t *c, int start, int lenin) { + switch(proxytype) { + case PROXY_SOCKS4: + case PROXY_SOCKS4A: + if(c->buflen < 8) + return 0; + if(c->buffer[0] == 0 && c->buffer[1] == 0x5a) { + if(c->address.sa.sa_family == AF_UNKNOWN) + update_address_ipv4(c, c->buffer + 4, c->buffer + 2); + + ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Proxy request granted"); + c->allow_request = ID; + return 8; + } else { + logger(LOG_ERR, "Proxy request rejected"); + return -1; + } + + case PROXY_SOCKS5: + if(c->buflen < 2) + return 0; + if(c->buffer[0] != 0x05 || c->buffer[1] == (char)0xff) { + logger(LOG_ERR, "Proxy authentication method rejected"); + return -1; + } + int offset = 2; + if(c->buffer[1] == 0x02) { + if(c->buflen < 4) + return 0; + if(c->buffer[2] != 0x05 || c->buffer[3] != 0x00) { + logger(LOG_ERR, "Proxy username/password rejected"); + return -1; + } + offset += 2; + } + if(c->buflen - offset < 7) + return 0; + if(c->buffer[offset] != 0x05 || c->buffer[offset + 1] != 0x00) { + logger(LOG_ERR, "Proxy request rejected"); + return -1; + } + int replen = offset + 6; + switch(c->buffer[offset + 3]) { + case 0x01: // IPv4 + if(c->address.sa.sa_family == AF_UNKNOWN) + update_address_ipv4(c, c->buffer + offset + 4, c->buffer + offset + 8); + replen += 4; + break; + case 0x03: // Hostname + if(c->address.sa.sa_family == AF_UNKNOWN) + update_address_ipv4(c, "\0\0\0\1", "\0\0"); + replen += ((uint8_t *)c->buffer)[offset + 4]; + break; + case 0x04: // IPv6 + if(c->address.sa.sa_family == AF_UNKNOWN) + update_address_ipv6(c, c->buffer + offset + 4, c->buffer + offset + 20); + replen += 16; + break; + default: + logger(LOG_ERR, "Proxy reply malformed"); + return -1; + } + if(c->buflen < replen) { + return 0; + } else { + ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Proxy request granted"); + c->allow_request = ID; + return replen; + } + + case PROXY_HTTP: { + char *p = memchr(c->buffer, '\n', c->buflen); + if(!p || p - c->buffer >= c->buflen) + return 0; + p = memchr(p + 1, '\n', c->buflen - (p + 1 - c->buffer)); + if(!p) + return 0; + + if(c->buflen < 9) + return 0; + + if(!strncasecmp(c->buffer, "HTTP/1.1 ", 9)) { + if(!strncmp(c->buffer + 9, "200", 3)) { + if(c->address.sa.sa_family == AF_UNKNOWN) + update_address_ipv4(c, "\0\0\0\1", "\0\0"); + logger(LOG_DEBUG, "Proxy request granted"); + replen = p + 1 - c->buffer; + c->allow_request = ID; + return replen; + } else { + logger(LOG_ERR, "Proxy request rejected: %s", c->buffer + 9); + return false; + } + } else { + logger(LOG_ERR, "Proxy reply malformed"); + return -1; + } + } + + default: + abort(); + } +} diff --git a/src/proxy.h b/src/proxy.h new file mode 100644 index 0000000..a982943 --- /dev/null +++ b/src/proxy.h @@ -0,0 +1,43 @@ +/* + proxy.h -- header for proxy.c + Copyright (C) 2015 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef __TINC_PROXY_H__ +#define __TINC_PROXY_H__ + +#include "connection.h" + +typedef enum proxytype_t { + PROXY_NONE = 0, + PROXY_SOCKS4, + PROXY_SOCKS4A, + PROXY_SOCKS5, + PROXY_HTTP, + PROXY_EXEC, +} proxytype_t; + +extern proxytype_t proxytype; +extern char *proxyhost; +extern char *proxyport; +extern char *proxyuser; +extern char *proxypass; + +extern bool send_proxyrequest(struct connection_t *c); +extern int receive_proxy_meta(struct connection_t *c, int start, int lenin); + +#endif diff --git a/src/route.c b/src/route.c index c11267b..bacfa62 100644 --- a/src/route.c +++ b/src/route.c @@ -2,6 +2,7 @@ route.c -- routing Copyright (C) 2000-2005 Ivo Timmermans, 2000-2014 Guus Sliepen + 2015 Vittorio Gambaletta 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 @@ -101,6 +102,260 @@ static bool checklength(node_t *source, vpn_packet_t *packet, length_t length) { return true; } +static void swap_mac_addresses(vpn_packet_t *packet) { + mac_t tmp; + memcpy(&tmp, &packet->data[0], sizeof tmp); + memcpy(&packet->data[0], &packet->data[6], sizeof tmp); + memcpy(&packet->data[6], &tmp, sizeof tmp); +} + +/* RFC 792 */ + +static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, length_t ether_size, uint8_t type, uint8_t code) { + struct ip ip = {0}; + struct icmp icmp = {0}; + + struct in_addr ip_src; + struct in_addr ip_dst; + uint32_t oldlen; + + if(ratelimit(3)) + return; + + /* Swap Ethernet source and destination addresses */ + + swap_mac_addresses(packet); + + /* Copy headers from packet into properly aligned structs on the stack */ + + memcpy(&ip, packet->data + ether_size, ip_size); + + /* Remember original source and destination */ + + ip_src = ip.ip_src; + ip_dst = ip.ip_dst; + + /* Try to reply with an IP address assigned to the local machine */ + + if (type == ICMP_TIME_EXCEEDED && code == ICMP_EXC_TTL) { + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd != -1) { + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr = ip.ip_src; + if (!connect(sockfd, (const struct sockaddr*) &addr, sizeof(addr))) { + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + socklen_t addrlen = sizeof(addr); + if (!getsockname(sockfd, (struct sockaddr*) &addr, &addrlen) && addrlen <= sizeof(addr)) { + ip_dst = addr.sin_addr; + } + } + close(sockfd); + } + } + + oldlen = packet->len - ether_size; + + if(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) + icmp.icmp_nextmtu = htons(packet->len - ether_size); + + if(oldlen >= IP_MSS - ip_size - icmp_size) + oldlen = IP_MSS - ip_size - icmp_size; + + /* Copy first part of original contents to ICMP message */ + + memmove(packet->data + ether_size + ip_size + icmp_size, packet->data + ether_size, oldlen); + + /* Fill in IPv4 header */ + + ip.ip_v = 4; + ip.ip_hl = ip_size / 4; + ip.ip_tos = 0; + ip.ip_len = htons(ip_size + icmp_size + oldlen); + ip.ip_id = 0; + ip.ip_off = 0; + ip.ip_ttl = 255; + ip.ip_p = IPPROTO_ICMP; + ip.ip_sum = 0; + ip.ip_src = ip_dst; + ip.ip_dst = ip_src; + + ip.ip_sum = inet_checksum(&ip, ip_size, ~0); + + /* Fill in ICMP header */ + + icmp.icmp_type = type; + icmp.icmp_code = code; + icmp.icmp_cksum = 0; + + icmp.icmp_cksum = inet_checksum(&icmp, icmp_size, ~0); + icmp.icmp_cksum = inet_checksum(packet->data + ether_size + ip_size + icmp_size, oldlen, icmp.icmp_cksum); + + /* Copy structs on stack back to packet */ + + memcpy(packet->data + ether_size, &ip, ip_size); + memcpy(packet->data + ether_size + ip_size, &icmp, icmp_size); + + packet->len = ether_size + ip_size + icmp_size + oldlen; + + send_packet(source, packet); +} + +/* RFC 2463 */ + +static void route_ipv6_unreachable(node_t *source, vpn_packet_t *packet, length_t ether_size, uint8_t type, uint8_t code) { + struct ip6_hdr ip6; + struct icmp6_hdr icmp6 = {0}; + uint16_t checksum; + + struct { + struct in6_addr ip6_src; /* source address */ + struct in6_addr ip6_dst; /* destination address */ + uint32_t length; + uint32_t next; + } pseudo; + + if(ratelimit(3)) + return; + + /* Swap Ethernet source and destination addresses */ + + swap_mac_addresses(packet); + + /* Copy headers from packet to structs on the stack */ + + memcpy(&ip6, packet->data + ether_size, ip6_size); + + /* Remember original source and destination */ + + pseudo.ip6_src = ip6.ip6_dst; + pseudo.ip6_dst = ip6.ip6_src; + + /* Try to reply with an IP address assigned to the local machine */ + + if (type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT) { + int sockfd = socket(AF_INET6, SOCK_DGRAM, 0); + if (sockfd != -1) { + struct sockaddr_in6 addr; + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_addr = ip6.ip6_src; + if (!connect(sockfd, (const struct sockaddr*) &addr, sizeof(addr))) { + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + socklen_t addrlen = sizeof(addr); + if (!getsockname(sockfd, (struct sockaddr*) &addr, &addrlen) && addrlen <= sizeof(addr)) { + pseudo.ip6_src = addr.sin6_addr; + } + } + close(sockfd); + } + } + + pseudo.length = packet->len - ether_size; + + if(type == ICMP6_PACKET_TOO_BIG) + icmp6.icmp6_mtu = htonl(pseudo.length); + + if(pseudo.length >= IP_MSS - ip6_size - icmp6_size) + pseudo.length = IP_MSS - ip6_size - icmp6_size; + + /* Copy first part of original contents to ICMP message */ + + memmove(packet->data + ether_size + ip6_size + icmp6_size, packet->data + ether_size, pseudo.length); + + /* Fill in IPv6 header */ + + ip6.ip6_flow = htonl(0x60000000UL); + ip6.ip6_plen = htons(icmp6_size + pseudo.length); + ip6.ip6_nxt = IPPROTO_ICMPV6; + ip6.ip6_hlim = 255; + ip6.ip6_src = pseudo.ip6_src; + ip6.ip6_dst = pseudo.ip6_dst; + + /* Fill in ICMP header */ + + icmp6.icmp6_type = type; + icmp6.icmp6_code = code; + icmp6.icmp6_cksum = 0; + + /* Create pseudo header */ + + pseudo.length = htonl(icmp6_size + pseudo.length); + pseudo.next = htonl(IPPROTO_ICMPV6); + + /* Generate checksum */ + + checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0); + checksum = inet_checksum(&icmp6, icmp6_size, checksum); + checksum = inet_checksum(packet->data + ether_size + ip6_size + icmp6_size, ntohl(pseudo.length) - icmp6_size, checksum); + + icmp6.icmp6_cksum = checksum; + + /* Copy structs on stack back to packet */ + + memcpy(packet->data + ether_size, &ip6, ip6_size); + memcpy(packet->data + ether_size + ip6_size, &icmp6, icmp6_size); + + packet->len = ether_size + ip6_size + ntohl(pseudo.length); + + send_packet(source, packet); +} + +static bool do_decrement_ttl(node_t *source, vpn_packet_t *packet) { + uint16_t type = packet->data[12] << 8 | packet->data[13]; + length_t ethlen = ether_size; + + if(type == ETH_P_8021Q) { + type = packet->data[16] << 8 | packet->data[17]; + ethlen += 4; + } + + switch (type) { + case ETH_P_IP: + if(!checklength(source, packet, ethlen + ip_size)) + return false; + + if(packet->data[ethlen + 8] <= 1) { + 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); + return false; + } + + uint16_t old = packet->data[ethlen + 8] << 8 | packet->data[ethlen + 9]; + packet->data[ethlen + 8]--; + uint16_t new = packet->data[ethlen + 8] << 8 | packet->data[ethlen + 9]; + + uint32_t checksum = packet->data[ethlen + 10] << 8 | packet->data[ethlen + 11]; + checksum += old + (~new & 0xFFFF); + while(checksum >> 16) + checksum = (checksum & 0xFFFF) + (checksum >> 16); + packet->data[ethlen + 10] = checksum >> 8; + packet->data[ethlen + 11] = checksum & 0xff; + + return true; + + case ETH_P_IPV6: + if(!checklength(source, packet, ethlen + ip6_size)) + return false; + + if(packet->data[ethlen + 7] <= 1) { + 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); + return false; + } + + packet->data[ethlen + 7]--; + + return true; + + default: + return true; + } +} + static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *packet) { if(!source || !via || !(via->options & OPTION_CLAMP_MSS)) return; @@ -160,7 +415,7 @@ static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *pac /* Found it */ uint16_t oldmss = packet->data[start + 22 + i] << 8 | packet->data[start + 23 + i]; uint16_t newmss = mtu - start - 20; - uint16_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) break; @@ -171,21 +426,16 @@ static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *pac packet->data[start + 22 + i] = newmss >> 8; packet->data[start + 23 + i] = newmss & 0xff; csum ^= 0xffff; - csum -= oldmss; + csum += oldmss ^ 0xffff; csum += newmss; + csum = (csum & 0xffff) + (csum >> 16); + csum += csum >> 16; csum ^= 0xffff; packet->data[start + 16] = csum >> 8; - packet->data[start + 17] = csum & 0xff; + packet->data[start + 17] = csum; break; } } - -static void swap_mac_addresses(vpn_packet_t *packet) { - mac_t tmp; - memcpy(&tmp, &packet->data[0], sizeof tmp); - memcpy(&packet->data[0], &packet->data[6], sizeof tmp); - memcpy(&packet->data[6], &tmp, sizeof tmp); -} static void learn_mac(mac_t *address) { subnet_t *subnet; @@ -249,77 +499,12 @@ void age_subnets(void) { } } -/* RFC 792 */ +static void route_broadcast(node_t *source, vpn_packet_t *packet) { + if(decrement_ttl && source != myself) + if(!do_decrement_ttl(source, packet)) + return; -static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, length_t ether_size, uint8_t type, uint8_t code) { - struct ip ip = {0}; - struct icmp icmp = {0}; - - struct in_addr ip_src; - struct in_addr ip_dst; - uint32_t oldlen; - - if(ratelimit(3)) - return; - - /* Swap Ethernet source and destination addresses */ - - swap_mac_addresses(packet); - - /* Copy headers from packet into properly aligned structs on the stack */ - - memcpy(&ip, packet->data + ether_size, ip_size); - - /* Remember original source and destination */ - - ip_src = ip.ip_src; - ip_dst = ip.ip_dst; - - oldlen = packet->len - ether_size; - - if(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) - icmp.icmp_nextmtu = htons(packet->len - ether_size); - - if(oldlen >= IP_MSS - ip_size - icmp_size) - oldlen = IP_MSS - ip_size - icmp_size; - - /* Copy first part of original contents to ICMP message */ - - memmove(packet->data + ether_size + ip_size + icmp_size, packet->data + ether_size, oldlen); - - /* Fill in IPv4 header */ - - ip.ip_v = 4; - ip.ip_hl = ip_size / 4; - ip.ip_tos = 0; - ip.ip_len = htons(ip_size + icmp_size + oldlen); - ip.ip_id = 0; - ip.ip_off = 0; - ip.ip_ttl = 255; - ip.ip_p = IPPROTO_ICMP; - ip.ip_sum = 0; - ip.ip_src = ip_dst; - ip.ip_dst = ip_src; - - ip.ip_sum = inet_checksum(&ip, ip_size, ~0); - - /* Fill in ICMP header */ - - icmp.icmp_type = type; - icmp.icmp_code = code; - icmp.icmp_cksum = 0; - - icmp.icmp_cksum = inet_checksum(&icmp, icmp_size, ~0); - icmp.icmp_cksum = inet_checksum(packet->data + ether_size + ip_size + icmp_size, oldlen, icmp.icmp_cksum); - - /* Copy structs on stack back to packet */ - - memcpy(packet->data + ether_size, &ip, ip_size); - memcpy(packet->data + ether_size + ip_size, &icmp, icmp_size); - - packet->len = ether_size + ip_size + icmp_size + oldlen; - - send_packet(source, packet); + broadcast_packet(source, packet); } /* RFC 791 */ @@ -403,6 +588,10 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) { if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself) return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_ANO); + if(decrement_ttl && source != myself && subnet->owner != myself) + if(!do_decrement_ttl(source, packet)) + return; + if(priorityinheritance) packet->priority = packet->data[15]; @@ -442,91 +631,11 @@ static void route_ipv4(node_t *source, vpn_packet_t *packet) { packet->data[31] == 255 && packet->data[32] == 255 && packet->data[33] == 255))) - broadcast_packet(source, packet); + route_broadcast(source, packet); else route_ipv4_unicast(source, packet); } -/* RFC 2463 */ - -static void route_ipv6_unreachable(node_t *source, vpn_packet_t *packet, length_t ether_size, uint8_t type, uint8_t code) { - struct ip6_hdr ip6; - struct icmp6_hdr icmp6 = {0}; - uint16_t checksum; - - struct { - struct in6_addr ip6_src; /* source address */ - struct in6_addr ip6_dst; /* destination address */ - uint32_t length; - uint32_t next; - } pseudo; - - if(ratelimit(3)) - return; - - /* Swap Ethernet source and destination addresses */ - - swap_mac_addresses(packet); - - /* Copy headers from packet to structs on the stack */ - - memcpy(&ip6, packet->data + ether_size, ip6_size); - - /* Remember original source and destination */ - - pseudo.ip6_src = ip6.ip6_dst; - pseudo.ip6_dst = ip6.ip6_src; - - pseudo.length = packet->len - ether_size; - - if(type == ICMP6_PACKET_TOO_BIG) - icmp6.icmp6_mtu = htonl(pseudo.length); - - if(pseudo.length >= IP_MSS - ip6_size - icmp6_size) - pseudo.length = IP_MSS - ip6_size - icmp6_size; - - /* Copy first part of original contents to ICMP message */ - - memmove(packet->data + ether_size + ip6_size + icmp6_size, packet->data + ether_size, pseudo.length); - - /* Fill in IPv6 header */ - - ip6.ip6_flow = htonl(0x60000000UL); - ip6.ip6_plen = htons(icmp6_size + pseudo.length); - ip6.ip6_nxt = IPPROTO_ICMPV6; - ip6.ip6_hlim = 255; - ip6.ip6_src = pseudo.ip6_src; - ip6.ip6_dst = pseudo.ip6_dst; - - /* Fill in ICMP header */ - - icmp6.icmp6_type = type; - icmp6.icmp6_code = code; - icmp6.icmp6_cksum = 0; - - /* Create pseudo header */ - - pseudo.length = htonl(icmp6_size + pseudo.length); - pseudo.next = htonl(IPPROTO_ICMPV6); - - /* Generate checksum */ - - checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0); - checksum = inet_checksum(&icmp6, icmp6_size, checksum); - checksum = inet_checksum(packet->data + ether_size + ip6_size + icmp6_size, ntohl(pseudo.length) - icmp6_size, checksum); - - icmp6.icmp6_cksum = checksum; - - /* Copy structs on stack back to packet */ - - memcpy(packet->data + ether_size, &ip6, ip6_size); - memcpy(packet->data + ether_size + ip6_size, &icmp6, icmp6_size); - - packet->len = ether_size + ip6_size + ntohl(pseudo.length); - - send_packet(source, packet); -} - static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) { subnet_t *subnet; node_t *via; @@ -562,6 +671,10 @@ static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) { if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself) return route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN); + if(decrement_ttl && source != myself && subnet->owner != myself) + if(!do_decrement_ttl(source, packet)) + return; + via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via; if(via == source) { @@ -678,6 +791,10 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet) { if(subnet->owner == myself) return; /* silently ignore */ + if(decrement_ttl) + if(!do_decrement_ttl(source, packet)) + return; + /* Create neighbor advertation reply */ memcpy(packet->data, packet->data + ETH_ALEN, ETH_ALEN); /* copy destination address */ @@ -735,7 +852,7 @@ static void route_ipv6(node_t *source, vpn_packet_t *packet) { } if(broadcast_mode && packet->data[38] == 255) - broadcast_packet(source, packet); + route_broadcast(source, packet); else route_ipv6_unicast(source, packet); } @@ -788,6 +905,10 @@ static void route_arp(node_t *source, vpn_packet_t *packet) { if(subnet->owner == myself) return; /* silently ignore */ + if(decrement_ttl) + if(!do_decrement_ttl(source, packet)) + return; + 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 */ @@ -824,7 +945,7 @@ static void route_mac(node_t *source, vpn_packet_t *packet) { subnet = lookup_subnet_mac(NULL, &dest); if(!subnet) { - broadcast_packet(source, packet); + route_broadcast(source, packet); return; } @@ -836,6 +957,10 @@ static void route_mac(node_t *source, vpn_packet_t *packet) { if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself) return; + if(decrement_ttl && source != myself && subnet->owner != myself) + if(!do_decrement_ttl(source, packet)) + return; + uint16_t type = packet->data[12] << 8 | packet->data[13]; if(priorityinheritance && type == ETH_P_IP && packet->len >= ether_size + ip_size) @@ -877,58 +1002,6 @@ static void route_mac(node_t *source, vpn_packet_t *packet) { send_packet(subnet->owner, packet); } -static bool do_decrement_ttl(node_t *source, vpn_packet_t *packet) { - uint16_t type = packet->data[12] << 8 | packet->data[13]; - length_t ethlen = ether_size; - - if(type == ETH_P_8021Q) { - type = packet->data[16] << 8 | packet->data[17]; - ethlen += 4; - } - - switch (type) { - case ETH_P_IP: - if(!checklength(source, packet, ethlen + ip_size)) - return false; - - if(packet->data[ethlen + 8] < 1) { - 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); - return false; - } - - uint16_t old = packet->data[ethlen + 8] << 8 | packet->data[ethlen + 9]; - packet->data[ethlen + 8]--; - uint16_t new = packet->data[ethlen + 8] << 8 | packet->data[ethlen + 9]; - - uint32_t checksum = packet->data[ethlen + 10] << 8 | packet->data[ethlen + 11]; - checksum += old + (~new & 0xFFFF); - while(checksum >> 16) - checksum = (checksum & 0xFFFF) + (checksum >> 16); - packet->data[ethlen + 10] = checksum >> 8; - packet->data[ethlen + 11] = checksum & 0xff; - - return true; - - case ETH_P_IPV6: - if(!checklength(source, packet, ethlen + ip6_size)) - return false; - - if(packet->data[ethlen + 7] < 1) { - 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); - return false; - } - - packet->data[ethlen + 7]--; - - return true; - - default: - return true; - } -} - void route(node_t *source, vpn_packet_t *packet) { if(forwarding_mode == FMODE_KERNEL && source != myself) { send_packet(myself, packet); @@ -938,10 +1011,6 @@ void route(node_t *source, vpn_packet_t *packet) { if(!checklength(source, packet, ether_size)) return; - if(decrement_ttl && source != myself) - if(!do_decrement_ttl(source, packet)) - return; - switch (routing_mode) { case RMODE_ROUTER: { @@ -972,7 +1041,7 @@ void route(node_t *source, vpn_packet_t *packet) { break; case RMODE_HUB: - broadcast_packet(source, packet); + route_broadcast(source, packet); break; } } diff --git a/src/subnet.c b/src/subnet.c index 6e8ad07..b4a636b 100644 --- a/src/subnet.c +++ b/src/subnet.c @@ -534,18 +534,17 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) { xasprintf(&envp[1], "DEVICE=%s", device ? : ""); xasprintf(&envp[2], "INTERFACE=%s", iface ? : ""); xasprintf(&envp[3], "NODE=%s", owner->name); + xasprintf(&envp[4], "NAME=%s", myself->name); if(owner != myself) { sockaddr2str(&owner->address, &address, &port); - // 4 and 5 are reserved for SUBNET and WEIGHT - xasprintf(&envp[6], "REMOTEADDRESS=%s", address); - xasprintf(&envp[7], "REMOTEPORT=%s", port); + // 5 and 6 are reserved for SUBNET and WEIGHT + xasprintf(&envp[7], "REMOTEADDRESS=%s", address); + xasprintf(&envp[8], "REMOTEPORT=%s", port); free(port); free(address); } - xasprintf(&envp[8], "NAME=%s", myself->name); - name = up ? "subnet-up" : "subnet-down"; if(!subnet) { @@ -561,12 +560,12 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) { weight = empty; // Prepare the SUBNET and WEIGHT variables - if(envp[4]) - free(envp[4]); if(envp[5]) free(envp[5]); - xasprintf(&envp[4], "SUBNET=%s", netstr); - xasprintf(&envp[5], "WEIGHT=%s", weight); + if(envp[6]) + free(envp[6]); + xasprintf(&envp[5], "SUBNET=%s", netstr); + xasprintf(&envp[6], "WEIGHT=%s", weight); execute_script(name, envp); } @@ -580,8 +579,8 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) { weight = empty; // Prepare the SUBNET and WEIGHT variables - xasprintf(&envp[4], "SUBNET=%s", netstr); - xasprintf(&envp[5], "WEIGHT=%s", weight); + xasprintf(&envp[5], "SUBNET=%s", netstr); + xasprintf(&envp[6], "WEIGHT=%s", weight); execute_script(name, envp); } diff --git a/src/tincd.c b/src/tincd.c index a2b3580..f106f5f 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -1,7 +1,7 @@ /* tincd.c -- the main file for tincd Copyright (C) 1998-2005 Ivo Timmermans - 2000-2015 Guus Sliepen + 2000-2016 Guus Sliepen 2008 Max Rijevski 2009 Michael Tokarev 2010 Julien Muchembled @@ -49,7 +49,12 @@ #include #endif +#ifdef HAVE_GETOPT_LONG #include +#else +#include "getopt.h" +#endif + #include "pidfile.h" #include "conf.h" @@ -239,7 +244,8 @@ static bool parse_options(int argc, char **argv) { usage(true); return false; } - netname = strcmp(optarg, ".") != 0 ? xstrdup(optarg) : NULL; + if(optarg && strcmp(optarg, ".")) + netname = xstrdup(optarg); break; case 'o': /* option */ @@ -547,9 +553,8 @@ int main(int argc, char **argv) { make_names(); if(show_version) { - printf("%s version %s (built %s %s, protocol %d)\n", PACKAGE, - VERSION, __DATE__, __TIME__, PROT_CURRENT); - printf("Copyright (C) 1998-2015 Ivo Timmermans, Guus Sliepen and others.\n" + printf("%s version %s\n", PACKAGE, VERSION); + printf("Copyright (C) 1998-2016 Ivo Timmermans, Guus Sliepen and others.\n" "See the AUTHORS file for a complete list.\n\n" "tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n" "and you are welcome to redistribute it under certain conditions;\n"