]> git.meshlink.io Git - meshlink/commitdiff
Merging of the entire pre5 branch.
authorGuus Sliepen <guus@tinc-vpn.org>
Sun, 10 Feb 2002 21:57:54 +0000 (21:57 +0000)
committerGuus Sliepen <guus@tinc-vpn.org>
Sun, 10 Feb 2002 21:57:54 +0000 (21:57 +0000)
70 files changed:
AUTHORS
Makefile.am
NEWS
README
THANKS
TODO
acconfig.h
configure.in
debian/.cvsignore [deleted file]
debian/Makefile.am [deleted file]
debian/README.Debian [deleted file]
debian/changelog [deleted file]
debian/conffiles [deleted file]
debian/control [deleted file]
debian/copyright [deleted file]
debian/dirs [deleted file]
debian/doc-base.tinc [deleted file]
debian/docs [deleted file]
debian/info [deleted file]
debian/init.d [deleted file]
debian/po-Makefile.in.in.diff [deleted file]
debian/postinst [deleted file]
debian/rules [deleted file]
debian/tinc.modules [deleted file]
doc/CONNECTIVITY
doc/NETWORKING
doc/PROTOCOL
doc/SECURITY2
doc/sample-config/tinc-down
doc/sample-config/tinc-up
doc/sample-config/tinc.conf
doc/tinc.conf.5
doc/tinc.texi
doc/tincd.8
lib/avl_tree.c
lib/dropin.c
lib/dropin.h
m4/openssl.m4
po/POTFILES.in
po/nl.po
redhat/Makefile.am [deleted file]
src/Makefile.am
src/conf.c
src/conf.h
src/connection.c
src/connection.h
src/device.h
src/edge.c
src/edge.h
src/freebsd/device.c
src/graph.c
src/graph.h
src/linux/device.c
src/meta.c
src/meta.h
src/net.c
src/net.h
src/node.c
src/node.h
src/openbsd/device.c
src/process.c
src/process.h
src/protocol.c
src/protocol.h
src/route.c
src/route.h
src/solaris/device.c
src/subnet.c
src/subnet.h
src/tincd.c

diff --git a/AUTHORS b/AUTHORS
index 710cc83b5eca3e32c3097e6251deece7e519fd03..4721984fa3ef658271a28909ef0a73748f6b5ad8 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -5,7 +5,6 @@ Ivo Timmermans <itimmermans@bigfoot.com>
 These files are from other sources:
  * lib/pidfile.h and lib/pidfile.c are by Martin Schulze, taken from
  the syslog 1.3 sources.
- * lib/dropin.c has various parts taken from OpenSSH.
 
 Also some of the macro files in the directory m4, and their
 accompanying files in lib, were taken from GNU fileutils.
index 85c2c18680c5199d20f6e628a6ea4b423eb19a94..bbfa0141e6253fb4e06d3202df18b47e7be13cbd 100644 (file)
@@ -2,7 +2,7 @@
 
 AUTOMAKE_OPTIONS = gnu
 
-SUBDIRS = m4 intl lib src doc po redhat
+SUBDIRS = m4 intl lib src doc po
 
 ACLOCAL_AMFLAGS =
 
diff --git a/NEWS b/NEWS
index d7282fa739b8fa3319613c46f00d834a9745a3c6..45b68e702ebe8184d7c3385c2dc77ad2ae76988a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,25 @@
-version 1.0pre4              Jan 17 2000
+version 1.0pre5              Feb  9 2002
+
+* Security enhancements:
+
+  * Added sequence number and optional message authentication code to
+    the packets.
+
+  * Configurable encryption cipher and digest algorithms.
+
+* More robust handling of dis- and reconnects.
+
+* Added a "switch" and a "hub" mode to allow bridging setups.
+
+* Preliminary support for routing of IPv6 packets.
+
+* Supports Linux, FreeBSD, OpenBSD and Solaris.
+
+
+It looks like this might be the last release before 1.0.
+
+
+version 1.0pre4              Jan 17 2001
 
 * Updated documentation; the documentation now reflects the
   configuration as it is.
diff --git a/README b/README
index 70d76f54dce0f0e9004fc10a516d082fff7e3efd..818a8d0d8354369d0ccdf54a28a96bb33d2ed98c 100644 (file)
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
-This is the README file for tinc version 1.0pre4. Installation
+This is the README file for tinc version 1.0pre5. Installation
 instructions may be found in the INSTALL file.
 
-tinc is Copyright (C) 1998-2001 by:
+tinc is Copyright (C) 1998-2002 by:
 
 Ivo Timmermans <itimmermans@bigfoot.com>,
 Guus Sliepen <guus@sliepen.warande.net>,
@@ -18,12 +18,16 @@ your option) any later version. See the file COPYING for more details.
 Security statement
 ------------------
 
-In august 2000, we discovered the existence of a security hole in all
-versions of tinc up to and including 1.0pre2. This had to do with the
-way we exchanged keys. Since then, we have been working on a new
-authentication scheme to make tinc as secure as possible. The current
-version uses the OpenSSL library and does authentication in much the
-same way as the SSH protocol does.
+In August 2000, we discovered the existence of a security hole in all versions
+of tinc up to and including 1.0pre2. This had to do with the way we exchanged
+keys. Since then, we have been working on a new authentication scheme to make
+tinc as secure as possible. The current version uses the OpenSSL library and
+uses strong authentication with RSA keys.
+
+On the 29th of December 2001, Jerome Etienne posted a security analysis of tinc
+1.0pre4. Due to a lack of sequence numbers and a message authentication code
+for each packet, an attacker could possibly disrupt certain network services or
+launch a denial of service attack by replaying intercepted packets.
 
 Cryptography is a hard thing to get right. We cannot make any
 guarantees. Time, review and feedback are the only things that can
@@ -31,6 +35,14 @@ prove the security of any cryptographic product. If you wish to review
 tinc or give us feedback, you are stronly encouraged to do so.
 
 
+Changes to configuration file format
+------------------------------------
+
+Some configuration variables have different names now. Most notably "TapDevice"
+should be changed into "Device", and "Device" should be changed into
+"BindToDevice".
+
+
 Requirements
 ------------
 
@@ -41,6 +53,9 @@ 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.
 
+In order to compile tinc, you will also need autoconf, automake, GNU make, m4
+and gettext.
+
 
 Features
 --------
@@ -68,3 +83,20 @@ This version supports multiple subnets at once. They are also sorted
 on subnet mask size. This means that it is possible to have
 overlapping subnets on the VPN, as long as their subnet mask sizes
 differ.
+
+Since pre5, tinc can operate in several routing modes. The default mode,
+"router", works exactly like the older version, and uses Subnet lines to
+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 algorithms used for encryption and generating message authentication codes
+can now be changed in the configuration files. All cipher and digest algorithms
+supported by OpenSSL can be used. Useful ciphers are "blowfish" (default),
+"bf-ofb", "des", "des3", etcetera. Useful digests are "sha1" (default), "md5",
+etcetera.
+
+Preliminary support for routing IPv6 packets has been added. Just add Subnet
+lines with IPv6 addresses (without using :: abbreviations) and use ifconfig to
+give the virtual network interface corresponding IPv6 addresses.
+Autoconfiguration will not work in router mode.
diff --git a/THANKS b/THANKS
index ed275bfc2567c2352b1da32da4ac885c1f9cdec4..0c50cf6241fcf367a3377959f0d6ffbc3bbd9227 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -16,6 +16,7 @@ We would like to thank
  * Matias Carrasco (for the Spanish translation of the manual)
  * Jamie Briggs (for finding a lot of socket leaks)
  * Armijn Hemel (for being our very own PR manager)
+ * Jerome Etienne (for a thorough security analysis of tinc)
 
 for their help, support and ideas.  Thank you guys!
 
diff --git a/TODO b/TODO
index 5dd5ecaead340926b818ce53dbb65ca2d57b8270..c0f2ee3f94c6888824afc1754e6714eb4b41a577 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,27 +1,5 @@
 TODO LIST
 
-Goals for 1.0 release:
+1.0:
 
-* Check Solaris port
-* Check FreeBSD port again (done)
-* Check TCPonly and IndirectData
-
-* Check different linux architectures (x86, alpha and sparc32 done)
-* Store private key in a separate file (done, 1 dec 2000)
-* Sanity checks on configuration directory (mostly done)
-* Use efficient tree algorithms instead of linked lists (done)
-* Reenable queues for delayed packets (done)
-* Merge documentation files (SECURITY, INSTALL, PROTOCOL) into tinc.texi (done)
-* Different authentication scheme (done)
-* Add randomness to packet headers and PING/PONG requests (done)
-
-Goals for future releases:
-
-* Compression
-* Routing by MAC/switching (allows for more than only IPv4) (done)
-* Broadcast/multicast (done)
-* Windowing, chaffing, scattering, background noise
-* ABC protocol (superscalabilty)
-* Proxy ARP (done)
-* Easy setup scripts (graphical?)
-* Threading
+* A nice, secure and stable release
index 9e9f886b3eb7ee864a7a8a1b9404f06dc492a23e..fd502bfc5174a3ab42567ef5a7ed1b0425fd9cff 100644 (file)
@@ -36,7 +36,6 @@
 /* Define to 1 if you have the stpcpy function.  */
 #undef HAVE_STPCPY
 
-
 /* For getopt */
 #if HAVE_STDLIB_H
 # define getopt system_getopt
@@ -68,5 +67,5 @@
 /* Define to 1 if checkpoint tracing is enabled */
 #undef ENABLE_TRACING
 
-/* Define to 1 if you have struct addrinfo */
-#undef HAVE_STRUCT_ADDRINFO
+/* Define to enable use of old SSLeay_add_all_algorithms() function */
+#undef HAVE_SSLEAY_ADD_ALL_ALGORITHMS
index 575113190ed25a676f55d2d06f2b25af8dc60265..df0f2bcc24a76033218ee6fe69a817293695e667 100644 (file)
@@ -1,6 +1,6 @@
 dnl Process this file with autoconf to produce a configure script.
 
-dnl $Id: configure.in,v 1.13.2.38 2001/11/15 23:49:46 zarq Exp $
+dnl $Id: configure.in,v 1.13.2.39 2002/02/10 21:57:51 guus Exp $
 
 AC_INIT(src/tincd.c)
 AM_INIT_AUTOMAKE(tinc, 1.0-cvs)
@@ -36,19 +36,19 @@ AC_CANONICAL_HOST
 case $host_os in
   *linux*)
     AC_DEFINE(HAVE_LINUX)
-    [ ln -sf linux/device.c src/device.c ]
+    [ rm -f src/device.c; ln -sf linux/device.c src/device.c ]
   ;;
   *freebsd*)
     AC_DEFINE(HAVE_FREEBSD)
-    [ ln -sf freebsd/device.c src/device.c ]
+    [ rm -f src/device.c; ln -sf freebsd/device.c src/device.c ]
   ;;
   *solaris*)
     AC_DEFINE(HAVE_SOLARIS)
-    [ ln -sf solaris/device.c src/device.c ]
+    [ rm -f src/device.c; ln -sf solaris/device.c src/device.c ]
   ;;
   *openbsd*)
     AC_DEFINE(HAVE_OPENBSD)
-    [ ln -sf openbsd/device.c src/device.c ]
+    [ rm -f src/device.c; ln -sf openbsd/device.c src/device.c ]
   ;;
 esac
 
@@ -68,28 +68,12 @@ AC_TYPE_SIZE_T
 AC_HEADER_TIME
 AC_STRUCT_TM
 
-AC_CACHE_CHECK([for struct addrinfo], ac_cv_have_struct_addrinfo, [
-  AC_TRY_COMPILE(
-    [
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-    ],
-    [ struct addrinfo s; s.ai_flags = 0; ],
-    [ ac_cv_have_struct_addrinfo="yes" ],
-    [ ac_cv_have_struct_addrinfo="no" ]
-  )])
-if test "x$ac_cv_have_struct_addrinfo" = "xyes" ; then
-  AC_DEFINE(HAVE_STRUCT_ADDRINFO)
-fi
-
 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 \
-getaddrinfo getnameinfo gai_strerror freeaddrinfo])
+asprintf putenv strdup fcloseall daemon strsignal get_current_dir_name])
 jm_FUNC_MALLOC
 jm_FUNC_REALLOC
 
@@ -127,5 +111,6 @@ intl/Makefile
 lib/Makefile
 m4/Makefile
 po/Makefile.in
-redhat/Makefile
-debian/Makefile)
+po/POTFILES
+po/Makefile
+)
diff --git a/debian/.cvsignore b/debian/.cvsignore
deleted file mode 100644 (file)
index 35de154..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile Makefile.in tmp postinst.debhelper postrm.debhelper
-preinst.debhelper prerm.debhelper substvars files
diff --git a/debian/Makefile.am b/debian/Makefile.am
deleted file mode 100644 (file)
index 0ed7907..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-EXTRA_DIST = README.Debian changelog conffiles control copyright dirs \
-       docs info init.d postinst rules doc-base.tinc tinc-up tinc-down \
-       tinc.modules
diff --git a/debian/README.Debian b/debian/README.Debian
deleted file mode 100644 (file)
index 5a4c224..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-tinc for Debian
-----------------------
-
-The manual for tinc is also available as info pages, type `info tinc'
-to read it.
-
-The system startup script for tinc, /etc/init.d/tinc, uses the file
-/etc/tinc/nets.boot to find out which networks have to be started.
-
- -- Ivo Timmermans <itimmermans@bigfoot.com>, Wed, 31 May 2000, 19:56:05 +0200
diff --git a/debian/changelog b/debian/changelog
deleted file mode 100644 (file)
index 20a39cd..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-tinc (1.0pre4-1) unstable; urgency=low
-
-  * New upstream version.
-
- -- Ivo Timmermans <ivo@debian.org>  Wed, 17 Jan 2001 02:42:49 +0100
-
-tinc (1.0pre3-2) unstable; urgency=low
-
-  * Set architecture to any (Closes: #80451).
-  * Added tinc.modules with some useful module aliases.
-
- -- Ivo Timmermans <ivo@debian.org>  Sat, 13 Jan 2001 16:10:57 +0100
-
-tinc (1.0pre3-1) unstable; urgency=low
-
-  * New upstream version (1.0pre3) (Closes: #71274).
-  * Better Depends and Build-Depends lines.
-  * Dropped dependencies on libgmp, added libssl.
-  * doc-base.tinc: New file.
-  * Deleted the file shlibs, as there on longer is a libblowfish.
-  * Patch po/Makefile.in.in from po-Makefile.in.in.diff if necessary.
-  * Use dh_perl to get accurate perl dependencies.
-
- -- Ivo Timmermans <ivo@debian.org>  Thu,  9 Nov 2000 21:58:40 +0100
-
-tinc (1.0pre2-1.1) unstable; urgency=low
-
-  * NMU at Ivo's request as his application is being processed, and his
-    sponsor is based in the US.
-
- -- J.H.M. Dassen (Ray) <jdassen@debian.org>  Wed, 28 Jun 2000 21:52:30 +0200
-
-tinc (1.0pre2-1) unstable; urgency=low
-
-  * postinst creates a file /etc/tinc/nets.boot, containing all networks
-    to be started upon system startup;
-  * init.d script starts all networks from that list.
-  * postinst script creates tap devices.
-
- -- Ivo Timmermans <itimmermans@bigfoot.com>  Tue, 16 May 2000 00:06:25 +0200
-
-tinc (1.0pre1-0.4) unstable; urgency=low
-
-  * postinst script.
-
- -- Ivo Timmermans <itimmermans@bigfoot.com>  Mon, 15 May 2000 19:22:05 +0200
-
-tinc (1.0pre1-0.3) unstable; urgency=low
-
-  * system startup script.
-
- -- Ivo Timmermans <itimmermans@bigfoot.com>  Sun, 14 May 2000 22:58:02 +0200
-  
-tinc (1.0pre1-0.2) unstable; urgency=low
-
-  * Included the blowfish license.
-
- -- Ivo Timmermans <itimmermans@bigfoot.com>  Fri, 21 Apr 2000 17:07:50 +0200
-
-tinc (1.0pre1-0.1) unstable; urgency=low
-
-  * Initial Release.
-
- -- Ivo Timmermans <itimmermans@bigfoot.com>  Fri, 21 Apr 2000 17:07:50 +0200
-
-Local variables:
-mode: debian-changelog
-End:
diff --git a/debian/conffiles b/debian/conffiles
deleted file mode 100644 (file)
index e0faa78..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-/etc/tinc/example/tinc.conf
-/etc/tinc/example/tinc-down
-/etc/tinc/example/tinc-up
-/etc/modutils/tinc
-/etc/init.d/tinc
diff --git a/debian/control b/debian/control
deleted file mode 100644 (file)
index 82d7df0..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-Source: tinc
-Section: non-US/main
-Priority: optional
-Maintainer: Ivo Timmermans <ivo@debian.org>
-Standards-Version: 3.0.1
-Build-Depends: libssl-dev, autoconf (>= 2.12),
- automake, debhelper, gettext
-
-Package: tinc
-Architecture: all
-Depends: ${shlibs:Depends}, ${perl:Depends}
-Description: Virtual Private Network daemon
- tinc is a daemon with which you can create a virtual private network
- (VPN).  One daemon can handle multiple connections, so you can
- create an entire (moderately sized) VPN with only one daemon per
- participating computer.
- .
- You need to have two kernel modules installed, on a Debian system
- they should already be there.  If they are not, the manual will
- explain you how to do that.
diff --git a/debian/copyright b/debian/copyright
deleted file mode 100644 (file)
index 7652f53..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-This package was debianized by Ivo Timmermans <itimmermans@bigfoot.com> on
-Fri, 21 Apr 2000 17:07:50 +0200.
-
-It was downloaded from http://tinc.nl.linux.org/
-
-Upstream Author(s):
- Ivo Timmermans <itimmermans@bigfoot.com>
- Guus Sliepen <guus@sliepen.warande.net>
-
-Copyright: GPL version 2. On Debian GNU/Linux systems, the complete
-text of the GNU General Public License can be found in
-/usr/share/common-licenses/GPL.
-
-The blowfish library is from the libssl package by Eric Young.  The
-copyright notice for this library follows.
-
-----------------------------------------------------------------------
-Copyright (C) 1995-1997 Eric Young (eay@mincom.oz.au)
-All rights reserved.
-
-This package is an Blowfish implementation written
-by Eric Young (eay@mincom.oz.au).
-
-This library is free for commercial and non-commercial use as long as
-the following conditions are aheared to.  The following conditions
-apply to all code found in this distribution.
-
-Copyright remains Eric Young's, and as such any Copyright notices in
-the code are not to be removed.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the copyright
-   notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-   This product includes software developed by Eric Young (eay@mincom.oz.au)
-
-THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
-
-The license and distribution terms for any publically available version or
-derivative of this code cannot be changed.  i.e. this code cannot simply be
-copied and put under another distrubution license
-[including the GNU Public License.]
-
-The reason behind this being stated in this direct manner is past
-experience in code simply being copied and the attribution removed
-from it and then being distributed as part of other packages. This
-implementation was a non-trivial and unpaid effort.
diff --git a/debian/dirs b/debian/dirs
deleted file mode 100644 (file)
index 3c03217..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-etc/tinc
-etc/tinc/example
diff --git a/debian/doc-base.tinc b/debian/doc-base.tinc
deleted file mode 100644 (file)
index 6f28d1f..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-Document: tinc
-Title: tinc Manual
-Author: Ivo Timmermans, Guus Sliepen
-Abstract: This manual describes how to set up a Virtual Private
- Network with tinc.
-Section: net
-
-Format: HTML
-Files: /usr/share/doc/tinc/tinc*.html
-Index: /usr/share/doc/tinc/tinc_toc.html
diff --git a/debian/docs b/debian/docs
deleted file mode 100644 (file)
index 9bdd99c..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-INSTALL
-NEWS
-README
diff --git a/debian/info b/debian/info
deleted file mode 100644 (file)
index 5468d6c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-doc/tinc.info
diff --git a/debian/init.d b/debian/init.d
deleted file mode 100644 (file)
index e3c55ed..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-#! /bin/sh
-#
-# System startup script for tinc
-# $Id: init.d,v 1.14.2.4 2000/12/05 09:03:41 zarq Exp $
-#
-# Based on Lubomir Bulej's Redhat init script.
-#
-# Create a file $NETSFILE (/etc/tinc/nets.boot), and put all the names of
-# the networks in there.  These names must be valid directory names under
-# $TCONF (/etc/tinc).  Lines starting with a # will be ignored in this
-# file.
-#
-
-DAEMON="/usr/sbin/tincd"
-NAME="tinc"
-DESC="tinc daemons"
-TCONF="/etc/tinc"
-EXTRA=""
-NETSFILE="$TCONF/nets.boot"
-NETS=""
-
-test -f $DAEMON || exit 0
-
-find_nets () {
-  if [ ! -f $NETSFILE ] ; then
-    echo "Please create $NETSFILE."
-    exit 0
-  fi
-  NETS="`egrep '^[ ]*[a-zA-Z0-9_]+[ ]*$' $NETSFILE`"
-}
-
-case "$1" in
-  start)
-    find_nets
-    echo -n "Starting $DESC:"
-    for n in $NETS ; do
-      echo -n " $n"
-      $DAEMON -n $n $EXTRA
-    done
-    echo "."
-  ;;
-  stop)
-    find_nets
-    echo -n "Stopping $DESC:"
-    for n in $NETS ; do
-      echo -n " $n"
-      $DAEMON -n $n $EXTRA -k
-    done
-    echo "."
-  ;;
-  restart|force-reload)
-    find_nets
-    echo -n "Restarting $DESC:"
-    for n in $NETS ; do
-      echo -n " $n"
-      $DAEMON -n $n $EXTRA -k
-      sleep 1
-      $DAEMON -n $n $EXTRA
-    done
-    echo "."
-  ;;
-  *)
-    echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload}"
-    exit 1
-  ;;
-esac
diff --git a/debian/po-Makefile.in.in.diff b/debian/po-Makefile.in.in.diff
deleted file mode 100644 (file)
index b33223a..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
---- Makefile.in.in.orig        Thu Nov  2 20:02:58 2000
-+++ Makefile.in.in     Thu Nov  2 23:25:42 2000
-@@ -24,6 +24,8 @@
- gettextsrcdir = $(prefix)/share/gettext/po
- subdir = po
-+DESTDIR = 
-+
- INSTALL = @INSTALL@
- INSTALL_DATA = @INSTALL_DATA@
- MKINSTALLDIRS = $(top_srcdir)/@MKINSTALLDIRS@
-@@ -111,16 +113,16 @@
- install-data-no: all
- install-data-yes: all
-       if test -r "$(MKINSTALLDIRS)"; then \
--        $(MKINSTALLDIRS) $(datadir); \
-+        $(MKINSTALLDIRS) $(DESTDIR)$(datadir); \
-       else \
--        $(SHELL) $(top_srcdir)/mkinstalldirs $(datadir); \
-+        $(SHELL) $(top_srcdir)/mkinstalldirs $(DESTDIR)$(datadir); \
-       fi
-       @catalogs='$(CATALOGS)'; \
-       for cat in $$catalogs; do \
-         cat=`basename $$cat`; \
-         case "$$cat" in \
--          *.gmo) destdir=$(gnulocaledir);; \
--          *)     destdir=$(localedir);; \
-+          *.gmo) destdir=$(DESTDIR)$(gnulocaledir);; \
-+          *)     destdir=$(DESTDIR)$(localedir);; \
-         esac; \
-         lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
-         dir=$$destdir/$$lang/LC_MESSAGES; \
diff --git a/debian/postinst b/debian/postinst
deleted file mode 100644 (file)
index b7d022b..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#! /bin/sh
-# postinst script for tinc
-#
-# $Id: postinst,v 1.6.4.1 2000/12/05 09:04:32 zarq Exp $
-#
-# see: dh_installdeb(1)
-
-TCONF="/etc/tinc"
-NETSFILE="$TCONF/nets.boot"
-
-set -e
-
-# summary of how this script can be called:
-#        * <postinst> `configure' <most-recently-configured-version>
-#        * <old-postinst> `abort-upgrade' <new version>
-#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
-#          <new-version>
-#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
-#          <failed-install-package> <version> `removing'
-#          <conflicting-package> <version>
-# for details, see /usr/doc/packaging-manual/
-#
-# quoting from the policy:
-#     Any necessary prompting should almost always be confined to the
-#     post-installation script, and should be protected with a conditional
-#     so that unnecessary prompting doesn't happen if a package's
-#     installation fails and the `postinst' is called with `abort-upgrade',
-#     `abort-remove' or `abort-deconfigure'.
-
-case "$1" in
-    configure)
-       if [ ! -e /dev/.devfs ] ; then
-           devices_exist=1
-           for d in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; do
-               test -e /dev/tap$d || devices_exist=0
-           done
-           if [ $devices_exist -eq 0 ] ; then
-               cd /dev && ./MAKEDEV netlink || true
-           fi
-       fi
-
-       if [ ! -e $NETSFILE ] ; then
-           echo "## This file contains all names of the networks to be started on system startup." > $NETSFILE
-       fi
-
-       if fgrep -q PublicKey `find /etc/tinc -type f` ; then
-           echo "If you are upgrading from version 1.0pre3, make sure you"
-           echo "regenerate the host keys.  For more information, refer to"
-           echo "/usr/share/doc/tinc/UPGRADING.txt."
-        fi
-    ;;
-
-    abort-upgrade|abort-remove|abort-deconfigure)
-
-    ;;
-
-    *)
-        echo "postinst called with unknown argument \`$1'" >&2
-        exit 0
-    ;;
-esac
-
-# dh_installdeb will replace this with shell code automatically
-# generated by other debhelper scripts.
-
-#DEBHELPER#
-
-exit 0
-
-
diff --git a/debian/rules b/debian/rules
deleted file mode 100644 (file)
index c07a054..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/usr/bin/make -f
-# Sample debian/rules that uses debhelper.
-# GNU copyright 1997 to 1999 by Joey Hess.
-
-# Uncomment this to turn on verbose mode.
-#export DH_VERBOSE=1
-
-# This is the debhelper compatability version to use.
-export DH_COMPAT=1
-
-build: build-stamp
-build-stamp:
-       dh_testdir
-
-#      # If the Makefile.in.in file in po/ already contains DESTDIR support, skip the patching.
-       cd `pwd`/po ; ( \
-         if ! grep DESTDIR Makefile.in.in > /dev/null ; then \
-           patch -Ns -p0 < `pwd`/../debian/po-Makefile.in.in.diff || true ;\
-         fi ;\
-       )
-
-       env CFLAGS='-O2 -Wall' ./autogen.sh --prefix=/usr --mandir=\$${prefix}/share/man \
-               --infodir=\$${prefix}/share/info --sysconfdir=/etc --localstatedir=/var
-
-       $(MAKE)
-
-       touch build-stamp
-
-clean:
-       dh_testdir
-       dh_testroot
-       rm -f build-stamp
-
-       -$(MAKE) cvs-clean
-
-       dh_clean
-
-install: build
-       dh_testdir
-       dh_testroot
-       dh_clean -k
-       dh_installdirs
-
-       $(MAKE) install DESTDIR=`pwd`/debian/tmp
-       mkdir -p `pwd`/debian/tmp/etc/tinc
-       cp -a doc/sample-config.tar.gz `pwd`/debian/tmp/etc/tinc/example
-       cd `pwd`/debian/tmp/etc/tinc/example && tar xzf sample-config.tar.gz && rm sample-config.tar.gz
-       ln -s /usr/share/doc/tinc/README.Debian `pwd`/debian/tmp/etc/tinc/example/README
-
-
-# Build architecture-independent files here.
-binary-indep: build install
-# We have nothing to do by default.
-
-# Build architecture-dependent files here.
-binary-arch: build install
-       dh_testdir
-       dh_testroot
-       dh_installdocs
-       dh_installexamples
-       dh_installinit
-       dh_installmanpages
-       dh_installmodules
-       dh_installinfo
-       dh_installchangelogs ChangeLog
-       dh_link
-       dh_strip
-       dh_compress
-       dh_fixperms
-       dh_installdeb
-       dh_perl
-       dh_shlibdeps
-       dh_gencontrol
-       dh_md5sums
-       dh_builddeb
-
-binary: binary-indep binary-arch
-.PHONY: build clean binary-indep binary-arch binary install
diff --git a/debian/tinc.modules b/debian/tinc.modules
deleted file mode 100644 (file)
index 7086e40..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-alias char-major-36 netlink_dev
-
-alias tap0 ethertap
-alias tap1 ethertap
-alias tap2 ethertap
-alias tap3 ethertap
-
-options tap0 -o tap0 -x unit=0
-options tap1 -o tap1 -x unit=1
-options tap2 -o tap2 -x unit=2
-options tap3 -o tap3 -x unit=3
-
-alias char-major-10-200 tun
index 3ced6ffb2d568a4d90efbdf7ab97f68de5655697..4a2aeea92e31082e1e39a60a849e3b928042d8be 100644 (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 Guus Sliepen <guus@sliepen.warande.net>
+   Copyright 2001-2002 Guus Sliepen <guus@sliepen.warande.net>
 
    Permission is granted to make and distribute verbatim copies of
    this documentation provided the copyright notice and this
@@ -12,7 +12,7 @@ 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.1.2.7 2001/07/24 08:51:36 guus Exp $
+   $Id: CONNECTIVITY,v 1.1.2.8 2002/02/10 21:57:51 guus Exp $
 
 1. Problem
 ==========
index 66b03edae53b564bcc4ccbb8a91444b9cf97f4e8..89a2e686ecdf3a3e94b8b0b13b8a13e8634eec3c 100644 (file)
@@ -1,7 +1,7 @@
 This is the network infrastructure documentation for tinc, a Virtual Private
 Network daemon.
 
-   Copyright 2001 Guus Sliepen <guus@sliepen.warande.net>
+   Copyright 2001-2002 Guus Sliepen <guus@sliepen.warande.net>
 
    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.1.2.1 2001/03/04 14:00:24 guus Exp $
+   $Id: NETWORKING,v 1.1.2.2 2002/02/10 21:57:51 guus Exp $
 
 1. Packet flow
 ==============
index 3ceff0753ab1933da5b59155ca6fa48e79037ae3..61e2c77bb18f7d08bf763357dc03b6c4da759936 100644 (file)
@@ -1,7 +1,7 @@
 This is the protocol documentation for tinc, a Virtual Private Network daemon.
 
-   Copyright 2000,2001 Guus Sliepen <guus@sliepen.warande.net>,
-             2000,2001 Ivo Timmmermans <itimmermans@bigfoot.com>
+   Copyright 2000-2002 Guus Sliepen <guus@sliepen.warande.net>,
+             2000-2002 Ivo Timmmermans <itimmermans@bigfoot.com>
 
    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.1.2.4 2001/01/07 17:08:02 guus Exp $
+   $Id: PROTOCOL,v 1.1.2.5 2002/02/10 21:57:51 guus Exp $
 
 
 1.  Protocols used in tinc
@@ -33,17 +33,19 @@ can be found in various UNIX flavours.
 Normal packets are sent without any state information, so the layout
 is pretty basic.
 
-A data packet can only be sent  if the encryption key is known to both
-parties, and the connection is  activated. If the encryption key is not
-known, a request is sent to the destination using the meta connection
-to retreive it.
+A data packet can only be sent if the encryption key, cipher and digest are
+known to both parties, and the connection is activated. If the encryption key
+is not known, a request is sent to the destination using the meta connection to
+retreive it.
 
- 0   1   2   3
-| LEN  | DATA :   \
-: DATA        .   } encrypted
-. :               /
-  .
+0   1   2   3   4   5   6   7   ...   97  98  99  100
+|     seqno     |         data        |     MAC       |
+\____________________________________/\_______________/
+                 |                           |
+  encrypted using symmetric cipher         digest
 
+The sequence number prevents replay attacks, the message authentication code
+prevents altered packets from being accepted.
 
 3.  Meta protocol
 ----------------
@@ -59,7 +61,7 @@ possible to use tools such as telnet or netcat to connect to a tinc
 daemon and to read and write requests by hand, provided that one
 understands the numeric codes sent.
 
-The authentication scheme is described in the SECURITY file. After a
+The authentication scheme is described in the SECURITY2 file. After a
 succesful authentication, the server and the client will exchange all the
 information about other tinc daemons and subnets they know of, so that both
 sides (and all the other tinc daemons behind them) have their information
@@ -67,19 +69,23 @@ synchronised.
 
 daemon message
 --------------------------------------------------------------------------
-origin ADD_HOST daemon a329e18c:655 0
-                    |         |      +--> options
-                    |         +---------> real address:port
-                    +-------------------> name of new tinc daemon
-origin ADD_SUBNET daemon 1,0a010100/ffffff00
-                      |   |     |       +--> netmask
-                      |   |     +----------> vpn IPv4 network address
-                      |   +----------------> subnet type (1=IPv4)
-                      +--------------------> owner of this subnet
+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_SUBNET node 192.168.1.0/24
+                     |         |     +--> masklength
+                     |         +--------> IPv4 network address
+                     +------------------> owner of this subnet
 --------------------------------------------------------------------------
 
-In case daemons leave the VPN, DEL_HOST and DEL_SUBNET messages with exactly
-the same syntax are sent to inform the other daemons of the departure.
+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.
 
 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
@@ -87,18 +93,22 @@ chances are that not every tinc daemon will ever send a packet to every
 other daemon. Instead, if a daemon needs a key it sends a request for it
 via the meta connection of the nearest hop in the direction of the
 destination. If any hop on the way has already learned the key, it will
-act as a proxy and forward it's copy back to the requestor.
+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 e4ae0b0a82d6e0078179b5290c62c7d0
-                   |       |       \______________________________/
-                   |       |                      +--> 128 bits 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
 --------------------------------------------------------------------------
index 3922f3fa4da9b151a8f0468cb53999b025004610..4276a018e5084c114db6959d1d5265015424536f 100644 (file)
@@ -1,7 +1,7 @@
 This is the security documentation for tinc, a Virtual Private Network daemon.
 
-   Copyright 2001 Guus Sliepen <guus@sliepen.warande.net>,
-             2001 Wessel Dankers <wsl@nl.linux.org>
+   Copyright 2001-2002 Guus Sliepen <guus@sliepen.warande.net>,
+             2001-2002 Wessel Dankers <wsl@nl.linux.org>
 
    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 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.1.2.1 2001/02/13 09:54:29 guus Exp $
+   $Id: SECURITY2,v 1.1.2.2 2002/02/10 21:57:51 guus Exp $
 
 Proposed new authentication scheme
 ----------------------------------
@@ -27,13 +27,11 @@ client  <attempts connection>
 
 server  <accepts connection>
 
-client  ID client 9 0
-              |   | +-> options
+client  ID client 12
               |   +---> version
               +-------> name of tinc daemon
 
-server  ID server 9 0
-              |   | +-> options
+server  ID server 12
               |   +---> version
               +-------> name of tinc daemon
 
@@ -64,6 +62,21 @@ client  CHAL_REPLY 816a86
 
 server  CHAL_REPLY 928ffe
                       +-> 160 bits SHA1 of H1
+
+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
+
+server  ACK 655 21.32.43.54 321 0
+             |       |       |  +-> options
+            |       |       +----> estimated weight
+            |       +------------> IP address of client as seen by server
+            +--------------------> UDP port of server
 --------------------------------------------------------------------------
 
 This new scheme has several improvements, both in efficiency and security.
@@ -107,9 +120,6 @@ Fourth: the first thing that is send via the symmetric cipher encrypted
 connection is a totally random string, so that there is no known plaintext (for
 an attacker) in the beginning of the encrypted stream.
 
-
-An explicit ACK is no longer needed, the CHAL_REPLY serves as an ACK.
-
 Some things to be discussed:
 
  - What should CHALLEN be? Same as RSAKEYLEN? 256 bits? More/less?
index 127499197ef70cf2401e6ea65ee81ad84700e7f3..65b049e2fdf78fca16c9df4bf3335db98f473c89 100644 (file)
@@ -1,7 +1,4 @@
 #!/bin/sh
 # This file closes down the tap device.
-# Note that if you use the universal tun/tap driver, you don't
-# need to do anything; once tinc quits the tap device is already
-# removed by the kernel.
 
-ifconfig tap1 down
+ifconfig $INTERFACE down
index f515e51dacc79bdc113ec84730c3027c622d721a..8f05c4a58c60383293504378c1514161837e31fe 100644 (file)
@@ -2,13 +2,14 @@
 # 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 ethertap this is tap0, tap1, tap2 etcetera,
-# but for the universal tun/tap device use $NETNAME.
+# 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 tap1 hw ether fe:fd:0:0:0:0
+ifconfig $INTERFACE hw ether fe:fd:0:0:0:0
 
 # 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 tap1 192.168.1.1 netmask 255.255.0.0 -arp
+ifconfig $INTERFACE 192.168.1.1 netmask 255.255.0.0 -arp
index ea5216ea78721622848fa6d73e76517c5478e672..f5f0aa6369237ea77b28d07417a0cba3a24d7557 100644 (file)
@@ -16,8 +16,10 @@ Name = alpha
 ConnectTo = beta
 
 # The tap device tinc will use. Required.
