Synchronise HEAD with CABAL branch.

This commit is contained in:
Guus Sliepen 2003-08-24 20:38:31 +00:00
parent efa5148bc7
commit 013a2e159e
173 changed files with 12252 additions and 28046 deletions

View file

@ -1,6 +1,6 @@
Main tinc authors:
Guus Sliepen <guus@sliepen.warande.net>
Ivo Timmermans <itimmermans@bigfoot.com>
Guus Sliepen <guus@sliepen.eu.org>
Ivo Timmermans <ivo@o2w.nl>
These files are from other sources:
* lib/pidfile.h and lib/pidfile.c are by Martin Schulze, taken from

View file

@ -2,16 +2,17 @@
AUTOMAKE_OPTIONS = gnu
SUBDIRS = m4 intl lib src doc po
SUBDIRS = m4 lib src doc po
ACLOCAL_AMFLAGS =
ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = system.h COPYING.README depcomp
EXTRA_DIST = config.rpath mkinstalldirs system.h COPYING.README depcomp
CVS_CREATED = ABOUT-NLS configure aclocal.m4 config.h.in config.guess \
config.sub install-sh ltconfig ltmain.sh missing mkinstalldirs \
stamp-h.in m4/Makefile.am ChangeLog po/Makefile.in.in \
po/tinc.pot src/.libs intl depcomp
po/tinc.pot po/*.sed po/*.header po/*.sin po/Rules-quot \
src/.libs intl depcomp
ChangeLog:
cvs2cl -U cvsusers --fsf
@ -20,6 +21,7 @@ cvs-clean: maintainer-clean
for f in $(CVS_CREATED) `find . -name Makefile.in` tinc-$(VERSION).tar.gz; do\
rm -Rf "$$f"; \
done
grep -l gettext `find m4 -type f` | xargs rm -f
deb:
dpkg-buildpackage -rfakeroot

37
NEWS
View file

@ -1,3 +1,40 @@
version 1.0.1 Aug 14 2003
* Allow empty lines in config files.
* Fix handling of spaces and backslashes in filenames under native Windows.
* Allow scripts to be executed under native Windows.
* Update documentation, make it less Linux specific.
version 1.0 Aug 4 2003
* Lots of small bugfixes and code cleanups.
* Throughput doubled and latency reduced.
* Added support for LZO compression.
* No need to set MAC address or disable ARP anymore.
* Added support for Windows 2000 and XP, both natively and in a Cygwin
environment.
version 1.0pre8 Sep 16 2002
* More fixes for subnets with prefixlength undivisible by 8.
* Added support for NetBSD and MacOS/X.
* Switched from undirected graphs to directed graphs to avoid certain race
conditions and improve scalability.
* Generalized broadcasting and forwarding of protocol messages.
* Cleanup of source code.
version 1.0pre7 Apr 7 2002
* Don't do blocking read()s when getting a signal.

57
README
View file

@ -1,10 +1,10 @@
This is the README file for tinc version 1.0pre7. Installation
This is the README file for tinc version 1.0.1. Installation
instructions may be found in the INSTALL file.
tinc is Copyright (C) 1998-2002 by:
tinc is Copyright (C) 1998-2003 by:
Ivo Timmermans <itimmermans@bigfoot.com>,
Guus Sliepen <guus@sliepen.warande.net>,
Ivo Timmermans <ivo@o2w.nl>,
Guus Sliepen <guus@sliepen.eu.org>,
and others.
For a complete list of authors see the AUTHORS file.
@ -44,13 +44,19 @@ Some configuration variables have different names now. Most notably "TapDevice"
should be changed into "Device", and "Device" should be changed into
"BindToDevice".
Compatibility
-------------
Version 1.0.1 is compatible with 1.0 and 1.0pre8 but not with older versions
of tinc.
Requirements
------------
Since 1.0pre3, we use OpenSSL for all cryptographic functions. So you
need to install this library first; grab it from
http://www.openssl.org/. We recommend version 0.9.5 or better. If
http://www.openssl.org/. You will need version 0.9.7 or later. If
this library is not installed on you system, configure will fail. The
manual in doc/tinc.texi contains more detailed information on how to
install this library.
@ -60,8 +66,11 @@ library whether or not you plan to enable the compression. You can find it at
http://www.gzip.org/zlib/. Because of a possible exploit in earlier versions we
recommand that you download version 1.1.4 or later.
In order to compile tinc, you will also need autoconf, automake, GNU make, m4
and gettext.
Since 1.0, the lzo library is also used for optional compression. You need this
library whether or not you plan to enable compression. You can find it at
http://www.oberhumer.com/opensource/lzo/.
In order to compile tinc, you will need a GNU C compiler environment.
Features
@ -70,17 +79,7 @@ Features
This version of tinc supports multiple virtual networks at once. To
use this feature, you may supply a netname via the -n or --net
options. The standard locations for the config files will then be
/etc/tinc/<net>/. Because of this feature, tinc will send packets
directly to their destinations, instead of to the uplink. If this
behaviour is undesirable (for instance because of firewalls or other
restrictions), please use an older version of tinc (I would recommend
tinc-0.2.19).
In order to force the kernel to accept received packets, the
destination MAC address will be set to FE:FD:00:00:00:00 upon
reception. The MAC address of the ethertap or tun/tap interface must
also be set to this address. See the manual for more detailed
information.
/etc/tinc/<net>/.
tincd regenerates its encryption key pairs. It does this on the first
activity after the keys have expired. This period is adjustable in the
@ -96,7 +95,7 @@ Since pre5, tinc can operate in several routing modes. The default mode,
determine the destination of packets. The other two modes, "switch" and "hub",
allow the tinc daemons to work together like a single network switch or hub.
This is useful for bridging networks. The latter modes only work properly on
Linux and FreeBSD.
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
@ -107,11 +106,17 @@ etcetera.
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. Autoconfiguration will not work in router mode. Tunneling IPv6
packets only works on Linux, FreeBSD and possibly OpenBSD.
addresses. tinc does not provide autoconfiguration for IPv6 hosts, if you need
it use radvd or zebra. Tunneling IPv6 packets only works on Linux, FreeBSD,
Windows and possibly OpenBSD.
It is also possible to make tunnels to other tinc daemons over IPv6 networks,
if the operating system supports IPv6. tinc will automatically use both IPv6
and IPv4 when available, but this can be changed by adding the option
"AddressFamily = ipv4" or "AddressFamily = ipv6" to the tinc.conf file.
Normally, when started tinc will detach and run in the background. In a native
Windows environment this means tinc will intall itself as a service, which will
restart after reboots. To prevent tinc from detaching or running as a service,
use the -D option.
It is also possible to make tunnels to other tinc daemons over IPv6 networks.
In order to enable this feature the option "AddressFamily = any" or
"AddressFamily = ipv6" must be added to the tinc.conf file. The host
configuration files should contain IPv6 addresses for the "Address" variables,
or hostnames which have an AAAA or A6 record.

8
THANKS
View file

@ -18,6 +18,14 @@ We would like to thank
* Armijn Hemel (for being our very own PR manager)
* Jerome Etienne (for a thorough security analysis of tinc)
* Mark Glines (for his compression patch)
* Nick Patavalis (RedHat package)
* Alessandro Gatti (for helping us support Darwin)
* Ivo van Dong (for help during the early versions of tinc)
* Jeroen Ubbink (for help testing tinc on Free- and NetBSD)
* LarstiQ (for help testing tinc on MacOS/X)
* Marc A. Lehmann (for criticism)
* Teemu Kiviniemi (for his lzo compression patch)
* Flynn Marquardt (for help testing tinc on Solaris 2.6)
for their help, support and ideas. Thank you guys!

4
TODO
View file

@ -1,5 +1,3 @@
TODO LIST
1.0:
* A nice, secure and stable release
* Think of new things to do.

View file

@ -1,91 +0,0 @@
/* Define to the name name of this package */
#undef PACKAGE
/* Define to the version of the package */
#undef VERSION
/* Define to rpl_malloc if the replacement function should be used. */
#undef malloc
/* Define to rpl_realloc if the replacement function should be used. */
#undef realloc
/* This is always defined. It enables GNU extensions on systems that
have them. */
#if !defined(_GNU_SOURCE)
# undef _GNU_SOURCE
#endif
#if !defined(__USE_BSD)
# undef __USE_BSD
#endif
/* Define to 1 if NLS is requested. */
#undef ENABLE_NLS
/* Define as 1 if you have catgets and don't want to use GNU gettext. */
#undef HAVE_CATGETS
/* Define as 1 if you have gettext and don't want to use GNU gettext. */
#undef HAVE_GETTEXT
/* Define if your locale.h file contains LC_MESSAGES. */
#undef HAVE_LC_MESSAGES
/* Define to 1 if you have the stpcpy function. */
#undef HAVE_STPCPY
/* For getopt */
#if HAVE_STDLIB_H
# define getopt system_getopt
# include <stdlib.h>
# undef getopt
#endif
/* Linux */
#undef HAVE_LINUX
/* FreeBSD */
#undef HAVE_FREEBSD
/* OpenBSD */
#undef HAVE_OPENBSD
/* Solaris */
#undef HAVE_SOLARIS
/* NetBSD */
#undef HAVE_NETBSD
/* Define to the location of the kernel sources */
#undef CONFIG_TINC_KERNELDIR
/* Define to 1 if tun/tap support is enabled and found */
#undef HAVE_TUNTAP
/* Define to the location of if_tun.h */
#undef LINUX_IF_TUN_H
/* Define to 1 if support for jumbograms is enabled */
#undef ENABLE_JUMBOGRAMS
/* Define to 1 if checkpoint tracing is enabled */
#undef ENABLE_TRACING
/* Define to enable use of old SSLeay_add_all_algorithms() function */
#undef HAVE_SSLEAY_ADD_ALL_ALGORITHMS
/* Define to 1 if you want to include GCRYPT support */
#undef USE_GCRYPT
/* Define to 1 if you want to include OpenSSL support */
#undef USE_OPENSSL
#if defined(USE_GCRYPT) && defined(USE_OPENSSL)
# error You can only define one of USE_GCRYPT and USE_OPENSSL
#endif
#if !defined(USE_GCRYPT) && !defined(USE_OPENSSL)
# error You must define exactly one of USE_GCRYPT and USE_OPENSSL
#endif

View file

@ -96,6 +96,30 @@ do
echo processing $dr
macrodirs=`sed -n -e 's,AM_ACLOCAL_INCLUDE(\(.*\)),\1,gp' < $coin`
( cd $dr
if grep "^AM_GNU_GETTEXT" configure.in >/dev/null; then
if grep "sed.*POTFILES" configure.in >/dev/null; then
: do nothing -- we still have an old unmodified configure.in
else
echo "Creating $dr/aclocal.m4 ..."
test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
echo "Running autopoint..."
autopoint --force
echo "Making $dr/aclocal.m4 writable ..."
test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
fi
fi
if grep "^AM_GNOME_GETTEXT" configure.in >/dev/null; then
echo "Creating $dr/aclocal.m4 ..."
test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
echo "Running autopoint..."
autopoint --force
echo "Making $dr/aclocal.m4 writable ..."
test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
fi
if grep "^AM_PROG_LIBTOOL" configure.in >/dev/null; then
echo "Running libtoolize..."
libtoolize --force --copy
fi
aclocalinclude="$ACLOCAL_FLAGS"
for k in $macrodirs; do
if test -d $k; then
@ -108,30 +132,6 @@ do
fi
done
touch ChangeLog
if grep "^AM_GNU_GETTEXT" configure.in >/dev/null; then
if grep "sed.*POTFILES" configure.in >/dev/null; then
: do nothing -- we still have an old unmodified configure.in
else
echo "Creating $dr/aclocal.m4 ..."
test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
echo "Running gettextize... Ignore non-fatal messages."
echo "no" | gettextize --force --copy
echo "Making $dr/aclocal.m4 writable ..."
test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
fi
fi
if grep "^AM_GNOME_GETTEXT" configure.in >/dev/null; then
echo "Creating $dr/aclocal.m4 ..."
test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
echo "Running gettextize... Ignore non-fatal messages."
echo "no" | gettextize --force --copy
echo "Making $dr/aclocal.m4 writable ..."
test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
fi
if grep "^AM_PROG_LIBTOOL" configure.in >/dev/null; then
echo "Running libtoolize..."
libtoolize --force --copy
fi
echo "Running aclocal $aclocalinclude ..."
aclocal $aclocalinclude
if grep "^AM_CONFIG_HEADER" configure.in >/dev/null; then

View file

@ -1,18 +1,24 @@
dnl Process this file with autoconf to produce a configure script.
dnl $Id: configure.in,v 1.19 2002/04/28 12:46:25 zarq Exp $
dnl $Id: configure.in,v 1.20 2003/08/24 20:38:18 guus Exp $
AC_PREREQ(2.57)
AC_INIT(src/tincd.c)
AM_INIT_AUTOMAKE(tinc, 1.0-cvs)
AM_CONFIG_HEADER(config.h)
AM_MAINTAINER_MODE
dnl Include the macros from the m4/ directory
AM_ACLOCAL_INCLUDE(m4)
AM_GNU_GETTEXT([external])
AM_GNU_GETTEXT_VERSION(0.12.1)
# Enable GNU extensions.
# Define this here, not in acconfig's @TOP@ section, since definitions
# in the latter don't make it into the configure-time tests.
AC_DEFINE([_GNU_SOURCE], [__USE_BSD])
AC_DEFINE([_GNU_SOURCE], 1, [Enable GNU extenstions])
AC_DEFINE([__USE_BSD], 1, [Enable BSD extensions])
ALL_LINGUAS="nl"
@ -24,66 +30,233 @@ AC_PROG_AWK
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
jm_PERL
AC_PROG_RANLIB
AC_ISC_POSIX
dnl Check and set OS
AC_CANONICAL_HOST
#AC_CANONICAL_HOST
case $host_os in
*linux*)
AC_DEFINE(HAVE_LINUX)
AC_DEFINE(HAVE_LINUX, 1, [Linux])
[ rm -f src/device.c; ln -sf linux/device.c src/device.c ]
;;
*freebsd*)
AC_DEFINE(HAVE_FREEBSD)
AC_DEFINE(HAVE_FREEBSD, 1, [FreeBSD])
[ rm -f src/device.c; ln -sf freebsd/device.c src/device.c ]
;;
*darwin*)
AC_DEFINE(HAVE_DARWIN, 1, [Darwin (MacOS/X)])
[ rm -f src/device.c; ln -sf darwin/device.c src/device.c ]
;;
*solaris*)
AC_DEFINE(HAVE_SOLARIS)
AC_DEFINE(HAVE_SOLARIS, 1, [Solaris/SunOS])
[ rm -f src/device.c; ln -sf solaris/device.c src/device.c ]
;;
*openbsd*)
AC_DEFINE(HAVE_OPENBSD)
AC_DEFINE(HAVE_OPENBSD, 1, [OpenBSD])
[ rm -f src/device.c; ln -sf openbsd/device.c src/device.c ]
;;
*netbsd*)
AC_DEFINE(HAVE_NETBSD)
AC_DEFINE(HAVE_NETBSD, 1, [NetBSD])
[ rm -f src/device.c; ln -sf netbsd/device.c src/device.c ]
;;
*cygwin*)
AC_DEFINE(HAVE_CYGWIN, 1, [Cygwin])
[ rm -f src/device.c; ln -sf cygwin/device.c src/device.c ]
;;
*mingw*)
AC_DEFINE(HAVE_MINGW, 1, [MinGW])
[ rm -f src/device.c; cp -f src/mingw/device.c src/device.c ]
LIBS="$LIBS -lws2_32"
;;
*)
AC_MSG_ERROR("Unknown operating system.")
;;
esac
AC_CACHE_SAVE
if test -d /sw/include ; then
CPPFLAGS="$CPPFLAGS -I/sw/include"
fi
if test -d /sw/lib ; then
LIBS="$LIBS -L/sw/lib"
fi
dnl Checks for libraries.
dnl Checks for header files.
dnl We do this in multiple stages, because unlike Linux all the other operating systems really suck and don't include their own dependencies.
AC_HEADER_STDC
AC_CHECK_HEADERS([fcntl.h limits.h sys/ioctl.h syslog.h unistd.h \
sys/time.h malloc.h strings.h sys/file.h])
AC_CHECK_HEADERS([stdbool.h syslog.h sys/file.h sys/ioctl.h sys/param.h sys/time.h sys/socket.h sys/wait.h sys/mman.h netdb.h arpa/inet.h])
AC_CHECK_HEADERS([net/if.h net/ethernet.h net/if_arp.h netinet/in_systm.h netinet/in.h netinet/in6.h],
[], [],
[#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
]
)
AC_CHECK_HEADERS([netinet/if_ether.h netinet/ip.h netinet/ip6.h],
[], [],
[#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#ifdef HAVE_NETINET_IN_SYSTM_H
#include <netinet/in_systm.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETINET_IN6_H
#include <netinet/in6.h>
#endif
#ifdef HAVE_NET_ETHERNET_H
#include <net/ethernet.h>
#endif
#ifdef HAVE_NET_IF_ARP_H
#include <net/if_arp.h>
#endif
]
)
AC_CHECK_HEADERS([netinet/tcp.h netinet/ip_icmp.h netinet/icmp6.h],
[], [],
[#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#ifdef HAVE_NETINET_IN_SYSTM_H
#include <netinet/in_systm.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETINET_IP_H
#include <netinet/ip.h>
#endif
#ifdef HAVE_NETINET_IN6_H
#include <netinet/in6.h>
#endif
#ifdef HAVE_NETINET_IP6_H
#include <netinet/ip6.h>
#endif
#ifdef HAVE_NET_ETHERNET_H
#include <net/ethernet.h>
#endif
#ifdef HAVE_NET_IF_ARP_H
#include <net/if_arp.h>
#endif
#ifdef HAVE_NETINET_IF_ETHER_H
#include <netinet/if_ether.h>
#endif
]
)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_C_VOLATILE
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_HEADER_TIME
AC_STRUCT_TM
tinc_ATTRIBUTE(__malloc__)
AC_CHECK_TYPES([socklen_t, struct arphdr, struct ether_arp, struct in_addr, struct addrinfo, struct ip, struct icmp, struct in6_addr, struct sockaddr_in6, struct ip6_hdr, struct icmp6_hdr, struct nd_neighbor_solicit, struct nd_opt_hdr], , ,
[#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#ifdef HAVE_NETINET_IN_SYSTM_H
#include <netinet/in_systm.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETINET_IP_H
#include <netinet/ip.h>
#endif
#ifdef HAVE_NETINET_TCP_H
#include <netinet/tcp.h>
#endif
#ifdef HAVE_NETINET_IN6_H
#include <netinet/in6.h>
#endif
#ifdef HAVE_NETINET_IP6_H
#include <netinet/ip6.h>
#endif
#ifdef HAVE_NET_ETHERNET_H
#include <net/ethernet.h>
#endif
#ifdef HAVE_NET_IF_ARP_H
#include <net/if_arp.h>
#endif
#ifdef HAVE_NETINET_IF_ETHER_H
#include <netinet/if_ether.h>
#endif
#ifdef HAVE_NETINET_IP_ICMP_H
#include <netinet/ip_icmp.h>
#endif
#ifdef HAVE_NETINET_ICMP6_H
#include <netinet/icmp6.h>
#endif
]
)
dnl Checks for library functions.
AC_FUNC_MEMCMP
AC_FUNC_ALLOCA
AC_TYPE_SIGNAL
AC_CHECK_FUNCS([ftime socket select strtol strerror flock unsetenv \
asprintf putenv strdup fcloseall daemon strsignal get_current_dir_name])
AC_CHECK_FUNCS([asprintf daemon fchmod fcloseall flock ftime fork get_current_dir_name gettimeofday mlockall putenv random select strdup strerror strsignal strtol system unsetenv vsyslog])
jm_FUNC_MALLOC
jm_FUNC_REALLOC
AM_GNU_GETTEXT
dnl Support for SunOS
AC_CHECK_FUNC(socket, [], [
@ -93,79 +266,36 @@ AC_CHECK_FUNC(gethostbyname, [], [
AC_CHECK_LIB(nsl, gethostbyname)
])
AC_CHECK_FUNCS([freeaddrinfo gai_strerror getaddrinfo getnameinfo inet_aton])
AC_CACHE_SAVE
dnl These are defined in files in m4/
tinc_TUNTAP
use_gcrypt=0
use_openssl=0
case $host_os in
*linux*)
tinc_TUNTAP
;;
esac
AC_ARG_WITH(gcrypt,
[ --with-gcrypt Use GCRYPT for all cryptographic functions],
[
if test "x$withval" = "xyes" ; then
use_gcrypt=1
else
use_gcrypt=0
fi
],
[use_gcrypt=0])
AC_ARG_WITH(openssl,
[ --with-openssl Use OpenSSL for all cryptographic functions],
[
if test "x$withval" = "xyes" ; then
use_openssl=1
else
use_openssl=0
fi
],
[use_openssl=0])
if test \( $use_gcrypt -eq 0 -a $use_openssl -eq 0 \) \
-o \( $use_gcrypt -eq 1 -a $use_openssl -eq 1 \) ; then
cat << EOM
Error: You must select exactly one of GCRYPT or OpenSSL.
EOM
echo use_openssl=$use_openssl, use_gcrypt=$use_gcrypt
exit 1
fi
if test $use_gcrypt -eq 1 ; then
AC_MSG_RESULT([Selecting GCRYPT for crypto])
tinc_GCRYPT
AC_DEFINE(USE_GCRYPT)
fi
if test $use_openssl -eq 1 ; then
AC_MSG_RESULT([Selecting OpenSSL for crypto])
tinc_OPENSSL
AC_DEFINE(USE_OPENSSL)
fi
tinc_ZLIB
tinc_OPENSSL
tinc_ZLIB
tinc_LZO
dnl Check if support for jumbograms is requested
AC_ARG_ENABLE(jumbograms,
[ --enable-jumbograms enable support for jumbograms (packets up to 9000 bytes)],
[ AC_DEFINE(ENABLE_JUMBOGRAMS) ]
AC_HELP_STRING([--enable-jumbograms], [enable support for jumbograms (packets up to 9000 bytes)]),
[ AC_DEFINE(ENABLE_JUMBOGRAMS, 1, [Support for jumbograms (packets up to 9000 bytes)]) ]
)
dnl Check if checkpoint tracing has to be enabled
AC_ARG_ENABLE(tracing,
[ --enable-tracing enable checkpoint tracing (debugging only)],
[ AC_DEFINE(ENABLE_TRACING) ]
AC_HELP_STRING([--enable-tracing], [enable checkpoint tracing (debugging only)]),
[ AC_DEFINE(ENABLE_TRACING, 1, [Checkpoint tracing]) ]
)
AC_SUBST(INCLUDES)
AC_OUTPUT(Makefile
src/Makefile
src/pokey/Makefile
doc/Makefile
doc/es/Makefile
intl/Makefile
lib/Makefile
m4/Makefile
po/Makefile.in
)
AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile doc/tincd.8 doc/tinc.conf.5 doc/tincinclude.texi lib/Makefile po/Makefile.in m4/Makefile])
AC_OUTPUT

View file

@ -1,3 +1,3 @@
zarq:Ivo Timmermans <itimmermans@bigfoot.com>
guus:Guus Sliepen <guus@sliepen.warande.net>
zarq:Ivo Timmermans <ivo@o2w.nl>
guus:Guus Sliepen <guus@sliepen.eu.org>
wsl:Wessel Dankers <wsl@nl.linux.org>

View file

@ -1,7 +1,7 @@
This document describes how nodes in a VPN find and connect to eachother and
maintain a stable network.
Copyright 2001-2002 Guus Sliepen <guus@sliepen.warande.net>
Copyright 2001-2002 Guus Sliepen <guus@sliepen.eu.org>
Permission is granted to make and distribute verbatim copies of
this documentation provided the copyright notice and this
@ -12,343 +12,34 @@ maintain a stable network.
provided that the entire resulting derived work is distributed
under the terms of a permission notice identical to this one.
$Id: CONNECTIVITY,v 1.2 2002/04/12 08:25:01 guus Exp $
$Id: CONNECTIVITY,v 1.3 2003/08/24 20:38:18 guus Exp $
1. Problem
1. Synchronisation
==================
Each tinc daemon has zero or more connections to other tinc daemons. It will
try to keep its own information synchronised with the other tinc daemons. If
one of its peers sends information, the tinc daemon will check if it is new
information. If so, it will update its own information and forward the new
information to all the other peers.
This scheme will make sure that after a short amount of time all tinc daemons
share the same information. It will also almost completely prevent information
from looping, because "new" information that is already known is ignored and
not forwarded any further. However, since information can also be deleted
there's the possibility of a looping sequence of add/delete messages. This is
resolved by additionaly adding a unique identifier to each broadcasted message.
Messages are dropped if the same message with that identifier has already been
seen.
2. Routing
==========
We have a set of nodes (A, B, C, ...) that are part of the same VPN. They need
to connect to eachother and form a single graph that satisfies the tree
property.
Every node tells its peers to which other peers it is connected. This way
every node will eventually know every connection every node has on the VPN.
Each node will use graph algorithms to determine if other nodes are reachable or not and
what the best route is to other nodes.
There is the possibility that loops are formed, the offending connections must
be eliminated.
Suppose we start with two smaller graphs that want to form a single larger
graph. Both graphs consist of three nodes:
A-----B-----C
D-----E-----F
It is very well possible that A wants to connect to D, and F wants to connect
to C, both at the same time. The following loop will occur:
A-----B-----C
| ^
| |
v |
D-----E-----F
The situation described here is totally symmetric, there is no preference to
one connection over the other. The problem of resolving the loop, maintaining
consistency and stability is therefore not a trivial one.
What happens when A---D and C---F are connected to eachother? They exchange
lists of known hosts. A knows of B and C, and D knows of E and F. The protocol
defines ADD_HOST messages, from now on we will say that "node X sends and
ADD_HOST(Y) to Z".
There are two possible scenarios: either both A---D and C---F finish
authentication at the same time, or A---D finishes first, so that ADD_HOST
messages will reach C and F before they finish authentication.
1.1 A---D finishes first
------------------------
After A---D authentication finishes the following actions are taken:
1 A sends ADD_HOST(B) to D
A sends ADD_HOST(C) to D
D sends ADD_HOST(E) to A
D sends ADD_HOST(F) to A
2 A sends ADD_HOST(D) to B
A receives ADD_HOST(E) from D:
A sends ADD_HOST(E) to B
A receives ADD_HOST(F) from D:
A sends ADD_HOST(F) to B
D sends ADD_HOST(A) to E
D receives ADD_HOST(B) from A:
D sends ADD_HOST(B) to E
D receives ADD_HOST(C) from A:
D sends ADD_HOST(C) to E
3 B receives ADD_HOST(D) from A,
B sends ADD_HOST(D) to C
B receives ADD_HOST(E) from A:
B sends ADD_HOST(E) to C
B receives ADD_HOST(F) from A:
B sends ADD_HOST(F) to C
E receives ADD_HOST(A) from D:
E sends ADD_HOST(A) to F
E receives ADD_HOST(B) from D:
E sends ADD_HOST(B) to F
E receives ADD_HOST(C) from D:
E sends ADD_HOST(C) to F
4 C receives ADD_HOST(D) from B.
C receives ADD_HOST(E) from B.
C receives ADD_HOST(F) from B.
F receives ADD_HOST(A) from E.
F receives ADD_HOST(B) from E.
F receives ADD_HOST(C) from E.
Then C---F authentication finishes, the following actions are taken:
1 C notes that F is already known:
Connection is closed.
F notes that C is already known:
Connection is closed.
1.2 Both A---D and C---F finish at the same time.
-------------------------------------------------
1 A sends ADD_HOST(B) to D
A sends ADD_HOST(C) to D
D sends ADD_HOST(E) to A
D sends ADD_HOST(F) to A
C sends ADD_HOST(A) to F
C sends ADD_HOST(B) to F
F sends ADD_HOST(D) to C
F sends ADD_HOST(E) to C
2 A sends ADD_HOST(D) to B
A receives ADD_HOST(E) from D:
A sends ADD_HOST(E) to B
A receives ADD_HOST(F) from D:
A sends ADD_HOST(F) to B
D sends ADD_HOST(A) to E
D receives ADD_HOST(B) from A:
D sends ADD_HOST(B) to E
D receives ADD_HOST(C) from A:
D sends ADD_HOST(C) to E
C sends ADD_HOST(F) to B
C receives ADD_HOST(D) from F:
A sends ADD_HOST(D) to B
C receives ADD_HOST(E) from F:
A sends ADD_HOST(E) to B
F sends ADD_HOSTS(C) to E
F receives ADD_HOST(A) from C:
D sends ADD_HOST(A) to E
F receives ADD_HOST(B) from C:
D sends ADD_HOST(B) to E
3 B receives ADD_HOST(D) from A,
B sends ADD_HOST(D) to C
B receives ADD_HOST(E) from A:
B sends ADD_HOST(E) to C
B receives ADD_HOST(F) from A:
B sends ADD_HOST(F) to C
E receives ADD_HOST(A) from D:
E sends ADD_HOST(A) to F
E receives ADD_HOST(B) from D:
E sends ADD_HOST(B) to F
E receives ADD_HOST(C) from D:
E sends ADD_HOST(C) to F
B receives ADD_HOST(F) from C, and notes that is is already known:
<insert solution here>
B receives ADD_HOST(D) from C, and notes that is is already known:
<insert solution here>
B receives ADD_HOST(E) from C, and notes that is is already known:
<insert solution here>
E receives ADD_HOST(C) from F, and notes that is is already known:
<insert solution here>
E receives ADD_HOST(A) from F, and notes that is is already known:
<insert solution here>
E receives ADD_HOST(B) from F, and notes that is is already known:
<insert solution here>
4 A receives ADD_HOST(D) from B, and notes that it is already known:
<insert solution here>
A receives ADD_HOST(E) from B, and notes that it is already known:
<insert solution here>
A receives ADD_HOST(F) from B, and notes that it is already known:
<insert solution here>
F receives ADD_HOST(A) from E, and notes that it is already known:
<insert solution here>
F receives ADD_HOST(B) from E, and notes that it is already known:
<insert solution here>
F receives ADD_HOST(B) from E, and notes that it is already known:
<insert solution here>
...
1.2.1 Augmenting ADD_HOST
-------------------------
A solution would be to augment ADD_HOST with an extra parameter, the nexthop of
the added host:
3 B receives ADD_HOST(D,A) from A,
B sends ADD_HOST(D,A) to C
B receives ADD_HOST(E,D) from A:
B sends ADD_HOST(E,D) to C
B receives ADD_HOST(F,E) from A:
B sends ADD_HOST(F,E) to C
E receives ADD_HOST(A,D) from D:
E sends ADD_HOST(A,D) to F
E receives ADD_HOST(B,A) from D:
E sends ADD_HOST(B,A) to F
E receives ADD_HOST(C,B) from D:
E sends ADD_HOST(C,B) to F
B receives ADD_HOST(F,C) from C, and notes that F is already known:
<insert solution here>
B receives ADD_HOST(D,E) from C, and notes that D is already known:
<insert solution here>
B receives ADD_HOST(E,F) from C, and notes that E is already known:
<insert solution here>
E receives ADD_HOST(C,F) from F, and notes that C is already known:
<insert solution here>
E receives ADD_HOST(A,B) from F, and notes that A is already known:
<insert solution here>
E receives ADD_HOST(B,C) from F, and notes that B is already known:
<insert solution here>
So, B and E have to make a choice. Which ADD_HOST is going to win? Fortunately,
since the ADD_HOST messages are augmented, they have an extra piece of
information they can use to decide in a deterministic way which one is going to
win. For example, B got ADD_HOST(F,E) and ADD_HOST(F,C). Since "E" > "C", it
could let ADD_HOST(F,E) win.
B receives ADD_HOST(F,C) from C, and notes that F is already known:
since "C" < "E", B ignores ADD_HOST(F,E)
B sends ADD_HOST(F,C) to A
...
E receives ADD_HOST(C,F) from F, and notes that C is already known:
since "F" > "B", E removes the ADD_HOST(C,B) in favour of the new one
E sends ADD_HOST(C,F) to D
4 A receives ADD_HOST(F,E) from B, and notes that F is already known:
since "E" < "D", A ignores ADD_HOST(F,D).
...
D receives ADD_HOST(C,F) from E, and notes that C is already known:
since "F" > "B", D removes the ADD_HOST(C,B),
closes the connection with C, in favour of the new one.
Ok, time to forget this crap.
1.2.2
-----
The problem with the current ADD/DEL_HOST technique is that each host only
knows the general direction in which to send packets for the other hosts. It
really doesn't know much about the true topology of the network, only about
it's direct neighbours. With so little information each host cannot make a
certain decision which it knows for sure all the others will decide too.
Let's do something totally different. Instead of notifying every host of the
addition of a new host, which is represented by a vertex in a graph, lets send
out notifications of new connections, which are the edges in a graph. This is
rather cheap, since our graphs are (almost) spanning trees, there is
approximately one edge for each vertex in the graph, so we don't need to send
more messages. Furthermore, an edge is characterized by two vertices, so we
only send a fixed amount of extra information. The size/complexity of the
problem therefore does not increase much.
What is the advantage of notifying each vertex of new edges instead of new
vertices? Well, all the vertices now know exactly which connections are made
between each host. This was not known with the former schemes.
Ok back to our problem:
A-----B-----C
D-----E-----F
Edges are undirected, and are characterised by the vertices it connects, sorted
alphabetically, so the edges in the two graphs are:
(A,B), (B,C), (D,E) and (E,F).
So again we have that A wants to connect to D, and F wants to connect to C,
both at the same time. The following loop will occur:
A-----B-----C
| ^
| |
v |
D-----E-----F
Instead of sending ADD_HOSTs, lets assume the hosts send ADD_EDGEs. So, after
making the connections:
1 A sends ADD_EDGE(A,D) to B
A sends ADD_EDGE(A,B) to D
A sends ADD_EDGE(B,C) to D
D sends ADD_EDGE(A,D) to E
D sends ADD_EDGE(D,E) to A
D sends ADD_EDGE(E,F) to A
C sends ADD_EDGE(C,F) to B
C sends ADD_EDGE(A,B) to F
C sends ADD_EDGE(B,C) to F
F sends ADD_EDGE(C,F) to E
F sends ADD_EDGE(D,E) to C
F sends ADD_EDGE(E,F) to C
2 B receives ADD_EDGE(A,D) from A:
B sends ADD_EDGE(A,D) to C
B receives ADD_EDGE(D,E) from A:
B sends ADD_EDGE(D,E) to C
B receives ADD_EDGE(E,F) from A:
B sends ADD_EDGE(E,F) to C
...
B receives ADD_EDGE(C,F) from C, notes that both C and F are already known,
but that the edge (C,F) was not known, so a loop has been created:
<resolve loop here>
Ok, how to resolve the loop? Remeber, we want to do that in such a way that it
is consistent with the way all the other hosts resolve the loop. Here is the
things B does when it notices that a loop is going to be formed:
B performs a Breadth First Search from the first element of the list of all
known hosts sorted alfabetically, in this case A, and thereby finds a
spanning tree. (This might later be changed into a minimum spanning tree
alhorithm, but the key point here is that all hosts do this with exactly the
same starting parameters.) All known edges that are not in the spanning tree
are marked inactive.
An edge marked inactive does not mean anything, unless this edge is connected
to B itself. In that case, B will stop sending messages over that edge. B might
consider closing this edge, but this is not really needed. Keeping it means no
DEL_EDGE has to be sent for it, and if another edge is removed (which will
quite certainly split the graph if it's a spanning tree), this edge might be
reactivated, without the need of sending a new ADD_EDGE for it. On the other
hand, we mustn't keep to many inactive edges, because we want to keep the
number of known edges linear to the number of hosts (otherwise the size of the
problem will grow quadratically).
So, since B didn't deactivate one of it's own edges, it forwards the
ADD_EDGE(C,F) to A, which also does a BFS, and so on, until it reaches F. F of
course also does a BFS, notes that is is one of it's own edges. It deactivates
the edge (C,F), and consequently will not forward the ADD_EDGE(C,F) to C
anymore. In the mean time, C got messages from B which will make C do the same.
Ok, suppose a DEL_EDGE was sent, and it means an inactive edge has to be
reactivated. The vertices connected by that edge must exchange their entire
knowledge of edges again, because in the mean time other messages could have
been sent, which were not properly forwarded. Take this example:
X C-----D
| | |
| | |
v | |
A-----B- - -E
The edge (B,E) is inactive. X is trying to make a new connection with A. A
sends an ADD_EDGE(A,X) to B, which forwards it to C. At that time, the
connection between C and D goes down, so C sends a DEL_EDGE(C,D) to B, and D
sends a DEL_EDGE(C,D) to E. If we just allow (B,E) to be reactivated again
without anything else, then E and D will never have received the ADD_EDGE(A,X).
So, B and E have to exchange edges again, and propagate them to the hosts they
already know.
Because all nodes share the same information, using a deterministic algorithm
each node will calculate the same minimum spanning tree for the entire VPN.
The MST will be used to send broadcast VPN packets.

View file

@ -1,23 +0,0 @@
# Having a separate GNUmakefile lets me use features of GNU make
# to generate the man pages.
# This makefile is used only if you run GNU Make.
# It is necessary if you want to build targets usually of interest
# only to the maintainer.
have-Makefile := $(shell test -f Makefile && echo yes)
# If the user runs GNU make but has not yet run ./configure,
# give them a diagnostic.
ifeq ($(have-Makefile),yes)
include Makefile
include $(srcdir)/Makefile.maint
else
all:
@echo There seems to be no Makefile in this directory.
@echo "You must run ./configure before running \`make'."
@exit 1
endif

175
doc/HOWTO
View file

@ -1,175 +0,0 @@
==============
The TINC HOWTO
==============
Wessel Dankers
wsl@nl.linux.org
Introduction
------------
Tinc is a system to create a virtual ethernet network on top of an existing
infrastructure. This infrastructure can be anything from modem lines to
gigabit ethernet networks, as long as they talk IP. Once you install and
configure tinc, your host will get an extra IP address, just like it would
when you stick an extra ethernet card into it. Using this IP address, it can
communicate with all hosts in its virtual network using strong encryption.
If you install Tinc on a router (and pick your numbers correctly) you can
have the router forward all packets. This way you can---instead of
connecting hosts---connect entire sites together! Now you need only one
outgoing network connection for both internet and intranet.
Architecture
------------
When a few Tinc daemons are running they will try to seek contact with
eachother. A daemon is all the time connected to a few other daemons,
but if traffic is required with a daemon it doesn't know yet, it will
instantly contact it and exchange keys. These so-called meta-connections
are made over TCP, using encryption of course.
When actual traffic has to be sent, a daemon checks his connection list to
see if the addressee is known (and makes contact with it if neccessary).
All packets are then sent using UDP to the other host, just like in a real
network. If a packet gets lost, the connection layer of Linux will resend
the packet, just like it would over a normal network.
Once in a while the daemons will renegotiate keys so that even if a cracker
breaks one, it'll be of limited use.
Getting Tinc
------------
Before you fetch the latest tarball, you might want to check if there's a
package for your Linux distribution. One of the main authors is a Debian
Developer, so you can expect the Debian packages to be very up to date.
The official website for Tinc can be found at http://tinc.nl.linux.org/.
There you can find Debian packages, RPM's and of course... the tarball!
Since we run Doohickey Linux Pro 1.0, for which no package exists (or
indeed the distribution itself) we shall compile the package ourselves.
Building
--------
The Tinc source adheres to so many standards it makes you head spin.
Even the debug messages have been localized! Amazing. Tinc also comes
with a configuration script. If you like to see what is there to
configure run ./configure --help | more. If you don't have time for such
nonsense:
./configure --sysconfdir=/etc
This will see if your system is nice enough to run tinc on, and will
create some Makefiles and other stuff which will together build tinc.
make
make install
The first will do the actual build, the second copies all files into place.
The kernel
----------
Next you will have to configure the kernel to support the tap device.
It is important that you run a recent kernel, but anything after 2.2.16
will do. You have to enable both the netlink device AND the ethertap
device (in that order). Enable them as modules!
Compile, install =) You don't even have to reboot.
Picking your numbers
--------------------
The first thing we should do is pick network numbers. Tinc has a very
peculiar taste for network numbers, which is caused by the way it routes
traffic. However, it turns out to be really handy if you want to use
your tinc host as a router for a site.
The numbers have to be in a range that is not yet in use in your existing,
real network! In this example we will use numbers from the 192.168.0/16
range. This is standard CIDR notation for all IP addresses from 192.168.0.0
to 192.168.255.255. The /16 means that the first 16 bits form the network
part.
It is common practice for Tinc networks to use private (RFC 1918) addresses.
This is not necessary, but it would be a waste to use official addresses
for a private network!
In the example we will connect three machines: f00f, fdiv and hlt. We will
give each an address, but not just that, also a slice of our address space
to play with.
Host Real address Tinc network
---------------------------------------------------
f00f 126.202.37.20 192.168.1.1/24
fdiv 126.202.37.81 192.168.2.1/24
hlt 103.22.1.218 192.168.3.1/24
It is very important that none of the Tinc netmasks overlap! Note how the
192.168.0/16 network covers the entire address space of the three hosts.
We will refer to the 192.168.0/16 network as the `umbrella' from now on.
As you can see we can fit 256 hosts into this umbrella this way, which is
also the practical maximum for tinc. Let's name our VPN 'fubar'.
The configuration file
----------------------
Let's create a configuration file for f00f. We have to put it in
/etc/tinc/fubar because that's how we named our VPN.
MyOwnVPNIP = 192.168.1.1/24
VpnMask = 255.255.0.0
ConnectTo = 126.202.37.81
ConnectTo = 103.22.1.218
TapDevice = /dev/tap0
The first two lines tell Tinc about the numbers we have chosen above.
Using the ConnectTo lines, the daemon will seek contact with the rest of
the umbrella. It's possible to configure any number of ConnectTo lines,
you can even omit them so that it just sits and waits until someone else
contacts it. Until someone does, the poor daemon won't be able to send
any data because it doesn't know where everybody is.
The TapDevice is where the tinc daemon will interface with the kernel.
The passphrases
---------------
We will have to generate keys for ourselves, and get a key from everybody
we want to ConnectTo. All of these go into a directory named
/etc/tinc/fubar/passphrases. PROTECT THIS DIRECTORY!
mkdir -m 700 /etc/tinc/fubar/passphrases
To generate our own key:
genauth 1024 >/etc/tinc/fubar/passphrases/local
You should then proceed to give this key to anyone who wants to ConnectTo
you. DO THIS IN A SECURE MANNER! Anyone who has this number can do icky
things to the umbrella network! Encrypt it using PGP, GPG or another
program using asymmetric keys. Read it over the phone (without anyone
listening of course). Send it by snailmail. Write the key down and bring
it to your partners personally!
If you get any keys from your partners, store them under their network
number. For example, the key we get from fdiv's network administrator
will be stored in /etc/tinc/fubar/passphrases/192.168.2.0 (note the 0).
Running the daemon
------------------
If you use a package manager to install Tinc, the startup scripts use a file
called /etc/tinc/nets.boot to see which umbrella's exist. It has a line
per VPN, and lines starting with a # are ignored. Ours will contain:
# Example VPN from the HOWTO
fubar
In Debian, /etc/init.d/tinc start will start the daemons.
If you use Doohickey Linux just like we do, you'll have to edit the systems
startup scripts by hand. It should contain something along the lines of:
insmod ethertap -s --name=tap0 unit=0
ifconfig tap0 hw ether fe:fd:c0:a8:01:01
ifconfig tap0 192.168.1.1 netmask 255.255.0.0 broadcast 192.168.255.255 -arp
There are two things to note here! First, the MAC address of the ethertap
device is very important. It must start with fe:fd, and end in the
hexadecimal representation of the VPN IP number.
Second, the netmask of the tap device is set to that of the umbrella!
--
$Id: HOWTO,v 1.6 2002/04/12 08:25:01 guus Exp $

View file

@ -1,20 +1,12 @@
## Process this file with automake to get Makefile.in
SUBDIRS = es
info_TEXINFOS = tinc.texi
dyn_MANS =
man_aux = $(dyn_MANS:.8=.x)
man_MANS = tincd.8 tinc.conf.5
man_MANS = tincd.8 tinc.conf.5 $(dyn_MANS)
EXTRA_DIST = tincinclude.texi.in tincd.8.in tinc.conf.5.in sample-config.tar.gz
PERL = @PERL@
HELP2MAN = help2man
MAINTAINERCLEANFILES = $(dyn_MANS)
EXTRA_DIST = $(man_MANS) $(HELP2MAN) $(man_aux) \
Makefile.maint GNUmakefile Makefile.summ sample-config.tar.gz
CLEANFILES = *.html
# Use `ginstall' in the definition of man_MANS to avoid
# confusion with the `install' target. The install rule transforms `ginstall'
@ -23,3 +15,12 @@ transform = s/ginstall/install/; @program_transform_name@
# For additional rules usually of interest only to the maintainer,
# see GNUmakefile and Makefile.maint.
sample-config.tar.gz: sample-config
GZIP=$(GZIP_ENV) $(AMTAR) chozf sample-config.tar.gz sample-config
texi2html: tinc.texi
texi2html -split=chapter tinc.texi
%.html: $(man_MANS)
w3mman2html $< > $@

