Merge branch 'master' of git://tinc-vpn.org/tinc into 1.1
authorGuus Sliepen <guus@tinc-vpn.org>
Mon, 9 May 2011 19:35:14 +0000 (21:35 +0200)
committerGuus Sliepen <guus@tinc-vpn.org>
Mon, 9 May 2011 19:35:14 +0000 (21:35 +0200)
Conflicts:
NEWS
README
configure.in
doc/tincd.8.in
lib/pidfile.c
src/bsd/device.c
src/dropin.h
src/net.c
src/net_packet.c
src/node.c
src/process.c
src/tincd.c

21 files changed:
1  2 
NEWS
README
configure.in
doc/tinc.texi
doc/tincd.8.in
have.h
src/bsd/device.c
src/conf.c
src/dropin.c
src/dropin.h
src/graph.c
src/memcmp.c
src/mingw/device.c
src/net.c
src/net_packet.c
src/netutl.c
src/node.c
src/process.c
src/protocol_key.c
src/solaris/device.c
src/tincd.c

diff --cc NEWS
index cee37ea824ca32fb6835e76a00f8a2f1d38ef4c3,792a71f1655badfe831522e64a6fb8beb28136d2..c48a0e80775073fc6e0a12d0dfbbd77f13465cda
--- 1/NEWS
--- 2/NEWS
+++ b/NEWS
@@@ -1,10 -1,4 +1,10 @@@
- Version 1.0.14               not released yet
 +Version 1.1-cvs              Work in progress
 +
 + * Use libevent to handle I/O events and timeouts.
 +
 + * Use splay trees instead of AVL trees.
 +
+ Version 1.0.14               May  8 2011
  
   * Fixed reading configuration files that do not end with a newline. Again.
  
diff --cc README
index 3f21f25d51fbb25957dd87ee200be5144f122e82,bc8bea00070b58a7ab723066bb21acd73115409b..b1236fab20edf2b03d8695a1e529b4afe472711c
--- 1/README
--- 2/README
+++ b/README
@@@ -1,7 -1,7 +1,7 @@@
 -This is the README file for tinc version 1.0.14. Installation
 +This is the README file for tinc version 1.1-cvs. Installation
  instructions may be found in the INSTALL file.
  
- tinc is Copyright (C) 1998-2010 by:
+ tinc is Copyright (C) 1998-2011 by:
  
  Ivo Timmermans,
  Guus Sliepen <guus@tinc-vpn.org>,
@@@ -69,18 -69,13 +69,16 @@@ this library is not installed on you sy
  manual in doc/tinc.texi contains more detailed information on how to
  install this library.
  
- Since 1.0pre6, the zlib library is used for optional compression. You need this
- library whether or not you plan to enable the compression. You can find it at
- http://www.gzip.org/zlib/. Because of a possible exploit in earlier versions we
- recommand that you download version 1.1.4 or later.
+ Since 1.0pre6, the zlib library is used for optional compression. You can
+ find it at http://www.gzip.org/zlib/. Because of a possible exploit in
+ earlier versions we recommend that you download version 1.1.4 or later.
  
- Since 1.0, the lzo library is also used for optional compression. You need this
- library whether or not you plan to enable compression. You can find it at
- http://www.oberhumer.com/opensource/lzo/.
+ Since 1.0, the lzo library is also used for optional compression. You can
+ find it at http://www.oberhumer.com/opensource/lzo/.
  
 +Since 1.1, the libevent library is used for the main event loop. You can find
 +it at http://monkey.org/~provos/libevent/.
 +
  In order to compile tinc, you will need a GNU C compiler environment.
  
  
diff --cc configure.in
index 5aacff6a47430926f712d2d789f6a066b55f448b,a6dd6d691b735ec59f867fadf01775f94dcf9c31..7c050139b4ca3ee5db7e7155d15da2489659bf94
@@@ -98,8 -101,8 +100,8 @@@ dnl Checks for header files
  dnl We do this in multiple stages, because unlike Linux all the other operating systems really suck and don't include their own dependencies.
  
  AC_HEADER_STDC