-# Default is /dev/tap0
-TapDevice = /dev/tap1
+# 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
index 46bc0cfe2c5d653bff83cc0c9cb1e9e5542f0ceb..547c75f180b8f458088984b488136b39cfbdcb68 100644 (file)
-.TH TINC 5 "Jan 2001" "tinc version 1.0pre4" "FSF"
-.SH NAME
-tinc.conf \- tinc daemon configuration
-.SH "DESCRIPTION"
-The files in the \fI/etc/tinc\fR directory contain runtime and
-security information for the \fBtincd\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/\fBnetname\fI/\fR, where \fBnetname\fR is your argument
-to the \fI-n\fR option. You'll notice that it appears in syslog as
-``tincd.\fBnetname\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/\fBnetname\fI/\fR; the configuration file should be
-\fI/etc/tinc/tinc.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 "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
-\fI/etc/tinc/\fBnetname\fI/tinc.conf\fR file.
-
-To make things easy, choose something that will give unique and easy
-to rememebr names to your tinc daemon(s).
+.Dd 2002-02-06
+.Dt TINC.CONF 5
+.\" Manual page created by:
+.\" Ivo Timmermans <itimmermans@bigfoot.com>
+.\" Guus Sliepen <guus@sliepen.warande.net>
+.Sh NAME
+.Nm tinc.conf
+.Nd tinc daemon configuration
+.Sh DESCRIPTION
+The files in the
+.Pa /etc/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 /etc/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 /etc/tinc/ ,
+instead of 
+.Pa /etc/tinc/ Ns Ar NETNAME Ns Pa / ;
+the configuration file should be
+.Pa /etc/tinc/tinc.conf ,
+and the host configuration files are now expected to be in
+.Pa /etc/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 /etc/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.
-.PP
-.SH "PUBLIC/PRIVATE KEYS"
-You should use \fBtincd --generate-keys\fR to generate public/private
-keypairs. It will generate two keys. The private
-key should be stored in a separate file \fI/etc/tinc/\fBnetname\fI/rsa_key.priv\fR
-\-\- where \fBnetname\fR stands for the network (See under \fBNETWORKS\fR)
-above. The public key should be stored in
-the host configuration file \fI/etc/tinc/\fBnetname\fI/hosts/\fBname\fR \-\- where \fBname\fR stands
-for the name of the local tinc daemon (See \fBNAMES\fR).
-.PP
-.SH "SERVER CONFIGURATION"
+.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 /etc/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 /etc/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
-\fI/etc/tinc/\fBnetname\fI/tinc.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
+.Pa /etc/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. \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
-Here are all valid variables, listed in alphabetical order. The default
-value is given between parentheses.
-.TP
-\fBConnectTo\fR = <\fIname\fR>
-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. The names should be known to this tinc daemon
-(i.e., there should be a host configuration file for the name on the ConnectTo
+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 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 BindToIP Li = Ar address Bq experimental
+If your computer has more than one IP address on a single interface
+(for example if you are running virtual hosts),
+.Nm tinc
+will by default listen on all of them for incoming connections.
+It is possible to bind only 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.
+.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;
+if connecting to the first one fails then tinc will try the next one, and so on.
+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).
-
-If you don't specify a host with \fBConnectTo\fR, tinc won't try to connect to other daemons at all,
+.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.
-.TP
-\fBHostnames\fR = <\fIyes|no\fR> (no)
+.It Va Device Li = Ar device Po /dev/tap0 or /dev/misc/net/tun 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.
+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 everytime it does
+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.
-.TP
-\fBInterface\fR = <\fIdevice\fR>
-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>
-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
-\fBName\fR = <\fIname\fR> [required]
-This is the name which identifies this tinc daemon. It must be unique for
-the virtual private network this daemon will connect to.
-.TP
-\fBPingTimeout\fR = <\fIseconds\fR> (60)
-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
-\fBPrivateKey\fR = <\fIkey\fR> [obsolete]
-The private RSA key of this tinc daemon. It will allow this tinc daemon to
-authenticate itself to other daemons.
-.TP
-\fBPrivateKeyFile\fR = <\fIfilename\fR> [recommended]
+.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.
+Currently this option only affects the Linux tun/tap device.
+.It Va KeyExpire Li = Ar period 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 MaxTimeout Li = Ar period 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.
+.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 a network switch does.
+Unicast, multicast and broadcast packets of every Ethernet protocol are supported in this mode
+at the cost of frequent broadcast ARP requests and routing table updates.
+.It hub
+In this mode every packet will be broadcast to the other daemons.
+.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 period 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 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 Bq recommended
 The file in which the private RSA key of this tinc daemon resides.
-
-Note that there must be exactly one of \fBPrivateKey\fR or \fBPrivateKeyFile\fR
+Note that there must be exactly one of
+.Va PrivateKey
+or
+.Va PrivateKeyFile
 specified in the configuration file.