View file

@ -1,38 +0,0 @@
# This -*- Makefile -*- uses features of GNU make.
# It is included via GNUmakefile.
# The following one line summaries were extracted from the
# original man pages using this bit of sh code:
# for i in *.1; do echo "$i: "|tr -d '\012'; \
# grep -A1 SH.NAME $i|sed '/SH NAME/d;s/^[^ ][^ ]* .- //'; done
include Makefile.summ
HELP2MAN-run = $(PERL) -w -- $(srcdir)/$(HELP2MAN)
# Depend on configure.in to get version number changes.
$(dyn_MANS): $(top_srcdir)/configure.in
# Depend on the source file containing the --help text.
# Filter out irregular cases.
regular-men = $(filter-out $(irregular-men),$(dyn_MANS))
$(regular-men): %.8: $(top_srcdir)/src/%.c
executable = $(patsubst %/install,%/ginstall, ../src/$(basename $@))
$(dyn_MANS): %.8: %.x $(HELP2MAN)
@if test -f $(executable); then \
echo "Updating man page $@"; \
rm -f $@-t $@; \
$(HELP2MAN-run) \
--name="$($(basename $@)-summary)" \
--include=$(basename $@).x \
$(executable) > $@-t; \
chmod -w $@-t; \
mv $@-t $@; \
else \
echo "WARNING: The man page $@ cannot be updated yet."; \
echo " Retry once the corresponding executable is built."; \
fi
sample-config.tar.gz:
GZIP=$(GZIP_ENV) $(AMTAR) chozf sample-config.tar.gz sample-config

View file

@ -1,2 +0,0 @@
# -*- makefile -*-
tincd-summary = tinc VPN daemon

View file

@ -1,7 +1,7 @@
This is the network infrastructure documentation for tinc, a Virtual Private
Network daemon.
Copyright 2001-2002 Guus Sliepen <guus@sliepen.warande.net>
Copyright 2001-2002 Guus Sliepen <guus@sliepen.eu.org>
Permission is granted to make and distribute verbatim copies of
this documentation provided the copyright notice and this
@ -12,7 +12,7 @@ Network daemon.
provided that the entire resulting derived work is distributed
under the terms of a permission notice identical to this one.
$Id: NETWORKING,v 1.2 2002/04/12 08:25:01 guus Exp $
$Id: NETWORKING,v 1.3 2003/08/24 20:38:18 guus Exp $
1. Packet flow
==============

View file

@ -1,7 +1,7 @@
This is the protocol documentation for tinc, a Virtual Private Network daemon.
Copyright 2000-2002 Guus Sliepen <guus@sliepen.warande.net>,
2000-2002 Ivo Timmmermans <itimmermans@bigfoot.com>
Copyright 2000-2002 Guus Sliepen <guus@sliepen.eu.org>,
2000-2002 Ivo Timmmermans <ivo@o2w.nl>
Permission is granted to make and distribute verbatim copies of
this documentation provided the copyright notice and this
@ -12,7 +12,7 @@ This is the protocol documentation for tinc, a Virtual Private Network daemon.
provided that the entire resulting derived work is distributed
under the terms of a permission notice identical to this one.
$Id: PROTOCOL,v 1.2 2002/04/12 08:25:01 guus Exp $
$Id: PROTOCOL,v 1.3 2003/08/24 20:38:18 guus Exp $
1. Protocols used in tinc
@ -69,24 +69,62 @@ synchronised.
daemon message
--------------------------------------------------------------------------
origin ADD_EDGE node1 12.23.34.45 655 node2 21.32.43.54 655 222 0
| | | \___________________/ | +-> options
| | | | +----> weight
| | | +----------------> see below
| | +--> UDP port
| +----------> real address
+------------------> name of node on one side of the edge
origin ADD_EDGE node1 node2 21.32.43.54 655 222 0
| | | | | +-> options
| | | | +----> weight
| | | +--------> UDP port of node2
| | +----------------> real address of node2
| +-------------------------> name of destination node
+-------------------------------> name of source node
origin ADD_SUBNET node 192.168.1.0/24
| | +--> prefixlength
| +--------> IPv4 network address
| +--------> network address
+------------------> owner of this subnet
--------------------------------------------------------------------------
The ADD_EDGE messages are to inform other tinc daemons that a connection between
two nodes exist. The address of the destination node is available so that
VPN packets can be sent directly to that node.
The ADD_SUBNET messages inform other tinc daemons that certain subnets belong
to certain nodes. tinc will use it to determine to which node a VPN packet has
to be sent.
message
------------------------------------------------------------------
DEL_EDGE node1 node2
| +----> name of destination node
+----------> name of source node
DEL_SUBNET node 192.168.1.0/24
| | +--> prefixlength
| +--------> network address
+------------------> owner of this subnet
------------------------------------------------------------------
In case a connection between two daemons is closed or broken, DEL_EDGE messages
are sent to inform the other daemons of that fact. Each daemon will calculate a
new route to the the daemons, or mark them unreachable if there isn't any.
message
------------------------------------------------------------------
REQ_KEY origin destination
| +--> name of the tinc daemon it wants the key from
+----------> name of the daemon that wants the key
ANS_KEY origin destination 4ae0b0a82d6e0078 91 64 4
| | \______________/ | | +--> MAC length
| | | | +-----> digest algorithm
| | | +--------> cipher algorithm
| | +--> 128 bits key
| +--> name of the daemon that wants the key
+----------> name of the daemon that uses this key
KEY_CHANGED origin
+--> daemon that has changed it's packet key
--------------------------------------------------------------------------
The keys used to encrypt VPN packets are not sent out directly. This is
because it would generate a lot of traffic on VPNs with many daemons, and
chances are that not every tinc daemon will ever send a packet to every
@ -97,33 +135,17 @@ act as a proxy and forward its copy back to the requestor.
daemon message
--------------------------------------------------------------------------
daemon REQ_KEY origin destination
| +--> name of the tinc daemon it wants the key from
+----------> name of the daemon that wants the key
daemon ANS_KEY origin destination 4ae0b0a82d6e0078 91 64 4
| | \______________/ | | +--> MAC length
| | | | +-----> digest algorithm
| | | +--------> cipher algorithm
| | +--> 128 bits key
| +--> name of the daemon that wants the key
+----------> name of the daemon that uses this key
daemon KEY_CHANGED origin
+--> daemon that has changed it's packet key
origin PING
dest. PONG
--------------------------------------------------------------------------
There is also a mechanism to check if hosts are still alive. Since network
failures or a crash can cause a daemon to be killed without properly
shutting down the TCP connection, this is necessary to keep an up to date
connection list. Pings are sent at regular intervals, except when there
is also some other traffic.
daemon message
--------------------------------------------------------------------------
origin PING
dest. PONG
--------------------------------------------------------------------------
is also some other traffic. A little bit of salt (random data) is added
with each PING and PONG message, to make sure that long sequences of PING/PONG
messages without any other traffic won't result in known plaintext.
This basically covers everything that is sent over the meta connection by
tinc.

View file

@ -1,6 +1,6 @@
This is the security documentation for tinc, a Virtual Private Network daemon.
Copyright 2001-2002 Guus Sliepen <guus@sliepen.warande.net>,
Copyright 2001-2002 Guus Sliepen <guus@sliepen.eu.org>,
2001-2002 Wessel Dankers <wsl@nl.linux.org>
Permission is granted to make and distribute verbatim copies of
@ -12,7 +12,7 @@ This is the security documentation for tinc, a Virtual Private Network daemon.
provided that the entire resulting derived work is distributed
under the terms of a permission notice identical to this one.
$Id: SECURITY2,v 1.2 2002/04/12 08:25:01 guus Exp $
$Id: SECURITY2,v 1.3 2003/08/24 20:38:18 guus Exp $
Proposed new authentication scheme
----------------------------------
@ -66,17 +66,15 @@ server CHAL_REPLY 928ffe
After the correct challenge replies are recieved, both ends have proved
their identity. Further information is exchanged.
client ACK 655 12.23.34.45 123 0
| | | +-> options
| | +----> estimated weight
| +------------> IP address of server as seen by client
+--------------------> UDP port of client
client ACK 655 123 0
| | +-> options
| +----> estimated weight
+--------> listening port of client
server ACK 655 21.32.43.54 321 0
| | | +-> options
| | +----> estimated weight
| +------------> IP address of client as seen by server
+--------------------> UDP port of server
server ACK 655 321 0
| | +-> options
| +----> estimated weight
+--------> listening port of server
--------------------------------------------------------------------------
This new scheme has several improvements, both in efficiency and security.

View file

@ -1 +0,0 @@
Makefile Makefile.in

View file

@ -1,3 +0,0 @@
## Process this file with automake to get Makefile.in
# Nothing to see here, go away!

View file