- AC_CHECK_HEADERS([stdbool.h syslog.h sys/file.h sys/ioctl.h sys/mman.h sys/param.h sys/socket.h sys/time.h sys/uio.h sys/un.h sys/wait.h netdb.h arpa/inet.h dirent.h])
- AC_CHECK_HEADERS([net/if.h net/if_types.h linux/if_tun.h net/if_tun.h net/if_tap.h net/ethernet.h net/if_arp.h netinet/in_systm.h netinet/in.h netinet/in6.h time.h],
 -AC_CHECK_HEADERS([stdbool.h syslog.h sys/file.h sys/ioctl.h sys/mman.h sys/param.h sys/resource.h sys/socket.h sys/time.h sys/uio.h sys/wait.h netdb.h arpa/inet.h dirent.h])
 -AC_CHECK_HEADERS([net/if.h net/if_types.h linux/if_tun.h net/if_tun.h net/tun/if_tun.h net/if_tap.h net/tap/if_tap.h net/ethernet.h net/if_arp.h netinet/in_systm.h netinet/in.h netinet/in6.h],
++AC_CHECK_HEADERS([stdbool.h syslog.h sys/file.h sys/ioctl.h sys/mman.h sys/param.h sys/resource.h sys/socket.h sys/time.h sys/uio.h sys/un.h sys/wait.h netdb.h arpa/inet.h dirent.h])
++AC_CHECK_HEADERS([net/if.h net/if_types.h linux/if_tun.h net/if_tun.h net/tun/if_tun.h net/if_tap.h net/tap/if_tap.h net/ethernet.h net/if_arp.h netinet/in_systm.h netinet/in.h netinet/in6.h time.h],
    [], [], [#include "have.h"]
  )
  AC_CHECK_HEADERS([netinet/if_ether.h netinet/ip.h netinet/ip6.h],
@@@ -127,7 -130,7 +129,7 @@@ dnl Checks for library functions
  AC_FUNC_MEMCMP
  AC_FUNC_ALLOCA
  AC_TYPE_SIGNAL
- AC_CHECK_FUNCS([asprintf daemon fchmod flock ftime fork get_current_dir_name gettimeofday mlockall putenv random select strdup strerror strsignal strtol system time unsetenv vsyslog writev],
 -AC_CHECK_FUNCS([asprintf daemon fchmod flock ftime fork get_current_dir_name gettimeofday mlockall putenv random select strdup strerror strsignal strtol system unsetenv usleep vsyslog writev],
++AC_CHECK_FUNCS([asprintf daemon fchmod flock ftime fork get_current_dir_name gettimeofday mlockall putenv random select strdup strerror strsignal strtol system time usleep unsetenv vsyslog writev],
    [], [], [#include "have.h"]
  )
  AC_FUNC_MALLOC
diff --cc doc/tinc.texi
index 3dc9eca46d899ca1aab790fdb587c5134fcbfab8,6bbc2e24ef20c2b3af9ec1cc9399d4c7b5dc87b3..7fc8909f9c25b6dd2ad49c3ea7ca06ac6fbd07ef
@@@ -37,10 -37,9 +37,10 @@@ permission notice identical to this one
  
  @page
  @vskip 0pt plus 1filll
 +@cindex copyright
  This is the info manual for @value{PACKAGE} version @value{VERSION}, a Virtual Private Network daemon.
  
- Copyright @copyright{} 1998-2010 Ivo Timmermans,
+ Copyright @copyright{} 1998-2011 Ivo Timmermans,
  Guus Sliepen <guus@@tinc-vpn.org> and
  Wessel Dankers <wsl@@tinc-vpn.org>.
  
@@@ -1552,12 -1558,24 +1574,16 @@@ This will also disable the automatic re
  Set debug level to @var{level}.  The higher the debug level, the more gets
  logged.  Everything goes via syslog.
  
 -@item -k, --kill[=@var{signal}]
 -Attempt to kill a running tincd (optionally with the specified @var{signal} instead of SIGTERM) and exit.
 -Use it in conjunction with the -n option to make sure you kill the right tinc daemon.
 -Under native Windows the optional argument is ignored,
 -the service will always be stopped and removed.
 -
  @item -n, --net=@var{netname}
- Use configuration for net @var{netname}. @xref{Multiple networks}.
+ Use configuration for net @var{netname}.
+ This will let tinc read all configuration files from
+ @file{@value{sysconfdir}/tinc/@var{netname}/}.
+ Specifying . for @var{netname} is the same as not specifying any @var{netname}.
+ @xref{Multiple networks}.
  
 -@item -K, --generate-keys[=@var{bits}]
 -Generate public/private keypair of @var{bits} length. If @var{bits} is not specified,
 -2048 is the default. tinc will ask where you want to store the files,
 -but will default to the configuration directory (you can use the -c or -n option
 -in combination with -K). After that, tinc will quit.
 +@item --controlsocket=@var{filename}
 +Open control socket at @var{filename}. If unspecified, the default is
 +@file{@value{localstatedir}/run/tinc.@var{netname}.control}.
  
  @item -L, --mlock
  Lock tinc into main memory.
diff --cc doc/tincd.8.in
index df6af144fc6b50bdab577bce05a3c40f5918216d,a8ef2fb836c7ca9ffa041cdf301a1d08321cabfd..a210979e30ca14bb771bd093107e08d1d8fc6f00
@@@ -53,6 -56,29 +53,14 @@@ Increase debug level or set it t
  .It Fl n, -net Ns = Ns Ar NETNAME
  Connect to net
  .Ar NETNAME .
 -.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 2048 bits.
 -When saving keys to existing files, tinc will not delete the old keys,
 -you have to remove them manually.
+ This will let tinc read all configuration files from
+ .Pa @sysconfdir@/tinc/ Ar NETNAME .
+ Specifying
+ .Li .
+ for
+ .Ar NETNAME
+ is the same as not specifying any
+ .Ar NETNAME .
  .It Fl L, -mlock
  Lock tinc into main memory.
  This will prevent sensitive data like shared private keys to be written to the system swap files/partitions.
diff --cc have.h
Simple merge
index 993b9825287cc975a529633b0d36c5b6bf6544d5,d6ef0e8259f6141999e66226b121696da2d2d6fc..d647734ed16d92a1baf9bdf56cccfede7625fbfc
@@@ -197,13 -197,12 +197,12 @@@ bool read_packet(vpn_packet_t *packet) 
  #ifdef HAVE_TUNEMU
                case DEVICE_TYPE_TUNEMU:
                        if(device_type == DEVICE_TYPE_TUNEMU)
 -                              lenin = tunemu_read(device_fd, packet->data + 14, MTU - 14);
 +                              inlen = tunemu_read(device_fd, packet->data + 14, MTU - 14);
                        else
- #else
-                               inlen = read(device_fd, packet->data + 14, MTU - 14);
  #endif
 -                              lenin = read(device_fd, packet->data + 14, MTU - 14);
++                              inlen = read(device_fd, packet->data + 14, MTU - 14);
  
 -                      if(lenin <= 0) {
 +                      if(inlen <= 0) {
                                logger(LOG_ERR, "Error while reading from %s %s: %s", device_info,
                                           device, strerror(errno));
                                return false;
diff --cc src/conf.c
Simple merge
diff --cc src/dropin.c
index 52fb5b8675bd3799eb8177e0df7222f4ecd5edbf,0000000000000000000000000000000000000000..4aed74e95125b6492f9ecc64e464d771f3fe9970
mode 100644,000000..100644
--- /dev/null
@@@ -1,172 -1,0 +1,173 @@@
-                   2000-2009 Guus Sliepen <guus@tinc-vpn.org>
 +/*
 +    dropin.c -- a set of drop-in replacements for libc functions
 +    Copyright (C) 2000-2005 Ivo Timmermans,
- #ifdef HAVE_MINGW
++                  2000-2011 Guus Sliepen <guus@tinc-vpn.org>
 +
 +    This program is free software; you can redistribute it and/or modify
 +    it under the terms of the GNU General Public License as published by
 +    the Free Software Foundation; either version 2 of the License, or
 +    (at your option) any later version.
 +
 +    This program is distributed in the hope that it will be useful,
 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +    GNU General Public License for more details.
 +
 +    You should have received a copy of the GNU General Public License along
 +    with this program; if not, write to the Free Software Foundation, Inc.,
 +    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 +*/
 +
 +#include "system.h"
 +
 +#include "xalloc.h"
 +
 +#ifndef HAVE_DAEMON
 +/*
 +  Replacement for the daemon() function.
 +  
 +  The daemon() function is for programs wishing to detach themselves
 +  from the controlling terminal and run in the background as system
 +  daemons.
 +
 +  Unless the argument nochdir is non-zero, daemon() changes the
 +  current working directory to the root (``/'').
 +
 +  Unless the argument noclose is non-zero, daemon() will redirect
 +  standard input, standard output and standard error to /dev/null.
 +*/
 +int daemon(int nochdir, int noclose) {
 +#ifdef HAVE_FORK
 +      pid_t pid;
 +      int fd;
 +
 +      pid = fork();
 +
 +      /* Check if forking failed */
 +      if(pid < 0) {
 +              perror("fork");
 +              exit(-1);
 +      }
 +
 +      /* If we are the parent, terminate */
 +      if(pid)
 +              exit(0);
 +
 +      /* Detach by becoming the new process group leader */
 +      if(setsid() < 0) {
 +              perror("setsid");
 +              return -1;
 +      }
 +
 +      /* Change working directory to the root (to avoid keeping mount
 +         points busy) */
 +      if(!nochdir) {
 +              chdir("/");
 +      }
 +
 +      /* Redirect stdin/out/err to /dev/null */
 +      if(!noclose) {
 +              fd = open("/dev/null", O_RDWR);
 +
 +              if(fd < 0) {
 +                      perror("opening /dev/null");
 +                      return -1;
 +              } else {
 +                      dup2(fd, 0);
 +                      dup2(fd, 1);
 +                      dup2(fd, 2);
 +              }
 +      }
 +
 +      return 0;
 +#else
 +      return -1;
 +#endif
 +}
 +#endif
 +
 +#ifndef HAVE_GET_CURRENT_DIR_NAME
 +/*
 +  Replacement for the GNU get_current_dir_name function:
 +
 +  get_current_dir_name will malloc(3) an array big enough to hold the
 +  current directory name.  If the environment variable PWD is set, and
 +  its value is correct, then that value will be returned.
 +*/
 +char *get_current_dir_name(void) {
 +      size_t size;
 +      char *buf;
 +      char *r;
 +
 +      /* Start with 100 bytes.  If this turns out to be insufficient to
 +         contain the working directory, double the size.  */
 +      size = 100;
 +      buf = xmalloc(size);
 +
 +      errno = 0;                                      /* Success */
 +      r = getcwd(buf, size);
 +
 +      /* getcwd returns NULL and sets errno to ERANGE if the bufferspace
 +         is insufficient to contain the entire working directory.  */
 +      while(r == NULL && errno == ERANGE) {
 +              free(buf);
 +              size <<= 1;                             /* double the size */
 +              buf = xmalloc(size);
 +              r = getcwd(buf, size);
 +      }
 +
 +      return buf;
 +}
 +#endif
 +
 +#ifndef HAVE_ASPRINTF
 +int asprintf(char **buf, const char *fmt, ...) {
 +      int result;
 +      va_list ap;
 +      va_start(ap, fmt);
 +      result = vasprintf(buf, fmt, ap);
 +      va_end(ap);
 +      return result;
 +}
 +
 +int vasprintf(char **buf, const char *fmt, va_list ap) {
 +      int status;
 +      va_list aq;
 +      int len;
 +
 +      len = 4096;
 +      *buf = xmalloc(len);
 +
 +      va_copy(aq, ap);
 +      status = vsnprintf(*buf, len, fmt, aq);
 +      va_end(aq);
 +
 +      if(status >= 0)
 +              *buf = xrealloc(*buf, status + 1);
 +
 +      if(status > len - 1) {
 +              len = status;
 +              va_copy(aq, ap);
 +              status = vsnprintf(*buf, len, fmt, aq);
 +              va_end(aq);
 +      }
 +
 +      return status;
 +}
 +#endif
 +
 +#ifndef HAVE_GETTIMEOFDAY
 +int gettimeofday(struct timeval *tv, void *tz) {
 +      tv->tv_sec = time(NULL);
 +      tv->tv_usec = 0;
 +      return 0;
 +}
 +#endif
 +
-       Sleep(usec / 1000);
++#ifndef HAVE_USLEEP
 +int usleep(long usec) {
++      struct timeval tv = {usec / 1000000, (usec / 1000) % 1000};
++      select(0, NULL, NULL, NULL, &tv);
 +      return 0;
 +}
 +#endif
diff --cc src/dropin.h
index e9d13535fbfb63f55d92e11dd79d4ef36b49386e,0000000000000000000000000000000000000000..a3a22e3fa0cd56feeee3733246a71b8c1230254c
mode 100644,000000..100644
--- /dev/null
@@@ -1,44 -1,0 +1,44 @@@
-                   2000-2009 Guus Sliepen <guus@tinc-vpn.org>
 +/*
 +    dropin.h -- header file for dropin.c
 +    Copyright (C) 2000-2005 Ivo Timmermans,
++                  2000-2011 Guus Sliepen <guus@tinc-vpn.org>
 +
 +    This program is free software; you can redistribute it and/or modify
 +    it under the terms of the GNU General Public License as published by
 +    the Free Software Foundation; either version 2 of the License, or
 +    (at your option) any later version.
 +
 +    This program is distributed in the hope that it will be useful,
 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +    GNU General Public License for more details.
 +
 +    You should have received a copy of the GNU General Public License along
 +    with this program; if not, write to the Free Software Foundation, Inc.,
 +    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 +*/
 +
 +#ifndef __DROPIN_H__
 +#define __DROPIN_H__
 +
 +#include "fake-getaddrinfo.h"
 +#include "fake-getnameinfo.h"
 +
 +#ifndef HAVE_DAEMON
 +extern int daemon(int, int);
 +#endif
 +
 +#ifndef HAVE_GET_CURRENT_DIR_NAME
 +extern char *get_current_dir_name(void);
 +#endif
 +
 +#ifndef HAVE_ASPRINTF
 +extern int asprintf(char **, const char *, ...);
 +extern int vasprintf(char **, const char *, va_list ap);
 +#endif
 +
 +#ifndef HAVE_GETTIMEOFDAY
 +extern int gettimeofday(struct timeval *, void *);
 +#endif
 +
 +#endif                                                        /* __DROPIN_H__ */
diff --cc src/graph.c
Simple merge
diff --cc src/memcmp.c
index 8103e1a7ff53f097faca1ec5e94089a676a83e9e,0000000000000000000000000000000000000000..910499484d47029f3e6f5e898a636a868c809152
mode 100644,000000..100644
--- /dev/null
@@@ -1,391 -1,0 +1,395 @@@
 +/* Copyright (C) 1991, 1993, 1995, 1997, 1998 Free Software Foundation, Inc.
 +   Contributed by Torbjorn Granlund (tege@sics.se).
 +
 +   NOTE: The canonical source of this file is maintained with the GNU C Library.
 +   Bugs can be reported to bug-glibc@prep.ai.mit.edu.
 +
 +   This program is free software; you can redistribute it and/or modify it
 +   under the terms of the GNU General Public License as published by the
 +   Free Software Foundation; either version 2, or (at your option) any
 +   later version.
 +
 +   This program is distributed in the hope that it will be useful,
 +   but WITHOUT ANY WARRANTY; without even the implied warranty of
 +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +   GNU General Public License for more details.
 +
 +   You should have received a copy of the GNU General Public License along
 +   with this program; if not, write to the Free Software Foundation, Inc.,
 +   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 +*/
 +
 +#ifdef HAVE_CONFIG_H
 +# include "config.h"
 +#endif
 +
++#ifdef HAVE_INTTYPES_H
++#include <inttypes.h>
++#endif
++
 +#undef        __ptr_t
 +#if defined __cplusplus || (defined __STDC__ && __STDC__)
 +# define __ptr_t      void *
 +#else /* Not C++ or ANSI C.  */
 +# undef       const
 +# define const
 +# define __ptr_t      char *
 +#endif /* C++ or ANSI C.  */
 +
 +#ifndef __P
 +# if defined __GNUC__ || (defined __STDC__ && __STDC__)
 +#  define __P(args) args
 +# else
 +#  define __P(args) ()
 +# endif  /* GCC.  */
 +#endif  /* Not __P.  */
 +
 +#if defined HAVE_STRING_H || defined _LIBC
 +# include <string.h>
 +#endif
 +
 +#undef memcmp
 +
 +#ifdef _LIBC
 +
 +# include <memcopy.h>
 +
 +#else /* Not in the GNU C library.  */
 +
 +# include <sys/types.h>
 +
 +/* Type to use for aligned memory operations.
 +   This should normally be the biggest type supported by a single load
 +   and store.  Must be an unsigned type.  */
 +# define op_t unsigned long int
 +# define OPSIZ        (sizeof(op_t))
 +
 +/* Threshold value for when to enter the unrolled loops.  */
 +# define OP_T_THRES   16
 +
 +/* Type to use for unaligned operations.  */
 +typedef unsigned char byte;
 +
 +# ifndef WORDS_BIGENDIAN
 +#  define MERGE(w0, sh_1, w1, sh_2) (((w0) >> (sh_1)) | ((w1) << (sh_2)))
 +# else
 +#  define MERGE(w0, sh_1, w1, sh_2) (((w0) << (sh_1)) | ((w1) >> (sh_2)))
 +# endif
 +
 +#endif        /* In the GNU C library.  */
 +
 +#ifdef WORDS_BIGENDIAN
 +# define CMP_LT_OR_GT(a, b) ((a) > (b) ? 1 : -1)
 +#else
 +# define CMP_LT_OR_GT(a, b) memcmp_bytes ((a), (b))
 +#endif
 +
 +/* BE VERY CAREFUL IF YOU CHANGE THIS CODE!  */
 +
 +/* The strategy of this memcmp is:
 +
 +   1. Compare bytes until one of the block pointers is aligned.
 +
 +   2. Compare using memcmp_common_alignment or
 +      memcmp_not_common_alignment, regarding the alignment of the other
 +      block after the initial byte operations.  The maximum number of
 +      full words (of type op_t) are compared in this way.
 +
 +   3. Compare the few remaining bytes.  */
 +
 +#ifndef WORDS_BIGENDIAN
 +/* memcmp_bytes -- Compare A and B bytewise in the byte order of the machine.
 +   A and B are known to be different.
 +   This is needed only on little-endian machines.  */
 +
 +static int memcmp_bytes __P((op_t, op_t));
 +
 +# ifdef  __GNUC__
 +__inline
 +# endif
 +static int
 +memcmp_bytes (a, b)
 +     op_t a, b;
 +{
 +  intptr_t srcp1 = (intptr_t) &a;
 +  intptr_t srcp2 = (intptr_t) &b;
 +  op_t a0, b0;
 +
 +  do
 +    {
 +      a0 = ((byte *) srcp1)[0];
 +      b0 = ((byte *) srcp2)[0];
 +      srcp1 += 1;
 +      srcp2 += 1;
 +    }
 +  while (a0 == b0);
 +  return a0 - b0;
 +}
 +#endif
 +
 +static int memcmp_common_alignment __P((intptr_t, intptr_t, size_t));
 +
 +/* memcmp_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN `op_t'
 +   objects (not LEN bytes!).  Both SRCP1 and SRCP2 should be aligned for
 +   memory operations on `op_t's.  */
 +#ifdef        __GNUC__
 +__inline
 +#endif
 +static int
 +memcmp_common_alignment (srcp1, srcp2, len)
 +     intptr_t srcp1;
 +     intptr_t srcp2;
 +     size_t len;
 +{
 +  op_t a0, a1;
 +  op_t b0, b1;
 +
 +  switch (len % 4)
 +    {
 +    default: /* Avoid warning about uninitialized local variables.  */
 +    case 2:
 +      a0 = ((op_t *) srcp1)[0];
 +      b0 = ((op_t *) srcp2)[0];
 +      srcp1 -= 2 * OPSIZ;
 +      srcp2 -= 2 * OPSIZ;
 +      len += 2;
 +      goto do1;
 +    case 3:
 +      a1 = ((op_t *) srcp1)[0];
 +      b1 = ((op_t *) srcp2)[0];
 +      srcp1 -= OPSIZ;
 +      srcp2 -= OPSIZ;
 +      len += 1;
 +      goto do2;
 +    case 0:
 +      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
 +      return 0;
 +      a0 = ((op_t *) srcp1)[0];
 +      b0 = ((op_t *) srcp2)[0];
 +      goto do3;
 +    case 1:
 +      a1 = ((op_t *) srcp1)[0];
 +      b1 = ((op_t *) srcp2)[0];
 +      srcp1 += OPSIZ;
 +      srcp2 += OPSIZ;
 +      len -= 1;
 +      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
 +      goto do0;
 +      /* Fall through.  */
 +    }
 +
 +  do
 +    {
 +      a0 = ((op_t *) srcp1)[0];
 +      b0 = ((op_t *) srcp2)[0];
 +      if (a1 != b1)
 +      return CMP_LT_OR_GT (a1, b1);
 +
 +    do3:
 +      a1 = ((op_t *) srcp1)[1];
 +      b1 = ((op_t *) srcp2)[1];
 +      if (a0 != b0)
 +      return CMP_LT_OR_GT (a0, b0);
 +
 +    do2:
 +      a0 = ((op_t *) srcp1)[2];
 +      b0 = ((op_t *) srcp2)[2];
 +      if (a1 != b1)
 +      return CMP_LT_OR_GT (a1, b1);
 +
 +    do1:
 +      a1 = ((op_t *) srcp1)[3];
 +      b1 = ((op_t *) srcp2)[3];
 +      if (a0 != b0)
 +      return CMP_LT_OR_GT (a0, b0);
 +
 +      srcp1 += 4 * OPSIZ;
 +      srcp2 += 4 * OPSIZ;
 +      len -= 4;
 +    }
 +  while (len != 0);
 +
 +  /* This is the right position for do0.  Please don't move
 +     it into the loop.  */
 + do0:
 +  if (a1 != b1)
 +    return CMP_LT_OR_GT (a1, b1);
 +  return 0;
 +}
 +
 +static int memcmp_not_common_alignment __P((intptr_t, intptr_t, size_t));
 +
 +/* memcmp_not_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN
 +   `op_t' objects (not LEN bytes!).  SRCP2 should be aligned for memory
 +   operations on `op_t', but SRCP1 *should be unaligned*.  */
 +#ifdef        __GNUC__
 +__inline
 +#endif
 +static int
 +memcmp_not_common_alignment (srcp1, srcp2, len)
 +     intptr_t srcp1;
 +     intptr_t srcp2;
 +     size_t len;
 +{
 +  op_t a0, a1, a2, a3;
 +  op_t b0, b1, b2, b3;
 +  op_t x;
 +  int shl, shr;
 +
 +  /* Calculate how to shift a word read at the memory operation
 +     aligned srcp1 to make it aligned for comparison.  */
 +
 +  shl = 8 * (srcp1 % OPSIZ);
 +  shr = 8 * OPSIZ - shl;
 +
 +  /* Make SRCP1 aligned by rounding it down to the beginning of the `op_t'
 +     it points in the middle of.  */
 +  srcp1 &= -OPSIZ;
 +
 +  switch (len % 4)
 +    {
 +    default: /* Avoid warning about uninitialized local variables.  */
 +    case 2:
 +      a1 = ((op_t *) srcp1)[0];
 +      a2 = ((op_t *) srcp1)[1];
 +      b2 = ((op_t *) srcp2)[0];
 +      srcp1 -= 1 * OPSIZ;
 +      srcp2 -= 2 * OPSIZ;
 +      len += 2;
 +      goto do1;
 +    case 3:
 +      a0 = ((op_t *) srcp1)[0];
 +      a1 = ((op_t *) srcp1)[1];
 +      b1 = ((op_t *) srcp2)[0];
 +      srcp2 -= 1 * OPSIZ;
 +      len += 1;
 +      goto do2;
 +    case 0:
 +      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
 +      return 0;
 +      a3 = ((op_t *) srcp1)[0];
 +      a0 = ((op_t *) srcp1)[1];
 +      b0 = ((op_t *) srcp2)[0];
 +      srcp1 += 1 * OPSIZ;
 +      goto do3;
 +    case 1:
 +      a2 = ((op_t *) srcp1)[0];
 +      a3 = ((op_t *) srcp1)[1];
 +      b3 = ((op_t *) srcp2)[0];
 +      srcp1 += 2 * OPSIZ;
 +      srcp2 += 1 * OPSIZ;
 +      len -= 1;
 +      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
 +      goto do0;
 +      /* Fall through.  */
 +    }
 +
 +  do
 +    {
 +      a0 = ((op_t *) srcp1)[0];
 +      b0 = ((op_t *) srcp2)[0];
 +      x = MERGE(a2, shl, a3, shr);
 +      if (x != b3)
 +      return CMP_LT_OR_GT (x, b3);
 +
 +    do3:
 +      a1 = ((op_t *) srcp1)[1];
 +      b1 = ((op_t *) srcp2)[1];
 +      x = MERGE(a3, shl, a0, shr);
 +      if (x != b0)
 +      return CMP_LT_OR_GT (x, b0);
 +
 +    do2:
 +      a2 = ((op_t *) srcp1)[2];
 +      b2 = ((op_t *) srcp2)[2];
 +      x = MERGE(a0, shl, a1, shr);
 +      if (x != b1)
 +      return CMP_LT_OR_GT (x, b1);
 +
 +    do1:
 +      a3 = ((op_t *) srcp1)[3];
 +      b3 = ((op_t *) srcp2)[3];
 +      x = MERGE(a1, shl, a2, shr);
 +      if (x != b2)
 +      return CMP_LT_OR_GT (x, b2);
 +
 +      srcp1 += 4 * OPSIZ;
 +      srcp2 += 4 * OPSIZ;
 +      len -= 4;
 +    }
 +  while (len != 0);
 +
 +  /* This is the right position for do0.  Please don't move
 +     it into the loop.  */
 + do0:
 +  x = MERGE(a2, shl, a3, shr);
 +  if (x != b3)
 +    return CMP_LT_OR_GT (x, b3);
 +  return 0;
 +}
 +
 +int
 +rpl_memcmp (s1, s2, len)
 +     const __ptr_t s1;
 +     const __ptr_t s2;
 +     size_t len;
 +{
 +  op_t a0;
 +  op_t b0;
 +  intptr_t srcp1 = (intptr_t) s1;
 +  intptr_t srcp2 = (intptr_t) s2;
 +  op_t res;
 +
 +  if (len >= OP_T_THRES)
 +    {
 +      /* There are at least some bytes to compare.  No need to test
 +       for LEN == 0 in this alignment loop.  */
 +      while (srcp2 % OPSIZ != 0)
 +      {
 +        a0 = ((byte *) srcp1)[0];
 +        b0 = ((byte *) srcp2)[0];
 +        srcp1 += 1;
 +        srcp2 += 1;
 +        res = a0 - b0;
 +        if (res != 0)
 +          return res;
 +        len -= 1;
 +      }
 +
 +      /* SRCP2 is now aligned for memory operations on `op_t'.
 +       SRCP1 alignment determines if we can do a simple,
 +       aligned compare or need to shuffle bits.  */
 +
 +      if (srcp1 % OPSIZ == 0)
 +      res = memcmp_common_alignment (srcp1, srcp2, len / OPSIZ);
 +      else
 +      res = memcmp_not_common_alignment (srcp1, srcp2, len / OPSIZ);
 +      if (res != 0)
 +      return res;
 +
 +      /* Number of bytes remaining in the interval [0..OPSIZ-1].  */
 +      srcp1 += len & -OPSIZ;
 +      srcp2 += len & -OPSIZ;
 +      len %= OPSIZ;
 +    }
 +
 +  /* There are just a few bytes to compare.  Use byte memory operations.  */
 +  while (len != 0)
 +    {
 +      a0 = ((byte *) srcp1)[0];
 +      b0 = ((byte *) srcp2)[0];
 +      srcp1 += 1;
 +      srcp2 += 1;
 +      res = a0 - b0;
 +      if (res != 0)
 +      return res;
 +      len -= 1;
 +    }
 +
 +  return 0;
 +}
 +
 +#ifdef weak_alias
 +# undef bcmp
 +weak_alias (memcmp, bcmp)
 +#endif
Simple merge
diff --cc src/net.c
Simple merge
index 7be466201eae816acca0d52ab3fd6ddcff545f92,c7efa8869e9d1d3ae544b007be368f9b13f60022..ded80a2fb94272bb98eaf5a9bdcad34dce739007
@@@ -551,32 -572,38 +561,44 @@@ void broadcast_packet(const node_t *fro
  }
  
  static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) {
 -      avl_node_t *node;
 +      splay_node_t *node;
-       node_t *n, *found = NULL;
+       edge_t *e;
+       node_t *n = NULL;
+       bool hard = false;
        static time_t last_hard_try = 0;
 +      time_t now = time(NULL);
 +
 +      if(last_hard_try == now)
 +              return NULL;
 +      else
 +              last_hard_try = now;
  
-       for(node = node_tree->head; node; node = node->next) {
-               n = node->data;
+       for(node = edge_weight_tree->head; node; node = node->next) {
+               e = node->data;
  
-               if(n == myself || !n->status.reachable || !digest_active(&n->indigest))
+               if(e->to == myself)
                        continue;
  
-               if(try_mac(n, pkt)) {
-                       found = n;
-                       break;
+               if(sockaddrcmp_noport(from, &e->address)) {
+                       if(last_hard_try == now)
+                               continue;
+                       hard = true;
                }
+               if(!try_mac(e->to, pkt))
+                       continue;
+               n = e->to;
+               break;
        }
  
-       return found;
+       if(hard)
+               last_hard_try = now;
+       return n;
  }
  
 -void handle_incoming_vpn_data(int sock) {
 +void handle_incoming_vpn_data(int sock, short events, void *data) {
        vpn_packet_t pkt;
        char *hostname;
        sockaddr_t from;
diff --cc src/netutl.c
Simple merge
diff --cc src/node.c
index 862bd69693ca9707e2ebd01076806e0e1bec43cf,36979ef375df6b0c8957a7b33e2fb2b82a57e8ee..9281178b582351057d69d7827b11e57cb3e608ff
@@@ -142,7 -141,12 +142,12 @@@ node_t *lookup_node_udp(const sockaddr_
  }
  
  void update_node_udp(node_t *n, const sockaddr_t *sa) {
 -      avl_delete(node_udp_tree, n);
+       if(n == myself) {
+               logger(LOG_WARNING, "Trying to update UDP address of myself!\n");
+               return;
+       }
 +      splay_delete(node_udp_tree, n);
  
        if(n->hostname)
                free(n->hostname);
diff --cc src/process.c
index d588a3fd830f50e8d7510d5fb9cd9eb4493f7dd3,e74c1d9aea7c0cd8b3a40120b8dfdd9811560ffb..737a75e2a4f8dfbc9298247c3e3eb83a1458ef51
@@@ -386,7 -540,13 +386,8 @@@ static struct 
        {SIGBUS, fatal_signal_handler},
        {SIGILL, fatal_signal_handler},
        {SIGPIPE, ignore_signal_handler},
 -      {SIGINT, sigint_handler},
 -      {SIGUSR1, sigusr1_handler},
 -      {SIGUSR2, sigusr2_handler},
        {SIGCHLD, ignore_signal_handler},
 -      {SIGALRM, sigalrm_handler},
 -      {SIGWINCH, sigwinch_handler},
+       {SIGABRT, SIG_DFL},
        {0, NULL}
  };
  #endif
Simple merge
Simple merge
diff --cc src/tincd.c
Simple merge