-.TP
-\fBTapDevice\fR = <\fIdevice\fR> (/dev/tap0 or /dev/net/tun)
-The ethertap or tun/tap device to use. tinc will automatically detect what
-kind of tapdevice it is.
-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.
-.PP
-.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.
-
-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.
-.PP
-.TP
-\fBAddress\fR = <\fIIP address\fR> [recommended]
-The real address or hostname of this tinc daemon.
-.TP
-\fBIndirectData\fR = <\fIyes\fR|\fIno\fR> (no) [experimental]
-This option specifies whether other tinc daemons besides the one you
-specified with 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.
-.TP
-\fBPort\fR = <\fIport number\fR> (655)
-The port on which this tinc daemon is listening for incoming connections.
-.TP
-\fBPublicKey\fR = <\fIkey\fR> [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.
-.TP
-\fBPublicKeyFile\fR = <\fIfilename\fR> [obsolete]
+.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.
+.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 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 Po no Pc Bq experimental
+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.
-
-From version 1.0pre4 on 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.
-.TP
-\fBSubnet\fR = <\fIaddress/masklength\fR>
-The subnet which this tinc daemon will serve. tinc tries to look up which other
-daemon it should send a packet to by searching the appropiate subnet. If the
-packet matches a subnet, it will be sent to the daemon who has this subnet in his
-host configuration file. Multiple subnet lines can be specified.
-
-At the moment, this directive is only used in the host configuration file of
-the local tinc daemon itself. In upcoming versions of tinc, it will be possible to
-restrict other hosts in which subnets they server.
-
-The subnets must be in a form like \fI192.168.1.0/24\fR, where 192.168.1.0 is the
-network address and 24 is the number of bits set in the netmask. Note that subnets
-like \fI192.168.1.1/24\fR are invalid! Read a networking howto/FAQ/guide if you
-don't understand this.
-.TP
-\fBTCPonly\fR = <\fIyes\fR|\fIno\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. It may not work at all.
+.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 masklength
+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 subnet lines 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 masklength.
+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.
+.It Va TCPOnly Li = yes | no Po no Pc Bq experimental
+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.
+This is experimental code, try this at your own risk.
+It may not work at all.
 Setting this options also implicitly sets IndirectData.
-.SH "FILES"
-.TP
-\fI/etc/tinc/\fR
+.El
+.Sh FILES
+.Bl -tag -width indent
+.It Pa /etc/tinc/
 The top directory for configuration files.
-.TP
-\fI/etc/tinc/\fBnetname\fI/tinc.conf\fR
+.It Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf
 The default name of the server configuration file for net
-\fBnetname\fR.
-.TP
-\fI/etc/tinc/\fBnetname\fI/hosts/\fR
+.Ar NETNAME .
+.It Pa /etc/tinc/ Ns Ar NETNAME Ns Pa /hosts/
 Host configuration files are kept in this directory.
-.TP
-\fI/etc/tinc/\fBnetname\fI/tinc-up\fR
-If an executable file with this name exists, it will be executed
-right after the tinc daemon has connected to the tap device. It can
-be used to ifconfig the network interface.
-
-If the tapdevice is a tun/tap device, the evironment variable
-\fB$IFNAME\fR will be set to the name of the network interface.
-.TP
-\fI/etc/tinc/\fBnetname\fI/tinc-down\fR
-If an executable file with this name exists, it will be executed
-right before the tinc daemon is going to close it's connection to the
-tap device.
-.PP
-.SH "SEE ALSO"
-\fBtincd\fR(8)
-.TP
-\fBhttp://tinc.nl.linux.org/\fR
-.TP
-\fBhttp://www.linuxdoc.org/LDP/nag2/\fR
-.PP
+.It Pa /etc/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.
+.Pp
+The environment variable
+.Ev NETNAME
+will be passed to the executable.
+If specified with the
+.Va Interface
+configuration variable,
+or if the virtual network device is a Linux tun/tap device,
+the environment variable
+.Ev INTERFACE
+will be set to the name of the network interface.
+.It Pa /etc/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.
+The same environment variables will be passed as mentioned above.
+.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
-.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
+.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
-tinc comes with ABSOLUTELY NO WARRANTY.  This is free software,
-and you are welcome to redistribute it under certain conditions;
+.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.
index eadb1510d8e287711333821569191c76bc8b1455..ca399d5b2640be227d008d2dadadfeff045a5cae 100644 (file)
@@ -1,5 +1,5 @@
 \input texinfo   @c -*-texinfo-*-
-@c $Id: tinc.texi,v 1.8.4.18 2001/05/25 12:45:37 guus Exp $
+@c $Id: tinc.texi,v 1.8.4.19 2002/02/10 21:57:51 guus Exp $
 @c %**start of header
 @setfilename tinc.info
 @settitle tinc Manual
@@ -7,17 +7,18 @@
 @c %**end of header
 
 @ifinfo
+@dircategory Networking tools
 @direntry
 * tinc: (tinc).              The tinc Manual.
 @end direntry
 
 This is the info manual for tinc, a Virtual Private Network daemon.
 
-Copyright @copyright{} 1998-2001 Ivo Timmermans
+Copyright @copyright{} 1998-2002 Ivo Timmermans
 <itimmermans@@bigfoot.com>, Guus Sliepen <guus@@sliepen.warande.net> and
 Wessel Dankers <wsl@@nl.linux.org>.
 
-$Id: tinc.texi,v 1.8.4.18 2001/05/25 12:45:37 guus Exp $
+$Id: tinc.texi,v 1.8.4.19 2002/02/10 21:57:51 guus Exp $
 
 Permission is granted to make and distribute verbatim copies of this
 manual provided the copyright notice and this permission notice are
@@ -38,11 +39,11 @@ permission notice identical to this one.
 @page
 @vskip 0pt plus 1filll
 @cindex copyright
-Copyright @copyright{} 1998-2001 Ivo Timmermans
+Copyright @copyright{} 1998-2002 Ivo Timmermans
 <itimmermans@@bigfoot.com>, Guus Sliepen <guus@@sliepen.warande.net> and
 Wessel Dankers <wsl@@nl.linux.org>.
 
-$Id: tinc.texi,v 1.8.4.18 2001/05/25 12:45:37 guus Exp $
+$Id: tinc.texi,v 1.8.4.19 2002/02/10 21:57:51 guus Exp $
 
 Permission is granted to make and distribute verbatim copies of this
 manual provided the copyright notice and this permission notice are
@@ -176,16 +177,14 @@ available too.
 @section Supported platforms
 
 @cindex platforms
-tinc has been verified to work under Linux, FreeBSD and Solaris, with
-various hardware architectures.  These are the three platforms
-that are supported by the universial TUN/TAP device driver, so if
-support for other operating systems is added to this driver, perhaps
-tinc will run on them as well.  Without this driver, tinc will most
+tinc has been verified to work under Linux, FreeBSD, OpenBSD and Solaris, with
+various hardware architectures.  These are some of the platforms
+that are supported by the universal tun/tap device driver or other virtual network device drivers.
+Without such a driver, tinc will most
 likely compile and run, but it will not be able to send or receive data
 packets.
 
 @cindex release
-The official release only truly supports Linux.
 For an up to date list of supported platforms, please check the list on
 our website:
 @uref{http://tinc.nl.linux.org/platforms.html}.
@@ -202,24 +201,32 @@ and arbitrary word length.  So in theory it should run on other
 processors that Linux runs on.  It has already been verified to run on
 alpha and sparc processors as well.
 
-tinc uses the ethertap device or the universal TUN/TAP driver. The former is provided in the standard kernel
-from version 2.1.60 up to 2.3.x, but has been replaced in favour of the TUN/TAP driver in kernel versions 2.4.0 and later.
+tinc uses the ethertap device or the universal tun/tap driver. The former is provided in the standard kernel
+from version 2.1.60 up to 2.3.x, but has been replaced in favour of the tun/tap driver in kernel versions 2.4.0 and later.
 
 
 @c ==================================================================
 @subsection FreeBSD
 
 @cindex FreeBSD
-tinc on FreeBSD relies on the universial TUN/TAP driver for its data
+tinc on FreeBSD relies on the universal tun/tap driver for its data
 acquisition from the kernel.  Therefore, tinc will work on the same platforms
 as this driver.  These are: FreeBSD 3.x, 4.x, 5.x.
 
 
+@c ==================================================================
+@subsection OpenBSD
+
+@cindex OpenBSD
+tinc on OpenBSD relies on the tun driver for its data
+acquisition from the kernel. It has been verified to work under at least OpenBSD 2.9.
+
+
 @c ==================================================================
 @subsection Solaris
 
 @cindex Solaris
-tinc on Solaris relies on the universial TUN/TAP driver for its data
+tinc on Solaris relies on the universal tun/tap driver for its data
 acquisition from the kernel.  Therefore, tinc will work on the same platforms
 as this driver.  These are: Solaris, 2.1.x.
 
@@ -278,6 +285,7 @@ you should read the @uref{http://howto.linuxberg.com/LDP/HOWTO/Kernel-HOWTO.html
 * Configuration of Linux kernels 2.1.60 up to 2.4.0::
 * Configuration of Linux kernels 2.4.0 and higher::
 * Configuration of FreeBSD kernels::
+* Configuration of OpenBSD kernels::
 * Configuration of Solaris kernels::
 @end menu
 
@@ -329,18 +337,18 @@ Here are the options you have to turn on when configuring a new kernel:
 Code maturity level options
 [*] Prompt for development and/or incomplete code/drivers
 Network device support
-<M> Universal TUN/TAP device driver support
+<M> Universal tun/tap device driver support
 @end example
 
 It's not necessary to compile this driver as a module, even if you are going to
 run more than one instance of tinc.
 
-If you have an early 2.4 kernel, you can choose both the TUN/TAP driver and the
+If you have an early 2.4 kernel, you can choose both the tun/tap driver and the
 `Ethertap network tap' device.  This latter is marked obsolete, and chances are
 that it won't even function correctly anymore.  Make sure you select the
-universal TUN/TAP driver.
+universal tun/tap driver.
 
-If you decide to build the TUN/TAP driver as a kernel module, add these lines
+If you decide to build the tun/tap driver as a kernel module, add these lines
 to @file{/etc/modules.conf}:
 
 @example
@@ -349,24 +357,35 @@ alias char-major-10-200 tun
 
 
 @c ==================================================================
-@node       Configuration of FreeBSD kernels, Configuration of Solaris kernels, Configuration of Linux kernels 2.4.0 and higher, Configuring the kernel
+@node       Configuration of FreeBSD kernels, Configuration of OpenBSD kernels, Configuration of Linux kernels 2.4.0 and higher, Configuring the kernel
 @subsection Configuration of FreeBSD kernels
 
 This section will contain information on how to configure your FreeBSD
-kernel to support the universal TUN/TAP device.  For 5.0 and 4.1
-systems, this is included in the kernel configuration, for earlier
-systems (4.0 and 3.x), you need to install the universal TUN/TAP driver
+kernel to support the universal tun/tap device.  For 4.1 and higher
+versions, this is included in the default kernel configuration, for earlier
+systems (4.0 and earlier), you need to install the universal tun/tap driver
 yourself.
 
 Unfortunately somebody still has to write the text.
 
 
 @c ==================================================================
-@node       Configuration of Solaris kernels,  , Configuration of FreeBSD kernels, Configuring the kernel
+@node       Configuration of OpenBSD kernels, Configuration of Solaris kernels, Configuration of FreeBSD kernels, Configuring the kernel
+@subsection Configuration of OpenBSD kernels
+
+This section will contain information on how to configure your OpenBSD
+kernel to support the tun device.  For 2.9 and 3.0 systems,
+this is included in the default kernel configuration.
+
+Unfortunately somebody still has to write the text.
+
+
+@c ==================================================================
+@node       Configuration of Solaris kernels,  , Configuration of OpenBSD kernels, Configuring the kernel
 @subsection Configuration of Solaris kernels
 
 This section will contain information on how to configure your Solaris
-kernel to support the universal TUN/TAP device.  You need to install
+kernel to support the universal tun/tap device.  You need to install
 this driver yourself.
 
 Unfortunately somebody still has to write the text.
@@ -451,11 +470,11 @@ all other requirements of the GPL are met.
 @node    Installation, Configuration, Preparations, Top
 @chapter Installation
 
-If you use Redhat or Debian, you may want to install one of the
+If you use Debian, you may want to install one of the
 precompiled packages for your system.  These packages are equipped with
 system startup scripts and sample configurations.
 
-If you don't run either of these systems, or you want to compile tinc
+If you cannot use one of the precompiled packages, or you want to compile tinc
 for yourself, you can use the source.  The source is distributed under
 the GNU General Public License (GPL).  Download the source from the
 @uref{http://tinc.nl.linux.org/download.html, download page}, which has
@@ -528,7 +547,7 @@ chown 0.0 /dev/tap@emph{N}
 
 There is a maximum of 16 ethertap devices.
 
-If you use the universal TUN/TAP driver, you have to create the
+If you use the universal tun/tap driver, you have to create the
 following device file (unless it already exist):
 
 @example
@@ -537,8 +556,8 @@ chown 0.0 /dev/tun
 @end example
 
 If you use Linux, and you run the new 2.4 kernel using the devfs filesystem,
-then the TUN/TAP device will probably be automatically generated as
-@file{/dev/net/tun}.
+then the tun/tap device will probably be automatically generated as
+@file{/dev/misc/net/tun}.
 
 Unlike the ethertap device, you do not need multiple device files if
 you are planning to run multiple tinc daemons.
@@ -617,7 +636,7 @@ A good resource on networking is the
 
 If you have everything clearly pictured in your mind,
 proceed in the following order:
-First, generate the configuration files (tinc.conf, your host configuration file, tinc-up and perhaps tinc-down).
+First, generate the configuration files (@file{tinc.conf}, your host configuration file, @file{tinc-up} and perhaps @file{tinc-down}).
 Then generate the keypairs.
 Finally, distribute the host configuration files.
 These steps are described in the subsections below.
@@ -717,8 +736,28 @@ required directives are given in @strong{bold}.
 @subsection Main configuration variables
 
 @table @asis
-@item @strong{ConnectTo = <name>}
+@cindex BindToInterface
+@item BindToInterface = <interface>
+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.
+
+This option may not work on all platforms.
+
+@cindex BindToIP
+@item BindToIP = <address>
+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.
+
+This option may not work on all platforms.
+
 @cindex ConnectTo
+@item @strong{ConnectTo = <name>}
 Specifies which host to connect to on startup.  Multiple ConnectTo
 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
@@ -729,8 +768,13 @@ If you don't specify a host with ConnectTo, regardless of whether a
 value for ConnectPort is given, tinc won't connect at all, and will
 instead just listen for incoming connections.
 
-@item Hostnames = <yes|no> (no)
+@cindex Device
+@item @strong{Device = <device>} (/dev/tap0 or /dev/misc/net/tun)
+The virtual network device to use.  Note that you can only use one device per
+daemon.  See also @ref{Device files}.
+
 @cindex Hostnames
+@item Hostnames = <yes|no> (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
@@ -739,57 +783,68 @@ it does a lookup if your DNS server is not responding.
 This does not affect resolving hostnames to IP addresses from the
 configuration file.
 
-@item Interface = <device>
 @cindex Interface
-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.
+@item Interface = <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.
+Currently this option only affects the Linux tun/tap device.
 
-@item InterfaceIP = <local address>
-@cindex InterfaceIP
-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.
+@cindex Mode
+@item Mode = <router|switch|hub> (router)
+This option selects the way packets are routed to other daemons.
+
+@table @asis
+@cindex router
+@item router
+In this mode 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.
+
+@cindex switch
+@item switch
+In this mode the MAC addresses of the packets on the VPN will be used to
+dynamically create a routing table just like a network switch does.
+Unicast, multicast and broadcast packets of every ethernet protocol are supported in this mode
+at the cost of frequent broadcast ARP requests and routing table updates.
+
+@cindex hub
+@item hub
+In this mode every packet will be broadcast to the other daemons.
+@end table
 
-@item KeyExpire = <seconds> (3600)
 @cindex KeyExpire
+@item KeyExpire = <seconds> (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.
 
-@item @strong{Name = <name>}
 @cindex Name
+@item @strong{Name = <name>}
 This is a symbolic name for this connection.  It can be anything
 
-@item PingTimeout = <seconds> (60)
 @cindex PingTimeout
+@item PingTimeout = <seconds> (60)
 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.
 
-@item PrivateKey = <key> [obsolete]
 @cindex PrivateKey
+@item PrivateKey = <key> [obsolete]
 This is the RSA private key for tinc. However, for safety reasons it is
 advised to store private keys of any kind in separate files. This prevents
 accidental eavesdropping if you are editting the configuration file.
 
-@item @strong{PrivateKeyFile = <path>} [recommended]
 @cindex PrivateKeyFile
+@item @strong{PrivateKeyFile = <path>} [recommended]
 This is the full path name of the RSA private key file that was
 generated by ``tincd --generate-keys''.  It must be a full path, not a
 relative directory.
 
-@item @strong{TapDevice = <device>} (/dev/tap0 or /dev/net/tun)
-@cindex TapDevice
-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.
+Note that there must be exactly one of PrivateKey
+or PrivateKeyFile
+specified in the configuration file.
 
 @end table
 
@@ -799,33 +854,50 @@ about configuring an ethertap device for Linux.
 @subsection Host configuration variables
 
 @table @asis
-@item @strong{Address = <IP address|hostname>} [recommended]
 @cindex Address
+@item @strong{Address = <IP address|hostname>} [recommended]
 This variable is only required if you want to connect to this host.  It
 must resolve to the external IP address where the host can be reached,
 not the one that is internal to the VPN.
 
-@item IndirectData = <yes|no> (no) [experimental]
+@cindex Cipher
+@item Cipher = <cipher> (blowfish)
+The symmetric cipher algorithm used to encrypt UDP packets.
+Any cipher supported by OpenSSL is recognized.
+
+@cindex Digest
+@item Digest = <digest> (sha1)
+The digest algorithm used to authenticate UDP packets.
+Any digest supported by OpenSSL is recognized.
+Furthermore, specifying "none" will turn off packet authentication.
+
 @cindex IndirectData
+@item IndirectData = <yes|no> (no) [experimental]
 This option specifies whether other tinc daemons besides the one you
 specified with 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.
 
-@item Port = <port> (655)
+@cindex MACLength
+@item MACLength = <length> (4)
+The length of the message authentication code used to authenticate UDP packets.
+Can be anything from 0
+up to the length of the digest produced by the digest algorithm.
+
 @cindex Port
+@item Port = <port> (655)
 Connect to the upstream host (given with the ConnectTo directive) on
 port port.  port may be given in decimal (default), octal (when preceded
 by a single zero) o hexadecimal (prefixed with 0x).  port is the port
 number for both the UDP and the TCP (meta) connections.
 
-@item PublicKey = <key> [obsolete]
 @cindex PublicKey
+@item PublicKey = <key> [obsolete]
 This is the RSA public key for this host.
 
-@item PublicKeyFile = <path> [obsolete]
 @cindex PublicKeyFile
+@item PublicKeyFile = <path> [obsolete]
 This is the full path name of the RSA public key file that was generated
 by ``tincd --generate-keys''.  It must be a full path, not a relative
 directory.
@@ -838,22 +910,29 @@ necessary. Either the PEM format is used, or exactly
 in each host configuration file, if you want to be able to establish a
 connection with that host.
 
-@item Subnet = <IP address/maskbits>
 @cindex Subnet
-This is the subnet range of all IP addresses that will be accepted by
-the host that defines it.
-
-The range must be contained in the IP address range of the tap device,
-not the real IP address of the host running tincd.
+@item Subnet = <address[/masklength]>
+The subnet which this tinc daemon will serve.
+tinc tries to look up which other daemon it should send a packet to by searching the appropiate subnet.
+If the packet matches a subnet,
+it will be sent to the daemon who has this subnet in his host configuration file.
+Multiple subnet lines can be specified for each daemon.
+
+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 masklength.
+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!
 
 @cindex CIDR notation
-maskbits is the number of bits set to 1 in the netmask part; for
+masklength is the number of bits set to 1 in the netmask part; for
 example: netmask 255.255.255.0 would become /24, 255.255.252.0 becomes
 /22. This conforms to standard CIDR notation as described in
 @uref{ftp://ftp.isi.edu/in-notes/rfc1519.txt, RFC1519}
 
-@item TCPonly = <yes|no> (no) [experimental]
 @cindex TCPonly
+@item TCPonly = <yes|no> (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
@@ -874,7 +953,7 @@ Adapt the following example to create a basic configuration file:
 
 @example
 Name = @emph{yourname}
-TapDevice = @emph{/dev/tap0}
+Device = @emph{/dev/tap0}
 PrivateKeyFile = /etc/tinc/@emph{netname}/rsa_key.priv
 @end example
 
@@ -919,37 +998,39 @@ Just press enter to accept the defaults.
 @section Network interfaces
 
 Before tinc can start transmitting data over the tunnel, it must
-set up the ethertap network devices.
+set up the virtual network interface.
 
 First, decide which IP addresses you want to have associated with these
 devices, and what network mask they must have.
 
-tinc will open an ethertap device or TUN/TAP device, which will also
-create a network interface called `tap0', or `tap1', and so on if you are using
-the ethertap driver, or a network interface with the same name as netname
-if you are using the universal TUN/TAP driver.
+tinc will open a virtual network device (@file{/dev/tun}, @file{/dev/tap0} or similar),
+which will also create a network interface called something like `tun0', `tap0', or,
+if you are using the Linux tun/tap driver, the network interface will by default have the same name as the netname.
 
 @cindex tinc-up
-You can configure that device by putting ordinary ifconfig, route, and other commands
+You can configure the network interface by putting ordinary ifconfig, route, and other commands
 to a script named @file{/etc/tinc/netname/tinc-up}. When tinc starts, this script
 will be executed. When tinc exits, it will execute the script named
 @file{/etc/tinc/netname/tinc-down}, but normally you don't need to create that script.
 
-An example @file{tinc-up} script when using the TUN/TAP driver:
+An example @file{tinc-up} script:
 
 @example
 #!/bin/sh
-ifconfig $NETNAME hw ether fe:fd:00:00:00:00
-ifconfig $NETNAME @emph{xx}.@emph{xx}.@emph{xx}.@emph{xx} netmask @emph{mask}
-ifconfig $NETNAME -arp
+ifconfig $INTERFACE hw ether fe:fd:0:0:0:0
+ifconfig $INTERFACE 192.168.1.1 netmask 255.255.0.0
+ifconfig $INTERFACE -arp
 @end example
 
 @cindex MAC address
 @cindex hardware address
 The first line sets up the MAC address of the network interface.
-Due to the nature of how Ethernet and tinc work, it has to be set to fe:fd:00:00:00:00.
-(tinc versions prior to 1.0pre3 required that the MAC address matched the IP address.)
-You can use the environment variable $NETNAME to get the name of the interface.
+Due to the nature of how Ethernet and tinc work, it has to be set to fe:fd:0:0:0:0
+for tinc to work in it's normal mode.
+If you configured tinc to work in `switch' or `hub' mode, the hardware address should instead
+be set to a unique address instead of fe:fd:0:0:0:0.
+
+You can use the environment variable $INTERFACE to get the name of the interface.
 If you are using the ethertap driver however, you need to replace it with tap@emph{N},
 corresponding to the device file name.
 
@@ -964,7 +1045,8 @@ own subnet.
 
 @cindex arp
 The last line tells the kernel not to use ARP on that interface.
-Again this has to do with how Ethernet and tinc work. Don't forget to add this line.
+Again this has to do with how Ethernet and tinc work.
+Use this option only if you are running tinc under Linux and are using tinc's normal routing mode.
 
 
 @c ==================================================================
@@ -1010,7 +1092,7 @@ In @file{/etc/tinc/company/tinc-up}:
 # Real interface of internal network:
 # ifconfig eth0 10.1.54.1 netmask 255.255.0.0 broadcast 10.1.255.255
 
-ifconfig tap0 hw ether fe:fd:00:00:00:00
+ifconfig tap0 hw ether fe:fd:0:0:0:0
 ifconfig tap0 10.1.54.1 netmask 255.0.0.0
 ifconfig tap0 -arp
 @end example
@@ -1020,7 +1102,7 @@ and in @file{/etc/tinc/company/tinc.conf}:
 @example
 Name = BranchA
 PrivateKey = /etc/tinc/company/rsa_key.priv
-TapDevice = /dev/tap0
+Device = /dev/tap0
 @end example
 
 On all hosts, /etc/tinc/company/hosts/BranchA contains:
@@ -1048,7 +1130,7 @@ In @file{/etc/tinc/company/tinc-up}:
 # Real interface of internal network:
 # ifconfig eth0 10.2.43.8 netmask 255.255.0.0 broadcast 10.2.255.255
 
-ifconfig tap0 hw ether fe:fd:00:00:00:00
+ifconfig tap0 hw ether fe:fd:0:0:0:0
 ifconfig tap0 10.2.1.12 netmask 255.0.0.0
 ifconfig tap0 -arp
 @end example
@@ -1085,7 +1167,7 @@ In @file{/etc/tinc/company/tinc-up}:
 # Real interface of internal network:
 # ifconfig eth0 10.3.69.254 netmask 255.255.0.0 broadcast 10.3.255.255
 
-ifconfig tap1 hw ether fe:fd:00:00:00:00
+ifconfig tap1 hw ether fe:fd:0:0:0:0
 ifconfig tap1 10.3.69.254 netmask 255.0.0.0
 ifconfig tap1 -arp
 @end example
@@ -1095,7 +1177,7 @@ and in @file{/etc/tinc/company/tinc.conf}:
 @example
 Name = BranchC
 ConnectTo = BranchA
-TapDevice = /dev/tap1
+Device = /dev/tap1
 @end example
 
 C already has another daemon that runs on port 655, so they have to
@@ -1133,13 +1215,13 @@ and in @file{/etc/tinc/company/tinc.conf}:
 @example
 Name = BranchD
 ConnectTo = BranchC
-TapDevice = /dev/net/tun
+Device = /dev/misc/net/tun
 PrivateKeyFile = /etc/tinc/company/rsa_key.priv
 @end example
 
 D will be connecting to C, which has a tincd running for this network on
 port 2000. It knows the port number from the host configuration file.
-Also note that since D uses the TUN/TAP driver, the network interface
+Also note that since D uses the tun/tap driver, the network interface
 will not be called `tun' or `tap0' or something like that, but will
 have the same name as netname.
 
@@ -1211,33 +1293,19 @@ generated automatically, so may be more up-to-date.
 @cindex options
 @c from the manpage
 @table @samp
+@item --bypass-security
+Disables encryption and authentication.
+Only useful for debugging.
+
 @item -c, --config=PATH
 Read configuration options from the directory PATH.  The default is
 @file{/etc/tinc/netname/}.
 
 @cindex debug level
-@item -d
-Increase debug level.  The higher it gets, the more gets
+@item -d, --debug=LEVEL
+Set debug level to LEVEL.  The higher the debug level, the more gets
 logged.  Everything goes via syslog.
 
-0 is the default, only some basic information connection attempts get
-logged.  Setting it to 1 will log a bit more, still not very
-disturbing.  With two -d's tincd will log protocol information, which can
-get pretty noisy.  Three or more -d's will output every single packet
-that goes out or comes in, which probably generates more data than the
-packets themselves.
-
-@item -k, --kill
-Attempt to kill a running tincd and exit.  A TERM signal (15) gets sent
-to the daemon that his its PID in /var/run/tinc.pid.
-
-Because it kills only one tinc daemon, you should use -n here if you
-started it that way.  It will then read the PID from
-@file{/var/run/tinc.NETNAME.pid}.
-
-@item -n, --net=NETNAME
-Connect to net NETNAME.  @xref{Multiple networks}.
-
 @item -K, --generate-keys[=BITS]
 Generate public/private keypair of BITS length. If BITS is not specified,
 1024 is the default. tinc will ask where you want to store the files,
@@ -1247,6 +1315,18 @@ in combination with -K). After that, tinc will quit.
 @item --help
 Display a short reminder of these runtime options and terminate.
 
+@item -k, --kill
+Attempt to kill a running tincd and exit.  A TERM signal (15) gets sent
+to the daemon that his its PID in @file{/var/run/tinc.NETNAME.pid}.
+Use it in conjunction with the -n option to make sure you kill the right tinc daemon.
+
+@item -n, --net=NETNAME
+Connect to net NETNAME.  @xref{Multiple networks}.
+
+@item -D, --no-detach
+Don't fork and detach.
+This will also disable the automatic restart mechanism for fatal errors.
+
 @item --version
 Output version information and exit.
 
@@ -1269,7 +1349,7 @@ only, so keep an eye on it!
 @item You forgot to compile `Netlink device emulation' in the kernel.
 @end itemize
 
-@item Can't write to /dev/net/tun: No such device
+@item Can't write to /dev/misc/net/tun: No such device
 
 @itemize
 @item You forgot to `modprobe tun'.
@@ -1280,10 +1360,10 @@ only, so keep an eye on it!
 
 @itemize
 @item Something is not configured right. Packets are being sent out to the
-tap device, but according to the Subnet directives in your host configuration
+virtual network device, but according to the Subnet directives in your host configuration
 file, those packets should go to your own host. Most common mistake is that
 you have a Subnet line in your host configuration file with a netmask which is
-just as large as the netmask of the tap device. The latter should in almost all
+just as large as the netmask of the virtual network interface. The latter should in almost all
 cases be larger. Rethink your configuration.
 Note that you will only see this message if you specified a debug
 level of 5 or higher!
@@ -1300,7 +1380,7 @@ Jan 1 12:00:00 host tinc.net[1234]: Read packet of length 46 from tap device
 Jan 1 12:00:00 host tinc.net[1234]: Trying to look up 0.0.192.168 in connection list failed!
 @end example
 @itemize
-@item Add the `ifconfig $NETNAME -arp' to tinc-up.
+@item Add the `ifconfig $INTERFACE -arp' to tinc-up.
 @end itemize
 
 @item Network address and subnet mask do not match!
@@ -1360,10 +1440,10 @@ computer over the existing Internet infrastructure.
 @node    The UDP tunnel, The meta-connection, The connection, The connection
 @subsection The UDP tunnel
 
-@cindex ethertap
+@cindex virtual network device
 @cindex frame type
 The data itself is read from a character device file, the so-called
-@emph{ethertap} device.  This device is associated with a network
+@emph{virtual network device}.  This device is associated with a network
 interface.  Any data sent to this interface can be read from the device,
 and any data written to the device gets sent from the interface.  Data to
 and from the device is formatted as if it were a normal Ethernet card,
@@ -1371,32 +1451,35 @@ so a frame is preceded by two MAC addresses and a @emph{frame type}
 field.
 
 So when tinc reads an Ethernet frame from the device, it determines its
-type.  Right now, tinc can only handle Internet Protocol version 4 (IPv4)
-frames, because it needs IP headers for routing.
-Plans to support other protocols and switching instead of routing are being made.
-(Some code for IPv6 routing and switching is already present but nonfunctional.)
-When tinc knows
-which type of frame it has read, it can also read the source and
-destination address from it.
+type. When tinc is in it's default routing mode, it can handle IPv4 and IPv6
+packets. Depending on the Subnet lines, it will send the packets off to their destination.
+In the `switch' and `hub' mode, tinc will use broadcasts and MAC address discovery
+to deduce the destination of the packets.
+Since the latter modes only depend on the link layer information,
+any protocol that runs over Ethernet is supported (for instance IPX and Appletalk).
 
-Now it is time that the frame gets encrypted.  Currently the only
-encryption algorithm available is blowfish.
+After the destination has been determined, a sequence number will be added to the packet.
+The packet will then be encrypted and a message authentication
+code will be appended.
 
 @cindex encapsulating
 @cindex UDP
-When the encryption is ready, time has come to actually transport the
+When that is done, time has come to actually transport the
 packet to the destination computer.  We do this by sending the packet
 over an UDP connection to the destination host.  This is called
 @emph{encapsulating}, the VPN packet (though now encrypted) is
 encapsulated in another IP datagram.
 
 When the destination receives this packet, the same thing happens, only
-in reverse.  So it does a decrypt on the contents of the UDP datagram,
-and it writes the decrypted information to its own ethertap device.
+in reverse.  So it checks the message authentication code, decrypts the contents of the UDP datagram,
+checks the sequence number
+and writes the decrypted information to its own virtual network device.
 
 To let the kernel on the receiving end accept the packet, the destination MAC
-address must match that of the tap interface. Because of the routing nature
-of tinc, ARP is not possible. tinc solves this by always overwriting the
+address must match that of the virtual network interface.
+If tinc is in it's default routing mode, ARP does not work, so the correct destination MAC cannot be set
+by the sending daemons.
+tinc solves this by always overwriting the
 destination MAC address with fe:fd:0:0:0:0. That is also the reason why you must
 set the MAC address of your tap interface to that address.
 
@@ -1451,32 +1534,35 @@ daemon and to read and write requests by hand, provided that one
 understands the numeric codes sent.
 
 The authentication scheme is described in @ref{Authentication protocol}. After a
-succesful authentication, the server and the client will exchange all the
+successful authentication, the server and the client will exchange all the
 information about other tinc daemons and subnets they know of, so that both
 sides (and all the other tinc daemons behind them) have their information
 synchronised.
 
-@cindex ADD_HOST
+@cindex ADD_EDGE
 @cindex ADD_SUBNET
 @example
 daemon message
 --------------------------------------------------------------------------
-origin ADD_HOST daemon a329e18c:655 0
-                    |         |      +--> options
-                    |         +---------> real address:port
-                    +-------------------> name of new tinc daemon
-origin ADD_SUBNET daemon 1,0a010100/ffffff00
-                      |   |     |       +--> netmask
-                      |   |     +----------> vpn IPv4 network address
-                      |   +----------------> subnet type (1=IPv4)
-                      +--------------------> owner of this subnet
+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_SUBNET node 192.168.1.0/24
+                     |         |     +--> masklength
+                     |         +--------> IPv4 network address
+                     +------------------> owner of this subnet
 --------------------------------------------------------------------------
 @end example
 
-@cindex DEL_HOST
-@cindex DEL_SUBNET
-In case daemons leave the VPN, DEL_HOST and DEL_SUBNET messages with exactly
-the same syntax are sent to inform the other daemons of the departure.
+@cindex DEL_EDGE
+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.
 
 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
@@ -1484,7 +1570,7 @@ chances are that not every tinc daemon will ever send a packet to every
 other daemon. Instead, if a daemon needs a key it sends a request for it
 via the meta connection of the nearest hop in the direction of the
 destination. If any hop on the way has already learned the key, it will
-act as a proxy and forward it's copy back to the requestor.
+act as a proxy and forward its copy back to the requester.
 
 @cindex REQ_KEY
 @cindex ANS_KEY
@@ -1495,11 +1581,15 @@ 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 e4ae0b0a82d6e0078179b5290c62c7d0
-                   |       |       \______________________________/
-                   |       |                      +--> 128 bits 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
 --------------------------------------------------------------------------
@@ -1518,12 +1608,8 @@ messages without any other traffic won't result in known plaintext.
 @example
 daemon message
 --------------------------------------------------------------------------
-origin PING 9e76
-             \__/
-               +--> 2 bytes of salt (random data)
-dest.  PONG 3b8d
-             \__/
-               +--> 2 bytes of salt (random data)
+origin PING
+dest.  PONG
 --------------------------------------------------------------------------
 @end example
 
@@ -1546,9 +1632,8 @@ the tinc project after TINC.
 But in order to be ``immune'' to eavesdropping, you'll have to encrypt
 your data.  Because tinc is a @emph{Secure} VPN (SVPN) daemon, it does
 exactly that: encrypt.
-tinc uses blowfish encryption in CBC mode and a small amount of salt
-at the beginning of each packet to make sure eavesdroppers cannot get
-any information at all from the packets they can intercept.
+tinc uses blowfish encryption in CBC mode, sequence numbers and message authentication codes
+to make sure eavesdroppers cannot get and cannot change any information at all from the packets they can intercept.
 
 @menu
 * Authentication protocol::
@@ -1565,6 +1650,11 @@ A new scheme for authentication in tinc has been devised, which offers some
 improvements over the protocol used in 1.0pre2 and 1.0pre3. Explanation is
 below.
 
+@cindex ID
+@cindex META_KEY
+@cindex CHALLENGE
+@cindex CHAL_REPLY
+@cindex ACK
 @example
 daemon  message
 --------------------------------------------------------------------------
@@ -1572,15 +1662,13 @@ client  <attempts connection>
 
 server  <accepts connection>
 
-client  ID client 10 0
-              |    | +-> options
-              |    +---> version
-              +--------> name of tinc daemon
+client  ID client 12
+              |   +---> version
+              +-------> name of tinc daemon
 
-server  ID server 10 0
-              |    | +-> options
-              |    +---> version
-              +--------> name of tinc daemon
+server  ID server 12
+              |   +---> version
+              +-------> name of tinc daemon
 
 client  META_KEY 5f0823a93e35b69e...7086ec7866ce582b
                  \_________________________________/
@@ -1593,8 +1681,8 @@ server  META_KEY 6ab9c1640388f8f0...45d1a07f8a672630
                                      encrypted with client's public RSA key
 
 From now on:
- - the client will encrypt outgoing traffic using S1
- - the server will encrypt outgoing traffic using S2
+ - the client will symmetrically encrypt outgoing traffic using S1
+ - the server will symmetrically encrypt outgoing traffic using S2
 
 client  CHALLENGE da02add1817c1920989ba6ae2a49cecbda0
                   \_________________________________/
@@ -1609,6 +1697,21 @@ client  CHAL_REPLY 816a86
 
 server  CHAL_REPLY 928ffe
                       +-> 160 bits SHA1 of H1
+
+After the correct challenge replies are received, 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
+
+server  ACK 655 21.32.43.54 321 0
+             |       |       |  +-> options
+            |       |       +----> estimated weight
+            |       +------------> IP address of client as seen by server
+            +--------------------> UDP port of server
 --------------------------------------------------------------------------
 @end example
 
@@ -1662,35 +1765,26 @@ an attacker) in the beginning of the encrypted stream.
 A data packet can only be sent if the encryption key is known to both
 parties, and the connection is  activated. If the encryption key is not
 known, a request is sent to the destination using the meta connection
-to retreive it. The packet is stored in a queue while waiting for the
+to retrieve it. The packet is stored in a queue while waiting for the
 key to arrive.
 
 @cindex UDP
 The UDP packet containing the network packet from the VPN has the following layout:
 
 @example
-... | IP header | UDP header | salt | VPN packet | UDP trailer
-                             \___________________/
-                                       |
-                                       V
+... | IP header | UDP header | seqno | VPN packet | MAC | UDP trailer
+                             \___________________/\_____/
+                                       |             |
+                                       V             +---> digest algorithm
                          Encrypted with symmetric cipher
 @end example
 
-So, the entire UDP payload is encrypted using a symmetric cipher (blowfish in CBC mode).
-2 bytes of salt (random data) are added in front of the actual VPN packet,
-so that two VPN packets with (almost) the same content do not seem to be
-the same for eavesdroppers.
-2 bytes of salt may not seem much, but you can encrypt 65536 identical packets
-now without an attacker being able to see that they were identical.
-Given a MTU of 1500 this means 96 Megabyte of data.
-
-There is no @emph{extra} provision against replay attacks or alteration of packets.
-However, the VPN packets, normally UDP or TCP packets themselves, contain
-checksums and sequence numbers.
-Since those checksums and sequence numbers are encrypted,
-they automatically become @emph{cryptographically secure}.
-The kernel will handle any checksum errors and duplicate packets.
-
+So, the entire VPN packet is encrypted using a symmetric cipher. A 32 bits
+sequence number is added in front of the actual VPN packet, to act as a unique
+IV for each packet and to prevent replay attacks. A message authentication code
+is added to the UDP packet to prevent alteration of packets. By default the
+first 4 bytes of the digest are used for this, but this can be changed using
+the MACLength configuration variable.
 
 @c ==================================================================
 @node    About us, Concept Index, Technical information, Top
index 138d81169b4d929cf4944f8599ec23257a215615..6c47610537e352e6dd99b1ea94bf2ba8845c4a55 100644 (file)
-.TH TINCD 8 "Jan 2001" "tinc version 1.0pre4" "FSF"
-.SH NAME
-tincd \- tinc VPN daemon
-.SH SYNOPSIS
-.B tincd
-[\fIoption\fR]...
-.SH DESCRIPTION
-.PP
-
-This is the daemon of tinc, a secure virtual private
-network (VPN) project. When started, tincd will read
-it's configuration file to determine what virtual subnets
-it has to serve and to what other tinc daemons it should connect.
-It will connect to the ethertap or tun/tap device and set up a socket
-for incoming connections.
-Optionally a script will be executed to further configure the tap device.
-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.
-
-.SH OPTIONS
-.TP
-\fB\-c\fR, \fB\-\-config\fR=\fIDIR\fR
-Read configuration options from DIR.
-.TP
-\fB\-D\fR, \fB\-\-no\-detach\fR
-Don't fork and detach. This will also disable the automatic
-restart mechanism for fatal errors.
-.TP
-\fB\-d\fR
-Increase debug level (see below).
-.TP
-\fB\-k\fR, \fB\-\-kill\fR
-Attempt to kill a running tincd and exit.
-.TP
-\fB\-n\fR, \fB\-\-net\fR=\fInetname\fR
-Connect to net `netname'.
-.TP
-\fB\-K\fR, \fB\-\-generate-keys\fR[=\fIBITS]\fR
-Generate public/private RSA keypair and exit. If BITS is omitted,
-the default length will be 1024 bits.
-.TP
-\fB\-\-help\fR
+.Dd 2002-02-07
+.Dt TINCD 8
+.\" Manual page created by:
+.\" Ivo Timmermans <itimmermans@bigfoot.com>
+.\" Guus Sliepen <guus@sliepen.warande.net>
+.Sh NAME
+.Nm tincd
+.Nd tinc VPN daemon
+.Sh SYNOPSIS
+.Nm
+.Op Fl cdDkKn
+.Op Fl -bypass-security
+.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 -version
+.Sh DESCRIPTION
+This is the daemon of tinc, a secure virtual private network (VPN) project.
+When started,
+.Nm
+will read it's configuration file to determine what virtual subnets it has to serve
+and to what other tinc daemons it should connect.
+It will connect to the ethertap or tun/tap device
+and set up a socket for incoming connections.
+Optionally a script will be executed to further configure the virtual device.
+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.
+.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 .
+.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.
-.TP
-\fB\-\-version\fR
+.It Fl k, -kill Ns Op = Ns Ar SIGNAL
+Attempt to kill a running
+.Nm
+(optionally with the specified
+.Ar SIGNAL
+instead of SIGQUIT) and exit.
+.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 -version
 Output version information and exit.
-.PP
-.SH "SIGNALS"
-.TP
-\fBHUP\fR
+.El
+.Sh SIGNALS
+.Bl -tag -width indent
+.It ALRM
+Forces
+.Nm
+to try to connect to all uplinks immediately.
+Usually
+.Nm
+attempts to do this itself,
+but increases the time it waits between the attempts each time it failed,
+and if
+.Nm
+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.
-.TP
-\fBINT\fR
-Closes all connections and quits.
-.TP
-\fBUSR1\fR
+.It INT
+Temporarily increases debug level to 5.
+Send this signal again to revert to the original level.
+.It USR1
 Dumps the connection list to syslog.
-.TP
-\fBUSR2\fR
-Dumps the subnet list to syslog.
-.TP
-\fBALRM\fR
-Forces tincd to try to connect to an uplink immediately. Usually tincd attempts
-to do this itself, but increases the time it waits between the attempts each time
-it failed, and if tincd didn't succeed to connect to an uplink the first time after
-it started, it defaults to the maximum time of 15 minutes.
-.PP
-.SH "DEBUG LEVELS"
-The tinc daemon can send a lot of messages to the syslog. The more \fB\-d\fR options are
-given to tincd, the more messages it will log. Each level inherits all messages of the
-previous level:
-.TP
-\fIno debug options\fR
-This will log a message indicating tincd has started along with a version number.
+.It USR2
+Dumps virtual network device statistics, all known nodes, edges and subnets to syslog.
+.It WINCH
+Purges all information remembered about unreachable nodes.
+.El
+.Sh DEBUG LEVELS
+The tinc daemon can send a lot of messages to the syslog.
+The higher the debug level,
+the more messages it will log.
+Each level inherits all messages of the previous level:
+.Bl -tag -width indent
+.It 0
+This will log a message indicating
+.Nm
+has started along with a version number.
 It will also any serious error.
-.TP
-\fB\-d\fR
+.It 1
 This will log all connections that are made with other tinc daemons.
-.TP
-\fB\-dd\fR
+.It 2
 This will log status and error messages from other tinc daemons.
-.TP
-\fB\-ddd\fR
+.It 3
 This will log all requests that are exchanged with other tinc daemons. These include
 authentication, key exchange and connection list updates.
-.TP
-\fB\-dddd\fR
+.It 4
 This will log a copy of everything received on the meta socket.
-.TP
-\fB\-ddddd\fR
+.It 5
 This will log all network traffic over the virtual private network.
-.PP
-.SH "FILES"
-.TP
-\fI/etc/tinc/\fBnetname\fI/tinc.conf\fR
-The configuration file for tincd.
-.TP
-\fI/etc/tinc/\fBnetname\fI/tinc-up\fR
-Script which is executed as soon as a tap device has been allocated.
+.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.
-.TP
-\fI/etc/tinc/\fBnetname\fI/tinc-down\fR
-Script which is executed when tinc quits.
-Purpose is to shut down the tap device.
-.TP
-\fI/etc/tinc/\fBnetname\fI/hosts/*\fR
+.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.
-.TP
-\fI/var/run/tinc.\fBnetname\fI.pid\fR
-The PID of the currently running tincd is stored in this file.
-.PP
-.SH "BUGS"
-The TCPonly and IndirectData options may not work correctly.
-.PP
-\fBThe cryptography in tinc is not well tested yet. Use it at your own risk!\fR
-.PP
-If you find any bugs, report them to tinc@nl.linux.org.
-.PP
-.SH "TODO"
-A lot, especially security auditting.
-.PP 
-.SH "SEE ALSO"
-\fBtinc.conf\fR(5)
-.TP
-\fBhttp://tinc.nl.linux.org/\fR
-.TP
-\fBhttp://www.cabal.org/\fR
-.PP
-The full documentation for
-.B tinc
-is maintained as a Texinfo manual.  If the
-.B info
+.It Pa /var/run/tinc. Ns Ar NETNAME Ns Pa .pid
+The PID of the currently running
+.Nm
+is stored in this file.
+.El
+.Sh BUGS
+The
+.Va BindToInterface ,
+.Va BindToIP ,
+.Va IndirectData
 and
-.B tinc
-programs are properly installed at your site, the command
-.IP
-.B info tinc
-.PP
+.Va TCPOnly
+options may not work correctly.
+.Pp
+.Sy The cryptography in tinc is not well tested yet. Use it at your own risk!
+.Pp
+If you find any bugs, report them to tinc@nl.linux.org.
+.Sh TODO
+A lot, especially security auditing.
+.Sh SEE ALSO
+.Xr tinc.conf 5 ,
+.Pa http://tinc.nl.linux.org/ ,
+.Pa http://www.cabal.org/ .
+.Pp
+The full documentation for tinc is maintained as a Texinfo manual.
+If the info and tinc programs are properly installed at your site,
+the command
+.Ic info tinc
 should give you access to the complete manual.
-.PP
-tinc comes with ABSOLUTELY NO WARRANTY.  This is free software,
-and you are welcome to redistribute it under certain conditions;
+.Pp
+tinc comes with ABSOLUTELY NO WARRANTY.
+This is free software, and you are welcome to redistribute it under certain conditions;
 see the file COPYING for details.
-.SH "AUTHORS"
-.na
-.nf
-Ivo Timmermans <itimmermans@bigfoot.com>
-Guus Sliepen <guus@sliepen.warande.net>
-
+.Sh AUTHORS
+.An "Ivo Timmermans" Aq itimmermans@bigfoot.com
+.An "Guus Sliepen" Aq guus@sliepen.warande.net
+.Pp
 And thanks to many others for their contributions to tinc!
-.PP
index a07f123f9fb3cf7ee814230fcd13bf84a74d3f7c..a4f005182a0051d6f33e1a90d7b6186778a9f1bc 100644 (file)
@@ -29,7 +29,7 @@
     library for inclusion into tinc (http://tinc.nl.linux.org/) by
     Guus Sliepen <guus@sliepen.warande.net>.
 
-    $Id: avl_tree.c,v 1.1.2.7 2001/02/27 16:50:29 guus Exp $
+    $Id: avl_tree.c,v 1.1.2.8 2002/02/10 21:57:51 guus Exp $
 */
 
 #include <stdio.h>
@@ -597,6 +597,15 @@ void avl_unlink_node(avl_tree_t *tree, avl_node_t *node)
   }
 
   avl_rebalance(tree, balnode);
+  
+  node->next = node->prev = node->parent = node->left = node->right = NULL;
+
+#ifdef AVL_COUNT
+  node->count = 0;
+#endif
+#ifdef AVL_DEPTH
+  node->depth = 0;
+#endif
 }
 
 void avl_delete_node(avl_tree_t *tree, avl_node_t *node)
index 04ddac0421d722d57ce8b05a210ed6bdc6a8e985..66aaa316f20cbaee6911af2b8d6f768b691664b3 100644 (file)
@@ -17,7 +17,7 @@
     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.1.2.7 2001/11/16 17:36:56 zarq Exp $
+    $Id: dropin.c,v 1.1.2.8 2002/02/10 21:57:51 guus Exp $
 */
 
 #include "config.h"
@@ -169,188 +169,3 @@ int asprintf(char **buf, const char *fmt, ...)
   return status;
 }
 #endif
-
-
-/*
- * fake library for ssh
- *
- * This file is included in getaddrinfo.c and getnameinfo.c.
- * See getaddrinfo.c and getnameinfo.c.
- */
-
-/* $Id: dropin.c,v 1.1.2.7 2001/11/16 17:36:56 zarq Exp $ */
-
-/* for old netdb.h */
-#ifndef EAI_NODATA
-#define EAI_NODATA     1
-#define EAI_MEMORY     2
-#endif
-
-/*
- * 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.
- */
-
-#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.";
-               default:
-                       return "unknown error.";
-       }
-}    
-#endif /* !HAVE_GAI_STRERROR */
-
-#ifndef HAVE_FREEADDRINFO
-void freeaddrinfo(struct addrinfo *ai)
-{
-       struct addrinfo *next;
-
-       do {
-               next = ai->ai_next;
-               free(ai);
-       } while (NULL != (ai = next));
-}
-#endif /* !HAVE_FREEADDRINFO */
-
-#ifndef HAVE_GETADDRINFO
-static struct addrinfo *malloc_ai(int port, u_long addr)
-{
-       struct addrinfo *ai;
-
-       ai = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
-       if (ai == NULL)
-               return(NULL);
-       
-       memset(ai, 0, sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
-       
-       ai->ai_addr = (struct sockaddr *)(ai + 1);
-       /* XXX -- ssh doesn't use sa_len */
-       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 *cur, *prev = NULL;
-       struct hostent *hp;
-       struct in_addr in;
-       int i, port;
-
-       if (servname)
-               port = htons(atoi(servname));
-       else
-               port = 0;
-
-       if (hints && hints->ai_flags & AI_PASSIVE) {
-               if (NULL != (*res = malloc_ai(port, htonl(0x00000000))))
-                       return 0;
-               else
-                       return EAI_MEMORY;
-       }
-               
-       if (!hostname) {
-               if (NULL != (*res = malloc_ai(port, htonl(0x7f000001))))
-                       return 0;
-               else
-                       return EAI_MEMORY;
-       }
-       
-       if (inet_aton(hostname, &in)) {
-               if (NULL != (*res = malloc_ai(port, in.s_addr)))
-                       return 0;
-               else
-                       return EAI_MEMORY;
-       }
-       
-       hp = gethostbyname(hostname);
-       if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
-               for (i = 0; hp->h_addr_list[i]; i++) {
-                       cur = malloc_ai(port, ((struct in_addr *)hp->h_addr_list[i])->s_addr);
-                       if (cur == NULL) {
-                               if (*res)
-                                       freeaddrinfo(*res);
-                               return EAI_MEMORY;
-                       }
-                       
-                       if (prev)
-                               prev->ai_next = cur;
-                       else
-                               *res = cur;
-
-                       prev = cur;
-               }
-               return 0;
-       }
-       
-       return EAI_NODATA;
-}
-#endif /* !HAVE_GETADDRINFO */
-
-
-/*
- * 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.
- */
-
-#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;
-       char tmpserv[16];
-
-       if (serv) {
-               snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port));
-               if (strlen(tmpserv) >= servlen)
-                       return EAI_MEMORY;
-               else
-                       strcpy(serv, tmpserv);
-       }
-
-       if (host) {
-               if (flags & NI_NUMERICHOST) {
-                       if (strlen(inet_ntoa(sin->sin_addr)) >= hostlen)
-                               return EAI_MEMORY;
-
-                       strcpy(host, inet_ntoa(sin->sin_addr));
-                       return 0;
-               } else {
-                       hp = gethostbyaddr((char *)&sin->sin_addr, 
-                               sizeof(struct in_addr), AF_INET);
-                       if (hp == NULL)
-                               return EAI_NODATA;
-                       
-                       if (strlen(hp->h_name) >= hostlen)
-                               return EAI_MEMORY;
-
-                       strcpy(host, hp->h_name);
-                       return 0;
-               }
-       }
-       return 0;
-}
-#endif /* !HAVE_GETNAMEINFO */
index 09e650e0af5bfd6c248e4916e0577d932aeeb4c6..ad66d99da46ec11c5cdf993fea2e8fdc0f2cc74a 100644 (file)
@@ -17,7 +17,7 @@
     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.1.2.5 2001/11/16 17:37:08 zarq Exp $
+    $Id: dropin.h,v 1.1.2.6 2002/02/10 21:57:51 guus Exp $
 */
 
 #ifndef __DROPIN_H__
@@ -35,53 +35,4 @@ extern char* get_current_dir_name(void);
 extern int asprintf(char **, const char *, ...);
 #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 */
-
-#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 */
-
-#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
-
 #endif /* __DROPIN_H__ */
index 2ef9c37853104a993e731e55d8b950710bd38145..e5c0939555b570aa7664ac45a4448f743deebd8d 100644 (file)
@@ -31,6 +31,14 @@ AC_DEFUN(tinc_OPENSSL,
 
   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!")]
+    )
+  )
+
   AC_CHECK_FUNC(dlopen,
     [],
     AC_CHECK_LIB(dl, dlopen,
index 75d43e6e9cf4c7b61efb40b96aeae3f62c45f7ce..05a120125c1a21166a6e51f60d2f2dc4d5e98873 100644 (file)
@@ -11,7 +11,19 @@ src/meta.c
 src/net.c
 src/netutl.c
 src/protocol.c
+src/protocol_auth.c
+src/protocol_edge.c
+src/protocol_key.c
+src/protocol_misc.c
+src/protocol_subnet.c
 src/subnet.c
 src/tincd.c
 src/process.c
 src/route.c
+src/node.c
+src/edge.c
+src/graph.c
+src/linux/device.c
+src/freebsd/device.c
+src/openbsd/device.c
+src/solaris/device.c
index 7ede015f825254365b8183047d536a9e2c757013..64895bf6d9999a0d58a9cdddfff945f361880ebd 100644 (file)
--- a/po/nl.po
+++ b/po/nl.po
 # Dutch messages for tinc
 # Copyright (C) 1999-2001 Ivo Timmermans, Guus Sliepen.
-# Ivo Timmermans <itimmermans@bigfoot.com>, 1999-2001.
-# Guus Sliepen <guus@sliepen.warande.net>, 2000,2001.
+# Ivo Timmermans <itimmermans@bigfoot.com>, 1999-2002.
+# Guus Sliepen <guus@sliepen.warande.net>, 2000-2002.
 msgid ""
 msgstr ""
 "Project-Id-Version: tinc 1.0-cvs\n"
-"POT-Creation-Date: 2001-10-08 17:37+0200\n"
-"PO-Revision-Date: 2001-10-08 17:37+0200\n"
+"POT-Creation-Date: 2002-02-09 21:32+0100\n"
+"PO-Revision-Date: 2002-02-09 17:20+0100\n"
 "Last-Translator: Guus Sliepen <guus@sliepen.warande.net>\n"
 "Language-Team: Dutch <vertaling@nl.linux.org>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=iso-8859-1\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: src/conf.c:240
+#: src/conf.c:173
 #, c-format
-msgid "Cannot open config file %s: %m"
-msgstr "Kan configuratie bestand %s niet openen: %m"
+msgid "\"yes\" or \"no\" expected for configuration variable %s in %s line %d"
+msgstr ""
+"\"ja\" of \"nee\" verwacht voor configuratievariabele %s in %s regel %d"
 
-#: src/conf.c:281
+#: src/conf.c:188
 #, c-format
-msgid "Invalid variable name `%s' on line %d while reading config file %s"
-msgstr ""
-"Ongeldige variabelenaam `%s' op regel %d tijdens lezen configuratie bestand %"
-"s"
+msgid "Integer expected for configuration variable %s in %s line %d"
+msgstr "Geheel getal verwacht voor configuratievariabele %s in %s regel %d"
 
-#: src/conf.c:288
+#: src/conf.c:219
 #, c-format
-msgid "No value for variable `%s' on line %d while reading config file %s"
+msgid "IP address expected for configuration variable %s in %s line %d"
+msgstr "IP adres verwacht voor configuratievariabele %s in %s regel %d"
+
+#: src/conf.c:233
+#, c-format
+msgid "Port number expected for configuration variable %s in %s line %d"
+msgstr "Poortnummer verwacht voor configuratievariabele %s in %s regel %d"
+
+#: src/conf.c:249
+#, c-format
+msgid "Subnet expected for configuration variable %s in %s line %d"
+msgstr "Subnet verwacht voor configuratievariabele %s in %s regel %d"
+
+#: src/conf.c:259
+#, c-format
+msgid ""
+"Network address and mask length do not match for configuration variable %s "
+"in %s line %d"
 msgstr ""
-"Geen waarde voor variabele `%s' op regel %d tijdens het lezen van "
-"configuratie bestand %s"
+"Netwerk adres en maskerlengte komen niet overeen bij configuratievariabele %"
+"s in %s regel %d"
+
+#: src/conf.c:367
+#, c-format
+msgid "Cannot open config file %s: %m"
+msgstr "Kan configuratie bestand %s niet openen: %m"
 
-#: src/conf.c:296
+#: src/conf.c:403
 #, c-format
-msgid "Invalid value for variable `%s' on line %d while reading config file %s"
+msgid "No value for variable `%s' on line %d while reading config file %s"
 msgstr ""
-"Ongeldige waarde voor variabele `%s' op regel %d tijdens lezen van "
+"Geen waarde voor variabele `%s' op regel %d tijdens het lezen van "
 "configuratie bestand %s"
 
-#: src/conf.c:325
+#: src/conf.c:436
 #, c-format
 msgid "Failed to read `%s': %m"
 msgstr "Lezen van `%s' mislukte: %m"
 
-#: src/conf.c:386
+#: src/conf.c:464
 #, c-format
 msgid "`%s' is not an absolute path"
 msgstr "`%s' is geen absoluut pad"
 
-#: src/conf.c:402 src/conf.c:435
+#: src/conf.c:480 src/conf.c:513
 #, c-format
 msgid "Couldn't stat `%s': %m"
 msgstr "Kon `%s' niet statten: %m"
 
-#: src/conf.c:409 src/conf.c:445
+#: src/conf.c:487 src/conf.c:523
 #, c-format
 msgid "`%s' is owned by UID %d instead of %d"
 msgstr "`%s' is eigendom van UID %d in plaats van %d"
 
-#: src/conf.c:416 src/conf.c:452
+#: src/conf.c:494 src/conf.c:530
 #, c-format
 msgid "Warning: `%s' is a symlink"
 msgstr "Waarschuwing: `%s' is een symbolische link"
 
-#: src/conf.c:421 src/conf.c:457
+#: src/conf.c:499 src/conf.c:535
 #, c-format
 msgid "Unable to read symbolic link `%s': %m"
 msgstr "Kan symbolische link `%s' niet lezen: %m"
 
 #. Accessible by others
-#: src/conf.c:468
+#: src/conf.c:546
 #, c-format
 msgid "`%s' has unsecure permissions"
 msgstr "`%s' heeft onveilige permissies"
 
 #. Ask for a file and/or directory name.
-#: src/conf.c:493
+#: src/conf.c:571
 #, c-format
 msgid "Please enter a file to save %s to [%s]: "
 msgstr "Geef een bestand om de %s naar de schrijven [%s]: "
 
-#: src/conf.c:499
+#: src/conf.c:577
 #, c-format
 msgid "Error while reading stdin: %s\n"
 msgstr "Fout tijdens lezen van standaardinvoer: %s\n"
 
-#: src/conf.c:525
+#: src/conf.c:603
 #, c-format
 msgid "Error opening file `%s': %s\n"
 msgstr "Fout bij het openen van het bestand `%s': %s\n"
 
-#: src/conf.c:535
+#: src/conf.c:613
 #, c-format
 msgid ""
 "The file `%s' (or any of the leading directories) has unsafe permissions.\n"
@@ -101,31 +122,18 @@ msgstr ""
 "bescherming.\n"
 "Ik maak of overschrijf dit bestand niet.\n"
 
-#: src/connection.c:236
-msgid "Connection list:"
-msgstr "Verbindingslijst:"
+#: src/connection.c:124
+msgid "Connections:"
+msgstr "Verbindingen:"
 
-#: src/connection.c:241
+#: src/connection.c:129
 #, c-format
-msgid " %s at %s port %hd options %ld sockets %d, %d status %04x"
-msgstr " %s op %s poort %hd opties %d sockets %d, %d status %04x"
+msgid " %s at %s port %hd options %ld socket %d status %04x"
+msgstr " %s op %s poort %hd opties %d socket %d status %04x"
 
-#: src/connection.c:246
-msgid "Known hosts:"
-msgstr "Bekende hosts:"
-
-#: src/connection.c:251
-#, c-format
-msgid ""
-" %s at %s port %hd options %ld sockets %d, %d status %04x nexthop %s prevhop "
-"%s via %s"
-msgstr ""
-" %s op %s poort %hd opties %d sockets %d, %d status %04x nexthop %s prevhop %"
-"s via %s"
-
-#: src/connection.c:256
-msgid "End of connection list."
-msgstr "Einde van verbindingslijst."
+#: src/connection.c:134
+msgid "End of connections."
+msgstr "Einde van verbindingen."
 
 #: src/meta.c:49
 #, c-format
@@ -162,50 +170,45 @@ msgstr "Fout op metadata socket voor %s (%s) tijdens lezen: %m"
 msgid "Metadata read buffer overflow for %s (%s)"
 msgstr "Metadata leesbuffer overloop voor %s (%s)"
 
-#: src/net.c:116
+#: src/net.c:111
 #, c-format
-msgid "No valid key known yet for %s (%s), queueing packet"
-msgstr ""
-"Nog geen geldige sleutel bekend voor %s (%s), pakket wordt in wachtrij gezet"
+msgid "Got unauthenticated packet from %s (%s)"
+msgstr "Kreeg niet-geauthenticeerd pakket van %s (%s)"
 
-#: src/net.c:149
+#: src/net.c:134
 #, c-format
-msgid "Error sending packet to %s (%s): %m"
-msgstr "Fout tijdens verzenden pakket naar %s (%s): %m"
+msgid "Got late or replayed packet from %s (%s), seqno %d"
+msgstr "Kreeg laat of gedupliceerd pakket van %s (%s), seqno %d"
 
-#: src/net.c:160
+#: src/net.c:162
 #, c-format
 msgid "Received packet of %d bytes from %s (%s)"
 msgstr "Ontvangst pakket van %d bytes van %s (%s)"
 
-#: src/net.c:201
+#: src/net.c:180
 #, c-format
-msgid "Writing packet of %d bytes to tap device"
-msgstr "Verzending pakket van %d bytes naar tap-apparaat"
-
-#: src/net.c:206 src/net.c:213
-#, c-format
-msgid "Can't write to tun/tap device: %m"
-msgstr "Kan niet naar tun/tap apparaat schrijven: %m"
+msgid "No valid key known yet for %s (%s), queueing packet"
+msgstr ""
+"Nog geen geldige sleutel bekend voor %s (%s), pakket wordt in wachtrij gezet"
 
-#: src/net.c:220
+#: src/net.c:225
 #, c-format
-msgid "Can't write to ethertap device: %m"
-msgstr "Kan niet naar ethertap apparaat schrijven: %m"
+msgid "Error sending packet to %s (%s): %m"
+msgstr "Fout tijdens verzenden pakket naar %s (%s): %m"
 
-#: src/net.c:236
+#: src/net.c:240
 #, c-format
 msgid "Sending packet of %d bytes to %s (%s)"
 msgstr "Verzending pakket van %d bytes naar %s (%s)"
 
-#: src/net.c:243
+#: src/net.c:247
 msgid "Packet is looping back to us!"
 msgstr "Pakket komt terug naar ons!"
 
-#: src/net.c:252
+#: src/net.c:256
 #, c-format
-msgid "%s (%s) is not active, dropping packet"
-msgstr "%s (%s) is niet actief, pakket wordt genegeerd"
+msgid "Node %s (%s) is not reachable"
+msgstr "Node %s (%s) is niet bereikbaar"
 
 #: src/net.c:264
 #, c-format
@@ -222,718 +225,505 @@ msgstr "Verspreiding pakket van %d bytes van %s (%s)"
 msgid "Flushing queue for %s (%s)"
 msgstr "Legen van wachtrij voor %s (%s)"
 
-#: src/net.c:353
-#, c-format
-msgid "Could not open %s: %m"
-msgstr "Kon %s niet openen: %m"
-
-#: src/net.c:380 src/net.c:386
-#, c-format
-msgid "%s is a Linux tun/tap device"
-msgstr "%s is een Linux tun/tap apparaat"
-
-#: src/net.c:387
-msgid "Old ioctl() request used"
-msgstr "Oud ioctl() verzoek gebruikt"
-
-#: src/net.c:393
-#, c-format
-msgid "%s is a Linux ethertap device"
-msgstr "%s is een Linux ethertap apparaat"
-
-#: src/net.c:398
-#, c-format
-msgid "%s is a FreeBSD tap device"
-msgstr "%s is een FreeBSD tap apparaat"
-
-#: src/net.c:409
-#, c-format
-msgid "Could not open /dev/ip: %m"
-msgstr "Kon /dev/ip niet openen: %m"
-
-#: src/net.c:415
-#, c-format
-msgid "Can't assign new interface: %m"
-msgstr "Kan nieuwe interface niet toekennen: %m"
-
-#: src/net.c:420
-#, c-format
-msgid "Could not open %s twice: %m"
-msgstr "Kon %s niet tweemaal openen: %m"
-
-#: src/net.c:425
-#, c-format
-msgid "Can't push IP module: %m"
-msgstr "Kan IP module niet toevoegen: %m"
-
-#: src/net.c:431
-#, c-format
-msgid "Can't set PPA %d: %m"
-msgstr "Kan PPA %d niet instellen: %m"
-
-#: src/net.c:436
-#, c-format
-msgid "Can't link TUN device to IP: %m"
-msgstr "Kan TUN device niet aan IP verbinden: %m"
-
-#: src/net.c:440
-#, c-format
-msgid "%s is a Solaris tun device"
-msgstr "%s is een Solaris tun apparaat"
-
-#: src/net.c:460
+#: src/net.c:326
 #, c-format
 msgid "Creating metasocket failed: %m"
 msgstr "Aanmaak van metasocket mislukt: %m"
 
-#: src/net.c:468 src/net.c:514 src/net.c:545 src/net.c:600 src/net.c:1102
-#: src/process.c:241 src/process.c:277
+#: src/net.c:334 src/net.c:380 src/net.c:407 src/net.c:987 src/process.c:258
+#: src/process.c:294
 #, c-format
 msgid "System call `%s' failed: %m"
 msgstr "Systeemaanroep `%s' mislukte: %m"
 
-#: src/net.c:489
+#: src/net.c:354
 #, c-format
-msgid "Unable to bind listen socket to interface %s: %m"
-msgstr "Kon luistersocket niet binden aan interface %s: %m"
+msgid "Can't bind to interface %s: %m"
+msgstr "Kan niet aan interface %s binden: %m"
 
-#: src/net.c:507
+#: src/net.c:373
 #, c-format
 msgid "Can't bind to port %hd/tcp: %m"
 msgstr "Kan niet aan poort %hd/tcp binden: %m"
 
-#: src/net.c:535
+#: src/net.c:397
 #, c-format
 msgid "Creating socket failed: %m"
 msgstr "Aanmaak socket mislukte: %m"
 
-#: src/net.c:558
+#: src/net.c:420
 #, c-format
 msgid "Can't bind to port %hd/udp: %m"
 msgstr "Kan niet aan poort %hd/udp binden: %m"
 
-#: src/net.c:576
+#: src/net.c:442
 #, c-format
-msgid "Trying to connect to %s"
-msgstr "Poging tot verbinding met %s"
+msgid "Trying to re-establish outgoing connection in %d seconds"
+msgstr "Poging tot herstellen van uitgaande verbinding over %d seconden"
+
+#: src/net.c:452
+#, c-format
+msgid "Trying to connect to %s (%s)"
+msgstr "Poging tot verbinden met %s (%s)"
 
-#: src/net.c:586
+#: src/net.c:458
 #, c-format
 msgid "Creating socket for %s port %d failed: %m"
 msgstr "Aanmaken socket voor %s poort %d mislukt: %m"
 
-#: src/net.c:623
+#: src/net.c:500
 #, c-format
 msgid "%s port %hd: %m"
 msgstr "%s poort %hd: %m"
 
-#: src/net.c:631
+#: src/net.c:509
 #, c-format
 msgid "fcntl for %s port %d: %m"
 msgstr "fcntl voor %s poort %d: %m"
 
-#: src/net.c:637
+#: src/net.c:515
 #, c-format
 msgid "Connected to %s port %hd"
 msgstr "Verbonden met %s poort %hd"
 
-#: src/net.c:656
-msgid "Invalid name for outgoing connection"
-msgstr "Ongelige naam voor uitgaande verbinding"
-
-#: src/net.c:667
+#: src/net.c:533
 #, c-format
-msgid "We are already connected to %s."
-msgstr "We zijn al verbonden met %s."
+msgid "Already connected to %s"
+msgstr "Reeds verbonden met %s"
 
-#: src/net.c:679
-#, c-format
-msgid "Error reading host configuration file for %s"
-msgstr "Fout tijdens lezen host configuratie bestand voor %s"
-
-#: src/net.c:686
+#: src/net.c:546
 #, c-format
 msgid "No address specified for %s"
 msgstr "Geen adres gespecificeerd voor %s"
 
-#: src/net.c:693
+#: src/net.c:558
 #, c-format
 msgid "Error looking up `%s': %m"
 msgstr "Fout bij het opzoeken van `%s': %m"
 
-#: src/net.c:703
+#: src/net.c:569
 #, c-format
-msgid "Could not set up a meta connection to %s"
-msgstr "Kon geen metaverbinding aangaan met %s"
+msgid "Could not set up a meta connection to %s (%s)"
+msgstr "Kon geen metaverbinding aangaan met %s (%s)"
 
-#: src/net.c:748
+#: src/net.c:610
 #, c-format
 msgid "Error reading RSA public key file `%s': %m"
 msgstr "Fout tijdens lezen RSA publieke sleutel bestand `%s': %m"
 
-#: src/net.c:756
+#: src/net.c:618
 #, c-format
 msgid "Reading RSA public key file `%s' failed: %m"
 msgstr "Lezen RSA publieke sleutel bestand `%s' mislukt: %m"
 
-#. Nothing worked.
-#: src/net.c:782
+#: src/net.c:643
 #, c-format
 msgid "No public key for %s specified!"
 msgstr "Geen publieke sleutel bekend voor %s gespecificeerd!"
 
-#: src/net.c:805
+#: src/net.c:663
 #, c-format
 msgid "Error reading RSA private key file `%s': %m"
 msgstr "Fout tijdens lezen RSA privé sleutel bestand `%s': %m"
 
-#: src/net.c:813
+#: src/net.c:671
 #, c-format
 msgid "Reading RSA private key file `%s' failed: %m"
 msgstr "Fout tijdens lezen RSA privé sleutel bestand `%s': %m"
 
 #
-#: src/net.c:820
+#: src/net.c:678
 msgid "No private key for tinc daemon specified!"
 msgstr "Geen privé sleutel voor tinc daemon gespecificeerd!"
 
-#: src/net.c:838
+#: src/net.c:699 src/net.c:700
 msgid "MYSELF"
 msgstr "MIJZELF"
 
-#: src/net.c:844
+#: src/net.c:707
 msgid "Name for tinc daemon required!"
 msgstr "Naam voor tinc daemon verplicht!"
 
-#: src/net.c:852
+#: src/net.c:713
 msgid "Invalid name for myself!"
 msgstr "Ongelige naam voor mijzelf!"
 
-#: src/net.c:861
+#: src/net.c:727
 msgid "Cannot open host configuration file for myself!"
 msgstr "Kan host configuratie bestand voor mijzelf niet openen!"
 
-#: src/net.c:894
-msgid "Network address and subnet mask do not match!"
-msgstr "Netwerk adres en subnet masker komen niet overeen!"
-
-#: src/net.c:933
+#: src/net.c:793
 msgid "Invalid routing mode!"
 msgstr "Ongelige routing modus!"
 
-#: src/net.c:945
+#: src/net.c:805
 msgid "Unable to set up a listening TCP socket!"
 msgstr "Kon geen TCP luistersocket aanmaken!"
 
-#: src/net.c:951
+#: src/net.c:811
 msgid "Unable to set up a listening UDP socket!"
 msgstr "Kon geen UDP luistersocket aanmaken!"
 
-#: src/net.c:979
+#: src/net.c:827
+msgid "Unrecognized cipher type!"
+msgstr "Onbekend cipher type!"
+
+#: src/net.c:860
+msgid "Unrecognized digest type!"
+msgstr "Onbekend digest type!"
+
+#: src/net.c:874
+msgid "MAC length exceeds size of digest!"
+msgstr "MAC lengte is groter dan dat van digest!"
+
+#: src/net.c:879
+msgid "Bogus MAC length!"
+msgstr "Onzinnige MAC lengte!"
+
+#: src/net.c:896
 #, c-format
 msgid "Ready: listening on port %hd"
 msgstr "Gereed: luisterend op poort %hd"
 
-#: src/net.c:1012
-#, c-format
-msgid "Failed to setup all outgoing connections, will retry in %d seconds"
-msgstr ""
-"Poging tot maken van alle uitgaande verbinding faalde, nieuwe poging over %d "
-"seconden"
-
-#: src/net.c:1108
-msgid "UNKNOWN"
-msgstr "ONBEKEND"
-
-#: src/net.c:1119
+#: src/net.c:1000
 #, c-format
 msgid "Connection from %s port %d"
 msgstr "Verbinding van %s poort %d"
 
-#: src/net.c:1165
+#: src/net.c:1045
 #, c-format
 msgid "This is a bug: %s:%d: %d:%m"
 msgstr "Dit is een programmeerfout: %s:%d: %d:%m"
 
-#: src/net.c:1171
+#: src/net.c:1051
 #, c-format
 msgid "Incoming data socket error: %s"
 msgstr "Fout op socket voor inkomend verkeer: %s"
 
-#: src/net.c:1177
+#: src/net.c:1057
 #, c-format
 msgid "Receiving packet failed: %m"
 msgstr "Ontvangst pakket mislukt: %m"
 
-#: src/net.c:1185
+#: src/net.c:1065
 #, c-format
-msgid "Received UDP packets on port %hd from unknown source %x:%hd"
+msgid "Received UDP packet on port %hd from unknown source %x:%hd"
 msgstr "Ontvangst UDP pakket op poort %hd van onbekende oorsprong %x:%hd"
 
-#: src/net.c:1224
+#: src/net.c:1088
+msgid "Purging unreachable nodes"
+msgstr "Verwijderen onbereikbare nodes"
+
+#: src/net.c:1098
 #, c-format
-msgid "Closing connection with %s (%s)"
-msgstr "Beëindigen verbinding met %s (%s)"
+msgid "Purging node %s (%s)"
+msgstr "Verwijdering node %s (%s)"
 
-#: src/net.c:1268
+#: src/net.c:1152
 #, c-format
-msgid "Trying to re-establish outgoing connection in %d seconds"
-msgstr "Poging tot herstellen van uitgaande verbinding over %d seconden"
+msgid "Closing connection with %s (%s)"
+msgstr "Beëindigen verbinding met %s (%s)"
 
-#: src/net.c:1303
+#: src/net.c:1223
 #, c-format
 msgid "%s (%s) didn't respond to PING"
 msgstr "%s (%s) antwoordde niet op ping"
 
-#: src/net.c:1316
+#: src/net.c:1236
 #, c-format
 msgid "Timeout from %s (%s) during authentication"
 msgstr "Timeout van %s (%s) tijdens authenticatie"
 
-#: src/net.c:1337
+#: src/net.c:1257
 #, c-format
 msgid "Accepting a new connection failed: %m"
 msgstr "Aanname van nieuwe verbinding is mislukt: %m"
 
-#: src/net.c:1345
+#: src/net.c:1265
 msgid "Closed attempted connection"
 msgstr "Aangenomen verbinding verbroken"
 
-#: src/net.c:1400
+#: src/net.c:1288
 #, c-format
-msgid "Error while reading from tun device: %m"
-msgstr "Fout tijdens lezen van tun apparaat: %m"
+msgid "Invalid name for outgoing connection in %s line %d"
+msgstr "Ongelige naam voor uitgaande verbinding in %s regel %d"
 
-#: src/net.c:1413
-#, c-format
-msgid "Error while reading from tun/tap device: %m"
-msgstr "Fout tijdens lezen van tun/tap apparaat: %m"
-
-#: src/net.c:1422
-#, c-format
-msgid "Error while reading from ethertap device: %m"
-msgstr "Fout tijdens lezen van ethertap apparaat: %m"
-
-#: src/net.c:1434
-msgid "Received short packet from tap device"
-msgstr "Kort pakket ontvangen van tap apparaat"
-
-#: src/net.c:1440
-#, c-format
-msgid "Read packet of length %d from tap device"
-msgstr "Pakket gelezen van lengte %d van tap apparaat"
-
-#: src/net.c:1472
+#: src/net.c:1384
 #, c-format
 msgid "Error while waiting for input: %m"
 msgstr "Fout tijdens wachten op invoer: %m"
 
-#: src/net.c:1479
+#: src/net.c:1391
 msgid "Rereading configuration file and restarting in 5 seconds"
 msgstr "Herlezen configuratiebestand en herstart in 5 seconden"
 
-#: src/net.c:1486
+#: src/net.c:1398
 msgid "Unable to reread configuration file, exiting"
 msgstr "Kan configuratiebestand niet herlezen, beëindigen"
 
-#: src/net.c:1512
+#: src/net.c:1430
 msgid "Regenerating symmetric key"
 msgstr "Hergenereren symmetrische sleutel"
 
-#: src/netutl.c:95
+#: src/net.c:1440
+msgid "Flushing event queue"
+msgstr "Legen taakrij"
+
+#: src/netutl.c:84
 #, c-format
 msgid "Error looking up `%s': %s\n"
 msgstr "Fout bij het opzoeken van `%s': %s\n"
 
-#: src/protocol.c:94
+#: src/protocol.c:75
 #, c-format
 msgid "Output buffer overflow while sending %s to %s (%s)"
 msgstr "Uitvoer buffer overvol tijdens zenden %s naar %s (%s)"
 
-#: src/protocol.c:101
+#: src/protocol.c:82
 #, c-format
 msgid "Sending %s to %s (%s): %s"
 msgstr "Verzending %s naar %s (%s): %s"
 
-#: src/protocol.c:103
+#: src/protocol.c:84
 #, c-format
 msgid "Sending %s to %s (%s)"
 msgstr "Verzending %s naar %s (%s)"
 
-#: src/protocol.c:120
+#: src/protocol.c:101
 #, c-format
 msgid "Unknown request from %s (%s): %s"
 msgstr "Onbekend verzoek van %s (%s): %s"
 
-#: src/protocol.c:123
+#: src/protocol.c:104
 #, c-format
 msgid "Unknown request from %s (%s)"
 msgstr "Onbekend verzoek van %s (%s)"
 
-#: src/protocol.c:133
+#: src/protocol.c:114
 #, c-format
 msgid "Got %s from %s (%s): %s"
 msgstr "Kreeg %s van %s (%s): %s"
 
-#: src/protocol.c:136
+#: src/protocol.c:117
 #, c-format
 msgid "Got %s from %s (%s)"
 msgstr "Kreeg %s van %s (%s)"
 
-#: src/protocol.c:143
+#: src/protocol.c:124
 #, c-format
 msgid "Unauthorized request from %s (%s)"
 msgstr "Niet toegestaan verzoek van %s (%s)"
 
-#: src/protocol.c:150
+#: src/protocol.c:131
 #, c-format
 msgid "Error while processing %s from %s (%s)"
 msgstr "Fout tijdens afhandelen %s van %s (%s)"
 
-#: src/protocol.c:157
+#: src/protocol.c:138
 #, c-format
 msgid "Bogus data received from %s (%s)"
 msgstr "Onzinnige data ontvangen van %s (%s)"
 
-#: src/protocol.c:180
+#: src/protocol_auth.c:69 src/protocol_auth.c:218 src/protocol_auth.c:311
+#: src/protocol_auth.c:367 src/protocol_auth.c:475 src/protocol_edge.c:85
+#: src/protocol_edge.c:215 src/protocol_key.c:78 src/protocol_key.c:116
+#: src/protocol_key.c:184 src/protocol_misc.c:61 src/protocol_misc.c:91
+#: src/protocol_misc.c:172 src/protocol_subnet.c:71 src/protocol_subnet.c:160
 #, c-format
-msgid "Got bad ID from %s"
-msgstr "Kreeg ongeldige ID van %s"
+msgid "Got bad %s from %s (%s)"
+msgstr "Kreeg verkeerde %s van %s (%s)"
 
-#: src/protocol.c:188
+#: src/protocol_auth.c:77 src/protocol_edge.c:93 src/protocol_edge.c:99
+#: src/protocol_edge.c:224 src/protocol_edge.c:230 src/protocol_subnet.c:79
+#: src/protocol_subnet.c:87 src/protocol_subnet.c:168
+#: src/protocol_subnet.c:186
 #, c-format
-msgid "Peer %s (%s) uses incompatible version %d"
-msgstr "Ander %s (%s) gebruikt een niet-compatibel protocol versie %d"
-
-#: src/protocol.c:197
-#, c-format
-msgid "Peer %s uses invalid identity name"
-msgstr "Ander %s gebruikt een ongeldige identiteitsnaam"
-
-#: src/protocol.c:212
-#, c-format
-msgid "Peer %s had unknown identity (%s)"
-msgstr "Ander %s heeft een onbekende identiteit (%s)"
-
-#: src/protocol.c:241
-#, c-format
-msgid "Removing old connection for %s at %s in favour of new connection at %s"
-msgstr ""
-"Verwijdering oude verbinding voor %s op %s in voordeel van nieuwe verbinding "
-"van %s"
+msgid "Got bad %s from %s (%s): %s"
+msgstr "Kreeg verkeerde %s van %s (%s): %s"
 
-#: src/protocol.c:257
+#: src/protocol_auth.c:87
 #, c-format
-msgid "%s is listening on %s:%hd, which is already in use by %s!"
-msgstr "%s luistert op %s:%hd, wat al in gebruik is door %s!"
+msgid "Peer %s is %s instead of %s"
+msgstr "Ander %s is %s in plaats van %s"
 
-#: src/protocol.c:273
+#: src/protocol_auth.c:98
 #, c-format
-msgid "Connection with %s (%s) activated"
-msgstr "Verbinding met %s (%s) geactiveerd"
-
-#: src/protocol.c:377
-#, c-format
-msgid "Got bad CHALLENGE from %s (%s)"
-msgstr "Kreeg ongeldige CHALLENGE van %s (%s)"
-
-#: src/protocol.c:387
-#, c-format
-msgid "Intruder: wrong challenge length from %s (%s)"
-msgstr "Indringer: verkeerde lengte voor uitdaging van %s (%s)"
-
-#: src/protocol.c:413
-#, c-format
-msgid "Trying to send CHAL_REPLY to %s (%s) without a valid CHALLENGE"
-msgstr "Poging tot zenden CHAL_REPLY naar %s (%s) zonder een geldige CHALLENGE"
-
-#: src/protocol.c:439
-#, c-format
-msgid "Got bad CHAL_REPLY from %s (%s)"
-msgstr "Kreeg ongeldige CHAL_REPLY van %s (%s)"
-
-#: src/protocol.c:447
-#, c-format
-msgid "Intruder: wrong challenge reply length from %s (%s)"
-msgstr "Indringer: verkeerde lengte van antwoord op uitdaging van %s (%s)"
-
-#: src/protocol.c:463
-#, c-format
-msgid "Intruder: wrong challenge reply from %s (%s)"
-msgstr "Indringer: verkeerd antwoord op de uitdaging van %s (%s)"
+msgid "Peer %s (%s) uses incompatible version %d"
+msgstr "Ander %s (%s) gebruikt incompatibele versie %d"
 
-#: src/protocol.c:468
+#: src/protocol_auth.c:117
 #, c-format
-msgid "Expected challenge reply: %s"
-msgstr "Verwacht antwoord op uitdaging: %s"
+msgid "Peer %s had unknown identity (%s)"
+msgstr "Ander %s heeft onbekende identiteit (%s)"
 
-#: src/protocol.c:517
+#: src/protocol_auth.c:175
 #, c-format
 msgid "Generated random meta key (unencrypted): %s"
-msgstr "Meta sleutel gegenereerd (niet versleuteld): %s"
+msgstr "Willekeurige meta sleutel aangemaakt (niet versleuteld): %s"
 
-#: src/protocol.c:529 src/protocol.c:592
+#: src/protocol_auth.c:187 src/protocol_auth.c:248
 #, c-format
 msgid "Error during encryption of meta key for %s (%s)"
-msgstr "Fout tijdens versleuteling van meta sleutel voor %s (%s)"
-
-#: src/protocol.c:562
-#, c-format
-msgid "Got bad METAKEY from %s (%s)"
-msgstr "Kreeg ongeldige METAKEY van %s (%s)"
+msgstr "Fout tijdens versleutelen van meta key voor %s (%s)"
 
-#: src/protocol.c:572
+#: src/protocol_auth.c:228 src/protocol_auth.c:321 src/protocol_auth.c:375
+#: src/protocol_auth.c:391
 #, c-format
-msgid "Intruder: wrong meta key length from %s (%s)"
-msgstr "Indringer: verkeerde lengte voor meta sleutel van %s (%s)"
+msgid "Possible intruder %s (%s): %s"
+msgstr "Mogelijke indringer %s (%s): %s"
 
-#: src/protocol.c:600
+#: src/protocol_auth.c:256
 #, c-format
 msgid "Received random meta key (unencrypted): %s"
-msgstr "Meta sleutel ontvangen (niet versleuteld): %s"
+msgstr "Ontving willekeurige meta key (niet versleuteld): %s"
 
-#: src/protocol.c:643
-#, c-format
-msgid "Got bad ADD_SUBNET from %s (%s)"
-msgstr "Kreeg ongeldige ADD_SUBNET van %s (%s)"
+#: src/protocol_auth.c:375
+msgid "wrong challenge reply length"
+msgstr "verkeerde lengte antwoord op uitdaging"
 
-#: src/protocol.c:651
-#, c-format
-msgid "Got bad ADD_SUBNET from %s (%s): invalid identity name"
-msgstr "Kreeg ongeldige ADD_SUBNET van %s (%s): ongeldige identiteitsnaam"
-
-#: src/protocol.c:659
-#, c-format
-msgid "Got bad ADD_SUBNET from %s (%s): invalid subnet string"
-msgstr "Kreeg ongeldige ADD_SUBNET van %s (%s): ongeldig subnet"
-
-#: src/protocol.c:667
-#, c-format
-msgid "Warning: got ADD_SUBNET from %s (%s) for ourself, restarting"
-msgstr "Waarschuwing: kreeg ADD_SUBNET van %s (%s) voor onszelf, herstart"
+#: src/protocol_auth.c:391
+msgid "wrong challenge reply"
+msgstr "verkeerd antwoord op uitdaging"
 
-#: src/protocol.c:677
+#: src/protocol_auth.c:396
 #, c-format
-msgid "Got ADD_SUBNET for %s from %s (%s) which is not in our connection list"
-msgstr ""
-"Kreeg ADD_SUBNET voor %s van %s (%s) die niet voorkomt in onze "
-"verbindingslijst"
-
-#: src/protocol.c:722
-#, c-format
-msgid "Got bad DEL_SUBNET from %s (%s)"
-msgstr "Kreeg ongeldige DEL_SUBNET van %s (%s)"
+msgid "Expected challenge reply: %s"
+msgstr "Verwachtte antwoord op uitdaging: %s"
 
-#: src/protocol.c:730
+#: src/protocol_auth.c:501
 #, c-format
-msgid "Got bad DEL_SUBNET from %s (%s): invalid identity name"
-msgstr "Kreeg ongeldige DEL_SUBNET van %s (%s): ongeldige identiteitsnaam"
+msgid "Established a second connection with %s (%s), closing old connection"
+msgstr "Tweede verbinding met %s (%s) gemaakt, oude verbinding wordt gesloten"
 
-#: src/protocol.c:738
+#: src/protocol_auth.c:534
 #, c-format
-msgid "Got bad DEL_SUBNET from %s (%s): invalid subnet string"
-msgstr "Kreeg ongeldige DEL_SUBNET van %s (%s): ongeldige identiteitsnaam"
+msgid "Connection with %s (%s) activated"
+msgstr "Verbinding met %s (%s) geactiveerd"
 
-#: src/protocol.c:748
-#, c-format
-msgid "Warning: got DEL_SUBNET from %s (%s) for ourself, restarting"
-msgstr "Waarschuwing: kreeg DEL_SUBNET van %s (%s) voor onszelf, herstart"
+#: src/protocol_edge.c:93 src/protocol_edge.c:99 src/protocol_edge.c:224
+#: src/protocol_edge.c:230 src/protocol_subnet.c:79 src/protocol_subnet.c:168
+msgid "invalid name"
+msgstr "ongelige naam"
 
-#: src/protocol.c:758
+#: src/protocol_edge.c:142
 #, c-format
-msgid "Got DEL_SUBNET for %s from %s (%s) which is not in our connection list"
+msgid "Got %s from %s (%s) for ourself which does not match existing entry"
 msgstr ""
-"Kreeg DEL_SUBNET voor %s van %s (%s) die niet voorkomt in onze "
-"verbindingslijst"
-
-#: src/protocol.c:798
-#, c-format
-msgid "Got bad ADD_HOST from %s (%s)"
-msgstr "Kreeg ongeldige ADD_HOST van %s (%s)"
+"Kreeg %s van %s (%s) voor onszelf welke niet overeenkomt met reeds bekende"
 
-#: src/protocol.c:806
+#: src/protocol_edge.c:149
 #, c-format
-msgid "Got bad ADD_HOST from %s (%s): invalid identity name"
-msgstr "Kreeg ongeldige ADD_HOST van %s (%s): ongeldige identiteitsnaam"
+msgid "Got %s from %s (%s) which does not match existing entry"
+msgstr "Kreeg %s van %s (%s) welke niet overeenkomt met reeds bekende"
 
-#: src/protocol.c:813
+#: src/protocol_edge.c:159
 #, c-format
-msgid "Got bad ADD_HOST from %s (%s): invalid prevhop name"
-msgstr "Kreeg ongeldige ADD_HOST van %s (%s): ongeldige prevhop naam"
+msgid "Got %s from %s (%s) for ourself which does not exist"
+msgstr "Kreeg %s van %s (%s) voor onszelf welke niet bestaat"
 
-#: src/protocol.c:822
+#: src/protocol_edge.c:241 src/protocol_edge.c:250 src/protocol_edge.c:261
 #, c-format
-msgid "Got ADD_HOST from %s (%s) for ourself!"
-msgstr "Kreeg ADD_HOST van %s (%s) voor onszelf!"
+msgid "Got %s from %s (%s) which does not appear in the edge tree"
+msgstr "Kreeg %s van %s (%s) welke niet voorkomt in de edge tree"
 
-#: src/protocol.c:835
+#: src/protocol_edge.c:268 src/protocol_subnet.c:115 src/protocol_subnet.c:211
 #, c-format
-msgid "Got bad ADD_HOST from %s (%s): unknown prevhop"
-msgstr "Kreeg ongeldige ADD_HOST van %s (%s): onbekende prevhop"
+msgid "Got %s from %s (%s) for ourself"
+msgstr "Kreeg %s van %s (%s) voor onszelf"
 
-#: src/protocol.c:847
+#: src/protocol_key.c:87
 #, c-format
-msgid "Got duplicate ADD_HOST for %s (%s) from %s (%s)"
-msgstr "Kreeg een tweede ADD_HOST voor %s (%s) van %s (%s)"
+msgid "Got %s from %s (%s) origin %s which does not exist"
+msgstr "Kreeg %s van %s (%s) herkomst %s welke niet bestaat"
 
-#: src/protocol.c:855
+#: src/protocol_key.c:125 src/protocol_key.c:193
 #, c-format
 msgid ""
-"Removing old entry for %s (%s) from %s in favour of new connection from %s"
+"Got %s from %s (%s) origin %s which does not exist in our connection list"
 msgstr ""
-"Verwijdering oude verbinding voor %s (%s) van %s in voordeel van nieuwe "
-"verbinding van %s"
-
-#: src/protocol.c:908
-#, c-format
-msgid "Got bad DEL_HOST from %s (%s)"
-msgstr "Kreeg ongeldige DEL_HOST van %s (%s)"
-
-#: src/protocol.c:917
-#, c-format
-msgid "Got bad DEL_HOST from %s (%s): invalid identity name"
-msgstr "Kreeg ongeldige DEL_HOST van %s (%s): ongeldige identiteitsnaam"
+"Kreeg %s van %s (%s) herkomst %s welke niet voorkomt in de verbindingslijst"
 
-#: src/protocol.c:923
+#: src/protocol_key.c:134 src/protocol_key.c:202
 #, c-format
-msgid "Got bad DEL_HOST from %s (%s): invalid prevhop name"
-msgstr "Kreeg ongeldige DEL_HOST van %s (%s): ongeldige prevhop naam"
+msgid ""
+"Got %s from %s (%s) destination %s which does not exist in our connection "
+"list"
+msgstr ""
+"Kreeg %s van %s (%s) doel %s welke niet voorkomt in de verbindingslijst"
 
-#: src/protocol.c:931
+#: src/protocol_key.c:234
 #, c-format
-msgid "Got DEL_HOST from %s (%s) for ourself!"
-msgstr "Kreeg DEL_HOST van %s (%s) voor onszelf!"
+msgid "Node %s (%s) uses unknown cipher!"
+msgstr "Node %s (%s) gebruikt onbekende cipher!"
 
-#: src/protocol.c:940
+#: src/protocol_key.c:239
 #, c-format
-msgid "Got DEL_HOST from %s (%s) for %s which is not in our connection list"
-msgstr ""
-"Kreeg DEL_HOST van %s (%s) voor %s die niet in onze verbindingslijst voorkomt"
+msgid "Node %s (%s) uses wrong keylength!"
+msgstr "Node %s (%s) gebruikt verkeerde lengte sleutel!"
 
-#: src/protocol.c:949
+#: src/protocol_key.c:253
 #, c-format
-msgid "Got DEL_HOST from %s (%s) for %s which doesn't match"
-msgstr "Kreeg DEL_HOST van %s (%s) voor %s wat niet overeenkomt"
+msgid "Node %s (%s) uses unknown digest!"
+msgstr "Node %s (%s) gebruikt onbekende digest!"
 
-#: src/protocol.c:987
+#: src/protocol_key.c:259
 #, c-format
-msgid "Got bad STATUS from %s (%s)"
-msgstr "Kreeg ongeldige STATUS van %s (%s)"
+msgid "Node %s (%s) uses bogus MAC length!"
+msgstr "Node %s (%s) gebruikt onzinnige MAC lengte!"
 
-#: src/protocol.c:994
+#: src/protocol_misc.c:68
 #, c-format
 msgid "Status message from %s (%s): %s: %s"
-msgstr "Ontving statusbericht van %s (%s): %s: %s"
+msgstr "Statusmelding van %s (%s): %s: %s"
 
-#: src/protocol.c:1017
-#, c-format
-msgid "Got bad ERROR from %s (%s)"
-msgstr "Kreeg ongeldige ERROR van %s (%s)"
-
-#: src/protocol.c:1024
+#: src/protocol_misc.c:98
 #, c-format
 msgid "Error message from %s (%s): %s: %s"
-msgstr "Ontving foutmelding van %s (%s): %s: %s"
+msgstr "Foutmelding van %s (%s): %s: %s"
 
-#: src/protocol.c:1116
-#, c-format
-msgid "Got bad KEY_CHANGED from %s (%s)"
-msgstr "Kreeg ongeldige KEY_CHANGED van %s (%s)"
+#: src/protocol_subnet.c:87 src/protocol_subnet.c:186
+msgid "invalid subnet string"
+msgstr "ongeldige subnet string"
 
-#: src/protocol.c:1123
+#: src/protocol_subnet.c:177
 #, c-format
-msgid ""
-"Got KEY_CHANGED from %s (%s) origin %s which does not exist in our "
-"connection list"
-msgstr ""
-"Kreeg KEY_CHANGED van %s (%s) herkomst %s die niet in onze verbindingslijst "
-"voorkomt"
+msgid "Got %s from %s (%s) for %s which is not in our node tree"
+msgstr "Kreeg %s van %s (%s) voor %s welke niet voorkomt in de node boom"
 
-#: src/protocol.c:1152
+#: src/protocol_subnet.c:201
 #, c-format
-msgid "Got bad REQ_KEY from %s (%s)"
-msgstr "Kreeg ongeldige REQ_KEY van %s (%s)"
+msgid "Got %s from %s (%s) for %s which does not appear in his subnet tree"
+msgstr "Kreeg %s van %s (%s) voor %s welke niet voorkomt in zijn subnet boom"
 
-#: src/protocol.c:1159
+#: src/subnet.c:109
 #, c-format
-msgid ""
-"Got REQ_KEY from %s (%s) origin %s which does not exist in our connection "
-"list"
+msgid "subnet_compare() was called with unknown subnet type %d, exitting!"
 msgstr ""
-"Kreeg REQ_KEY van %s (%s) herkomst %s die niet in onze verbindingslijst "
-"voorkomt"
+"subnet_compare() werd aangeroepen met onbekend subnet type %d, beëindigen!"
 
-#: src/protocol.c:1177
-#, c-format
-msgid ""
-"Got REQ_KEY from %s (%s) destination %s which does not exist in our "
-"connection list"
-msgstr ""
-"Kreeg REQ_KEY van %s (%s) doel %s die niet in onze verbindingslijst voorkomt"
-
-#: src/protocol.c:1213
-#, c-format
-msgid "Got bad ANS_KEY from %s (%s)"
-msgstr "Kreeg ongeldige ANS_KEY van %s (%s)"
-
-#: src/protocol.c:1220
-#, c-format
-msgid ""
-"Got ANS_KEY from %s (%s) origin %s which does not exist in our connection "
-"list"
-msgstr ""
-"Kreeg ANS_KEY van %s (%s) herkomst %s die niet in onze verbindingslijst "
-"voorkomt"
-
-#: src/protocol.c:1231
-#, c-format
-msgid "Got bad ANS_KEY from %s (%s) origin %s: invalid key length"
-msgstr ""
-"Kreeg ongeldige ADD_KEY van %s (%s) herkomst %s: ongeldige sleutellengte"
-
-#: src/protocol.c:1242
-#, c-format
-msgid ""
-"Got ANS_KEY from %s (%s) destination %s which does not exist in our "
-"connection list"
-msgstr ""
-"Kreeg ANS_KEY van %s (%s) doel %s die niet in onze verbindingslijst voorkomt"
-
-#: src/protocol.c:1287
-#, c-format
-msgid "Got bad PACKET from %s (%s)"
-msgstr "Kreeg ongeldig PAKKET van %s (%s)"
-
-#: src/subnet.c:119
-#, c-format
-msgid "subnet_compare() was called with unknown subnet type %d, restarting!"
-msgstr ""
-"subnet_compare() werd aangeroepen met onbekend subnet type %d, opnieuw "
-"starten"
-
-#: src/subnet.c:156
-#, c-format
-msgid "Duplicate subnet %s for %s (%s), previous owner %s (%s)!"
-msgstr "Duplicaat subnet %s voor %s (%s), vorige eigenaar %s (%s)!"
-
-#: src/subnet.c:280
+#: src/subnet.c:327
 msgid "unknown subnet type"
 msgstr "onbekend subnet type"
 
-#: src/subnet.c:358
+#: src/subnet.c:411
 msgid "Subnet list:"
 msgstr "Subnet lijst:"
 
-#: src/subnet.c:366
+#: src/subnet.c:416
+#, c-format
+msgid " %s owner %s"
+msgstr " %s eigenaar %s"
+
+#: src/subnet.c:419
 msgid "End of subnet list."
 msgstr "Einde van subnet lijst."
 
-#: src/tincd.c:95
+#: src/tincd.c:100
 #, c-format
 msgid "Try `%s --help' for more information.\n"
 msgstr "Probeer `%s --help' voor meer informatie.\n"
 
-#: src/tincd.c:98
+#: src/tincd.c:103
 #, c-format
 msgid ""
 "Usage: %s [option]...\n"
@@ -942,7 +732,7 @@ msgstr ""
 "Gebruik: %s [optie]...\n"
 "\n"
 
-#: src/tincd.c:99
+#: src/tincd.c:104
 msgid ""
 "  -c, --config=DIR           Read configuration options from DIR.\n"
 "  -D, --no-detach            Don't fork and detach.\n"
@@ -952,12 +742,12 @@ msgid ""
 msgstr ""
 "  -c, --config=MAP           Lees configuratie uit MAP.\n"
 "  -D, --no-detach            Start geen nieuw proces.\n"
-"  -d                         Verhoog debugniveau.\n"
+"  -d, --debug[=NIVEAU]       Verhoog debugniveau of stel het in op NIVEAU.\n"
 "  -k, --kill[=SIGNAAL]       Poging tot zenden signaal naar lopende tincd en "
 "beëindig.\n"
 "  -n, --net=NETNAAM          Verbind met net NETNAAM.\n"
 
-#: src/tincd.c:104
+#: src/tincd.c:109
 msgid ""
 "  -K, --generate-keys[=BITS] Generate public/private RSA keypair.\n"
 "      --help                 Display this help and exit.\n"
@@ -969,13 +759,13 @@ msgstr ""
 "      --version              Geef versie informatie en beëindig.\n"
 "\n"
 
-#: src/tincd.c:107
+#: src/tincd.c:112
 msgid "Report bugs to tinc@nl.linux.org.\n"
 msgstr ""
 "Meld fouten in het programma aan tinc@nl.linux.org;\n"
 "Meld fouten in de vertaling aan vertaling@nl.linux.org.\n"
 
-#: src/tincd.c:150
+#: src/tincd.c:155
 #, c-format
 msgid ""
 "Invalid argument `%s'; BITS must be a number equal to or greater than 512.\n"
@@ -983,24 +773,24 @@ msgstr ""
 "Ongeldig argument `%s'; BITS moet een nummer zijn gelijk aan of groter dan "
 "512.\n"
 
-#: src/tincd.c:211
+#: src/tincd.c:216
 #, c-format
 msgid "Generating %d bits keys:\n"
 msgstr "Bezig met genereren van een %d bits sleutel:\n"
 
-#: src/tincd.c:216
+#: src/tincd.c:221
 msgid "Error during key generation!\n"
 msgstr "Fout tijdens genereren sleutel!\n"
 
-#: src/tincd.c:220
+#: src/tincd.c:225
 msgid "Done.\n"
 msgstr "Klaar.\n"
 
-#: src/tincd.c:227
+#: src/tincd.c:234
 msgid "public RSA key"
 msgstr "openbare RSA sleutel"
 
-#: src/tincd.c:231 src/tincd.c:242
+#: src/tincd.c:238 src/tincd.c:249
 msgid ""
 "Appending key to existing contents.\n"
 "Make sure only one key is stored in the file.\n"
@@ -1008,30 +798,30 @@ msgstr ""
 "Sleutel wordt toegevoegd aan bestaande inhoud.\n"
 "Let er op dat er slechts Ã©Ã©n sleutel in het bestand is.\n"
 
-#: src/tincd.c:238
+#: src/tincd.c:245
 msgid "private RSA key"
 msgstr "geheime RSA sleutel"
 
-#: src/tincd.c:263
+#: src/tincd.c:270
 msgid "Both netname and configuration directory given, using the latter..."
 msgstr ""
 "Zowel netnaam als configuratiemap zijn gegeven, laatste wordt gebruikt..."
 
-#: src/tincd.c:292
+#: src/tincd.c:299
 #, c-format
 msgid "%s version %s (built %s %s, protocol %d)\n"
 msgstr "%s versie %s (gemaakt %s %s, protocol %d)\n"
 
-#: src/tincd.c:293
+#: src/tincd.c:300
 msgid ""
-"Copyright (C) 1998-2001 Ivo Timmermans, Guus Sliepen and others.\n"
+"Copyright (C) 1998-2002 Ivo Timmermans, Guus Sliepen and others.\n"
 "See the AUTHORS file for a complete list.\n"
 "\n"
 "tinc comes with ABSOLUTELY NO WARRANTY.  This is free software,\n"
 "and you are welcome to redistribute it under certain conditions;\n"
 "see the file COPYING for details.\n"
 msgstr ""
-"Copyright (C) 1998-2001 Ivo Timmermans, Guus Sliepen en anderen.\n"
+"Copyright (C) 1998-2002 Ivo Timmermans, Guus Sliepen en anderen.\n"
 "Zie het bestand AUTHORS voor een volledige lijst.\n"
 "\n"
 "tinc wordt gedistribueerd ZONDER ENIGE GARANTIE.  Dit is vrije "
@@ -1039,127 +829,120 @@ msgstr ""
 "en je bent welkom om het te distribueren onder bepaalde voorwaarden;\n"
 "zie het bestand COPYING voor details.\n"
 
-#: src/tincd.c:307
+#: src/tincd.c:314
 msgid "You must be root to run this program.\n"
 msgstr "Je moet systeembeheerder zijn om dit programma te kunnen draaien.\n"
 
-#: src/tincd.c:348
+#: src/tincd.c:363
 msgid "Unrecoverable error"
 msgstr "Onherstelbare fout"
 
-#: src/tincd.c:353
+#: src/tincd.c:368
 #, c-format
 msgid "Restarting in %d seconds!"
 msgstr "Herstart in %d seconden!"
 
-#: src/process.c:340 src/tincd.c:358
+#: src/process.c:358 src/tincd.c:373
 msgid "Not restarting."
 msgstr "Geen herstart."
 
-#: src/process.c:62
+#: src/process.c:68
 #, c-format
 msgid "Memory exhausted (couldn't allocate %d bytes), exiting."
 msgstr "Geheugen uitgeput (kon geen %d bytes reserveren), beëindigen."
 
-#: src/process.c:90
-#, c-format
-msgid "Total bytes written: tap %d, socket %d; bytes read: tap %d, socket %d"
-msgstr ""
-"Totaal aantal bytes geschreven: tap %d, socket %d; bytes read: tap %d, "
-"socket %d"
-
-#: src/process.c:93
+#: src/process.c:98
 msgid "Terminating"
 msgstr "Beëindigen"
 
-#: src/process.c:109
+#: src/process.c:114
 #, c-format
 msgid "A tincd is already running for net `%s' with pid %d.\n"
 msgstr "Een tincd draait al voor net `%s' met pid %d.\n"
 
-#: src/process.c:112
+#: src/process.c:117
 #, c-format
 msgid "A tincd is already running with pid %d.\n"
 msgstr "Een tincd draait al met pid %d.\n"
 
-#: src/process.c:133
+#: src/process.c:138
 #, c-format
 msgid "No other tincd is running for net `%s'.\n"
 msgstr "Geen andere tincd draait voor net `%s'.\n"
 
-#: src/process.c:135
+#: src/process.c:140
 msgid "No other tincd is running.\n"
 msgstr "Geen andere tincd draait.\n"
 
-#: src/process.c:142
+#: src/process.c:147
 msgid "Removing stale lock file.\n"
 msgstr "Verwijdering oud vergrendelingsbestand.\n"
 
-#: src/process.c:169
+#: src/process.c:174
 #, c-format
 msgid "Couldn't detach from terminal: %s"
 msgstr "Kon niet ontkoppelen van terminal: %s"
 
-#: src/process.c:182
+#: src/process.c:187
 #, c-format
 msgid "tincd %s (%s %s) starting, debug level %d"
 msgstr "tincd %s (%s %s) start, debug niveau %d"
 
-#: src/process.c:185
+#: src/process.c:190
 #, c-format
 msgid "tincd %s starting"
 msgstr "tincd %s wordt gestart"
 
-#: src/process.c:249
+#: src/process.c:266
 #, c-format
 msgid "Executing script %s"
 msgstr "Uitvoeren script %s"
 
-#: src/process.c:257
+#: src/process.c:274
 #, c-format
 msgid "Process %d (%s) exited with non-zero status %d"
 msgstr "Proces %d (%s) beëindigde met status %d"
 
-#: src/process.c:265
+#: src/process.c:282
 #, c-format
 msgid "Process %d (%s) was killed by signal %d (%s)"
 msgstr "Proces %d (%s) was gestopt door signaal %d (%s)"
 
-#: src/process.c:271
+#: src/process.c:288
 #, c-format
 msgid "Process %d (%s) terminated abnormally"
 msgstr "Proces %d (%s) abnormaal beëindigd"
 
-#: src/process.c:296
+#: src/process.c:313
 msgid "Got TERM signal"
 msgstr "Kreeg TERM signaal"
 
-#: src/process.c:305
+#: src/process.c:322
 msgid "Got QUIT signal"
 msgstr "Kreeg QUIT signaal"
 
-#: src/process.c:312
+#: src/process.c:329
 msgid "Got another SEGV signal: not restarting"
 msgstr "Kreeg nog een SEGV signaal: geen herstart"
 
-#: src/process.c:321
+#: src/process.c:338
 msgid "Got SEGV signal"
 msgstr "Kreeg SEGV signaal"
 
-#: src/process.c:326
+#: src/process.c:343
 msgid "Trying to re-execute in 5 seconds..."
 msgstr "Poging tot herstarten over 5 seconden..."
 
-#: src/process.c:349
+#: src/process.c:367
 msgid "Got HUP signal"
 msgstr "Kreeg HUP signaal"
 
-#: src/process.c:358
+#: src/process.c:376
 #, c-format
 msgid "Reverting to old debug level (%d)"
 msgstr "Herstellen van oud debug niveau (%d)"
 
-#: src/process.c:365
+#: src/process.c:383
 #, c-format
 msgid ""
 "Temporarily setting debug level to 5.  Kill me with SIGINT again to go back "
@@ -1168,54 +951,216 @@ msgstr ""
 "Tijdelijk instellen debug niveau op 5. Zend nog een SIGINT signaal om niveau "
 "%d te herstellen."
 
-#: src/process.c:387 src/process.c:396
+#: src/process.c:394
+msgid "Got ALRM signal"
+msgstr "Kreeg ALRM signaal"
+
+#: src/process.c:423
 #, c-format
 msgid "Got unexpected signal %d (%s)"
 msgstr "Kreeg onverwacht signaal %d (%s)"
 
-#: src/process.c:443
+#: src/process.c:432
+#, c-format
+msgid "Ignored signal %d (%s)"
+msgstr "Signaal %d (%s) genegeerd"
+
+#: src/process.c:487
 #, c-format
 msgid "Installing signal handler for signal %d (%s) failed: %s\n"
 msgstr "Installeren van signaal afhandelaar voor signaal %d (%s) faalde: %s\n"
 
-#: src/route.c:68
+#: src/route.c:69
 #, c-format
-msgid "Learned new MAC address %hhx:%hhx:%hhx:%hhx:%hhx:%hhx"
-msgstr "Nieuw MAC adres %hhx:%hhx:%hhx:%hhx:%hhx:%hhx geleerd"
+msgid "Learned new MAC address %hx:%hx:%hx:%hx:%hx:%hx"
+msgstr "Nieuw MAC adres %hx:%hx:%hx:%hx:%hx:%hx geleerd"
 
-#: src/route.c:123
+#: src/route.c:124
 #, c-format
 msgid "Cannot route packet: unknown destination address %d.%d.%d.%d"
 msgstr "Kan pakket niet routeren: onbekend doeladres %d.%d.%d.%d"
 
-#: src/route.c:138
-msgid "Cannot route packet: IPv6 routing not yet implemented"
-msgstr "Kan pakket niet routeren: IPv6 routering nog niet geïmplementeerd"
+#: src/route.c:144
+#, c-format
+msgid ""
+"Cannot route packet: unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%"
+"hx:%hx:%hx"
+msgstr ""
+"Kan pakket niet routeren: onbekend IPv6 doeladres %hx:%hx:%hx:%hx:%hx:%hx:%"
+"hx:%hx"
 
-#: src/route.c:172
+#: src/route.c:189
 msgid "Cannot route packet: received unknown type ARP request"
 msgstr "Kan pakket niet routeren: ontvangst van onbekend type ARP verzoek"
 
-#: src/route.c:186
+#: src/route.c:203
 #, c-format
 msgid "Cannot route packet: ARP request for unknown address %d.%d.%d.%d"
 msgstr "Kan pakket niet routeren: ARP verzoek voor onbekend adres %d.%d.%d.%d"
 
-#: src/route.c:238
+#: src/route.c:255
 #, c-format
 msgid "Cannot route packet: unknown type %hx"
 msgstr "Kan pakket niet routeren: onbekend type %hx"
 
-#~ msgid "Still failed to connect to other, will retry in %d seconds"
-#~ msgstr "Wederom niet verbonden met de ander, nieuwe poging over %d seconden"
+#: src/node.c:161
+msgid "Nodes:"
+msgstr "Nodes:"
 
-#~ msgid "Uplink %s (%s) is already in our connection list"
-#~ msgstr "%s (%s) staat al in onze verbindingslijst"
+#: src/node.c:166
+#, c-format
+msgid ""
+" %s at %s port %hd cipher %d digest %d maclength %d options %ld status %04x "
+"nexthop %s via %s"
+msgstr ""
+" %s op %s poort %hd cipher %d digest %d maclengte %d opties %ld status %04x "
+"nexthop %s via %s"
 
-#~ msgid "Removing old entry for %s (%s) in favour of new connection"
-#~ msgstr ""
-#~ "Verwijdering oude verbinding voor %s (%s) in voordeel van nieuwe "
-#~ "verbinding"
+#: src/node.c:171
+msgid "End of nodes."
+msgstr "Einde van nodes."
+
+#: src/edge.c:194
+msgid "Edges:"
+msgstr "Edges:"
+
+#: src/edge.c:201
+#, c-format
+msgid " %s at %s port %hd - %s at %s port %hd options %ld weight %d"
+msgstr " %s op %s poort %hd - %s op %s poort %hd opties %ld gewicht %d"
+
+#: src/edge.c:209
+msgid "End of edges."
+msgstr "Einde van edges."
+
+#: src/graph.c:224
+#, c-format
+msgid "Node %s (%s) became reachable"
+msgstr "Node %s (%s) werd bereikbaar"
+
+#: src/graph.c:233
+#, c-format
+msgid "Node %s (%s) became unreachable"
+msgstr "Node %s (%s) is niet meer bereikbaar"
+
+#: src/freebsd/device.c:69 src/linux/device.c:84 src/openbsd/device.c:73
+#: src/solaris/device.c:74
+#, c-format
+msgid "Could not open %s: %m"
+msgstr "Kon `%s' niet openen: %m"
+
+#: src/linux/device.c:109 src/linux/device.c:119
+msgid "Linux tun/tap device"
+msgstr "Linux tun/tap apparaat"
 
-#~ msgid "Got INT signal, exiting"
-#~ msgstr "Kreeg INT signaal, beëindigen"
+#: src/linux/device.c:117
+#, c-format
+msgid "Old ioctl() request was needed for %s"
+msgstr "Oud ioctl() verzoek was nodig voor %s"
+
+#: src/linux/device.c:126
+msgid "Linux ethertap device"
+msgstr "Linux ethertap apparaat"
+
+#: src/freebsd/device.c:86 src/linux/device.c:130 src/openbsd/device.c:89
+#: src/solaris/device.c:128
+#, c-format
+msgid "%s is a %s"
+msgstr "%s is een %s"
+
+#: src/freebsd/device.c:107 src/linux/device.c:153 src/linux/device.c:163
+#: src/openbsd/device.c:110 src/solaris/device.c:145
+#, c-format
+msgid "Error while reading from %s %s: %m"
+msgstr "Fout tijdens lezen van %s %s: %m"
+
+#: src/freebsd/device.c:116 src/linux/device.c:174 src/openbsd/device.c:125
+#: src/solaris/device.c:160
+#, c-format
+msgid "Read packet of %d bytes from %s"
+msgstr "Pakket van %d bytes gelezen van %s"
+
+#: src/freebsd/device.c:127 src/linux/device.c:185 src/openbsd/device.c:138
+#: src/solaris/device.c:171
+#, c-format
+msgid "Writing packet of %d bytes to %s"
+msgstr "Pakket van %d bytes geschreven naar %s"
+
+#: src/linux/device.c:192 src/linux/device.c:201 src/openbsd/device.c:148
+#: src/solaris/device.c:176
+#, c-format
+msgid "Can't write to %s %s: %m"
+msgstr "Kan niet schrijven naar %s %s: %m"
+
+#: src/freebsd/device.c:143 src/linux/device.c:214 src/openbsd/device.c:159
+#: src/solaris/device.c:188
+#, c-format
+msgid "Statistics for %s %s:"
+msgstr "Statistieken voor %s %s:"
+
+#: src/freebsd/device.c:144 src/linux/device.c:215 src/openbsd/device.c:160
+#: src/solaris/device.c:189
+#, c-format
+msgid " total bytes in:  %10d"
+msgstr " totaal aantal bytes in:  %10d"
+
+#: src/freebsd/device.c:145 src/linux/device.c:216 src/openbsd/device.c:161
+#: src/solaris/device.c:190
+#, c-format
+msgid " total bytes out: %10d"
+msgstr " totaal aantal bytes uit: %10d"
+
+#: src/freebsd/device.c:84
+msgid "FreeBSD tap device"
+msgstr "FreeBSD tap apparaat"
+
+#: src/freebsd/device.c:132
+#, c-format
+msgid "Error while writing to %s %s: %m"
+msgstr "Fout tijdens schrijven naar %s %s: %m"
+
+#: src/openbsd/device.c:87
+msgid "OpenBSD tun device"
+msgstr "OpenBSD tun apparaat"
+
+#: src/solaris/device.c:85
+#, c-format
+msgid "Could not open /dev/ip: %m"
+msgstr "Kon /dev/ip niet openen: %m"
+
+#: src/solaris/device.c:91
+#, c-format
+msgid "Can't assign new interface: %m"
+msgstr "Kan geen nieuwe interface toekennen: %m"
+
+#: src/solaris/device.c:96
+#, c-format
+msgid "Could not open %s twice: %m"
+msgstr "Kon `%s' niet twee keer openen: %m"
+
+#: src/solaris/device.c:101
+#, c-format
+msgid "Can't push IP module: %m"
+msgstr "Kan IP module niet invoegen: %m"
+
+#: src/solaris/device.c:107
+#, c-format
+msgid "Can't set PPA %d: %m"
+msgstr "Kon PPA %d niet instellen: %m"
+
+#: src/solaris/device.c:112
+#, c-format
+msgid "Can't link TUN device to IP: %m"
+msgstr "Kan TUN apparaat niet koppelen aan IP: %m"
+
+#: src/solaris/device.c:116
+msgid "Solaris tun device"
+msgstr "Solaris tun apparaat"
+
+#~ msgid "No digest, MAC length ignored"
+#~ msgstr "Geen digest, MAC lengte genegeerd"
+
+#~ msgid "Failed to setup all outgoing connections, will retry in %d seconds"
+#~ msgstr ""
+#~ "Poging tot maken van alle uitgaande verbinding faalde, nieuwe poging over "
+#~ "%d seconden"
diff --git a/redhat/Makefile.am b/redhat/Makefile.am
deleted file mode 100644 (file)
index 1eaf7d6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-EXTRA_DIST = tinc tinc.spec
index 59f6f5e70225efed35d87c61ae7fd57333a09837..7ea85a15227d21c8001654fa32edcf5c185746d1 100644 (file)
@@ -1,14 +1,17 @@
 ## Produce this file with automake to get Makefile.in
-# $Id: Makefile.am,v 1.4.4.18 2001/11/16 12:16:28 zarq Exp $
+# $Id: Makefile.am,v 1.4.4.19 2002/02/10 21:57:52 guus Exp $
 
 sbin_PROGRAMS = tincd
 
-tincd_SOURCES = conf.c connection.c device.c edge.c graph.c meta.c net.c node.c process.c      \
-       protocol.c route.c subnet.c tincd.c
+EXTRA_DIST = linux/device.c freebsd/device.c openbsd/device.c solaris/device.c
+
+tincd_SOURCES = conf.c connection.c device.c edge.c event.c graph.c meta.c net.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
 
-noinst_HEADERS = conf.h connection.h device.h edge.h graph.h meta.h net.h node.h process.h     \
+noinst_HEADERS = conf.h connection.h device.h edge.h event.h graph.h meta.h net.h netutl.h node.h process.h    \
        protocol.h route.h subnet.h
 
 LIBS = @LIBS@ @INTLLIBS@
index 3be2e33eda1874f6bf71d1dbadbaa5c8eb16b55a..fc8237201cba67075f3aed67836fecd29818d079 100644 (file)
@@ -1,8 +1,8 @@
 /*
     conf.c -- configuration code
     Copyright (C) 1998 Robert van der Meulen
-                  1998-2001 Ivo Timmermans <itimmermans@bigfoot.com>
-                  2000,2001 Guus Sliepen <guus@sliepen.warande.net>
+                  1998-2002 Ivo Timmermans <itimmermans@bigfoot.com>
+                  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
@@ -19,7 +19,7 @@
     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.9.4.51 2001/11/16 22:31:41 zarq Exp $
+    $Id: conf.c,v 1.9.4.52 2002/02/10 21:57:53 guus Exp $
 */
 
 #include "config.h"
 #include <avl_tree.h>
 
 #include "conf.h"
+#include "netutl.h" /* for str2address */
 
 #include "system.h"
 
 avl_tree_t *config_tree;
 
 int debug_lvl = 0;
-int timeout = 0; /* seconds before timeout */
+int pingtimeout = 0;             /* seconds before timeout */
 char *confbase = NULL;           /* directory in which all config files are */
 char *netname = NULL;            /* name of the vpn network */
 
-/* Will be set if HUP signal is received. It will be processed when it is safe. */
-int sighup = 0;
-
 int config_compare(config_t *a, config_t *b)
 {
   int result;
@@ -202,6 +200,41 @@ cp
   return 1;
 }
 
+int get_config_address(config_t *cfg, ipv4_t **result)
+{
+  ipv4_t *ip;
+cp
+  if(!cfg)
+    return 0;
+
+  ip = xmalloc(sizeof(*ip));
+  *ip = str2address(cfg->value);
+
+  if(ip)
+    {
+      *result = ip;
+      return 1;
+    }
+
+  syslog(LOG_ERR, _("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)
+    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;
@@ -209,34 +242,27 @@ cp
   if(!cfg)
     return 0;
 
-#warning FIXME 
-/*   ip = strtoip(cfg->value); */
+  subnet = str2net(cfg->value);
 
-/*   if(!ip) */
-/*     { */
-/*       syslog(LOG_ERR, _("IP address expected for configuration variable %s in %s line %d"), */
-/*              cfg->variable, cfg->file, cfg->line); */
-/*       return 0; */
-/*     } */
+  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((ip->address & ip->mask) != ip->address) */
-/*     { */
-/*       syslog(LOG_ERR, _("Network address and subnet mask for configuration variable %s in %s line %d"), */
-/*              cfg->variable, cfg->file, cfg->line); */
-/*       free(ip); */
-/*       return 0; */
-/*     } */
-
-/*   subnet = new_subnet(); */
-/*   subnet->type = SUBNET_IP; */
-/*   subnet->net.ip.address = ip->address; */
-/*   subnet->net.ip.mask = ip->mask; */
-  
-/*   free(ip); */
+  if(subnet->type == SUBNET_IPV4)
+    if((subnet->net.ipv4.address & subnet->net.ipv4.mask) != subnet->net.ipv4.address)
+      {
+       syslog(LOG_ERR, _("Network address and mask length do not match for configuration variable %s in %s line %d"),
+               cfg->variable, cfg->file, cfg->line);
+       free(subnet);
+       return 0;
+      }
 
-/*   *result = subnet; */
+  *result = subnet;
   
   return 1;
 }
index 0d3d664526444227dcde88ec78a3893f85302f66..a04d6687d81ec5936c3772c44448a69bb4adbe38 100644 (file)
@@ -1,7 +1,7 @@
 /*
     conf.h -- header for conf.c
-    Copyright (C) 1998-2001 Ivo Timmermans <itimmermans@bigfoot.com>
-                  2000,2001 Guus Sliepen <guus@sliepen.warande.net>
+    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
@@ -17,7 +17,7 @@
     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.6.4.30 2001/11/16 12:14:20 zarq Exp $
+    $Id: conf.h,v 1.6.4.31 2002/02/10 21:57:53 guus Exp $
 */
 
 #ifndef __TINC_CONF_H__
@@ -37,9 +37,8 @@ typedef struct config_t {
 extern avl_tree_t *config_tree;
 
 extern int debug_lvl;
-extern int timeout;
+extern int pingtimeout;
 extern int maxtimeout;
-extern int sighup;
 extern int bypass_security;
 extern char *confbase;
 extern char *netname;
@@ -53,7 +52,9 @@ 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 *, ipv4_t **);
 struct subnet_t; /* Needed for next line. */
 extern int get_config_subnet(config_t *, struct subnet_t **);
 
index f7f650050467709e772b1e0879a7f2717d015d65..815de4ba29a914816a1c0cb685d9393fad58297e 100644 (file)
@@ -1,7 +1,7 @@
 /*
     connection.c -- connection list management
-    Copyright (C) 2000,2001 Guus Sliepen <guus@sliepen.warande.net>,
-                  2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>
+    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
@@ -17,7 +17,7 @@
     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.2.26 2001/11/16 12:20:44 zarq Exp $
+    $Id: connection.c,v 1.1.2.27 2002/02/10 21:57:53 guus Exp $
 */
 
 #include "config.h"
@@ -31,6 +31,7 @@
 #include <list.h>
 
 #include "net.h"       /* Don't ask. */
+#include "netutl.h"
 #include "config.h"
 #include "conf.h"
 #include <utils.h>
@@ -105,11 +106,12 @@ cp
 cp
 }
 
-connection_t *lookup_connection(struct addrinfo *address)
+connection_t *lookup_connection(ipv4_t address, port_t port)
 {
   connection_t c;
 cp
   c.address = address;
+  c.port = port;
 
   return avl_search(connection_tree, &c);
 }
index 349fd97135d02f32a3665db9bda7fcaf9a3b1abd..1689aee35d551ab1cba2f5eb4bd281f8d137e69d 100644 (file)
@@ -1,7 +1,7 @@
 /*
     connection.h -- header for connection.c
-    Copyright (C) 2000,2001 Guus Sliepen <guus@sliepen.warande.net>,
-                  2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>
+    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
@@ -17,7 +17,7 @@
     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.2.23 2001/11/16 12:01:48 zarq Exp $
+    $Id: connection.h,v 1.1.2.24 2002/02/10 21:57:53 guus Exp $
 */
 
 #ifndef __TINC_CONNECTION_H__
 #include "node.h"
 #include "edge.h"
 
-#include <config.h>
-#include <dropin.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 outgoing:1;                  /* I myself asked for this conn */
   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:17;
+  int unused:18;
 } connection_status_t;
 
 typedef struct connection_t {
   char *name;                      /* name he claims to have */
 
-  struct addrinfo *address;        /* his real (internet) ip */
-  char *port;                      /* port number of meta connection */
+  ipv4_t address;                  /* his real (internet) ip */
+  port_t port;                     /* port number of meta connection */
   char *hostname;                  /* the hostname of its real ip */
   int protocol_version;            /* used protocol */
 
@@ -78,9 +74,10 @@ typedef struct connection_t {
   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 */
+  struct edge_t *edge;         /* edge associated with this connection */
 
   RSA *rsa_key;                    /* his public/private key */
   EVP_CIPHER *incipher;            /* Cipher he will use to send data to us */
@@ -112,7 +109,7 @@ 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 connection_t *lookup_connection(struct addrinfo *);
+extern connection_t *lookup_connection(ipv4_t, short unsigned int);
 extern void dump_connections(void);
 extern int read_connection_config(connection_t *);
 
index 05dcaaa6bb81fe0253017f58b616d8479bf3d0c0..3d3aa761b808c00e97f37147a1fe4ca80ee02d4b 100644 (file)
@@ -1,7 +1,7 @@
 /*
     net.h -- generic header for device.c
-    Copyright (C) 2001 Ivo Timmermans <zarq@iname.com>
-                  2001 Guus Sliepen <guus@sliepen.warande.net>
+    Copyright (C) 2001-2002 Ivo Timmermans <zarq@iname.com>
+                  2001-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
@@ -17,7 +17,7 @@
     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.1.2.4 2001/10/31 12:50:24 guus Exp $
+    $Id: device.h,v 1.1.2.5 2002/02/10 21:57:54 guus Exp $
 */
 
 #ifndef __TINC_DEVICE_H__
index b9ecd8ef4bc936725dd6a1abee89609a040df71a..1851f51f8b9b5d5aa1b91143c3f236d9a2e1cf00 100644 (file)
@@ -1,7 +1,7 @@
 /*
     edge.c -- edge tree management
-    Copyright (C) 2000,2001 Guus Sliepen <guus@sliepen.warande.net>,
-                  2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>
+    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
@@ -17,7 +17,7 @@
     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.2.5 2001/11/16 12:21:49 zarq Exp $
+    $Id: edge.c,v 1.1.2.6 2002/02/10 21:57:54 guus Exp $
 */
 
 #include "config.h"
@@ -30,6 +30,7 @@
 #include <list.h>
 
 #include "net.h"       /* Don't ask. */
+#include "netutl.h"
 #include "config.h"
 #include "conf.h"
 #include <utils.h>
@@ -45,12 +46,12 @@ int edge_compare(edge_t *a, edge_t *b)
 {
   int result;
 
-  result = strcmp(a->from->name, b->from->name);
+  result = strcmp(a->from.node->name, b->from.node->name);
   
   if(result)
     return result;
   else
-    return strcmp(a->to->name, b->to->name);
+    return strcmp(a->to.node->name, b->to.node->name);
 }
 
 /* Evil edge_compare() from a parallel universe ;)
@@ -59,7 +60,7 @@ int edge_compare(edge_t *a, edge_t *b)
 {
   int result;
 
-  return (result = strcmp(a->from->name, b->from->name)) || (result = strcmp(a->to->name, b->to->name)), result;
+  return (result = strcmp(a->from.node->name, b->from.node->name)) || (result = strcmp(a->to.node->name, b->to.node->name)), result;
 }
 
 */
@@ -69,15 +70,15 @@ 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->name, a->to->name) < 0)
-    name_a1 = a->from->name, name_a2 = a->to->name;
+  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->name, name_a2 = a->from->name;
+    name_a1 = a->to.node->name, name_a2 = a->from.node->name;
 
-  if(strcmp(b->from->name, b->to->name) < 0)
-    name_b1 = b->from->name, name_b2 = b->to->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->name, name_b2 = b->from->name;
+    name_b1 = b->to.node->name, name_b2 = b->from.node->name;
 
   result = strcmp(name_a1, name_b1);
   
@@ -151,8 +152,8 @@ void edge_add(edge_t *e)
 cp
   avl_insert(edge_tree, e);
   avl_insert(edge_weight_tree, e);
-  avl_insert(e->from->edge_tree, e);
-  avl_insert(e->to->edge_tree, e);
+  avl_insert(e->from.node->edge_tree, e);
+  avl_insert(e->to.node->edge_tree, e);
 cp
 }
 