@ -1,375 +0,0 @@
#!/usr/bin/perl -w
# Generate a short man page from --help and --version output.
# Copyright © 1997, 98 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
# the Free Software Foundation; either version 2, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Written by Brendan O'Dea <bod@compusol.com.au>
use 5.004;
use strict;
use Getopt::Long;
use POSIX qw(strftime setlocale LC_TIME);
my $this_program = 'help2man';
my $this_version = '1.006';
my $version_info = <<EOT;
$this_program $this_version
Copyright (C) 1997, 98 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.
Written by Brendan O'Dea <bod\@compusol.com.au>
EOT
my $help_info = <<EOT;
`$this_program' generates a man page out of `--help' and `--version' output.
Usage: $this_program [OPTION]... EXECUTABLE
--name=STRING use `STRING' as the description for the NAME paragraph
--include=FILE include material from `FILE'
--opt-include=FILE include material from `FILE' if it exists
--output=FILE send output to `FILE'
--no-info suppress pointer to Texinfo manual
--help print this help, then exit
--version print $this_program program version number, then exit
EXECUTABLE should accept `--help' and `version' options.
EOT
my ($include, $opt_name, $opt_include, $opt_output, $opt_no_info);
# Parse options.
GetOptions (
'name=s' => \$opt_name,
'include=s' => \$include,
'opt-include=s' => \$opt_include,
'output=s' => \$opt_output,
'no-info' => \$opt_no_info,
help => sub { print $help_info; exit },
version => sub { print $version_info; exit },
) or die $help_info;
die $help_info unless @ARGV == 1;
my %include = ();
my @include = (); # to retain order
# Process include file (if given). Format is:
#
# [section name]
# verbatim text
if ($include or $opt_include)
{
if (open INC, $include || $opt_include)
{
my $sect;
while (<INC>)
{
if (/^\[([^]]+)\]/)
{
$sect = uc $1;
$sect =~ s/^\s+//;
$sect =~ s/\s+$//;
next;
}
# Silently ignore anything before the first
# section--allows for comments and revision info.
next unless $sect;
push @include, $sect unless $include{$sect};
$include{$sect} ||= '';
$include{$sect} .= $_;
}
close INC;
die "$this_program: no valid information found in `$include'\n"
unless %include;
# Compress trailing blank lines.
for (keys %include)
{
$include{$_} =~ s/\n+$//;
$include{$_} .= "\n" unless /^NAME$/;
}
}
else
{
die "$this_program: can't open `$include' ($!)\n" if $include;
}
}
# Turn off localisation of executable's ouput.
@ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
# Turn off localisation of date (for strftime)
setlocale LC_TIME, 'C';
# Grab help and version paragraphs from executable
my @help = split /\n\n+/, `$ARGV[0] --help 2>/dev/null`
or die "$this_program: can't get `--help' info from $ARGV[0]\n";
my @version = split /\n\n+/, `$ARGV[0] --version 2>/dev/null`
or die "$this_program: can't get `--version' info from $ARGV[0]\n";
my $date = strftime "%B %Y", localtime;
my $program = $ARGV[0]; $program =~ s!.*/!!;
my $package = $program;
my $version;
if ($opt_output)
{
unlink $opt_output
or die "$this_program: can't unlink $opt_output ($!)\n"
if -e $opt_output;
open STDOUT, ">$opt_output"
or die "$this_program: can't create $opt_output ($!)\n";
}
# The first line of the --version information is assumed to be in one
# of the following formats:
#
# <version>
# <program> <version>
# GNU <program> <version>
# <program> (GNU <package>) <version>
# <program> - GNU <package> <version>
#
# and seperated from any copyright/author details by a blank line.
$_ = shift @version;
if (/^(\S+)\s+\((GNU\s+[^)]+)\)\s+(.*)/ or
/^(\S+)\s+-\s*(GNU\s+\S+)\s+(.*)/)
{
$program = $1;
$package = $2;
$version = $3;
}
elsif (/^(GNU\s+)?(\S+)\s+(.*)/)
{
$program = $2;
$package = $1 ? "$1$2" : $2;
$version = $3;
}
else
{
$version = $_;
}
$program =~ s!.*/!!;
# no info for `info' itself
$opt_no_info = 1 if $program eq 'info';
# --name overrides --include contents
$include{NAME} = "$program \\- $opt_name" if $opt_name;
# Default (useless) NAME paragraph
$include{NAME} ||= "$program \\- manual page for $program $version";
# Man pages traditionally have the page title in caps.
my $PROGRAM = uc $program;
# Header.
print <<EOT;
.\" DO NOT MODIFY THIS FILE! It was generated by $this_program $this_version.
.TH $PROGRAM 1 "$date" "$package $version" "FSF"
.SH NAME
$include{NAME}
EOT
my $accumulate = 1;
my @description = ();
sub convert_option;
# Output converted --help information.
for (@help)
{
chomp;
if (s/^Usage:\s+\S+\s+(.*)\n?//)
{
# Turn the usage clause into a synopsis.
my $synopsis = '';
do {
my $syn = $1;
$syn =~ s/(([][]|\.\.+)+)/\\fR$1\\fI/g;
$syn =~ s/^/\\fI/ unless $syn =~ s/^\\fR//;
$syn .= '\fR';
$syn =~ s/\\fI(\s*)\\fR/$1/g;
$synopsis .= ".br\n" unless $accumulate;
$synopsis .= ".B $program\n";
$synopsis .= "$syn\n";
$accumulate = 0;
} while s/^(?:Usage|\s*or):\s+\S+\s+(.*)\n?//;
# Include file overrides SYNOPSIS.
print ".SH SYNOPSIS\n", $include{SYNOPSIS} || $synopsis;
# Dump any accumulated description text.
print ".SH DESCRIPTION\n";
print @description;
# Add additional description text from include file.
if ($include{DESCRIPTION})
{
print ".PP\n" unless $include{DESCRIPTION} =~ /^\..P/;
print $include{DESCRIPTION};
}
next unless $_;
}
# Accumulate text if the synopsis has not been produced yet.
if ($accumulate)
{
push @description, ".PP\n" if @description;
push @description, "$_\n";
next;
}
# Catch start of options.
if (/^Options:/)
{
print qq(.SH OPTIONS\n);
s/Options://;
}
# Catch bug report text.
if (/^Report bugs |^Email bug reports to /)
{
print qq(.SH "REPORTING BUGS"\n$_\n);
next;
}
# Special case for tar 1.12: --label=NAME\nPATTERN.
s{(\n[ \t]*)(-V,[ \t]+--label=NAME.*)\n[ \t]+PATTERN[ \t]+}
{$1$2$1\\&...=PATTERN };
# Convert options.
s/(\s)(-[][\w=-]+|\\&\S+)/$1 . convert_option $2/ge;
# Option subsections have second line indented.
print qq(.SS "$1"\n) if s/^(\S.*)\n(\s)/$2/;
# Lines indented more than about 10 spaces may be assumed to be
# continuations of the previous line.
s/\n {10,}/ /g;
# Lines following dotted (*) or numbered points may also be
# continued if indented to the same level as the text following
# the point.
1 while s{((?:^|\n)(\s+)(?:[1-9][.)]|\*)(\s+)(?:[^\n]+))\n\2 \3(\S)}
{$1 $4}g;
# Indented paragraph.
if (/^\s/)
{
for (split /\n/)
{
s/^\s+//;
s/([^,])\s+/$1\n/;
print ".TP\n$_\n" if $_;
}
}
# Anything else.
else
{
print ".PP\n$_\n";
}
}
# Print any include items other than the ones we have already dealt
# with.
for (@include)
{
print qq(.SH "$_"\n$include{$_})
unless /^(NAME|SYNOPSIS|DESCRIPTION|SEE ALSO)$/;
}
# Refer to the real documentation.
if ($include{'SEE ALSO'} or !$opt_no_info)
{
print qq(.SH "SEE ALSO"\n);
print $include{'SEE ALSO'}, ".PP\n" if $include{'SEE ALSO'};
print <<EOT unless $opt_no_info;
The full documentation for
.B $program
is maintained as a Texinfo manual. If the
.B info
and
.B $program
programs are properly installed at your site, the command
.IP
.B info $program
.PP
should give you access to the complete manual.
EOT
}
# Output converted --version information.
for (@version)
{
chomp;
# Join hyphenated lines.
s/([A-Za-z])-\n */$1/g;
# Convert copyright symbol or (c) to nroff character.
s/Copyright\s+(?:\xa9|\([Cc]\))/Copyright \\(co/g;
# Insert appropriate headings for copyright and author.
if (/^Copyright\s\\/) { print ".SH COPYRIGHT\n" }
elsif (/^Written\s+by/) { print ".SH AUTHOR\n" }
else { print ".PP\n"; }
# Insert line breaks before additional copyright messages and the
# disclaimer.
s/(.)\n(Copyright\s|This is free software)/$1\n.br\n$2/g;
print "$_\n";
}
exit;
# Convert option dashes to \- to stop nroff from hyphenating 'em, and
# embolden. Option arguments get italicised.
sub convert_option
{
my $option = '\fB' . shift;
$option =~ s/-/\\-/g;
unless ($option =~ s/\[=(.*)\]$/\\fR[=\\fI$1\\fR]/)
{
$option =~ s/=(.)/\\fR=\\fI$1/;
$option =~ s/ (.)/ \\fI$1/;
$option .= '\fR';
}
$option;
}

View file

@ -2,14 +2,10 @@
# This file sets up the tap device.
# It gives you the freedom to do anything you want with it.
# Use the correct name for the tap device:
# For the Linux tun/tap device $INTERFACE is set to the right name,
# but for ethertap and FreeBSD this is tap0, tap1, tap2 etcetera,
# for Solaris and OpenBSD it is tun0, tun1, etcetera.
# Set hardware ethernet address (required!)
ifconfig $INTERFACE hw ether fe:fd:0:0:0:0
# The environment variable $INTERFACE is set to the right name
# on most platforms, but if it doesn't work try to set it manually.
# Give it the right ip and netmask. Remember, the subnet of the
# tap device must be larger than that of the individual Subnets
# as defined in the host configuration file!
ifconfig $INTERFACE 192.168.1.1 netmask 255.255.0.0 -arp
ifconfig $INTERFACE 192.168.1.1 netmask 255.255.0.0

View file

@ -15,11 +15,8 @@ Name = alpha
# May be used multiple times for redundance.
ConnectTo = beta
# The tap device tinc will use. Required.
# The tap device tinc will use.
# Default is /dev/tap0 for ethertap or FreeBSD,
# /dev/tun0 for Solaris and OpenBSD,
# and /dev/misc/net/tun for Linux tun/tap device.
Device = /dev/misc/net/tun
# The file in which the private key for this host is stored. Required.
PrivateKeyFile = /etc/tinc/example/rsa_key.priv
# and /dev/net/tun for Linux tun/tap device.
Device = /dev/net/tun

File diff suppressed because it is too large Load diff

View file

@ -1,196 +0,0 @@
.TH TINC 5 "May 2000" "tinc version 1.0" "FSF"
.SH NAME
tincd.conf \- tinc daemon configuration
.SH "DESCRIPTION"
The files in the \fI/etc/tinc\fR directory contain runtime and
security information for the \fBtinc\fR(8) daemon.
.PP
.SH "NETWORKS"
It is perfectly ok for you to run more than one tinc daemon. However,
in its default form, you will soon notice that you can't use two
different configuration files without the \fI-c\fR option.
We have thought of another way of dealing with this: network
names. This means that you call \fBtincd\fR with the \fI-n\fR argument,
which will assign a name to this daemon.
The effect of this is that the daemon will set its configuration
``root'' to \fI/etc/tinc/\fBnn\fI/\fR, where \fBnn\fR is your argument
to the \fI-n\fR option. You'll notice that it appears in syslog as
``tincd.\fBnn\fR''.
However, it is not strictly necessary that you call tinc with the -n
option. In this case, the network name would just be empty, and it
will be used as such. tinc now looks for files in \fI/etc/tinc/\fR,
instead of \fI/etc/tinc/\fBnn\fI/\fR; the configuration file should be
\fI/etc/tinc/tincd.conf\fR, and the passphrases are now expected to be
in \fI/etc/tinc/passphrases/\fR.
But it is highly recommended that you use this feature of tinc,
because it will be so much clearer whom your daemon talks to. Hence,
we will assume that you use it.
.PP
.SH "PASSPHRASES"
You should use the \fBgenauth\fR(8) program to generate passphrases.
with, it accepts a single parameter, which is the number of bits the
passphrase should be. Its output should be stored in
\fI/etc/tinc/\fBnn\fI/passphrases/local\fR \-\- where \fBnn\fR stands
for the network (See under \fBNETWORKS\fR) above.
Please see the manpage for \fBgenauth\fR to learn more about setting
up an authentication scheme.
.PP
.SH "CONFIGURATION"
The actual configuration of the daemon is done in the file
\fI/etc/tinc/\fBnn\fI/tincd.conf\fR.
This file consists of comments (lines started with a \fB#\fR) or
assignments in the form of
.PP
.Vb 1
\& \fIVariable \fB= \fIValue\fR.
.Ve
.PP
The variable names are case insensitive, and any spaces, tabs,
newlines and carriage returns are ignored. \fINote\fR: it is not
required that you put in the \fB=\fR sign, but doing so improves
readability. If you leave it out, remember to replace it with at least
one space character.
.PP
.SH "VARIABLES"
.PP
Here are all valid variables, listed in alphabetical order. The default
value, required or optional is given between parentheses.
.TP
\fBConnectPort\fR = <\fIport\fR> (655)
Connect to the upstream host (given with the \fBConnectTo\fR directive) on
port \fIport\fR. port may be given in decimal (default), octal (when preceded
by a single zero) or hexadecimal (prefixed with 0x). \fIport\fR is the port
number for both the UDP and the TCP (meta) connections.
.TP
\fBConnectTo\fR = <\fIIP address|hostname\fR> (optional)
Specifies which host to connect to on startup. Multiple \fBConnectTo\fR variables
may be specified, if connecting to the first one fails then tinc will try
the next one, and so on. It is possible to specify hostnames for dynamic IP
addresses (like those given on dyndns.org), tinc will not cache the resolved
IP address.
If you don't specify a host with \fBConnectTo\fR, regardless of whether a
value for \fBConnectPort\fR is given, tinc won't connect at all, and will
instead just listen for incoming connections.
.TP
\fBHostnames\fR = <\fIyes|no\fR> (no)
This option selects whether IP addresses (both real and on the VPN) should
be resolved. Since DNS lookups are blocking, it might affect tinc's
efficiency, even stopping the daemon for a few seconds everytime it does
a lookup if your DNS server is not responding.
This does not affect resolving hostnames to IP addresses from the configuration
file.
.TP
\fBIndirectData\fR = <\fIyes|no\fR> (no)
This option specifies whether other tinc daemons besides the one you
specified with \fBConnectTo\fR can make a direct connection to you. This is
especially useful if you are behind a firewall and it is impossible
to make a connection from the outside to your tinc daemon. Otherwise,
it is best to leave this option out or set it to no.
.TP
\fBInterface\fR = <\fIdevice\fR> (optional)
If you have more than one network interface in your computer, tinc will by
default listen on all of them for incoming connections. It is possible to
bind tinc to a single interface like eth0 or ppp0 with this variable.
.TP
\fBInterfaceIP\fR = <\fIlocal address\fR> (optional)
If your computer has more than one IP address on a single interface (for example
if you are running virtual hosts), tinc will by default listen on all of them for
incoming connections. It is possible to bind tinc to a single IP address with
this variable. It is still possible to listen on several interfaces at the same
time though, if they share the same IP address.
.TP
\fBKeyExpire\fR = <\fIseconds\fR> (3600)
This option controls the time the encryption keys used to encrypt the data
are valid. It is common practice to change keys at regular intervals to
make it even harder for crackers, even though it is thought to be nearly
impossible to crack a single key.
.TP
\fBListenPort\fR = <\fIport\fR> (655)
Listen on local port \fIport\fR. The computer connecting to this daemon should
use this number as the argument for his \fBConnectPort\fR.
.TP
\fBMyOwnVPNIP\fR = <\fIlocal address[/maskbits]\fR> (required)
The \fIlocal address\fR is the number that the daemon will propagate to
other daemons on the network when it is identifying itself. Hence this
will be the file name of the passphrase file that the other end expects
to find the passphrase in.
The local address is the IP address of the tap device, not the real IP
address of the host running tincd. Due to changes in recent kernels, it
is also necessary that you make the ethernet (also known as MAC) address
equal to the IP address (see the example).
\fImaskbits\fR is the number of bits set to 1 in the netmask part.
.TP
\fBMyVirtualIP\fR = <\fIlocal address[/maskbits]>
This is an alias for \fBMyOwnVPNIP\fR.
.TP
\fBPassphrases\fR = <\fIdirectory\fR> (/etc/tinc/NETNAME/passphrases)
The directory where tinc will look for passphrases when someone tries to
connect. Please see the manpage for genauth(8) for more information
about passphrases as used by tinc.
.TP
\fBPingTimeout\fR = <\fIseconds\fR> (5)
The number of seconds of inactivity that tinc will wait before sending a
probe to the other end. If that other end doesn't answer within that
same amount of seconds, the connection is terminated, and the others
will be notified of this.
.TP
\fBTapDevice\fR = <\fIdevice\fR> (/dev/tap0)
The ethertap device to use. Note that you can only use one device per
daemon. The info pages of the tinc package contain more information
about configuring an ethertap device for Linux.
.TP
\fBTCPonly\fR = <\fIyes|no\fR> (no, experimental)
If this variable is set to yes, then the packets are tunnelled over a TCP
connection instead of a UDP connection. This is especially useful for those
who want to run a tinc daemon from behind a masquerading firewall, or if
UDP packet routing is disabled somehow. This is experimental code,
try this at your own risk.
.TP
\fBVpnMask\fR = <\fImask\fR> (optional)
The mask that defines the scope of the entire VPN. This option is not used
by the tinc daemon itself, but can be used by startup scripts to configure
the ethertap devices correctly.
.PP
.SH "FILES"
.TP
\fI/etc/tinc/\fR
The top directory for configuration files.
.TP
\fI/etc/tinc/\fBnn\fI/tincd.conf\fR
The default name of the configuration file for net
\fBnn\fR.
.TP
\fI/etc/tinc/\fBnn\fI/passphrases/\fR
Passphrases are kept in this directory. (See the section
\fBPASSPHRASES\fR above).
.PP
.SH "SEE ALSO"
\fBtincd\fR(8), \fBgenauth\fR(8)
.TP
\fBhttp://tinc.nl.linux.org/\fR
.PP
The full documentation for
.B tinc
is maintained as a Texinfo manual. If the
.B info
and
.B tinc
programs are properly installed at your site, the command
.IP
.B info tinc
.PP
should give you access to the complete manual.
.PP
tinc comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions;
see the file COPYING for details.

399
doc/tinc.conf.5.in Normal file
View file

@ -0,0 +1,399 @@
.Dd 2002-04-09
.Dt TINC.CONF 5
.\" Manual page created by:
.\" Ivo Timmermans <ivo@o2w.nl>
.\" Guus Sliepen <guus@sliepen.eu.org>
.Sh NAME
.Nm tinc.conf
.Nd tinc daemon configuration
.Sh DESCRIPTION
The files in the
.Pa @sysconfdir@/tinc/
directory contain runtime and security information for the tinc daemon.
.Sh NETWORKS
It is perfectly ok for you to run more than one tinc daemon.
However, in its default form,
you will soon notice that you can't use two different configuration files without the
.Fl c
option.
.Pp
We have thought of another way of dealing with this: network names.
This means that you call
.Nm
with the
.Fl n
option, which will assign a name to this daemon.
.Pp
The effect of this is that the daemon will set its configuration root to
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa / ,
where
.Ar NETNAME
is your argument to the
.Fl n
option.
You'll notice that messages appear in syslog as coming from
.Nm tincd. Ns Ar NETNAME .
.Pp
However, it is not strictly necessary that you call tinc with the
.Fl n
option.
In this case, the network name would just be empty,
and it will be used as such.
.Nm tinc
now looks for files in
.Pa @sysconfdir@/tinc/ ,
instead of
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa / ;
the configuration file should be
.Pa @sysconfdir@/tinc/tinc.conf ,
and the host configuration files are now expected to be in
.Pa @sysconfdir@/tinc/hosts/ .
.Pp
But it is highly recommended that you use this feature of
.Nm tinc ,
because it will be so much clearer whom your daemon talks to.
Hence, we will assume that you use it.
.Sh NAMES
Each tinc daemon should 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
file.
.Pp
To make things easy,
choose something that will give unique and easy to remember names to your tinc daemon(s).
You could try things like hostnames, owner surnames or location names.
.Sh PUBLIC/PRIVATE KEYS
You should use
.Ic tincd -K
to generate public/private keypairs.
It will generate two keys.
The private key should be stored in a separate file
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /rsa_key.priv
\-\- where
.Ar NETNAME
stands for the network (see
.Sx NETWORKS )
above.
The public key should be stored in the host configuration file
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Va NAME
\-\- where
.Va NAME
stands for the name of the local tinc daemon (see
.Sx NAMES ) .
.Sh SERVER CONFIGURATION
The server configuration of the daemon is done in the file
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf .
This file consists of comments (lines started with a
.Li # )
or assignments in the form of:
.Pp
.Va Variable Li = Ar Value .
.Pp
The variable names are case insensitive, and any spaces, tabs,
newlines and carriage returns are ignored.
Note: it is not required that you put in the
.Li =
sign, but doing so improves readability.
If you leave it out, remember to replace it with at least one space character.
.Pp
Here are all valid variables, listed in alphabetical order.
The default value is given between parentheses.
.Bl -tag -width indent
.It Va AddressFamily Li = ipv4 | ipv6 | any Pq any
This option affects the address family of listening and outgoing sockets.
If
.Qq any
is selected, then depending on the operating system both IPv4 and IPv6 or just
IPv6 listening sockets will be created.
.It Va BindToAddress Li = Ar address Bq experimental
If your computer has more than one IPv4 or IPv6 address,
.Nm tinc
will by default listen on all of them for incoming connections.
It is possible to bind only to a single address with this variable.
.Pp
This option may not work on all platforms.
.It Va BindToInterface Li = Ar interface Bq experimental
If your computer has more than one network interface,
.Nm tinc
will by default listen on all of them for incoming connections.
It is possible to bind only to a single interface with this variable.
.Pp
This option may not work on all platforms.
.It Va ConnectTo Li = Ar name
Specifies which other tinc daemon to connect to on startup.
Multiple
.Va ConnectTo
variables may be specified,
in which case outgoing connections to each specified tinc daemon are made.
The names should be known to this tinc daemon
(i.e., there should be a host configuration file for the name on the
.Va ConnectTo
line).
.Pp
If you don't specify a host with
.Va ConnectTo ,
.Nm tinc
won't try to connect to other daemons at all,
and will instead just listen for incoming connections.
.It Va Device Li = Ar device Po Pa /dev/tap0 , Pa /dev/net/tun No or other depending on platform Pc
The virtual network device to use.
.Nm tinc
will automatically detect what kind of device it is.
Note that you can only use one device per daemon.
Under Windows, use
.Va Interface
instead of
.Va Device .
The info pages of the tinc package contain more information
about configuring the virtual network device.
.It Va Hostnames Li = yes | no Pq no
This option selects whether IP addresses (both real and on the VPN) should
be resolved. Since DNS lookups are blocking, it might affect tinc's
efficiency, even stopping the daemon for a few seconds every time it does
a lookup if your DNS server is not responding.
.Pp
This does not affect resolving hostnames to IP addresses from the
host configuration files.
.It Va Interface Li = Ar interface
Defines the name of the interface corresponding to the virtual network device.
Depending on the operating system and the type of device this may or may not actually set the name of the interface.
Under Windows, this variable is used to select which network interface will be used.
If you specified a
.Va Device ,
this variable is almost always already correctly set.
.It Va KeyExpire Li = Ar seconds Pq 3600
This option controls the period the encryption keys used to encrypt the data are valid.
It is common practice to change keys at regular intervals to make it even harder for crackers,
even though it is thought to be nearly impossible to crack a single key.
.It Va MACExpire Li = Ar seconds Pq 600
This option controls the amount of time MAC addresses are kept before they are removed.
This only has effect when
.Va Mode
is set to
.Qq switch .
.It Va MaxTimeout Li = Ar seconds Pq 900
This is the maximum delay before trying to reconnect to other tinc daemons.
.It Va Mode Li = router | switch | hub Pq router
This option selects the way packets are routed to other daemons.
.Bl -tag -width indent
.It router
In this mode
.Va Subnet
variables in the host configuration files will be used to form a routing table.
Only unicast packets of routable protocols (IPv4 and IPv6) are supported in this mode.
.Pp
This is the default mode, and unless you really know you need another mode, don't change it.
.It switch
In this mode the MAC addresses of the packets on the VPN will be used to
dynamically create a routing table just like an Ethernet switch does.
Unicast, multicast and broadcast packets of every protocol that runs over Ethernet are supported in this mode
at the cost of frequent broadcast ARP requests and routing table updates.
.Pp
This mode is primarily useful if you want to bridge Ethernet segments.
.It hub
This mode is almost the same as the switch mode, but instead
every packet will be broadcast to the other daemons
while no routing table is managed.
.El
.It Va Name Li = Ar name Bq required
This is the name which identifies this tinc daemon.
It must be unique for the virtual private network this daemon will connect to.
.It Va PingTimeout Li = Ar seconds Pq 60
The number of seconds of inactivity that
.Nm tinc
will wait before sending a probe to the other end.
If that other end doesn't answer within that same amount of time,
the connection is terminated,
and the others will be notified of this.
.It Va PriorityInheritance Li = yes | no Po no Pc Bq experimental
When this option is enabled the value of the TOS field of tunneled IPv4 packets
will be inherited by the UDP packets that are sent out.
.It Va PrivateKey Li = Ar key Bq obsolete
The private RSA key of this tinc daemon.
It will allow this tinc daemon to authenticate itself to other daemons.
.It Va PrivateKeyFile Li = Ar filename Po Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /rsa_key.priv Pc
The file in which the private RSA key of this tinc daemon resides.
Note that there must be exactly one of
.Va PrivateKey
or
.Va PrivateKeyFile
specified in the configuration file.
.El
.Sh HOST CONFIGURATION FILES
The host configuration files contain all information needed
to establish a connection to those hosts.
A host configuration file is also required for the local tinc daemon,
it will use it to read in it's listen port, public key and subnets.
.Pp
The idea is that these files are portable.
You can safely mail your own host configuration file to someone else.
That other person can then copy it to his own hosts directory,
and now his tinc daemon will be able to connect to your tinc daemon.
Since host configuration files only contain public keys,
no secrets are revealed by sending out this information.
.Bl -tag -width indent
.It Va Address Li = Ar address Bq recommended
The IP address or hostname of this tinc daemon on the real network.
This wil only be used when trying to make an outgoing connection to this tinc daemon.
Multiple
.Va Address
variables can be specified, in which case each address will be tried until a working
connection has been established.
.It Va Cipher Li = Ar cipher Pq blowfish
The symmetric cipher algorithm used to encrypt UDP packets.
Any cipher supported by OpenSSL is recognised.
Furthermore, specifying
.Qq none
will turn off packet encryption.
.It Va Compression Li = Ar level Pq 0
This option sets the level of compression used for UDP packets.
Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib),
10 (fast lzo) and 11 (best lzo).
.It Va Digest Li = Ar digest Pq sha1
The digest algorithm used to authenticate UDP packets.
Any digest supported by OpenSSL is recognised.
Furthermore, specifying
.Qq none
will turn off packet authentication.
.It Va IndirectData Li = yes | no Pq no
This option specifies whether other tinc daemons besides the one you specified with
.Va ConnectTo
can make a direct connection to you.
This is especially useful if you are behind a firewall
and it is impossible to make a connection from the outside to your tinc daemon.
Otherwise, it is best to leave this option out or set it to no.
.It Va MACLength Li = Ar length Pq 4
The length of the message authentication code used to authenticate UDP packets.
Can be anything from
.Qq 0
up to the length of the digest produced by the digest algorithm.
.It Va Port Li = Ar port Pq 655
The port number on which this tinc daemon is listening for incoming connections.
.It Va PublicKey Li = Ar key Bq obsolete
The public RSA key of this tinc daemon.
It will be used to cryptographically verify it's identity and to set up a secure connection.
.It Va PublicKeyFile Li = Ar filename Bq obsolete
The file in which the public RSA key of this tinc daemon resides.
.Pp
From version 1.0pre4 on
.Nm tinc
will store the public key directly into the host configuration file in PEM format,
the above two options then are not necessary.
Either the PEM format is used, or exactly one of the above two options must be specified
in each host configuration file,
if you want to be able to establish a connection with that host.
.It Va Subnet Li = Ar address Ns Op Li / Ns Ar prefixlength
The subnet which this tinc daemon will serve.
.Nm tinc
tries to look up which other daemon it should send a packet to by searching the appropriate subnet.
If the packet matches a subnet,
it will be sent to the daemon who has this subnet in his host configuration file.
Multiple
.Va Subnet
variables can be specified.
.Pp
Subnets can either be single MAC, IPv4 or IPv6 addresses,
in which case a subnet consisting of only that single address is assumed,
or they can be a IPv4 or IPv6 network address with a prefixlength.
Shorthand notations are not supported.
For example, IPv4 subnets must be in a form like 192.168.1.0/24,
where 192.168.1.0 is the network address and 24 is the number of bits set in the netmask.
Note that subnets like 192.168.1.1/24 are invalid!
Read a networking HOWTO/FAQ/guide if you don't understand this.
IPv6 subnets are notated like fec0:0:0:1:0:0:0:0/64.
MAC addresses are notated like 0:1a:2b:3c:4d:5e.
.It Va TCPOnly Li = yes | no Pq no
If this variable is set to yes,
then the packets are tunnelled over the TCP connection instead of a UDP connection.
This is especially useful for those who want to run a tinc daemon
from behind a masquerading firewall,
or if UDP packet routing is disabled somehow.
Setting this options also implicitly sets IndirectData.
.El
.Sh SCRIPTS
Apart from reading the server and host configuration files,
tinc can also run scripts at certain moments.
On Windows (not Cygwin), the scripts should have the extension
.Pa .bat .
.Bl -tag -width indent
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /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.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-down
This script is started right before the tinc daemon quits.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Ar HOST Ns Pa -up
This script is started when the tinc daemon with name
.Ar HOST
becomes reachable.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Ar HOST Ns Pa -down
This script is started when the tinc daemon with name
.Ar HOST
becomes unreachable.
.El
.Pp
The scripts are started without command line arguments, but can make use of certain environment variables.
Under UNIX like operating systems the names of environment variables must be preceded by a
.Li $
in scripts.
Under Windows, in
.Pa .bat
files, they have to be put between
.Li %
signs.
.Bl -tag -width indent
.It Ev NETNAME
If a netname was specified, this environment variable contains it.
.It Ev NAME
Contains the name of this tinc daemon.
.It Ev DEVICE
Contains the name of the virtual network device that tinc uses.
.It Ev INTERFACE
Contains the name of the virtual network interface that tinc uses.
This should be used for commands like
.Pa ifconfig .
.It Ev NODE
When a host becomes (un)reachable, this is set to its name.
.It Ev REMOTEADDRESS
When a host becomes (un)reachable, this is set to its real address.
.It Ev REMOTEPORT
When a host becomes (un)reachable, this is set to the port number it uses for communication with other tinc daemons.
.El
.Sh FILES
The most important files are:
.Bl -tag -width indent
.It Pa @sysconfdir@/tinc/
The top directory for configuration files.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf
The default name of the server configuration file for net
.Ar NETNAME .
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/
Host configuration files are kept in this directory.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up
If an executable file with this name exists,
it will be executed right after the tinc daemon has connected to the virtual network device.
It can be used to set up the corresponding network interface.
.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-down
If an executable file with this name exists,
it will be executed right before the tinc daemon is going to close
its connection to the virtual network device.
.El
.Sh SEE ALSO
.Xr tincd 8 ,
.Pa http://tinc.nl.linux.org/ ,
.Pa http://www.linuxdoc.org/LDP/nag2/ .
.Pp
The full documentation for
.Nm tinc
is maintained as a Texinfo manual.
If the info and tinc programs are properly installed at your site, the command
.Ic info tinc
should give you access to the complete manual.
.Pp
.Nm tinc
comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it under certain conditions;
see the file COPYING for details.

File diff suppressed because it is too large Load diff

View file

@ -1,22 +1,25 @@
.Dd 2002-03-25
.Dt TINCD 8
.\" Manual page created by:
.\" Ivo Timmermans <itimmermans@bigfoot.com>
.\" Guus Sliepen <guus@sliepen.warande.net>
.\" Ivo Timmermans <ivo@o2w.nl>
.\" Guus Sliepen <guus@sliepen.eu.org>
.Sh NAME
.Nm tincd
.Nd tinc VPN daemon
.Sh SYNOPSIS
.Nm
.Op Fl cdDkKn
.Op Fl -bypass-security
.Op Fl cdDkKnL
.Op Fl -config Ns = Ns Ar DIR
.Op Fl -debug Ns = Ns Ar LEVEL
.Op Fl -generate-keys Ns Op = Ns Ar BITS
.Op Fl -help
.Op Fl -kill Ns = Ns Ar SIGNAL
.Op Fl -net Ns = Ns Ar NETNAME
.Op Fl -no-detach
.Op Fl -debug Ns Op = Ns Ar LEVEL
.Op Fl -kill Ns Op = Ns Ar SIGNAL
.Op Fl -net Ns = Ns Ar NETNAME
.Op Fl -generate-keys Ns Op = Ns Ar BITS
.Op Fl -mlock
.Op Fl -logfile Ns Op = Ns Ar FILE
.Op Fl -pidfile Ns = Ns Ar FILE
.Op Fl -bypass-security
.Op Fl -help
.Op Fl -version
.Sh DESCRIPTION
This is the daemon of tinc, a secure virtual private network (VPN) project.
@ -31,37 +34,59 @@ If that succeeds,
it will detach from the controlling terminal and continue in the background,
accepting and setting up connections to other tinc daemons
that are part of the virtual private network.
Under Windows (not Cygwin) tinc will install itself as a service,
which will be restarted automatically after reboots.
.Sh OPTIONS
.Bl -tag -width indent
.It Fl -bypass-security
Disables encryption and authentication.
Only useful for debugging.
.It Fl c, -config Ns = Ns Ar DIR
Read configuration options from
.Ar DIR .
Read configuration files from
.Ar DIR
instead of
.Pa @sysconfdir@/tinc/ .
.It Fl D, -no-detach
Don't fork and detach.
This will also disable the automatic restart mechanism for fatal errors.
If not mentioned otherwise, this will show log messages on the standard error output.
.It Fl d, -debug Ns Op = Ns Ar LEVEL
Increase debug level or set it to
.Ar LEVEL
(see below).
.It Fl K, -generate-keys Ns Op = Ns Ar BITS
Generate public/private RSA keypair and exit.
If
.Ar BITS
is omitted, the default length will be 1024 bits.
.It Fl -help
Display short list of options.
.It Fl k, -kill Ns Op = Ns Ar SIGNAL
Attempt to kill a running
.Nm
(optionally with the specified
.Ar SIGNAL
instead of SIGTERM) and exit.
Under Windows (not Cygwin) the optional argument is ignored,
the service will always be stopped and removed.
.It Fl n, -net Ns = Ns Ar NETNAME
Connect to net
.Ar NETNAME .
.It Fl D, -no-detach
Don't fork and detach.
This will also disable the automatic restart mechanism for fatal errors.
.It Fl K, -generate-keys Ns Op = Ns Ar BITS
Generate public/private RSA keypair and exit.
If
.Ar BITS
is omitted, the default length will be 1024 bits.
.It Fl L, -mlock
Lock tinc into main memory.
This will prevent sensitive data like shared private keys to be written to the system swap files/partitions.
.It Fl -logfile Ns Op = Ns Ar FILE
Write log entries to a file instead of to the system logging facility.
If
.Ar FILE
is omitted, the default is
.Pa @localstatedir@/log/tinc. Ns Ar NETNAME Ns Pa .log.
.It Fl -pidfile Ns = Ns Ar FILE
Write PID to
.Ar FILE
instead of
.Pa @localstatedir@/run/tinc. Ns Ar NETNAME Ns Pa .pid.
Under Windows this option will be ignored.
.It Fl -bypass-security
Disables encryption and authentication of the meta protocol.
Only useful for debugging.
.It Fl -help
Display short list of options.
.It Fl -version
Output version information and exit.
.El
@ -80,7 +105,11 @@ and if
didn't succeed to connect to an uplink the first time after it started,
it defaults to the maximum time of 15 minutes.
.It HUP
Closes all connections, rereads the configuration file and restarts the daemon.
Partially rereads configuration files.
Connections to hosts whose host config file are removed are closed.
New outgoing connections specified in
.Pa tinc.conf
will be made.
.It INT
Temporarily increases debug level to 5.
Send this signal again to revert to the original level.
@ -105,7 +134,7 @@ It will also any serious error.
.It 1
This will log all connections that are made with other tinc daemons.
.It 2
This will log status and error messages from other tinc daemons.
This will log status and error messages from scripts and other tinc daemons.
.It 3
This will log all requests that are exchanged with other tinc daemons. These include
authentication, key exchange and connection list updates.
@ -116,29 +145,11 @@ This will log all network traffic over the virtual private network.
.El
.Sh FILES
.Bl -tag -width indent
.It Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf
The configuration file for
.Nm .
.It Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /tinc-up
Script which is executed as soon as the virtual network device has been allocated.
Purpose is to further configure that device.
.It Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /tinc-down
Script which is executed when
.Nm
exits.
Purpose is to cleanly shut down the virtual network device before it will be deallocated.
.It Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /hosts/*
The directory containing the host configuration files
used to authenticate other tinc daemons.
.It Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Ar NAME Ns Pa -up
Script which is executed as soon as host
.Ar NAME
becomes reachable.
.It Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Ar NAME Ns Pa -down
Script which is executed as soon as host
.Ar NAME
becomes unreachable.
.It Pa /var/run/tinc. Ns Ar NETNAME Ns Pa .pid
.It Pa @sysconfdir@/tinc/
Directory containing the configuration files tinc uses.
For more information, see
.Xr tinc.conf 5 .
.It Pa @localstatedir@/run/tinc. Ns Ar NETNAME Ns Pa .pid
The PID of the currently running
.Nm
is stored in this file.
@ -168,7 +179,7 @@ tinc comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it under certain conditions;
see the file COPYING for details.
.Sh AUTHORS
.An "Ivo Timmermans" Aq itimmermans@bigfoot.com
.An "Guus Sliepen" Aq guus@sliepen.warande.net
.An "Ivo Timmermans" Aq ivo@o2w.nl
.An "Guus Sliepen" Aq guus@sliepen.eu.org
.Pp
And thanks to many others for their contributions to tinc!

4
doc/tincinclude.texi.in Normal file
View file

@ -0,0 +1,4 @@
@set VERSION @VERSION@
@set PACKAGE @PACKAGE@
@set sysconfdir @sysconfdir@
@set localstatedir @localstatedir@

View file

@ -1,17 +1,15 @@
## Process this file with automake to produce Makefile.in
# $Id: Makefile.am,v 1.9 2002/05/02 13:11:55 zarq Exp $
# $Id: Makefile.am,v 1.10 2003/08/24 20:38:20 guus Exp $
noinst_LIBRARIES = libtinc.a
noinst_LIBRARIES = libvpn.a
INCLUDES = @INCLUDES@ -I. -I$(top_builddir) -I$(top_srcdir)/intl
INCLUDES = @INCLUDES@ -I. -I$(top_builddir)
libtinc_a_SOURCES = xmalloc.c pidfile.c utils.c getopt.c getopt1.c \
list.c avl_tree.c hooks.c dropin.c edge.c conf.c netutl.c logging.c connection.c subnet.c node.c graph.c event.c
libvpn_a_SOURCES = xmalloc.c pidfile.c utils.c getopt.c getopt1.c list.c avl_tree.c dropin.c fake-getaddrinfo.c fake-getnameinfo.c
libtinc_a_LIBADD = @LIBOBJS@ @ALLOCA@
libtinc_a_DEPENDENCIES = $(libvpn_a_LIBADD)
libvpn_a_LIBADD = @LIBOBJS@ @ALLOCA@
libvpn_a_DEPENDENCIES = $(libvpn_a_LIBADD)
noinst_HEADERS = xalloc.h pidfile.h utils.h getopt.h list.h avl_tree.h \
hooks.h dropin.h edge.h net.h conf.h netutl.h logging.h connection.h subnet.h node.h graph.h event.h
noinst_HEADERS = xalloc.h pidfile.h utils.h getopt.h list.h avl_tree.h dropin.h fake-getaddrinfo.h fake-getnameinfo.h fake-gai-errnos.h gettext.h ipv6.h ipv4.h ethernet.h
EXTRA_DIST = README
EXTRA_DIST =

View file

@ -1 +0,0 @@
The files in this directory were merely copied from fileutils 4.0.

File diff suppressed because it is too large Load diff

View file

@ -1,9 +1,9 @@
/*
avl_tree.h -- header file for avl_tree.c
Copyright (C) 1998 Michael H. Buselli
2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>,
2000,2001 Guus Sliepen <guus@sliepen.warande.net>
2000,2001 Wessel Dankers <wsl@nl.linux.org>
2000-2003 Ivo Timmermans <ivo@o2w.nl>,
2000-2003 Guus Sliepen <guus@sliepen.eu.org>
2000-2003 Wessel Dankers <wsl@nl.linux.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -27,9 +27,9 @@
Cleaned up and incorporated some of the ideas from the red-black tree
library for inclusion into tinc (http://tinc.nl.linux.org/) by
Guus Sliepen <guus@sliepen.warande.net>.
Guus Sliepen <guus@sliepen.eu.org>.
$Id: avl_tree.h,v 1.2 2002/04/09 15:26:00 zarq Exp $
$Id: avl_tree.h,v 1.3 2003/08/24 20:38:20 guus Exp $
*/
@ -37,54 +37,54 @@
#define __AVL_TREE_H__
#ifndef AVL_DEPTH
#ifndef AVL_COUNT
#define AVL_DEPTH
#endif
#ifndef AVL_COUNT
#define AVL_DEPTH
#endif
#endif
typedef struct avl_node_t {
/* Linked list part */
/* Linked list part */
struct avl_node_t *next;
struct avl_node_t *prev;
struct avl_node_t *next;
struct avl_node_t *prev;
/* Tree part */
/* Tree part */
struct avl_node_t *parent;
struct avl_node_t *left;
struct avl_node_t *right;
struct avl_node_t *parent;
struct avl_node_t *left;
struct avl_node_t *right;
#ifdef AVL_COUNT
unsigned int count;
unsigned int count;
#endif
#ifdef AVL_DEPTH
unsigned char depth;
unsigned char depth;
#endif
/* Payload */
/* Payload */
void *data;
void *data;
} avl_node_t;
typedef int (*avl_compare_t) (const void *, const void *);
typedef void (*avl_action_t) (const void *);
typedef void (*avl_action_node_t) (const avl_node_t *);
typedef int (*avl_compare_t)(const void *, const void *);
typedef void (*avl_action_t)(const void *);
typedef void (*avl_action_node_t)(const avl_node_t *);
typedef struct avl_tree_t {
/* Linked list part */
/* Linked list part */
avl_node_t *head;
avl_node_t *tail;
avl_node_t *head;
avl_node_t *tail;
/* Tree part */
/* Tree part */
avl_node_t *root;
avl_node_t *root;
avl_compare_t compare;
avl_action_t delete;
avl_compare_t compare;
avl_action_t delete;
} avl_tree_t;
@ -128,18 +128,18 @@ extern avl_node_t *avl_search_closest_greater_node(const avl_tree_t *, const voi
/* Tree walking */
extern void avl_foreach(avl_tree_t *, avl_action_t);
extern void avl_foreach_node(avl_tree_t *, avl_action_t);
extern void avl_foreach(const avl_tree_t *, avl_action_t);
extern void avl_foreach_node(const avl_tree_t *, avl_action_t);
/* Indexing */
#ifdef AVL_COUNT
extern unsigned int avl_count(avl_tree_t *);
extern unsigned int avl_count(const avl_tree_t *);
extern avl_node_t *avl_get_node(const avl_tree_t *, unsigned int);
extern unsigned int avl_index(const avl_node_t *);
#endif
#ifdef AVL_DEPTH
extern unsigned int avl_depth(avl_tree_t *);
extern unsigned int avl_depth(const avl_tree_t *);
#endif
#endif /* __AVL_TREE_H__ */
#endif /* __AVL_TREE_H__ */

View file

@ -1,269 +0,0 @@
/*
conf.c -- configuration storage & retrieval code
Copyright (C) 1998 Robert van der Meulen
1998-2002 Ivo Timmermans <ivo@o2w.nl>
2000-2002 Guus Sliepen <guus@sliepen.warande.net>
2000 Cris van Pelt <tribbel@arise.dhs.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: conf.c,v 1.1 2002/04/28 12:46:25 zarq Exp $
*/
#include "config.h"
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <xalloc.h>
#include <utils.h> /* for cp */
#include <avl_tree.h>
#include "conf.h"
#include "netutl.h" /* for str2address */
#include "logging.h"
#include "system.h"
avl_tree_t *config_tree;
int pingtimeout = 0; /* seconds before timeout */
char *confbase = NULL; /* directory in which all config files are */
char *netname = NULL; /* name of the vpn network */
int config_compare(config_t *a, config_t *b)
{
int result;
result = strcasecmp(a->variable, b->variable);
if(result)
return result;
result = a->line - b->line;
if(result)
return result;
else
return strcmp(a->file, b->file);
}
void init_configuration(avl_tree_t **config_tree)
{
cp
*config_tree = avl_alloc_tree((avl_compare_t)config_compare, (avl_action_t)free_config);
cp
}
void exit_configuration(avl_tree_t **config_tree)
{
cp
avl_delete_tree(*config_tree);
*config_tree = NULL;
cp
}
config_t *new_config(void)
{
config_t *cfg;
cp
cfg = (config_t *)xmalloc_and_zero(sizeof(*cfg));
return cfg;
}
void free_config(config_t *cfg)
{
cp
if(cfg->variable)
free(cfg->variable);
if(cfg->value)
free(cfg->value);
if(cfg->file)
free(cfg->file);
free(cfg);
cp
}
void config_add(avl_tree_t *config_tree, config_t *cfg)
{
cp
avl_insert(config_tree, cfg);
cp
}
config_t *lookup_config(avl_tree_t *config_tree, char *variable)
{
config_t cfg, *found;
cp
cfg.variable = variable;
cfg.file = "";
cfg.line = 0;
found = avl_search_closest_greater(config_tree, &cfg);
if(!found)
return NULL;
if(strcasecmp(found->variable, variable))
return NULL;
return found;
}
config_t *lookup_config_next(avl_tree_t *config_tree, config_t *cfg)
{
avl_node_t *node;
config_t *found;
cp
node = avl_search_node(config_tree, cfg);
if(node)
{
if(node->next)
{
found = (config_t *)node->next->data;
if(!strcasecmp(found->variable, cfg->variable))
return found;
}
}
return NULL;
}
int get_config_bool(config_t *cfg, int *result)
{
cp
if(!cfg)
return 0;
if(!strcasecmp(cfg->value, "yes"))
{
*result = 1;
return 1;
}
else if(!strcasecmp(cfg->value, "no"))
{
*result = 0;
return 1;
}
syslog(LOG_ERR, _("\"yes\" or \"no\" expected for configuration variable %s in %s line %d"),
cfg->variable, cfg->file, cfg->line);
return 0;
}
int get_config_int(config_t *cfg, int *result)
{
cp
if(!cfg)
return 0;
if(sscanf(cfg->value, "%d", result) == 1)
return 1;
syslog(LOG_ERR, _("Integer expected for configuration variable %s in %s line %d"),
cfg->variable, cfg->file, cfg->line);
return 0;
}
int get_config_string(config_t *cfg, char **result)
{
cp
if(!cfg)
return 0;
*result = xstrdup(cfg->value);
return 1;
}
int get_config_address(config_t *cfg, struct addrinfo **result)
{
struct addrinfo *ai;
cp
if(!cfg)
return 0;
ai = str2addrinfo(cfg->value, NULL, 0);
if(ai)
{
*result = ai;
return 1;
}
syslog(LOG_ERR, _("Hostname or IP address expected for configuration variable %s in %s line %d"),
cfg->variable, cfg->file, cfg->line);
return 0;
}
int get_config_port(config_t *cfg, port_t *result)
{
cp
if(!cfg)
return 0;
if(sscanf(cfg->value, "%hu", result) == 1)
{
*result = htons(*result);
return 1;
}
syslog(LOG_ERR, _("Port number expected for configuration variable %s in %s line %d"),
cfg->variable, cfg->file, cfg->line);
return 0;
}
int get_config_subnet(config_t *cfg, subnet_t **result)
{
subnet_t *subnet;
cp
if(!cfg)
return 0;
subnet = str2net(cfg->value);
if(!subnet)
{
syslog(LOG_ERR, _("Subnet expected for configuration variable %s in %s line %d"),
cfg->variable, cfg->file, cfg->line);
return 0;
}
/* Teach newbies what subnets are... */
if(((subnet->type == SUBNET_IPV4) && maskcheck((char *)&subnet->net.ipv4.address, subnet->net.ipv4.prefixlength, sizeof(ipv4_t)))
|| ((subnet->type == SUBNET_IPV6) && maskcheck((char *)&subnet->net.ipv6.address, subnet->net.ipv6.prefixlength, sizeof(ipv6_t))))
{
syslog(LOG_ERR, _("Network address and prefix length do not match for configuration variable %s in %s line %d"),
cfg->variable, cfg->file, cfg->line);
free(subnet);
return 0;
}
*result = subnet;
return 1;
}

View file

@ -1,126 +0,0 @@
/*
connection.c -- connection list management
Copyright (C) 2000-2002 Guus Sliepen <guus@sliepen.warande.net>,
2000-2002 Ivo Timmermans <itimmermans@bigfoot.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: connection.c,v 1.1 2002/04/28 12:46:25 zarq Exp $
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <avl_tree.h>
#include <list.h>
#include "net.h" /* Don't ask. */
#include "netutl.h"
#include "config.h"
#include "conf.h"
#include <utils.h>
#include "subnet.h"
#include "logging.h"
#include "xalloc.h"
#include "system.h"
avl_tree_t *connection_tree; /* Meta connections */
int connection_compare(connection_t *a, connection_t *b)
{
return a - b;
}
void init_connections(void)
{
cp
connection_tree = avl_alloc_tree((avl_compare_t)connection_compare, NULL);
cp
}
void exit_connections(void)
{
cp
avl_delete_tree(connection_tree);
cp
}
connection_t *new_connection(void)
{
connection_t *c;
cp
c = (connection_t *)xmalloc_and_zero(sizeof(connection_t));
if(!c)
return NULL;
gettimeofday(&c->start, NULL);
cp
return c;
}
void free_connection(connection_t *c)
{
cp
if(c->hostname)
free(c->hostname);
if(c->inkey)
free(c->inkey);
if(c->outkey)
free(c->outkey);
if(c->mychallenge)
free(c->mychallenge);
if(c->hischallenge)
free(c->hischallenge);
free(c);
cp
}
void connection_add(connection_t *c)
{
cp
avl_insert(connection_tree, c);
cp
}
void connection_del(connection_t *c)
{
cp
avl_delete(connection_tree, c);
cp
}
void dump_connections(void)
{
avl_node_t *node;
connection_t *c;
cp
syslog(LOG_DEBUG, _("Connections:"));
for(node = connection_tree->head; node; node = node->next)
{
c = (connection_t *)node->data;
syslog(LOG_DEBUG, _(" %s at %s options %lx socket %d status %04x"),
c->name, c->hostname, c->options, c->socket, c->status);
}
syslog(LOG_DEBUG, _("End of connections."));
cp
}

View file

@ -1,141 +0,0 @@
/*
connection.h -- header for connection.c
Copyright (C) 2000-2002 Guus Sliepen <guus@sliepen.warande.net>,
2000-2002 Ivo Timmermans <itimmermans@bigfoot.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: connection.h,v 1.1 2002/04/28 12:46:25 zarq Exp $
*/
#ifndef __TINC_CONNECTION_H__
#define __TINC_CONNECTION_H__
#include <sys/time.h>
#include <avl_tree.h>
#include <list.h>
#ifdef USE_OPENSSL
# ifdef HAVE_OPENSSL_EVP_H
# include <openssl/evp.h>
# else
# include <evp.h>
# endif
# ifdef HAVE_OPENSSL_RSA_H
# include <openssl/rsa.h>
# else
# include <rsa.h>
# endif
#endif /* USE_OPENSSL */
#ifdef USE_GCRYPT
# include <gcrypt.h>
#endif
#include "net.h"
#include "conf.h"
#include "node.h"
#include "edge.h"
#define OPTION_INDIRECT 0x0001
#define OPTION_TCPONLY 0x0002
typedef struct connection_status_t {
int pinged:1; /* sent ping */
int active:1; /* 1 if active.. */
int connecting:1; /* 1 if we are waiting for a non-blocking connect() to finish */
int termreq:1; /* the termination of this connection was requested */
int remove:1; /* Set to 1 if you want this connection removed */
int timeout:1; /* 1 if gotten timeout */
int encryptout:1; /* 1 if we can encrypt outgoing traffic */
int decryptin:1; /* 1 if we have to decrypt incoming traffic */
int mst:1; /* 1 if this connection is part of a minimum spanning tree */
int unused:18;
} connection_status_t;
typedef struct connection_t {
char *name; /* name he claims to have */
sockaddr_t address; /* his real (internet) ip */
char *hostname; /* the hostname of its real ip */
int protocol_version; /* used protocol */
int socket; /* socket used for this connection */
long int options; /* options for this connection */
struct connection_status_t status; /* status info */
int estimated_weight; /* estimation for the weight of the edge for this connection */
struct timeval start; /* time this connection was started, used for above estimation */
struct outgoing_t *outgoing; /* used to keep track of outgoing connections */
struct node_t *node; /* node associated with the other end */
struct edge_t *edge; /* edge associated with this connection */
#ifdef USE_OPENSSL
RSA *rsa_key; /* his public/private key */
const EVP_CIPHER *incipher; /* Cipher he will use to send data to us */
const EVP_CIPHER *outcipher; /* Cipher we will use to send data to him */
EVP_CIPHER_CTX *inctx; /* Context of encrypted meta data that will come from him to us */
EVP_CIPHER_CTX *outctx; /* Context of encrypted meta data that will be sent from us to him */
const EVP_MD *indigest;
const EVP_MD *outdigest;
#endif
#ifdef USE_GCRYPT
GCRY_SEXP rsa_key;
GCRY_CIPHER_HD incipher;
GCRY_CIPHER_HD outcipher;
GCRY_CIPHER_HD inctx;
GCRY_CIPHER_HD outctx;
GCRY_MD_HD indigest;
GCRY_MD_HD outdigest;
/* FIXME */
#endif
char *inkey; /* His symmetric meta key + iv */
char *outkey; /* Our symmetric meta key + iv */
int inkeylength; /* Length of his key + iv */
int outkeylength; /* Length of our key + iv */
int inmaclength;
int outmaclength;
int incompression;
int outcompression;
char *mychallenge; /* challenge we received from him */
char *hischallenge; /* challenge we sent to him */
char buffer[MAXBUFSIZE]; /* metadata input buffer */
int buflen; /* bytes read into buffer */
int tcplen; /* length of incoming TCPpacket */
int allow_request; /* defined if there's only one request possible */
time_t last_ping_time; /* last time we saw some activity from the other end */
avl_tree_t *config_tree; /* Pointer to configuration tree belonging to him */
} connection_t;
extern avl_tree_t *connection_tree;
extern void init_connections(void);
extern void exit_connections(void);
extern connection_t *new_connection(void);
extern void free_connection(connection_t *);
extern void connection_add(connection_t *);
extern void connection_del(connection_t *);
extern void dump_connections(void);
extern int read_connection_config(connection_t *);
#endif /* __TINC_CONNECTION_H__ */

View file

@ -1,7 +1,7 @@
/*
dropin.c -- a set of drop-in replacements for libc functions
Copyright (C) 2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>,
2000,2001 Guus Sliepen <guus@sliepen.warande.net>
Copyright (C) 2000-2003 Ivo Timmermans <ivo@o2w.nl>,
2000-2003 Guus Sliepen <guus@sliepen.eu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -17,23 +17,12 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: dropin.c,v 1.2 2002/04/09 15:26:00 zarq Exp $
$Id: dropin.c,v 1.3 2003/08/24 20:38:20 guus Exp $
*/
#include "config.h"
#include "system.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <xalloc.h>
#include <system.h>
#include <errno.h>
#include "xalloc.h"
#ifndef HAVE_DAEMON
/*
@ -51,61 +40,55 @@
*/
int daemon(int nochdir, int noclose)
{
pid_t pid;
int fd;
pid = fork();
/* Check if forking failed */
if(pid < 0)
{
perror("fork");
exit(-1);
}
#ifdef HAVE_FORK
pid_t pid;
int fd;
/* If we are the parent, terminate */
if(pid)
exit(0);
pid = fork();
/* Detach by becoming the new process group leader */
if(setsid() < 0)
{
perror("setsid");
return -1;
}
/* Change working directory to the root (to avoid keeping mount
points busy) */
if(!nochdir)
{
chdir("/");
}
/* Redirect stdin/out/err to /dev/null */
if(!noclose)
{
fd = open("/dev/null", O_RDWR);
/* Check if forking failed */
if(pid < 0) {
perror("fork");
exit(-1);
}
if(fd < 0)
{
perror("opening /dev/null");
return -1;
}
else
{
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
}
}
/* If we are the parent, terminate */
if(pid)
exit(0);
return 0;
/* Detach by becoming the new process group leader */
if(setsid() < 0) {
perror("setsid");
return -1;
}
/* Change working directory to the root (to avoid keeping mount
points busy) */
if(!nochdir) {
chdir("/");
}
/* Redirect stdin/out/err to /dev/null */
if(!noclose) {
fd = open("/dev/null", O_RDWR);
if(fd < 0) {
perror("opening /dev/null");
return -1;
} else {
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
}
}
return 0;
#else
return -1;
#endif
}
#endif
#ifndef HAVE_GET_CURRENT_DIR_NAME
/*
Replacement for the GNU get_current_dir_name function:
@ -116,56 +99,75 @@ int daemon(int nochdir, int noclose)
*/
char *get_current_dir_name(void)
{
size_t size;
char *buf;
char *r;
size_t size;
char *buf;
char *r;
/* Start with 100 bytes. If this turns out to be insufficient to
contain the working directory, double the size. */
size = 100;
buf = xmalloc(size);
/* Start with 100 bytes. If this turns out to be insufficient to
contain the working directory, double the size. */
size = 100;
buf = xmalloc(size);
errno = 0; /* Success */
r = getcwd(buf, size);
/* getcwd returns NULL and sets errno to ERANGE if the bufferspace
is insufficient to contain the entire working directory. */
while(r == NULL && errno == ERANGE)
{
free(buf);
size <<= 1; /* double the size */
buf = xmalloc(size);
r = getcwd(buf, size);
}
errno = 0; /* Success */
r = getcwd(buf, size);
return buf;
/* getcwd returns NULL and sets errno to ERANGE if the bufferspace
is insufficient to contain the entire working directory. */
while(r == NULL && errno == ERANGE) {
free(buf);
size <<= 1; /* double the size */
buf = xmalloc(size);
r = getcwd(buf, size);
}
return buf;
}
#endif
#ifndef HAVE_ASPRINTF
int asprintf(char **buf, const char *fmt, ...)
{
int status;
va_list ap;
int len;
len = 4096;
*buf = xmalloc(len);
int status;
va_list ap;
int len;
va_start(ap, fmt);
status = vsnprintf (*buf, len, fmt, ap);
va_end (ap);
len = 4096;
*buf = xmalloc(len);
if(status >= 0)
*buf = xrealloc(*buf, status);
va_start(ap, fmt);
status = vsnprintf(*buf, len, fmt, ap);
va_end(ap);
if(status > len-1)
{
len = status;
va_start(ap, fmt);
status = vsnprintf (*buf, len, fmt, ap);
va_end (ap);
}
if(status >= 0)
*buf = xrealloc(*buf, status + 1);
return status;
if(status > len - 1) {
len = status;
va_start(ap, fmt);
status = vsnprintf(*buf, len, fmt, ap);
va_end(ap);
}
return status;
}
#endif
#ifndef HAVE_GETTIMEOFDAY
int gettimeofday(struct timeval *tv, void *tz) {
tv->tv_sec = time(NULL);
tv->tv_usec = 0;
return 0;
}
#endif
#ifndef HAVE_RANDOM
#include <openssl/rand.h>
long int random(void) {
long int x;
RAND_pseudo_bytes((unsigned char *)&x, sizeof(x));
return x;
}
#endif

View file

@ -1,7 +1,7 @@
/*
dropin.h -- header file for dropin.c
Copyright (C) 2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>,
2000,2001 Guus Sliepen <guus@sliepen.warande.net>
Copyright (C) 2000-2003 Ivo Timmermans <ivo@o2w.nl>,
2000-2003 Guus Sliepen <guus@sliepen.eu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -17,22 +17,38 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: dropin.h,v 1.2 2002/04/09 15:26:00 zarq Exp $
$Id: dropin.h,v 1.3 2003/08/24 20:38:20 guus Exp $
*/
#ifndef __DROPIN_H__
#define __DROPIN_H__
#include "fake-getaddrinfo.h"
#include "fake-getnameinfo.h"
#ifndef HAVE_DAEMON
extern int daemon(int, int);
#endif
#ifndef HAVE_GET_CURRENT_DIR_NAME
extern char* get_current_dir_name(void);
extern char *get_current_dir_name(void);
#endif
#ifndef HAVE_ASPRINTF
extern int asprintf(char **, const char *, ...);
#endif
#endif /* __DROPIN_H__ */
#ifndef HAVE_GETNAMEINFO
extern int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
size_t hostlen, char *serv, size_t servlen, int flags);
#endif
#ifndef HAVE_GETTIMEOFDAY
extern int gettimeofday(struct timeval *, void *);
#endif
#ifndef HAVE_RANDOM
extern long int random(void);
#endif
#endif /* __DROPIN_H__ */

View file

@ -1,212 +0,0 @@
/*
edge.c -- edge tree management
Copyright (C) 2000-2002 Guus Sliepen <guus@sliepen.warande.net>,
2000-2002 Ivo Timmermans <itimmermans@bigfoot.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: edge.c,v 1.1 2002/04/28 12:46:25 zarq Exp $
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <string.h>
#include <avl_tree.h>
#include <list.h>
#include "net.h" /* Don't ask. */
#include "netutl.h"
#include "config.h"
#include "conf.h"
#include <utils.h>
#include "subnet.h"
#include "xalloc.h"
#include "system.h"
avl_tree_t *edge_tree; /* Tree with all known edges (replaces active_tree) */
avl_tree_t *edge_weight_tree; /* Tree with all edges, sorted on weight */
int edge_compare(edge_t *a, edge_t *b)
{
int result;
result = strcmp(a->from.node->name, b->from.node->name);
if(result)
return result;
else
return strcmp(a->to.node->name, b->to.node->name);
}
/* Evil edge_compare() from a parallel universe ;)
int edge_compare(edge_t *a, edge_t *b)
{
int result;
return (result = strcmp(a->from.node->name, b->from.node->name)) || (result = strcmp(a->to.node->name, b->to.node->name)), result;
}
*/
int edge_name_compare(edge_t *a, edge_t *b)
{
int result;
char *name_a1, *name_a2, *name_b1, *name_b2;
if(strcmp(a->from.node->name, a->to.node->name) < 0)
name_a1 = a->from.node->name, name_a2 = a->to.node->name;
else
name_a1 = a->to.node->name, name_a2 = a->from.node->name;
if(strcmp(b->from.node->name, b->to.node->name) < 0)
name_b1 = b->from.node->name, name_b2 = b->to.node->name;
else
name_b1 = b->to.node->name, name_b2 = b->from.node->name;
result = strcmp(name_a1, name_b1);
if(result)
return result;
else
return strcmp(name_a2, name_b2);
}
int edge_weight_compare(edge_t *a, edge_t *b)
{
int result;
result = a->weight - b->weight;
if(result)
return result;
else
return edge_name_compare(a, b);
}
void init_edges(void)
{
cp
edge_tree = avl_alloc_tree((avl_compare_t)edge_compare, NULL);
edge_weight_tree = avl_alloc_tree((avl_compare_t)edge_weight_compare, NULL);
cp
}
avl_tree_t *new_edge_tree(void)
{
cp
return avl_alloc_tree((avl_compare_t)edge_name_compare, NULL);
cp
}
void free_edge_tree(avl_tree_t *edge_tree)
{
cp
avl_delete_tree(edge_tree);
cp
}
void exit_edges(void)
{
cp
avl_delete_tree(edge_tree);
cp
}
/* Creation and deletion of connection elements */
edge_t *new_edge(void)
{
edge_t *e;
cp
e = (edge_t *)xmalloc_and_zero(sizeof(*e));
cp
return e;
}
void free_edge(edge_t *e)
{
cp
free(e);
cp
}
void edge_add(edge_t *e)
{
cp
avl_insert(edge_tree, e);
avl_insert(edge_weight_tree, e);
avl_insert(e->from.node->edge_tree, e);
avl_insert(e->to.node->edge_tree, e);
cp
}
void edge_del(edge_t *e)
{
cp
avl_delete(edge_tree, e);
avl_delete(edge_weight_tree, e);
avl_delete(e->from.node->edge_tree, e);
avl_delete(e->to.node->edge_tree, e);
cp
}
edge_t *lookup_edge(node_t *from, node_t *to)
{
edge_t v, *result;
cp
v.from.node = from;
v.to.node = to;
result = avl_search(edge_tree, &v);
if(result)
return result;
cp
v.from.node = to;
v.to.node = from;
return avl_search(edge_tree, &v);
}
void dump_edges(void)
{
avl_node_t *node;
edge_t *e;
char *from_udp, *to_udp;
cp
syslog(LOG_DEBUG, _("Edges:"));
for(node = edge_tree->head; node; node = node->next)
{
e = (edge_t *)node->data;
from_udp = sockaddr2hostname(&e->from.udpaddress);
to_udp = sockaddr2hostname(&e->to.udpaddress);
syslog(LOG_DEBUG, _(" %s at %s - %s at %s options %lx weight %d"),
e->from.node->name, from_udp,
e->to.node->name, to_udp,
e->options, e->weight);
free(from_udp);
free(to_udp);
}
syslog(LOG_DEBUG, _("End of edges."));
cp
}

View file

@ -1,60 +0,0 @@
/*
error.c -- generalized error handling
Copyright (C) 2000 Ivo Timmermans <itimmermans@bigfoot.com>
2000 Guus Sliepen <guus@sliepen.warande.net>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: error.c,v 1.1 2000/10/19 20:56:49 zarq Exp $
*/
#include "config.h"
#include <stdio.h>
#ifdef STDC_HEADERS
# include <stdarg.h>
#endif
#ifdef HAVE_SYSLOG_H
# include <syslog.h>
#endif
#include <error.h>
#include <system.h>
void error(int severity, const char *message, ...)
{
va_list v;
extern int detached;
va_start(v, message);
#ifdef HAVE_SYSLOG
if(detached)
{
syslog(LOG_ERR, _(message), v);
}
else
#endif /* HAVE_SYSLOG */
{
vfprintf(stderr, _(message), v);
fputs("\n", stderr);
}
va_end(v);
if(severity | ERR_FATAL)
exit(1);
}

View file

@ -1,34 +0,0 @@
/*
error.h -- header file for error.h
Copyright (C) 2000 Ivo Timmermans <itimmermans@bigfoot.com>
2000 Guus Sliepen <guus@sliepen.warande.net>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: error.h,v 1.1 2000/10/19 20:56:49 zarq Exp $
*/
#ifndef __TINC_ERROR_H__
#define __TINC_ERROR_H__
#define ERR_IGNORE 00000 /* Ignore this error */
#define ERR_FATAL 00001 /* Terminate program */
#define ERR_UNLOAD 00002 /* Unload associated module */
#define ERR_WARNING 01000 /* Warning message only */
#define ERR_DEBUG 04000 /* Debug message */
extern void error(int severity, const char *message, ...);
#endif /* __TINC_ERROR_H__ */

75
lib/ethernet.h Normal file
View file

@ -0,0 +1,75 @@
/*
ethernet.h -- missing Ethernet related definitions
Copyright (C) 2003 Ivo Timmermans <ivo@o2w.nl>
2003 Guus Sliepen <guus@sliepen.eu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: ethernet.h,v 1.2 2003/08/24 20:38:20 guus Exp $
*/
#ifndef __TINC_ETHERNET_H__
#define __TINC_ETHERNET_H__
#ifndef ETH_ALEN
#define ETH_ALEN 6
#endif
#ifndef ETHER_ADDR_LEN
#define ETHER_ADDR_LEN 6
#endif
#ifndef ARPHRD_ETHER
#define ARPHRD_ETHER 1
#endif
#ifndef ETHERTYPE_IP
#define ETHERTYPE_IP 0x0800
#endif
#ifndef HAVE_STRUCT_ARPHDR
struct arphdr {
unsigned short int ar_hrd;
unsigned short int ar_pro;
unsigned char ar_hln;
unsigned char ar_pln;
unsigned short int ar_op;
};
#define ARPOP_REQUEST 1
#define ARPOP_REPLY 2
#define ARPOP_RREQUEST 3
#define ARPOP_RREPLY 4
#define ARPOP_InREQUEST 8
#define ARPOP_InREPLY 9
#define ARPOP_NAK 10
#endif
#ifndef HAVE_STRUCT_ETHER_ARP
struct ether_arp {
struct arphdr ea_hdr;
uint8_t arp_sha[ETH_ALEN];
uint8_t arp_spa[4];
uint8_t arp_tha[ETH_ALEN];
uint8_t arp_tpa[4];
};
#define arp_hrd ea_hdr.ar_hrd
#define arp_pro ea_hdr.ar_pro
#define arp_hln ea_hdr.ar_hln
#define arp_pln ea_hdr.ar_pln
#define arp_op ea_hdr.ar_op
#endif
#endif /* __TINC_ETHERNET_H__ */

15
lib/fake-gai-errnos.h Normal file
View file

@ -0,0 +1,15 @@
/*
* fake library for ssh
*
* This file is included in getaddrinfo.c and getnameinfo.c.
* See getaddrinfo.c and getnameinfo.c.
*/
/* $Id: fake-gai-errnos.h,v 1.2 2003/08/24 20:38:20 guus Exp $ */
/* for old netdb.h */
#ifndef EAI_NODATA
#define EAI_NODATA 1
#define EAI_MEMORY 2
#define EAI_FAMILY 3
#endif

104
lib/fake-getaddrinfo.c Normal file
View file

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

49
lib/fake-getaddrinfo.h Normal file
View file

@ -0,0 +1,49 @@
/* $Id: fake-getaddrinfo.h,v 1.2 2003/08/24 20:38:20 guus Exp $ */
#ifndef _FAKE_GETADDRINFO_H
#define _FAKE_GETADDRINFO_H
#include "fake-gai-errnos.h"
#ifndef AI_PASSIVE
# define AI_PASSIVE 1
# define AI_CANONNAME 2
#endif
#ifndef NI_NUMERICHOST
# define NI_NUMERICHOST 2
# define NI_NAMEREQD 4
# define NI_NUMERICSERV 8
#endif
#ifndef AI_NUMERICHOST
#define AI_NUMERICHOST 4
#endif
#ifndef HAVE_STRUCT_ADDRINFO
struct addrinfo {
int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
int ai_family; /* PF_xxx */
int ai_socktype; /* SOCK_xxx */
int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
size_t ai_addrlen; /* length of ai_addr */
char *ai_canonname; /* canonical name for hostname */
struct sockaddr *ai_addr; /* binary address */
struct addrinfo *ai_next; /* next structure in linked list */
};
#endif /* !HAVE_STRUCT_ADDRINFO */
#ifndef HAVE_GETADDRINFO
int getaddrinfo(const char *hostname, const char *servname,
const struct addrinfo *hints, struct addrinfo **res);
#endif /* !HAVE_GETADDRINFO */
#ifndef HAVE_GAI_STRERROR
char *gai_strerror(int ecode);
#endif /* !HAVE_GAI_STRERROR */
#ifndef HAVE_FREEADDRINFO
void freeaddrinfo(struct addrinfo *ai);
#endif /* !HAVE_FREEADDRINFO */
#endif /* _FAKE_GETADDRINFO_H */

55
lib/fake-getnameinfo.c Normal file
View file

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

18
lib/fake-getnameinfo.h Normal file
View file

@ -0,0 +1,18 @@
/* $Id: fake-getnameinfo.h,v 1.2 2003/08/24 20:38:20 guus Exp $ */
#ifndef _FAKE_GETNAMEINFO_H
#define _FAKE_GETNAMEINFO_H
#ifndef HAVE_GETNAMEINFO
int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
size_t hostlen, char *serv, size_t servlen, int flags);
#endif /* !HAVE_GETNAMEINFO */
#ifndef NI_MAXSERV
# define NI_MAXSERV 32
#endif /* !NI_MAXSERV */
#ifndef NI_MAXHOST
# define NI_MAXHOST 1025
#endif /* !NI_MAXHOST */
#endif /* _FAKE_GETNAMEINFO_H */

View file

@ -85,16 +85,7 @@ USA. */
#define getpid() GetCurrentProcessId()
#endif
#ifndef _
/* This is for other GNU distributions with internationalized messages.
When compiling libc, the _ macro is predefined. */
#ifdef HAVE_LIBINTL_H
# include <libintl.h>
# define _(msgid) gettext (msgid)
#else
# define _(msgid) (msgid)
#endif
#endif
#include "gettext.h"
/* This version of `getopt' appears to the caller like standard Unix `getopt'
but it behaves differently for the user, since it allows the user
@ -268,7 +259,7 @@ extern pid_t __libc_pid;
is valid for the getopt call we must make sure that the ARGV passed
to getopt is that one passed to the process. */
static void
__attribute__ ((unused))
__attribute__ ((__unused__))
store_args_and_env (int argc, char *const *argv)
{
/* XXX This is no good solution. We should rather copy the args so

79
lib/gettext.h Normal file
View file

@ -0,0 +1,79 @@
/* Convenience header for conditional use of GNU <libintl.h>.
Copyright (C) 1995-1998, 2000-2003 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published
by the Free Software Foundation; either version 2, 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA. */
#ifndef _LIBGETTEXT_H
#define _LIBGETTEXT_H 1
/* NLS can be disabled through the configure --disable-nls option. */
#if ENABLE_NLS
/* Get declarations of GNU message catalog functions. */
# include <libintl.h>
# include <locale.h>
/* Shorthand notation */
# define _(Text) gettext (Text)
#else
/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
chokes if dcgettext is defined as a macro. So include it now, to make
later inclusions of <locale.h> a NOP. We don't include <libintl.h>
as well because people using "gettext.h" will not include <libintl.h>,
and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
is OK. */
#if defined(__sun)
# include <locale.h>
#endif
/* Disabled NLS.
The casts to 'const char *' serve the purpose of producing warnings
for invalid uses of the value returned from these functions.
On pre-ANSI systems without 'const', the config.h file is supposed to
contain "#define const". */
# define gettext(Msgid) ((const char *) (Msgid))
# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
# define ngettext(Msgid1, Msgid2, N) \
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
# define dngettext(Domainname, Msgid1, Msgid2, N) \
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
# define textdomain(Domainname) ((const char *) (Domainname))
# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
# define _(Text) Text
# define setlocale(Category, Locale) ((const char *) (Locale))
#endif
/* A pseudo function call that serves as a marker for the automated
extraction of messages, but does not call gettext(). The run-time
translation is done at a different place in the code.
The argument, String, should be a literal string. Concatenated strings
and other string expressions won't work.
The macro's expansion is not parenthesized, so that it is suitable as
initializer for static 'char[]' or 'const char[]' variables. */
#define gettext_noop(String) String
#define N_(Text) Text
#endif /* _LIBGETTEXT_H */

View file

@ -1,285 +0,0 @@
/*
graph.c -- graph algorithms
Copyright (C) 2001-2002 Guus Sliepen <guus@sliepen.warande.net>,
2001-2002 Ivo Timmermans <itimmermans@bigfoot.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: graph.c,v 1.1 2002/05/02 11:50:07 zarq Exp $
*/
/* We need to generate two trees from the graph:
1. A minimum spanning tree for broadcasts,
2. A single-source shortest path tree for unicasts.
Actually, the first one alone would suffice but would make unicast packets
take longer routes than necessary.
For the MST algorithm we can choose from Prim's or Kruskal's. I personally
favour Kruskal's, because we make an extra AVL tree of edges sorted on
weights (metric). That tree only has to be updated when an edge is added or
removed, and during the MST algorithm we just have go linearly through that
tree, adding safe edges until #edges = #nodes - 1. The implementation here
however is not so fast, because I tried to avoid having to make a forest and
merge trees.
For the SSSP algorithm Dijkstra's seems to be a nice choice. Currently a
simple breadth-first search is presented here.
The SSSP algorithm will also be used to determine whether nodes are directly,
indirectly or not reachable from the source. It will also set the correct
destination address and port of a node if possible.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(HAVE_FREEBSD) || defined(HAVE_OPENBSD)
#include <sys/param.h>
#endif
#include <netinet/in.h>
#include <avl_tree.h>
#include <hooks.h>
#include <utils.h>
#include "netutl.h"
#include "node.h"
#include "edge.h"
#include "connection.h"
#include "logging.h"
#include "system.h"
/* Implementation of Kruskal's algorithm.
Running time: O(EN)
Please note that sorting on weight is already done by add_edge().
*/
void mst_kruskal(void)
{
avl_node_t *node, *next;
edge_t *e;
node_t *n;
connection_t *c;
int nodes = 0;
int safe_edges = 0;
int skipped;
/* Clear MST status on connections */
for(node = connection_tree->head; node; node = node->next)
{
c = (connection_t *)node->data;
c->status.mst = 0;
}
/* Do we have something to do at all? */
if(!edge_weight_tree->head)
return;
if(debug_lvl >= DEBUG_SCARY_THINGS)
syslog(LOG_DEBUG, "Running Kruskal's algorithm:");
/* Clear visited status on nodes */
for(node = node_tree->head; node; node = node->next)
{
n = (node_t *)node->data;
n->status.visited = 0;
nodes++;
}
/* Starting point */
((edge_t *)edge_weight_tree->head->data)->from.node->status.visited = 1;
/* Add safe edges */
for(skipped = 0, node = edge_weight_tree->head; node; node = next)
{
next = node->next;
e = (edge_t *)node->data;
if(e->from.node->status.visited == e->to.node->status.visited)
{
skipped = 1;
continue;
}
e->from.node->status.visited = 1;
e->to.node->status.visited = 1;
if(e->connection)
e->connection->status.mst = 1;
safe_edges++;
if(debug_lvl >= DEBUG_SCARY_THINGS)
syslog(LOG_DEBUG, " Adding edge %s - %s weight %d", e->from.node->name, e->to.node->name, e->weight);
if(skipped)
{
next = edge_weight_tree->head;
continue;
}
}
if(debug_lvl >= DEBUG_SCARY_THINGS)
syslog(LOG_DEBUG, "Done, counted %d nodes and %d safe edges.", nodes, safe_edges);
}
/* Implementation of a simple breadth-first search algorithm.
Running time: O(E)
*/
void sssp_bfs(void)
{
avl_node_t *node, *from, *next, *to;
edge_t *e;
node_t *n;
halfconnection_t to_hc, from_hc;
avl_tree_t *todo_tree;
int indirect;
todo_tree = avl_alloc_tree(NULL, NULL);
/* Clear visited status on nodes */
for(node = node_tree->head; node; node = node->next)
{
n = (node_t *)node->data;
n->status.visited = 0;
n->status.indirect = 1;
}
/* Begin with myself */
myself->status.visited = 1;
myself->status.indirect = 0;
myself->nexthop = myself;
myself->via = myself;
node = avl_alloc_node();
node->data = myself;
avl_insert_top(todo_tree, node);
/* Loop while todo_tree is filled */
while(todo_tree->head)
{
for(from = todo_tree->head; from; from = next) /* "from" is the node from which we start */
{
next = from->next;
n = (node_t *)from->data;
for(to = n->edge_tree->head; to; to = to->next) /* "to" is the edge connected to "from" */
{
e = (edge_t *)to->data;
if(e->from.node == n) /* "from_hc" is the halfconnection with .node == from */
to_hc = e->to, from_hc = e->from;
else
to_hc = e->from, from_hc = e->to;
/* Situation:
/
/
------(n)from_hc-----to_hc
\
\
n->address is set to the to_hc.udpaddress of the edge left of n.
We are currently examining the edge right of n:
- If from_hc.udpaddress != n->address, then to_hc.node is probably
not reachable for the nodes left of n. We do as if the indirectdata
flag is set on edge e.
- If edge e provides for better reachability of to_hc.node, update
to_hc.node and (re)add it to the todo_tree to (re)examine the reachability
of nodes behind it.
*/
indirect = n->status.indirect || e->options & OPTION_INDIRECT || ((n != myself) && sockaddrcmp(&n->address, &from_hc.udpaddress));
if(to_hc.node->status.visited && (!to_hc.node->status.indirect || indirect))
continue;
to_hc.node->status.visited = 1;
to_hc.node->status.indirect = indirect;
to_hc.node->nexthop = (n->nexthop == myself) ? to_hc.node : n->nexthop;
to_hc.node->via = indirect ? n->via : to_hc.node;
to_hc.node->options = e->options;
if(sockaddrcmp(&to_hc.node->address, &to_hc.udpaddress))
{
node = avl_unlink(node_udp_tree, to_hc.node);
to_hc.node->address = to_hc.udpaddress;
if(to_hc.node->hostname)
free(to_hc.node->hostname);
to_hc.node->hostname = sockaddr2hostname(&to_hc.udpaddress);
avl_insert_node(node_udp_tree, node);
}
node = avl_alloc_node();
node->data = to_hc.node;
avl_insert_before(todo_tree, from, node);
}
avl_delete_node(todo_tree, from);
}
}
avl_free_tree(todo_tree);
/* Check reachability status. */
for(node = node_tree->head; node; node = next)
{
next = node->next;
n = (node_t *)node->data;
if(n->status.visited)
{
if(!n->status.reachable)
{
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Node %s (%s) became reachable"), n->name, n->hostname);
n->status.reachable = 1;
run_hooks("node-visible", n);
}
}
else
{
if(n->status.reachable)
{
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Node %s (%s) became unreachable"), n->name, n->hostname);
n->status.reachable = 0;
n->status.validkey = 0;
n->status.waitingforkey = 0;
n->sent_seqno = 0;
run_hooks("node-invisible", n);
}
}
}
}
void graph(void)
{
mst_kruskal();
sssp_bfs();
}

View file

@ -1,56 +0,0 @@
/*
hash.c -- Handle hash datastructures
Copyright (C) 2000 Ivo Timmermans <itimmermans@bigfoot.com>
2000 Guus Sliepen <guus@sliepen.warande.net>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: hash.c,v 1.1 2000/10/20 16:44:32 zarq Exp $
*/
#include "config.h"
/*
hash_delete
delete one element, indicated by key, from hash
*/
int hash_delete(hash_t hash, char *key)
{
}
/*
hash_insert_maybe
insert an element into the hash, unless an element with the
same key already exists.
*/
int hash_insert_maybe(hash_t hash, void *data, char *key)
{
if(hash_retrieve(hash, key))
{
}
}
/*
hash_insert_or_update
If an element indicated by key exists in the hash, update the
associated pointer. Otherwise, insert this pointer as a new
element.
*/
int hash_insert_or_update(hash_t hash, void *data, char *key)
{
}

View file

@ -1 +0,0 @@
/* */

View file

@ -1,34 +0,0 @@
/*
hooks.h -- header file for hooks.c
Copyright (C) 2002 Guus Sliepen <guus@sliepen.warande.net>,
2002 Ivo Timmermans <ivo@o2w.nl>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: hooks.h,v 1.2 2002/05/07 14:48:41 zarq Exp $
*/
#ifndef __TINC_HOOKS_H__
#define __TINC_HOOKS_H__
#include <stdarg.h>
typedef void (hook_function_t)(const char*,va_list);
void run_hooks(const char *type, ...);
void add_hook(const char *type, hook_function_t *hook);
void del_hook(const char *type, hook_function_t *hook);
#endif /* __TINC_HOOKS_H__ */

132
lib/ipv4.h Normal file
View file

@ -0,0 +1,132 @@
/*
ipv4.h -- missing IPv4 related definitions
Copyright (C) 2003 Ivo Timmermans <ivo@o2w.nl>
2003 Guus Sliepen <guus@sliepen.eu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: ipv4.h,v 1.2 2003/08/24 20:38:20 guus Exp $
*/
#ifndef __TINC_IPV4_H__
#define __TINC_IPV4_H__
#ifndef AF_INET
#define AF_INET 2
#endif
#ifndef IPPROTO_ICMP
#define IPPROTO_ICMP 1
#endif
#ifndef ICMP_DEST_UNREACH
#define ICMP_DEST_UNREACH 3
#endif
#ifndef ICMP_NET_UNKNOWN
#define ICMP_NET_UNKNOWN 6
#endif
#ifndef ICMP_NET_UNREACH
#define ICMP_NET_UNREACH 0
#endif
#ifndef IP_MSS
#define IP_MSS 576
#endif
#ifndef HAVE_STRUCT_IP
struct ip {
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int ip_hl:4;
unsigned int ip_v:4;
#else
unsigned int ip_v:4;
unsigned int ip_hl:4;
#endif
uint8_t ip_tos;
uint16_t ip_len;
uint16_t ip_id;
uint16_t ip_off;
#define IP_RF 0x8000
#define IP_DF 0x4000
#define IP_MF 0x2000
#define IP_OFFMASK 0x1fff
uint8_t ip_ttl;
uint8_t ip_p;
uint16_t ip_sum;
struct in_addr ip_src, ip_dst;
};
#endif
#ifndef HAVE_STRUCT_ICMP
struct icmp {
uint8_t icmp_type;
uint8_t icmp_code;
uint16_t icmp_cksum;
union {
uint8_t ih_pptr;
struct in_addr ih_gwaddr;
struct ih_idseq {
uint16_t icd_id;
uint16_t icd_seq;
} ih_idseq;
uint32_t ih_void;
struct ih_pmtu {
uint16_t ipm_void;
uint16_t ipm_nextmtu;
} ih_pmtu;
struct ih_rtradv {
uint8_t irt_num_addrs;
uint8_t irt_wpa;
uint16_t irt_lifetime;
} ih_rtradv;
} icmp_hun;
#define icmp_pptr icmp_hun.ih_pptr
#define icmp_gwaddr icmp_hun.ih_gwaddr
#define icmp_id icmp_hun.ih_idseq.icd_id
#define icmp_seq icmp_hun.ih_idseq.icd_seq
#define icmp_void icmp_hun.ih_void
#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void
#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu
#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs
#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa
#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime
union {
struct {
uint32_t its_otime;
uint32_t its_rtime;
uint32_t its_ttime;
} id_ts;
struct {
struct ip idi_ip;
} id_ip;
uint32_t id_mask;
uint8_t id_data[1];
} icmp_dun;
#define icmp_otime icmp_dun.id_ts.its_otime
#define icmp_rtime icmp_dun.id_ts.its_rtime
#define icmp_ttime icmp_dun.id_ts.its_ttime
#define icmp_ip icmp_dun.id_ip.idi_ip
#define icmp_radv icmp_dun.id_radv
#define icmp_mask icmp_dun.id_mask
#define icmp_data icmp_dun.id_data
};
#endif
#endif /* __TINC_IPV4_H__ */

120
lib/ipv6.h Normal file
View file

@ -0,0 +1,120 @@
/*
ipv6.h -- missing IPv6 related definitions
Copyright (C) 2003 Ivo Timmermans <ivo@o2w.nl>
2003 Guus Sliepen <guus@sliepen.eu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: ipv6.h,v 1.2 2003/08/24 20:38:20 guus Exp $
*/
#ifndef __TINC_IPV6_H__
#define __TINC_IPV6_H__
#ifndef AF_INET6
#define AF_INET6 10
#endif
#ifndef IPPROTO_ICMPV6
#define IPPROTO_ICMPV6 58
#endif
#ifndef HAVE_STRUCT_IN6_ADDR
struct in6_addr {
union {
uint8_t u6_addr8[16];
uint16_t u6_addr16[8];
uint32_t u6_addr32[4];
} in6_u;
};
#define s6_addr in6_u.u6_addr8
#define s6_addr16 in6_u.u6_addr16
#define s6_addr32 in6_u.u6_addr32
#endif
#ifndef HAVE_STRUCT_SOCKADDR_IN6
struct sockaddr_in6 {
uint16_t sin6_family;
uint16_t sin6_port;
uint32_t sin6_flowinfo;
struct in6_addr sin6_addr;
uint32_t sin6_scope_id;
};
#endif
#ifndef IN6_IS_ADDR_V4MAPPED
#define IN6_IS_ADDR_V4MAPPED(a) \
((((__const uint32_t *) (a))[0] == 0) \
&& (((__const uint32_t *) (a))[1] == 0) \
&& (((__const uint32_t *) (a))[2] == htonl (0xffff)))
#endif
#ifndef HAVE_STRUCT_IP6_HDR
struct ip6_hdr {
union {
struct ip6_hdrctl {
uint32_t ip6_un1_flow;
uint16_t ip6_un1_plen;
uint8_t ip6_un1_nxt;
uint8_t ip6_un1_hlim;
} ip6_un1;
uint8_t ip6_un2_vfc;
} ip6_ctlun;
struct in6_addr ip6_src;
struct in6_addr ip6_dst;
};
#define ip6_vfc ip6_ctlun.ip6_un2_vfc
#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow
#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen
#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt
#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim
#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim
#endif
#ifndef HAVE_STRUCT_ICMP6_HDR
struct icmp6_hdr {
uint8_t icmp6_type;
uint8_t icmp6_code;
uint16_t icmp6_cksum;
union {
uint32_t icmp6_un_data32[1];
uint16_t icmp6_un_data16[2];
uint8_t icmp6_un_data8[4];
} icmp6_dataun;
};
#define ICMP6_DST_UNREACH_NOROUTE 0
#define ICMP6_DST_UNREACH 1
#define ICMP6_DST_UNREACH_ADDR 3
#define ND_NEIGHBOR_SOLICIT 135
#define ND_NEIGHBOR_ADVERT 136
#endif
#ifndef HAVE_STRUCT_ND_NEIGHBOR_SOLICIT
struct nd_neighbor_solicit {
struct icmp6_hdr nd_ns_hdr;
struct in6_addr nd_ns_target;
};
#define ND_OPT_SOURCE_LINKADDR 1
#define ND_OPT_TARGET_LINKADDR 2
#endif
#ifndef HAVE_STRUCT_ND_OPT_HDR
struct nd_opt_hdr {
uint8_t nd_opt_type;
uint8_t nd_opt_len;
};
#endif
#endif /* __TINC_IPV6_H__ */

View file

@ -1,7 +1,7 @@
/*
list.c -- functions to deal with double linked lists
Copyright (C) 2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>
2000,2001 Guus Sliepen <guus@sliepen.warande.net>
Copyright (C) 2000-2003 Ivo Timmermans <ivo@o2w.nl>
2000-2003 Guus Sliepen <guus@sliepen.eu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -17,181 +17,170 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: list.c,v 1.2 2002/04/09 15:26:00 zarq Exp $
$Id: list.c,v 1.3 2003/08/24 20:38:20 guus Exp $
*/
#include "config.h"
#include <stdlib.h>
#include <xalloc.h>
#include <system.h>
#include "system.h"
#include "list.h"
#include "xalloc.h"
/* (De)constructors */
list_t *list_alloc(list_action_t delete)
{
list_t *list;
list_t *list;
list = xmalloc_and_zero(sizeof(list_t));
list->delete = delete;
list = xmalloc_and_zero(sizeof(list_t));
list->delete = delete;
return list;
return list;
}
void list_free(list_t *list)
{
free(list);
free(list);
}
list_node_t *list_alloc_node(void)
{
list_node_t *node;
node = xmalloc_and_zero(sizeof(list_node_t));
return node;
return (list_node_t *)xmalloc_and_zero(sizeof(list_node_t));
}
void list_free_node(list_t *list, list_node_t *node)
{
if(node->data && list->delete)
list->delete(node->data);
free(node);
if(node->data && list->delete)
list->delete(node->data);
free(node);
}
/* Insertion and deletion */
list_node_t *list_insert_head(list_t *list, void *data)
{
list_node_t *node;
node = list_alloc_node();
node->data = data;
node->prev = NULL;
node->next = list->head;
list->head = node;
if(node->next)
node->next->prev = node;
else
list->tail = node;
list_node_t *node;
list->count++;
node = list_alloc_node();
return node;
node->data = data;
node->prev = NULL;
node->next = list->head;
list->head = node;
if(node->next)
node->next->prev = node;
else
list->tail = node;
list->count++;
return node;
}
list_node_t *list_insert_tail(list_t *list, void *data)
{
list_node_t *node;
node = list_alloc_node();
node->data = data;
node->next = NULL;
node->prev = list->tail;
list->tail = node;
if(node->prev)
node->prev->next = node;
else
list->head = node;
list_node_t *node;
list->count++;
return node;
node = list_alloc_node();
node->data = data;
node->next = NULL;
node->prev = list->tail;
list->tail = node;
if(node->prev)
node->prev->next = node;
else
list->head = node;
list->count++;
return node;
}
void list_unlink_node(list_t *list, list_node_t *node)
{
if(node->prev)
node->prev->next = node->next;
else
list->head = node->next;
if(node->next)
node->next->prev = node->prev;
else
list->tail = node->prev;
if(node->prev)
node->prev->next = node->next;
else
list->head = node->next;
list->count--;
if(node->next)
node->next->prev = node->prev;
else
list->tail = node->prev;
list->count--;
}
void list_delete_node(list_t *list, list_node_t *node)
{
list_unlink_node(list, node);
list_free_node(list, node);
list_unlink_node(list, node);
list_free_node(list, node);
}
void list_delete_head(list_t *list)
{
list_delete_node(list, list->head);
list_delete_node(list, list->head);
}
void list_delete_tail(list_t *list)
{
list_delete_node(list, list->tail);
list_delete_node(list, list->tail);
}
/* Head/tail lookup */
void *list_get_head(list_t *list)
{
if(list->head)
return list->head->data;
else
return NULL;
if(list->head)
return list->head->data;
else
return NULL;
}
void *list_get_tail(list_t *list)
{
if(list->tail)
return list->tail->data;
else
return NULL;
if(list->tail)
return list->tail->data;
else
return NULL;
}
/* Fast list deletion */
void list_delete_list(list_t *list)
{
list_node_t *node, *next;
for(node = list->head; node; node = next)
{
next = node->next;
list_free_node(list, node);
}
list_node_t *node, *next;
list_free(list);
for(node = list->head; node; node = next) {
next = node->next;
list_free_node(list, node);
}
list_free(list);
}
/* Traversing */
void list_foreach_node(list_t *list, list_action_node_t action)
{
list_node_t *node, *next;
list_node_t *node, *next;
for(node = list->head; node; node = next)
{
next = node->next;
action(node);
}
for(node = list->head; node; node = next) {
next = node->next;
action(node);
}
}
void list_foreach(list_t *list, list_action_t action)
{
list_node_t *node, *next;
list_node_t *node, *next;
for(node = list->head; node; node = next)
{
next = node->next;
if(node->data)
action(node->data);
}
for(node = list->head; node; node = next) {
next = node->next;
if(node->data)
action(node->data);
}
}

View file

@ -1,7 +1,7 @@
/*
list.h -- header file for list.c
Copyright (C) 2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>
2000,2001 Guus Sliepen <guus@sliepen.warande.net>
Copyright (C) 2000-2003 Ivo Timmermans <ivo@o2w.nl>
2000-2003 Guus Sliepen <guus@sliepen.eu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -17,39 +17,37 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: list.h,v 1.2 2002/04/09 15:26:00 zarq Exp $
$Id: list.h,v 1.3 2003/08/24 20:38:20 guus Exp $
*/
#ifndef __TINC_LIST_H__
#define __TINC_LIST_H__
typedef struct list_node_t
{
struct list_node_t *prev;
struct list_node_t *next;
typedef struct list_node_t {
struct list_node_t *prev;
struct list_node_t *next;
/* Payload */
/* Payload */
void *data;
void *data;
} list_node_t;
typedef void (*list_action_t) (const void *);
typedef void (*list_action_node_t) (const list_node_t *);
typedef void (*list_action_t)(const void *);
typedef void (*list_action_node_t)(const list_node_t *);
typedef struct list_t
{
list_node_t *head;
list_node_t *tail;
int count;
typedef struct list_t {
list_node_t *head;
list_node_t *tail;
int count;
/* Callbacks */
/* Callbacks */
list_action_t delete;
list_action_t delete;
} list_t;
/* (De)constructors */
extern list_t *list_alloc(list_action_t);
extern list_t *list_alloc(list_action_t) __attribute__ ((__malloc__));
extern void list_free(list_t *);
extern list_node_t *list_alloc_node(void);
extern void list_free_node(list_t *, list_node_t *);
@ -79,4 +77,4 @@ extern void list_delete_list(list_t *);
extern void list_foreach(list_t *, list_action_t);
extern void list_foreach_node(list_t *, list_action_node_t);
#endif /* __TINC_LIST_H__ */
#endif /* __TINC_LIST_H__ */

View file

@ -1,106 +0,0 @@
/*
logging.c -- log messages to e.g. syslog
Copyright (C) 2001-2002 Guus Sliepen <guus@sliepen.warande.net>,
2001-2002 Ivo Timmermans <itimmermans@bigfoot.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: logging.c,v 1.1 2002/04/28 12:46:25 zarq Exp $
*/
#include "config.h"
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <syslog.h>
#include <avl_tree.h>
#include "logging.h"
avl_tree_t *log_hooks_tree = NULL;
int debug_lvl = 0;
int log_compare(const void *a, const void *b)
{
if(a < b)
return -1;
if(a > b)
return 1;
return 0;
}
void log(int level, int priority, char *fmt, ...)
{
avl_node_t *avlnode;
va_list args;
va_start(args, fmt);
for(avlnode = log_hooks_tree->head; avlnode; avlnode = avlnode->next)
{
assert(avlnode->data);
((log_function_t*)(avlnode->data))(level, priority, fmt, args);
}
va_end(args);
}
void log_add_hook(log_function_t *fn)
{
if(!log_hooks_tree)
log_hooks_tree = avl_alloc_tree(log_compare, NULL);
avl_insert(log_hooks_tree, (void*)fn);
}
void log_del_hook(log_function_t *fn)
{
avl_delete(log_hooks_tree, (void*)fn);
}
void log_default(int level, int priority, char *fmt, va_list ap)
{
if(debug_lvl >= level)
{
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
}
}
void log_syslog(int level, int priority, char *fmt, va_list ap)
{
const int priorities[] = { LOG_DEBUG, LOG_INFO, LOG_NOTICE, LOG_ERR, LOG_CRIT };
if(debug_lvl >= level)
vsyslog(priorities[priority], fmt, ap);
}
void tinc_syslog(int priority, char *fmt, ...)
{
/* Mapping syslog prio -> tinc prio */
const int priorities[] = { TLOG_CRITICAL, TLOG_CRITICAL, TLOG_CRITICAL, TLOG_ERROR,
TLOG_NOTICE, TLOG_NOTICE, TLOG_INFO, TLOG_DEBUG };
avl_node_t *avlnode;
va_list args;
va_start(args, fmt);
for(avlnode = log_hooks_tree->head; avlnode; avlnode = avlnode->next)
{
assert(avlnode->data);
((log_function_t*)(avlnode->data))(0, priorities[priority], fmt, args);
}
va_end(args);
}

View file

@ -1,74 +0,0 @@
/*
logging.h -- header for logging.c
Copyright (C) 2002 Guus Sliepen <guus@sliepen.warande.net>,
2002 Ivo Timmermans <ivo@o2w.nl>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: logging.h,v 1.1 2002/04/28 12:46:25 zarq Exp $
*/
#ifndef __TINC_LOGGING_H__
#define __TINC_LOGGING_H__
#include <stdarg.h>
enum {
TLOG_DEBUG,
TLOG_INFO,
TLOG_NOTICE,
TLOG_ERROR,
TLOG_CRITICAL
};
enum {
DEBUG_NOTHING = 0, /* Quiet mode, only show starting/stopping of the daemon */
DEBUG_CONNECTIONS = 1, /* Show (dis)connects of other tinc daemons via TCP */
DEBUG_ERROR = 2, /* Show error messages received from other hosts */
DEBUG_STATUS = 2, /* Show status messages received from other hosts */
DEBUG_PROTOCOL = 3, /* Show the requests that are sent/received */
DEBUG_META = 4, /* Show contents of every request that is sent/received */
DEBUG_TRAFFIC = 5, /* Show network traffic information */
DEBUG_PACKET = 6, /* Show contents of each packet that is being sent/received */
DEBUG_SCARY_THINGS = 10 /* You have been warned */
};
typedef void (log_function_t)(int,int,char*,va_list);
extern int debug_lvl;
extern avl_tree_t *log_hooks_tree;
extern void log(int, int, char *, ...);
extern void log_add_hook(log_function_t *);
extern void log_del_hook(log_function_t *);
extern log_function_t log_default;
extern log_function_t log_syslog;
extern void tinc_syslog(int, char *, ...);
#ifndef LOG_ERR /* Something from syslog.h */
# define syslog tinc_syslog
#define LOG_EMERG 0 /* system is unusable */
#define LOG_ALERT 1 /* action must be taken immediately */
#define LOG_CRIT 2 /* critical conditions */
#define LOG_ERR 3 /* error conditions */
#define LOG_WARNING 4 /* warning conditions */
#define LOG_NOTICE 5 /* normal but significant condition */
#define LOG_INFO 6 /* informational */
#define LOG_DEBUG 7 /* debug-level messages */
#else
# warning dont include syslog!
#endif
#endif /* __TINC_LOGGING_H__ */

153
lib/net.h
View file

@ -1,153 +0,0 @@
/*
net.h -- header for net.c
Copyright (C) 1998-2002 Ivo Timmermans <zarq@iname.com>
2000-2002 Guus Sliepen <guus@sliepen.warande.net>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: net.h,v 1.1 2002/04/28 12:46:25 zarq Exp $
*/
#ifndef __TINC_NET_H__
#define __TINC_NET_H__
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>
#include "config.h"
#ifdef ENABLE_JUMBOGRAMS
#define MTU 9014 /* 9000 bytes payload + 14 bytes ethernet header */
#define MAXSIZE 9100 /* MTU + header (seqno) and trailer (CBC padding and HMAC) */
#define MAXBUFSIZE 9100 /* Must support TCP packets of length 9000. */
#else
#define MTU 1514 /* 1500 bytes payload + 14 bytes ethernet header */
#define MAXSIZE 1600 /* MTU + header (seqno) and trailer (CBC padding and HMAC) */
#define MAXBUFSIZE 2100 /* Quite large but needed for support of keys up to 8192 bits. */
#endif
#define MAXSOCKETS 128 /* Overkill... */
#define MAXQUEUELENGTH 8 /* Maximum number of packats in a single queue */
typedef struct mac_t
{
unsigned char x[6];
} mac_t;
typedef struct ipv4_t
{
unsigned char x[4];
} ipv4_t;
typedef struct ip_mask_t {
ipv4_t address;
ipv4_t mask;
} ip_mask_t;
typedef struct ipv6_t
{
unsigned short x[8];
} ipv6_t;
typedef unsigned short port_t;
typedef short length_t;
typedef union {
struct sockaddr sa;
struct sockaddr_in in;
struct sockaddr_in6 in6;
} sockaddr_t;
#ifdef SA_LEN
#define SALEN(s) SA_LEN(&s)
#else
#define SALEN(s) (s.sa_family==AF_INET?sizeof(struct sockaddr_in):sizeof(struct sockaddr_in6))
#endif
typedef struct vpn_packet_t {
length_t len; /* the actual number of bytes in the `data' field */
int priority; /* priority or TOS */
unsigned int seqno; /* 32 bits sequence number (network byte order of course) */
unsigned char data[MAXSIZE];
} vpn_packet_t;
typedef struct queue_element_t {
void *packet;
struct queue_element_t *prev;
struct queue_element_t *next;
} queue_element_t;
typedef struct packet_queue_t {
queue_element_t *head;
queue_element_t *tail;
} packet_queue_t;
typedef struct outgoing_t {
char *name;
int timeout;
struct config_t *cfg;
struct addrinfo *ai;
struct addrinfo *aip;
} outgoing_t;
typedef struct listen_socket_t {
int tcp;
int udp;
sockaddr_t sa;
} listen_socket_t;
extern int maxtimeout;
extern int seconds_till_retry;
extern int addressfamily;
extern char *request_name[];
extern char *status_text[];
#include "connection.h" /* Yes, very strange placement indeed, but otherwise the typedefs get all tangled up */
extern listen_socket_t listen_socket[MAXSOCKETS];
extern int listen_sockets;
extern int keyexpires;
extern int keylifetime;
extern int do_prune;
extern int do_purge;
extern char *myport;
extern time_t now;
extern void retry_outgoing(outgoing_t *);
extern void handle_incoming_vpn_data(int);
extern void finish_connecting(connection_t *);
extern void do_outgoing_connection(connection_t *);
extern int handle_new_meta_connection(int);
extern int setup_listen_socket(sockaddr_t *);
extern int setup_vpn_in_socket(sockaddr_t *);
extern void send_packet(struct node_t *, vpn_packet_t *);
extern void receive_packet(struct node_t *, vpn_packet_t *);
extern void receive_tcppacket(struct connection_t *, char *, int);
extern void broadcast_packet(struct node_t *, vpn_packet_t *);
extern int setup_network_connections(void);
extern void setup_outgoing_connection(struct outgoing_t *);
extern void try_outgoing_connections(void);
extern void close_network_connections(void);
extern void main_loop(void);
extern void terminate_connection(connection_t *, int);
extern void flush_queue(struct node_t *);
extern int read_rsa_public_key(struct connection_t *);
#endif /* __TINC_NET_H__ */

View file

@ -1,247 +0,0 @@
/*
netutl.c -- some supporting network utility code
Copyright (C) 1998-2002 Ivo Timmermans <itimmermans@bigfoot.com>
2000-2002 Guus Sliepen <guus@sliepen.warande.net>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: netutl.c,v 1.1 2002/04/28 12:46:25 zarq Exp $
*/
#include "config.h"
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <utils.h>
#include <xalloc.h>
#include "errno.h"
#include "conf.h"
#include "net.h"
#include "netutl.h"
#include "logging.h"
#include "system.h"
int hostnames = 0;
/*
Turn a string into a struct addrinfo.
Return NULL on failure.
*/
struct addrinfo *str2addrinfo(char *address, char *service, int socktype)
{
struct addrinfo hint, *ai;
int err;
cp
memset(&hint, 0, sizeof(hint));
hint.ai_family = addressfamily;
hint.ai_socktype = socktype;
if((err = getaddrinfo(address, service, &hint, &ai)))
{
if(debug_lvl >= DEBUG_ERROR)
syslog(LOG_WARNING, _("Error looking up %s port %s: %s\n"), address, service, gai_strerror(err));
cp_trace();
return NULL;
}
cp
return ai;
}
sockaddr_t str2sockaddr(char *address, char *port)
{
struct addrinfo hint, *ai;
sockaddr_t result;
int err;
cp
memset(&hint, 0, sizeof(hint));
hint.ai_family = AF_UNSPEC;
hint.ai_flags = AI_NUMERICHOST;
hint.ai_socktype = SOCK_STREAM;
if((err = getaddrinfo(address, port, &hint, &ai) || !ai))
{
syslog(LOG_ERR, _("Error looking up %s port %s: %s\n"), address, port, gai_strerror(err));
cp_trace();
raise(SIGFPE);
exit(0);
}
result = *(sockaddr_t *)ai->ai_addr;
freeaddrinfo(ai);
cp
return result;
}
void sockaddr2str(sockaddr_t *sa, char **addrstr, char **portstr)
{
char address[NI_MAXHOST];
char port[NI_MAXSERV];
char *scopeid;
int err;
cp
if((err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port), NI_NUMERICHOST|NI_NUMERICSERV)))
{
syslog(LOG_ERR, _("Error while translating addresses: %s"), gai_strerror(err));
cp_trace();
raise(SIGFPE);
exit(0);
}
#ifdef HAVE_LINUX
if((scopeid = strchr(address, '%')))
*scopeid = '\0'; /* Descope. */
#endif
*addrstr = xstrdup(address);
*portstr = xstrdup(port);
cp
}
char *sockaddr2hostname(sockaddr_t *sa)
{
char *str;
char address[NI_MAXHOST] = "unknown";
char port[NI_MAXSERV] = "unknown";
int err;
cp
if((err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port), hostnames?0:(NI_NUMERICHOST|NI_NUMERICSERV))))
{
syslog(LOG_ERR, _("Error while looking up hostname: %s"), gai_strerror(err));
}
asprintf(&str, _("%s port %s"), address, port);
cp
return str;
}
int sockaddrcmp(sockaddr_t *a, sockaddr_t *b)
{
int result;
cp
result = a->sa.sa_family - b->sa.sa_family;
if(result)
return result;
switch(a->sa.sa_family)
{
case AF_UNSPEC:
return 0;
case AF_INET:
result = memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof(a->in.sin_addr));
if(result)
return result;
return memcmp(&a->in.sin_port, &b->in.sin_port, sizeof(a->in.sin_port));
case AF_INET6:
result = memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr));
if(result)
return result;
return memcmp(&a->in6.sin6_port, &b->in6.sin6_port, sizeof(a->in6.sin6_port));
default:
syslog(LOG_ERR, _("sockaddrcmp() was called with unknown address family %d, exitting!"), a->sa.sa_family);
cp_trace();
raise(SIGFPE);
exit(0);
}
cp
}
void sockaddrunmap(sockaddr_t *sa)
{
if(sa->sa.sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sa->in6.sin6_addr))
{
sa->in.sin_addr.s_addr = ((uint32_t *)&sa->in6.sin6_addr)[3];
sa->in.sin_family = AF_INET;
}
}
/* Subnet mask handling */
int maskcmp(char *a, char *b, int masklen, int len)
{
int i, m, result;
cp
for(m = masklen, i = 0; m >= 8; m -= 8, i++)
if((result = a[i] - b[i]))
return result;
if(m)
return (a[i] & (0x100 - (1 << (8 - m)))) - (b[i] & (0x100 - (1 << (8 - m))));
return 0;
}
void mask(char *a, int masklen, int len)
{
int i;
cp
i = masklen / 8;
masklen %= 8;
if(masklen)
a[i++] &= (0x100 - (1 << masklen));
for(; i < len; i++)
a[i] = 0;
}
void maskcpy(char *a, char *b, int masklen, int len)
{
int i, m;
cp
for(m = masklen, i = 0; m >= 8; m -= 8, i++)
a[i] = b[i];
if(m)
{
a[i] = b[i] & (0x100 - (1 << m));
i++;
}
for(; i < len; i++)
a[i] = 0;
}
int maskcheck(char *a, int masklen, int len)
{
int i;
cp
i = masklen / 8;
masklen %= 8;
if(masklen)
if(a[i++] & (char)~(0x100 - (1 << masklen)))
return -1;
for(; i < len; i++)
if(a[i] != 0)
return -1;
return 0;
}