@@ -161,8 +162,8 @@ void edge_del(edge_t *e)
 cp
   avl_delete(edge_tree, e);
   avl_delete(edge_weight_tree, e);
-  avl_delete(e->from->edge_tree, e);
-  avl_delete(e->to->edge_tree, e);
+  avl_delete(e->from.node->edge_tree, e);
+  avl_delete(e->to.node->edge_tree, e);
 cp
 }
 
@@ -170,16 +171,16 @@ edge_t *lookup_edge(node_t *from, node_t *to)
 {
   edge_t v, *result;
 cp
-  v.from = from;
-  v.to = to;
+  v.from.node = from;
+  v.to.node = to;
 
   result = avl_search(edge_tree, &v);
 
   if(result)
     return result;
 cp
-  v.from = to;
-  v.to = from;
+  v.from.node = to;
+  v.to.node = from;
 
   return avl_search(edge_tree, &v);
 }
@@ -188,14 +189,21 @@ void dump_edges(void)
 {
   avl_node_t *node;
   edge_t *e;
+  char *from_address, *to_address;
 cp
   syslog(LOG_DEBUG, _("Edges:"));
 
   for(node = edge_tree->head; node; node = node->next)
     {
       e = (edge_t *)node->data;
-      syslog(LOG_DEBUG, _(" %s - %s options %ld weight %d"),
-             e->from->name, e->to->name, e->options, e->weight);
+      from_address = address2str(e->from.address);
+      to_address = address2str(e->to.address);
+      syslog(LOG_DEBUG, _(" %s at %s port %hd - %s at %s port %hd options %ld weight %d"),
+             e->from.node->name, from_address, e->from.port,
+            e->to.node->name, to_address, e->to.port,
+            e->options, e->weight);
+      free(from_address);
+      free(to_address);             
     }
     
   syslog(LOG_DEBUG, _("End of edges."));
index 0de989adb188e6bfde74f49195934c8ffbbfeb20..9a60af652a645d6ddb304e4c616632b94bc1fa8a 100644 (file)
@@ -1,7 +1,7 @@
 /*
     edge.h -- header for edge.c
-    Copyright (C) 2001 Guus Sliepen <guus@sliepen.warande.net>,
-                  2001 Ivo Timmermans <itimmermans@bigfoot.com>
+    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
@@ -17,7 +17,7 @@
     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.2.4 2001/11/16 12:13:34 zarq Exp $
+    $Id: edge.h,v 1.1.2.5 2002/02/10 21:57:54 guus Exp $
 */
 
 #ifndef __TINC_EDGE_H__
 #include "node.h"
 #include "connection.h"
 
-/* I don't know if halfconnection_t is useful... */
-
 typedef struct halfconnection_t {
   struct node_t *node;             /* node associated with this end of the connection */
 
-  struct addrinfo *address;        /* real (internet) ip on this end of the meta connection */
-  char *hostname;                  /* the hostname of real ip */
+  ipv4_t address;                  /* real (internet) ip on this end of the meta connection */
+  port_t port;                     /* port number of this end of the meta connection */
 } halfconnection_t;
 
 typedef struct edge_t {
-  struct node_t *from;
-  struct node_t *to;
+  struct halfconnection_t from;
+  struct halfconnection_t to;
 
   long int options;                /* options turned on for this edge */
   int weight;                      /* weight of this edge */
index b11bab932793d2ca451101072a9653476a134251..492ba33d3f95db5154808cfadf4b614e29963217 100644 (file)
@@ -1,7 +1,7 @@
 /*
     device.c -- Interaction with FreeBSD tap device
-    Copyright (C) 2001 Ivo Timmermans <itimmermans@bigfoot.com>,
-                  2001 Guus Sliepen <guus@sliepen.warande.net>
+    Copyright (C) 2001-2002 Ivo Timmermans <itimmermans@bigfoot.com>,
+                  2001-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
     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.1.2.1 2001/10/12 15:22:59 guus Exp $
+    $Id: device.c,v 1.1.2.2 2002/02/10 21:57:54 guus Exp $
 */
 
+#include "config.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <net/if.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <string.h>
+
+#include <utils.h>
+#include "conf.h"
+#include "net.h"
+#include "subnet.h"
+
+#include "system.h"
+
 #define DEFAULT_DEVICE "/dev/tap0"
 
 int device_fd = -1;
 int device_type;
-char *device_fname;
+char *device;
+char *interface;
 char *device_info;
-
 int device_total_in = 0;
 int device_total_out = 0;
 
-*
+extern subnet_t mymac;
+
+/*
   open the local ethertap device
 */
 int setup_device(void)
 {
-  struct ifreq ifr;
-
 cp
-  if(!get_config_string(lookup_config(config_tree, "Device"), &device_fname)))
-    device_fname = DEFAULT_DEVICE;
+  if(!get_config_string(lookup_config(config_tree, "Device"), &device))
+    device = DEFAULT_DEVICE;
 
+  if(!get_config_string(lookup_config(config_tree, "Interface"), &interface))
+    interface = netname;
 cp
-  if((device_fd = open(device_fname, O_RDWR | O_NONBLOCK)) < 0)
+  if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0)
     {
-      syslog(LOG_ERR, _("Could not open %s: %m"), device_fname);
+      syslog(LOG_ERR, _("Could not open %s: %m"), device);
       return -1;
     }
 cp
-  device_fd = device_fd;
 
   /* Set default MAC address for ethertap devices */
 
@@ -62,11 +83,17 @@ cp
 
   device_info = _("FreeBSD tap device");
 
-  syslog(LOG_INFO, _("%s is a %s"), device_fname, device_info);
+  syslog(LOG_INFO, _("%s is a %s"), device, device_info);
 cp
   return 0;
 }
 
+void close_device(void)
+{
+cp
+  close(device_fd);
+}
+
 /*
   read, encrypt and send data that is
   available through the ethertap device
@@ -77,7 +104,7 @@ int read_packet(vpn_packet_t *packet)
 cp
   if((lenin = read(device_fd, packet->data, MTU)) <= 0)
     {
-      syslog(LOG_ERR, _("Error while reading from %s %s: %m"), device_info, device_fname);
+      syslog(LOG_ERR, _("Error while reading from %s %s: %m"), device_info, device);
       return -1;
     }
 
@@ -102,10 +129,19 @@ cp
 
   if(write(device_fd, packet->data, packet->len) < 0)
     {
-      syslog(LOG_ERR, _("Error while writing to %s %s: %m"), device_info, device_fname);
+      syslog(LOG_ERR, _("Error while writing to %s %s: %m"), device_info, device);
       return -1;
     }
 
   device_total_out += packet->len;
 cp
 }
+
+void dump_device_stats(void)
+{
+cp
+  syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
+  syslog(LOG_DEBUG, _(" total bytes in:  %10d"), device_total_in);
+  syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
+cp
+}
index aa1ec72a26bddf757e3d0b4c21e1b45397e78ece..0847b2814e081996a52c327e445d15ced83d06be 100644 (file)
@@ -1,7 +1,7 @@
 /*
     graph.c -- graph algorithms
-    Copyright (C) 2001 Guus Sliepen <guus@sliepen.warande.net>,
-                  2001 Ivo Timmermans <itimmermans@bigfoot.com>
+    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
@@ -17,7 +17,7 @@
     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.2.5 2001/10/31 12:50:24 guus Exp $
+    $Id: graph.c,v 1.1.2.6 2002/02/10 21:57:54 guus Exp $
 */
 
 /* We need to generate two trees from the graph:
 
    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 <syslog.h>
 #include "config.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 <utils.h>
 
+#include "netutl.h"
 #include "node.h"
 #include "edge.h"
 #include "connection.h"
@@ -67,6 +77,11 @@ void mst_kruskal(void)
   int safe_edges = 0;
   int skipped;
 
+  /* Do we have something to do at all? */
+  
+  if(!edge_weight_tree->head)
+    return;
+
   /* Clear visited status on nodes */
 
   for(node = node_tree->head; node; node = node->next)
@@ -78,7 +93,7 @@ void mst_kruskal(void)
 
   /* Starting point */
   
-  ((edge_t *)edge_weight_tree->head->data)->from->status.visited = 1;
+  ((edge_t *)edge_weight_tree->head->data)->from.node->status.visited = 1;
 
   /* Clear MST status on connections */
 
@@ -95,14 +110,14 @@ void mst_kruskal(void)
       next = node->next;
       e = (edge_t *)node->data;
 
-      if(e->from->status.visited == e->to->status.visited)
+      if(e->from.node->status.visited == e->to.node->status.visited)
         {
           skipped = 1;
           continue;
         }
 
-      e->from->status.visited = 1;
-      e->to->status.visited = 1;
+      e->from.node->status.visited = 1;
+      e->to.node->status.visited = 1;
       if(e->connection)
         e->connection->status.mst = 1;
 
@@ -120,11 +135,12 @@ void mst_kruskal(void)
    Running time: O(E)
 */
 
-void sssp_bfs(int prune)
+void sssp_bfs(void)
 {
   avl_node_t *node, *from, *next, *to;
   edge_t *e;
-  node_t *n, *check;
+  node_t *n;
+  halfconnection_t to_hc, from_hc;
   avl_tree_t *todo_tree;
 
   todo_tree = avl_alloc_tree(NULL, NULL);
@@ -150,46 +166,82 @@ void sssp_bfs(int prune)
 
   while(todo_tree->head)
     {
-      for(from = todo_tree->head; from; from = next)
+      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)
+          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 == n)
-                check = e->to;
+              if(e->from.node == n)                              /* "from_hc" is the halfconnection with .node == from */
+                to_hc = e->to, from_hc = e->from;
               else
-                check = e->from;
+                to_hc = e->from, from_hc = e->to;
 
-              if(!check->status.visited)
+              if(!to_hc.node->status.visited)
                 {
-                  check->status.visited = 1;
-                  check->nexthop = (n->nexthop == myself) ? check : n->nexthop;
-                  check->via = (e->options & OPTION_INDIRECT || n->via != n) ? n->via : check;
+                  to_hc.node->status.visited = 1;
+                  to_hc.node->nexthop = (n->nexthop == myself) ? to_hc.node : n->nexthop;
+                  to_hc.node->via = (e->options & OPTION_INDIRECT || n->via != n) ? n->via : to_hc.node;
+                 to_hc.node->options = e->options;
+                  if(to_hc.node->address != to_hc.address || to_hc.node->port != to_hc.port)
+                 {
+                    node = avl_unlink(node_udp_tree, to_hc.node);
+                    to_hc.node->address = to_hc.address;
+                   to_hc.node->port = to_hc.port;
+                   if(to_hc.node->hostname)
+                     free(to_hc.node->hostname);
+                   to_hc.node->hostname = hostlookup(htonl(to_hc.address));
+                    avl_insert_node(node_udp_tree, node);
+                 }
+                 to_hc.node->port = to_hc.port;
                   node = avl_alloc_node();
-                  node->data = check;
+                  node->data = to_hc.node;
                   avl_insert_before(todo_tree, from, node);
                 }
             }
 
-           avl_delete_node(todo_tree, from);
+          avl_delete_node(todo_tree, from);
         }
     }
 
   avl_free_tree(todo_tree);
   
-  /* Nodes we haven't visited are unreachable, prune them. */
+  /* Check reachability status. */
 
-  if(prune)
-    for(node = node_tree->head; node; node = next)
-      {
-        next = node->next;
-        n = (node_t *)node->data;
+  for(node = node_tree->head; node; node = next)
+    {
+      next = node->next;
+      n = (node_t *)node->data;
 
-        if(n->status.visited == 0)
-          node_del(n);
+      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;
+       }
+      }
+      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;
+       }
       }
+    }
+}
+
+void graph(void)
+{
+  mst_kruskal();
+  sssp_bfs();
 }
index bd6cc3f85813648be8bc3903ea40de02bf837210..3c8c0d5b49bddd11ebe53dea99c257306308808c 100644 (file)
@@ -1,7 +1,7 @@
 /*
     graph.h -- header for graph.c
-    Copyright (C) 2001 Guus Sliepen <guus@sliepen.warande.net>,
-                  2001 Ivo Timmermans <itimmermans@bigfoot.com>
+    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
@@ -17,8 +17,9 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: graph.h,v 1.1.2.2 2001/10/31 12:50:24 guus Exp $
+    $Id: graph.h,v 1.1.2.3 2002/02/10 21:57:54 guus Exp $
 */
 
+extern void graph(void);
 extern void mst_kruskal(void);
-extern void sssp_bfs(int);
+extern void sssp_bfs(void);
index 02d7a7a5c843350296cb0d4f5ac650d5013cea2d..a54647ec98c97393002ffdfd43aca8c2ba557e82 100644 (file)
@@ -1,7 +1,7 @@
 /*
     device.c -- Interaction with Linux ethertap and tun/tap device
-    Copyright (C) 2001 Ivo Timmermans <itimmermans@bigfoot.com>,
-                  2001 Guus Sliepen <guus@sliepen.warande.net>
+    Copyright (C) 2001-2002 Ivo Timmermans <itimmermans@bigfoot.com>,
+                  2001-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
@@ -17,7 +17,7 @@
     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.1.2.4 2001/10/31 12:50:24 guus Exp $
+    $Id: device.c,v 1.1.2.5 2002/02/10 21:57:54 guus Exp $
 */
 
 #include "config.h"
@@ -63,7 +63,7 @@ char *device_info;
 int device_total_in = 0;
 int device_total_out = 0;
 