View file

@ -1,188 +0,0 @@
/*
node.c -- node tree management
Copyright (C) 2001-2002 Guus Sliepen <guus@sliepen.warande.net>,
2001-2002 Ivo Timmermans <itimmermans@bigfoot.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: node.c,v 1.1 2002/04/28 12:46:25 zarq Exp $
*/
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include <avl_tree.h>
#include "node.h"
#include "netutl.h"
#include "net.h"
#include <utils.h>
#include <xalloc.h>
#include <hooks.h>
#include "logging.h"
#include "system.h"
avl_tree_t *node_tree; /* Known nodes, sorted by name */
avl_tree_t *node_udp_tree; /* Known nodes, sorted by address and port */
node_t *myself;
int node_compare(node_t *a, node_t *b)
{
return strcmp(a->name, b->name);
}
int node_udp_compare(node_t *a, node_t *b)
{
int result;
cp
result = sockaddrcmp(&a->address, &b->address);
if(result)
return result;
return (a->name && b->name)?strcmp(a->name, b->name):0;
}
void init_nodes(void)
{
cp
node_tree = avl_alloc_tree((avl_compare_t)node_compare, NULL);
node_udp_tree = avl_alloc_tree((avl_compare_t)node_udp_compare, NULL);
cp
}
void exit_nodes(void)
{
cp
avl_delete_tree(node_tree);
avl_delete_tree(node_udp_tree);
cp
}
node_t *new_node(void)
{
node_t *n = (node_t *)xmalloc_and_zero(sizeof(*n));
cp
n->subnet_tree = new_subnet_tree();
n->edge_tree = new_edge_tree();
n->queue = list_alloc((list_action_t)free);
cp
return n;
}
void free_node(node_t *n)
{
cp
if(n->queue)
list_delete_list(n->queue);
if(n->name)
free(n->name);
if(n->hostname)
free(n->hostname);
if(n->key)
free(n->key);
if(n->subnet_tree)
free_subnet_tree(n->subnet_tree);
if(n->edge_tree)
free_edge_tree(n->edge_tree);
free(n);
cp
}
void node_add(node_t *n)
{
cp
avl_insert(node_tree, n);
avl_insert(node_udp_tree, n);
run_hooks("node-add", n);
cp
}
void node_del(node_t *n)
{
avl_node_t *node, *next;
edge_t *e;
subnet_t *s;
cp
for(node = n->subnet_tree->head; node; node = next)
{
next = node->next;
s = (subnet_t *)node->data;
subnet_del(n, s);
}
for(node = n->subnet_tree->head; node; node = next)
{
next = node->next;
e = (edge_t *)node->data;
edge_del(e);
}
cp
avl_delete(node_tree, n);
avl_delete(node_udp_tree, n);
run_hooks("node-del", n);
cp
}
node_t *lookup_node(char *name)
{
node_t n;
cp
n.name = name;
return avl_search(node_tree, &n);
}
node_t *lookup_node_udp(sockaddr_t *sa)
{
node_t n;
cp
n.address = *sa;
n.name = NULL;
return avl_search(node_udp_tree, &n);
}
void dump_nodes(void)
{
avl_node_t *node;
node_t *n;
cp
log(0, TLOG_DEBUG,
_("Nodes:"));
for(node = node_tree->head; node; node = node->next)
{
n = (node_t *)node->data;
#ifdef USE_OPENSSL
syslog(LOG_DEBUG, _(" %s at %s cipher %d digest %d maclength %d compression %d options %lx status %04x nexthop %s via %s"),
n->name, n->hostname, n->cipher?n->cipher->nid:0, n->digest?n->digest->type:0, n->maclength, n->compression, n->options,
n->status, n->nexthop?n->nexthop->name:"-", n->via?n->via->name:"-");
#endif
#ifdef USE_GCRYPT
syslog(LOG_DEBUG, _(" %s at %s cipher %d digest %d maclength %d compression %d options %lx status %04x nexthop %s via %s"),
n->name, n->hostname, n->cipher?-1:0, n->digest?-1:0, n->maclength, n->compression, n->options,
n->status, n->nexthop?n->nexthop->name:"-", n->via?n->via->name:"-");
#endif
}
syslog(LOG_DEBUG, _("End of nodes."));
cp
}