-subnet_t mymac;
+extern subnet_t mymac;
 
 /*
   open the local ethertap device
@@ -158,9 +158,7 @@ cp
     }
   else /* ethertap */
     {
-      struct iovec vector[2] = {{&packet->len, 2}, {packet->data, MTU}};
-
-      if((lenin = readv(device_fd, vector, 2)) <= 0)
+      if((lenin = read(device_fd, packet->data - 2, MTU + 2)) <= 0)
         {
           syslog(LOG_ERR, _("Error while reading from %s %s: %m"), device_info, device);
           return -1;
@@ -197,9 +195,8 @@ cp
     }
   else/* ethertap */
     {
-      struct iovec vector[2] = {{&packet->len, 2}, {packet->data, MTU}};
-
-      if(writev(device_fd, vector, 2) < 0)
+      *(short int *)(packet->data - 2) = packet->len;
+      if(write(device_fd, packet->data - 2, packet->len + 2) < 0)
         {
           syslog(LOG_ERR, _("Can't write to %s %s: %m"), device_info, device);
           return -1;
index 786d56af7aa64dff191503aa9ea5f5ccb130361d..73ffa69b42baae542b751e1f8478fbcad2224c14 100644 (file)
@@ -1,7 +1,7 @@
 /*
     meta.c -- handle the meta communication
-    Copyright (C) 2000,2001 Guus Sliepen <guus@sliepen.warande.net>,
-                  2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>
+    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
@@ -17,7 +17,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: meta.c,v 1.1.2.21 2001/10/27 12:13:17 guus Exp $
+    $Id: meta.c,v 1.1.2.22 2002/02/10 21:57:54 guus Exp $
 */
 
 #include "config.h"
index e0823a82e05ea8dc2267b9665f6f0b3557efc4b9..d54573effa2896a590738858739b8d6a8415755a 100644 (file)
@@ -1,7 +1,7 @@
 /*
     meta.h -- header for meta.c
-    Copyright (C) 2000,2001 Guus Sliepen <guus@sliepen.warande.net>,
-                  2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>
+    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
@@ -17,7 +17,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: meta.h,v 1.1.2.5 2001/01/07 17:08:58 guus Exp $
+    $Id: meta.h,v 1.1.2.6 2002/02/10 21:57:54 guus Exp $
 */
 
 #ifndef __TINC_META_H__
index c7b612c743e76d24ffd5d4adcb492cf881c63db3..544bf63568eb6614e9b2f71ebdfc7cda5b6b1d2d 100644 (file)
--- a/src/net.c
+++ b/src/net.c
@@ -1,7 +1,7 @@
 /*
     net.c -- most of the network code
-    Copyright (C) 1998-2001 Ivo Timmermans <itimmermans@bigfoot.com>,
-                  2000,2001 Guus Sliepen <guus@sliepen.warande.net>
+    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
@@ -17,7 +17,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: net.c,v 1.35.4.151 2001/11/16 22:41:38 zarq Exp $
+    $Id: net.c,v 1.35.4.152 2002/02/10 21:57:54 guus Exp $
 */
 
 #include "config.h"
@@ -49,6 +49,7 @@
 #include <openssl/rand.h>
 #include <openssl/evp.h>
 #include <openssl/pem.h>
+#include <openssl/hmac.h>
 
 #ifndef HAVE_RAND_PSEUDO_BYTES
 #define RAND_pseudo_bytes RAND_bytes
 #include "connection.h"
 #include "meta.h"
 #include "net.h"
+#include "netutl.h"
 #include "process.h"
 #include "protocol.h"
 #include "subnet.h"
+#include "graph.h"
 #include "process.h"
 #include "route.h"
 #include "device.h"
+#include "event.h"
 
 #include "system.h"
 
@@ -82,52 +86,59 @@ int keylifetime = 0;
 int keyexpires = 0;
 
 int do_prune = 0;
+int do_purge = 0;
+int sighup = 0;
+int sigalrm = 0;
+
+#define MAX_SEQNO 1073741824
 
 /* VPN packet I/O */
 
-char *hostlookup(struct sockaddr *addr, int numericonly)
+void receive_udppacket(node_t *n, vpn_packet_t *inpkt)
 {
-  char *hostname;
-  int flags = 0;
-  int r;
-
+  vpn_packet_t outpkt;
+  int outlen, outpad;
+  EVP_CIPHER_CTX ctx;
+  char hmac[EVP_MAX_MD_SIZE];
 cp
-  if(numericonly
-     || (get_config_bool(lookup_config(config_tree, "ResolveDNS"), &r)
-        || !r ))
-      flags |= NI_NUMERICHOST;
 
-  hostname = xmalloc(NI_MAXHOST);
-
-  if((r = getnameinfo(addr, sizeof(*addr), hostname, NI_MAXHOST, NULL, 0, flags)) != 0)
+  if(myself->digest && myself->maclength)
     {
-      free(hostname);
-      if(flags & NI_NUMERICHOST)
+      inpkt->len -= myself->maclength;
+      HMAC(myself->digest, myself->key, myself->keylength, (char *)&inpkt->seqno, inpkt->len, hmac, NULL);
+      if(memcmp(hmac, (char *)&inpkt->seqno + inpkt->len, myself->maclength))
        {
-         syslog(LOG_ERR, _("Address conversion failed: %s"),
-                gai_strerror(r));
-         return NULL;
+         syslog(LOG_DEBUG, _("Got unauthenticated packet from %s (%s)"), n->name, n->hostname);
+         return;
        }
-      else
-       return hostlookup(addr, 1);
     }
-cp
-  return hostname;
-}
 
-void receive_udppacket(node_t *n, vpn_packet_t *inpkt)
-{
-  vpn_packet_t outpkt;
-  int outlen, outpad;
-  EVP_CIPHER_CTX ctx;
-cp
   /* Decrypt the packet */
 
-  EVP_DecryptInit(&ctx, myself->cipher, myself->key, myself->key + myself->cipher->key_len);
-  EVP_DecryptUpdate(&ctx, outpkt.salt, &outlen, inpkt->salt, inpkt->len);
-  EVP_DecryptFinal(&ctx, outpkt.salt + outlen, &outpad);
-  outlen += outpad;
-  outpkt.len = outlen - sizeof(outpkt.salt);
+  if(myself->cipher)
+  {
+    EVP_DecryptInit(&ctx, myself->cipher, myself->key, myself->key + myself->cipher->key_len);
+    EVP_DecryptUpdate(&ctx, (char *)&outpkt.seqno, &outlen, (char *)&inpkt->seqno, inpkt->len);
+    EVP_DecryptFinal(&ctx, (char *)&outpkt.seqno + outlen, &outpad);
+    outlen += outpad;
+    outpkt.len = outlen - sizeof(outpkt.seqno);
+  }
+  else
+  {
+    memcpy((char *)&outpkt.seqno, (char *)&inpkt->seqno, inpkt->len);
+    outpkt.len = inpkt->len - sizeof(outpkt.seqno);
+  }
+
+  if (ntohl(outpkt.seqno) <= n->received_seqno)
+  {
+    syslog(LOG_DEBUG, _("Got late or replayed packet from %s (%s), seqno %d"), n->name, n->hostname, ntohl(*(unsigned int *)&outpkt.seqno));
+    return;
+  }
+  
+  n->received_seqno = ntohl(outpkt.seqno);
+
+  if(n->received_seqno > MAX_SEQNO)
+    keyexpires = 0;
 
   receive_packet(n, &outpkt);
 cp
@@ -159,6 +170,8 @@ void send_udppacket(node_t *n, vpn_packet_t *inpkt)
   vpn_packet_t outpkt;
   int outlen, outpad;
   EVP_CIPHER_CTX ctx;
+  struct sockaddr_in to;
+  socklen_t tolen = sizeof(to);
   vpn_packet_t *copy;
 cp
   if(!n->status.validkey)
@@ -182,14 +195,32 @@ cp
 
   /* Encrypt the packet. */
 
-  RAND_pseudo_bytes(inpkt->salt, sizeof(inpkt->salt));
+  inpkt->seqno = htonl(++(n->sent_seqno));
 
-  EVP_EncryptInit(&ctx, n->cipher, n->key, n->key + n->cipher->key_len);
-  EVP_EncryptUpdate(&ctx, outpkt.salt, &outlen, inpkt->salt, inpkt->len + sizeof(inpkt->salt));
-  EVP_EncryptFinal(&ctx, outpkt.salt + outlen, &outpad);
-  outlen += outpad;
-  
-  if((sendto(udp_socket, (char *) outpkt.salt, outlen, 0, n->address->ai_addr, n->address->ai_addrlen)) < 0)
+  if(n->cipher)
+  {
+    EVP_EncryptInit(&ctx, n->cipher, n->key, n->key + n->cipher->key_len);
+    EVP_EncryptUpdate(&ctx, (char *)&outpkt.seqno, &outlen, (char *)&inpkt->seqno, inpkt->len + sizeof(inpkt->seqno));
+    EVP_EncryptFinal(&ctx, (char *)&outpkt.seqno + outlen, &outpad);
+    outlen += outpad;
+  }
+  else
+  {
+    memcpy((char *)&outpkt.seqno, (char *)&inpkt->seqno, inpkt->len + sizeof(inpkt->seqno));
+    outlen = inpkt->len + sizeof(inpkt->seqno);
+  }
+
+  if(n->digest && n->maclength)
+    {
+      HMAC(n->digest, n->key, n->keylength, (char *)&outpkt.seqno, outlen, (char *)&outpkt.seqno + outlen, &outpad);
+      outlen += n->maclength;
+    }
+
+  to.sin_family = AF_INET;
+  to.sin_addr.s_addr = htonl(n->address);
+  to.sin_port = htons(n->port);
+
+  if((sendto(udp_socket, (char *)&outpkt.seqno, outlen, 0, (const struct sockaddr *)&to, tolen)) < 0)
     {
       syslog(LOG_ERR, _("Error sending packet to %s (%s): %m"),
              n->name, n->hostname);
@@ -203,6 +234,7 @@ cp
 */
 void send_packet(node_t *n, vpn_packet_t *packet)
 {
+  node_t *via;
 cp
   if(debug_lvl >= DEBUG_TRAFFIC)
     syslog(LOG_ERR, _("Sending packet of %d bytes to %s (%s)"),
@@ -217,21 +249,31 @@ cp
 
       return;
     }
+  if(!n->status.reachable)
+    {
+      if(debug_lvl >= DEBUG_TRAFFIC)
+       syslog(LOG_INFO, _("Node %s (%s) is not reachable"),
+              n->name, n->hostname);
+      return;
+    }
+
+  via = (n->via == myself)?n->nexthop:n->via;
 
-  if(n->via != n && debug_lvl >= DEBUG_TRAFFIC)
+  if(via != n && debug_lvl >= DEBUG_TRAFFIC)
     syslog(LOG_ERR, _("Sending packet to %s via %s (%s)"),
-           n->name, n->via->name, n->via->hostname);
+           n->name, via->name, n->via->hostname);
 
-  if((myself->options | n->via->options) & OPTION_TCPONLY)
+  if((myself->options | via->options) & OPTION_TCPONLY)
     {
-      if(send_tcppacket(n->via->connection, packet))
-        terminate_connection(n->via->connection, 1);
+      if(send_tcppacket(via->connection, packet))
+        terminate_connection(via->connection, 1);
     }
   else
-    send_udppacket(n->via, packet);
+    send_udppacket(via, packet);
 }
 
-/* Broadcast a packet to all active direct connections */
+/* Broadcast a packet using the minimum spanning tree */
 
 void broadcast_packet(node_t *from, vpn_packet_t *packet)
 {
@@ -245,7 +287,7 @@ cp
   for(node = connection_tree->head; node; node = node->next)
     {
       c = (connection_t *)node->data;
-      if(c->status.active && c != from->nexthop->connection)
+      if(c->status.active && c->status.mst && c != from->nexthop->connection)
         send_packet(c->node, packet);
     }
 cp
@@ -269,200 +311,142 @@ cp
 
 /* Setup sockets */
 
-int setup_listen_socket(node_t *n)
+int setup_listen_socket(port_t port)
 {
   int nfd, flags;
+  struct sockaddr_in a;
   int option;
-  char *address;
-  int r;
-  struct addrinfo hints, *ai, *aitop;
-  int ipv6preferred;
+  ipv4_t *address;
 #ifdef HAVE_LINUX
   char *interface;
 #endif
-
 cp
-
-  if(!get_config_string(lookup_config(config_tree, "BindToAddress"), &address))
+  if((nfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
     {
-      address = NULL;
+      syslog(LOG_ERR, _("Creating metasocket failed: %m"));
+      return -1;
     }
 
-  hints.ai_socktype = SOCK_STREAM;
-  hints.ai_protocol = IPPROTO_TCP;
-  hints.ai_family = AF_INET;
-  if(get_config_bool(lookup_config(config_tree, "IPv6Preferred"), &ipv6preferred))
+  flags = fcntl(nfd, F_GETFL);
+  if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0)
     {
-      if(ipv6preferred)
-       hints.ai_family = PF_UNSPEC;
-    }
-  if((r = getaddrinfo(address, n->port, &hints, &aitop)) != 0)
-    {
-      syslog(LOG_ERR, _("Looking up `%s' failed: %s\n"),
-            address, gai_strerror(r));
+      close(nfd);
+      syslog(LOG_ERR, _("System call `%s' failed: %m"),
+            "fcntl");
       return -1;
     }
 
-  /* Try to create a listening socket for all alternatives we got from
-     getaddrinfo. */
-  for(ai = aitop; ai != NULL; ai = ai->ai_next)
-    {
-      if((nfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0)
-       {
-         syslog(LOG_ERR, _("Creating metasocket failed: %m"));
-         continue;
-       }
-      
-      flags = fcntl(nfd, F_GETFL);
-      if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0)
-       {
-         close(nfd);
-         syslog(LOG_ERR, _("System call `%s' failed: %m"),
-                "fcntl");
-         continue;
-       }
-      
-      /* Optimize TCP settings */
-      
-      option = 1;
-      setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
-      setsockopt(nfd, SOL_SOCKET, SO_KEEPALIVE, &option, sizeof(option));
+  /* Optimize TCP settings */
+
+  option = 1;
+  setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
+  setsockopt(nfd, SOL_SOCKET, SO_KEEPALIVE, &option, sizeof(option));
 #ifdef HAVE_LINUX
-      setsockopt(nfd, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
-      
-      option = IPTOS_LOWDELAY;
-      setsockopt(nfd, SOL_IP, IP_TOS, &option, sizeof(option));
-      
-      if(get_config_string(lookup_config(config_tree, "BindToInterface"), &interface))
-       if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface)))
-         {
-           close(nfd);
-           syslog(LOG_ERR, _("Can't bind to interface %s: %m"), interface);
-           continue;
-         }
+  setsockopt(nfd, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
+
+  option = IPTOS_LOWDELAY;
+  setsockopt(nfd, SOL_IP, IP_TOS, &option, sizeof(option));
+
+  if(get_config_string(lookup_config(config_tree, "BindToInterface"), &interface))
+    if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface)))
+      {
+        close(nfd);
+        syslog(LOG_ERR, _("Can't bind to interface %s: %m"), interface);
+        return -1;
+      }
 #endif
 
-      if(bind(nfd, ai->ai_addr, ai->ai_addrlen))
-       {
-         close(nfd);
-         syslog(LOG_ERR, _("Can't bind to %s port %s/tcp: %m"),
-                ai->ai_canonname, n->port);
-         continue;
-       }
-      
-      if(listen(nfd, 3))
-       {
-         close(nfd);
-         syslog(LOG_ERR, _("System call `%s' failed: %m"),
-                "listen");
-         continue;
-       }
+  memset(&a, 0, sizeof(a));
+  a.sin_family = AF_INET;
+  a.sin_addr.s_addr = htonl(INADDR_ANY);
+  a.sin_port = htons(port);
 
-      break; /* We have successfully bound to a socket */
+  if(get_config_address(lookup_config(config_tree, "BindToAddress"), &address))
+    {
+      a.sin_addr.s_addr = htonl(*address);
+      free(address);
     }
 
-  if(ai == NULL) /* None of the alternatives succeeded */
+  if(bind(nfd, (struct sockaddr *)&a, sizeof(struct sockaddr)))
     {
-      syslog(LOG_ERR, _("Failed to open a listening socket."));
+      close(nfd);
+      syslog(LOG_ERR, _("Can't bind to port %hd/tcp: %m"), port);
+      return -1;
+    }
+
+  if(listen(nfd, 3))
+    {
+      close(nfd);
+      syslog(LOG_ERR, _("System call `%s' failed: %m"),
+            "listen");
       return -1;
     }
 cp
   return nfd;
 }
 
-int setup_vpn_in_socket(node_t *n)
+int setup_vpn_in_socket(port_t port)
 {
-  const int one = 1;
   int nfd, flags;
-  int option;
-  char *address;
-  int r;
-  struct addrinfo hints, *ai, *aitop;
-  int ipv6preferred;
-#ifdef HAVE_LINUX
-  char *interface;
-#endif
-
+  struct sockaddr_in a;
+  const int one = 1;
 cp
-
-  if(!get_config_string(lookup_config(config_tree, "BindToAddress"), &address))
-    {
-      address = NULL;
-    }
-
-  hints.ai_socktype = SOCK_DGRAM;
-  hints.ai_protocol = IPPROTO_UDP;
-  hints.ai_family = AF_INET;
-  if(get_config_bool(lookup_config(config_tree, "IPv6Preferred"), &ipv6preferred))
-    {
-      if(ipv6preferred)
-       hints.ai_family = PF_UNSPEC;
-    }
-  if((r = getaddrinfo(address, n->port, &hints, &aitop)) != 0)
+  if((nfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
     {
-      syslog(LOG_ERR, _("Looking up `%s' failed: %s\n"),
-            address, gai_strerror(r));
+      close(nfd);
+      syslog(LOG_ERR, _("Creating socket failed: %m"));
       return -1;
     }
 
   setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
 
-  /* Try to create a listening socket for all alternatives we got from
-     getaddrinfo. */
-  for(ai = aitop; ai != NULL; ai = ai->ai_next)
+  flags = fcntl(nfd, F_GETFL);
+  if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0)
     {
-      if((nfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0)
-       {
-         syslog(LOG_ERR, _("Creating metasocket failed: %m"));
-         continue;
-       }
-      
-      flags = fcntl(nfd, F_GETFL);
-      if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0)
-       {
-         close(nfd);
-         syslog(LOG_ERR, _("System call `%s' failed: %m"),
-                "fcntl");
-         continue;
-       }
-      
-      /* Optimize UDP settings */
-      
-      option = 1;
-      setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
-#ifdef HAVE_LINUX
-      if(get_config_string(lookup_config(config_tree, "BindToInterface"), &interface))
-       if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface)))
-         {
-           close(nfd);
-           syslog(LOG_ERR, _("Can't bind to interface %s: %m"), interface);
-           continue;
-         }
-#endif
-
-      if(bind(nfd, ai->ai_addr, ai->ai_addrlen))
-       {
-         close(nfd);
-         syslog(LOG_ERR, _("Can't bind to %s port %s/tcp: %m"),
-                ai->ai_canonname, n->port);
-         continue;
-       }
-      
-      break; /* We have successfully bound to a socket */
+      close(nfd);
+      syslog(LOG_ERR, _("System call `%s' failed: %m"),
+            "fcntl");
+      return -1;
     }
 
-  if(ai == NULL) /* None of the alternatives succeeded */
+  memset(&a, 0, sizeof(a));
+  a.sin_family = AF_INET;
+  a.sin_port = htons(port);
+  a.sin_addr.s_addr = htonl(INADDR_ANY);
+
+  if(bind(nfd, (struct sockaddr *)&a, sizeof(struct sockaddr)))
     {
-      syslog(LOG_ERR, _("Failed to open a listening socket."));
+      close(nfd);
+      syslog(LOG_ERR, _("Can't bind to port %hd/udp: %m"), port);
       return -1;
     }
 cp
   return nfd;
 }
 
+void retry_outgoing(outgoing_t *outgoing)
+{
+  event_t *event;
+cp
+  outgoing->timeout += 5;
+  if(outgoing->timeout > maxtimeout)
+    outgoing->timeout = maxtimeout;
+
+  event = new_event();
+  event->handler = (event_handler_t)setup_outgoing_connection;
+  event->time = time(NULL) + outgoing->timeout;
+  event->data = outgoing;
+  event_add(event);
+
+  if(debug_lvl >= DEBUG_CONNECTIONS)
+    syslog(LOG_NOTICE, _("Trying to re-establish outgoing connection in %d seconds"), outgoing->timeout);
+cp
+}
+
 int setup_outgoing_socket(connection_t *c)
 {
   int flags;
+  struct sockaddr_in a;
 cp
   if(debug_lvl >= DEBUG_CONNECTIONS)
     syslog(LOG_INFO, _("Trying to connect to %s (%s)"), c->name, c->hostname);
@@ -471,7 +455,7 @@ cp
 
   if(c->socket == -1)
     {
-      syslog(LOG_ERR, _("Creating socket for %s port %s failed: %m"),
+      syslog(LOG_ERR, _("Creating socket for %s port %d failed: %m"),
              c->hostname, c->port);
       return -1;
     }
@@ -506,10 +490,14 @@ cp
 
   /* Connect */
 
-  if(connect(c->socket, c->address->ai_addr, c->address->ai_addrlen) == -1)
+  a.sin_family = AF_INET;
+  a.sin_port = htons(c->port);
+  a.sin_addr.s_addr = htonl(c->address);
+
+  if(connect(c->socket, (struct sockaddr *)&a, sizeof(a)) == -1)
     {
       close(c->socket);
-      syslog(LOG_ERR, _("%s port %s: %m"), c->hostname, c->port);
+      syslog(LOG_ERR, _("%s port %hd: %m"), c->hostname, c->port);
       return -1;
     }
 
@@ -518,38 +506,37 @@ cp
   if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0)
     {
       close(c->socket);
-      syslog(LOG_ERR, _("fcntl for %s port %s: %m"),
+      syslog(LOG_ERR, _("fcntl for %s port %d: %m"),
              c->hostname, c->port);
       return -1;
     }
 
   if(debug_lvl >= DEBUG_CONNECTIONS)
-    syslog(LOG_INFO, _("Connected to %s port %s"),
+    syslog(LOG_INFO, _("Connected to %s port %hd"),
          c->hostname, c->port);
 cp
   return 0;
 }
 
-int setup_outgoing_connection(char *name)
+void setup_outgoing_connection(outgoing_t *outgoing)
 {
   connection_t *c;
   node_t *n;
-  struct addrinfo *ai, *aitop, hints;
-  int r, ipv6preferred;
-
+  struct hostent *h;
 cp
-  n = lookup_node(name);
+  n = lookup_node(outgoing->name);
   
   if(n)
     if(n->connection)
       {
         if(debug_lvl >= DEBUG_CONNECTIONS)       
-          syslog(LOG_INFO, _("Already connected to %s"), name);
-        return 0;
+          syslog(LOG_INFO, _("Already connected to %s"), outgoing->name);
+        n->connection->outgoing = outgoing;
+        return;
       }
 
   c = new_connection();
-  c->name = xstrdup(name);
+  c->name = xstrdup(outgoing->name);
 
   init_configuration(&c->config_tree);
   read_connection_config(c);
@@ -558,52 +545,40 @@ cp
     {
       syslog(LOG_ERR, _("No address specified for %s"), c->name);
       free_connection(c);
-      return -1;
-    }
-
-  if(!get_config_string(lookup_config(c->config_tree, "Port"), &c->port))
-    {
-      syslog(LOG_ERR, _("No port specified for %s"), c->name);
-      free_connection(c);
-      return -1;
+      free(outgoing->name);
+      free(outgoing);
+      return;
     }
 
-  hints.ai_socktype = SOCK_STREAM;
-  hints.ai_family = AF_INET;
-  if(get_config_bool(lookup_config(c->config_tree, "IPv6Preferred"), &ipv6preferred))
-    {
-      if(ipv6preferred)
-       hints.ai_family = PF_UNSPEC;
-    }
+  if(!get_config_port(lookup_config(c->config_tree, "Port"), &c->port))
+    c->port = 655;
 
-  if((r = getaddrinfo(c->hostname, c->port, &hints, &aitop)) != 0)
+  if(!(h = gethostbyname(c->hostname)))
     {
-      syslog(LOG_ERR, _("Looking up %s failed: %s\n"),
-            c->hostname, gai_strerror(r));
-      return -1;
+      syslog(LOG_ERR, _("Error looking up `%s': %m"), c->hostname);
+      free_connection(c);
+      retry_outgoing(outgoing);
+      return;
     }
 
-  for(ai = aitop; ai != NULL; ai = ai->ai_next)
-    {
-      if(setup_outgoing_socket(c) < 0)
-       continue;
-    }
+  c->address = ntohl(*((ipv4_t*)(h->h_addr_list[0])));
+  c->hostname = hostlookup(htonl(c->address));
 
-  if(ai == NULL)
+  if(setup_outgoing_socket(c) < 0)
     {
-      /* No connection alternative succeeded */
-      free_connection(c);
-      return -1;
+      syslog(LOG_ERR, _("Could not set up a meta connection to %s (%s)"),
+             c->name, c->hostname);
+      retry_outgoing(outgoing);
+      return;
     }
 
-  c->status.outgoing = 1;
+  c->outgoing = outgoing;
   c->last_ping_time = time(NULL);
 
   connection_add(c);
 
   send_id(c);
 cp
-  return 0;
 }
 
 int read_rsa_public_key(connection_t *c)
@@ -714,7 +689,7 @@ int setup_myself(void)
 {
   config_t *cfg;
   subnet_t *subnet;
-  char *name, *mode;
+  char *name, *mode, *cipher, *digest;
   int choice;
 cp
   myself = new_node();
@@ -764,8 +739,8 @@ cp
       return -1;
     }
 */
-  if(!get_config_string(lookup_config(myself->connection->config_tree, "Port"), &myself->port))
-    myself->port = "655";
+  if(!get_config_port(lookup_config(myself->connection->config_tree, "Port"), &myself->port))
+    myself->port = 655;
 
   myself->connection->port = myself->port;
 
@@ -825,13 +800,13 @@ cp
 cp
   /* Open sockets */
   
-  if((tcp_socket = setup_listen_socket(myself)) < 0)
+  if((tcp_socket = setup_listen_socket(myself->port)) < 0)
     {
       syslog(LOG_ERR, _("Unable to set up a listening TCP socket!"));
       return -1;
     }
 
-  if((udp_socket = setup_vpn_in_socket(myself)) < 0)
+  if((udp_socket = setup_vpn_in_socket(myself->port)) < 0)
     {
       syslog(LOG_ERR, _("Unable to set up a listening UDP socket!"));
       return -1;
@@ -839,9 +814,28 @@ cp
 cp
   /* Generate packet encryption key */
 
-  myself->cipher = EVP_bf_cbc();
+  if(get_config_string(lookup_config(myself->connection->config_tree, "Cipher"), &cipher))
+    {
+      if(!strcasecmp(cipher, "none"))
+        {
+         myself->cipher = NULL;
+       }
+      else
+        {
+         if(!(myself->cipher = EVP_get_cipherbyname(cipher)))
+            {
+             syslog(LOG_ERR, _("Unrecognized cipher type!"));
+             return -1;
+           }
+        }
+    }
+  else
+    myself->cipher = EVP_bf_cbc();
 
-  myself->keylength = myself->cipher->key_len + myself->cipher->iv_len;
+  if(myself->cipher)
+    myself->keylength = myself->cipher->key_len + myself->cipher->iv_len;
+  else
+    myself->keylength = 1;
 
   myself->key = (char *)xmalloc(myself->keylength);
   RAND_pseudo_bytes(myself->key, myself->keylength);
@@ -850,6 +844,45 @@ cp
     keylifetime = 3600;
 
   keyexpires = time(NULL) + keylifetime;
+
+  /* Check if we want to use message authentication codes... */
+
+  if(get_config_string(lookup_config(myself->connection->config_tree, "Digest"), &digest))
+    {
+      if(!strcasecmp(digest, "none"))
+        {
+         myself->digest = NULL;
+       }
+      else
+        {
+          if(!(myself->digest = EVP_get_digestbyname(digest)))
+           {
+             syslog(LOG_ERR, _("Unrecognized digest type!"));
+             return -1;
+            }
+       }
+    }
+  else
+    myself->digest = EVP_sha1();
+
+  if(get_config_int(lookup_config(myself->connection->config_tree, "MACLength"), &myself->maclength))
+    {
+      if(myself->digest)
+        {
+         if(myself->maclength > myself->digest->md_size)
+            {
+             syslog(LOG_ERR, _("MAC length exceeds size of digest!"));
+             return -1;
+           }
+         else if (myself->maclength < 0)
+            {
+             syslog(LOG_ERR, _("Bogus MAC length!"));
+             return -1;
+           }
+        }
+    }
+  else
+    myself->maclength = 4;
 cp
   /* Done */
 
@@ -858,7 +891,9 @@ cp
   myself->status.active = 1;
   node_add(myself);
 
-  syslog(LOG_NOTICE, _("Ready: listening on port %s"), myself->port);
+  graph();
+
+  syslog(LOG_NOTICE, _("Ready: listening on port %hd"), myself->port);
 cp
   return 0;
 }
@@ -873,16 +908,17 @@ cp
   init_subnets();
   init_nodes();
   init_edges();
+  init_events();
 
-  if(get_config_int(lookup_config(config_tree, "PingTimeout"), &timeout))
+  if(get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout))
     {
-      if(timeout < 1)
+      if(pingtimeout < 1)
         {
-          timeout = 86400;
+          pingtimeout = 86400;
         }
     }
   else
-    timeout = 60;
+    pingtimeout = 60;
 
   if(setup_device() < 0)
     return -1;
@@ -893,8 +929,7 @@ cp
   if(setup_myself() < 0)
     return -1;
 
-  signal(SIGALRM, try_outgoing_connections);
-  alarm(5);
+  try_outgoing_connections();
 cp
   return 0;
 }
@@ -911,15 +946,18 @@ cp
     {
       next = node->next;
       c = (connection_t *)node->data;
-      c->status.outgoing = 0;
+      if(c->outgoing)
+        free(c->outgoing->name), free(c->outgoing);
       terminate_connection(c, 0);
     }
 
-  terminate_connection(myself->connection, 0);
+  if(myself && myself->connection)
+    terminate_connection(myself->connection, 0);
 
   close(udp_socket);
   close(tcp_socket);
 
+  exit_events();
   exit_edges();
   exit_subnets();
   exit_nodes();
@@ -952,21 +990,14 @@ cp
       return NULL;
     }
 
-  c->address = sockaddr_to_addrinfo(ci);
-
-  c->hostname = xmalloc(INET6_ADDRSTRLEN);
-  if((inet_ntop(ci.sin_family, &(ci.sin_addr), c->hostname, INET6_ADDRSTRLEN)) == NULL)
-    {
-      syslog(LOG_ERR, _("Couldn't convert address to string: %m"));
-      free(c->hostname);
-      return NULL;
-    }
-  asprintf(&(c->port), "%d", htons(ci.sin_port));
+  c->address = ntohl(ci.sin_addr.s_addr);
+  c->hostname = hostlookup(ci.sin_addr.s_addr);
+  c->port = htons(ci.sin_port);
   c->socket = sfd;
   c->last_ping_time = time(NULL);
 
   if(debug_lvl >= DEBUG_CONNECTIONS)
-    syslog(LOG_NOTICE, _("Connection from %s port %s"),
+    syslog(LOG_NOTICE, _("Connection from %s port %d"),
          c->hostname, c->port);
 
   c->allow_request = ID;
@@ -1021,19 +1052,20 @@ cp
       return;
     }
 
-  if((pkt.len = recvfrom(udp_socket, (char *) pkt.salt, MTU, 0, (struct sockaddr *)&from, &fromlen)) <= 0)
+  if((pkt.len = recvfrom(udp_socket, (char *)&pkt.seqno, MAXSIZE, 0, (struct sockaddr *)&from, &fromlen)) <= 0)
     {
       syslog(LOG_ERR, _("Receiving packet failed: %m"));
       return;
     }
 
-  n = lookup_node_udp(sockaddr_to_addrinfo(&from));
+  n = lookup_node_udp(ntohl(from.sin_addr.s_addr), ntohs(from.sin_port));
 
   if(!n)
     {
-      syslog(LOG_WARNING, _("Received UDP packet on port %s from unknown source %x:%hd"), myself->port, ntohl(from.sin_addr.s_addr), ntohs(from.sin_port));
+      syslog(LOG_WARNING, _("Received UDP packet on port %hd from unknown source %x:%hd"), myself->port, ntohl(from.sin_addr.s_addr), ntohs(from.sin_port));
       return;
     }
+
 /*
   if(n->connection)
     n->connection->last_ping_time = time(NULL);
@@ -1042,6 +1074,65 @@ cp
 cp
 }
 
+/* Purge edges and subnets of unreachable nodes. Use carefully. */
+
+void purge(void)
+{
+  avl_node_t *nnode, *nnext, *enode, *enext, *snode, *snext, *cnode;
+  node_t *n;
+  edge_t *e;
+  subnet_t *s;
+  connection_t *c;
+cp
+  if(debug_lvl >= DEBUG_PROTOCOL)
+    syslog(LOG_DEBUG, _("Purging unreachable nodes"));
+
+  for(nnode = node_tree->head; nnode; nnode = nnext)
+  {
+    nnext = nnode->next;
+    n = (node_t *)nnode->data;
+
+    if(!n->status.reachable)
+    {
+      if(debug_lvl >= DEBUG_SCARY_THINGS)
+        syslog(LOG_DEBUG, _("Purging node %s (%s)"), n->name, n->hostname);
+
+      for(snode = n->subnet_tree->head; snode; snode = snext)
+      {
+        snext = snode->next;
+       s = (subnet_t *)snode->data;
+       
+       for(cnode = connection_tree->head; cnode; cnode = cnode->next)
+       {
+         c = (connection_t *)cnode->data;
+         if(c->status.active)
+           send_del_subnet(c, s);
+       }
+       
+       subnet_del(n, s);
+      }
+       
+      for(enode = n->edge_tree->head; enode; enode = enext)
+      {
+        enext = enode->next;
+       e = (edge_t *)enode->data;
+       
+       for(cnode = connection_tree->head; cnode; cnode = cnode->next)
+       {
+         c = (connection_t *)cnode->data;
+         if(c->status.active)
+           send_del_edge(c, e);
+       }
+       
+       edge_del(e);
+      }
+
+      node_del(n);
+    }
+  }    
+cp
+}
+
 /*
   Terminate a connection:
   - Close the socket
@@ -1081,14 +1172,16 @@ cp
       edge_del(c->edge);
     }
 
+  /* Run MST and SSSP algorithms */
+  
+  graph();
+
   /* Check if this was our outgoing connection */
 
-  if(c->status.outgoing)
+  if(c->outgoing)
     {
-      c->status.outgoing = 0;
-      signal(SIGALRM, try_outgoing_connections);
-      alarm(seconds_till_retry);
-      syslog(LOG_NOTICE, _("Trying to re-establish outgoing connection in %d seconds"), seconds_till_retry);
+      retry_outgoing(c->outgoing);
+      c->outgoing = NULL;
     }
 
   /* Deactivate */
@@ -1120,7 +1213,7 @@ cp
     {
       next = node->next;
       c = (connection_t *)node->data;
-      if(c->last_ping_time + timeout < now)
+      if(c->last_ping_time + pingtimeout < now)
         {
           if(c->status.active)
             {
@@ -1180,71 +1273,27 @@ cp
   return 0;
 }
 
-void randomized_alarm(int seconds)
-{
-  unsigned char r;
-  RAND_pseudo_bytes(&r, 1);
-  alarm((seconds * (int)r) / 128 + 1);
-}
-
-/* This function is severely fucked up.
-   We want to redesign it so the following rules apply:
-   
-   - Try all ConnectTo's in a row:
-     - if a connect() fails, try next one immediately,
-     - if it works, wait 5 seconds or so.
-   - If none of them were succesful, increase delay and retry.
-   - If all were succesful, don't try anymore.
-*/
-
-RETSIGTYPE
-try_outgoing_connections(int a)
+void try_outgoing_connections(void)
 {
   static config_t *cfg = NULL;
-  static int retry = 0;
   char *name;
+  outgoing_t *outgoing;
 cp
-  if(!cfg)
-    cfg = lookup_config(config_tree, "ConnectTo");
-
-  if(!cfg)
-    return;
-
-  while(cfg)
+  for(cfg = lookup_config(config_tree, "ConnectTo"); cfg; cfg = lookup_config_next(config_tree, cfg))
     {
       get_config_string(cfg, &name);
 
       if(check_id(name))
         {
           syslog(LOG_ERR, _("Invalid name for outgoing connection in %s line %d"), cfg->file, cfg->line);
+          free(name);
           continue;
         }
 
-      if(setup_outgoing_connection(name))   /* function returns 0 when there are no problems */
-        retry = 1;
-
-      cfg = lookup_config_next(config_tree, cfg); /* Next time skip to next ConnectTo line */
-    }
-
-  get_config_int(lookup_config(config_tree, "MaxTimeout"), &maxtimeout);
-
-  if(retry)
-    {
-      seconds_till_retry += 5;
-      if(seconds_till_retry > maxtimeout)    /* Don't wait more than MAXTIMEOUT seconds. */
-        seconds_till_retry = maxtimeout;
-
-      syslog(LOG_ERR, _("Failed to setup any outgoing connection, will retry in %d seconds"),
-        seconds_till_retry);
-  
-      /* Randomize timeout to avoid global synchronisation effects */
-      randomized_alarm(seconds_till_retry);
-    }
-  else
-    {
-      seconds_till_retry = 5;
+      outgoing = xmalloc_and_zero(sizeof(*outgoing));
+      outgoing->name = name;
+      setup_outgoing_connection(outgoing);
     }
-cp
 }
 
 /*
@@ -1292,6 +1341,9 @@ cp
       if(c->status.remove)
        connection_del(c);
     }
+  
+  if(!connection_tree->head)
+    purge();
 cp
 }
 
@@ -1305,13 +1357,16 @@ void main_loop(void)
   int r;
   time_t last_ping_check;
   int t;
+  event_t *event;
   vpn_packet_t packet;
 cp
   last_ping_check = time(NULL);
 
+  srand(time(NULL));
+
   for(;;)
     {
-      tv.tv_sec = timeout;
+      tv.tv_sec = 1 + (rand() & 7); /* Approx. 5 seconds, randomized to prevent global synchronisation effects */
       tv.tv_usec = 0;
 
       if(do_prune)
@@ -1324,7 +1379,7 @@ cp
 
       if((r = select(FD_SETSIZE, &fset, NULL, NULL, &tv)) < 0)
         {
-         if(errno != EINTR) /* because of alarm */
+         if(errno != EINTR) /* because of a signal */
             {
               syslog(LOG_ERR, _("Error while waiting for input: %m"));
               return;
@@ -1352,11 +1407,17 @@ cp
           continue;
         }
 
+      if(do_purge)
+        {
+         purge();
+         do_purge = 0;
+       }
+
       t = time(NULL);
 
       /* Let's check if everybody is still alive */
 
-      if(last_ping_check + timeout < t)
+      if(last_ping_check + pingtimeout < t)
        {
          check_dead_connections();
           last_ping_check = time(NULL);
@@ -1374,6 +1435,25 @@ cp
             }
        }
 
+      if(sigalrm)
+        {
+          syslog(LOG_INFO, _("Flushing event queue"));
+
+         while(event_tree->head)
+           {
+             event = (event_t *)event_tree->head->data;
+             event->handler(event->data);
+             event_del(event);
+           }
+         sigalrm = 0;
+        }
+
+      while((event = get_expired_event()))
+        {
+         event->handler(event->data);
+          free(event);
+       }
+
       if(r > 0)
         {
           check_network_activity(&fset);
@@ -1381,9 +1461,7 @@ cp
           /* local tap data */
           if(FD_ISSET(device_fd, &fset))
             {
-              if(read_packet(&packet))
-                return;
-              else
+              if(!read_packet(&packet))
                 route_outgoing(&packet);
             }
         }
index 6b2c6b4df98156327740f91c57bc8093cca54bed..93ac391e4e7883116bade65b247145c2d673ebae 100644 (file)
--- a/src/net.h
+++ b/src/net.h
@@ -1,7 +1,7 @@
 /*
     net.h -- header for net.c
-    Copyright (C) 1998-2001 Ivo Timmermans <zarq@iname.com>
-                  2000,2001 Guus Sliepen <guus@sliepen.warande.net>
+    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
@@ -17,7 +17,7 @@
     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.9.4.37 2001/11/16 12:08:38 zarq Exp $
+    $Id: net.h,v 1.9.4.38 2002/02/10 21:57:54 guus Exp $
 */
 
 #ifndef __TINC_NET_H__
 
 #include "config.h"
 
-#define MAXSIZE 1700   /* should be a bit more than the MTU for the tapdevice */
-#define MTU 1600
-#define SALTLEN        2       /* to spice things up for the NSA... */
+#define MTU 1514     /* 1500 bytes payload + 14 bytes ethernet header */
+#define MAXSIZE 1600 /* MTU + header (seqno) and trailer (CBC padding and HMAC) */
 
-#define MAC_ADDR_S "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MAC_ADDR_V(x) ((unsigned char*)&(x))[0],((unsigned char*)&(x))[1], \
-                      ((unsigned char*)&(x))[2],((unsigned char*)&(x))[3], \
-                      ((unsigned char*)&(x))[4],((unsigned char*)&(x))[5]
-
-#define IP_ADDR_S "%d.%d.%d.%d"
-
-#ifdef WORDS_BIGENDIAN
-# define IP_ADDR_V(x) ((unsigned char*)&(x))[0],((unsigned char*)&(x))[1], \
-                      ((unsigned char*)&(x))[2],((unsigned char*)&(x))[3]
-#else
-# define IP_ADDR_V(x) ((unsigned char*)&(x))[3],((unsigned char*)&(x))[2], \
-                      ((unsigned char*)&(x))[1],((unsigned char*)&(x))[0]
-#endif
-
-#define MAXBUFSIZE 4096 /* Probably way too much, but it must fit every possible request. */
-
-/* tap types */
-#define TAP_TYPE_ETHERTAP 0
-#define TAP_TYPE_TUNTAP   1
+#define MAXBUFSIZE 2048 /* Probably way too much, but it must fit every possible request. */
 
 typedef struct mac_t
 {
   unsigned char x[6];
 } mac_t;
 
+typedef unsigned long 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 struct vpn_packet_t {
   length_t len;                        /* the actual number of bytes in the `data' field */
-  unsigned char salt[SALTLEN]; /* two bytes of randomness */
+  unsigned int seqno;          /* 32 bits sequence number (network byte order of course) */
   unsigned char data[MAXSIZE];
 } vpn_packet_t;
 
@@ -76,11 +70,16 @@ typedef struct packet_queue_t {
   queue_element_t *tail;
 } packet_queue_t;
 
+typedef struct outgoing_t {
+  char *name;
+  int timeout;
+} outgoing_t;
+
 extern int maxtimeout;
 extern int seconds_till_retry;
 
-extern char *request_name[256];
-extern char *status_text[10];
+extern char *request_name[];
+extern char *status_text[];
 
 #include "connection.h"                /* Yes, very strange placement indeed, but otherwise the typedefs get all tangled up */
 
@@ -89,11 +88,12 @@ 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 *);
-extern RETSIGTYPE try_outgoing_connections(int);
 
 #endif /* __TINC_NET_H__ */
index ba795ba92ad577643c8eb2a3363cf17f52a66366..5307ea666dfb996f2c292df06db7b5c48abc87b9 100644 (file)
@@ -1,7 +1,7 @@
 /*
     node.c -- node tree management
-    Copyright (C) 2001 Guus Sliepen <guus@sliepen.warande.net>,
-                  2001 Ivo Timmermans <itimmermans@bigfoot.com>
+    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
@@ -17,7 +17,7 @@
     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.2.7 2001/11/16 17:39:38 zarq Exp $
+    $Id: node.c,v 1.1.2.8 2002/02/10 21:57:54 guus Exp $
 */
 
 #include "config.h"
@@ -47,10 +47,13 @@ int node_udp_compare(node_t *a, node_t *b)
 {
   if(a->address < b->address)
     return -1;
-  else if (a->address > b->address)
+  if (a->address > b->address)
     return 1;
-  else
-    return a->port - b->port;
+  if (a->port < b->port)
+    return -1;
+  if (a->port > b->port)
+    return 1;
+  return (a->name && b->name)?strcmp(a->name, b->name):0;
 }
 
 void init_nodes(void)
@@ -140,11 +143,13 @@ cp
   return avl_search(node_tree, &n);
 }
 
-node_t *lookup_node_udp(struct addrinfo *address)
+node_t *lookup_node_udp(ipv4_t address, port_t port)
 {
   node_t n;
 cp
+  n.name = NULL;
   n.address = address;
+  n.port = port;
   return avl_search(node_udp_tree, &n);
 }
 
@@ -158,9 +163,9 @@ cp
   for(node = node_tree->head; node; node = node->next)
     {
       n = (node_t *)node->data;
-      syslog(LOG_DEBUG, _(" %s at %s port %s options %ld status %04x nexthop %s via %s"),
-             n->name, n->hostname, n->port, n->options,
-             n->status, n->nexthop->name, n->via->name);
+      syslog(LOG_DEBUG, _(" %s at %s port %hd cipher %d digest %d maclength %d options %ld status %04x nexthop %s via %s"),
+             n->name, n->hostname, n->port, n->cipher?n->cipher->nid:0, n->digest?n->digest->type:0, n->maclength, n->options,
+             n->status, n->nexthop?n->nexthop->name:"-", n->via?n->via->name:"-");
     }
     
   syslog(LOG_DEBUG, _("End of nodes."));
index 83305ce3c3740b760761090bd76c6440dcfcbd02..6d281e62f2aee6b56373d28aa80cbc83ea4113b5 100644 (file)
@@ -1,7 +1,7 @@
 /*
     node.h -- header for node.c
-    Copyright (C) 2001 Guus Sliepen <guus@sliepen.warande.net>,
-                  2001 Ivo Timmermans <itimmermans@bigfoot.com>
+    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
@@ -17,7 +17,7 @@
     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.1.2.9 2001/11/16 15:56:44 zarq Exp $
+    $Id: node.h,v 1.1.2.10 2002/02/10 21:57:54 guus Exp $
 */
 
 #ifndef __TINC_NODE_H__
@@ -33,23 +33,27 @@ typedef struct node_status_t {
   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 unused:28;
+  int reachable:1;                 /* 1 if this node is reachable in the graph */
+  int unused:27;
 } node_status_t;
 
 typedef struct node_t {
   char *name;                      /* name of this node */
   long int options;                /* options turned on for this node */
 
-  struct addrinfo *address;        /* his real (internet) ip to send UDP packets to */
-  char *port;                      /* string representation of the port number */
+  ipv4_t address;                  /* his real (internet) ip to send UDP packets to */
+  port_t port;                     /* port number of UDP connection */
   char *hostname;                  /* the hostname of its real ip */
 
   struct node_status_t status;
 
-  EVP_CIPHER *cipher;              /* Cipher type for UDP packets */ 
+  const EVP_CIPHER *cipher;        /* Cipher type for UDP packets */ 
   char *key;                       /* Cipher key and iv */
   int keylength;                   /* Cipher key and iv length*/
 
+  const EVP_MD *digest;            /* Digest type for MAC */
+  int maclength;                   /* Length of MAC */
+
   list_t *queue;                   /* Queue for packets awaiting to be encrypted */
 
   struct node_t *nexthop;          /* nearest node from us to him */
@@ -60,10 +64,14 @@ typedef struct node_t {
   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 */
 } 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);
@@ -72,8 +80,7 @@ extern void free_node(node_t *n);
 extern void node_add(node_t *n);
 extern void node_del(node_t *n);
 extern node_t *lookup_node(char *);
-extern node_t *lookup_node_udp(struct addrinfo *);
+extern node_t *lookup_node_udp(ipv4_t, port_t);
 extern void dump_nodes(void);
 
-
 #endif /* __TINC_NODE_H__ */
index 45840010c1c16b0c4f4bbb706f9cd7851cf7c184..1fccd14f18fc8db8dc7876008e68909348b35dd5 100644 (file)
@@ -1,7 +1,7 @@
 /*
     device.c -- Interaction with OpenBSD tun device
-    Copyright (C) 2001 Ivo Timmermans <itimmermans@bigfoot.com>,
-                  2001 Guus Sliepen <guus@sliepen.warande.net>
+    Copyright (C) 2001-2002 Ivo Timmermans <itimmermans@bigfoot.com>,
+                  2001-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
     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.1.2.2 2001/10/12 15:52:03 guus Exp $
+    $Id: device.c,v 1.1.2.3 2002/02/10 21:57:54 guus Exp $
 */
 
+#include "config.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <net/if.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <string.h>
+
+#include <utils.h>
+#include "conf.h"
+#include "net.h"
+#include "subnet.h"
+
+#include "system.h"
+
 #define DEFAULT_DEVICE "/dev/tun0"
 
 #define DEVICE_TYPE_ETHERTAP 0
 
 int device_fd = -1;
 int device_type;
-char *device_fname;
+char *device;
+char *interface;
 char *device_info;
 
 int device_total_in = 0;
 int device_total_out = 0;
 
+extern subnet_t mymac;
+
 /*
   open the local ethertap device
 */
 int setup_device(void)
 {
-  if(!get_config_string(lookup_config(config_tree, "Device"), &device_fname)))
-    device_fname = DEFAULT_DEVICE;
+  if(!get_config_string(lookup_config(config_tree, "Device"), &device))
+    device = DEFAULT_DEVICE;
 
+  if(!get_config_string(lookup_config(config_tree, "Interface"), &interface))
+    interface = netname;
 cp
-  if((device_fd = open(device_fname, O_RDWR | O_NONBLOCK)) < 0)
+  if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0)
     {
-      syslog(LOG_ERR, _("Could not open %s: %m"), device_fname);
+      syslog(LOG_ERR, _("Could not open %s: %m"), device);
       return -1;
     }
 cp
@@ -60,28 +86,35 @@ cp
 
   device_info = _("OpenBSD tun device");
 
-  syslog(LOG_INFO, _("%s is a %s"), device_fname, device_info);
+  syslog(LOG_INFO, _("%s is a %s"), device, device_info);
 cp
   return 0;
 }
 
+void close_device(void)
+{
+cp
+  close(device_fd);
+cp
+}
+
 int read_packet(vpn_packet_t *packet)
 {
   int lenin;
   u_int32_t type;
-cp
   struct iovec vector[2] = {{&type, sizeof(type)}, {packet->data + 14, MTU - 14}};
+cp
 
   if((lenin = readv(device_fd, vector, 2)) <= 0)
     {
-      syslog(LOG_ERR, _("Error while reading from %s %s: %m"), device_info, device_fname);
+      syslog(LOG_ERR, _("Error while reading from %s %s: %m"), device_info, device);
       return -1;
     }
 
-  memcpy(vp->data, mymac.net.mac.address.x, 6);
-  memcpy(vp->data + 6, mymac.net.mac.address.x, 6);
-  vp->data[12] = 0x08;
-  vp->data[13] = 0x00;
+  memcpy(packet->data, mymac.net.mac.address.x, 6);
+  memcpy(packet->data + 6, mymac.net.mac.address.x, 6);
+  packet->data[12] = 0x08;
+  packet->data[13] = 0x00;
 
   packet->len = lenin + 10;
 
@@ -89,7 +122,7 @@ cp
 
   if(debug_lvl >= DEBUG_TRAFFIC)
     {
-      syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), device_info, packet.len);
+      syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, device_info);
     }
 
   return 0;
@@ -99,20 +132,32 @@ cp
 int write_packet(vpn_packet_t *packet)
 {
   u_int32_t type = htonl(AF_INET);
+  struct iovec vector[2];
 cp
   if(debug_lvl >= DEBUG_TRAFFIC)
     syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
            packet->len, device_info);
 
-
-  struct iovec vector[2] = {{&type, sizeof(type)}, {packet->data + 14, packet->len - 14}};
+  vector[0].iov_base = &type;
+  vector[0].iov_len = sizeof(type);
+  vector[1].iov_base = packet->data + 14;
+  vector[1].iov_len = packet->len - 14;
 
   if(writev(device_fd, vector, 2) < 0)
     {
-      syslog(LOG_ERR, _("Can't write to %s %s: %m"), device_info, packet.len);
+      syslog(LOG_ERR, _("Can't write to %s %s: %m"), device_info, device);
       return -1;
     }
 
   device_total_out += packet->len;
 cp
 }
+
+void dump_device_stats(void)
+{
+cp
+  syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
+  syslog(LOG_DEBUG, _(" total bytes in:  %10d"), device_total_in);
+  syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
+cp
+}
index 8ca8733f72c74f8c619b1c9906c5801d83e029fd..cd1b96e69a75e83c6fde274acb04038d26e2d3c5 100644 (file)
@@ -1,7 +1,7 @@
 /*
     process.c -- process management functions
-    Copyright (C) 1999-2001 Ivo Timmermans <itimmermans@bigfoot.com>,
-                  2000,2001 Guus Sliepen <guus@sliepen.warande.net>
+    Copyright (C) 1999-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
@@ -17,7 +17,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: process.c,v 1.1.2.32 2001/11/03 22:53:02 guus Exp $
+    $Id: process.c,v 1.1.2.33 2002/02/10 21:57:54 guus Exp $
 */
 
 #include "config.h"
@@ -59,6 +59,10 @@ sigset_t emptysigset;
 
 static int saved_debug_lvl = 0;
 
+extern int sighup;
+extern int sigalrm;
+extern int do_purge;
+
 void memory_full(int size)
 {
   syslog(LOG_ERR, _("Memory exhausted (couldn't allocate %d bytes), exiting."), size);
@@ -342,6 +346,7 @@ sigsegv_handler(int a, siginfo_t *info, void *b)
       act.sa_mask = emptysigset;
       act.sa_flags = SA_SIGINFO;
       act.sa_sigaction = sigsegv_square;
+      sigaction(SIGSEGV, &act, NULL);
 
       close_network_connections();
       sleep(5);
@@ -351,7 +356,7 @@ sigsegv_handler(int a, siginfo_t *info, void *b)
   else
     {
       syslog(LOG_NOTICE, _("Not restarting."));
-      exit(0);
+      exit(1);
     }
 }
 
@@ -382,6 +387,14 @@ sigint_handler(int a, siginfo_t *info, void *b)
     }
 }
 
+RETSIGTYPE
+sigalrm_handler(int a, siginfo_t *info, void *b)
+{
+  if(debug_lvl > DEBUG_NOTHING)
+    syslog(LOG_NOTICE, _("Got ALRM signal"));
+  sigalrm = 1;
+}
+
 RETSIGTYPE
 sigusr1_handler(int a, siginfo_t *info, void *b)
 {
@@ -397,6 +410,13 @@ sigusr2_handler(int a, siginfo_t *info, void *b)
   dump_subnets();
 }
 
+RETSIGTYPE
+sigwinch_handler(int a, siginfo_t *info, void *b)
+{
+  extern int do_purge;
+  do_purge = 1;
+}
+
 RETSIGTYPE
 unexpected_signal_handler(int a, siginfo_t *info, void *b)
 {
@@ -427,7 +447,8 @@ struct {
   { SIGUSR1, sigusr1_handler },
   { SIGUSR2, sigusr2_handler },
   { SIGCHLD, ignore_signal_handler },
-  { SIGALRM, ignore_signal_handler },
+  { SIGALRM, sigalrm_handler },
+  { SIGWINCH, sigwinch_handler },
   { 0, NULL }
 };
 
@@ -447,7 +468,7 @@ setup_signals(void)
   for(i = 0; i < NSIG; i++) 
     {
       if(!do_detach)
-        act.sa_sigaction = SIG_DFL;
+        act.sa_sigaction = (void(*)(int, siginfo_t *, void *))SIG_DFL;
       else
         act.sa_sigaction = unexpected_signal_handler;
       sigaction(i, &act, NULL);
@@ -455,7 +476,7 @@ setup_signals(void)
 
   /* If we didn't detach, allow coredumps */
   if(!do_detach)
-    sighandlers[3].handler = SIG_DFL;
+    sighandlers[3].handler = (void(*)(int, siginfo_t *, void *))SIG_DFL;
 
   /* Then, for each known signal that we want to catch, assign a
      handler to the signal, with error checking this time. */
index fe7466ed62d9a193abb701b5f643d9f99fcf8007..1289d2da6e3865b16a6252c817e5890951e00e0d 100644 (file)
@@ -1,7 +1,7 @@
 /*
     process.h -- header file for process.c
-    Copyright (C) 1999-2001 Ivo Timmermans <itimmermans@bigfoot.com>,
-                  2000,2001 Guus Sliepen <guus@sliepen.warande.net>
+    Copyright (C) 1999-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
@@ -17,7 +17,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: process.h,v 1.1.2.9 2001/09/01 12:36:53 guus Exp $
+    $Id: process.h,v 1.1.2.10 2002/02/10 21:57:54 guus Exp $
 */
 
 #ifndef __TINC_PROCESS_H__
index 36e10c40ea9ac8bfe5130c9105e74dacb0872662..af8029d0a79c511fc1f0dfe4c9a64aff56cfd1fa 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    protocol.c -- handle the meta-protocol
+    protocol.c -- handle the meta-protocol, basic functions
     Copyright (C) 1999-2001 Ivo Timmermans <itimmermans@bigfoot.com>,
                   2000,2001 Guus Sliepen <guus@sliepen.warande.net>
 
@@ -17,7 +17,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: protocol.c,v 1.28.4.121 2001/11/16 17:39:59 zarq Exp $
+    $Id: protocol.c,v 1.28.4.122 2002/02/10 21:57:54 guus Exp $
 */
 
 #include "config.h"
 #include <stdlib.h>
 #include <string.h>
 #include <syslog.h>
-#include <sys/socket.h>
-#include <unistd.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <errno.h>
 
 #include <utils.h>
-#include <xalloc.h>
-#include <avl_tree.h>
-#include <list.h>
-
-#include <netinet/in.h>
-
-#include <openssl/sha.h>
-#include <openssl/rand.h>
-#include <openssl/evp.h>
-
-#ifndef HAVE_RAND_PSEUDO_BYTES
-#define RAND_pseudo_bytes RAND_bytes
-#endif
 
 #include "conf.h"
-#include "net.h"
 #include "protocol.h"
 #include "meta.h"
 #include "connection.h"
-#include "node.h"
-#include "edge.h"
-#include "graph.h"
 
 #include "system.h"
 
-int mykeyused = 0;
-
 int check_id(char *id)
 {
   int i;
@@ -164,1391 +143,28 @@ cp
   return 0;
 }
 
-/* The authentication protocol is described in detail in doc/SECURITY2,
-   the rest will be described in doc/PROTOCOL. */
-
-int send_id(connection_t *c)
-{
-cp
-  return send_request(c, "%d %s %d", ID, myself->connection->name, myself->connection->protocol_version);
-}
-
-int id_h(connection_t *c)
-{
-  char name[MAX_STRING_SIZE];
-int bla;
-cp
-  if(sscanf(c->buffer, "%*d "MAX_STRING" %d", name, &c->protocol_version) != 2)
-    {
-       syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ID", c->name, c->hostname);
-       return -1;
-    }
-
-  /* Check if identity is a valid name */
-
-  if(check_id(name))
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ID", c->name, c->hostname, "invalid name");
-      return -1;
-    }
-
-  /* If we set c->name in advance, make sure we are connected to the right host */
-  
-  if(c->name)
-    {
-      if(strcmp(c->name, name))
-        {
-          syslog(LOG_ERR, _("Peer %s is %s instead of %s"), c->hostname, name, c->name);
-          return -1;
-        }
-    }
-  else
-    c->name = xstrdup(name);
-
-  /* Check if version matches */
-
-  if(c->protocol_version != myself->connection->protocol_version)
-    {
-      syslog(LOG_ERR, _("Peer %s (%s) uses incompatible version %d"),
-             c->name, c->hostname, c->protocol_version);
-      return -1;
-    }
-  
-  if(bypass_security)
-    {
-      if(!c->config_tree)
-        init_configuration(&c->config_tree);
-      c->allow_request = ACK;
-      return send_ack(c);
-    }
-
-  if(!c->config_tree)
-    {
-      init_configuration(&c->config_tree);
-
-      if((bla = read_connection_config(c)))
-        {
-          syslog(LOG_ERR, _("Peer %s had unknown identity (%s)"), c->hostname, c->name);
-          return -1;
-        }
-    }
-
-  if(read_rsa_public_key(c))
-    {
-      return -1;
-    }
-
-  c->allow_request = METAKEY;
-cp
-  return send_metakey(c);
-}
-
-int send_metakey(connection_t *c)
-{
-  char buffer[MAX_STRING_SIZE];
-  int len, x;
-cp
-  len = RSA_size(c->rsa_key);
-
-  /* Allocate buffers for the meta key */
-
-  if(!c->outkey)
-    c->outkey = xmalloc(len);
-    
-  if(!c->outctx)
-    c->outctx = xmalloc(sizeof(*c->outctx));
-cp
-  /* Copy random data to the buffer */
-
-  RAND_bytes(c->outkey, len);
-
-  /* The message we send must be smaller than the modulus of the RSA key.
-     By definition, for a key of k bits, the following formula holds:
-     
-       2^(k-1) <= modulus < 2^(k)
-     
-     Where ^ means "to the power of", not "xor".
-     This means that to be sure, we must choose our message < 2^(k-1).
-     This can be done by setting the most significant bit to zero.
-  */
-  
-  c->outkey[0] &= 0x7F;
-  
-  if(debug_lvl >= DEBUG_SCARY_THINGS)
-    {
-      bin2hex(c->outkey, buffer, len);
-      buffer[len*2] = '\0';
-      syslog(LOG_DEBUG, _("Generated random meta key (unencrypted): %s"), buffer);
-    }
-
-  /* Encrypt the random data
-  
-     We do not use one of the PKCS padding schemes here.
-     This is allowed, because we encrypt a totally random string
-     with a length equal to that of the modulus of the RSA key.
-  */
-
-  if(RSA_public_encrypt(len, c->outkey, buffer, c->rsa_key, RSA_NO_PADDING) != len)
-    {
-      syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), c->name, c->hostname);
-      return -1;
-    }
-cp
-  /* Convert the encrypted random data to a hexadecimal formatted string */
-
-  bin2hex(buffer, buffer, len);
-  buffer[len*2] = '\0';
-
-  /* Send the meta key */
-
-  x = send_request(c, "%d %s", METAKEY, buffer);
-
-  /* Further outgoing requests are encrypted with the key we just generated */
-
-  EVP_EncryptInit(c->outctx, EVP_bf_cfb(),
-                  c->outkey + len - EVP_bf_cfb()->key_len,
-                  c->outkey + len - EVP_bf_cfb()->key_len - EVP_bf_cfb()->iv_len);
-
-  c->status.encryptout = 1;
-cp
-  return x;
-}
-
-int metakey_h(connection_t *c)
-{
-  char buffer[MAX_STRING_SIZE];
-  int len;
-cp
-  if(sscanf(c->buffer, "%*d "MAX_STRING, buffer) != 1)
-    {
-       syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "METAKEY", c->name, c->hostname);
-       return -1;
-    }
-cp
-  len = RSA_size(myself->connection->rsa_key);
-
-  /* Check if the length of the meta key is all right */
-
-  if(strlen(buffer) != len*2)
-    {
-      syslog(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, c->hostname, "wrong keylength");
-      return -1;
-    }
-
-  /* Allocate buffers for the meta key */
-cp
-  if(!c->inkey)
-    c->inkey = xmalloc(len);
-
-  if(!c->inctx)
-    c->inctx = xmalloc(sizeof(*c->inctx));
-
-  /* Convert the challenge from hexadecimal back to binary */
-cp
-  hex2bin(buffer,buffer,len);
-
-  /* Decrypt the meta key */
-cp  
-  if(RSA_private_decrypt(len, buffer, c->inkey, myself->connection->rsa_key, RSA_NO_PADDING) != len)   /* See challenge() */
-    {
-      syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), c->name, c->hostname);
-      return -1;
-    }
-
-  if(debug_lvl >= DEBUG_SCARY_THINGS)
-    {
-      bin2hex(c->inkey, buffer, len);
-      buffer[len*2] = '\0';
-      syslog(LOG_DEBUG, _("Received random meta key (unencrypted): %s"), buffer);
-    }
-
-  /* All incoming requests will now be encrypted. */
-cp
-  EVP_DecryptInit(c->inctx, EVP_bf_cfb(),
-                  c->inkey + len - EVP_bf_cfb()->key_len,
-                  c->inkey + len - EVP_bf_cfb()->key_len - EVP_bf_cfb()->iv_len);
-  
-  c->status.decryptin = 1;
-
-  c->allow_request = CHALLENGE;
-cp
-  return send_challenge(c);
-}
-
-int send_challenge(connection_t *c)
-{
-  char buffer[MAX_STRING_SIZE];
-  int len, x;
-cp
-  /* CHECKME: what is most reasonable value for len? */
-
-  len = RSA_size(c->rsa_key);
-
-  /* Allocate buffers for the challenge */
-
-  if(!c->hischallenge)
-    c->hischallenge = xmalloc(len);
-cp
-  /* Copy random data to the buffer */
-
-  RAND_bytes(c->hischallenge, len);
-
-cp
-  /* Convert to hex */
-
-  bin2hex(c->hischallenge, buffer, len);
-  buffer[len*2] = '\0';
-
-cp
-  /* Send the challenge */
-
-  x = send_request(c, "%d %s", CHALLENGE, buffer);
-cp
-  return x;
-}
-
-int challenge_h(connection_t *c)
-{
-  char buffer[MAX_STRING_SIZE];
-  int len;
-cp
-  if(sscanf(c->buffer, "%*d "MAX_STRING, buffer) != 1)
-    {
-       syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "CHALLENGE", c->name, c->hostname);
-       return -1;
-    }
-
-  len = RSA_size(myself->connection->rsa_key);
-
-  /* Check if the length of the challenge is all right */
-
-  if(strlen(buffer) != len*2)
-    {
-      syslog(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, c->hostname, "wrong challenge length");
-      return -1;
-    }
-
-  /* Allocate buffers for the challenge */
-
-  if(!c->mychallenge)
-    c->mychallenge = xmalloc(len);
-
-  /* Convert the challenge from hexadecimal back to binary */
-
-  hex2bin(buffer,c->mychallenge,len);
-
-  c->allow_request = CHAL_REPLY;
-
-  /* Rest is done by send_chal_reply() */
-cp
-  return send_chal_reply(c);
-}
-
-int send_chal_reply(connection_t *c)
-{
-  char hash[SHA_DIGEST_LENGTH*2+1];
-cp
-  /* Calculate the hash from the challenge we received */
-
-  SHA1(c->mychallenge, RSA_size(myself->connection->rsa_key), hash);
-
-  /* Convert the hash to a hexadecimal formatted string */
-
-  bin2hex(hash,hash,SHA_DIGEST_LENGTH);
-  hash[SHA_DIGEST_LENGTH*2] = '\0';
-
-  /* Send the reply */
-
-cp
-  return send_request(c, "%d %s", CHAL_REPLY, hash);
-}
-
-int chal_reply_h(connection_t *c)
-{
-  char hishash[MAX_STRING_SIZE];
-  char myhash[SHA_DIGEST_LENGTH];
-cp
-  if(sscanf(c->buffer, "%*d "MAX_STRING, hishash) != 1)
-    {
-       syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "CHAL_REPLY", c->name, c->hostname);
-       return -1;
-    }
-
-  /* Check if the length of the hash is all right */
-
-  if(strlen(hishash) != SHA_DIGEST_LENGTH*2)
-    {
-      syslog(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, c->hostname, _("wrong challenge reply length"));
-      return -1;
-    }
-
-  /* Convert the hash to binary format */
-
-  hex2bin(hishash, hishash, SHA_DIGEST_LENGTH);
-
-  /* Calculate the hash from the challenge we sent */
-
-  SHA1(c->hischallenge, RSA_size(c->rsa_key), myhash);
-
-  /* Verify the incoming hash with the calculated hash */
-
-  if(memcmp(hishash, myhash, SHA_DIGEST_LENGTH))
-    {
-      syslog(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, c->hostname, _("wrong challenge reply"));
-      if(debug_lvl >= DEBUG_SCARY_THINGS)
-        {
-          bin2hex(myhash, hishash, SHA_DIGEST_LENGTH);
-          hishash[SHA_DIGEST_LENGTH*2] = '\0';
-          syslog(LOG_DEBUG, _("Expected challenge reply: %s"), hishash);
-        }
-      return -1;
-    }
-
-  /* Identity has now been positively verified.
-     Send an acknowledgement with the rest of the information needed.
-   */
-
-  c->allow_request = ACK;
-cp
-  return send_ack(c);
-}
-
-int send_ack(connection_t *c)
-{
-  /* ACK message contains rest of the information the other end needs
-     to create node_t and edge_t structures. */
-
-  struct timeval now;
-
-  /* Estimate weight */
-  
-  gettimeofday(&now, NULL);
-  c->estimated_weight = (now.tv_sec - c->start.tv_sec) * 1000 + (now.tv_usec - c->start.tv_usec) / 1000;
-cp
-  return send_request(c, "%d %hd %d", ACK, myself->port, c->estimated_weight);
-}
-
-int ack_h(connection_t *c)
-{
-  int weight;
-  node_t *n;
-  subnet_t *s;
-  edge_t *e;
-  connection_t *other;
-  avl_node_t *node, *node2;
-cp
-  if(sscanf(c->buffer, "%*d %hd %d", &port, &weight) != 2)
-    {
-       syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ACK", c->name, c->hostname);
-       return -1;
-    }
-
-  /* Check if we already have a node_t for him */
-
-  n = lookup_node(c->name);
-  
-  if(!n)
-    {
-      n = new_node();
-      n->name = xstrdup(c->name);
-      n->address = c->address;
-      n->hostname = xstrdup(c->hostname);
-      n->port = port;
-
-      /* FIXME: Also check if no other tinc daemon uses the same IP and port for UDP traffic */
-
-      node_add(n);
-    }
-  else
-    {
-      if(n->connection)
-        {
-          /* Oh dear, we already have a connection to this node. */
-          syslog(LOG_DEBUG, _("Established a second connection with %s (%s), closing old connection"), n->name, n->hostname);
-          terminate_connection(n->connection, 0);
-        }
-          
-      /* FIXME: check if information in existing node matches that of the other end of this connection */
-    }
-  
-  n->connection = c;
-  c->node = n;
-  
-  /* Check some options
-  
-  if((cfg = get_config_val(c->config, config_indirectdata)))
-    {
-      if(cfg->data.val == stupid_true)
-        c->options |= OPTION_INDIRECT;
-    }
-
-  if((cfg = get_config_val(c->config, config_tcponly)))
-    {
-      if(cfg->data.val == stupid_true)
-        c->options |= OPTION_TCPONLY;
-    }
-
-  if((myself->options | c->options) & OPTION_INDIRECT)
-    c->via = myself;
-  else
-    c->via = c;
-
-  */
-
-  /* Create an edge_t for this connection */
-
-  c->edge = new_edge();
-  
-  c->edge->from = myself;
-  c->edge->to = n;
-  c->edge->weight = (weight + c->estimated_weight) / 2;
-  c->edge->connection = c;
-
-  edge_add(c->edge);
-
-  /* Activate this connection */
-
-  c->allow_request = ALL;
-  c->status.active = 1;
-  c->node->cipher = EVP_bf_cbc();
-  c->node->keylength = c->node->cipher->key_len + c->node->cipher->iv_len;
-
-  if(debug_lvl >= DEBUG_CONNECTIONS)
-    syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), c->name, c->hostname);
-
-cp
-  /* Send him our subnets */
-  
-  for(node = myself->subnet_tree->head; node; node = node->next)
-    {
-      s = (subnet_t *)node->data;
-      send_add_subnet(c, s);
-    }
-
-  /* And send him all known nodes and their subnets */
-  
-  for(node = node_tree->head; node; node = node->next)
-    {
-      n = (node_t *)node->data;
-
-      if(n == c->node || n == myself)
-        continue;
-
-      send_add_node(c, n);
-
-      for(node2 = c->node->subnet_tree->head; node2; node2 = node2->next)
-        {
-          s = (subnet_t *)node2->data;
-          send_add_subnet(c, s);
-        }
-    }
-
-  /* Send all known edges */
-
-  for(node = edge_tree->head; node; node = node->next)
-    {
-      e = (edge_t *)node->data;
-
-      if(e == c->edge)
-        continue;
-
-      send_add_edge(c, e);
-    }
-
-  /* Notify others of this connection */
+/* Jumptable for the request handlers */
 