View file

@ -1,106 +0,0 @@
/*
node.h -- header for node.c
Copyright (C) 2001-2002 Guus Sliepen <guus@sliepen.warande.net>,
2001-2002 Ivo Timmermans <itimmermans@bigfoot.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: node.h,v 1.2 2002/05/02 11:50:07 zarq Exp $
*/
#ifndef __TINC_NODE_H__
#define __TINC_NODE_H__
#ifdef USE_GCRYPT
#include <gcrypt.h>
#endif
#include <avl_tree.h>
#include "subnet.h"
#include "connection.h"
typedef struct node_status_t {
int active:1; /* 1 if active.. */
int validkey:1; /* 1 if we currently have a valid key for him */
int waitingforkey:1; /* 1 if we already sent out a request */
int visited:1; /* 1 if this node has been visited by one of the graph algorithms */
int reachable:1; /* 1 if this node is reachable in the graph */
int indirect:1; /* 1 if this node is not directly reachable by us */
int unused:26;
} node_status_t;
typedef struct node_t {
char *name; /* name of this node */
long int options; /* options turned on for this node */
sockaddr_t address; /* his real (internet) ip to send UDP packets to */
char *hostname; /* the hostname of its real ip */
struct node_status_t status;
#ifdef USE_OPENSSL
const EVP_CIPHER *cipher; /* Cipher type for UDP packets */
#endif
#ifdef USE_GCRYPT
GCRY_CIPHER_HD cipher; /* Cipher type for UDP packets */
#endif
char *key; /* Cipher key and iv */
int keylength; /* Cipher key and iv length*/
#ifdef USE_OPENSSL
const EVP_MD *digest; /* Digest type for MAC */
#endif
#ifdef USE_GCRYPT
GCRY_MD_HD digest; /* Digest type for MAC */
#endif
int maclength; /* Length of MAC */
int compression; /* Compressionlevel, 0 = no compression */
list_t *queue; /* Queue for packets awaiting to be encrypted */
struct node_t *nexthop; /* nearest node from us to him */
struct node_t *via; /* next hop for UDP packets */
avl_tree_t *subnet_tree; /* Pointer to a tree of subnets belonging to this node */
avl_tree_t *edge_tree; /* Edges with this node as one of the endpoints */
struct connection_t *connection; /* Connection associated with this node (if a direct connection exists) */
unsigned int sent_seqno; /* Sequence number last sent to this node */
unsigned int received_seqno; /* Sequence number last received from this node */
void *data; /* Interface details */
} node_t;
extern struct node_t *myself;
extern avl_tree_t *node_tree;
extern avl_tree_t *node_udp_tree;
extern void init_nodes(void);
extern void exit_nodes(void);
extern node_t *new_node(void);
extern void free_node(node_t *);
extern void node_add(node_t *);
extern void node_del(node_t *);
extern node_t *lookup_node(char *);
extern node_t *lookup_node_udp(sockaddr_t *);
extern void dump_nodes(void);
#endif /* __TINC_NODE_H__ */

View file

@ -25,16 +25,9 @@
* First version (v0.2) released
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <fcntl.h>
#include "system.h"
#ifndef HAVE_MINGW
/* read_pid
*
* Reads the specified pidfile and returns the read pid.
@ -135,4 +128,4 @@ int remove_pid (char *pidfile)
{
return unlink (pidfile);
}
#endif

View file

@ -19,6 +19,7 @@
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*/
#ifndef HAVE_MINGW
/* read_pid
*
* Reads the specified pidfile and returns the read pid.
@ -48,3 +49,4 @@ int write_pid (char *pidfile);
* is returned
*/
int remove_pid (char *pidfile);
#endif

596
lib/rbl.c
View file