-  for(node = connection_tree->head; node; node = node->next)
-    {
-      other = (connection_t *)node->data;
+int (*request_handlers[])(connection_t*) = {
+  id_h, metakey_h, challenge_h, chal_reply_h, ack_h,
+  status_h, error_h, termreq_h,
+  ping_h, pong_h,
+//  add_node_h, del_node_h,
+  add_subnet_h, del_subnet_h,
+  add_edge_h, del_edge_h,
+  key_changed_h, req_key_h, ans_key_h,
+  tcppacket_h,
+};
 
-      if(other->status.active && other != c)
-        {
-          send_add_node(other, c->node);
-          send_add_edge(other, c->edge);
-        }
-    }
-
-  /* Run MST and SSSP algorithms */
-  
-  mst_kruskal();
-  sssp_bfs(0);
-cp
-  return 0;
-}
-
-
-
-/* Address and subnet information exchange */
-
-int send_add_subnet(connection_t *c, subnet_t *subnet)
-{
-  int x;
-  char *netstr;
-cp
-  x = send_request(c, "%d %s %s", ADD_SUBNET,
-                      subnet->owner->name, netstr = net2str(subnet));
-  free(netstr);
-cp
-  return x;
-}
-
-int add_subnet_h(connection_t *c)
-{
-  char subnetstr[MAX_STRING_SIZE];
-  char name[MAX_STRING_SIZE];
-  node_t *owner;
-  connection_t *other;
-  subnet_t *s;
-  avl_node_t *node;
-cp
-  if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 2)
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_SUBNET", c->name, c->hostname);
-      return -1;
-    }
-
-  /* Check if owner name is a valid */
-
-  if(check_id(name))
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_SUBNET", c->name, c->hostname, _("invalid name"));
-      return -1;
-    }
-
-  /* Check if subnet string is valid */
-
-  if(!(s = str2net(subnetstr)))
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_SUBNET", c->name, c->hostname, _("invalid subnet string"));
-      return -1;
-    }
-
-  /* Check if the owner of the new subnet is in the connection list */
-
-  owner = lookup_node(name);
-
-  if(!owner)
-    {
-      syslog(LOG_ERR, _("Got ADD_SUBNET from %s (%s) for %s which is not in our connection list"),
-             c->name, c->hostname, name);
-      return -1;
-    }
-
-  /* Check if we already know this subnet */
-  
-  if(lookup_subnet(owner, s))
-    {
-      free_subnet(s);
-      return 0;
-    }
-
-  /* If everything is correct, add the subnet to the list of the owner */
-
-  subnet_add(owner, s);
-
-  /* Tell the rest */
-  
-  for(node = connection_tree->head; node; node = node->next)
-    {
-      other = (connection_t *)node->data;
-      if(other->status.active && other != c)
-        send_add_subnet(other, s);
-    }
-cp
-  return 0;
-}
-
-int send_del_subnet(connection_t *c, subnet_t *s)
-{
-  int x;
-  char *netstr;
-cp
-  x = send_request(c, "%d %s %s", DEL_SUBNET, s->owner->name, netstr = net2str(s));
-  free(netstr);
-cp
-  return x;
-}
-
-int del_subnet_h(connection_t *c)
-{
-  char subnetstr[MAX_STRING_SIZE];
-  char name[MAX_STRING_SIZE];
-  node_t *owner;
-  connection_t *other;
-  subnet_t *s, *find;
-  avl_node_t *node;
-cp
-  if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 3)
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_SUBNET", c->name, c->hostname);
-      return -1;
-    }
-
-  /* Check if owner name is a valid */
-
-  if(check_id(name))
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_SUBNET", c->name, c->hostname, _("invalid name"));
-      return -1;
-    }
-
-  /* Check if the owner of the new subnet is in the connection list */
-
-  if(!(owner = lookup_node(name)))
-    {
-      syslog(LOG_ERR, _("Got %s from %s (%s) for %s which is not in our connection list"),
-             "DEL_SUBNET", c->name, c->hostname, name);
-      return -1;
-    }
-
-  /* Check if subnet string is valid */
-
-  if(!(s = str2net(subnetstr)))
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_SUBNET", c->name, c->hostname, _("invalid subnet string"));
-      return -1;
-    }
-
-  /* If everything is correct, delete the subnet from the list of the owner */
-
-  find = lookup_subnet(owner, s);
-  
-  free_subnet(s);
-
-  if(!find)
-    {
-      syslog(LOG_ERR, _("Got %s from %s (%s) for %s which does not appear in his subnet tree"),
-             "DEL_SUBNET", c->name, c->hostname, name);
-      return -1;
-    }
-  
-  subnet_del(owner, find);
-
-  /* Tell the rest */
-  
-  for(node = connection_tree->head; node; node = node->next)
-    {
-      other = (connection_t *)node->data;
-      if(other->status.active && other != c)
-        send_del_subnet(other, s);
-    }
-cp
-  return 0;
-}
-
-/* New and closed connections notification */
-
-int send_add_node(connection_t *c, node_t *n)
-{
-cp
-  return send_request(c, "%d %s %lx:%d", ADD_NODE,
-                      n->name, n->address, n->port);
-}
-
-int add_node_h(connection_t *c)
-{
-  connection_t *other;
-  node_t *n;
-  char name[MAX_STRING_SIZE];
-  ipv4_t address;
-  port_t port;
-  avl_node_t *node;
-cp
-  if(sscanf(c->buffer, "%*d "MAX_STRING" %lx:%hd", name, &address, &port) != 3)
-    {
-       syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_NODE", c->name, c->hostname);
-       return -1;
-    }
-
-  /* Check if identity is a valid name */
-
-  if(check_id(name))
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_NODE", c->name, c->hostname, _("invalid name"));
-      return -1;
-    }
-
-  /* Check if node already exists */
-  
-  n = lookup_node(name);
-  
-  if(n)
-    {
-      /* Check if it matches */
-
-      if(n->address != address || n->port != port)
-        syslog(LOG_DEBUG, _("Got %s from %s (%s) for %s which does not match existing entry"), "ADD_NODE", c->name, c->hostname, n->name);
-
-      return 0;
-    }
-  else
-    {
-      n = new_node();
-      n->name = xstrdup(name);
-      n->address = address;
-      n->port = port;
-      node_add(n);
-    }
-
-  /* Tell the rest about the new node */
-
-  for(node = connection_tree->head; node; node = node->next)
-    {
-      other = (connection_t *)node->data;
-      if(other->status.active && other !=c)
-        send_add_node(other, n);
-    }
-
-cp
-  return 0;
-}
-
-int send_del_node(connection_t *c, node_t *n)
-{
-cp
-  return send_request(c, "%d %s %lx:%d", DEL_NODE,
-                      n->name, n->address, n->port);
-}
-
-int del_node_h(connection_t *c)
-{
-  node_t *n;
-  char name[MAX_STRING_SIZE];
-  ipv4_t address;
-  port_t port;
-  connection_t *other;
-  avl_node_t *node;
-cp
-  if(sscanf(c->buffer, "%*d "MAX_STRING" %lx:%hd", name, &address, &port) != 3)
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_NODE",
-             c->name, c->hostname);
-      return -1;
-    }
-
-  /* Check if identity is a valid name */
-
-  if(check_id(name))
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_NODE", c->name, c->hostname, _("invalid name"));
-      return -1;
-    }
-
-  /* Check if somebody tries to delete ourself */
-
-  if(!strcmp(name, myself->name))
-    {
-      syslog(LOG_ERR, _("Got %s from %s (%s) for ourself!"), "DEL_NODE",
-             c->name, c->hostname);
-      return -1;
-    }
-
-  /* Check if the deleted host exists */
-
-  n = lookup_node(name);
-
-  if(!n)
-    {
-      syslog(LOG_WARNING, _("Got %s from %s (%s) for %s which does not exist"), "DEL_NODE", c->name, c->hostname, n->name);
-      return 0;
-    }
-  
-  /* Check if the rest matches */
-  
-  if(address != n->address || port != n->port)
-    {
-      syslog(LOG_WARNING, _("Got %s from %s (%s) for %s which does not match existing entry"), "DEL_NODE", c->name, c->hostname, n->name);
-    }
-
-  /* Tell the rest about the deleted node */
-
-  for(node = connection_tree->head; node; node = node->next)
-    {
-      other = (connection_t *)node->data;
-      if(other->status.active && other != c)
-        send_del_node(other, n);
-    }
-
-  /* Delete the node */
-  
-  node_del(n);
-
-  mst_kruskal();
-  sssp_bfs(0);
-cp
-  return 0;
-}
-
-/* Edges */
-
-int send_add_edge(connection_t *c, edge_t *e)
-{
-cp
-  return send_request(c, "%d %s %s %lx %d", ADD_EDGE,
-                      e->from->name, e->to->name, e->options, e->weight);
-}
-
-int add_edge_h(connection_t *c)
-{
-  connection_t *other;
-  edge_t *e;
-  node_t *from, *to;
-  char from_name[MAX_STRING_SIZE];
-  char to_name[MAX_STRING_SIZE];
-  long int options;
-  int weight;
-  avl_node_t *node;
-cp
-  if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" %lx %d", from_name, to_name, &options, &weight) != 4)
-    {
-       syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_EDGE", c->name, c->hostname);
-       return -1;
-    }
-
-  /* Check if names are valid */
-
-  if(check_id(from_name))
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_EDGE", c->name, c->hostname, _("invalid name"));
-      return -1;
-    }
-
-  if(check_id(to_name))
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_EDGE", c->name, c->hostname, _("invalid name"));
-      return -1;
-    }
-
-  /* Lookup nodes */
-
-  from = lookup_node(from_name);
-  
-  if(!from)
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_EDGE", c->name, c->hostname, _("unknown node"));
-      return -1;
-    }
-
-  to = lookup_node(to_name);
-  
-  if(!to)
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_EDGE", c->name, c->hostname, _("unknown node"));
-      return -1;
-    }
-
-  /* Check if edge already exists */
-  
-  e = lookup_edge(from, to);
-  
-  if(e)
-    {
-      if(e->weight != weight || e->options != options)
-        {
-          syslog(LOG_ERR, _("Got %s from %s (%s) which does not match existing entry"), "ADD_EDGE", c->name, c->hostname);
-          return -1;
-        }
-      
-      return 0;
-    }
-  else
-    {
-      e = new_edge();
-      e->from = from;
-      e->to = to;
-      e->options = options;
-      e->weight = weight;
-      edge_add(e);
-    }
-
-  /* Tell the rest about the new edge */
-
-  for(node = connection_tree->head; node; node = node->next)
-    {
-      other = (connection_t *)node->data;
-      if(other->status.active && other != c)
-        send_add_edge(other, e);
-    }
-
-  /* Run MST before or after we tell the rest? */
-
-  mst_kruskal();
-  sssp_bfs(0);
-cp
-  return 0;
-}
-
-int send_del_edge(connection_t *c, edge_t *e)
-{
-cp
-  return send_request(c, "%d %s %s %lx %d", DEL_EDGE,
-                      e->from->name, e->to->name, e->options, e->weight);
-}
-
-int del_edge_h(connection_t *c)
-{
-  edge_t *e;
-  char from_name[MAX_STRING_SIZE];
-  char to_name[MAX_STRING_SIZE];
-  node_t *from, *to;
-  long int options;
-  int weight;
-  connection_t *other;
-  avl_node_t *node;
-cp
-  if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" %lx %d", from_name, to_name, &options, &weight) != 4)
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_EDGE",
-             c->name, c->hostname);
-      return -1;
-    }
-
-  /* Check if names are valid */
-
-  if(check_id(from_name))
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_EDGE", c->name, c->hostname, _("invalid name"));
-      return -1;
-    }
-
-  if(check_id(to_name))
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_EDGE", c->name, c->hostname, _("invalid name"));
-      return -1;
-    }
-
-  /* Lookup nodes */
-
-  from = lookup_node(from_name);
-  
-  if(!from)
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_EDGE", c->name, c->hostname, _("unknown node"));
-      return 0;
-    }
-
-  to = lookup_node(to_name);
-  
-  if(!to)
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_EDGE", c->name, c->hostname, _("unknown node"));
-      return 0;
-    }
-
-  /* Check if edge exists */
-  
-  e = lookup_edge(from, to);
-  
-  if(e)
-    {
-      if(e->weight != weight || e->options != options)
-        {
-          syslog(LOG_ERR, _("Got %s from %s (%s) which does not match existing entry"), "ADD_EDGE", c->name, c->hostname);
-          return -1;
-        }
-    }
-  else
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_EDGE", c->name, c->hostname, _("unknown edge"));
-      return 0;
-    }
-
-  /* Tell the rest about the deleted edge */
-
-  for(node = connection_tree->head; node; node = node->next)
-    {
-      other = (connection_t *)node->data;
-      if(other->status.active && other != c)
-        send_del_edge(other, e);
-    }
-
-  /* Delete the edge */
-  
-  edge_del(e);
-
-  /* Run MST before or after we tell the rest? */
-
-  mst_kruskal();
-  sssp_bfs(1);
-cp
-  return 0;
-}
-
-
-/* Status and error notification routines */
-
-int send_status(connection_t *c, int statusno, char *statusstring)
-{
-cp
-  if(!statusstring)
-    statusstring = status_text[statusno];
-cp
-  return send_request(c, "%d %d %s", STATUS, statusno, statusstring);
-}
-
-int status_h(connection_t *c)
-{
-  int statusno;
-  char statusstring[MAX_STRING_SIZE];
-cp
-  if(sscanf(c->buffer, "%*d %d "MAX_STRING, &statusno, statusstring) != 2)
-    {
-       syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "STATUS",
-              c->name, c->hostname);
-       return -1;
-    }
-
-  if(debug_lvl >= DEBUG_STATUS)
-    {
-      syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"),
-             c->name, c->hostname, status_text[statusno], statusstring);
-    }
-
-cp
-  return 0;
-}
-
-int send_error(connection_t *c, int err, char *errstring)
-{
-cp
-  if(!errstring)
-    errstring = strerror(err);
-  return send_request(c, "%d %d %s", ERROR, err, errstring);
-}
-
-int error_h(connection_t *c)
-{
-  int err;
-  char errorstring[MAX_STRING_SIZE];
-cp
-  if(sscanf(c->buffer, "%*d %d "MAX_STRING, &err, errorstring) != 2)
-    {
-       syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ERROR",
-              c->name, c->hostname);
-       return -1;
-    }
-
-  if(debug_lvl >= DEBUG_ERROR)
-    {
-      syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"),
-             c->name, c->hostname, strerror(err), errorstring);
-    }
-
-  terminate_connection(c, c->status.active);
-cp
-  return 0;
-}
-
-int send_termreq(connection_t *c)
-{
-cp
-  return send_request(c, "%d", TERMREQ);
-}
-
-int termreq_h(connection_t *c)
-{
-cp
-  terminate_connection(c, c->status.active);
-cp
-  return 0;
-}
-
-int send_ping(connection_t *c)
-{
-  char salt[SALTLEN*2+1];
-cp
-  c->status.pinged = 1;
-  c->last_ping_time = time(NULL);
-  RAND_pseudo_bytes(salt, SALTLEN);
-  bin2hex(salt, salt, SALTLEN);
-  salt[SALTLEN*2] = '\0';
-cp
-  return send_request(c, "%d %s", PING, salt);
-}
-
-int ping_h(connection_t *c)
-{
-cp
-  return send_pong(c);
-}
-
-int send_pong(connection_t *c)
-{
-  char salt[SALTLEN*2+1];
-cp
-  RAND_pseudo_bytes(salt, SALTLEN);
-  bin2hex(salt, salt, SALTLEN);
-  salt[SALTLEN*2] = '\0';
-cp
-  return send_request(c, "%d %s", PONG, salt);
-}
-
-int pong_h(connection_t *c)
-{
-cp
-  c->status.pinged = 0;
-cp
-  return 0;
-}
-
-/* Key exchange */
-
-int send_key_changed(connection_t *c, node_t *n)
-{
-  connection_t *other;
-  avl_node_t *node;
-cp
-  /* Only send this message if some other daemon requested our key previously.
-     This reduces unnecessary key_changed broadcasts.
-  */
-
-  if(n == myself && !mykeyused)
-    return 0;
-
-  for(node = connection_tree->head; node; node = node->next)
-    {
-      other = (connection_t *)node->data;
-      if(other->status.active && other != c)
-        send_request(other, "%d %s", KEY_CHANGED, n->name);
-    }
-cp
-  return 0;
-}
-
-int key_changed_h(connection_t *c)
-{
-  char name[MAX_STRING_SIZE];
-  node_t *n;
-cp
-  if(sscanf(c->buffer, "%*d "MAX_STRING, name) != 1)
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "KEY_CHANGED",
-             c->name, c->hostname);
-      return -1;
-    }
-
-  n = lookup_node(name);
-
-  if(!n)
-    {
-      syslog(LOG_ERR, _("Got %s from %s (%s) origin %s which does not exist"), "KEY_CHANGED",
-             c->name, c->hostname, name);
-      return -1;
-    }
-
-  n->status.validkey = 0;
-  n->status.waitingforkey = 0;
-
-  send_key_changed(c, n);
-cp
-  return 0;
-}
-
-int send_req_key(connection_t *c, node_t *from, node_t *to)
-{
-cp
-  return send_request(c, "%d %s %s", REQ_KEY,
-                      from->name, to->name);
-}
-
-int req_key_h(connection_t *c)
-{
-  char from_name[MAX_STRING_SIZE];
-  char to_name[MAX_STRING_SIZE];
-  node_t *from, *to;
-  char key[MAX_STRING_SIZE];
-cp
-  if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING, from_name, to_name) != 2)
-    {
-       syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "REQ_KEY",
-              c->name, c->hostname);
-       return -1;
-    }
-
-  from = lookup_node(from_name);
-
-  if(!from)
-    {
-      syslog(LOG_ERR, _("Got %s from %s (%s) origin %s which does not exist in our connection list"), "REQ_KEY",
-             c->name, c->hostname, from_name);
-      return -1;
-    }
-
-  to = lookup_node(to_name);
-  
-  if(!to)
-    {
-      syslog(LOG_ERR, _("Got %s from %s (%s) destination %s which does not exist in our connection list"), "REQ_KEY",
-             c->name, c->hostname, to_name);
-      return -1;
-    }
-
-  /* Check if this key request is for us */
-
-  if(to == myself)     /* Yes, send our own key back */
-    {
-      bin2hex(myself->key, key, myself->keylength);
-      key[myself->keylength * 2] = '\0';
-      send_ans_key(c, myself, from, key);
-      mykeyused = 1;
-    }
-  else
-    {
-      if(to->status.validkey)  /* Proxy keys */
-        {
-          bin2hex(to->key, key, to->keylength);
-          key[to->keylength * 2] = '\0';
-          send_ans_key(c, to, from, key);
-        }
-      else
-        send_req_key(to->nexthop->connection, from, to);
-    }
-
-cp
-  return 0;
-}
-
-int send_ans_key(connection_t *c, node_t *from, node_t *to, char *key)
-{
-cp
-  return send_request(c, "%d %s %s %s", ANS_KEY,
-                      from->name, to->name, key);
-}
-
-int ans_key_h(connection_t *c)
-{
-  char from_name[MAX_STRING_SIZE];
-  char to_name[MAX_STRING_SIZE];
-  char key[MAX_STRING_SIZE];
-  int keylength;
-  node_t *from, *to;
-cp
-  if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING, from_name, to_name, key) != 3)
-    {
-       syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ANS_KEY",
-              c->name, c->hostname);
-       return -1;
-    }
-
-  from = lookup_node(from_name);
-
-  if(!from)
-    {
-      syslog(LOG_ERR, _("Got %s from %s (%s) origin %s which does not exist in our connection list"), "ANS_KEY",
-             c->name, c->hostname, from_name);
-      return -1;
-    }
-
-  to = lookup_node(to_name);
-
-  if(!to)
-    {
-      syslog(LOG_ERR, _("Got %s from %s (%s) destination %s which does not exist in our connection list"), "ANS_KEY",
-             c->name, c->hostname, to_name);
-      return -1;
-    }
-
-  /* Check correctness of packet key */
-
-  keylength = strlen(key);
-
-  if(keylength != from->keylength * 2)
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s) origin %s: %s"), "ANS_KEY",
-             c->name, c->hostname, from->name, _("invalid key length"));
-      return -1;
-    }
-
-  /* Forward it if necessary */
-
-  if(to != myself)
-    {
-      send_ans_key(to->nexthop->connection, from, to, key);
-    }
-
-  /* Update our copy of the origin's packet key */
-
-  if(from->key)
-    free(from->key);
-
-  from->key = xstrdup(key);
-  keylength /= 2;
-  hex2bin(from->key, from->key, keylength);
-  from->key[keylength] = '\0';
-
-  from->status.validkey = 1;
-  from->status.waitingforkey = 0;
-  
-  flush_queue(from);
-cp
-  return 0;
-}
-
-int send_tcppacket(connection_t *c, vpn_packet_t *packet)
-{
-  int x;
-cp  
-  /* Evil hack. */
-
-  x = send_request(c, "%d %hd", PACKET, packet->len);
-
-  if(x)
-    return x;
-cp
-  return send_meta(c, packet->data, packet->len);
-}
-
-int tcppacket_h(connection_t *c)
-{
-  short int len;
-cp  
-  if(sscanf(c->buffer, "%*d %hd", &len) != 1)
-    {
-      syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "PACKET", c->name, c->hostname);
-      return -1;
-    }
-
-  /* Set reqlen to len, this will tell receive_meta() that a tcppacket is coming. */
-
-  c->tcplen = len;
-cp
-  return 0;
-}
-
-/* Jumptable for the request handlers */
-
-int (*request_handlers[])(connection_t*) = {
-  id_h, metakey_h, challenge_h, chal_reply_h, ack_h,
-  status_h, error_h, termreq_h,
-  ping_h, pong_h,
-  add_node_h, del_node_h,
-  add_subnet_h, del_subnet_h,
-  add_edge_h, del_edge_h,
-  key_changed_h, req_key_h, ans_key_h,
-  tcppacket_h,
-};
-
-/* Request names */
+/* Request names */
 
 char (*request_name[]) = {
   "ID", "METAKEY", "CHALLENGE", "CHAL_REPLY", "ACK",
   "STATUS", "ERROR", "TERMREQ",
   "PING", "PONG",
-  "ADD_NODE", "DEL_NODE",
+//  "ADD_NODE", "DEL_NODE",
   "ADD_SUBNET", "DEL_SUBNET",
   "ADD_EDGE", "DEL_EDGE",
   "KEY_CHANGED", "REQ_KEY", "ANS_KEY",
   "PACKET",
 };
-
-/* Status strings */
-
-char (*status_text[]) = {
-  "Warning",
-};
-
-/* Error strings */
-
-char (*error_text[]) = {
-  "Error",
-};
index 5fc30f3866d6ff6e8006e105c14e9d6e8eda2268..5528b98f076b6a99e7cebd1aaca1b81c81f06290 100644 (file)
@@ -17,7 +17,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: protocol.h,v 1.5.4.24 2001/10/28 08:41:19 guus Exp $
+    $Id: protocol.h,v 1.5.4.25 2002/02/10 21:57:54 guus Exp $
 */
 
 #ifndef __TINC_PROTOCOL_H__
@@ -31,7 +31,7 @@
    incompatible version have different protocols.
  */
 
-#define PROT_CURRENT 11
+#define PROT_CURRENT 12
 
 /* Request numbers */
 
@@ -40,7 +40,7 @@ enum {
   ID = 0, METAKEY, CHALLENGE, CHAL_REPLY, ACK,
   STATUS, ERROR, TERMREQ,
   PING, PONG,
-  ADD_NODE, DEL_NODE,
+//  ADD_NODE, DEL_NODE,
   ADD_SUBNET, DEL_SUBNET,
   ADD_EDGE, DEL_EDGE,
   KEY_CHANGED, REQ_KEY, ANS_KEY,
@@ -53,33 +53,58 @@ enum {
 #define MAX_STRING_SIZE 1024
 #define MAX_STRING "%1024s"
 
-extern int (*request_handlers[])(connection_t*);
-
-extern int send_id(connection_t*);
-extern int send_metakey(connection_t*);
-extern int send_challenge(connection_t*);
-extern int send_chal_reply(connection_t*);
-extern int send_ack(connection_t*);
-extern int send_status(connection_t*, int, char*);
-extern int send_error(connection_t*, int, char*);
-extern int send_termreq(connection_t*);
-extern int send_ping(connection_t*);
-extern int send_pong(connection_t*);
-extern int send_add_node(connection_t*, node_t*);
-extern int send_del_node(connection_t*, node_t*);
-extern int send_add_subnet(connection_t*, subnet_t*);
-extern int send_del_subnet(connection_t*, subnet_t*);
-extern int send_add_edge(connection_t*, edge_t*);
-extern int send_del_edge(connection_t*, edge_t*);
-extern int send_key_changed(connection_t*, node_t*);
-extern int send_req_key(connection_t*, node_t*, node_t*);
-extern int send_ans_key(connection_t*, node_t*, node_t*, char*);
-extern int send_tcppacket(connection_t *, vpn_packet_t *);
-
-/* Old functions */
+/* Basic functions */
 
-extern int notify_others(connection_t *, connection_t *, int (*function)(connection_t*, connection_t*));
+extern int send_request(connection_t*, const char*, ...);
 extern int receive_request(connection_t *);
 extern int check_id(char *);
 
+/* Requests */
+
+extern int send_id(connection_t *);
+extern int send_metakey(connection_t *);
+extern int send_challenge(connection_t *);
+extern int send_chal_reply(connection_t *);
+extern int send_ack(connection_t *);
+extern int send_status(connection_t *, int, char *);
+extern int send_error(connection_t *, int, char *);
+extern int send_termreq(connection_t *);
+extern int send_ping(connection_t *);
+extern int send_pong(connection_t *);
+// extern int send_add_node(connection_t *, node_t *);
+// extern int send_del_node(connection_t *, node_t *);
+extern int send_add_subnet(connection_t *, subnet_t *);
+extern int send_del_subnet(connection_t *, subnet_t *);
+extern int send_add_edge(connection_t *, edge_t *);
+extern int send_del_edge(connection_t *, edge_t *);
+extern int send_key_changed(connection_t *, node_t *);
+extern int send_req_key(connection_t *, node_t *, node_t *);
+extern int send_ans_key(connection_t *, node_t *, node_t *);
+extern int send_tcppacket(connection_t *, vpn_packet_t *);
+
+/* Request handlers  */
+
+extern int (*request_handlers[])(connection_t *);
+
+extern int id_h(connection_t *);
+extern int metakey_h(connection_t *);
+extern int challenge_h(connection_t *);
+extern int chal_reply_h(connection_t *);
+extern int ack_h(connection_t *);
+extern int status_h(connection_t *);
+extern int error_h(connection_t *);
+extern int termreq_h(connection_t *);
+extern int ping_h(connection_t *);
+extern int pong_h(connection_t *);
+// extern int add_node_h(connection_t *);
+// extern int del_node_h(connection_t *);
+extern int add_subnet_h(connection_t *);
+extern int del_subnet_h(connection_t *);
+extern int add_edge_h(connection_t *);
+extern int del_edge_h(connection_t *);
+extern int key_changed_h(connection_t *);
+extern int req_key_h(connection_t *);
+extern int ans_key_h(connection_t *);
+extern int tcppacket_h(connection_t *);
+
 #endif /* __TINC_PROTOCOL_H__ */
index 8df8128a116c2f49fce13c5d15d3075561f0b55e..0e16565bbde40a9f115385647dd6a57cbe2e1d05 100644 (file)
@@ -1,7 +1,7 @@
 /*
     route.c -- routing
-    Copyright (C) 2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>,
-                  2000,2001 Guus Sliepen <guus@sliepen.warande.net>
+    Copyright (C) 2000-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
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: route.c,v 1.1.2.21 2001/11/16 17:40:50 zarq Exp $
+    $Id: route.c,v 1.1.2.22 2002/02/10 21:57:54 guus Exp $
 */
 
 #include "config.h"
 
-#ifdef HAVE_FREEBSD
+#if defined(HAVE_FREEBSD) || defined(HAVE_OPENBSD)
  #include <sys/param.h>
 #endif
 #include <sys/socket.h>
 #include <netinet/in.h>
-#ifdef HAVE_SOLARIS
+#if defined(HAVE_SOLARIS) || defined(HAVE_OPENBSD)
  #include <net/if.h>
  #define ETHER_ADDR_LEN 6
 #else
@@ -66,7 +66,7 @@ cp
   if(!subnet || subnet->owner!=myself)
     {
       if(debug_lvl >= DEBUG_TRAFFIC)
-        syslog(LOG_INFO, _("Learned new MAC address %hhx:%hhx:%hhx:%hhx:%hhx:%hhx"),
+        syslog(LOG_INFO, _("Learned new MAC address %hx:%hx:%hx:%hx:%hx:%hx"),
                address->x[0], address->x[1], address->x[2], address->x[3],  address->x[4], address->x[5]);
                
       subnet = new_subnet();
@@ -103,10 +103,26 @@ cp
     return NULL;
 }
 
+node_t *route_ipv4(vpn_packet_t *packet)
+{
+  ipv4_t dest;
+  subnet_t *subnet;
+cp
+#ifdef HAVE_SOLARIS
+  /* The other form gives bus errors on a SparcStation 20. */
+  dest = ((packet->data[30] * 0x100 + packet->data[31]) * 0x100 + packet->data[32]) * 0x100 + packet->data[33];
+#else
+  dest = ntohl(*((unsigned long*)(&packet->data[30])));
+#endif
+cp  
+  subnet = lookup_subnet_ipv4(&dest);
+cp
   if(!subnet)
     {
       if(debug_lvl >= DEBUG_TRAFFIC)
         {
+          syslog(LOG_WARNING, _("Cannot route packet: unknown destination address %d.%d.%d.%d"),
+                 packet->data[30], packet->data[31], packet->data[32], packet->data[33]);
         }
 
       return NULL;
@@ -115,21 +131,25 @@ cp
   return subnet->owner;  
 }
 
-node_t *route_ip(vpn_packet_t *packet)
+node_t *route_ipv6(vpn_packet_t *packet)
 {
-  struct addrinfo *dest;
   subnet_t *subnet;
 cp
-#warning FIXME
-  memcpy(&dest, &packet->data[30], 0);
-
-  subnet = lookup_subnet_ip(&dest);
+  subnet = lookup_subnet_ipv6((ipv6_t *)&packet->data[38]);
 cp
   if(!subnet)
     {
       if(debug_lvl >= DEBUG_TRAFFIC)
         {
-          syslog(LOG_WARNING, _("Cannot route packet: unknown IP destination address"));
+          syslog(LOG_WARNING, _("Cannot route packet: unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"),
+           ntohs(*(short unsigned int *)&packet->data[38]),
+           ntohs(*(short unsigned int *)&packet->data[40]),
+           ntohs(*(short unsigned int *)&packet->data[42]),
+           ntohs(*(short unsigned int *)&packet->data[44]),
+           ntohs(*(short unsigned int *)&packet->data[46]),
+           ntohs(*(short unsigned int *)&packet->data[48]),
+           ntohs(*(short unsigned int *)&packet->data[50]),
+           ntohs(*(short unsigned int *)&packet->data[52]));
         }
 
       return NULL;
@@ -143,7 +163,7 @@ void route_arp(vpn_packet_t *packet)
   struct ether_arp *arp;
   subnet_t *subnet;
   unsigned char ipbuf[4];
-  struct addrinfo *dest;
+  ipv4_t dest;
 cp
   /* First, snatch the source address from the ARP packet */
 
@@ -172,9 +192,9 @@ cp
     }
 
   /* Check if the IP address exists on the VPN */
-#warning FIXME
+
   dest = ntohl(*((unsigned long*)(arp->arp_tpa)));
-  subnet = lookup_subnet_ip(&dest);
+  subnet = lookup_subnet_ipv4(&dest);
 
   if(!subnet)
     {
index 4423e7242bec50e2ee8d023c4b2728facbd263c1..70aab89a8a8df3dada996ec72b78ccb4c9c8b3b3 100644 (file)
@@ -1,7 +1,7 @@
 /*
     route.h -- header file for route.c
-    Copyright (C) 2000,2001 Ivo Timmermans <zarq@iname.com>
-                  2000,2001 Guus Sliepen <guus@sliepen.warande.net>         
+    Copyright (C) 2000-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
@@ -17,7 +17,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: route.h,v 1.1.2.4 2001/10/27 12:13:17 guus Exp $
+    $Id: route.h,v 1.1.2.5 2002/02/10 21:57:54 guus Exp $
 */
 
 #ifndef __TINC_ROUTE_H__
index 57b6829a04bcd23f794cbb6126c3570fd6691f2a..dcfd8c4477c423674da883f39632ecb99613e4e0 100644 (file)
@@ -1,7 +1,7 @@
 /*
     device.c -- Interaction with Solaris tun device
-    Copyright (C) 2001 Ivo Timmermans <itimmermans@bigfoot.com>,
-                  2001 Guus Sliepen <guus@sliepen.warande.net>
+    Copyright (C) 2001-2002 Ivo Timmermans <itimmermans@bigfoot.com>,
+                  2001-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
@@ -17,7 +17,7 @@
     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.1.2.3 2001/11/05 19:06:07 guus Exp $
+    $Id: device.c,v 1.1.2.4 2002/02/10 21:57:54 guus Exp $
 */
 
 
@@ -157,7 +157,7 @@ cp
 
   if(debug_lvl >= DEBUG_TRAFFIC)
     {
-      syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), device_info, packet->len);
+      syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, device_info);
     }
 
   return 0;
index 1b7bc386700b06b02b1739456f1b676d4701d746..6745e2f4766790f0be304aa3a017715952bab7ac 100644 (file)
@@ -1,7 +1,7 @@
 /*
     subnet.c -- handle subnet lookups and lists
-    Copyright (C) 2000,2001 Guus Sliepen <guus@sliepen.warande.net>,
-                  2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>
+    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
@@ -17,7 +17,7 @@
     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.2.28 2001/10/30 12:59:12 guus Exp $
+    $Id: subnet.c,v 1.1.2.29 2002/02/10 21:57:54 guus Exp $
 */
 
 #include "config.h"
 #include <stdio.h>
 #include <syslog.h>
 #include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
 
 #include "conf.h"
 #include "net.h"
@@ -102,10 +106,12 @@ cp
       case SUBNET_IPV6:
         return subnet_compare_ipv6(a, b);
       default:
-        syslog(LOG_ERR, _("subnet_compare() was called with unknown subnet type %d, restarting!"), a->type);
-        sighup = 1;
-        return 0;
+        syslog(LOG_ERR, _("subnet_compare() was called with unknown subnet type %d, exitting!"), a->type);
+        cp_trace();
+        exit(0);
     }
+
+  return 0;
 }
 
 /* Initialising trees */
@@ -178,65 +184,108 @@ cp
 
 subnet_t *str2net(char *subnetstr)
 {
-  int type;
+  int i, l;
   subnet_t *subnet;
-cp
-  if(sscanf(subnetstr, "%d,", &type) != 1)
-    return NULL;
+  unsigned short int x[6];
 cp
   subnet = new_subnet();
 cp
-  switch(type)
+  if(sscanf(subnetstr, "%hu.%hu.%hu.%hu/%d",
+              &x[0],
+              &x[1],
+              &x[2],
+              &x[3],
+              &subnet->net.ipv4.masklength) == 5)
     {
-      case SUBNET_MAC:
-        if(sscanf(subnetstr, "%d,%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &subnet->type,
-                   &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]) != 7)
-          {
-            free_subnet(subnet);
-            return NULL;
-          }
-        break;
-      case SUBNET_IPV4:
-        if(sscanf(subnetstr, "%d,%lx/%lx", &subnet->type, &subnet->net.ipv4.address, &subnet->net.ipv4.mask) != 3)
-          {
-            free_subnet(subnet);
-            return NULL;
-          }
-        break;
-      case SUBNET_IPV6:
-        if(sscanf(subnetstr, "%d,%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx", &subnet->type,
-                   &subnet->net.ipv6.address.x[0],
-                   &subnet->net.ipv6.address.x[1],
-                   &subnet->net.ipv6.address.x[2],
-                   &subnet->net.ipv6.address.x[3],
-                   &subnet->net.ipv6.address.x[4],
-                   &subnet->net.ipv6.address.x[5],
-                   &subnet->net.ipv6.address.x[6],
-                   &subnet->net.ipv6.address.x[7],
-                   &subnet->net.ipv6.mask.x[0],
-                   &subnet->net.ipv6.mask.x[1],
-                   &subnet->net.ipv6.mask.x[2],
-                   &subnet->net.ipv6.mask.x[3],
-                   &subnet->net.ipv6.mask.x[4],
-                   &subnet->net.ipv6.mask.x[5],
-                   &subnet->net.ipv6.mask.x[6],
-                   &subnet->net.ipv6.mask.x[7]) != 17)
-          {
-            free_subnet(subnet);
-            return NULL;
-          }
-        break;
-      default:
-        free_subnet(subnet);
-        return NULL;
+      subnet->type = SUBNET_IPV4;
+      subnet->net.ipv4.address = (((((x[0] << 8) + x[1]) << 8) + x[2]) << 8) + x[3];
+      subnet->net.ipv4.mask = ~((1 << (32 - subnet->net.ipv4.masklength)) - 1);
+      return subnet;
     }
-cp
-  return subnet;
+             
+  if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d",
+             &subnet->net.ipv6.address.x[0],
+             &subnet->net.ipv6.address.x[1],
+             &subnet->net.ipv6.address.x[2],
+             &subnet->net.ipv6.address.x[3],
+             &subnet->net.ipv6.address.x[4],
+             &subnet->net.ipv6.address.x[5],
+             &subnet->net.ipv6.address.x[6],
+             &subnet->net.ipv6.address.x[7],
+             &subnet->net.ipv6.masklength) == 9)
+    {
+      subnet->type = SUBNET_IPV6;
+      for(l = subnet->net.ipv6.masklength, i = 0; i < 8; l -= 16, i++)
+      {
+        subnet->net.ipv6.address.x[i] = htons(subnet->net.ipv6.address.x[i]);
+        if(l >= 16)
+          subnet->net.ipv6.mask.x[i] = 65535;
+       else if (l > 0)
+         subnet->net.ipv6.mask.x[i] = htons(65536 - (1 << l));
+       else
+          subnet->net.ipv6.mask.x[i] = 0;
+      }
+      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.address = (((((x[0] << 8) + x[1]) << 8) + x[2]) << 8) + x[3];
+      subnet->net.ipv4.mask = ~0;
+      subnet->net.ipv4.masklength = 32;
+      return subnet;
+    }
+             
+  if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
+             &subnet->net.ipv6.address.x[0],
+             &subnet->net.ipv6.address.x[1],
+             &subnet->net.ipv6.address.x[2],
+             &subnet->net.ipv6.address.x[3],
+             &subnet->net.ipv6.address.x[4],
+             &subnet->net.ipv6.address.x[5],
+             &subnet->net.ipv6.address.x[6],
+             &subnet->net.ipv6.address.x[7]) == 8)
+    {
+      subnet->type = SUBNET_IPV6;
+      subnet->net.ipv6.masklength = 128;
+      for(l = subnet->net.ipv6.masklength, i = 0; i < 8; l -= 16, i++)
+      {
+        subnet->net.ipv6.address.x[i] = htons(subnet->net.ipv6.address.x[i]);
+        if(l >= 16)
+          subnet->net.ipv6.mask.x[i] = 65535;
+       else if (l > 0)
+         subnet->net.ipv6.mask.x[i] = htons(65536 - (1 << l));
+       else
+          subnet->net.ipv6.mask.x[i] = 0;
+      }
+      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;
+      subnet->net.mac.address.x[0] = x[0];
+      subnet->net.mac.address.x[1] = x[1];
+      subnet->net.mac.address.x[2] = x[2];
+      subnet->net.mac.address.x[3] = x[3];
+      subnet->net.mac.address.x[4] = x[4];
+      subnet->net.mac.address.x[5] = x[5];
+      return subnet;
+    }
+
+  free(subnet);
+  return NULL;
 }
 
 char *net2str(subnet_t *subnet)
@@ -246,7 +295,7 @@ cp
   switch(subnet->type)
     {
       case SUBNET_MAC:
-        asprintf(&netstr, "%d,%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", subnet->type,
+        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],
@@ -255,26 +304,24 @@ cp
                    subnet->net.mac.address.x[5]);
         break;
       case SUBNET_IPV4:
-        asprintf(&netstr, "%d,%lx/%lx", subnet->type, subnet->net.ipv4.address, subnet->net.ipv4.mask);
+        asprintf(&netstr, "%hu.%hu.%hu.%hu/%d",
+                  (unsigned short int)((subnet->net.ipv4.address >> 24) & 255),
+                  (unsigned short int)((subnet->net.ipv4.address >> 16) & 255),
+                  (unsigned short int)((subnet->net.ipv4.address >> 8) & 255),
+                  (unsigned short int)(subnet->net.ipv4.address & 255),
+                  subnet->net.ipv4.masklength);
         break;
       case SUBNET_IPV6:
-        asprintf(&netstr, "%d,%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx", subnet->type,
-                   subnet->net.ipv6.address.x[0],
-                   subnet->net.ipv6.address.x[1],
-                   subnet->net.ipv6.address.x[2],
-                   subnet->net.ipv6.address.x[3],
-                   subnet->net.ipv6.address.x[4],
-                   subnet->net.ipv6.address.x[5],
-                   subnet->net.ipv6.address.x[6],
-                   subnet->net.ipv6.address.x[7],
-                   subnet->net.ipv6.mask.x[0],
-                   subnet->net.ipv6.mask.x[1],
-                   subnet->net.ipv6.mask.x[2],
-                   subnet->net.ipv6.mask.x[3],
-                   subnet->net.ipv6.mask.x[4],
-                   subnet->net.ipv6.mask.x[5],
-                   subnet->net.ipv6.mask.x[6],
-                   subnet->net.ipv6.mask.x[7]);
+        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.masklength);
         break;
       default:
         asprintf(&netstr, _("unknown subnet type"));
@@ -342,8 +389,8 @@ subnet_t *lookup_subnet_ipv6(ipv6_t *address)
   int i;
 cp
   subnet.type = SUBNET_IPV6;
-  memcpy(&subnet.net.ipv6.address, address, sizeof(ipv6_t));
-  memset(&subnet.net.ipv6.mask, 0xFF, 16);
+  memcpy(subnet.net.ipv6.address.x, address, sizeof(ipv6_t));
+  memset(subnet.net.ipv6.mask.x, 0xFF, 16);
   
   p = (subnet_t *)avl_search_closest_greater(subnet_tree, &subnet);
   
@@ -366,7 +413,7 @@ cp
     {
       subnet = (subnet_t *)node->data;
       netstr = net2str(subnet);
-      syslog(LOG_DEBUG, " %s owner %s", netstr, subnet->owner->name);
+      syslog(LOG_DEBUG, _(" %s owner %s"), netstr, subnet->owner->name);
       free(netstr);
     }
   syslog(LOG_DEBUG, _("End of subnet list."));
index 45e9cc12dc72a489de6318b50849bba86df2480b..9657ad9c424cdcca3c5247da6d525a29bb428730 100644 (file)
@@ -17,7 +17,7 @@
     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.2.14 2001/11/16 12:10:54 zarq Exp $
+    $Id: subnet.h,v 1.1.2.15 2002/02/10 21:57:54 guus Exp $
 */
 
 #ifndef __TINC_SUBNET_H__
@@ -28,7 +28,8 @@
 enum
 {
   SUBNET_MAC = 0,
-  SUBNET_IP,
+  SUBNET_IPV4,
+  SUBNET_IPV6,
   SUBNET_TYPES                         /* Guardian */
 };
 
@@ -37,11 +38,19 @@ typedef struct subnet_mac_t
   mac_t address;
 } subnet_mac_t;
 
-typedef struct subnet_ip_t
+typedef struct subnet_ipv4_t
 {
-  struct addrinfo *address;
-  struct addrinfo *mask;
-} subnet_ip_t;
+  ipv4_t address;
+  ipv4_t mask;
+  int masklength;
+} subnet_ipv4_t;
+
+typedef struct subnet_ipv6_t
+{
+  ipv6_t address;
+  ipv6_t mask;
+  int masklength;
+} subnet_ipv6_t;
 
 #include "node.h"
 
@@ -56,9 +65,9 @@ typedef struct subnet_t {
   union net
     {
       subnet_mac_t mac;
-      subnet_ip_t ip;
+      subnet_ipv4_t ipv4;
+      subnet_ipv6_t ipv6;
     } net;
-    
 } subnet_t;
 
 extern subnet_t *new_subnet(void);
@@ -73,7 +82,8 @@ 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_ip(struct addrinfo *);
+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__ */
index f4ecebff3a9b50b100f5190c38e1eac0d9c77d08..d9288bac47030bd38a6f2715f338b5c8992cf3e5 100644 (file)
@@ -1,7 +1,7 @@
 /*
     tincd.c -- the main file for tincd
-    Copyright (C) 1998-2001 Ivo Timmermans <itimmermans@bigfoot.com>
-                  2000,2001 Guus Sliepen <guus@sliepen.warande.net>
+    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
@@ -17,7 +17,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: tincd.c,v 1.10.4.56 2001/11/16 22:40:26 zarq Exp $
+    $Id: tincd.c,v 1.10.4.57 2002/02/10 21:57:54 guus Exp $
 */
 
 #include "config.h"
 #include <openssl/rand.h>
 #include <openssl/rsa.h>
 #include <openssl/pem.h>
+#include <openssl/evp.h>
 
 #include <utils.h>
 #include <xalloc.h>
 
 #include "conf.h"
 #include "net.h"
+#include "netutl.h"
 #include "process.h"
 #include "protocol.h"
 #include "subnet.h"
@@ -295,7 +297,7 @@ main(int argc, char **argv, char **envp)
   if(show_version)
     {
       printf(_("%s version %s (built %s %s, protocol %d)\n"), PACKAGE, VERSION, __DATE__, __TIME__, PROT_CURRENT);
-      printf(_("Copyright (C) 1998-2001 Ivo Timmermans, Guus Sliepen and others.\n"
+      printf(_("Copyright (C) 1998-2002 Ivo Timmermans, Guus Sliepen and others.\n"
               "See the AUTHORS file for a complete list.\n\n"
               "tinc comes with ABSOLUTELY NO WARRANTY.  This is free software,\n"
               "and you are welcome to redistribute it under certain conditions;\n"
@@ -327,6 +329,13 @@ main(int argc, char **argv, char **envp)
   /* Slllluuuuuuurrrrp! */
 cp
   RAND_load_file("/dev/urandom", 1024);
+
+#ifdef HAVE_SSLEAY_ADD_ALL_ALGORITHMS
+  SSLeay_add_all_algorithms();
+#else
+  OpenSSL_add_all_algorithms();
+#endif
+
 cp
   if(generate_keys)
     {