@ -1,596 +0,0 @@
/*
rbl.c -- red-black tree + linked list convenience
Copyright (C) 2000 Ivo Timmermans <itimmermans@bigfoot.com>,
2000 Guus Sliepen <guus@sliepen.warande.net>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: rbl.c,v 1.2 2002/04/09 15:26:00 zarq Exp $
*/
#include "config.h"
#include <stdlib.h>
#include <xalloc.h>
#include "rbl.h"
#include <system.h>
/* Allocate a new rbl node */
rbl_t *new_rbl()
{
return (rbl_t *)xmalloc_and_zero(sizeof(rbl_t));
}
/* Free a rbl node */
void free_rbl(rbl_t *rbl)
{
if(rbl->data && rbl->tree->delete)
rbl->tree->delete(rbl->data);
free(rbl);
}
/* Allocate a new rbltree header */
rbltree_t *new_rbltree(rbl_compare_t compare, rbl_action_t delete)
{
rbltree_t *tree;
tree = (rbltree_t *)xmalloc_and_zero(sizeof(rbltree_t));
if(tree)
{
tree->compare = compare;
tree->delete = delete;
}
return tree;
}
/* Free a rbltree header */
void free_rbltree(rbltree_t *tree)
{
free(tree);
}
/* Search closest match in the tree */
rbl_t *rbl_search_closest_rbl(rbltree_t *tree, void *data)
{
rbl_t *rbl, *next;
int result;
next = rbl = tree->top;
while(next)
{
rbl = next;
result = tree->compare(data, rbl->data);
if(result < 0)
next = rbl->left;
else if(result > 0)
next = rbl->right;
else
break;
}
return rbl;
}
/* Search closest match in the tree */
rbl_t *rbl_search_closest_greater_rbl(rbltree_t *tree, void *data)
{
rbl_t *rbl;
rbl = rbl_search_closest_rbl(tree, data);
if(rbl)
{
if(tree->compare(data, rbl->data) > 0)
rbl = rbl->next;
}
return rbl;
}
/* Search closest match in the tree */
rbl_t *rbl_search_closest_smaller_rbl(rbltree_t *tree, void *data)
{
rbl_t *rbl;
rbl = rbl_search_closest_rbl(tree, data);
if(rbl)
{
if(tree->compare(data, rbl->data) < 0)
rbl = rbl->next;
}
return rbl;
}
void *rbl_search_closest(rbltree_t *tree, void *data)
{
rbl_t *rbl;
rbl = rbl_search_closest_rbl(tree, data);
if(rbl)
return rbl->data;
else
return NULL;
}
void *rbl_search_closest_greater(rbltree_t *tree, void *data)
{
rbl_t *rbl;
rbl = rbl_search_closest_greater_rbl(tree, data);
if(rbl)
return rbl->data;
else
return NULL;
}
void *rbl_search_closest_smaller(rbltree_t *tree, void *data)
{
rbl_t *rbl;
rbl = rbl_search_closest_smaller_rbl(tree, data);
if(rbl)
return rbl->data;
else
return NULL;
}
/* Search exact match or return NULL pointer */
rbl_t *rbl_search_rbl(rbltree_t *tree, void *data)
{
rbl_t *rbl;
int result;
rbl = tree->top;
while(rbl)
{
result = tree->compare(data, rbl->data);
if(result < 0)
rbl = rbl->left;
else if(result > 0)
rbl = rbl->right;
else
return rbl;
}
return NULL;
}
void *rbl_search(rbltree_t *tree, void *data)
{
rbl_t *rbl;
rbl = rbl_search_rbl(tree, data);
if(rbl)
return rbl->data;
else
return NULL;
}
/* Red-black tree operations taken from Introduction to Algorithms,
Cormen, Leiserson & Rivest, chapter 14.
*/
void rbl_left_rotate(rbl_t *x)
{
rbl_t *y;
y = x->right;
x->right = y->left;
if(y->left)
y->left->parent = x;
y->parent = x->parent;
if(!x->parent)
x->tree->top = y;
else
if(x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
y->left = x;
x->parent = y;
}
void rbl_right_rotate(rbl_t *y)
{
rbl_t *x;
x = y->left;
y->left = x->right;
if(x->right)
x->right->parent = y;
x->parent = y->parent;
if(!y->parent)
y->tree->top = x;
else
if(y == y->parent->right)
y->parent->right = x;
else
y->parent->left = x;
x->right = y;
y->parent = x;
}
/* Insert a node into the rbl tree */
rbl_t *rbl_insert_rbl(rbltree_t *tree, rbl_t *rbl)
{
rbl_t *closest, *x, *y;
int result;
rbl->tree = tree;
/* Binary tree and linked list insert */
if(tree->top)
{
closest = rbl_search_closest_rbl(tree, rbl->data);
result = tree->compare(rbl->data, closest->data);
if(result < 0)
{
closest->left = rbl;
rbl->prev = closest->prev;
rbl->next = closest;
closest->prev = rbl;
if(rbl->prev)
rbl->prev->next = rbl;
else
tree->head = rbl;
}
else if(result > 0)
{
closest->right = rbl;
rbl->next = closest->next;
rbl->prev = closest;
closest->next = rbl;
if(rbl->next)
rbl->next->prev = rbl;
else
tree->tail = rbl;
}
else
return closest; /* Ofcourse, we cannot add two identical things */
rbl->parent = closest;
}
else
{
tree->top = rbl;
tree->head = rbl;
tree->tail = rbl;
}
/* Red-black part of insert */
x = rbl;
x->color = RBL_RED;
while(x != tree->top && x->parent->color == RBL_RED)
{
if(x->parent == x->parent->parent->left)
{
y = x->parent->parent->right;
if(y && y->color == RBL_RED)
{
x->parent->color = RBL_BLACK;
y->color = RBL_BLACK;
x->parent->parent->color = RBL_RED;
x = x->parent->parent;
}
else
{
if(x == x->parent->right)
{
x = x->parent;
rbl_left_rotate(x);
}
x->parent->color = RBL_BLACK;
x->parent->parent->color = RBL_RED;
rbl_right_rotate(x->parent->parent);
}
}
else
{
y = x->parent->parent->left;
if(y && y->color == RBL_RED)
{
x->parent->color = RBL_BLACK;
y->color = RBL_BLACK;
x->parent->parent->color = RBL_RED;
x = x->parent->parent;
}
else
{
if(x == x->parent->left)
{
x = x->parent;
rbl_right_rotate(x);
}
x->parent->color = RBL_BLACK;
x->parent->parent->color = RBL_RED;
rbl_left_rotate(x->parent->parent);
}
}
}
tree->top->color = RBL_BLACK;
return rbl;
}
/* Create a new node and insert it into the tree */
rbl_t *rbl_insert(rbltree_t *tree, void *data)
{
rbl_t *rbl;
rbl = new_rbl();
rbl->data = data;
if(rbl_insert_rbl(tree, rbl) == rbl)
return rbl;
else
{
free_rbl(rbl);
return NULL;
}
}
/* Restore red-black property after violation due to a deletion */
void rbl_delete_fixup(rbl_t *x)
{
rbl_t *w;
while(x != x->tree->top && x->color == RBL_BLACK)
{
if(x == x->parent->left)
{
w = x->parent->right;
if(w->color == RBL_RED)
{
w->color = RBL_BLACK;
x->parent->color = RBL_RED;
rbl_left_rotate(x->parent);
w = x->parent->right;
}
if(w->left->color == RBL_BLACK && w->right->color == RBL_BLACK)
{
w->color = RBL_RED;
x = x->parent;
}
else
{
if(w->right->color == RBL_BLACK)
{
w->left->color = RBL_BLACK;
w->color = RBL_RED;
rbl_right_rotate(w);
w = x->parent->right;
}
w->color = x->parent->color;
x->parent->color = RBL_BLACK;
w->right->color = RBL_BLACK;
rbl_left_rotate(x->parent);
x = x->tree->top;
}
}
else
{
w = x->parent->left;
if(w->color == RBL_RED)
{
w->color = RBL_BLACK;
x->parent->color = RBL_RED;
rbl_right_rotate(x->parent);
w = x->parent->left;
}
if(w->right->color == RBL_BLACK && w->left->color == RBL_BLACK)
{
w->color = RBL_RED;
x = x->parent;
}
else
{
if(w->left->color == RBL_BLACK)
{
w->right->color = RBL_BLACK;
w->color = RBL_RED;
rbl_left_rotate(w);
w = x->parent->left;
}
w->color = x->parent->color;
x->parent->color = RBL_BLACK;
w->left->color = RBL_BLACK;
rbl_right_rotate(x->parent);
x = x->tree->top;
}
}
}
x->color = RBL_BLACK;
}
/* Unlink node from the tree, but keep the node intact. */
rbl_t *rbl_unlink_rbl(rbl_t *rbl)
{
rbl_t *x, *y;
/* Binary tree delete */
if(rbl->left && rbl->right)
y = rbl->next;
else
y = rbl;
if(y->left)
x = y->left;
else
x = y->right;
if(x)
x->parent = y->parent;
if(!y->parent)
rbl->tree->top = x;
else
if(y == y->parent->left)
y->parent->left = x;
else
y->parent->right = x;
if(y != rbl)
{
y->left = rbl->left;
y->right = rbl->right;
y->parent = rbl->parent;
if(rbl == rbl->parent->left)
rbl->parent->left = y;
else
rbl->parent->right = y;
}
/* Linked list delete */
if(rbl->prev)
rbl->prev->next = rbl->next;
else
rbl->tree->head = rbl->next;
if(rbl->next)
rbl->next->prev = rbl->prev;
else
rbl->tree->tail = rbl->prev;
/* Red-black part of delete */
if(y->color == RBL_BLACK && x)
rbl_delete_fixup(x);
return rbl;
}
/* Search node in tree and unlink it */
rbl_t *rbl_unlink(rbltree_t *tree, void *data)
{
rbl_t *rbl;
rbl = rbl_search_rbl(tree, data);
if(rbl)
rbl_unlink_rbl(rbl);
return rbl;
}
/* Unlink node and free it */
void rbl_delete_rbl(rbl_t *rbl)
{
rbl_unlink_rbl(rbl);
free_rbl(rbl);
}
/* Search node in tree, unlink and free it */
void rbl_delete(rbltree_t *tree, void *data)
{
rbl_t *rbl;
rbl = rbl_unlink(tree, data);
if(rbl)
free_rbl(rbl);
}
/* Optimized unlinking for a complete tree */
void rbl_unlink_rbltree(rbltree_t *tree)
{
rbl_t *rbl, *next;
for(rbl = tree->head; rbl; rbl = next)
{
next = rbl->next;
rbl->tree = NULL;
rbl->parent = NULL;
rbl->left = NULL;
rbl->right = NULL;
rbl->prev = NULL;
rbl->next = NULL;
}
tree->top = NULL;
tree->head = NULL;
tree->tail = NULL;
}
/* Optimized deletion for a complete tree */
void rbl_delete_rbltree(rbltree_t *tree)
{
rbl_t *rbl, *next;
for(rbl = tree->head; rbl; rbl = next)
{
next = rbl->next;
free_rbl(rbl);
}
tree->top = NULL;
tree->head = NULL;
tree->tail = NULL;
}
/* Do action for each list entry (in order)
Deletion of entry for which action is called is allowed.
*/
void rbl_foreach(rbltree_t *tree, rbl_action_t action)
{
rbl_t *rbl, *next;
for(rbl = tree->head; rbl; rbl = next)
{
next = rbl->next;
action(rbl->data);
}
}
void rbl_foreach_rbl(rbltree_t *tree, rbl_action_rbl_t action)
{
rbl_t *rbl, *next;
for(rbl = tree->head; rbl; rbl = next)
{
next = rbl->next;
action(rbl);
}
}

104
lib/rbl.h
View file

@ -1,104 +0,0 @@
/*
rbl.h -- header file for rbl.c
Copyright (C) 2000 Ivo Timmermans <itimmermans@bigfoot.com>,
2000 Guus Sliepen <guus@sliepen.warande.net>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: rbl.h,v 1.2 2002/04/09 15:26:00 zarq Exp $
*/
#ifndef __RBL_H__
#define __RBL_H__
#define RBL_FOREACH(tree,rbl) for(rbl = tree->head; rbl; rbl = rbl->next)
typedef struct rbl_t
{
/* 'red-black tree' part */
struct rbltree_t *tree;
int color;
struct rbl_t *parent;
struct rbl_t *left;
struct rbl_t *right;
/* 'linked list' part */
struct rbl_t *prev;
struct rbl_t *next;
/* payload */
void *data;
} rbl_t;
typedef int (*rbl_compare_t) (const void *, const void *);
typedef void (*rbl_action_t) (const void *);
typedef void (*rbl_action_rbl_t) (const struct rbl_t *);
typedef struct rbltree_t
{
/* callback functions */
rbl_compare_t compare;
rbl_action_t delete;
/* tree part */
struct rbl_t *top;
/* linked list */
struct rbl_t *head;
struct rbl_t *tail;
} rbltree_t;
enum color
{
RBL_RED,
RBL_BLACK
} color;
extern rbltree_t *new_rbltree(rbl_compare_t, rbl_action_t);
extern void free_rbltree(rbltree_t *);
extern rbl_t *new_rbl(void);
extern void free_rbl(rbl_t *);
extern void *rbl_search(rbltree_t *, void *);
extern void *rbl_search_closest(rbltree_t *, void *);
extern void *rbl_search_closest_greater(rbltree_t *, void *);
extern void *rbl_search_closest_smaller(rbltree_t *, void *);
extern rbl_t *rbl_search_rbl(rbltree_t *, void *);
extern rbl_t *rbl_search_closest_rbl(rbltree_t *, void *);
extern rbl_t *rbl_search_closest_greater_rbl(rbltree_t *, void *);
extern rbl_t *rbl_search_closest_smaller_rbl(rbltree_t *, void *);
extern rbl_t *rbl_insert(rbltree_t *, void *);
extern rbl_t *rbl_unlink(rbltree_t *, void *);
extern void rbl_delete(rbltree_t *, void *);
extern rbl_t *rbl_insert_rbl(rbltree_t *, rbl_t *);
extern rbl_t *rbl_unlink_rbl(rbl_t *);
extern void rbl_delete_rbl(rbl_t *);
extern void rbl_unlink_rbltree(rbltree_t *);
extern void rbl_delete_rbltree(rbltree_t *);
extern void rbl_foreach(rbltree_t *, rbl_action_t);
extern void rbl_foreach_rbl(rbltree_t *, rbl_action_rbl_t);
#endif /* __RBL_H__ */

View file

@ -1,399 +0,0 @@
/*
subnet.c -- handle subnet lookups and lists
Copyright (C) 2000-2002 Guus Sliepen <guus@sliepen.warande.net>,
2000-2002 Ivo Timmermans <itimmermans@bigfoot.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: subnet.c,v 1.1 2002/04/28 12:46:26 zarq Exp $
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <hooks.h>
#include <utils.h>
#include <xalloc.h>
#include <avl_tree.h>
#include "conf.h"
#include "net.h"
#include "node.h"
#include "subnet.h"
#include "netutl.h"
#include "logging.h"
#include "system.h"
/* lists type of subnet */
avl_tree_t *subnet_tree;
/* Subnet comparison */
int subnet_compare_mac(subnet_t *a, subnet_t *b)
{
cp
return memcmp(&a->net.mac.address, &b->net.mac.address, sizeof(mac_t));
}
int subnet_compare_ipv4(subnet_t *a, subnet_t *b)
{
int result;
cp
result = memcmp(&a->net.ipv4.address, &b->net.ipv4.address, sizeof(ipv4_t));
if(result)
return result;
return a->net.ipv4.prefixlength - b->net.ipv4.prefixlength;
}
int subnet_compare_ipv6(subnet_t *a, subnet_t *b)
{
int result;
cp
result = memcmp(&a->net.ipv6.address, &b->net.ipv6.address, sizeof(ipv6_t));
if(result)
return result;
return a->net.ipv6.prefixlength - b->net.ipv6.prefixlength;
}
int subnet_compare(subnet_t *a, subnet_t *b)
{
int result;
cp
result = a->type - b->type;
if(result)
return result;
switch(a->type)
{
case SUBNET_MAC:
return subnet_compare_mac(a, b);
case SUBNET_IPV4:
return subnet_compare_ipv4(a, b);
case SUBNET_IPV6:
return subnet_compare_ipv6(a, b);
default:
syslog(LOG_ERR, _("subnet_compare() was called with unknown subnet type %d, exitting!"), a->type);
cp_trace();
exit(0);
}
return 0;
}
/* Initialising trees */
void init_subnets(void)
{
cp
subnet_tree = avl_alloc_tree((avl_compare_t)subnet_compare, (avl_action_t)free_subnet);
cp
}
void exit_subnets(void)
{
cp
avl_delete_tree(subnet_tree);
cp
}
avl_tree_t *new_subnet_tree(void)
{
cp
return avl_alloc_tree((avl_compare_t)subnet_compare, NULL);
cp
}
void free_subnet_tree(avl_tree_t *subnet_tree)
{
cp
avl_delete_tree(subnet_tree);
cp
}
/* Allocating and freeing space for subnets */
subnet_t *new_subnet(void)
{
cp
return (subnet_t *)xmalloc(sizeof(subnet_t));
}
void free_subnet(subnet_t *subnet)
{
cp
free(subnet);
}
/* Adding and removing subnets */
void subnet_add(node_t *n, subnet_t *subnet)
{
cp
subnet->owner = n;
avl_insert(subnet_tree, subnet);
cp
avl_insert(n->subnet_tree, subnet);
run_hooks("subnet-add", subnet);
cp
}
void subnet_del(node_t *n, subnet_t *subnet)
{
cp
avl_delete(n->subnet_tree, subnet);
cp
avl_delete(subnet_tree, subnet);
run_hooks("subnet-del", subnet);
cp
}
/* Ascii representation of subnets */
subnet_t *str2net(char *subnetstr)
{
int i, l;
subnet_t *subnet;
unsigned short int x[8];
cp
subnet = new_subnet();
cp
if(sscanf(subnetstr, "%hu.%hu.%hu.%hu/%d",
&x[0], &x[1], &x[2], &x[3],
&l) == 5)
{
subnet->type = SUBNET_IPV4;
subnet->net.ipv4.prefixlength = l;
for(i = 0; i < 4; i++)
subnet->net.ipv4.address.x[i] = x[i];
return subnet;
}
if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d",
&x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
&l) == 9)
{
subnet->type = SUBNET_IPV6;
subnet->net.ipv6.prefixlength = l;
for(i = 0; i < 8; i++)
subnet->net.ipv6.address.x[i] = htons(x[i]);
return subnet;
}
if(sscanf(subnetstr, "%hu.%hu.%hu.%hu",
&x[0], &x[1], &x[2], &x[3]) == 4)
{
subnet->type = SUBNET_IPV4;
subnet->net.ipv4.prefixlength = 32;
for(i = 0; i < 4; i++)
subnet->net.ipv4.address.x[i] = x[i];
return subnet;
}
if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
&x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7]) == 8)
{
subnet->type = SUBNET_IPV6;
subnet->net.ipv6.prefixlength = 128;
for(i = 0; i < 8; i++)
subnet->net.ipv6.address.x[i] = htons(x[i]);
return subnet;
}
if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx",
&x[0], &x[1], &x[2], &x[3], &x[4], &x[5]) == 6)
{
subnet->type = SUBNET_MAC;
for(i = 0; i < 6; i++)
subnet->net.mac.address.x[i] = x[i];
return subnet;
}
free(subnet);
return NULL;
}
char *net2str(subnet_t *subnet)
{
char *netstr;
cp
switch(subnet->type)
{
case SUBNET_MAC:
asprintf(&netstr, "%hx:%hx:%hx:%hx:%hx:%hx",
subnet->net.mac.address.x[0],
subnet->net.mac.address.x[1],
subnet->net.mac.address.x[2],
subnet->net.mac.address.x[3],
subnet->net.mac.address.x[4],
subnet->net.mac.address.x[5]);
break;
case SUBNET_IPV4:
asprintf(&netstr, "%hu.%hu.%hu.%hu/%d",
subnet->net.ipv4.address.x[0],
subnet->net.ipv4.address.x[1],
subnet->net.ipv4.address.x[2],
subnet->net.ipv4.address.x[3],
subnet->net.ipv4.prefixlength);
break;
case SUBNET_IPV6:
asprintf(&netstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d",
ntohs(subnet->net.ipv6.address.x[0]),
ntohs(subnet->net.ipv6.address.x[1]),
ntohs(subnet->net.ipv6.address.x[2]),
ntohs(subnet->net.ipv6.address.x[3]),
ntohs(subnet->net.ipv6.address.x[4]),
ntohs(subnet->net.ipv6.address.x[5]),
ntohs(subnet->net.ipv6.address.x[6]),
ntohs(subnet->net.ipv6.address.x[7]),
subnet->net.ipv6.prefixlength);
break;
default:
syslog(LOG_ERR, _("net2str() was called with unknown subnet type %d, exitting!"), subnet->type);
cp_trace();
exit(0);
}
cp
return netstr;
}
/* Subnet lookup routines */
subnet_t *lookup_subnet(node_t *owner, subnet_t *subnet)
{
cp
return avl_search(owner->subnet_tree, subnet);
}
subnet_t *lookup_subnet_mac(mac_t *address)
{
subnet_t subnet, *p;
cp
subnet.type = SUBNET_MAC;
memcpy(&subnet.net.mac.address, address, sizeof(mac_t));
p = (subnet_t *)avl_search(subnet_tree, &subnet);
cp
return p;
}
subnet_t *lookup_subnet_ipv4(ipv4_t *address)
{
subnet_t subnet, *p;
cp
subnet.type = SUBNET_IPV4;
memcpy(&subnet.net.ipv4.address, address, sizeof(ipv4_t));
subnet.net.ipv4.prefixlength = 32;
do
{
/* Go find subnet */
p = (subnet_t *)avl_search_closest_smaller(subnet_tree, &subnet);
/* Check if the found subnet REALLY matches */
cp
if(p)
{
if(p->type != SUBNET_IPV4)
{
p = NULL;
break;
}
if (!maskcmp((char *)address, (char *)&p->net.ipv4.address, p->net.ipv4.prefixlength, sizeof(ipv4_t)))
break;
else
{
/* Otherwise, see if there is a bigger enclosing subnet */
subnet.net.ipv4.prefixlength = p->net.ipv4.prefixlength - 1;
maskcpy((char *)&subnet.net.ipv4.address, (char *)&p->net.ipv4.address, subnet.net.ipv4.prefixlength, sizeof(ipv4_t));
}
}
} while (p);
cp
return p;
}
subnet_t *lookup_subnet_ipv6(ipv6_t *address)
{
subnet_t subnet, *p;
cp
subnet.type = SUBNET_IPV6;
memcpy(&subnet.net.ipv6.address, address, sizeof(ipv6_t));
subnet.net.ipv6.prefixlength = 128;
do
{
/* Go find subnet */
p = (subnet_t *)avl_search_closest_smaller(subnet_tree, &subnet);
/* Check if the found subnet REALLY matches */
cp
if(p)
{
if(p->type != SUBNET_IPV6)
return NULL;
if (!maskcmp((char *)address, (char *)&p->net.ipv6.address, p->net.ipv6.prefixlength, sizeof(ipv6_t)))
break;
else
{
/* Otherwise, see if there is a bigger enclosing subnet */
subnet.net.ipv6.prefixlength = p->net.ipv6.prefixlength - 1;
maskcpy((char *)&subnet.net.ipv6.address, (char *)&p->net.ipv6.address, subnet.net.ipv6.prefixlength, sizeof(ipv6_t));
}
}
} while (p);
cp
return p;
}
void dump_subnets(void)
{
char *netstr;
subnet_t *subnet;
avl_node_t *node;
cp
syslog(LOG_DEBUG, _("Subnet list:"));
for(node = subnet_tree->head; node; node = node->next)
{
subnet = (subnet_t *)node->data;
netstr = net2str(subnet);
syslog(LOG_DEBUG, _(" %s owner %s"), netstr, subnet->owner->name);
free(netstr);
}
syslog(LOG_DEBUG, _("End of subnet list."));
cp
}

View file

@ -1,90 +0,0 @@
/*
subnet.h -- header for subnet.c
Copyright (C) 2000,2001 Guus Sliepen <guus@sliepen.warande.net>,
2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: subnet.h,v 1.1 2002/04/28 12:46:26 zarq Exp $
*/
#ifndef __TINC_SUBNET_H__
#define __TINC_SUBNET_H__
#include "net.h"
enum
{
SUBNET_MAC = 0,
SUBNET_IPV4,
SUBNET_IPV6,
SUBNET_TYPES /* Guardian */
};
typedef struct subnet_mac_t
{
mac_t address;
time_t lastseen;
} subnet_mac_t;
typedef struct subnet_ipv4_t
{
ipv4_t address;
int prefixlength;
} subnet_ipv4_t;
typedef struct subnet_ipv6_t
{
ipv6_t address;
int prefixlength;
} subnet_ipv6_t;
#include "node.h"
typedef struct subnet_t {
struct node_t *owner; /* the owner of this subnet */
struct node_t *uplink; /* the uplink which we should send packets to for this subnet */
int type; /* subnet type (IPv4? IPv6? MAC? something even weirder?) */
/* And now for the actual subnet: */
union net
{
subnet_mac_t mac;
subnet_ipv4_t ipv4;
subnet_ipv6_t ipv6;
} net;
void *data; /* Interface details */
} subnet_t;
extern subnet_t *new_subnet(void);
extern void free_subnet(subnet_t *);
extern void init_subnets(void);
extern void exit_subnets(void);
extern avl_tree_t *new_subnet_tree(void);
extern void free_subnet_tree(avl_tree_t *);
extern void subnet_add(struct node_t *, subnet_t *);
extern void subnet_del(struct node_t *, subnet_t *);
extern char *net2str(subnet_t *);
extern subnet_t *str2net(char *);
extern subnet_t *lookup_subnet(struct node_t *, subnet_t *);
extern subnet_t *lookup_subnet_mac(mac_t *);
extern subnet_t *lookup_subnet_ipv4(ipv4_t *);
extern subnet_t *lookup_subnet_ipv6(ipv6_t *);
extern void dump_subnets(void);
#endif /* __TINC_SUBNET_H__ */

View file

@ -1,7 +1,7 @@
/*
utils.c -- gathering of some stupid small functions
Copyright (C) 1999-2001 Ivo Timmermans <zarq@iname.com>
2000,2001 Guus Sliepen <guus@sliepen.warande.net>
Copyright (C) 1999-2003 Ivo Timmermans <zarq@iname.com>
2000-2003 Guus Sliepen <guus@sliepen.eu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -18,15 +18,10 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <sys/types.h>
#include <ctype.h>
#include <string.h>
#include "system.h"
#include "config.h"
#include <utils.h>
#include <syslog.h>
#include <xalloc.h>
#include "../src/logger.h"
#include "utils.h"
#ifdef ENABLE_TRACING
volatile int (cp_line[]) = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
@ -38,50 +33,70 @@ char *hexadecimals = "0123456789ABCDEF";
int charhex2bin(char c)
{
if(isdigit(c))
return c - '0';
else
return toupper(c) - 'A' + 10;
if(isdigit(c))
return c - '0';
else
return toupper(c) - 'A' + 10;
}
void hex2bin(char *src, char *dst, int length)
{
int i;
for(i=0; i<length; i++)
dst[i] = charhex2bin(src[i*2])*16 + charhex2bin(src[i*2+1]);
int i;
for(i = 0; i < length; i++)
dst[i] = charhex2bin(src[i * 2]) * 16 + charhex2bin(src[i * 2 + 1]);
}
void bin2hex(char *src, char *dst, int length)
{
int i;
for(i=length-1; i>=0; i--)
{
dst[i*2+1] = hexadecimals[(unsigned char)src[i] & 15];
dst[i*2] = hexadecimals[(unsigned char)src[i]>>4];
}
int i;
for(i = length - 1; i >= 0; i--) {
dst[i * 2 + 1] = hexadecimals[(unsigned char) src[i] & 15];
dst[i * 2] = hexadecimals[(unsigned char) src[i] >> 4];
}
}
#ifdef ENABLE_TRACING
void cp_trace()
{
syslog(LOG_DEBUG, "Checkpoint trace: %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d...",
cp_file[(cp_index+15)%16], cp_line[(cp_index+15)%16],
cp_file[(cp_index+14)%16], cp_line[(cp_index+14)%16],
cp_file[(cp_index+13)%16], cp_line[(cp_index+13)%16],
cp_file[(cp_index+12)%16], cp_line[(cp_index+12)%16],
cp_file[(cp_index+11)%16], cp_line[(cp_index+11)%16],
cp_file[(cp_index+10)%16], cp_line[(cp_index+10)%16],
cp_file[(cp_index+9)%16], cp_line[(cp_index+9)%16],
cp_file[(cp_index+8)%16], cp_line[(cp_index+8)%16],
cp_file[(cp_index+7)%16], cp_line[(cp_index+7)%16],
cp_file[(cp_index+6)%16], cp_line[(cp_index+6)%16],
cp_file[(cp_index+5)%16], cp_line[(cp_index+5)%16],
cp_file[(cp_index+4)%16], cp_line[(cp_index+4)%16],
cp_file[(cp_index+3)%16], cp_line[(cp_index+3)%16],
cp_file[(cp_index+2)%16], cp_line[(cp_index+2)%16],
cp_file[(cp_index+1)%16], cp_line[(cp_index+1)%16],
cp_file[cp_index], cp_line[cp_index]
);
logger(LOG_DEBUG, "Checkpoint trace: %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d...",
cp_file[(cp_index + 15) % 16], cp_line[(cp_index + 15) % 16],
cp_file[(cp_index + 14) % 16], cp_line[(cp_index + 14) % 16],
cp_file[(cp_index + 13) % 16], cp_line[(cp_index + 13) % 16],
cp_file[(cp_index + 12) % 16], cp_line[(cp_index + 12) % 16],
cp_file[(cp_index + 11) % 16], cp_line[(cp_index + 11) % 16],
cp_file[(cp_index + 10) % 16], cp_line[(cp_index + 10) % 16],
cp_file[(cp_index + 9) % 16], cp_line[(cp_index + 9) % 16],
cp_file[(cp_index + 8) % 16], cp_line[(cp_index + 8) % 16],
cp_file[(cp_index + 7) % 16], cp_line[(cp_index + 7) % 16],
cp_file[(cp_index + 6) % 16], cp_line[(cp_index + 6) % 16],
cp_file[(cp_index + 5) % 16], cp_line[(cp_index + 5) % 16],
cp_file[(cp_index + 4) % 16], cp_line[(cp_index + 4) % 16],
cp_file[(cp_index + 3) % 16], cp_line[(cp_index + 3) % 16],
cp_file[(cp_index + 2) % 16], cp_line[(cp_index + 2) % 16],
cp_file[(cp_index + 1) % 16], cp_line[(cp_index + 1) % 16],
cp_file[cp_index], cp_line[cp_index]
);
}
#endif
#if defined(HAVE_MINGW) || defined(HAVE_CYGWIN)
#ifdef HAVE_CYGWIN
#include <w32api/windows.h>
#endif
char *winerror(int err) {
static char buf[1024], *newline;
if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, sizeof(buf), NULL)) {
strncpy(buf, _("(unable to format errormessage)"), sizeof(buf));
};
if((newline = strchr(buf, '\r')))
*newline = '\0';
return buf;
}
#endif

View file

@ -1,7 +1,7 @@
/*
utils.h -- header file for utils.c
Copyright (C) 1999-2002 Ivo Timmermans <ivo@o2w.nl>
2000-2002 Guus Sliepen <guus@sliepen.warande.net>
Copyright (C) 1999-2003 Ivo Timmermans <zarq@iname.com>
2000-2003 Guus Sliepen <guus@sliepen.eu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -21,25 +21,26 @@
#ifndef __TINC_UTILS_H__
#define __TINC_UTILS_H__
#include <ctype.h>
#define min(a,b) (((a)<(b))?(a):(b))
#ifdef ENABLE_TRACING
extern volatile int cp_line[];
extern volatile char *cp_file[];
extern volatile int cp_index;
extern void cp_trace(void);
#define cp { cp_line[cp_index] = __LINE__; cp_file[cp_index] = __FILE__; cp_index++; cp_index %= 16; }
#define ecp { fprintf(stderr, "Explicit checkpoint in %s line %d\n", __FILE__, __LINE__); }
#define cp() { cp_line[cp_index] = __LINE__; cp_file[cp_index] = __FILE__; cp_index++; cp_index %= 16; }
#define ecp() { fprintf(stderr, "Explicit checkpoint in %s line %d\n", __FILE__, __LINE__); }
#else
#define cp
#define ecp
#define cp_trace()
#define cp()
#define ecp()
#define cp_trace()
#endif
extern void hex2bin(char *src, char *dst, int length);
extern void bin2hex(char *src, char *dst, int length);
#endif /* __TINC_UTILS_H__ */
#ifdef HAVE_MINGW
extern char *winerror(int);
#define strerror(x) ((x)>0?strerror(x):winerror(GetLastError()))
#endif
#endif /* __TINC_UTILS_H__ */

View file

@ -18,9 +18,9 @@ extern char *const xalloc_msg_memory_exhausted;
/* FIXME: describe */
extern void (*xalloc_fail_func) ();
void *xmalloc PARAMS ((size_t n));
void *xmalloc_and_zero PARAMS ((size_t n));
void *xmalloc PARAMS ((size_t n)) __attribute__ ((__malloc__));
void *xmalloc_and_zero PARAMS ((size_t n)) __attribute__ ((__malloc__));
void *xcalloc PARAMS ((size_t n, size_t s));
void *xrealloc PARAMS ((void *p, size_t n));
void *xrealloc PARAMS ((void *p, size_t n)) __attribute__ ((__malloc__));
char *xstrdup PARAMS ((const char *s));
char *xstrdup PARAMS ((const char *s)) __attribute__ ((__malloc__));

View file

@ -32,15 +32,7 @@ void *realloc ();
void free ();
#endif
#if ENABLE_NLS
# include <libintl.h>
# define _(Text) gettext (Text)
#else
# define textdomain(Domain)
# define _(Text) Text
#endif
#define N_(Text) Text
#include "gettext.h"
#include "xalloc.h"
#ifndef EXIT_FAILURE

25
m4/attribute.m4 Normal file
View file

@ -0,0 +1,25 @@
dnl Check to find out whether function attributes are supported.
dnl If they are not, #define them to be nothing.
AC_DEFUN(tinc_ATTRIBUTE,
[
AC_CACHE_CHECK([for working $1 attribute], tinc_cv_attribute_$1,
[
tempcflags="$CFLAGS"
CFLAGS="$CFLAGS -Wall -Werror"
AC_COMPILE_IFELSE(
[AC_LANG_SOURCE(
[void test(void) __attribute__ (($1));
void test(void) { return; }
],
)],
[tinc_cv_attribute_$1=yes],
[tinc_cv_attribute_$1=no]
)
CFLAGS="$tempcflags"
])
if test ${tinc_cv_attribute_$1} = no; then
AC_DEFINE([$1], [], [Defined if the $1 attribute is not supported.])
fi
])

39
m4/lzo.m4 Normal file
View file

@ -0,0 +1,39 @@
dnl Check to find the lzo headers/libraries
AC_DEFUN(tinc_LZO,
[
tinc_ac_save_CPPFLAGS="$CPPFLAGS"
AC_ARG_WITH(lzo,
AC_HELP_STRING([--with-lzo=DIR], [lzo base directory, or:]),
[lzo="$withval"
CFLAGS="$CFLAGS -I$withval/include"
CPPFLAGS="$CPPFLAGS -I$withval/include"
LIBS="$LIBS -L$withval/lib"]
)
AC_ARG_WITH(lzo-include,
AC_HELP_STRING([--with-lzo-include=DIR], [lzo headers directory]),
[lzo_include="$withval"
CFLAGS="$CFLAGS -I$withval"
CPPFLAGS="$CPPFLAGS -I$withval"]
)
AC_ARG_WITH(lzo-lib,
AC_HELP_STRING([--with-lzo-lib=DIR], [lzo library directory]),
[lzo_lib="$withval"
LIBS="$LIBS -L$withval"]
)
AC_CHECK_HEADERS(lzo1x.h,
[],
[AC_MSG_ERROR("lzo header files not found."); break]
)
CPPFLAGS="$tinc_ac_save_CPPFLAGS"
AC_CHECK_LIB(lzo, lzo1x_1_compress,
[LIBS="$LIBS -llzo"],
[AC_MSG_ERROR("lzo libraries not found.")]
)
])

View file

@ -20,8 +20,7 @@ AC_DEFUN(jm_FUNC_MALLOC,
fi
dnl xmalloc.c requires that this symbol be defined so it doesn't
dnl mistakenly use a broken malloc -- as it might if this test were omitted.
ac_kludge=HAVE_DONE_WORKING_MALLOC_CHECK
AC_DEFINE_UNQUOTED($ac_kludge)
AC_DEFINE(HAVE_DONE_WORKING_MALLOC_CHECK, 1, [Needed for xmalloc.c])
AC_CACHE_CHECK([for working malloc], jm_cv_func_working_malloc,
[AC_TRY_RUN([
@ -38,7 +37,8 @@ AC_DEFUN(jm_FUNC_MALLOC,
jm_cv_func_working_malloc=no)
])
if test $jm_cv_func_working_malloc = no; then
LIBOBJS="$LIBOBJS malloc.o"
AC_DEFINE_UNQUOTED(malloc, rpl_malloc)
dnl This was: LIBOBJS="$LIBOBJS malloc.$ac_objext"
AC_LIBOBJ([malloc])
AC_DEFINE(malloc, rpl_malloc, [Replacement malloc()])
fi
])

View file

@ -4,48 +4,63 @@ AC_DEFUN(tinc_OPENSSL,
[
tinc_ac_save_CPPFLAGS="$CPPFLAGS"
AC_ARG_WITH(openssl,
AC_HELP_STRING([--with-openssl=DIR], [OpenSSL base directory, or:]),
[openssl="$withval"
CFLAGS="$CFLAGS -I$withval/include"
CPPFLAGS="$CPPFLAGS -I$withval/include"
LIBS="$LIBS -L$withval/lib"]
)
AC_ARG_WITH(openssl-include,
[ --with-openssl-include=DIR OpenSSL headers directory (without trailing /openssl)],
AC_HELP_STRING([--with-openssl-include=DIR], [OpenSSL headers directory (without trailing /openssl)]),
[openssl_include="$withval"
CFLAGS="$CFLAGS -I$withval"
CPPFLAGS="$CPPFLAGS -I$withval"]
)
AC_ARG_WITH(openssl-lib,
[ --with-openssl-lib=DIR OpenSSL library directory],
AC_HELP_STRING([--with-openssl-lib=DIR], [OpenSSL library directory]),
[openssl_lib="$withval"
LIBS="$LIBS -L$withval"]
)
AC_CHECK_HEADERS(openssl/evp.h openssl/rsa.h openssl/rand.h openssl/err.h openssl/sha.h openssl/pem.h,
[],
[AC_MSG_ERROR("OpenSSL header files not found."); break]
[AC_MSG_ERROR([OpenSSL header files not found.]); break]
)
CPPFLAGS="$tinc_ac_save_CPPFLAGS"
AC_CHECK_LIB(crypto, SHA1_version,
[LIBS="$LIBS -lcrypto"],
[AC_MSG_ERROR("OpenSSL libraries not found.")]
)
AC_CHECK_FUNCS(RAND_pseudo_bytes)
AC_CHECK_FUNC(OpenSSL_add_all_algorithms,
[],
AC_CHECK_FUNC(SSLeay_add_all_algorithms,
[AC_DEFINE(HAVE_SSLEAY_ADD_ALL_ALGORITHMS)],
[AC_MSG_ERROR("Missing required OpenSSL functionality!")]
case $host_os in
*mingw*)
AC_CHECK_LIB(crypto, SHA1_version,
[LIBS="$LIBS -lcrypto -lgdi32"],
[AC_MSG_ERROR([OpenSSL libraries not found.])]
)
)
AC_CHECK_FUNC(dlopen,
[],
AC_CHECK_LIB(dl, dlopen,
[LIBS="$LIBS -ldl"],
[AC_MSG_ERROR("OpenSSL depends on libdl.")]
;;
*)
AC_CHECK_LIB(crypto, SHA1_version,
[LIBS="$LIBS -lcrypto"],
[AC_MSG_ERROR([OpenSSL libraries not found.])]
)
AC_CHECK_FUNC(dlopen,
[],
[AC_CHECK_LIB(dl, dlopen,
[LIBS="$LIBS -ldl"],
[AC_MSG_ERROR([OpenSSL depends on libdl.]); break]
)]
)
;;
esac
AC_CHECK_FUNCS([RAND_pseudo_bytes EVP_EncryptInit_ex], ,
[AC_MSG_ERROR([Missing OpenSSL functionality, make sure you have installed the latest version.]); break],
)
found_openssl=1
AC_CHECK_DECL([OpenSSL_add_all_algorithms], ,
[AC_MSG_ERROR([Missing OpenSSL functionality, make sure you have installed the latest version.]); break],
[#include <openssl/evp.h>]
)
])

View file

@ -1,39 +0,0 @@
#serial 1
dnl From Jim Meyering.
dnl Find a new-enough version of Perl.
dnl
AC_DEFUN(jm_PERL,
[
dnl FIXME: don't hard-code 5.003
dnl FIXME: should we cache the result?
AC_MSG_CHECKING([for perl5.003 or newer])
if test "${PERL+set}" = set; then
# `PERL' is set in the user's environment.
candidate_perl_names="$PERL"
perl_specified=yes
else
candidate_perl_names='perl perl5'
perl_specified=no
fi
found=no
AC_SUBST(PERL)
PERL="$missing_dir/missing perl"
for perl in $candidate_perl_names; do
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
if ( $perl -e 'require 5.003' ) > /dev/null 2>&1; then
PERL=$perl
found=yes
break
fi
done
AC_MSG_RESULT($found)
test $found = no && AC_MSG_WARN([
*** You don't seem to have perl5.003 or newer installed.
*** Because of that, you may be unable to regenerate certain files
*** if you modify the sources from which they are derived.] )
])

View file

@ -20,8 +20,7 @@ AC_DEFUN(jm_FUNC_REALLOC,
fi
dnl xmalloc.c requires that this symbol be defined so it doesn't
dnl mistakenly use a broken realloc -- as it might if this test were omitted.
ac_kludge=HAVE_DONE_WORKING_REALLOC_CHECK
AC_DEFINE_UNQUOTED($ac_kludge)
AC_DEFINE(HAVE_DONE_WORKING_REALLOC_CHECK, 1, [Needed for xmalloc.c])
AC_CACHE_CHECK([for working realloc], jm_cv_func_working_realloc,
[AC_TRY_RUN([
@ -38,7 +37,8 @@ AC_DEFUN(jm_FUNC_REALLOC,
jm_cv_func_working_realloc=no)
])
if test $jm_cv_func_working_realloc = no; then
LIBOBJS="$LIBOBJS realloc.o"
AC_DEFINE_UNQUOTED(realloc, rpl_realloc)
dnl This was: LIBOBJS="$LIBOBJS realloc.$ac_objext"
AC_LIBOBJ([realloc])
AC_DEFINE(realloc, rpl_realloc, [Replacement realloc()])
fi
])

View file

@ -2,38 +2,37 @@ dnl Check to find out whether the running kernel has support for TUN/TAP
AC_DEFUN(tinc_TUNTAP,
[
AC_ARG_WITH(kernel,
[ --with-kernel=dir give the directory with kernel sources]
[ (default: /usr/src/linux)],
kerneldir="$withval",
kerneldir="/usr/src/linux"
)
AC_CACHE_CHECK([for linux/if_tun.h], tinc_cv_linux_if_tun_h,
[
AC_TRY_COMPILE([#include "$kerneldir/include/linux/if_tun.h"],
[int a = IFF_TAP;],
if_tun_h="\"$kerneldir/include/linux/if_tun.h\"",
[AC_TRY_COMPILE([#include <linux/if_tun.h>],
[int a = IFF_TAP;],
if_tun_h="default",
if_tun_h="no"
)]
AC_ARG_WITH(kernel,
AC_HELP_STRING([--with-kernel=DIR], [give the directory with kernel sources (default: /usr/src/linux)]),
kerneldir="$withval",
kerneldir="/usr/src/linux"
)
if test $if_tun_h = no; then
tinc_cv_linux_if_tun_h=none
else
tinc_cv_linux_if_tun_h="$if_tun_h"
AC_CACHE_CHECK([for linux/if_tun.h], tinc_cv_linux_if_tun_h,
[
AC_TRY_COMPILE([#include "$kerneldir/include/linux/if_tun.h"],
[int a = IFF_TAP;],
if_tun_h="\"$kerneldir/include/linux/if_tun.h\"",
[AC_TRY_COMPILE([#include <linux/if_tun.h>],
[int a = IFF_TAP;],
if_tun_h="default",
if_tun_h="no"
)]
)
if test $if_tun_h = no; then
tinc_cv_linux_if_tun_h=none
else
tinc_cv_linux_if_tun_h="$if_tun_h"
fi
])
if test $tinc_cv_linux_if_tun_h != none; then
AC_DEFINE(HAVE_TUNTAP, 1, [Universal tun/tap driver present])
if test $tinc_cv_linux_if_tun_h != default; then
AC_DEFINE_UNQUOTED(LINUX_IF_TUN_H, $tinc_cv_linux_if_tun_h, [Location of if_tun.h])
fi
fi
])
if test $tinc_cv_linux_if_tun_h != none; then
AC_DEFINE(HAVE_TUNTAP)
if test $tinc_cv_linux_if_tun_h != default; then
AC_DEFINE_UNQUOTED(LINUX_IF_TUN_H, $tinc_cv_linux_if_tun_h)
fi
fi
AC_SUBST(LINUX_IF_TUN_H)
AC_SUBST(HAVE_TUNTAP)
AC_SUBST(LINUX_IF_TUN_H)
AC_SUBST(HAVE_TUNTAP)
])

View file

@ -4,15 +4,23 @@ AC_DEFUN(tinc_ZLIB,
[
tinc_ac_save_CPPFLAGS="$CPPFLAGS"
AC_ARG_WITH(zlib,
AC_HELP_STRING([--with-zlib=DIR], [zlib base directory, or:]),
[zlib="$withval"
CFLAGS="$CFLAGS -I$withval/include"
CPPFLAGS="$CPPFLAGS -I$withval/include"
LIBS="$LIBS -L$withval/lib"]
)
AC_ARG_WITH(zlib-include,
[ --with-zlib-include=DIR zlib headers directory],
AC_HELP_STRING([--with-zlib-include=DIR], [zlib headers directory]),
[zlib_include="$withval"
CFLAGS="$CFLAGS -I$withval"
CPPFLAGS="$CPPFLAGS -I$withval"]
)
AC_ARG_WITH(zlib-lib,
[ --with-zlib-lib=DIR zlib library directory],
AC_HELP_STRING([--with-zlib-lib=DIR], [zlib library directory]),
[zlib_lib="$withval"
LIBS="$LIBS -L$withval"]
)

View file

@ -1 +0,0 @@
Makefile Makefile.in

View file

@ -1 +0,0 @@
EXTRA_DIST = tinc tinc.spec

View file

@ -1,14 +0,0 @@
To make tinc RPMs:
copy tinc-???.tar.gz to /usr/src/redhat/SOURCES/ and run
rpm -ba tinc.spec
- and tinc.spec can be found in this directory.
The rpm's will be placed in /usr/src/redhat/RPMS/i386 (e.g.).
Happy Hacking!
Mads Kiilerich <mads@kiilerich.com>

View file

@ -1,337 +0,0 @@
#!/bin/sh
#
# tinc tincd VPN setup script
#
# chkconfig: 2345 46 54
#
# version: 1.0.8
# authors: Lubomir Bulej <pallas@kadan.cz>
# Mads Kiilerich <mads@kiilerich.com>
#
# description: This script parses tinc configuration files for networks given \
# in /etc/tinc/nets.boot and for each of the networks it sets up \
# the interface and static routes and starts the tinc daemon.
#
# processname: tincd
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0
#############################################################################
# configuration & sanity checks
TINCD=/usr/sbin/tincd
TCONF=/etc/tinc
TPIDS=/var/run
#DEBUG=-dddd
NETSFILE=$TCONF/nets.boot
# Check the daemon
if [ ! -x $TINCD ]; then
echo "**tinc: $TINCD does not exist or is not executable!" >&2
exit
fi
# Check if ip-route is installed
if [ ! -f /sbin/ip ]; then
echo "**tinc: ip-route utilities not installed!" >&2
exit
fi
# Check the kernel
if ! ip addr &> /dev/null; then
echo "**tinc: kernel not configured for use with ip-route!" >&2
exit
fi
# Check the configuration directory
if [ ! -d $TCONF ]; then
echo "**tinc: configuration directory ($TCONF) not found!" >&2
exit
fi
# Check nets.boot
if [ ! -f $NETSFILE ]; then
echo "**tinc: file with list of VPNs to start ($NETSFILE) not found!" >&2
exit
fi
# Load names of networks to be started
NETS="$(sed -e 's/#.*//; s/[[:space:]]//g; /^$/ d' $NETSFILE)"
##############################################################################
# prefix_to_mask Converts prefix length to netmask
# eg. 17 -> 255.255.128.0
# $1 ... prefix
prefix_to_mask () {
_MSK=""; _len="$1"
for _dot in "." "." "." " "; do
if [ ${_len} -ge 8 ]; then
_fld=8
else
_fld="${_len}"
fi
_MSK="${_MSK}$((255 & (255 << (8 - _fld))))${_dot}"
_len=$((_len - _fld))
done
echo ${_MSK}
}
##############################################################################
# mask_to_prefix Converts netmask to prefix length
# eg. 255.255.192.0 -> 18
# $1 ... netmask
mask_to_prefix () {
_LEN=0; _msk="$1"
for _tmp in 1 2 3 4; do
_fld=${_msk%%.*}
_msk=${_msk#*.}
while [ ${_fld} -ne 0 ]; do
_fld=$(((_fld << 1) & 255))
_LEN=$((_LEN + 1))
done
done
echo ${_LEN}
}
##############################################################################
# vpn_load () Loads VPN configuration
#
# $1 ... VPN to load
vpn_load () {
CFG="$TCONF/$1/tinc.conf"
[ -f $CFG ] || { MSG="$CFG does not exist!"; return 1; }
# load TINCD config
DEV="$(grep -i -e '^[[:space:]]*TapDevice' $CFG | sed 's/[[:space:]]//g; s/^.*=//g')"
VPN="$(grep -i -e '^[[:space:]]*(MyOwnVPNIP|MyVirtualIP)' -E $CFG | sed 's/[[:space:]]//g; s/^.*=//g')"
IFM="$(grep -i -e '^[[:space:]]*VPNMask' $CFG | sed 's/[[:space:]]//g; s/^.*=//g')"
# TapDevice syntax validation
[ -z "$DEV" ] && \
{ MSG="TapDevice required!"; return 1; }
[ $(echo $DEV | wc -l) -gt 1 ] && \
{ MSG="multiple TapDevice entries not allowed!"; return 1; }
echo $DEV | grep -q -x -E '/dev/tap[[:digit:]]+' ||
{ MSG="TapDevice should be in form /dev/tapX!"; return 1; }
# MyOwnVPNIP/MyVirtualIP syntax validation
[ -z "$VPN" ] && \
{ MSG="MyOwnVPNIP/MyVirtualIP required!"; return 1; }
[ $(echo $VPN | wc -l) -gt 1 ] && \
{ MSG="multiple MyOwnVPNIP/MyVirtualIP entries not allowed!"; return 1; }
echo $VPN | grep -q -x -E \
'([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}/[[:digit:]]{1,2}' || \
{ MSG="badly formed MyOwnVPNIP/MyVirtualIP address $VPN!"; return 1; }
# VPNMask syntax validation
[ $(echo $IFM | wc -l) -gt 1 ] && \
{ MSG="multiple VPNMask entries not allowed!"; return 1; }
# device & IP address extraction
TAP=${DEV##*/}
NUM=${TAP#tap}
ADR=${VPN%%/*}
# netmask is calculated from MyVirtualIP netmask prefix length, except when
# VPNMask is specified, in which case it is used instead of default prefix
# VPNMask not specified
if [ -z "$IFM" ]; then
LEN=${VPN##*/}
MSK=$(prefix_to_mask $LEN)
# VPNMask is prefix length, convert it to netmask for MSK
elif echo $IFM | grep -q -x -E '[[:digit:]]{1,2}'; then
VPN="$ADR/$IFM"
MSK=$(prefix_to_mask $IFM)
# VPNMask is netmask, convert it to prefix length for VPN
elif echo $IFM | grep -q -x -E '([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}'; then
VPN="$ADR/$(mask_to_prefix $IFM)"
MSK="$IFM"
else
MSG="badly formed interface netmask (VPNMask=$IFM)!"
return 1
fi
# Network & broadcast addresses
BRD=$(ipcalc --broadcast $ADR $MSK | cut -d"=" -f2)
NET=$(ipcalc --network $ADR $MSK | cut -d"=" -f2)
# MAC address
MAC=$(printf "fe:fd:%0.2x:%0.2x:%0.2x:%0.2x" $(echo $ADR | { IFS=. ; read a b c d; echo $a $b $c $d; }))
# debugging
# echo >&2
# echo "VPN $VPN TAP $TAP NUM $NUM MAC $MAC IFM $IFM" >&2
# echo "ADR $ADR MSK $MSK NET $NET BRD $BRD" >&2
return 0
}
##############################################################################
# vpn_start () starts specified VPN
#
# $1 ... VPN to start
vpn_start () {
MSG=""; ERR=""
vpn_load $1 || return 1
# create device file
if [ ! -c $DEV ]; then
[ -e $DEV ] && rm -f $DEV
mknod --mode=0600 $DEV c 36 $((16 + NUM))
fi
# load device module
ERR="$(insmod ethertap -o "ethertap$NUM" unit="$NUM" 2>&1 1> /dev/null)" ||
{ MSG="could not insmod ethertap as unit $NUM!"; return 2; }
# configure the interface
ERR="$(ip link set $TAP address $MAC 2>&1)" ||
{ MSG="could not set address for device $TAP!"; return 3; }
ERR="$(ip link set $TAP up 2>&1)" ||
{ MSG="could not bring up device $TAP!"; return 3; }
ERR="$(ip addr add $VPN brd $BRD dev $TAP 2>&1)" ||
{ MSG="could not set IP address for device $TAP!"; return 3; }
# start tincd
$TINCD --net="$1" $DEBUG || \
{ MSG="could not start daemon for network $1"; return 3; }
# setup custom static routes
/etc/sysconfig/network-scripts/ifup-routes $TAP
return 0
} # vpn_start
##############################################################################
# vpn_stop () Stops specified VPN
#
# $1 ... VPN to stop
vpn_stop () {
MSG=""; ERR=""
vpn_load $1 || return 1
# kill the tincd daemon
PID="$TPIDS/tinc.$1.pid"
if [ -f $PID ]; then
$TINCD --net="$1" --kill &> /dev/null
RET=$?
if [ $RET -eq 0 ]; then
dly=0
while [ $dly -le 5 ]; do
[ -f $PID ] || break
sleep 1; dly=$((dly + 1))
done
fi
# remove stale PID file
[ -f $PID ] && rm -f $PID
fi
# bring the interface down
ip addr flush dev $TAP &> /dev/null
ip link set $TAP down &> /dev/null
# remove ethertap module
rmmod "ethertap$NUM" &> /dev/null
return 0
} # vpn_stop
# Check if there is anything to start
if [ ! -z "$1" -a "$1" != "status" -a -z "$NETS" ]; then
echo "**tinc: no networks found in $NETSFILE!" >&2
exit
fi
# See how we were called.
case "$1" in
start)
for vpn in $NETS; do
echo -n "Bringing up TINC network $vpn: "
vpn_start $vpn && \
success "startup of network $vpn" || \
failure "startup of network $vpn"
echo
if [ ! -z "$MSG" ]; then
[ ! -z "$ERR" ] && echo "$ERR" >&2
echo "**tinc: $MSG" >&2
fi
done
touch /var/lock/subsys/tinc
;;
stop)
for vpn in $NETS; do
echo -n "Shutting down TINC network $vpn: "
vpn_stop $vpn && \
success "shutdown of network $vpn" || \
failure "shutdown of network $vpn"
echo
if [ ! -z "$MSG" ]; then
[ ! -z "$ERR" ] && echo "$ERR" >&2
echo "**tinc: $MSG" >&2
fi
done
rm -f /var/lock/subsys/tinc
;;
status)
echo -n "Configured VPNs: "
for vpn in $NETS; do
PID="$TPIDS/tinc.$vpn.pid"
[ -f $PID ] && PID="$(cat $PID)" || PID="-dead-"
ps ax | grep "^[[:space:]]*$PID" && STS="OK" || STS="DEAD"
echo -n "$vpn:$STS "
done
echo
;;
restart)
$0 stop
$0 start
;;
*)
echo "Usage: tinc {start|stop|status|restart}"
exit 1
esac
exit 0

View file

@ -1,113 +0,0 @@
Summary: tinc Virtual Private Network daemon
Name: tinc
Version: 1.0pre3
Release: 1
Copyright: GPL
Group: System Environment/Daemons
URL: http://tinc.nl.linux.org/
Source0: %{name}-%{version}.tar.gz
Buildroot: /var/tmp/%{name}-%{version}-%{release}
Requires: iproute
# for building the package the following is required:
# /usr/bin/texi2html /usr/bin/patch
%description
# taken from doc/tinc.texi
tinc is a Virtual Private Network (VPN) daemon that uses tunneling and
encryption to create a secure private network between hosts on the
Internet.
Because the tunnel appears to the IP level network code as a normal
network device, there is no need to adapt any existing software.
This tunneling allows VPN sites to share information with each other
over the Internet without exposing any information to others.
See http://tinc.nl.linux.org/
%prep
%setup -q -n %{name}-%{version}
%build
./configure --prefix=/usr --sysconfdir=/etc
make
/usr/bin/texi2html doc/tinc.texi
%install
rm -rf $RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT
gzip $RPM_BUILD_ROOT/usr/info/tinc.info
mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d/
cp redhat/tinc $RPM_BUILD_ROOT/etc/rc.d/init.d/
ME=my.vpn.ip.number
PEER=peer.vpn.ip.number
PEEREAL=peer.real.ip.number
umask 077
mkdir -p $RPM_BUILD_ROOT/etc/tinc/$PEER/passphrases
cat <<END >$RPM_BUILD_ROOT/etc/tinc/$PEER/tinc.conf
# Sample tinc configuration.
# Insert your own ip numbers instead of the placeholders,
# and be sure to use your own passphrases.
# See man tinc.conf(5) tincd(8) genauth(8), info tinc and
# /usr/doc/%{name}-%{version}/tinc.conf.sample
TapDevice = /dev/tap0
ConnectTo = $PEEREAL
MyVirtualIP = $ME/32
AllowConnect = no
END
cat <<END >$RPM_BUILD_ROOT/etc/tinc/$PEER/passphrases/local
1024 c1da5b633b428d783fec96ac89bb6bd4ed97ac673942706ba2240cde977158b7cd5f4055b7db70a7365d1f8df6a1a7c9dbb73f4e2bf8484fc14aee68d0f950e2bce82dd2a6386f040546a61e77cd1c25265ce03182e4e2c9a00ae0ea2f1f89ac04a10f7b67312187b5d2d74618803974ba6f053116b1460bc194c652dc28c84a
END
cat <<END >$RPM_BUILD_ROOT/etc/tinc/$PEER/passphrases/$PEER
1024 9dff58799827c3ae73699d9d4029cf80ee4cfd3a8408495cdb68c78dec602c46f362aedeea80928384254bc7d0bfbf9756c0783b5ec9943161863530a8861947147d124286e8c46fd98af988c96ba65c63acefc01f6c03b6b8f7d9897acb02c083adb7416ee5ccbc19610a8b9ade2599d8f66e94c715f2e1a15054a78a3f3260
END
%clean
rm -rf $RPM_BUILD_ROOT
%pre
%post
/sbin/chkconfig --add tinc
grep -q '^tinc[[:space:]]' /etc/services || patch -s /etc/services << END
*** services.org Tue Apr 18 13:22:22 2000
--- services Tue Apr 18 13:24:19 2000
***************
*** 145,148 ****
--- 145,150 ----
hmmp-ind 612/tcp dqs313_intercell# HMMP Indication / DQS
hmmp-ind 612/udp dqs313_intercell# HMMP Indication / DQS
+ tinc 655/tcp TINC # tinc vpn
+ tinc 655/udp TINC # http://tinc.nl.linux.org/
#
# UNIX specific services
END
grep -q '^alias tap0' /etc/conf.modules || cat >> /etc/conf.modules << END
# tinc uses ethertap/netlink
alias tap0 ethertap
alias char-major-36 netlink_dev
END
/sbin/install-info /usr/info/tinc.info.gz /usr/info/dir
%preun
/sbin/install-info --delete /usr/info/tinc.info.gz /usr/info/dir
%postun
%files
%doc AUTHORS ChangeLog NEWS README THANKS *.html doc/tinc.conf.sample
%config /etc/tinc/
%attr(0755,root,root) /etc/rc.d/init.d/tinc
/usr/sbin/genauth
/usr/sbin/tincd
/usr/lib/tinc/
/usr/man/man5/tinc.conf.5
/usr/man/man8/genauth.8
/usr/man/man8/tincd.8
/usr/info/tinc.info.gz

View file

@ -1,33 +1,31 @@
## Produce this file with automake to get Makefile.in
# $Id: Makefile.am,v 1.12 2002/05/02 13:11:55 zarq Exp $
SUBDIRS = pokey
# $Id: Makefile.am,v 1.13 2003/08/24 20:38:23 guus Exp $
sbin_PROGRAMS = tincd
EXTRA_DIST = linux/device.c freebsd/device.c openbsd/device.c solaris/device.c
EXTRA_DIST = linux/device.c freebsd/device.c openbsd/device.c solaris/device.c netbsd/device.c darwin/device.c cygwin/device.c mingw/device.c raw_socket/device.c
tincd_SOURCES = read_conf.c device.c meta.c net_packet.c net_setup.c \
net_socket.c process.c protocol.c protocol_auth.c protocol_edge.c protocol_misc.c \
protocol_key.c protocol_subnet.c route.c tincd.c net.c callbacks.c
tincd_SOURCES = conf.c connection.c edge.c event.c graph.c logger.c meta.c net.c net_packet.c net_setup.c \
net_socket.c netutl.c node.c process.c protocol.c protocol_auth.c protocol_edge.c protocol_misc.c \
protocol_key.c protocol_subnet.c route.c subnet.c tincd.c
INCLUDES = @INCLUDES@ -I$(top_builddir) -I$(top_srcdir)/lib -I$(top_srcdir)/intl
nodist_tincd_SOURCES = device.c
noinst_HEADERS = read_conf.h device.h meta.h process.h \
protocol.h route.h callbacks.h
DEFAULT_INCLUDES =
LIBS = @LIBS@ @INTLLIBS@
INCLUDES = @INCLUDES@ -I$(top_builddir) -I$(top_srcdir)/lib
noinst_HEADERS = conf.h connection.h device.h edge.h event.h graph.h logger.h meta.h net.h netutl.h node.h process.h \
protocol.h route.h subnet.h
LIBS = @LIBS@ @LIBINTL@
tincd_LDADD = \
$(top_builddir)/lib/libtinc.a -lgcrypt
$(top_builddir)/lib/libvpn.a
localedir = $(datadir)/locale
CFLAGS = @CFLAGS@ -DPKGLIBDIR=$(pkglibdir) -DCONFDIR=\"$(sysconfdir)\" \
-DLOCALEDIR=\"$(localedir)\" -DLOCALSTATEDIR=\"$(localstatedir)\"
AM_CFLAGS = @CFLAGS@ -DCONFDIR=\"$(sysconfdir)\" -DLOCALEDIR=\"$(localedir)\" -DLOCALSTATEDIR=\"$(localstatedir)\"
dist-hook:
rm -f `find . -type l`
lint: $(tincd_SOURCES)
lclint -nullassign -nullret +trytorecover +posixlib -skipansiheaders -skipposixheaders +gnuextensions -I/usr/include -I/usr/lib/gcc-lib/i386-linux/2.95.2/include -I. -I/home/zarq/p/tinc/cvs/cabal/src -I.. -I.. -I/home/zarq/p/tinc/cvs/cabal/lib -I/home/zarq/p/tinc/cvs/cabal/intl -D_POSIX_SOURCE -D__ELF__ -Dunix -D__i386__ -Dlinux -DHAVE_CONFIG_H -DPKGLIBDIR=/usr/local/lib/tinc -DCONFDIR=\"/usr/local/etc\" -DLOCALEDIR=\"/usr/local/share/locale\" $^

View file

@ -1,39 +0,0 @@
#include "config.h"
#include <stdarg.h>
#include <hooks.h>
#include <node.h>
#include "callbacks.h"
#include "process.h"
#include "system.h"
void hook_node_visible(const char *hooktype, va_list ap)
{
char *name;
node_t *n;
n = va_arg(ap, node_t*);
asprintf(&name, "hosts/%s-down", n->name);
execute_script(name);
free(name);
}
void hook_node_invisible(const char *hooktype, va_list ap)
{
char *name;
node_t *n;
n = va_arg(ap, node_t*);
asprintf(&name, "hosts/%s-up", n->name);
execute_script(name);
free(name);
}
void init_callbacks(void)
{
add_hook("node-visible", hook_node_visible);
add_hook("node-invisible", hook_node_invisible);
}

View file

@ -1,7 +0,0 @@
#ifndef __TINC_CALLBACKS_H__
#define __TINC_CALLBACKS_H__
extern void init_callbacks(void);
#endif /* __TINC_CALLBACKS_H__ */

489
src/conf.c Normal file
View file

@ -0,0 +1,489 @@
/*
conf.c -- configuration code
Copyright (C) 1998 Robert van der Meulen
1998-2003 Ivo Timmermans <ivo@o2w.nl>
2000-2003 Guus Sliepen <guus@sliepen.eu.org>
2000 Cris van Pelt <tribbel@arise.dhs.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: conf.c,v 1.14 2003/08/24 20:38:24 guus Exp $
*/
#include "system.h"
#include "avl_tree.h"
#include "conf.h"
#include "logger.h"
#include "netutl.h" /* for str2address */
#include "utils.h" /* for cp */
#include "xalloc.h"
avl_tree_t *config_tree;
int pingtimeout = 0; /* seconds before timeout */
char *confbase = NULL; /* directory in which all config files are */
char *netname = NULL; /* name of the vpn network */
static int config_compare(const config_t *a, const config_t *b)
{
int result;
result = strcasecmp(a->variable, b->variable);
if(result)
return result;
result = a->line - b->line;
if(result)
return result;
else
return strcmp(a->file, b->file);
}
void init_configuration(avl_tree_t ** config_tree)
{
cp();
*config_tree = avl_alloc_tree((avl_compare_t) config_compare, (avl_action_t) free_config);
}
void exit_configuration(avl_tree_t ** config_tree)
{
cp();
avl_delete_tree(*config_tree);
*config_tree = NULL;
}
config_t *new_config(void)
{
cp();
return (config_t *) xmalloc_and_zero(sizeof(config_t));
}
void free_config(config_t *cfg)
{
cp();
if(cfg->variable)
free(cfg->variable);
if(cfg->value)
free(cfg->value);
if(cfg->file)
free(cfg->file);
free(cfg);
}
void config_add(avl_tree_t *config_tree, config_t *cfg)
{
cp();
avl_insert(config_tree, cfg);
}
config_t *lookup_config(const avl_tree_t *config_tree, char *variable)
{
config_t cfg, *found;
cp();
cfg.variable = variable;
cfg.file = "";
cfg.line = 0;
found = avl_search_closest_greater(config_tree, &cfg);
if(!found)
return NULL;
if(strcasecmp(found->variable, variable))
return NULL;
return found;
}
config_t *lookup_config_next(const avl_tree_t *config_tree, const config_t *cfg)
{
avl_node_t *node;
config_t *found;
cp();
node = avl_search_node(config_tree, cfg);
if(node) {
if(node->next) {
found = (config_t *) node->next->data;
if(!strcasecmp(found->variable, cfg->variable))
return found;
}
}
return NULL;
}
bool get_config_bool(const config_t *cfg, bool *result)
{
cp();
if(!cfg)
return false;
if(!strcasecmp(cfg->value, "yes")) {
*result = true;
return true;
} else if(!strcasecmp(cfg->value, "no")) {
*result = false;
return true;
}
logger(LOG_ERR, _("\"yes\" or \"no\" expected for configuration variable %s in %s line %d"),
cfg->variable, cfg->file, cfg->line);
return false;
}
bool get_config_int(const config_t *cfg, int *result)
{
cp();
if(!cfg)
return false;
if(sscanf(cfg->value, "%d", result) == 1)
return true;
logger(LOG_ERR, _("Integer expected for configuration variable %s in %s line %d"),
cfg->variable, cfg->file, cfg->line);
return false;
}
bool get_config_string(const config_t *cfg, char **result)
{
cp();
if(!cfg)
return false;
*result = xstrdup(cfg->value);
return true;
}
bool get_config_address(const config_t *cfg, struct addrinfo **result)
{
struct addrinfo *ai;
cp();
if(!cfg)
return false;
ai = str2addrinfo(cfg->value, NULL, 0);
if(ai) {
*result = ai;
return true;
}
logger(LOG_ERR, _("Hostname or IP address expected for configuration variable %s in %s line %d"),
cfg->variable, cfg->file, cfg->line);
return false;
}
bool get_config_subnet(const config_t *cfg, subnet_t ** result)
{
subnet_t *subnet;
cp();
if(!cfg)
return false;
subnet = str2net(cfg->value);
if(!subnet) {
logger(LOG_ERR, _("Subnet expected for configuration variable %s in %s line %d"),
cfg->variable, cfg->file, cfg->line);
return false;
}
/* Teach newbies what subnets are... */
if(((subnet->type == SUBNET_IPV4)
&& !maskcheck(&subnet->net.ipv4.address, subnet->net.ipv4.prefixlength, sizeof(ipv4_t)))
|| ((subnet->type == SUBNET_IPV6)
&& !maskcheck(&subnet->net.ipv6.address, subnet->net.ipv6.prefixlength, sizeof(ipv6_t)))) {
logger(LOG_ERR, _ ("Network address and prefix length do not match for configuration variable %s in %s line %d"),
cfg->variable, cfg->file, cfg->line);
free(subnet);
return false;
}
*result = subnet;
return true;
}
/*
Read exactly one line and strip the trailing newline if any. If the
file was on EOF, return NULL. Otherwise, return all the data in a
dynamically allocated buffer.
If line is non-NULL, it will be used as an initial buffer, to avoid
unnecessary mallocing each time this function is called. If buf is
given, and buf needs to be expanded, the var pointed to by buflen
will be increased.
*/
static char *readline(FILE * fp, char **buf, size_t *buflen)
{
char *newline = NULL;
char *p;
char *line; /* The array that contains everything that has been read so far */
char *idx; /* Read into this pointer, which points to an offset within line */
size_t size, newsize; /* The size of the current array pointed to by line */
size_t maxlen; /* Maximum number of characters that may be read with fgets. This is newsize - oldsize. */
if(feof(fp))
return NULL;
if(buf && buflen) {
size = *buflen;
line = *buf;
} else {
size = 100;
line = xmalloc(size);
}
maxlen = size;
idx = line;
*idx = 0;
for(;;) {
errno = 0;
p = fgets(idx, maxlen, fp);
if(!p) { /* EOF or error */
if(feof(fp))
break;
/* otherwise: error; let the calling function print an error message if applicable */
free(line);
return NULL;
}
newline = strchr(p, '\n');
if(!newline) { /* We haven't yet read everything to the end of the line */
newsize = size << 1;
line = xrealloc(line, newsize);
idx = &line[size - 1];
maxlen = newsize - size + 1;
size = newsize;
} else {
*newline = '\0'; /* kill newline */
break; /* yay */
}
}
if(buf && buflen) {
*buflen = size;
*buf = line;
}
return line;
}
/*
Parse a configuration file and put the results in the configuration tree
starting at *base.
*/
int read_config_file(avl_tree_t *config_tree, const char *fname)
{
int err = -2; /* Parse error */
FILE *fp;
char *buffer, *line;
char *variable, *value;
int lineno = 0;
int len;
bool ignore = false;
config_t *cfg;
size_t bufsize;
cp();
fp = fopen(fname, "r");
if(!fp) {
logger(LOG_ERR, _("Cannot open config file %s: %s"), fname,
strerror(errno));
return -3;
}
bufsize = 100;
buffer = xmalloc(bufsize);
for(;;) {
line = readline(fp, &buffer, &bufsize);
if(!line) {
err = -1;
break;
}
if(feof(fp)) {
err = 0;
break;
}
lineno++;
if(!*line || *line == '#')
continue;
if(ignore) {
if(!strncmp(line, "-----END", 8))
ignore = false;
continue;
}
if(!strncmp(line, "-----BEGIN", 10)) {
ignore = true;
continue;
}
variable = value = line;
len = strcspn(value, "\t =");
value += len;
value += strspn(value, "\t ");
if(*value == '=') {
value++;
value += strspn(value, "\t ");
}
variable[len] = '\0';
if(!*value) {
logger(LOG_ERR, _("No value for variable `%s' on line %d while reading config file %s"),
variable, lineno, fname);
break;
}
cfg = new_config();
cfg->variable = xstrdup(variable);
cfg->value = xstrdup(value);
cfg->file = xstrdup(fname);
cfg->line = lineno;
config_add(config_tree, cfg);
}
free(buffer);
fclose(fp);
return err;
}
bool read_server_config()
{
char *fname;
int x;
cp();
asprintf(&fname, "%s/tinc.conf", confbase);
x = read_config_file(config_tree, fname);
if(x == -1) { /* System error: complain */
logger(LOG_ERR, _("Failed to read `%s': %s"), fname, strerror(errno));
}
free(fname);
return x == 0;
}
FILE *ask_and_open(const char *filename, const char *what, const char *mode)
{
FILE *r;
char *directory;
char *fn;
/* Check stdin and stdout */
if(!isatty(0) || !isatty(1)) {
/* Argh, they are running us from a script or something. Write
the files to the current directory and let them burn in hell
for ever. */
fn = xstrdup(filename);
} else {
/* Ask for a file and/or directory name. */
fprintf(stdout, _("Please enter a file to save %s to [%s]: "),
what, filename);
fflush(stdout);
fn = readline(stdin, NULL, NULL);
if(!fn) {
fprintf(stderr, _("Error while reading stdin: %s\n"),
strerror(errno));
return NULL;
}
if(!strlen(fn))
/* User just pressed enter. */
fn = xstrdup(filename);
}
#ifdef HAVE_MINGW
if(fn[0] != '\\' && fn[0] != '/' && !strchr(fn, ':')) {
#else
if(fn[0] != '/') {
#endif
/* The directory is a relative path or a filename. */
char *p;
directory = get_current_dir_name();
asprintf(&p, "%s/%s", directory, fn);
free(fn);
free(directory);
fn = p;
}
umask(0077); /* Disallow everything for group and other */
/* Open it first to keep the inode busy */
r = fopen(fn, mode);
if(!r) {
fprintf(stderr, _("Error opening file `%s': %s\n"),
fn, strerror(errno));
free(fn);
return NULL;
}
free(fn);
return r;
}

View file

@ -1,7 +1,7 @@
/*
conf.h -- header for conf.c
Copyright (C) 1998-2002 Ivo Timmermans <itimmermans@bigfoot.com>
2000-2002 Guus Sliepen <guus@sliepen.warande.net>
Copyright (C) 1998-2003 Ivo Timmermans <ivo@o2w.nl>
2000-2003 Guus Sliepen <guus@sliepen.eu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -17,49 +17,47 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: conf.h,v 1.1 2002/04/28 12:46:25 zarq Exp $
$Id: conf.h,v 1.11 2003/08/24 20:38:24 guus Exp $
*/
#ifndef __TINC_CONF_H__
#define __TINC_CONF_H__
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <avl_tree.h>
#include "net.h"
#include "subnet.h"
#include "avl_tree.h"
typedef struct config_t {
char *variable;
char *value;
char *file;
int line;
char *variable;
char *value;
char *file;
int line;
} config_t;
#include "subnet.h"
extern avl_tree_t *config_tree;
extern int pingtimeout;
extern int maxtimeout;
extern int bypass_security;
extern bool bypass_security;
extern char *confbase;
extern char *netname;
extern void init_configuration(avl_tree_t **);
extern void exit_configuration(avl_tree_t **);
extern config_t *new_config(void);
extern config_t *new_config(void) __attribute__ ((__malloc__));
extern void free_config(config_t *);
extern void config_add(avl_tree_t *, config_t *);
extern config_t *lookup_config(avl_tree_t *, char *);
extern config_t *lookup_config_next(avl_tree_t *, config_t *);
extern int get_config_bool(config_t *, int *);
extern int get_config_int(config_t *, int *);
extern int get_config_port(config_t *, port_t *);
extern int get_config_string(config_t *, char **);
extern int get_config_address(config_t *, struct addrinfo **);
struct subnet_t; /* Needed for next line. */
extern int get_config_subnet(config_t *, struct subnet_t **);
extern config_t *lookup_config(const avl_tree_t *, char *);
extern config_t *lookup_config_next(const avl_tree_t *, const config_t *);
extern bool get_config_bool(const config_t *, bool *);
extern bool get_config_int(const config_t *, int *);
extern bool get_config_string(const config_t *, char **);
extern bool get_config_address(const config_t *, struct addrinfo **);
extern bool get_config_subnet(const config_t *, struct subnet_t **);
#endif /* __TINC_CONF_H__ */
extern int read_config_file(avl_tree_t *, const char *);
extern bool read_server_config(void);
extern FILE *ask_and_open(const char *, const char *, const char *);
extern bool is_safe_path(const char *);
#endif /* __TINC_CONF_H__ */

143
src/connection.c Normal file
View file

@ -0,0 +1,143 @@
/*
connection.c -- connection list management
Copyright (C) 2000-2003 Guus Sliepen <guus@sliepen.eu.org>,
2000-2003 Ivo Timmermans <ivo@o2w.nl>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: connection.c,v 1.4 2003/08/24 20:38:24 guus Exp $
*/
#include "system.h"
#include "avl_tree.h"
#include "conf.h"
#include "list.h"
#include "logger.h"
#include "net.h" /* Don't ask. */
#include "netutl.h"
#include "subnet.h"
#include "utils.h"
#include "xalloc.h"
avl_tree_t *connection_tree; /* Meta connections */
connection_t *broadcast;
static int connection_compare(const connection_t *a, const connection_t *b)
{
return (void *)a - (void *)b;
}
void init_connections(void)
{
cp();
connection_tree = avl_alloc_tree((avl_compare_t) connection_compare, NULL);
broadcast = new_connection();
broadcast->name = xstrdup(_("everyone"));
broadcast->hostname = xstrdup(_("BROADCAST"));
}
void exit_connections(void)
{
cp();
avl_delete_tree(connection_tree);
free_connection(broadcast);
}
connection_t *new_connection(void)
{
connection_t *c;
cp();
c = (connection_t *) xmalloc_and_zero(sizeof(connection_t));
if(!c)
return NULL;
gettimeofday(&c->start, NULL);
return c;
}
void free_connection(connection_t *c)
{
cp();
if(c->hostname)
free(c->hostname);
if(c->inkey)
free(c->inkey);
if(c->outkey)
free(c->outkey);
if(c->mychallenge)
free(c->mychallenge);
if(c->hischallenge)
free(c->hischallenge);
free(c);
}
void connection_add(connection_t *c)
{
cp();
avl_insert(connection_tree, c);
}
void connection_del(connection_t *c)
{
cp();
avl_delete(connection_tree, c);
}
void dump_connections(void)
{
avl_node_t *node;
connection_t *c;
cp();
logger(LOG_DEBUG, _("Connections:"));
for(node = connection_tree->head; node; node = node->next) {
c = (connection_t *) node->data;
logger(LOG_DEBUG, _(" %s at %s options %lx socket %d status %04x"),
c->name, c->hostname, c->options, c->socket, *(uint32_t *)&c->status);
}
logger(LOG_DEBUG, _("End of connections."));
}
bool read_connection_config(connection_t *c)
{
char *fname;
int x;
cp();
asprintf(&fname, "%s/hosts/%s", confbase, c->name);
x = read_config_file(c->config_tree, fname);
free(fname);
return x == 0;
}

110
src/connection.h Normal file
View file

@ -0,0 +1,110 @@
/*
connection.h -- header for connection.c
Copyright (C) 2000-2003 Guus Sliepen <guus@sliepen.eu.org>,
2000-2003 Ivo Timmermans <ivo@o2w.nl>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: connection.h,v 1.4 2003/08/24 20:38:24 guus Exp $
*/
#ifndef __TINC_CONNECTION_H__
#define __TINC_CONNECTION_H__
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include "avl_tree.h"
#define OPTION_INDIRECT 0x0001
#define OPTION_TCPONLY 0x0002
typedef struct connection_status_t {
int pinged:1; /* sent ping */
int active:1; /* 1 if active.. */
int connecting:1; /* 1 if we are waiting for a non-blocking connect() to finish */
int termreq:1; /* the termination of this connection was requested */
int remove:1; /* Set to 1 if you want this connection removed */
int timeout:1; /* 1 if gotten timeout */
int encryptout:1; /* 1 if we can encrypt outgoing traffic */
int decryptin:1; /* 1 if we have to decrypt incoming traffic */
int mst:1; /* 1 if this connection is part of a minimum spanning tree */
int unused:18;
} connection_status_t;
#include "edge.h"
#include "list.h"
#include "net.h"
#include "node.h"
typedef struct connection_t {
char *name; /* name he claims to have */
union sockaddr_t address; /* his real (internet) ip */
char *hostname; /* the hostname of its real ip */
int protocol_version; /* used protocol */
int socket; /* socket used for this connection */
long int options; /* options for this connection */
struct connection_status_t status; /* status info */
int estimated_weight; /* estimation for the weight of the edge for this connection */
struct timeval start; /* time this connection was started, used for above estimation */
struct outgoing_t *outgoing; /* used to keep track of outgoing connections */
struct node_t *node; /* node associated with the other end */
struct edge_t *edge; /* edge associated with this connection */
RSA *rsa_key; /* his public/private key */
const EVP_CIPHER *incipher; /* Cipher he will use to send data to us */
const EVP_CIPHER *outcipher; /* Cipher we will use to send data to him */
EVP_CIPHER_CTX *inctx; /* Context of encrypted meta data that will come from him to us */
EVP_CIPHER_CTX *outctx; /* Context of encrypted meta data that will be sent from us to him */
char *inkey; /* His symmetric meta key + iv */
char *outkey; /* Our symmetric meta key + iv */
int inkeylength; /* Length of his key + iv */
int outkeylength; /* Length of our key + iv */
const EVP_MD *indigest;
const EVP_MD *outdigest;
int inmaclength;
int outmaclength;
int incompression;
int outcompression;
char *mychallenge; /* challenge we received from him */
char *hischallenge; /* challenge we sent to him */
char buffer[MAXBUFSIZE]; /* metadata input buffer */
int buflen; /* bytes read into buffer */
int reqlen; /* length of incoming request */
int tcplen; /* length of incoming TCPpacket */
int allow_request; /* defined if there's only one request possible */
time_t last_ping_time; /* last time we saw some activity from the other end */
avl_tree_t *config_tree; /* Pointer to configuration tree belonging to him */
} connection_t;
extern avl_tree_t *connection_tree;
extern connection_t *broadcast;
extern void init_connections(void);
extern void exit_connections(void);
extern connection_t *new_connection(void) __attribute__ ((__malloc__));
extern void free_connection(connection_t *);
extern void connection_add(connection_t *);
extern void connection_del(connection_t *);
extern void dump_connections(void);
extern bool read_connection_config(connection_t *);
#endif /* __TINC_CONNECTION_H__ */

290
src/cygwin/device.c Normal file
View file

@ -0,0 +1,290 @@
/*
device.c -- Interaction with Windows tap driver in a Cygwin environment
Copyright (C) 2002-2003 Ivo Timmermans <ivo@o2w.nl>,
2002-2003 Guus Sliepen <guus@sliepen.eu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: device.c,v 1.2 2003/08/24 20:38:29 guus Exp $
*/
#include "system.h"
#include <w32api/windows.h>
#include <w32api/winioctl.h>
#include "conf.h"
#include "logger.h"
#include "net.h"
#include "route.h"
#include "utils.h"
#include "xalloc.h"
#define REG_CONTROL_NET "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
#define USERMODEDEVICEDIR "\\\\.\\"
#define USERDEVICEDIR "\\??\\"
#define TAPSUFFIX ".tap"
#define TAP_CONTROL_CODE(request,method) CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD | 8000, request, method, FILE_ANY_ACCESS)
#define TAP_IOCTL_GET_LASTMAC TAP_CONTROL_CODE(0, METHOD_BUFFERED)
#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE(1, METHOD_BUFFERED)
#define TAP_IOCTL_SET_STATISTICS TAP_CONTROL_CODE(2, METHOD_BUFFERED)
int device_fd = -1;
static HANDLE device_handle = INVALID_HANDLE_VALUE;
char *device = NULL;
char *iface = NULL;
char *device_info = NULL;
int device_total_in = 0;
int device_total_out = 0;
pid_t reader_pid;
int sp[2];
bool setup_device(void)
{
HKEY key, key2;
int i;
char regpath[1024];
char adapterid[1024];
char adaptername[1024];
char tapname[1024];
char gelukt = 0;
long len;
bool found = false;
cp();
get_config_string(lookup_config(config_tree, "Device"), &device);
get_config_string(lookup_config(config_tree, "Interface"), &iface);
/* Open registry and look for network adapters */
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_CONTROL_NET, 0, KEY_READ, &key)) {
logger(LOG_ERR, _("Unable to read registry: %s"), winerror(GetLastError()));
return false;
}
for (i = 0; ; i++) {
len = sizeof(adapterid);
if(RegEnumKeyEx(key, i, adapterid, &len, 0, 0, 0, NULL))
break;
/* Find out more about this adapter */
snprintf(regpath, sizeof(regpath), "%s\\%s\\Connection", REG_CONTROL_NET, adapterid);
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2))
continue;
len = sizeof(adaptername);
err = RegQueryValueEx(key2, "Name", 0, 0, adaptername, &len);
RegCloseKey(key2);
if(err)
continue;
if(device) {
if(!strcmp(device, adapterid)) {
found = true;
break;
} else
continue;
}
if(iface) {
if(!strcmp(iface, adaptername)) {
found = true;
break;
} else
continue;
}
snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
if(device_handle != INVALID_HANDLE_VALUE) {
CloseHandle(device_handle);
found = true;
break;
}
}
RegCloseKey(key);
if(!found) {
logger(LOG_ERR, _("No Windows tap device found!"));
return false;
}
if(!device)
device = xstrdup(adapterid);
if(!iface)
iface = xstrdup(adaptername);
snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, device);
/* Now we are going to open this device twice: once for reading and once for writing.
We do this because apparently it isn't possible to check for activity in the select() loop.
Furthermore I don't really know how to do it the "Windows" way. */
if(socketpair(AF_UNIX, SOCK_DGRAM, PF_UNIX, sp)) {
logger(LOG_DEBUG, _("System call `%s' failed: %s"), "socketpair", strerror(errno));
return false;
}
/* The parent opens the tap device for writing. */
device_handle = CreateFile(tapname, GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM , 0);
if(device_handle == INVALID_HANDLE_VALUE) {
logger(LOG_ERR, _("Could not open Windows tap device %s (%s) for writing: %s"), device, iface, winerror(GetLastError()));
return false;
}
device_fd = sp[0];
/* Get MAC address from tap device */
if(!DeviceIoControl(device_handle, TAP_IOCTL_GET_MAC, mymac.x, sizeof(mymac.x), mymac.x, sizeof(mymac.x), &len, 0)) {
logger(LOG_ERR, _("Could not get MAC address from Windows tap device %s (%s): %s"), device, iface, winerror(GetLastError()));
return false;
}
if(routing_mode == RMODE_ROUTER) {
overwrite_mac = 1;
}
/* Now we start the child */
reader_pid = fork();
if(reader_pid == -1) {
logger(LOG_DEBUG, _("System call `%s' failed: %s"), "fork", strerror(errno));
return false;
}
if(!reader_pid) {
/* The child opens the tap device for reading, blocking.
It passes everything it reads to the socket. */
char buf[MTU];
long lenin;
CloseHandle(device_handle);
device_handle = CreateFile(tapname, GENERIC_READ, FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
if(device_handle == INVALID_HANDLE_VALUE) {
logger(LOG_ERR, _("Could not open Windows tap device %s (%s) for reading: %s"), device, iface, winerror(GetLastError()));
buf[0] = 0;
write(sp[1], buf, 1);
exit(1);
}
logger(LOG_DEBUG, _("Tap reader forked and running."));
/* Notify success */
buf[0] = 1;
write(sp[1], buf, 1);
/* Pass packets */
for(;;) {
ReadFile(device_handle, buf, MTU, &lenin, NULL);
write(sp[1], buf, lenin);
}
}
read(device_fd, &gelukt, 1);
if(gelukt != 1) {
logger(LOG_DEBUG, _("Tap reader failed!"));
return false;
}
device_info = _("Windows tap device");
logger(LOG_INFO, _("%s (%s) is a %s"), device, iface, device_info);
return true;
}
void close_device(void)
{
cp();
close(sp[0]);
close(sp[1]);
CloseHandle(device_handle);
kill(reader_pid, SIGKILL);
}
bool read_packet(vpn_packet_t *packet)
{
int lenin;
cp();
if((lenin = read(sp[0], packet->data, MTU)) <= 0) {
logger(LOG_ERR, _("Error while reading from %s %s: %s"), device_info,
device, strerror(errno));
return false;
}
packet->len = lenin;
device_total_in += packet->len;
ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len,
device_info);
return true;
}
bool write_packet(vpn_packet_t *packet)
{
long lenout;
cp();
ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
if(!WriteFile (device_handle, packet->data, packet->len, &lenout, NULL)) {
logger(LOG_ERR, _("Error while writing to %s %s: %s"), device_info, device, winerror(GetLastError()));
return false;
}
device_total_out += packet->len;
return true;
}
void dump_device_stats(void)
{
cp();
logger(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
logger(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
logger(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
}

118
src/darwin/device.c Normal file
View file

@ -0,0 +1,118 @@
/*
device.c -- Interaction with MacOS/X tun device
Copyright (C) 2001-2003 Ivo Timmermans <ivo@o2w.nl>,
2001-2003 Guus Sliepen <guus@sliepen.eu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: device.c,v 1.2 2003/08/24 20:38:29 guus Exp $
*/
#include "system.h"
#include "conf.h"
#include "logger.h"
#include "net.h"
#include "utils.h"
#define DEFAULT_DEVICE "/dev/tun0"
int device_fd = -1;
char *device;
char *iface;
char *device_info;
int device_total_in = 0;
int device_total_out = 0;
bool setup_device(void)
{
cp();
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = DEFAULT_DEVICE;
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
iface = rindex(device, '/') ? rindex(device, '/') + 1 : device;
if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) {
logger(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
return false;
}
device_info = _("MacOS/X tun device");
logger(LOG_INFO, _("%s is a %s"), device, device_info);
return true;
}
void close_device(void)
{
cp();
close(device_fd);
}
bool read_packet(vpn_packet_t *packet)
{
int lenin;
cp();
if((lenin = read(device_fd, packet->data + 14, MTU - 14)) <= 0) {
logger(LOG_ERR, _("Error while reading from %s %s: %s"), device_info,
device, strerror(errno));
return false;
}
packet->data[12] = 0x08;
packet->data[13] = 0x00;
packet->len = lenin + 14;
device_total_in += packet->len;
ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Read packet of %d bytes from %s"),
packet->len, device_info);
return true;
}
bool write_packet(vpn_packet_t *packet)
{
cp();
ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
if(write(device_fd, packet->data + 14, packet->len - 14) < 0) {
logger(LOG_ERR, _("Error while writing to %s %s: %s"), device_info,
device, strerror(errno));
return false;
}
device_total_out += packet->len;
return true;
}
void dump_device_stats(void)
{
cp();
logger(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
logger(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
logger(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
}

View file

@ -1,7 +1,7 @@
/*
net.h -- generic header for device.c
Copyright (C) 2001-2002 Ivo Timmermans <zarq@iname.com>
2001-2002 Guus Sliepen <guus@sliepen.warande.net>
Copyright (C) 2001-2003 Ivo Timmermans <zarq@iname.com>
2001-2003 Guus Sliepen <guus@sliepen.eu.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -17,20 +17,23 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: device.h,v 1.2 2002/04/09 15:26:00 zarq Exp $
$Id: device.h,v 1.3 2003/08/24 20:38:24 guus Exp $
*/
#ifndef __TINC_DEVICE_H__
#define __TINC_DEVICE_H__
#include "net.h"
extern int device_fd;
extern char *device;
extern char *interface;
extern int setup_device(void);
extern char *iface;
extern bool setup_device(void);
extern void close_device(void);
extern int read_packet(vpn_packet_t *);
extern int write_packet(vpn_packet_t *);
extern bool read_packet(struct vpn_packet_t *);
extern bool write_packet(struct vpn_packet_t *);
extern void dump_device_stats(void);
#endif /* __TINC_DEVICE_H__ */
#endif /* __TINC_DEVICE_H__ */

162
src/edge.c Normal file
View file

@ -0,0 +1,162 @@
/*
edge.c -- edge tree management
Copyright (C) 2000-2003 Guus Sliepen <guus@sliepen.eu.org>,
2000-2003 Ivo Timmermans <ivo@o2w.nl>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: edge.c,v 1.4 2003/08/24 20:38:24 guus Exp $
*/
#include "system.h"
#include "avl_tree.h"
#include "edge.h"
#include "logger.h"
#include "netutl.h"
#include "node.h"
#include "utils.h"
#include "xalloc.h"
avl_tree_t *edge_weight_tree; /* Tree with all edges, sorted on weight */
static int edge_compare(const edge_t *a, const edge_t *b)
{
return strcmp(a->to->name, b->to->name);
}
static int edge_weight_compare(const edge_t *a, const edge_t *b)
{
int result;
result = a->weight - b->weight;
if(result)
return result;
result = strcmp(a->from->name, b->from->name);
if(result)
return result;
return strcmp(a->to->name, b->to->name);
}
void init_edges(void)
{
cp();
edge_weight_tree = avl_alloc_tree((avl_compare_t) edge_weight_compare, NULL);
}
avl_tree_t *new_edge_tree(void)
{
cp();
return avl_alloc_tree((avl_compare_t) edge_compare, (avl_action_t) free_edge);
}
void free_edge_tree(avl_tree_t *edge_tree)
{
cp();
avl_delete_tree(edge_tree);
}
void exit_edges(void)
{
cp();
avl_delete_tree(edge_weight_tree);
}
/* Creation and deletion of connection elements */
edge_t *new_edge(void)
{
cp();
return (edge_t *) xmalloc_and_zero(sizeof(edge_t));
}
void free_edge(edge_t *e)
{
cp();
sockaddrfree(&e->address);
free(e);
}
void edge_add(edge_t *e)
{
cp();
avl_insert(edge_weight_tree, e);
avl_insert(e->from->edge_tree, e);
e->reverse = lookup_edge(e->to, e->from);
if(e->reverse)
e->reverse->reverse = e;
}
void edge_del(edge_t *e)
{
cp();
if(e->reverse)
e->reverse->reverse = NULL;
avl_delete(edge_weight_tree, e);
avl_delete(e->from->edge_tree, e);
}
edge_t *lookup_edge(node_t *from, node_t *to)
{
edge_t v;
cp();
v.from = from;
v.to = to;
return avl_search(from->edge_tree, &v);
}
void dump_edges(void)
{
avl_node_t *node, *node2;
node_t *n;
edge_t *e;
char *address;
cp();
logger(LOG_DEBUG, _("Edges:"));
for(node = node_tree->head; node; node = node->next) {
n = (node_t *) node->data;
for(node2 = n->edge_tree->head; node2; node2 = node2->next) {
e = (edge_t *) node2->data;
address = sockaddr2hostname(&e->address);
logger(LOG_DEBUG, _(" %s to %s at %s options %lx weight %d"),
e->from->name, e->to->name, address, e->options, e->weight);
free(address);
}
}
logger(LOG_DEBUG, _("End of edges."));
}

View file

@ -1,7 +1,7 @@
/*
edge.h -- header for edge.c
Copyright (C) 2001-2002 Guus Sliepen <guus@sliepen.warande.net>,
2001-2002 Ivo Timmermans <itimmermans@bigfoot.com>
Copyright (C) 2001-2003 Guus Sliepen <guus@sliepen.eu.org>,
2001-2003 Ivo Timmermans <ivo@o2w.nl>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -17,48 +17,40 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: edge.h,v 1.1 2002/04/28 12:46:25 zarq Exp $
$Id: edge.h,v 1.4 2003/08/24 20:38:24 guus Exp $
*/
#ifndef __TINC_EDGE_H__
#define __TINC_EDGE_H__
#include <avl_tree.h>
#include "avl_tree.h"
#include "connection.h"
#include "net.h"
#include "node.h"
#include "connection.h"
typedef struct halfconnection_t {
struct node_t *node; /* node associated with this end of the connection */
/* sockaddr_t tcpaddress; */ /* real (internet) ip on this end of the meta connection */
sockaddr_t udpaddress; /* real (internet) ip on this end of the vpn connection */
} halfconnection_t;
typedef struct edge_t {
struct halfconnection_t from;
struct halfconnection_t to;
struct node_t *from;
struct node_t *to;
sockaddr_t address;
long int options; /* options turned on for this edge */
int weight; /* weight of this edge */
struct connection_t *connection; /* connection associated with this edge, if available */
long int options; /* options turned on for this edge */
int weight; /* weight of this edge */
void *if_data; /* Interface data */
struct connection_t *connection; /* connection associated with this edge, if available */
struct edge_t *reverse; /* edge in the opposite direction, if available */
} edge_t;
extern avl_tree_t *edge_tree; /* Tree with all known edges (replaces active_tree) */
extern avl_tree_t *edge_weight_tree; /* Tree with all known edges sorted on weight */
extern avl_tree_t *edge_weight_tree; /* Tree with all known edges sorted on weight */
extern void init_edges(void);
extern void exit_edges(void);
extern edge_t *new_edge(void);
extern edge_t *new_edge(void) __attribute__ ((__malloc__));
extern void free_edge(edge_t *);
extern avl_tree_t *new_edge_tree(void);
extern avl_tree_t *new_edge_tree(void) __attribute__ ((__malloc__));
extern void free_edge_tree(avl_tree_t *);
extern void edge_add(edge_t *);
extern void edge_del(edge_t *);
extern edge_t *lookup_edge(struct node_t *, struct node_t *);
extern void dump_edges(void);
#endif /* __TINC_EDGE_H__ */
#endif /* __TINC_EDGE_H__ */

View file

@ -1,358 +0,0 @@
/*
encr.c -- everything that deals with encryption
Copyright (C) 1998,1999,2000 Ivo Timmermans <itimmermans@bigfoot.com>
2000 Guus Sliepen <guus@sliepen.warande.net>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: encr.c,v 1.13 2000/10/18 20:12:08 zarq Exp $
*/
#include "config.h"
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <sys/socket.h>
#include <sys/time.h>
#ifdef HAVE_GMP_H
# include <gmp.h>
#else
# ifdef HAVE_GMP2_GMP_H
# include <gmp2/gmp.h>
# endif
#endif
#include <utils.h>
#include <xalloc.h>
#include <cipher.h>
#include "conf.h"
#include "encr.h"
#include "net.h"
#include "protocol.h"
#include "system.h"
#define ENCR_GENERATOR "0xd"
#define ENCR_PRIME "0x7fffffffffffffffffffffffffffffff" /* Mersenne :) */
char text_key[1000];
char *my_public_key_base36;
int key_inited = 0, encryption_keylen;
mpz_t my_private_key, my_public_key, generator, shared_prime;
int my_key_expiry = (time_t)(-1);
char* mypassphrase;
int mypassphraselen;
int char_hex_to_bin(int c)
{
if(isdigit(c))
return c - '0';
else
return tolower(c) - 'a' + 10;
}
int str_hex_to_bin(unsigned char *bin, unsigned char *hex)
{
int i = 0, j = 0, l = strlen(hex);
cp
if(l&1)
{
i = j = 1;
bin[0] = char_hex_to_bin(hex[0]);
}
for(; i < l; i+=2, j++)
bin[j] = (char_hex_to_bin(hex[i]) << 4) + char_hex_to_bin(hex[i+1]);
cp
return j&1?j+1:j;
}
int read_passphrase(char *which, char **out)
{
FILE *f;
config_t const *cfg;
char *filename;
int size;
extern char *confbase;
char *pp;
cp
if((cfg = get_config_val(passphrasesdir)) == NULL)
{
asprintf(&filename, "%spassphrases/%s", confbase, which);
}
else
{
asprintf(&filename, "%s/%s", (char*)cfg->data.ptr, which);
}
if((f = fopen(filename, "rb")) == NULL)
{
if(debug_lvl > 1)
syslog(LOG_ERR, _("Could not open %s: %m"), filename);
return -1;
}
fscanf(f, "%d ", &size);
if(size < 1 || size > (1<<15))
{
syslog(LOG_ERR, _("Illegal passphrase in %s; size would be %d"), filename, size);
return -1;
}
/* Hmz... hackish... strange +1 and +2 stuff... I really like more comments on those alignment thingies! */
pp = xmalloc(size/4 + 1); /* Allocate enough for fgets */
fgets(pp, size/4 + 1, f); /* Read passhrase and reserve one byte for end-of-string */
fclose(f);
*out = xmalloc(size/8 + 2); /* Allocate enough bytes, +1 for rounding if bits%8 != 0, +1 for 2-byte alignment */
cp
return str_hex_to_bin(*out, pp);
}
int read_my_passphrase(void)
{
cp
if((mypassphraselen = read_passphrase("local", &mypassphrase)) < 0)
return -1;
cp
return 0;
}
int generate_private_key(void)
{
FILE *f;
int i;
char *s;
config_t const *cfg;
cp
if((cfg = get_config_val(keyexpire)) == NULL)
my_key_expiry = (time_t)(time(NULL) + 3600);
else
my_key_expiry = (time_t)(time(NULL) + cfg->data.val);
if(debug_lvl > 1)
syslog(LOG_NOTICE, _("Generating %d bits keys"), PRIVATE_KEY_BITS);
if((f = fopen("/dev/urandom", "r")) == NULL)
{
syslog(LOG_ERR, _("Opening /dev/urandom failed: %m"));
return -1;
}
s = xmalloc((2 * PRIVATE_KEY_LENGTH) + 1);
for(i = 0; i < PRIVATE_KEY_LENGTH; i++)
sprintf(&s[i << 1], "%02x", fgetc(f));
s[2 * PRIVATE_KEY_LENGTH] = '\0';
mpz_set_str(my_private_key, s, 16);
cp
return 0;
}
void calculate_public_key(void)
{
cp
mpz_powm(my_public_key, generator, my_private_key, shared_prime);
my_public_key_base36 = mpz_get_str(NULL, 36, my_public_key);
cp
}
unsigned char static_key[] = { 0x9c, 0xbf, 0x36, 0xa9, 0xce, 0x20, 0x1b, 0x8b, 0x67, 0x56, 0x21, 0x5d, 0x27, 0x1b, 0xd8, 0x7a };
int security_init(void)
{
cp
mpz_init(my_private_key);
mpz_init(my_public_key);
mpz_init_set_str(shared_prime, ENCR_PRIME, 0);
mpz_init_set_str(generator, ENCR_GENERATOR, 0);
if(read_my_passphrase() < 0)
return -1;
if(generate_private_key() < 0)
return -1;
if(cipher_init(CIPHER_BLOWFISH) < 0)
return -1;
calculate_public_key();
cp
return 0;
}
void set_shared_key(char *almost_key)
{
char *tmp;
int len;
mpz_t ak, our_shared_key;
cp
mpz_init_set_str(ak, almost_key, 36);
mpz_init(our_shared_key);
mpz_powm(our_shared_key, ak, my_private_key, shared_prime);
tmp = mpz_get_str(NULL, 16, our_shared_key);
len = str_hex_to_bin(text_key, tmp);
cipher_set_key(&encryption_key, len, text_key);
key_inited = 1;
encryption_keylen = len;
if(debug_lvl > 2)
syslog(LOG_INFO, _("Encryption key set to %s"), tmp);
free(tmp);
mpz_clear(ak);
mpz_clear(our_shared_key);
cp
}
void encrypt_passphrase(passphrase_t *pp)
{
char key[1000];
char tmp[1000];
unsigned char phrase[1000];
int keylen;
int i;
BF_KEY bf_key;
cp
mpz_get_str(tmp, 16, my_public_key);
keylen = str_hex_to_bin(key, tmp);
cipher_set_key(&bf_key, keylen, key);
low_crypt_key(mypassphrase, phrase, &bf_key, mypassphraselen, BF_ENCRYPT);
pp->len = ((mypassphraselen - 1) | 7) + 1;
pp->phrase = xmalloc((pp->len << 1) + 1);
for(i = 0; i < pp->len; i++)
snprintf(&(pp->phrase)[i << 1], 3, "%02x", (int)phrase[i]);
pp->phrase[(pp->len << 1) + 1] = '\0';
if(key_inited)
cipher_set_key(&encryption_key, encryption_keylen, text_key);
cp
}
int verify_passphrase(conn_list_t *cl, unsigned char *his_pubkey)
{
char key[1000];
char *tmp;
unsigned char phrase[1000];
int keylen, pplen;
mpz_t pk;
unsigned char *out;
BF_KEY bf_key;
char *which;
char *meuk;
cp
mpz_init_set_str(pk, his_pubkey, 36);
tmp = mpz_get_str(NULL, 16, pk);
keylen = str_hex_to_bin(key, tmp);
out = xmalloc((cl->pp->len >> 1) + 3);
pplen = str_hex_to_bin(phrase, cl->pp->phrase);
cipher_set_key(&bf_key, keylen, key);
low_crypt_key(phrase, out, &bf_key, pplen, BF_DECRYPT);
if(key_inited)
cipher_set_key(&encryption_key, encryption_keylen, text_key);
asprintf(&which, IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
if((pplen = read_passphrase(which, &meuk)) < 0)
return -1;
if(memcmp(meuk, out, pplen))
return -1;
cp
return 0;
}
char *make_shared_key(char *pk)
{
mpz_t tmp, res;
char *r;
cp
mpz_init_set_str(tmp, pk, 36);
mpz_init(res);
mpz_powm(res, tmp, my_private_key, shared_prime);
r = mpz_get_str(NULL, 36, res);
mpz_clear(res);
mpz_clear(tmp);
cp
return r;
}
/*
free a key after overwriting it
*/
void free_key(enc_key_t *k)
{
cp
if(!k)
return;
if(k->key)
{
memset(k->key, (char)(-1), k->length);
free(k->key);
}
free(k);
cp
}
void recalculate_encryption_keys(void)
{
conn_list_t *p;
char *ek;
cp
for(p = conn_list; p != NULL; p = p->next)
{
if(!p->public_key || !p->public_key->key)
/* We haven't received a key from this host (yet). */
continue;
ek = make_shared_key(p->public_key->key);
free_key(p->datakey);
p->datakey = xmalloc(sizeof(*p->datakey));
p->datakey->length = strlen(ek);
p->datakey->expiry = p->public_key->expiry;
p->datakey->key = xmalloc(strlen(ek) + 1);
strcpy(p->datakey->key, ek);
}
cp
}
void regenerate_keys(void)
{
cp
generate_private_key();
calculate_public_key();
send_key_changed_all();
recalculate_encryption_keys();
cp
}

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