AUTOMAKE_OPTIONS = gnu
-SUBDIRS = m4 lib src doc
+SUBDIRS = m4 src doc
ACLOCAL_AMFLAGS = -I m4
-EXTRA_DIST = have.h system.h COPYING.README README.android
+EXTRA_DIST = COPYING.README README.android
ChangeLog:
git log > ChangeLog
-
-deb:
- dpkg-buildpackage -rfakeroot
-
-rpm: dist
- cp $(distdir).tar.gz /usr/src/redhat/SOURCES/
- cp redhat/tinc.spec /usr/src/redhat/SOURCES/
- cd /usr/src/redhat/SOURCES/ && rpm -bb tinc.spec
-
-release:
- rm -f ChangeLog
- $(MAKE) ChangeLog
- echo "Please edit the NEWS file now..."
- /usr/bin/editor NEWS
- $(MAKE) dist
--- /dev/null
+dnl Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.61)
+AC_INIT([tinc], [1.0.22])
+AC_CONFIG_SRCDIR([src/tincd.c])
+AM_INIT_AUTOMAKE([1.11 check-news std-options subdir-objects nostdinc -Wall])
+AC_CONFIG_HEADERS([config.h])
+AM_MAINTAINER_MODE
+
+# Enable GNU extensions.
+# Define this here, not in acconfig's @TOP@ section, since definitions
+# in the latter don't make it into the configure-time tests.
+AC_GNU_SOURCE
+AC_DEFINE([__USE_BSD], 1, [Enable BSD extensions])
+
+dnl Checks for programs.
+AC_PROG_CC_C99
+AC_PROG_CPP
+AC_PROG_INSTALL
+
+dnl Check and set OS
+
+AC_CANONICAL_HOST
+
+case $host_os in
+ *linux*)
+ linux=true
+ AC_DEFINE(HAVE_LINUX, 1, [Linux])
+ ;;
+ *freebsd*)
+ bsd=true
+ AC_DEFINE(HAVE_FREEBSD, 1, [FreeBSD])
+ ;;
+ *darwin*)
+ bsd=true
+ AC_DEFINE(HAVE_DARWIN, 1, [Darwin (MacOS/X)])
+ ;;
+ *solaris*)
+ solaris=true
+ AC_DEFINE(HAVE_SOLARIS, 1, [Solaris/SunOS])
+ ;;
+ *openbsd*)
+ bsd=true
+ AC_DEFINE(HAVE_OPENBSD, 1, [OpenBSD])
+ ;;
+ *netbsd*)
+ bsd=true
+ AC_DEFINE(HAVE_NETBSD, 1, [NetBSD])
+ ;;
+ *dragonfly*)
+ bsd=true
+ AC_DEFINE(HAVE_DRAGONFLY, 1, [DragonFly])
+ ;;
+ *bsd*)
+ bsd=true
+ AC_MSG_WARN("Unknown BSD variant, tinc might not compile or work!")
+ AC_DEFINE(HAVE_BSD, 1, [Unknown BSD variant])
+ ;;
+ *cygwin*)
+ cygwin=true
+ AC_DEFINE(HAVE_CYGWIN, 1, [Cygwin])
+ ;;
+ *mingw*)
+ mingw=true
+ AC_DEFINE(HAVE_MINGW, 1, [MinGW])
+ LIBS="$LIBS -lws2_32 -lgdi32 -lcrypt32"
+ ;;
+ *)
+ AC_MSG_ERROR("Unknown operating system.")
+ ;;
+esac
+
+AC_ARG_ENABLE(uml,
+ AS_HELP_STRING([--enable-uml], [enable support for User Mode Linux]),
+ [ AS_IF([test "x$enable_uml" = "xyes"],
+ [ AC_DEFINE(ENABLE_UML, 1, [Support for UML])
+ uml=true
+ ],
+ [uml=false])
+ ],
+ [uml=false]
+)
+
+AC_ARG_ENABLE(vde,
+ AS_HELP_STRING([--enable-vde], [enable support for Virtual Distributed Ethernet]),
+ [ AS_IF([test "x$enable_vde" = "xyes"],
+ [ AC_CHECK_HEADERS(libvdeplug_dyn.h, [], [AC_MSG_ERROR([VDE plug header files not found.]); break])
+ AC_DEFINE(ENABLE_VDE, 1, [Support for VDE])
+ vde=true
+ ],
+ [vde=false])
+ ],
+ [vde=false]
+)
+
+AC_ARG_ENABLE(tunemu,
+ AS_HELP_STRING([--enable-tunemu], [enable support for the tunemu driver]),
+ [ AS_IF([test "x$enable_tunemu" = "xyes"],
+ [ AC_DEFINE(ENABLE_TUNEMU, 1, [Support for tunemu])
+ tunemu=true
+ ],
+ [tunemu=false])
+ ],
+ [tunemu=false]
+)
+
+AC_ARG_WITH(windows2000,
+ AS_HELP_STRING([--without-windows2000], [compile with support for Windows 2000. This disables support for tunneling over existing IPv6 networks.]),
+ [ AS_IF([test "x$with_windows2000" = "xyes"],
+ [AC_DEFINE(WITH_WINDOWS2000, 1, [Compile with support for Windows 2000])])
+ ]
+)
+
+AM_CONDITIONAL(LINUX, test "$linux" = true)
+AM_CONDITIONAL(BSD, test "$bsd" = true)
+AM_CONDITIONAL(SOLARIS, test "$solaris" = true)
+AM_CONDITIONAL(MINGW, test "$mingw" = true)
+AM_CONDITIONAL(CYGWIN, test "$cygwin" = true)
+AM_CONDITIONAL(UML, test "$uml" = true)
+AM_CONDITIONAL(VDE, test "$vde" = true)
+AM_CONDITIONAL(TUNEMU, test "$tunemu" = true)
+
+AC_CACHE_SAVE
+
+if test -d /sw/include ; then
+ CPPFLAGS="$CPPFLAGS -I/sw/include"
+fi
+if test -d /sw/lib ; then
+ LIBS="$LIBS -L/sw/lib"
+fi
+
+dnl Checks for libraries.
+
+dnl Checks for header files.
+dnl We do this in multiple stages, because unlike Linux all the other operating systems really suck and don't include their own dependencies.
+
+AC_HEADER_STDC
+AC_CHECK_HEADERS([stdbool.h syslog.h sys/file.h sys/ioctl.h sys/mman.h sys/param.h sys/resource.h sys/socket.h sys/time.h time.h sys/uio.h sys/wait.h netdb.h arpa/inet.h dirent.h])
+AC_CHECK_HEADERS([net/if.h net/if_types.h linux/if_tun.h net/if_tun.h net/tun/if_tun.h net/if_tap.h net/tap/if_tap.h net/ethernet.h net/if_arp.h netinet/in_systm.h netinet/in.h netinet/in6.h netpacket/packet.h],
+ [], [], [#include "src/have.h"]
+)
+AC_CHECK_HEADERS([netinet/if_ether.h netinet/ip.h netinet/ip6.h],
+ [], [], [#include "src/have.h"]
+)
+AC_CHECK_HEADERS([netinet/tcp.h netinet/ip_icmp.h netinet/icmp6.h],
+ [], [], [#include "src/have.h"]
+)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_C_VOLATILE
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_HEADER_TIME
+AC_STRUCT_TM
+
+tinc_ATTRIBUTE(__malloc__)
+
+AC_CHECK_TYPES([socklen_t, struct ether_header, struct arphdr, struct ether_arp, struct in_addr, struct addrinfo, struct ip, struct icmp, struct in6_addr, struct sockaddr_in6, struct ip6_hdr, struct icmp6_hdr, struct nd_neighbor_solicit, struct nd_opt_hdr], , ,
+ [#include "src/have.h"]
+)
+
+dnl Checks for library functions.
+AC_TYPE_SIGNAL
+AC_CHECK_FUNCS([asprintf daemon fchmod flock ftime fork get_current_dir_name gettimeofday mlockall pselect putenv random select strdup strerror strsignal strtol system unsetenv usleep vsyslog writev],
+ [], [], [#include "src/have.h"]
+)
+
+dnl Support for SunOS
+
+AC_CHECK_FUNC(socket, [], [
+ AC_CHECK_LIB(socket, connect)
+])
+AC_CHECK_FUNC(gethostbyname, [], [
+ AC_CHECK_LIB(nsl, gethostbyname)
+])
+
+AC_CHECK_DECLS([freeaddrinfo, gai_strerror, getaddrinfo, getnameinfo],
+ [], [], [#include "src/have.h"]
+)
+
+AC_CACHE_SAVE
+
+dnl These are defined in files in m4/
+
+tinc_ZLIB
+tinc_LZO
+tinc_OPENSSL
+
+dnl Check if support for jumbograms is requested
+AC_ARG_ENABLE(jumbograms,
+ AS_HELP_STRING([--disable-jumbograms], [enable support for jumbograms (packets up to 9000 bytes)]),
+ [ AS_IF([test "x$enable_jumbograms" = "xyes"],
+ [ AC_DEFINE(ENABLE_JUMBOGRAMS, 1, [Support for jumbograms (packets up to 9000 bytes)]) ])
+ ]
+)
+
+AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile m4/Makefile])
+
+AC_OUTPUT
+++ /dev/null
-dnl Process this file with autoconf to produce a configure script.
-
-AC_PREREQ(2.61)
-AC_INIT
-AC_CONFIG_SRCDIR([src/tincd.c])
-AM_INIT_AUTOMAKE(tinc, 1.0.22)
-AC_CONFIG_HEADERS([config.h])
-AM_MAINTAINER_MODE
-
-# Enable GNU extensions.
-# Define this here, not in acconfig's @TOP@ section, since definitions
-# in the latter don't make it into the configure-time tests.
-AC_GNU_SOURCE
-AC_DEFINE([__USE_BSD], 1, [Enable BSD extensions])
-
-dnl Checks for programs.
-AC_PROG_CC_C99
-AC_PROG_CPP
-AC_PROG_INSTALL
-AC_PROG_LN_S
-AC_PROG_RANLIB
-
-dnl Check and set OS
-
-AC_CANONICAL_HOST
-
-case $host_os in
- *linux*)
- AC_DEFINE(HAVE_LINUX, 1, [Linux])
- [ rm -f src/device.c; ln -sf linux/device.c src/device.c ]
- ;;
- *freebsd*)
- AC_DEFINE(HAVE_FREEBSD, 1, [FreeBSD])
- [ rm -f src/device.c; ln -sf bsd/device.c src/device.c ]
- ;;
- *darwin*)
- AC_DEFINE(HAVE_DARWIN, 1, [Darwin (MacOS/X)])
- [ rm -f src/device.c; ln -sf bsd/device.c src/device.c ]
- ;;
- *solaris*)
- AC_DEFINE(HAVE_SOLARIS, 1, [Solaris/SunOS])
- [ rm -f src/device.c; ln -sf solaris/device.c src/device.c ]
- ;;
- *openbsd*)
- AC_DEFINE(HAVE_OPENBSD, 1, [OpenBSD])
- [ rm -f src/device.c; ln -sf bsd/device.c src/device.c ]
- ;;
- *netbsd*)
- AC_DEFINE(HAVE_NETBSD, 1, [NetBSD])
- [ rm -f src/device.c; ln -sf bsd/device.c src/device.c ]
- ;;
- *dragonfly*)
- AC_DEFINE(HAVE_DRAGONFLY, 1, [DragonFly])
- [ rm -f src/device.c; ln -sf bsd/device.c src/device.c ]
- ;;
- *bsd*)
- AC_MSG_WARN("Unknown BSD variant, tinc might not compile or work!")
- AC_DEFINE(HAVE_BSD, 1, [Unknown BSD variant])
- [ rm -f src/device.c; ln -sf bsd/device.c src/device.c ]
- ;;
- *cygwin*)
- AC_DEFINE(HAVE_CYGWIN, 1, [Cygwin])
- [ rm -f src/device.c; ln -sf cygwin/device.c src/device.c ]
- ;;
- *mingw*)
- AC_DEFINE(HAVE_MINGW, 1, [MinGW])
- [ rm -f src/device.c; cp -f src/mingw/device.c src/device.c ]
- LIBS="$LIBS -lws2_32 -lgdi32 -lcrypt32"
- ;;
- *)
- AC_MSG_ERROR("Unknown operating system.")
- ;;
-esac
-
-AC_ARG_ENABLE(uml,
- AS_HELP_STRING([--enable-uml], [enable support for User Mode Linux]),
- [ AS_IF([test "x$enable_uml" = "xyes"],
- [ AC_DEFINE(ENABLE_UML, 1, [Support for UML])
- uml=true
- ],
- [uml=false])
- ],
- [uml=false]
-)
-
-AC_ARG_ENABLE(vde,
- AS_HELP_STRING([--enable-vde], [enable support for Virtual Distributed Ethernet]),
- [ AS_IF([test "x$enable_vde" = "xyes"],
- [ AC_CHECK_HEADERS(libvdeplug_dyn.h, [], [AC_MSG_ERROR([VDE plug header files not found.]); break])
- AC_DEFINE(ENABLE_VDE, 1, [Support for VDE])
- vde=true
- ],
- [vde=false])
- ],
- [vde=false]
-)
-
-AC_ARG_ENABLE(tunemu,
- AS_HELP_STRING([--enable-tunemu], [enable support for the tunemu driver]),
- [ AS_IF([test "x$enable_tunemu" = "xyes"],
- [ AC_DEFINE(ENABLE_TUNEMU, 1, [Support for tunemu])
- tunemu=true
- ],
- [tunemu=false])
- ],
- [tunemu=false]
-)
-
-AC_ARG_WITH(windows2000,
- AS_HELP_STRING([--without-windows2000], [compile with support for Windows 2000. This disables support for tunneling over existing IPv6 networks.]),
- [ AS_IF([test "x$with_windows2000" = "xyes"],
- [AC_DEFINE(WITH_WINDOWS2000, 1, [Compile with support for Windows 2000])])
- ]
-)
-
-AM_CONDITIONAL(UML, test "$uml" = true)
-AM_CONDITIONAL(VDE, test "$vde" = true)
-AM_CONDITIONAL(TUNEMU, test "$tunemu" = true)
-
-AC_CACHE_SAVE
-
-if test -d /sw/include ; then
- CPPFLAGS="$CPPFLAGS -I/sw/include"
-fi
-if test -d /sw/lib ; then
- LIBS="$LIBS -L/sw/lib"
-fi
-
-dnl Checks for libraries.
-
-dnl Checks for header files.
-dnl We do this in multiple stages, because unlike Linux all the other operating systems really suck and don't include their own dependencies.
-
-AC_HEADER_STDC
-AC_CHECK_HEADERS([stdbool.h syslog.h sys/file.h sys/ioctl.h sys/mman.h sys/param.h sys/resource.h sys/socket.h sys/time.h time.h sys/uio.h sys/wait.h netdb.h arpa/inet.h dirent.h])
-AC_CHECK_HEADERS([net/if.h net/if_types.h linux/if_tun.h net/if_tun.h net/tun/if_tun.h net/if_tap.h net/tap/if_tap.h net/ethernet.h net/if_arp.h netinet/in_systm.h netinet/in.h netinet/in6.h netpacket/packet.h],
- [], [], [#include "have.h"]
-)
-AC_CHECK_HEADERS([netinet/if_ether.h netinet/ip.h netinet/ip6.h],
- [], [], [#include "have.h"]
-)
-AC_CHECK_HEADERS([netinet/tcp.h netinet/ip_icmp.h netinet/icmp6.h],
- [], [], [#include "have.h"]
-)
-
-dnl Checks for typedefs, structures, and compiler characteristics.
-AC_C_CONST
-AC_C_VOLATILE
-AC_TYPE_PID_T
-AC_TYPE_SIZE_T
-AC_HEADER_TIME
-AC_STRUCT_TM
-
-tinc_ATTRIBUTE(__malloc__)
-
-AC_CHECK_TYPES([socklen_t, struct ether_header, struct arphdr, struct ether_arp, struct in_addr, struct addrinfo, struct ip, struct icmp, struct in6_addr, struct sockaddr_in6, struct ip6_hdr, struct icmp6_hdr, struct nd_neighbor_solicit, struct nd_opt_hdr], , ,
- [#include "have.h"]
-)
-
-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 pselect putenv random select strdup strerror strsignal strtol system unsetenv usleep vsyslog writev],
- [], [], [#include "have.h"]
-)
-AC_FUNC_MALLOC
-AC_FUNC_REALLOC
-
-dnl Support for SunOS
-
-AC_CHECK_FUNC(socket, [], [
- AC_CHECK_LIB(socket, connect)
-])
-AC_CHECK_FUNC(gethostbyname, [], [
- AC_CHECK_LIB(nsl, gethostbyname)
-])
-
-AC_CHECK_DECLS([freeaddrinfo, gai_strerror, getaddrinfo, getnameinfo],
- [], [], [#include "have.h"]
-)
-
-AC_CACHE_SAVE
-
-dnl These are defined in files in m4/
-
-tinc_ZLIB
-tinc_LZO
-tinc_OPENSSL
-
-dnl Check if support for jumbograms is requested
-AC_ARG_ENABLE(jumbograms,
- AS_HELP_STRING([--disable-jumbograms], [enable support for jumbograms (packets up to 9000 bytes)]),
- [ AS_IF([test "x$enable_jumbograms" = "xyes"],
- [ AC_DEFINE(ENABLE_JUMBOGRAMS, 1, [Support for jumbograms (packets up to 9000 bytes)]) ])
- ]
-)
-
-AC_SUBST(INCLUDES)
-
-AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile lib/Makefile m4/Makefile])
-
-AC_OUTPUT
EXTRA_DIST = tincinclude.texi.in tincd.8.in tinc.conf.5.in sample-config.tar.gz
-CLEANFILES = *.html tinc.info tincd.8 tinc.conf.5 tincinclude.texi
+CLEANFILES = *.html tincd.8 tinc.conf.5 tincinclude.texi
# Use `ginstall' in the definition of man_MANS to avoid
# confusion with the `install' target. The install rule transforms `ginstall'
+++ /dev/null
-/*
- have.h -- include headers which are known to exist
- Copyright (C) 1998-2005 Ivo Timmermans
- 2003-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 __TINC_HAVE_H__
-#define __TINC_HAVE_H__
-
-#ifdef HAVE_MINGW
-#ifdef WITH_WINDOWS2000
-#define WINVER Windows2000
-#else
-#define WINVER WindowsXP
-#endif
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include <signal.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#ifdef HAVE_MINGW
-#include <w32api.h>
-#include <winsock2.h>
-#include <windows.h>
-#include <ws2tcpip.h>
-#endif
-
-#ifdef HAVE_STDBOOL_H
-#include <stdbool.h>
-#endif
-
-#ifdef HAVE_TERMIOS_H
-#include <termios.h>
-#endif
-
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
-#endif
-
-/* Include system specific headers */
-
-#ifdef HAVE_SYSLOG_H
-#include <syslog.h>
-#endif
-
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-
-#ifdef HAVE_SYS_FILE_H
-#include <sys/file.h>
-#endif
-
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif
-
-#ifdef HAVE_SYS_UIO_H
-#include <sys/uio.h>
-#endif
-
-#ifdef HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-
-/* SunOS really wants sys/socket.h BEFORE net/if.h,
- and FreeBSD wants these lines below the rest. */
-
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
-#ifdef HAVE_NET_IF_H
-#include <net/if.h>
-#endif
-
-#ifdef HAVE_NET_IF_TYPES_H
-#include <net/if_types.h>
-#endif
-
-#ifdef HAVE_NET_IF_TUN_H
-#include <net/if_tun.h>
-#endif
-
-#ifdef HAVE_NET_TUN_IF_TUN_H
-#include <net/tun/if_tun.h>
-#endif
-
-#ifdef HAVE_NET_IF_TAP_H
-#include <net/if_tap.h>
-#endif
-
-#ifdef HAVE_NET_TAP_IF_TAP_H
-#include <net/tap/if_tap.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_SYSTM_H
-#include <netinet/in_systm.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-
-#ifdef HAVE_NETINET_IP_H
-#include <netinet/ip.h>
-#endif
-
-#ifdef HAVE_NETINET_TCP_H
-#include <netinet/tcp.h>
-#endif
-
-#ifdef HAVE_NETINET_IN6_H
-#include <netinet/in6.h>
-#endif
-
-#ifdef HAVE_NETINET_IP6_H
-#include <netinet/ip6.h>
-#endif
-
-#ifdef HAVE_NET_ETHERNET_H
-#include <net/ethernet.h>
-#endif
-
-#ifdef HAVE_NET_IF_ARP_H
-#include <net/if_arp.h>
-#endif
-
-#ifdef HAVE_NETINET_IP_ICMP_H
-#include <netinet/ip_icmp.h>
-#endif
-
-#ifdef HAVE_NETINET_ICMP6_H
-#include <netinet/icmp6.h>
-#endif
-
-#ifdef HAVE_NETINET_IF_ETHER_H
-#include <netinet/if_ether.h>
-#endif
-
-#endif /* __TINC_SYSTEM_H__ */
+++ /dev/null
-## Process this file with automake to produce Makefile.in
-
-noinst_LIBRARIES = libvpn.a
-
-INCLUDES = @INCLUDES@ -I. -I$(top_builddir)
-
-libvpn_a_SOURCES = xmalloc.c pidfile.c utils.c getopt.c getopt1.c list.c avl_tree.c dropin.c fake-getaddrinfo.c fake-getnameinfo.c
-
-libvpn_a_LIBADD = @LIBOBJS@ @ALLOCA@
-libvpn_a_DEPENDENCIES = $(libvpn_a_LIBADD)
-
-noinst_HEADERS = xalloc.h pidfile.h utils.h getopt.h list.h avl_tree.h dropin.h fake-getaddrinfo.h fake-getnameinfo.h fake-gai-errnos.h ipv6.h ipv4.h ethernet.h
-
-EXTRA_DIST =
+++ /dev/null
-/* alloca.c -- allocate automatically reclaimed memory
- (Mostly) portable public-domain implementation -- D A Gwyn
-
- This implementation of the PWB library alloca function,
- which is used to allocate space off the run-time stack so
- that it is automatically reclaimed upon procedure exit,
- was inspired by discussions with J. Q. Johnson of Cornell.
- J.Otto Tennant <jot@cray.com> contributed the Cray support.
-
- There are some preprocessor constants that can
- be defined when compiling for your specific system, for
- improved efficiency; however, the defaults should be okay.
-
- The general concept of this implementation is to keep
- track of all alloca-allocated blocks, and reclaim any
- that are found to be deeper in the stack than the current
- invocation. This heuristic does not reclaim storage as
- soon as it becomes invalid, but it will do so eventually.
-
- As a special case, alloca(0) reclaims storage without
- allocating any. It is a good idea to use alloca(0) in
- your main control loop, etc. to force garbage collection. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#ifdef emacs
-# include "blockinput.h"
-#endif
-
-/* If compiling with GCC 2, this file's not needed. */
-#if !defined (__GNUC__) || __GNUC__ < 2
-
-/* If someone has defined alloca as a macro,
- there must be some other way alloca is supposed to work. */
-# ifndef alloca
-
-# ifdef emacs
-# ifdef static
-/* actually, only want this if static is defined as ""
- -- this is for usg, in which emacs must undefine static
- in order to make unexec workable
- */
-# ifndef STACK_DIRECTION
-you
-lose
--- must know STACK_DIRECTION at compile-time
-# endif /* STACK_DIRECTION undefined */
-# endif /* static */
-# endif /* emacs */
-
-/* If your stack is a linked list of frames, you have to
- provide an "address metric" ADDRESS_FUNCTION macro. */
-
-# if defined (CRAY) && defined (CRAY_STACKSEG_END)
-long i00afunc ();
-# define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
-# else
-# define ADDRESS_FUNCTION(arg) &(arg)
-# endif
-
-# if __STDC__
-typedef void *pointer;
-# else
-typedef char *pointer;
-# endif
-
-# ifndef NULL
-# define NULL 0
-# endif
-
-/* Different portions of Emacs need to call different versions of
- malloc. The Emacs executable needs alloca to call xmalloc, because
- ordinary malloc isn't protected from input signals. On the other
- hand, the utilities in lib-src need alloca to call malloc; some of
- them are very simple, and don't have an xmalloc routine.
-
- Non-Emacs programs expect this to call xmalloc.
-
- Callers below should use malloc. */
-
-# ifndef emacs
-# define malloc xmalloc
-# endif
-extern pointer malloc ();
-
-/* Define STACK_DIRECTION if you know the direction of stack
- growth for your system; otherwise it will be automatically
- deduced at run-time.
-
- STACK_DIRECTION > 0 => grows toward higher addresses
- STACK_DIRECTION < 0 => grows toward lower addresses
- STACK_DIRECTION = 0 => direction of growth unknown */
-
-# ifndef STACK_DIRECTION
-# define STACK_DIRECTION 0 /* Direction unknown. */
-# endif
-
-# if STACK_DIRECTION != 0
-
-# define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
-
-# else /* STACK_DIRECTION == 0; need run-time code. */
-
-static int stack_dir; /* 1 or -1 once known. */
-# define STACK_DIR stack_dir
-
-static void
-find_stack_direction ()
-{
- static char *addr = NULL; /* Address of first `dummy', once known. */
- auto char dummy; /* To get stack address. */
-
- if (addr == NULL)
- { /* Initial entry. */
- addr = ADDRESS_FUNCTION (dummy);
-
- find_stack_direction (); /* Recurse once. */
- }
- else
- {
- /* Second entry. */
- if (ADDRESS_FUNCTION (dummy) > addr)
- stack_dir = 1; /* Stack grew upward. */
- else
- stack_dir = -1; /* Stack grew downward. */
- }
-}
-
-# endif /* STACK_DIRECTION == 0 */
-
-/* An "alloca header" is used to:
- (a) chain together all alloca'ed blocks;
- (b) keep track of stack depth.
-
- It is very important that sizeof(header) agree with malloc
- alignment chunk size. The following default should work okay. */
-
-# ifndef ALIGN_SIZE
-# define ALIGN_SIZE sizeof(double)
-# endif
-
-typedef union hdr
-{
- char align[ALIGN_SIZE]; /* To force sizeof(header). */
- struct
- {
- union hdr *next; /* For chaining headers. */
- char *deep; /* For stack depth measure. */
- } h;
-} header;
-
-static header *last_alloca_header = NULL; /* -> last alloca header. */
-
-/* Return a pointer to at least SIZE bytes of storage,
- which will be automatically reclaimed upon exit from
- the procedure that called alloca. Originally, this space
- was supposed to be taken from the current stack frame of the
- caller, but that method cannot be made to work for some
- implementations of C, for example under Gould's UTX/32. */
-
-pointer
-alloca (size)
- unsigned size;
-{
- auto char probe; /* Probes stack depth: */
- register char *depth = ADDRESS_FUNCTION (probe);
-
-# if STACK_DIRECTION == 0
- if (STACK_DIR == 0) /* Unknown growth direction. */
- find_stack_direction ();
-# endif
-
- /* Reclaim garbage, defined as all alloca'd storage that
- was allocated from deeper in the stack than currently. */
-
- {
- register header *hp; /* Traverses linked list. */
-
-# ifdef emacs
- BLOCK_INPUT;
-# endif
-
- for (hp = last_alloca_header; hp != NULL;)
- if ((STACK_DIR > 0 && hp->h.deep > depth)
- || (STACK_DIR < 0 && hp->h.deep < depth))
- {
- register header *np = hp->h.next;
-
- free ((pointer) hp); /* Collect garbage. */
-
- hp = np; /* -> next header. */
- }
- else
- break; /* Rest are not deeper. */
-
- last_alloca_header = hp; /* -> last valid storage. */
-
-# ifdef emacs
- UNBLOCK_INPUT;
-# endif
- }
-
- if (size == 0)
- return NULL; /* No allocation required. */
-
- /* Allocate combined header + user data storage. */
-
- {
- register pointer new = malloc (sizeof (header) + size);
- /* Address of header. */
-
- ((header *) new)->h.next = last_alloca_header;
- ((header *) new)->h.deep = depth;
-
- last_alloca_header = (header *) new;
-
- /* User storage begins just after header. */
-
- return (pointer) ((char *) new + sizeof (header));
- }
-}
-
-# if defined (CRAY) && defined (CRAY_STACKSEG_END)
-
-# ifdef DEBUG_I00AFUNC
-# include <stdio.h>
-# endif
-
-# ifndef CRAY_STACK
-# define CRAY_STACK
-# ifndef CRAY2
-/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
-struct stack_control_header
- {
- long shgrow:32; /* Number of times stack has grown. */
- long shaseg:32; /* Size of increments to stack. */
- long shhwm:32; /* High water mark of stack. */
- long shsize:32; /* Current size of stack (all segments). */
- };
-
-/* The stack segment linkage control information occurs at
- the high-address end of a stack segment. (The stack
- grows from low addresses to high addresses.) The initial
- part of the stack segment linkage control information is
- 0200 (octal) words. This provides for register storage
- for the routine which overflows the stack. */
-
-struct stack_segment_linkage
- {
- long ss[0200]; /* 0200 overflow words. */
- long sssize:32; /* Number of words in this segment. */
- long ssbase:32; /* Offset to stack base. */
- long:32;
- long sspseg:32; /* Offset to linkage control of previous
- segment of stack. */
- long:32;
- long sstcpt:32; /* Pointer to task common address block. */
- long sscsnm; /* Private control structure number for
- microtasking. */
- long ssusr1; /* Reserved for user. */
- long ssusr2; /* Reserved for user. */
- long sstpid; /* Process ID for pid based multi-tasking. */
- long ssgvup; /* Pointer to multitasking thread giveup. */
- long sscray[7]; /* Reserved for Cray Research. */
- long ssa0;
- long ssa1;
- long ssa2;
- long ssa3;
- long ssa4;
- long ssa5;
- long ssa6;
- long ssa7;
- long sss0;
- long sss1;
- long sss2;
- long sss3;
- long sss4;
- long sss5;
- long sss6;
- long sss7;
- };
-
-# else /* CRAY2 */
-/* The following structure defines the vector of words
- returned by the STKSTAT library routine. */
-struct stk_stat
- {
- long now; /* Current total stack size. */
- long maxc; /* Amount of contiguous space which would
- be required to satisfy the maximum
- stack demand to date. */
- long high_water; /* Stack high-water mark. */
- long overflows; /* Number of stack overflow ($STKOFEN) calls. */
- long hits; /* Number of internal buffer hits. */
- long extends; /* Number of block extensions. */
- long stko_mallocs; /* Block allocations by $STKOFEN. */
- long underflows; /* Number of stack underflow calls ($STKRETN). */
- long stko_free; /* Number of deallocations by $STKRETN. */
- long stkm_free; /* Number of deallocations by $STKMRET. */
- long segments; /* Current number of stack segments. */
- long maxs; /* Maximum number of stack segments so far. */
- long pad_size; /* Stack pad size. */
- long current_address; /* Current stack segment address. */
- long current_size; /* Current stack segment size. This
- number is actually corrupted by STKSTAT to
- include the fifteen word trailer area. */
- long initial_address; /* Address of initial segment. */
- long initial_size; /* Size of initial segment. */
- };
-
-/* The following structure describes the data structure which trails
- any stack segment. I think that the description in 'asdef' is
- out of date. I only describe the parts that I am sure about. */
-
-struct stk_trailer
- {
- long this_address; /* Address of this block. */
- long this_size; /* Size of this block (does not include
- this trailer). */
- long unknown2;
- long unknown3;
- long link; /* Address of trailer block of previous
- segment. */
- long unknown5;
- long unknown6;
- long unknown7;
- long unknown8;
- long unknown9;
- long unknown10;
- long unknown11;
- long unknown12;
- long unknown13;
- long unknown14;
- };
-
-# endif /* CRAY2 */
-# endif /* not CRAY_STACK */
-
-# ifdef CRAY2
-/* Determine a "stack measure" for an arbitrary ADDRESS.
- I doubt that "lint" will like this much. */
-
-static long
-i00afunc (long *address)
-{
- struct stk_stat status;
- struct stk_trailer *trailer;
- long *block, size;
- long result = 0;
-
- /* We want to iterate through all of the segments. The first
- step is to get the stack status structure. We could do this
- more quickly and more directly, perhaps, by referencing the
- $LM00 common block, but I know that this works. */
-
- STKSTAT (&status);
-
- /* Set up the iteration. */
-
- trailer = (struct stk_trailer *) (status.current_address
- + status.current_size
- - 15);
-
- /* There must be at least one stack segment. Therefore it is
- a fatal error if "trailer" is null. */
-
- if (trailer == 0)
- abort ();
-
- /* Discard segments that do not contain our argument address. */
-
- while (trailer != 0)
- {
- block = (long *) trailer->this_address;
- size = trailer->this_size;
- if (block == 0 || size == 0)
- abort ();
- trailer = (struct stk_trailer *) trailer->link;
- if ((block <= address) && (address < (block + size)))
- break;
- }
-
- /* Set the result to the offset in this segment and add the sizes
- of all predecessor segments. */
-
- result = address - block;
-
- if (trailer == 0)
- {
- return result;
- }
-
- do
- {
- if (trailer->this_size <= 0)
- abort ();
- result += trailer->this_size;
- trailer = (struct stk_trailer *) trailer->link;
- }
- while (trailer != 0);
-
- /* We are done. Note that if you present a bogus address (one
- not in any segment), you will get a different number back, formed
- from subtracting the address of the first block. This is probably
- not what you want. */
-
- return (result);
-}
-
-# else /* not CRAY2 */
-/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
- Determine the number of the cell within the stack,
- given the address of the cell. The purpose of this
- routine is to linearize, in some sense, stack addresses
- for alloca. */
-
-static long
-i00afunc (long address)
-{
- long stkl = 0;
-
- long size, pseg, this_segment, stack;
- long result = 0;
-
- struct stack_segment_linkage *ssptr;
-
- /* Register B67 contains the address of the end of the
- current stack segment. If you (as a subprogram) store
- your registers on the stack and find that you are past
- the contents of B67, you have overflowed the segment.
-
- B67 also points to the stack segment linkage control
- area, which is what we are really interested in. */
-
- stkl = CRAY_STACKSEG_END ();
- ssptr = (struct stack_segment_linkage *) stkl;
-
- /* If one subtracts 'size' from the end of the segment,
- one has the address of the first word of the segment.
-
- If this is not the first segment, 'pseg' will be
- nonzero. */
-
- pseg = ssptr->sspseg;
- size = ssptr->sssize;
-
- this_segment = stkl - size;
-
- /* It is possible that calling this routine itself caused
- a stack overflow. Discard stack segments which do not
- contain the target address. */
-
- while (!(this_segment <= address && address <= stkl))
- {
-# ifdef DEBUG_I00AFUNC
- fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
-# endif
- if (pseg == 0)
- break;
- stkl = stkl - pseg;
- ssptr = (struct stack_segment_linkage *) stkl;
- size = ssptr->sssize;
- pseg = ssptr->sspseg;
- this_segment = stkl - size;
- }
-
- result = address - this_segment;
-
- /* If you subtract pseg from the current end of the stack,
- you get the address of the previous stack segment's end.
- This seems a little convoluted to me, but I'll bet you save
- a cycle somewhere. */
-
- while (pseg != 0)
- {
-# ifdef DEBUG_I00AFUNC
- fprintf (stderr, "%011o %011o\n", pseg, size);
-# endif
- stkl = stkl - pseg;
- ssptr = (struct stack_segment_linkage *) stkl;
- size = ssptr->sssize;
- pseg = ssptr->sspseg;
- result += size;
- }
- return (result);
-}
-
-# endif /* not CRAY2 */
-# endif /* CRAY */
-
-# endif /* no alloca */
-#endif /* not GCC version 2 */
+++ /dev/null
-/*
- avl_tree.c -- avl_ tree and linked list convenience
- Copyright (C) 1998 Michael H. Buselli
- 2000-2005 Ivo Timmermans,
- 2000-2006 Guus Sliepen <guus@tinc-vpn.org>
- 2000-2005 Wessel Dankers <wsl@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.
-
- Original AVL tree library by Michael H. Buselli <cosine@cosine.org>.
-
- Modified 2000-11-28 by Wessel Dankers <wsl@tinc-vpn.org> to use counts
- instead of depths, to add the ->next and ->prev and to generally obfuscate
- the code. Mail me if you found a bug.
-
- Cleaned up and incorporated some of the ideas from the red-black tree
- library for inclusion into tinc (http://www.tinc-vpn.org/) by
- Guus Sliepen <guus@tinc-vpn.org>.
-*/
-
-#include "system.h"
-
-#include "avl_tree.h"
-#include "xalloc.h"
-
-#ifdef AVL_COUNT
-#define AVL_NODE_COUNT(n) ((n) ? (n)->count : 0)
-#define AVL_L_COUNT(n) (AVL_NODE_COUNT((n)->left))
-#define AVL_R_COUNT(n) (AVL_NODE_COUNT((n)->right))
-#define AVL_CALC_COUNT(n) (AVL_L_COUNT(n) + AVL_R_COUNT(n) + 1)
-#endif
-
-#ifdef AVL_DEPTH
-#define AVL_NODE_DEPTH(n) ((n) ? (n)->depth : 0)
-#define L_AVL_DEPTH(n) (AVL_NODE_DEPTH((n)->left))
-#define R_AVL_DEPTH(n) (AVL_NODE_DEPTH((n)->right))
-#define AVL_CALC_DEPTH(n) ((L_AVL_DEPTH(n)>R_AVL_DEPTH(n)?L_AVL_DEPTH(n):R_AVL_DEPTH(n)) + 1)
-#endif
-
-#ifndef AVL_DEPTH
-static int lg(unsigned int u) __attribute__ ((__const__));
-
-static int lg(unsigned int u)
-{
- int r = 1;
-
- if(!u)
- return 0;
-
- if(u & 0xffff0000) {
- u >>= 16;
- r += 16;
- }
-
- if(u & 0x0000ff00) {
- u >>= 8;
- r += 8;
- }
-
- if(u & 0x000000f0) {
- u >>= 4;
- r += 4;
- }
-
- if(u & 0x0000000c) {
- u >>= 2;
- r += 2;
- }
-
- if(u & 0x00000002)
- r++;
-
- return r;
-}
-#endif
-
-/* Internal helper functions */
-
-static int avl_check_balance(const avl_node_t *node)
-{
-#ifdef AVL_DEPTH
- int d;
-
- d = R_AVL_DEPTH(node) - L_AVL_DEPTH(node);
-
- return d < -1 ? -1 : d > 1 ? 1 : 0;
-#else
-/* int d;
- * d = lg(AVL_R_COUNT(node)) - lg(AVL_L_COUNT(node));
- * d = d<-1?-1:d>1?1:0;
- */
- int pl, r;
-
- pl = lg(AVL_L_COUNT(node));
- r = AVL_R_COUNT(node);
-
- if(r >> pl + 1)
- return 1;
-
- if(pl < 2 || r >> pl - 2)
- return 0;
-
- return -1;
-#endif
-}
-
-static void avl_rebalance(avl_tree_t *tree, avl_node_t *node)
-{
- avl_node_t *child;
- avl_node_t *gchild;
- avl_node_t *parent;
- avl_node_t **superparent;
-
- parent = node;
-
- while(node) {
- parent = node->parent;
-
- superparent =
- parent ? node ==
- parent->left ? &parent->left : &parent->right : &tree->root;
-
- switch (avl_check_balance(node)) {
- case -1:
- child = node->left;
-#ifdef AVL_DEPTH
- if(L_AVL_DEPTH(child) >= R_AVL_DEPTH(child)) {
-#else
- if(AVL_L_COUNT(child) >= AVL_R_COUNT(child)) {
-#endif
- node->left = child->right;
- if(node->left)
- node->left->parent = node;
-
- child->right = node;
- node->parent = child;
- *superparent = child;
- child->parent = parent;
-#ifdef AVL_COUNT
- node->count = AVL_CALC_COUNT(node);
- child->count = AVL_CALC_COUNT(child);
-#endif
-#ifdef AVL_DEPTH
- node->depth = AVL_CALC_DEPTH(node);
- child->depth = AVL_CALC_DEPTH(child);
-#endif
- } else {
- gchild = child->right;
- node->left = gchild->right;
-
- if(node->left)
- node->left->parent = node;
- child->right = gchild->left;
-
- if(child->right)
- child->right->parent = child;
- gchild->right = node;
-
- if(gchild->right)
- gchild->right->parent = gchild;
- gchild->left = child;
-
- if(gchild->left)
- gchild->left->parent = gchild;
- *superparent = gchild;
-
- gchild->parent = parent;
-#ifdef AVL_COUNT
- node->count = AVL_CALC_COUNT(node);
- child->count = AVL_CALC_COUNT(child);
- gchild->count = AVL_CALC_COUNT(gchild);
-#endif
-#ifdef AVL_DEPTH
- node->depth = AVL_CALC_DEPTH(node);
- child->depth = AVL_CALC_DEPTH(child);
- gchild->depth = AVL_CALC_DEPTH(gchild);
-#endif
- }
- break;
-
- case 1:
- child = node->right;
-#ifdef AVL_DEPTH
- if(R_AVL_DEPTH(child) >= L_AVL_DEPTH(child)) {
-#else
- if(AVL_R_COUNT(child) >= AVL_L_COUNT(child)) {
-#endif
- node->right = child->left;
- if(node->right)
- node->right->parent = node;
- child->left = node;
- node->parent = child;
- *superparent = child;
- child->parent = parent;
-#ifdef AVL_COUNT
- node->count = AVL_CALC_COUNT(node);
- child->count = AVL_CALC_COUNT(child);
-#endif
-#ifdef AVL_DEPTH
- node->depth = AVL_CALC_DEPTH(node);
- child->depth = AVL_CALC_DEPTH(child);
-#endif
- } else {
- gchild = child->left;
- node->right = gchild->left;
-
- if(node->right)
- node->right->parent = node;
- child->left = gchild->right;
-
- if(child->left)
- child->left->parent = child;
- gchild->left = node;
-
- if(gchild->left)
- gchild->left->parent = gchild;
- gchild->right = child;
-
- if(gchild->right)
- gchild->right->parent = gchild;
-
- *superparent = gchild;
- gchild->parent = parent;
-#ifdef AVL_COUNT
- node->count = AVL_CALC_COUNT(node);
- child->count = AVL_CALC_COUNT(child);
- gchild->count = AVL_CALC_COUNT(gchild);
-#endif
-#ifdef AVL_DEPTH
- node->depth = AVL_CALC_DEPTH(node);
- child->depth = AVL_CALC_DEPTH(child);
- gchild->depth = AVL_CALC_DEPTH(gchild);
-#endif
- }
- break;
-
- default:
-#ifdef AVL_COUNT
- node->count = AVL_CALC_COUNT(node);
-#endif
-#ifdef AVL_DEPTH
- node->depth = AVL_CALC_DEPTH(node);
-#endif
- }
- node = parent;
- }
-}
-
-/* (De)constructors */
-
-avl_tree_t *avl_alloc_tree(avl_compare_t compare, avl_action_t delete)
-{
- avl_tree_t *tree;
-
- tree = xmalloc_and_zero(sizeof(avl_tree_t));
- tree->compare = compare;
- tree->delete = delete;
-
- return tree;
-}
-
-void avl_free_tree(avl_tree_t *tree)
-{
- free(tree);
-}
-
-avl_node_t *avl_alloc_node(void)
-{
- return xmalloc_and_zero(sizeof(avl_node_t));
-}
-
-void avl_free_node(avl_tree_t *tree, avl_node_t *node)
-{
- if(node->data && tree->delete)
- tree->delete(node->data);
-
- free(node);
-}
-
-/* Searching */
-
-void *avl_search(const avl_tree_t *tree, const void *data)
-{
- avl_node_t *node;
-
- node = avl_search_node(tree, data);
-
- return node ? node->data : NULL;
-}
-
-void *avl_search_closest(const avl_tree_t *tree, const void *data, int *result)
-{
- avl_node_t *node;
-
- node = avl_search_closest_node(tree, data, result);
-
- return node ? node->data : NULL;
-}
-
-void *avl_search_closest_smaller(const avl_tree_t *tree, const void *data)
-{
- avl_node_t *node;
-
- node = avl_search_closest_smaller_node(tree, data);
-
- return node ? node->data : NULL;
-}
-
-void *avl_search_closest_greater(const avl_tree_t *tree, const void *data)
-{
- avl_node_t *node;
-
- node = avl_search_closest_greater_node(tree, data);
-
- return node ? node->data : NULL;
-}
-
-avl_node_t *avl_search_node(const avl_tree_t *tree, const void *data)
-{
- avl_node_t *node;
- int result;
-
- node = avl_search_closest_node(tree, data, &result);
-
- return result ? NULL : node;
-}
-
-avl_node_t *avl_search_closest_node(const avl_tree_t *tree, const void *data,
- int *result)
-{
- avl_node_t *node;
- int c;
-
- node = tree->root;
-
- if(!node) {
- if(result)
- *result = 0;
- return NULL;
- }
-
- for(;;) {
- c = tree->compare(data, node->data);
-
- if(c < 0) {
- if(node->left)
- node = node->left;
- else {
- if(result)
- *result = -1;
- break;
- }
- } else if(c > 0) {
- if(node->right)
- node = node->right;
- else {
- if(result)
- *result = 1;
- break;
- }
- } else {
- if(result)
- *result = 0;
- break;
- }
- }
-
- return node;
-}
-
-avl_node_t *avl_search_closest_smaller_node(const avl_tree_t *tree,
- const void *data)
-{
- avl_node_t *node;
- int result;
-
- node = avl_search_closest_node(tree, data, &result);
-
- if(result < 0)
- node = node->prev;
-
- return node;
-}
-
-avl_node_t *avl_search_closest_greater_node(const avl_tree_t *tree,
- const void *data)
-{
- avl_node_t *node;
- int result;
-
- node = avl_search_closest_node(tree, data, &result);
-
- if(result > 0)
- node = node->next;
-
- return node;
-}
-
-/* Insertion and deletion */
-
-avl_node_t *avl_insert(avl_tree_t *tree, void *data)
-{
- avl_node_t *closest, *new;
- int result;
-
- if(!tree->root) {
- new = avl_alloc_node();
- new->data = data;
- avl_insert_top(tree, new);
- } else {
- closest = avl_search_closest_node(tree, data, &result);
-
- switch (result) {
- case -1:
- new = avl_alloc_node();
- new->data = data;
- avl_insert_before(tree, closest, new);
- break;
-
- case 1:
- new = avl_alloc_node();
- new->data = data;
- avl_insert_after(tree, closest, new);
- break;
-
- default:
- return NULL;
- }
- }
-
-#ifdef AVL_COUNT
- new->count = 1;
-#endif
-#ifdef AVL_DEPTH
- new->depth = 1;
-#endif
-
- return new;
-}
-
-avl_node_t *avl_insert_node(avl_tree_t *tree, avl_node_t *node)
-{
- avl_node_t *closest;
- int result;
-
- if(!tree->root)
- avl_insert_top(tree, node);
- else {
- closest = avl_search_closest_node(tree, node->data, &result);
-
- switch (result) {
- case -1:
- avl_insert_before(tree, closest, node);
- break;
-
- case 1:
- avl_insert_after(tree, closest, node);
- break;
-
- case 0:
- return NULL;
- }
- }
-
-#ifdef AVL_COUNT
- node->count = 1;
-#endif
-#ifdef AVL_DEPTH
- node->depth = 1;
-#endif
-
- return node;
-}
-
-void avl_insert_top(avl_tree_t *tree, avl_node_t *node)
-{
- node->prev = node->next = node->parent = NULL;
- tree->head = tree->tail = tree->root = node;
-}
-
-void avl_insert_before(avl_tree_t *tree, avl_node_t *before,
- avl_node_t *node)
-{
- if(!before) {
- if(tree->tail)
- avl_insert_after(tree, tree->tail, node);
- else
- avl_insert_top(tree, node);
- return;
- }
-
- node->next = before;
- node->parent = before;
- node->prev = before->prev;
-
- if(before->left) {
- avl_insert_after(tree, before->prev, node);
- return;
- }
-
- if(before->prev)
- before->prev->next = node;
- else
- tree->head = node;
-
- before->prev = node;
- before->left = node;
-
- avl_rebalance(tree, before);
-}
-
-void avl_insert_after(avl_tree_t *tree, avl_node_t *after, avl_node_t *node)
-{
- if(!after) {
- if(tree->head)
- avl_insert_before(tree, tree->head, node);
- else
- avl_insert_top(tree, node);
- return;
- }
-
- if(after->right) {
- avl_insert_before(tree, after->next, node);
- return;
- }
-
- node->prev = after;
- node->parent = after;
- node->next = after->next;
-
- if(after->next)
- after->next->prev = node;
- else
- tree->tail = node;
-
- after->next = node;
- after->right = node;
-
- avl_rebalance(tree, after);
-}
-
-avl_node_t *avl_unlink(avl_tree_t *tree, void *data)
-{
- avl_node_t *node;
-
- node = avl_search_node(tree, data);
-
- if(node)
- avl_unlink_node(tree, node);
-
- return node;
-}
-
-void avl_unlink_node(avl_tree_t *tree, avl_node_t *node)
-{
- avl_node_t *parent;
- avl_node_t **superparent;
- avl_node_t *subst, *left, *right;
- avl_node_t *balnode;
-
- if(node->prev)
- node->prev->next = node->next;
- else
- tree->head = node->next;
- if(node->next)
- node->next->prev = node->prev;
- else
- tree->tail = node->prev;
-
- parent = node->parent;
-
- superparent =
- parent ? node ==
- parent->left ? &parent->left : &parent->right : &tree->root;
-
- left = node->left;
- right = node->right;
- if(!left) {
- *superparent = right;
-
- if(right)
- right->parent = parent;
-
- balnode = parent;
- } else if(!right) {
- *superparent = left;
- left->parent = parent;
- balnode = parent;
- } else {
- subst = node->prev;
-
- if(subst == left) {
- balnode = subst;
- } else {
- balnode = subst->parent;
- balnode->right = subst->left;
-
- if(balnode->right)
- balnode->right->parent = balnode;
-
- subst->left = left;
- left->parent = subst;
- }
-
- subst->right = right;
- subst->parent = parent;
- right->parent = subst;
- *superparent = subst;
- }
-
- 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)
-{
- avl_unlink_node(tree, node);
- avl_free_node(tree, node);
-}
-
-void avl_delete(avl_tree_t *tree, void *data)
-{
- avl_node_t *node;
-
- node = avl_search_node(tree, data);
-
- if(node)
- avl_delete_node(tree, node);
-}
-
-/* Fast tree cleanup */
-
-void avl_delete_tree(avl_tree_t *tree)
-{
- avl_node_t *node, *next;
-
- for(node = tree->head; node; node = next) {
- next = node->next;
- avl_free_node(tree, node);
- }
-
- avl_free_tree(tree);
-}
-
-/* Tree walking */
-
-void avl_foreach(const avl_tree_t *tree, avl_action_t action)
-{
- avl_node_t *node, *next;
-
- for(node = tree->head; node; node = next) {
- next = node->next;
- action(node->data);
- }
-}
-
-void avl_foreach_node(const avl_tree_t *tree, avl_action_t action)
-{
- avl_node_t *node, *next;
-
- for(node = tree->head; node; node = next) {
- next = node->next;
- action(node);
- }
-}
-
-/* Indexing */
-
-#ifdef AVL_COUNT
-unsigned int avl_count(const avl_tree_t *tree)
-{
- return AVL_NODE_COUNT(tree->root);
-}
-
-avl_node_t *avl_get_node(const avl_tree_t *tree, unsigned int index)
-{
- avl_node_t *node;
- unsigned int c;
-
- node = tree->root;
-
- while(node) {
- c = AVL_L_COUNT(node);
-
- if(index < c) {
- node = node->left;
- } else if(index > c) {
- node = node->right;
- index -= c + 1;
- } else {
- return node;
- }
- }
-
- return NULL;
-}
-
-unsigned int avl_index(const avl_node_t *node)
-{
- avl_node_t *next;
- unsigned int index;
-
- index = AVL_L_COUNT(node);
-
- while((next = node->parent)) {
- if(node == next->right)
- index += AVL_L_COUNT(next) + 1;
- node = next;
- }
-
- return index;
-}
-#endif
-#ifdef AVL_DEPTH
-unsigned int avl_depth(const avl_tree_t *tree)
-{
- return AVL_NODE_DEPTH(tree->root);
-}
-#endif
+++ /dev/null
-/*
- avl_tree.h -- header file for avl_tree.c
- Copyright (C) 1998 Michael H. Buselli
- 2000-2005 Ivo Timmermans,
- 2000-2006 Guus Sliepen <guus@tinc-vpn.org>
- 2000-2005 Wessel Dankers <wsl@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.
-
- Original AVL tree library by Michael H. Buselli <cosine@cosine.org>.
-
- Modified 2000-11-28 by Wessel Dankers <wsl@tinc-vpn.org> to use counts
- instead of depths, to add the ->next and ->prev and to generally obfuscate
- the code. Mail me if you found a bug.
-
- Cleaned up and incorporated some of the ideas from the red-black tree
- library for inclusion into tinc (http://www.tinc-vpn.org/) by
- Guus Sliepen <guus@tinc-vpn.org>.
-*/
-
-
-#ifndef __AVL_TREE_H__
-#define __AVL_TREE_H__
-
-#ifndef AVL_DEPTH
-#ifndef AVL_COUNT
-#define AVL_DEPTH
-#endif
-#endif
-
-typedef struct avl_node_t {
-
- /* Linked list part */
-
- struct avl_node_t *next;
- struct avl_node_t *prev;
-
- /* Tree part */
-
- struct avl_node_t *parent;
- struct avl_node_t *left;
- struct avl_node_t *right;
-
-#ifdef AVL_COUNT
- unsigned int count;
-#endif
-#ifdef AVL_DEPTH
- unsigned char depth;
-#endif
-
- /* Payload */
-
- void *data;
-
-} avl_node_t;
-
-typedef int (*avl_compare_t)(const void *, const void *);
-typedef void (*avl_action_t)(const void *);
-typedef void (*avl_action_node_t)(const avl_node_t *);
-
-typedef struct avl_tree_t {
-
- /* Linked list part */
-
- avl_node_t *head;
- avl_node_t *tail;
-
- /* Tree part */
-
- avl_node_t *root;
-
- avl_compare_t compare;
- avl_action_t delete;
-
-} avl_tree_t;
-
-/* (De)constructors */
-
-extern avl_tree_t *avl_alloc_tree(avl_compare_t, avl_action_t);
-extern void avl_free_tree(avl_tree_t *);
-
-extern avl_node_t *avl_alloc_node(void);
-extern void avl_free_node(avl_tree_t *tree, avl_node_t *);
-
-/* Insertion and deletion */
-
-extern avl_node_t *avl_insert(avl_tree_t *, void *);
-extern avl_node_t *avl_insert_node(avl_tree_t *, avl_node_t *);
-
-extern void avl_insert_top(avl_tree_t *, avl_node_t *);
-extern void avl_insert_before(avl_tree_t *, avl_node_t *, avl_node_t *);
-extern void avl_insert_after(avl_tree_t *, avl_node_t *, avl_node_t *);
-
-extern avl_node_t *avl_unlink(avl_tree_t *, void *);
-extern void avl_unlink_node(avl_tree_t *tree, avl_node_t *);
-extern void avl_delete(avl_tree_t *, void *);
-extern void avl_delete_node(avl_tree_t *, avl_node_t *);
-
-/* Fast tree cleanup */
-
-extern void avl_delete_tree(avl_tree_t *);
-
-/* Searching */
-
-extern void *avl_search(const avl_tree_t *, const void *);
-extern void *avl_search_closest(const avl_tree_t *, const void *, int *);
-extern void *avl_search_closest_smaller(const avl_tree_t *, const void *);
-extern void *avl_search_closest_greater(const avl_tree_t *, const void *);
-
-extern avl_node_t *avl_search_node(const avl_tree_t *, const void *);
-extern avl_node_t *avl_search_closest_node(const avl_tree_t *, const void *, int *);
-extern avl_node_t *avl_search_closest_smaller_node(const avl_tree_t *, const void *);
-extern avl_node_t *avl_search_closest_greater_node(const avl_tree_t *, const void *);
-
-/* Tree walking */
-
-extern void avl_foreach(const avl_tree_t *, avl_action_t);
-extern void avl_foreach_node(const avl_tree_t *, avl_action_t);
-
-/* Indexing */
-
-#ifdef AVL_COUNT
-extern unsigned int avl_count(const avl_tree_t *);
-extern avl_node_t *avl_get_node(const avl_tree_t *, unsigned int);
-extern unsigned int avl_index(const avl_node_t *);
-#endif
-#ifdef AVL_DEPTH
-extern unsigned int avl_depth(const avl_tree_t *);
-#endif
-
-#endif /* __AVL_TREE_H__ */
+++ /dev/null
-/*
- dropin.c -- a set of drop-in replacements for libc functions
- 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.
-*/
-
-#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
-
-#ifndef HAVE_USLEEP
-int usleep(long long usec) {
- struct timeval tv = {usec / 1000000, (usec / 1000) % 1000};
- select(0, NULL, NULL, NULL, &tv);
- return 0;
-}
-#endif
+++ /dev/null
-/*
- 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
-
-#ifndef HAVE_USLEEP
-extern int usleep(long long);
-#endif
-
-#endif /* __DROPIN_H__ */
+++ /dev/null
-/*
- ethernet.h -- missing Ethernet related definitions
- Copyright (C) 2005 Ivo Timmermans
- 2006 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 __TINC_ETHERNET_H__
-#define __TINC_ETHERNET_H__
-
-#ifndef ETH_ALEN
-#define ETH_ALEN 6
-#endif
-
-#ifndef ARPHRD_ETHER
-#define ARPHRD_ETHER 1
-#endif
-
-#ifndef ETH_P_IP
-#define ETH_P_IP 0x0800
-#endif
-
-#ifndef ETH_P_ARP
-#define ETH_P_ARP 0x0806
-#endif
-
-#ifndef ETH_P_IPV6
-#define ETH_P_IPV6 0x86DD
-#endif
-
-#ifndef ETH_P_8021Q
-#define ETH_P_8021Q 0x8100
-#endif
-
-#ifndef HAVE_STRUCT_ETHER_HEADER
-struct ether_header {
- uint8_t ether_dhost[ETH_ALEN];
- uint8_t ether_shost[ETH_ALEN];
- uint16_t ether_type;
-} __attribute__ ((__packed__));
-#endif
-
-#ifndef HAVE_STRUCT_ARPHDR
-struct arphdr {
- uint16_t ar_hrd;
- uint16_t ar_pro;
- uint8_t ar_hln;
- uint8_t ar_pln;
- uint16_t ar_op;
-} __attribute__ ((__packed__));
-
-#define ARPOP_REQUEST 1
-#define ARPOP_REPLY 2
-#define ARPOP_RREQUEST 3
-#define ARPOP_RREPLY 4
-#define ARPOP_InREQUEST 8
-#define ARPOP_InREPLY 9
-#define ARPOP_NAK 10
-#endif
-
-#ifndef HAVE_STRUCT_ETHER_ARP
-struct ether_arp {
- struct arphdr ea_hdr;
- uint8_t arp_sha[ETH_ALEN];
- uint8_t arp_spa[4];
- uint8_t arp_tha[ETH_ALEN];
- uint8_t arp_tpa[4];
-} __attribute__ ((__packed__));
-#define arp_hrd ea_hdr.ar_hrd
-#define arp_pro ea_hdr.ar_pro
-#define arp_hln ea_hdr.ar_hln
-#define arp_pln ea_hdr.ar_pln
-#define arp_op ea_hdr.ar_op
-#endif
-
-#endif /* __TINC_ETHERNET_H__ */
+++ /dev/null
-/*
- * fake library for ssh
- *
- * This file is included in getaddrinfo.c and getnameinfo.c.
- * See getaddrinfo.c and getnameinfo.c.
- */
-
-/* for old netdb.h */
-#ifndef EAI_NODATA
-#define EAI_NODATA 1
-#endif
-
-#ifndef EAI_MEMORY
-#define EAI_MEMORY 2
-#endif
-
-#ifndef EAI_FAMILY
-#define EAI_FAMILY 3
-#endif
+++ /dev/null
-/*
- * fake library for ssh
- *
- * This file includes getaddrinfo(), freeaddrinfo() and gai_strerror().
- * These funtions are defined in rfc2133.
- *
- * But these functions are not implemented correctly. The minimum subset
- * is implemented for ssh use only. For exapmle, this routine assumes
- * that ai_family is AF_INET. Don't use it for another purpose.
- */
-
-#include "system.h"
-
-#include "ipv4.h"
-#include "ipv6.h"
-#include "fake-getaddrinfo.h"
-#include "xalloc.h"
-
-#if !HAVE_DECL_GAI_STRERROR
-char *gai_strerror(int ecode)
-{
- switch (ecode) {
- case EAI_NODATA:
- return "No address associated with hostname";
- case EAI_MEMORY:
- return "Memory allocation failure";
- case EAI_FAMILY:
- return "Address family not supported";
- default:
- return "Unknown error";
- }
-}
-#endif /* !HAVE_GAI_STRERROR */
-
-#if !HAVE_DECL_FREEADDRINFO
-void freeaddrinfo(struct addrinfo *ai)
-{
- struct addrinfo *next;
-
- while(ai) {
- next = ai->ai_next;
- free(ai);
- ai = next;
- }
-}
-#endif /* !HAVE_FREEADDRINFO */
-
-#if !HAVE_DECL_GETADDRINFO
-static struct addrinfo *malloc_ai(uint16_t port, uint32_t addr)
-{
- struct addrinfo *ai;
-
- ai = xmalloc_and_zero(sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
-
- ai->ai_addr = (struct sockaddr *)(ai + 1);
- ai->ai_addrlen = sizeof(struct sockaddr_in);
- ai->ai_addr->sa_family = ai->ai_family = AF_INET;
-
- ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
- ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
-
- return ai;
-}
-
-int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
-{
- struct addrinfo *prev = NULL;
- struct hostent *hp;
- struct in_addr in = {0};
- int i;
- uint16_t port = 0;
-
- if(hints && hints->ai_family != AF_INET && hints->ai_family != AF_UNSPEC)
- return EAI_FAMILY;
-
- if (servname)
- port = htons(atoi(servname));
-
- if (hints && hints->ai_flags & AI_PASSIVE) {
- *res = malloc_ai(port, htonl(0x00000000));
- return 0;
- }
-
- if (!hostname) {
- *res = malloc_ai(port, htonl(0x7f000001));
- return 0;
- }
-
- hp = gethostbyname(hostname);
-
- if(!hp || !hp->h_addr_list || !hp->h_addr_list[0])
- return EAI_NODATA;
-
- for (i = 0; hp->h_addr_list[i]; i++) {
- *res = malloc_ai(port, ((struct in_addr *)hp->h_addr_list[i])->s_addr);
-
- if(prev)
- prev->ai_next = *res;
-
- prev = *res;
- }
-
- return 0;
-}
-#endif /* !HAVE_GETADDRINFO */
+++ /dev/null
-#ifndef _FAKE_GETADDRINFO_H
-#define _FAKE_GETADDRINFO_H
-
-#include "fake-gai-errnos.h"
-
-#ifndef AI_PASSIVE
-# define AI_PASSIVE 1
-# define AI_CANONNAME 2
-#endif
-
-#ifndef NI_NUMERICHOST
-# define NI_NUMERICHOST 2
-# define NI_NAMEREQD 4
-# define NI_NUMERICSERV 8
-#endif
-
-#ifndef AI_NUMERICHOST
-#define AI_NUMERICHOST 4
-#endif
-
-#ifndef HAVE_STRUCT_ADDRINFO
-struct addrinfo {
- int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
- int ai_family; /* PF_xxx */
- int ai_socktype; /* SOCK_xxx */
- int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
- size_t ai_addrlen; /* length of ai_addr */
- char *ai_canonname; /* canonical name for hostname */
- struct sockaddr *ai_addr; /* binary address */
- struct addrinfo *ai_next; /* next structure in linked list */
-};
-#endif /* !HAVE_STRUCT_ADDRINFO */
-
-#if !HAVE_DECL_GETADDRINFO
-int getaddrinfo(const char *hostname, const char *servname,
- const struct addrinfo *hints, struct addrinfo **res);
-#endif /* !HAVE_GETADDRINFO */
-
-#if !HAVE_DECL_GAI_STRERROR
-char *gai_strerror(int ecode);
-#endif /* !HAVE_GAI_STRERROR */
-
-#if !HAVE_DECL_FREEADDRINFO
-void freeaddrinfo(struct addrinfo *ai);
-#endif /* !HAVE_FREEADDRINFO */
-
-#endif /* _FAKE_GETADDRINFO_H */
+++ /dev/null
-/*
- * fake library for ssh
- *
- * This file includes getnameinfo().
- * These funtions are defined in rfc2133.
- *
- * But these functions are not implemented correctly. The minimum subset
- * is implemented for ssh use only. For exapmle, this routine assumes
- * that ai_family is AF_INET. Don't use it for another purpose.
- */
-
-#include "system.h"
-
-#include "fake-getnameinfo.h"
-#include "fake-getaddrinfo.h"
-
-#if !HAVE_DECL_GETNAMEINFO
-
-int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags)
-{
- struct sockaddr_in *sin = (struct sockaddr_in *)sa;
- struct hostent *hp;
- int len;
-
- if(sa->sa_family != AF_INET)
- return EAI_FAMILY;
-
- if(serv && servlen) {
- len = snprintf(serv, servlen, "%d", ntohs(sin->sin_port));
- if(len < 0 || len >= servlen)
- return EAI_MEMORY;
- }
-
- if(!host || !hostlen)
- return 0;
-
- if(flags & NI_NUMERICHOST) {
- len = snprintf(host, hostlen, "%s", inet_ntoa(sin->sin_addr));
- if(len < 0 || len >= hostlen)
- return EAI_MEMORY;
- return 0;
- }
-
- hp = gethostbyaddr((char *)&sin->sin_addr, sizeof(struct in_addr), AF_INET);
-
- if(!hp || !hp->h_name || !hp->h_name[0])
- return EAI_NODATA;
-
- len = snprintf(host, hostlen, "%s", hp->h_name);
- if(len < 0 || len >= hostlen)
- return EAI_MEMORY;
-
- return 0;
-}
-#endif /* !HAVE_GETNAMEINFO */
+++ /dev/null
-#ifndef _FAKE_GETNAMEINFO_H
-#define _FAKE_GETNAMEINFO_H
-
-#if !HAVE_DECL_GETNAMEINFO
-int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
- size_t hostlen, char *serv, size_t servlen, int flags);
-#endif /* !HAVE_GETNAMEINFO */
-
-#ifndef NI_MAXSERV
-# define NI_MAXSERV 32
-#endif /* !NI_MAXSERV */
-#ifndef NI_MAXHOST
-# define NI_MAXHOST 1025
-#endif /* !NI_MAXHOST */
-
-#endif /* _FAKE_GETNAMEINFO_H */
+++ /dev/null
-/* Getopt for GNU.
- NOTE: getopt is now part of the C library, so if you don't know what
- "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
- before changing it!
-
- Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97
- Free Software Foundation, Inc.
-
-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.
-*/
-\f
-/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
- Ditto for AIX 3.2 and <stdlib.h>. */
-#ifndef _NO_PROTO
-#define _NO_PROTO
-#endif
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if !defined (__STDC__) || !__STDC__
-/* This is a separate conditional since some stdc systems
- reject `defined (const)'. */
-#ifndef const
-#define const
-#endif
-#endif
-
-#include <stdio.h>
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-/* Comment out all this code if we are using the GNU C Library, and are not
- actually compiling the library itself. This code is part of the GNU C
- Library, but also included in many other GNU distributions. Compiling
- and linking in this code is a waste when using the GNU C library
- (especially if it is a shared library). Rather than having every GNU
- program understand `configure --with-gnu-libc' and omit the object files,
- it is simpler to just do this in the source for each such file. */
-
-#define GETOPT_INTERFACE_VERSION 2
-#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2
-#include <gnu-versions.h>
-#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
-#define ELIDE_CODE
-#endif
-#endif
-
-#ifndef ELIDE_CODE
-
-
-/* This needs to come after some library #include
- to get __GNU_LIBRARY__ defined. */
-#ifdef __GNU_LIBRARY__
-/* Don't include stdlib.h for non-GNU C libraries because some of them
- contain conflicting prototypes for getopt. */
-#include <stdlib.h>
-#include <unistd.h>
-#endif /* GNU C library. */
-
-#ifdef VMS
-#include <unixlib.h>
-#if HAVE_STRING_H - 0
-#include <string.h>
-#endif
-#endif
-
-#if defined (WIN32) && !defined (__CYGWIN32__)
-/* It's not Unix, really. See? Capital letters. */
-#include <windows.h>
-#define getpid() GetCurrentProcessId()
-#endif
-
-/* This version of `getopt' appears to the caller like standard Unix `getopt'
- but it behaves differently for the user, since it allows the user
- to intersperse the options with the other arguments.
-
- As `getopt' works, it permutes the elements of ARGV so that,
- when it is done, all the options precede everything else. Thus
- all application programs are extended to handle flexible argument order.
-
- Setting the environment variable POSIXLY_CORRECT disables permutation.
- Then the behavior is completely standard.
-
- GNU application programs can use a third alternative mode in which
- they can distinguish the relative order of options and other arguments. */
-
-#include "getopt.h"
-
-/* For communication from `getopt' to the caller.
- When `getopt' finds an option that takes an argument,
- the argument value is returned here.
- Also, when `ordering' is RETURN_IN_ORDER,
- each non-option ARGV-element is returned here. */
-
-char *optarg = NULL;
-
-/* Index in ARGV of the next element to be scanned.
- This is used for communication to and from the caller
- and for communication between successive calls to `getopt'.
-
- On entry to `getopt', zero means this is the first call; initialize.
-
- When `getopt' returns -1, this is the index of the first of the
- non-option elements that the caller should itself scan.
-
- Otherwise, `optind' communicates from one call to the next
- how much of ARGV has been scanned so far. */
-
-/* 1003.2 says this must be 1 before any call. */
-int optind = 1;
-
-/* Formerly, initialization of getopt depended on optind==0, which
- causes problems with re-calling getopt as programs generally don't
- know that. */
-
-int __getopt_initialized = 0;
-
-/* The next char to be scanned in the option-element
- in which the last option character we returned was found.
- This allows us to pick up the scan where we left off.
-
- If this is zero, or a null string, it means resume the scan
- by advancing to the next ARGV-element. */
-
-static char *nextchar;
-
-/* Callers store zero here to inhibit the error message
- for unrecognized options. */
-
-int opterr = 1;
-
-/* Set to an option character which was unrecognized.
- This must be initialized on some systems to avoid linking in the
- system's own getopt implementation. */
-
-int optopt = '?';
-
-/* Describe how to deal with options that follow non-option ARGV-elements.
-
- If the caller did not specify anything,
- the default is REQUIRE_ORDER if the environment variable
- POSIXLY_CORRECT is defined, PERMUTE otherwise.
-
- REQUIRE_ORDER means don't recognize them as options;
- stop option processing when the first non-option is seen.
- This is what Unix does.
- This mode of operation is selected by either setting the environment
- variable POSIXLY_CORRECT, or using `+' as the first character
- of the list of option characters.
-
- PERMUTE is the default. We permute the contents of ARGV as we scan,
- so that eventually all the non-options are at the end. This allows options
- to be given in any order, even with programs that were not written to
- expect this.
-
- RETURN_IN_ORDER is an option available to programs that were written
- to expect options and other ARGV-elements in any order and that care about
- the ordering of the two. We describe each non-option ARGV-element
- as if it were the argument of an option with character code 1.
- Using `-' as the first character of the list of option characters
- selects this mode of operation.
-
- The special argument `--' forces an end of option-scanning regardless
- of the value of `ordering'. In the case of RETURN_IN_ORDER, only
- `--' can cause `getopt' to return -1 with `optind' != ARGC. */
-
-static enum
-{
- REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
-} ordering;
-
-/* Value of POSIXLY_CORRECT environment variable. */
-static char *posixly_correct;
-\f
-#ifdef __GNU_LIBRARY__
-/* We want to avoid inclusion of string.h with non-GNU libraries
- because there are many ways it can cause trouble.
- On some systems, it contains special magic macros that don't work
- in GCC. */
-#include <string.h>
-#define my_index strchr
-#else
-
-/* Avoid depending on library functions or files
- whose names are inconsistent. */
-
-char *getenv ();
-
-static char *
-my_index (str, chr)
- const char *str;
- int chr;
-{
- while (*str)
- {
- if (*str == chr)
- return (char *) str;
- str++;
- }
- return 0;
-}
-
-/* If using GCC, we can safely declare strlen this way.
- If not using GCC, it is ok not to declare it. */
-#ifdef __GNUC__
-/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
- That was relevant to code that was here before. */
-#if !defined (__STDC__) || !__STDC__
-/* gcc with -traditional declares the built-in strlen to return int,
- and has done so at least since version 2.4.5. -- rms. */
-extern int strlen (const char *);
-#endif /* not __STDC__ */
-#endif /* __GNUC__ */
-
-#endif /* not __GNU_LIBRARY__ */
-\f
-/* Handle permutation of arguments. */
-
-/* Describe the part of ARGV that contains non-options that have
- been skipped. `first_nonopt' is the index in ARGV of the first of them;
- `last_nonopt' is the index after the last of them. */
-
-static int first_nonopt;
-static int last_nonopt;
-
-#ifdef _LIBC
-/* Bash 2.0 gives us an environment variable containing flags
- indicating ARGV elements that should not be considered arguments. */
-
-/* Defined in getopt_init.c */
-extern char *__getopt_nonoption_flags;
-
-static int nonoption_flags_max_len;
-static int nonoption_flags_len;
-
-static int original_argc;
-static char *const *original_argv;
-
-extern pid_t __libc_pid;
-
-/* Make sure the environment variable bash 2.0 puts in the environment
- is valid for the getopt call we must make sure that the ARGV passed
- to getopt is that one passed to the process. */
-static void
-__attribute__ ((__unused__))
-store_args_and_env (int argc, char *const *argv)
-{
- /* XXX This is no good solution. We should rather copy the args so
- that we can compare them later. But we must not use malloc(3). */
- original_argc = argc;
- original_argv = argv;
-}
-text_set_element (__libc_subinit, store_args_and_env);
-
-# define SWAP_FLAGS(ch1, ch2) \
- if (nonoption_flags_len > 0) \
- { \
- char __tmp = __getopt_nonoption_flags[ch1]; \
- __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
- __getopt_nonoption_flags[ch2] = __tmp; \
- }
-#else /* !_LIBC */
-# define SWAP_FLAGS(ch1, ch2)
-#endif /* _LIBC */
-
-/* Exchange two adjacent subsequences of ARGV.
- One subsequence is elements [first_nonopt,last_nonopt)
- which contains all the non-options that have been skipped so far.
- The other is elements [last_nonopt,optind), which contains all
- the options processed since those non-options were skipped.
-
- `first_nonopt' and `last_nonopt' are relocated so that they describe
- the new indices of the non-options in ARGV after they are moved. */
-
-#if defined (__STDC__) && __STDC__
-static void exchange (char **);
-#endif
-
-static void
-exchange (argv)
- char **argv;
-{
- int bottom = first_nonopt;
- int middle = last_nonopt;
- int top = optind;
- char *tem;
-
- /* Exchange the shorter segment with the far end of the longer segment.
- That puts the shorter segment into the right place.
- It leaves the longer segment in the right place overall,
- but it consists of two parts that need to be swapped next. */
-
-#ifdef _LIBC
- /* First make sure the handling of the `__getopt_nonoption_flags'
- string can work normally. Our top argument must be in the range
- of the string. */
- if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
- {
- /* We must extend the array. The user plays games with us and
- presents new arguments. */
- char *new_str = malloc (top + 1);
- if (new_str == NULL)
- nonoption_flags_len = nonoption_flags_max_len = 0;
- else
- {
- memcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len);
- memset (&new_str[nonoption_flags_max_len], '\0',
- top + 1 - nonoption_flags_max_len);
- nonoption_flags_max_len = top + 1;
- __getopt_nonoption_flags = new_str;
- }
- }
-#endif
-
- while (top > middle && middle > bottom)
- {
- if (top - middle > middle - bottom)
- {
- /* Bottom segment is the short one. */
- int len = middle - bottom;
- register int i;
-
- /* Swap it with the top part of the top segment. */
- for (i = 0; i < len; i++)
- {
- tem = argv[bottom + i];
- argv[bottom + i] = argv[top - (middle - bottom) + i];
- argv[top - (middle - bottom) + i] = tem;
- SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
- }
- /* Exclude the moved bottom segment from further swapping. */
- top -= len;
- }
- else
- {
- /* Top segment is the short one. */
- int len = top - middle;
- register int i;
-
- /* Swap it with the bottom part of the bottom segment. */
- for (i = 0; i < len; i++)
- {
- tem = argv[bottom + i];
- argv[bottom + i] = argv[middle + i];
- argv[middle + i] = tem;
- SWAP_FLAGS (bottom + i, middle + i);
- }
- /* Exclude the moved top segment from further swapping. */
- bottom += len;
- }
- }
-
- /* Update records for the slots the non-options now occupy. */
-
- first_nonopt += (optind - last_nonopt);
- last_nonopt = optind;
-}
-
-/* Initialize the internal data when the first call is made. */
-
-#if defined (__STDC__) && __STDC__
-static const char *_getopt_initialize (int, char *const *, const char *);
-#endif
-static const char *
-_getopt_initialize (argc, argv, optstring)
- int argc;
- char *const *argv;
- const char *optstring;
-{
- /* Start processing options with ARGV-element 1 (since ARGV-element 0
- is the program name); the sequence of previously skipped
- non-option ARGV-elements is empty. */
-
- first_nonopt = last_nonopt = optind;
-
- nextchar = NULL;
-
- posixly_correct = getenv ("POSIXLY_CORRECT");
-
- /* Determine how to handle the ordering of options and nonoptions. */
-
- if (optstring[0] == '-')
- {
- ordering = RETURN_IN_ORDER;
- ++optstring;
- }
- else if (optstring[0] == '+')
- {
- ordering = REQUIRE_ORDER;
- ++optstring;
- }
- else if (posixly_correct != NULL)
- ordering = REQUIRE_ORDER;
- else
- ordering = PERMUTE;
-
-#ifdef _LIBC
- if (posixly_correct == NULL
- && argc == original_argc && argv == original_argv)
- {
- if (nonoption_flags_max_len == 0)
- {
- if (__getopt_nonoption_flags == NULL
- || __getopt_nonoption_flags[0] == '\0')
- nonoption_flags_max_len = -1;
- else
- {
- const char *orig_str = __getopt_nonoption_flags;
- int len = nonoption_flags_max_len = strlen (orig_str);
- if (nonoption_flags_max_len < argc)
- nonoption_flags_max_len = argc;
- __getopt_nonoption_flags =
- (char *) malloc (nonoption_flags_max_len);
- if (__getopt_nonoption_flags == NULL)
- nonoption_flags_max_len = -1;
- else
- {
- memcpy (__getopt_nonoption_flags, orig_str, len);
- memset (&__getopt_nonoption_flags[len], '\0',
- nonoption_flags_max_len - len);
- }
- }
- }
- nonoption_flags_len = nonoption_flags_max_len;
- }
- else
- nonoption_flags_len = 0;
-#endif
-
- return optstring;
-}
-\f
-/* Scan elements of ARGV (whose length is ARGC) for option characters
- given in OPTSTRING.
-
- If an element of ARGV starts with '-', and is not exactly "-" or "--",
- then it is an option element. The characters of this element
- (aside from the initial '-') are option characters. If `getopt'
- is called repeatedly, it returns successively each of the option characters
- from each of the option elements.
-
- If `getopt' finds another option character, it returns that character,
- updating `optind' and `nextchar' so that the next call to `getopt' can
- resume the scan with the following option character or ARGV-element.
-
- If there are no more option characters, `getopt' returns -1.
- Then `optind' is the index in ARGV of the first ARGV-element
- that is not an option. (The ARGV-elements have been permuted
- so that those that are not options now come last.)
-
- OPTSTRING is a string containing the legitimate option characters.
- If an option character is seen that is not listed in OPTSTRING,
- return '?' after printing an error message. If you set `opterr' to
- zero, the error message is suppressed but we still return '?'.
-
- If a char in OPTSTRING is followed by a colon, that means it wants an arg,
- so the following text in the same ARGV-element, or the text of the following
- ARGV-element, is returned in `optarg'. Two colons mean an option that
- wants an optional arg; if there is text in the current ARGV-element,
- it is returned in `optarg', otherwise `optarg' is set to zero.
-
- If OPTSTRING starts with `-' or `+', it requests different methods of
- handling the non-option ARGV-elements.
- See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
-
- Long-named options begin with `--' instead of `-'.
- Their names may be abbreviated as long as the abbreviation is unique
- or is an exact match for some defined option. If they have an
- argument, it follows the option name in the same ARGV-element, separated
- from the option name by a `=', or else the in next ARGV-element.
- When `getopt' finds a long-named option, it returns 0 if that option's
- `flag' field is nonzero, the value of the option's `val' field
- if the `flag' field is zero.
-
- The elements of ARGV aren't really const, because we permute them.
- But we pretend they're const in the prototype to be compatible
- with other systems.
-
- LONGOPTS is a vector of `struct option' terminated by an
- element containing a name which is zero.
-
- LONGIND returns the index in LONGOPT of the long-named option found.
- It is only valid when a long-named option has been found by the most
- recent call.
-
- If LONG_ONLY is nonzero, '-' as well as '--' can introduce
- long-named options. */
-
-int
-_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
- int argc;
- char *const *argv;
- const char *optstring;
- const struct option *longopts;
- int *longind;
- int long_only;
-{
- optarg = NULL;
-
- if (optind == 0 || !__getopt_initialized)
- {
- if (optind == 0)
- optind = 1; /* Don't scan ARGV[0], the program name. */
- optstring = _getopt_initialize (argc, argv, optstring);
- __getopt_initialized = 1;
- }
-
- /* Test whether ARGV[optind] points to a non-option argument.
- Either it does not have option syntax, or there is an environment flag
- from the shell indicating it is not an option. The later information
- is only used when the used in the GNU libc. */
-#ifdef _LIBC
-#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
- || (optind < nonoption_flags_len \
- && __getopt_nonoption_flags[optind] == '1'))
-#else
-#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
-#endif
-
- if (nextchar == NULL || *nextchar == '\0')
- {
- /* Advance to the next ARGV-element. */
-
- /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
- moved back by the user (who may also have changed the arguments). */
- if (last_nonopt > optind)
- last_nonopt = optind;
- if (first_nonopt > optind)
- first_nonopt = optind;
-
- if (ordering == PERMUTE)
- {
- /* If we have just processed some options following some non-options,
- exchange them so that the options come first. */
-
- if (first_nonopt != last_nonopt && last_nonopt != optind)
- exchange ((char **) argv);
- else if (last_nonopt != optind)
- first_nonopt = optind;
-
- /* Skip any additional non-options
- and extend the range of non-options previously skipped. */
-
- while (optind < argc && NONOPTION_P)
- optind++;
- last_nonopt = optind;
- }
-
- /* The special ARGV-element `--' means premature end of options.
- Skip it like a null option,
- then exchange with previous non-options as if it were an option,
- then skip everything else like a non-option. */
-
- if (optind != argc && !strcmp (argv[optind], "--"))
- {
- optind++;
-
- if (first_nonopt != last_nonopt && last_nonopt != optind)
- exchange ((char **) argv);
- else if (first_nonopt == last_nonopt)
- first_nonopt = optind;
- last_nonopt = argc;
-
- optind = argc;
- }
-
- /* If we have done all the ARGV-elements, stop the scan
- and back over any non-options that we skipped and permuted. */
-
- if (optind == argc)
- {
- /* Set the next-arg-index to point at the non-options
- that we previously skipped, so the caller will digest them. */
- if (first_nonopt != last_nonopt)
- optind = first_nonopt;
- return -1;
- }
-
- /* If we have come to a non-option and did not permute it,
- either stop the scan or describe it to the caller and pass it by. */
-
- if (NONOPTION_P)
- {
- if (ordering == REQUIRE_ORDER)
- return -1;
- optarg = argv[optind++];
- return 1;
- }
-
- /* We have found another option-ARGV-element.
- Skip the initial punctuation. */
-
- nextchar = (argv[optind] + 1
- + (longopts != NULL && argv[optind][1] == '-'));
- }
-
- /* Decode the current option-ARGV-element. */
-
- /* Check whether the ARGV-element is a long option.
-
- If long_only and the ARGV-element has the form "-f", where f is
- a valid short option, don't consider it an abbreviated form of
- a long option that starts with f. Otherwise there would be no
- way to give the -f short option.
-
- On the other hand, if there's a long option "fubar" and
- the ARGV-element is "-fu", do consider that an abbreviation of
- the long option, just like "--fu", and not "-f" with arg "u".
-
- This distinction seems to be the most useful approach. */
-
- if (longopts != NULL
- && (argv[optind][1] == '-'
- || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
- {
- char *nameend;
- const struct option *p;
- const struct option *pfound = NULL;
- int exact = 0;
- int ambig = 0;
- int indfound = -1;
- int option_index;
-
- for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
- /* Do nothing. */ ;
-
- /* Test all long options for either exact match
- or abbreviated matches. */
- for (p = longopts, option_index = 0; p->name; p++, option_index++)
- if (!strncmp (p->name, nextchar, nameend - nextchar))
- {
- if ((unsigned int) (nameend - nextchar)
- == (unsigned int) strlen (p->name))
- {
- /* Exact match found. */
- pfound = p;
- indfound = option_index;
- exact = 1;
- break;
- }
- else if (pfound == NULL)
- {
- /* First nonexact match found. */
- pfound = p;
- indfound = option_index;
- }
- else
- /* Second or later nonexact match found. */
- ambig = 1;
- }
-
- if (ambig && !exact)
- {
- if (opterr)
- fprintf (stderr, "%s: option `%s' is ambiguous\n",
- argv[0], argv[optind]);
- nextchar += strlen (nextchar);
- optind++;
- optopt = 0;
- return '?';
- }
-
- if (pfound != NULL)
- {
- option_index = indfound;
- optind++;
- if (*nameend)
- {
- /* Don't test has_arg with >, because some C compilers don't
- allow it to be used on enums. */
- if (pfound->has_arg)
- optarg = nameend + 1;
- else
- {
- if (opterr)
- {
- if (argv[optind - 1][1] == '-')
- /* --option */
- fprintf (stderr,
- "%s: option `--%s' doesn't allow an argument\n",
- argv[0], pfound->name);
- else
- /* +option or -option */
- fprintf (stderr,
- "%s: option `%c%s' doesn't allow an argument\n",
- argv[0], argv[optind - 1][0], pfound->name);
- }
-
- nextchar += strlen (nextchar);
-
- optopt = pfound->val;
- return '?';
- }
- }
- else if (pfound->has_arg == 1)
- {
- if (optind < argc)
- optarg = argv[optind++];
- else
- {
- if (opterr)
- fprintf (stderr,
- "%s: option `%s' requires an argument\n",
- argv[0], argv[optind - 1]);
- nextchar += strlen (nextchar);
- optopt = pfound->val;
- return optstring[0] == ':' ? ':' : '?';
- }
- }
- nextchar += strlen (nextchar);
- if (longind != NULL)
- *longind = option_index;
- if (pfound->flag)
- {
- *(pfound->flag) = pfound->val;
- return 0;
- }
- return pfound->val;
- }
-
- /* Can't find it as a long option. If this is not getopt_long_only,
- or the option starts with '--' or is not a valid short
- option, then it's an error.
- Otherwise interpret it as a short option. */
- if (!long_only || argv[optind][1] == '-'
- || my_index (optstring, *nextchar) == NULL)
- {
- if (opterr)
- {
- if (argv[optind][1] == '-')
- /* --option */
- fprintf (stderr, "%s: unrecognized option `--%s'\n",
- argv[0], nextchar);
- else
- /* +option or -option */
- fprintf (stderr, "%s: unrecognized option `%c%s'\n",
- argv[0], argv[optind][0], nextchar);
- }
- nextchar = (char *) "";
- optind++;
- optopt = 0;
- return '?';
- }
- }
-
- /* Look at and handle the next short option-character. */
-
- {
- char c = *nextchar++;
- char *temp = my_index (optstring, c);
-
- /* Increment `optind' when we start to process its last character. */
- if (*nextchar == '\0')
- ++optind;
-
- if (temp == NULL || c == ':')
- {
- if (opterr)
- {
- if (posixly_correct)
- /* 1003.2 specifies the format of this message. */
- fprintf (stderr, "%s: illegal option -- %c\n",
- argv[0], c);
- else
- fprintf (stderr, "%s: invalid option -- %c\n",
- argv[0], c);
- }
- optopt = c;
- return '?';
- }
- /* Convenience. Treat POSIX -W foo same as long option --foo */
- if (temp[0] == 'W' && temp[1] == ';')
- {
- char *nameend;
- const struct option *p;
- const struct option *pfound = NULL;
- int exact = 0;
- int ambig = 0;
- int indfound = 0;
- int option_index;
-
- /* This is an option that requires an argument. */
- if (*nextchar != '\0')
- {
- optarg = nextchar;
- /* If we end this ARGV-element by taking the rest as an arg,
- we must advance to the next element now. */
- optind++;
- }
- else if (optind == argc)
- {
- if (opterr)
- {
- /* 1003.2 specifies the format of this message. */
- fprintf (stderr, "%s: option requires an argument -- %c\n",
- argv[0], c);
- }
- optopt = c;
- if (optstring[0] == ':')
- c = ':';
- else
- c = '?';
- return c;
- }
- else
- /* We already incremented `optind' once;
- increment it again when taking next ARGV-elt as argument. */
- optarg = argv[optind++];
-
- /* optarg is now the argument, see if it's in the
- table of longopts. */
-
- for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
- /* Do nothing. */ ;
-
- /* Test all long options for either exact match
- or abbreviated matches. */
- for (p = longopts, option_index = 0; p->name; p++, option_index++)
- if (!strncmp (p->name, nextchar, nameend - nextchar))
- {
- if ((unsigned int) (nameend - nextchar) == strlen (p->name))
- {
- /* Exact match found. */
- pfound = p;
- indfound = option_index;
- exact = 1;
- break;
- }
- else if (pfound == NULL)
- {
- /* First nonexact match found. */
- pfound = p;
- indfound = option_index;
- }
- else
- /* Second or later nonexact match found. */
- ambig = 1;
- }
- if (ambig && !exact)
- {
- if (opterr)
- fprintf (stderr, "%s: option `-W %s' is ambiguous\n",
- argv[0], argv[optind]);
- nextchar += strlen (nextchar);
- optind++;
- return '?';
- }
- if (pfound != NULL)
- {
- option_index = indfound;
- if (*nameend)
- {
- /* Don't test has_arg with >, because some C compilers don't
- allow it to be used on enums. */
- if (pfound->has_arg)
- optarg = nameend + 1;
- else
- {
- if (opterr)
- fprintf (stderr,
- "%s: option `-W %s' doesn't allow an argument\n",
- argv[0], pfound->name);
-
- nextchar += strlen (nextchar);
- return '?';
- }
- }
- else if (pfound->has_arg == 1)
- {
- if (optind < argc)
- optarg = argv[optind++];
- else
- {
- if (opterr)
- fprintf (stderr,
- "%s: option `%s' requires an argument\n",
- argv[0], argv[optind - 1]);
- nextchar += strlen (nextchar);
- return optstring[0] == ':' ? ':' : '?';
- }
- }
- nextchar += strlen (nextchar);
- if (longind != NULL)
- *longind = option_index;
- if (pfound->flag)
- {
- *(pfound->flag) = pfound->val;
- return 0;
- }
- return pfound->val;
- }
- nextchar = NULL;
- return 'W'; /* Let the application handle it. */
- }
- if (temp[1] == ':')
- {
- if (temp[2] == ':')
- {
- /* This is an option that accepts an argument optionally. */
- if (*nextchar != '\0')
- {
- optarg = nextchar;
- optind++;
- }
- else
- optarg = NULL;
- nextchar = NULL;
- }
- else
- {
- /* This is an option that requires an argument. */
- if (*nextchar != '\0')
- {
- optarg = nextchar;
- /* If we end this ARGV-element by taking the rest as an arg,
- we must advance to the next element now. */
- optind++;
- }
- else if (optind == argc)
- {
- if (opterr)
- {
- /* 1003.2 specifies the format of this message. */
- fprintf (stderr,
- "%s: option requires an argument -- %c\n",
- argv[0], c);
- }
- optopt = c;
- if (optstring[0] == ':')
- c = ':';
- else
- c = '?';
- }
- else
- /* We already incremented `optind' once;
- increment it again when taking next ARGV-elt as argument. */
- optarg = argv[optind++];
- nextchar = NULL;
- }
- }
- return c;
- }
-}
-
-int
-getopt (argc, argv, optstring)
- int argc;
- char *const *argv;
- const char *optstring;
-{
- return _getopt_internal (argc, argv, optstring,
- (const struct option *) 0,
- (int *) 0,
- 0);
-}
-
-#endif /* Not ELIDE_CODE. */
-\f
-#ifdef TEST
-
-/* Compile with -DTEST to make an executable for use in testing
- the above definition of `getopt'. */
-
-int
-main (argc, argv)
- int argc;
- char **argv;
-{
- int c;
- int digit_optind = 0;
-
- while (1)
- {
- int this_option_optind = optind ? optind : 1;
-
- c = getopt (argc, argv, "abc:d:0123456789");
- if (c == -1)
- break;
-
- switch (c)
- {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (digit_optind != 0 && digit_optind != this_option_optind)
- printf ("digits occur in two different argv-elements.\n");
- digit_optind = this_option_optind;
- printf ("option %c\n", c);
- break;
-
- case 'a':
- printf ("option a\n");
- break;
-
- case 'b':
- printf ("option b\n");
- break;
-
- case 'c':
- printf ("option c with value `%s'\n", optarg);
- break;
-
- case '?':
- break;
-
- default:
- printf ("?? getopt returned character code 0%o ??\n", c);
- }
- }
-
- if (optind < argc)
- {
- printf ("non-option ARGV-elements: ");
- while (optind < argc)
- printf ("%s ", argv[optind++]);
- printf ("\n");
- }
-
- exit (0);
-}
-
-#endif /* TEST */
+++ /dev/null
-/* Declarations for getopt.
- Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc.
-
-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.
-*/
-
-#ifndef _GETOPT_H
-#define _GETOPT_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* For communication from `getopt' to the caller.
- When `getopt' finds an option that takes an argument,
- the argument value is returned here.
- Also, when `ordering' is RETURN_IN_ORDER,
- each non-option ARGV-element is returned here. */
-
-extern char *optarg;
-
-/* Index in ARGV of the next element to be scanned.
- This is used for communication to and from the caller
- and for communication between successive calls to `getopt'.
-
- On entry to `getopt', zero means this is the first call; initialize.
-
- When `getopt' returns -1, this is the index of the first of the
- non-option elements that the caller should itself scan.
-
- Otherwise, `optind' communicates from one call to the next
- how much of ARGV has been scanned so far. */
-
-extern int optind;
-
-/* Callers store zero here to inhibit the error message `getopt' prints
- for unrecognized options. */
-
-extern int opterr;
-
-/* Set to an option character which was unrecognized. */
-
-extern int optopt;
-
-/* Describe the long-named options requested by the application.
- The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
- of `struct option' terminated by an element containing a name which is
- zero.
-
- The field `has_arg' is:
- no_argument (or 0) if the option does not take an argument,
- required_argument (or 1) if the option requires an argument,
- optional_argument (or 2) if the option takes an optional argument.
-
- If the field `flag' is not NULL, it points to a variable that is set
- to the value given in the field `val' when the option is found, but
- left unchanged if the option is not found.
-
- To have a long-named option do something other than set an `int' to
- a compiled-in constant, such as set a value from `optarg', set the
- option's `flag' field to zero and its `val' field to a nonzero
- value (the equivalent single-letter option character, if there is
- one). For long options that have a zero `flag' field, `getopt'
- returns the contents of the `val' field. */
-
-struct option
-{
-#if defined (__STDC__) && __STDC__
- const char *name;
-#else
- char *name;
-#endif
- /* has_arg can't be an enum because some compilers complain about
- type mismatches in all the code that assumes it is an int. */
- int has_arg;
- int *flag;
- int val;
-};
-
-/* Names for the values of the `has_arg' field of `struct option'. */
-
-#define no_argument 0
-#define required_argument 1
-#define optional_argument 2
-
-#if defined (__STDC__) && __STDC__
-#ifdef __GNU_LIBRARY__
-/* Many other libraries have conflicting prototypes for getopt, with
- differences in the consts, in stdlib.h. To avoid compilation
- errors, only prototype getopt for the GNU C library. */
-extern int getopt (int argc, char *const *argv, const char *shortopts);
-#else /* not __GNU_LIBRARY__ */
-extern int getopt ();
-#endif /* __GNU_LIBRARY__ */
-extern int getopt_long (int argc, char *const *argv, const char *shortopts,
- const struct option *longopts, int *longind);
-extern int getopt_long_only (int argc, char *const *argv,
- const char *shortopts,
- const struct option *longopts, int *longind);
-
-/* Internal only. Users should not call this directly. */
-extern int _getopt_internal (int argc, char *const *argv,
- const char *shortopts,
- const struct option *longopts, int *longind,
- int long_only);
-#else /* not __STDC__ */
-extern int getopt ();
-extern int getopt_long ();
-extern int getopt_long_only ();
-
-extern int _getopt_internal ();
-#endif /* __STDC__ */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _GETOPT_H */
+++ /dev/null
-/* getopt_long and getopt_long_only entry points for GNU getopt.
- Copyright (C) 1987,88,89,90,91,92,93,94,96,97 Free Software Foundation, Inc.
-
-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.
-*/
-\f
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "getopt.h"
-
-#if !defined (__STDC__) || !__STDC__
-/* This is a separate conditional since some stdc systems
- reject `defined (const)'. */
-#ifndef const
-#define const
-#endif
-#endif
-
-#include <stdio.h>
-
-/* Comment out all this code if we are using the GNU C Library, and are not
- actually compiling the library itself. This code is part of the GNU C
- Library, but also included in many other GNU distributions. Compiling
- and linking in this code is a waste when using the GNU C library
- (especially if it is a shared library). Rather than having every GNU
- program understand `configure --with-gnu-libc' and omit the object files,
- it is simpler to just do this in the source for each such file. */
-
-#define GETOPT_INTERFACE_VERSION 2
-#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2
-#include <gnu-versions.h>
-#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
-#define ELIDE_CODE
-#endif
-#endif
-
-#ifndef ELIDE_CODE
-
-
-/* This needs to come after some library #include
- to get __GNU_LIBRARY__ defined. */
-#ifdef __GNU_LIBRARY__
-#include <stdlib.h>
-#endif
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-int
-getopt_long (argc, argv, options, long_options, opt_index)
- int argc;
- char *const *argv;
- const char *options;
- const struct option *long_options;
- int *opt_index;
-{
- return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
-}
-
-/* Like getopt_long, but '-' as well as '--' can indicate a long option.
- If an option that starts with '-' (not '--') doesn't match a long option,
- but does match a short option, it is parsed as a short option
- instead. */
-
-int
-getopt_long_only (argc, argv, options, long_options, opt_index)
- int argc;
- char *const *argv;
- const char *options;
- const struct option *long_options;
- int *opt_index;
-{
- return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
-}
-
-
-#endif /* Not ELIDE_CODE. */
-\f
-#ifdef TEST
-
-#include <stdio.h>
-
-int
-main (argc, argv)
- int argc;
- char **argv;
-{
- int c;
- int digit_optind = 0;
-
- while (1)
- {
- int this_option_optind = optind ? optind : 1;
- int option_index = 0;
- static struct option long_options[] =
- {
- {"add", 1, 0, 0},
- {"append", 0, 0, 0},
- {"delete", 1, 0, 0},
- {"verbose", 0, 0, 0},
- {"create", 0, 0, 0},
- {"file", 1, 0, 0},
- {0, 0, 0, 0}
- };
-
- c = getopt_long (argc, argv, "abc:d:0123456789",
- long_options, &option_index);
- if (c == -1)
- break;
-
- switch (c)
- {
- case 0:
- printf ("option %s", long_options[option_index].name);
- if (optarg)
- printf (" with arg %s", optarg);
- printf ("\n");
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (digit_optind != 0 && digit_optind != this_option_optind)
- printf ("digits occur in two different argv-elements.\n");
- digit_optind = this_option_optind;
- printf ("option %c\n", c);
- break;
-
- case 'a':
- printf ("option a\n");
- break;
-
- case 'b':
- printf ("option b\n");
- break;
-
- case 'c':
- printf ("option c with value `%s'\n", optarg);
- break;
-
- case 'd':
- printf ("option d with value `%s'\n", optarg);
- break;
-
- case '?':
- break;
-
- default:
- printf ("?? getopt returned character code 0%o ??\n", c);
- }
- }
-
- if (optind < argc)
- {
- printf ("non-option ARGV-elements: ");
- while (optind < argc)
- printf ("%s ", argv[optind++]);
- printf ("\n");
- }
-
- exit (0);
-}
-
-#endif /* TEST */
+++ /dev/null
-/*
- ipv4.h -- missing IPv4 related definitions
- Copyright (C) 2005 Ivo Timmermans
- 2006-2012 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 __TINC_IPV4_H__
-#define __TINC_IPV4_H__
-
-#ifndef AF_INET
-#define AF_INET 2
-#endif
-
-#ifndef IPPROTO_ICMP
-#define IPPROTO_ICMP 1
-#endif
-
-#ifndef ICMP_DEST_UNREACH
-#define ICMP_DEST_UNREACH 3
-#endif
-
-#ifndef ICMP_FRAG_NEEDED
-#define ICMP_FRAG_NEEDED 4
-#endif
-
-#ifndef ICMP_NET_UNKNOWN
-#define ICMP_NET_UNKNOWN 6
-#endif
-
-#ifndef ICMP_TIME_EXCEEDED
-#define ICMP_TIME_EXCEEDED 11
-#endif
-
-#ifndef ICMP_EXC_TTL
-#define ICMP_EXC_TTL 0
-#endif
-
-#ifndef ICMP_NET_UNREACH
-#define ICMP_NET_UNREACH 0
-#endif
-
-#ifndef ICMP_NET_ANO
-#define ICMP_NET_ANO 9
-#endif
-
-#ifndef IP_MSS
-#define IP_MSS 576
-#endif
-
-#ifndef HAVE_STRUCT_IP
-struct ip {
-#if __BYTE_ORDER == __LITTLE_ENDIAN
- unsigned int ip_hl:4;
- unsigned int ip_v:4;
-#else
- unsigned int ip_v:4;
- unsigned int ip_hl:4;
-#endif
- uint8_t ip_tos;
- uint16_t ip_len;
- uint16_t ip_id;
- uint16_t ip_off;
-#define IP_RF 0x8000
-#define IP_DF 0x4000
-#define IP_MF 0x2000
- uint8_t ip_ttl;
- uint8_t ip_p;
- uint16_t ip_sum;
- struct in_addr ip_src, ip_dst;
-} __attribute__ ((__packed__));
-#endif
-
-#ifndef IP_OFFMASK
-#define IP_OFFMASK 0x1fff
-#endif
-
-#ifndef HAVE_STRUCT_ICMP
-struct icmp {
- uint8_t icmp_type;
- uint8_t icmp_code;
- uint16_t icmp_cksum;
- union {
- uint8_t ih_pptr;
- struct in_addr ih_gwaddr;
- struct ih_idseq {
- uint16_t icd_id;
- uint16_t icd_seq;
- } ih_idseq;
- uint32_t ih_void;
-
-
- struct ih_pmtu {
- uint16_t ipm_void;
- uint16_t ipm_nextmtu;
- } ih_pmtu;
-
- struct ih_rtradv {
- uint8_t irt_num_addrs;
- uint8_t irt_wpa;
- uint16_t irt_lifetime;
- } ih_rtradv;
- } icmp_hun;
-#define icmp_pptr icmp_hun.ih_pptr
-#define icmp_gwaddr icmp_hun.ih_gwaddr
-#define icmp_id icmp_hun.ih_idseq.icd_id
-#define icmp_seq icmp_hun.ih_idseq.icd_seq
-#define icmp_void icmp_hun.ih_void
-#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void
-#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu
-#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs
-#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa
-#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime
- union {
- struct {
- uint32_t its_otime;
- uint32_t its_rtime;
- uint32_t its_ttime;
- } id_ts;
- struct {
- struct ip idi_ip;
- } id_ip;
- uint32_t id_mask;
- uint8_t id_data[1];
- } icmp_dun;
-#define icmp_otime icmp_dun.id_ts.its_otime
-#define icmp_rtime icmp_dun.id_ts.its_rtime
-#define icmp_ttime icmp_dun.id_ts.its_ttime
-#define icmp_ip icmp_dun.id_ip.idi_ip
-#define icmp_radv icmp_dun.id_radv
-#define icmp_mask icmp_dun.id_mask
-#define icmp_data icmp_dun.id_data
-} __attribute__ ((__packed__));
-#endif
-
-#endif /* __TINC_IPV4_H__ */
+++ /dev/null
-/*
- ipv6.h -- missing IPv6 related definitions
- Copyright (C) 2005 Ivo Timmermans
- 2006-2012 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 __TINC_IPV6_H__
-#define __TINC_IPV6_H__
-
-#ifndef AF_INET6
-#define AF_INET6 10
-#endif
-
-#ifndef IPPROTO_ICMPV6
-#define IPPROTO_ICMPV6 58
-#endif
-
-#ifndef HAVE_STRUCT_IN6_ADDR
-struct in6_addr {
- union {
- uint8_t u6_addr8[16];
- uint16_t u6_addr16[8];
- uint32_t u6_addr32[4];
- } in6_u;
-} __attribute__ ((__packed__));
-#define s6_addr in6_u.u6_addr8
-#define s6_addr16 in6_u.u6_addr16
-#define s6_addr32 in6_u.u6_addr32
-#endif
-
-#ifndef HAVE_STRUCT_SOCKADDR_IN6
-struct sockaddr_in6 {
- uint16_t sin6_family;
- uint16_t sin6_port;
- uint32_t sin6_flowinfo;
- struct in6_addr sin6_addr;
- uint32_t sin6_scope_id;
-} __attribute__ ((__packed__));
-#endif
-
-#ifndef IN6_IS_ADDR_V4MAPPED
-#define IN6_IS_ADDR_V4MAPPED(a) \
- ((((__const uint32_t *) (a))[0] == 0) \
- && (((__const uint32_t *) (a))[1] == 0) \
- && (((__const uint32_t *) (a))[2] == htonl (0xffff)))
-#endif
-
-#ifndef HAVE_STRUCT_IP6_HDR
-struct ip6_hdr {
- union {
- struct ip6_hdrctl {
- uint32_t ip6_un1_flow;
- uint16_t ip6_un1_plen;
- uint8_t ip6_un1_nxt;
- uint8_t ip6_un1_hlim;
- } ip6_un1;
- uint8_t ip6_un2_vfc;
- } ip6_ctlun;
- struct in6_addr ip6_src;
- struct in6_addr ip6_dst;
-} __attribute__ ((__packed__));
-#define ip6_vfc ip6_ctlun.ip6_un2_vfc
-#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow
-#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen
-#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt
-#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim
-#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim
-#endif
-
-#ifndef HAVE_STRUCT_ICMP6_HDR
-struct icmp6_hdr {
- uint8_t icmp6_type;
- uint8_t icmp6_code;
- uint16_t icmp6_cksum;
- union {
- uint32_t icmp6_un_data32[1];
- uint16_t icmp6_un_data16[2];
- uint8_t icmp6_un_data8[4];
- } icmp6_dataun;
-} __attribute__ ((__packed__));
-#define ICMP6_DST_UNREACH_NOROUTE 0
-#define ICMP6_DST_UNREACH 1
-#define ICMP6_PACKET_TOO_BIG 2
-#define ICMP6_TIME_EXCEEDED 3
-#define ICMP6_DST_UNREACH_ADMIN 1
-#define ICMP6_DST_UNREACH_ADDR 3
-#define ICMP6_TIME_EXCEED_TRANSIT 0
-#define ND_NEIGHBOR_SOLICIT 135
-#define ND_NEIGHBOR_ADVERT 136
-#define icmp6_data32 icmp6_dataun.icmp6_un_data32
-#define icmp6_data16 icmp6_dataun.icmp6_un_data16
-#define icmp6_data8 icmp6_dataun.icmp6_un_data8
-#define icmp6_mtu icmp6_data32[0]
-#endif
-
-#ifndef HAVE_STRUCT_ND_NEIGHBOR_SOLICIT
-struct nd_neighbor_solicit {
- struct icmp6_hdr nd_ns_hdr;
- struct in6_addr nd_ns_target;
-} __attribute__ ((__packed__));
-#define ND_OPT_SOURCE_LINKADDR 1
-#define ND_OPT_TARGET_LINKADDR 2
-#define nd_ns_type nd_ns_hdr.icmp6_type
-#define nd_ns_code nd_ns_hdr.icmp6_code
-#define nd_ns_cksum nd_ns_hdr.icmp6_cksum
-#define nd_ns_reserved nd_ns_hdr.icmp6_data32[0]
-#endif
-
-#ifndef HAVE_STRUCT_ND_OPT_HDR
-struct nd_opt_hdr {
- uint8_t nd_opt_type;
- uint8_t nd_opt_len;
-} __attribute__ ((__packed__));
-#endif
-
-#endif /* __TINC_IPV6_H__ */
+++ /dev/null
-/*
- list.c -- functions to deal with double linked lists
- Copyright (C) 2000-2005 Ivo Timmermans
- 2000-2006 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 "list.h"
-#include "xalloc.h"
-
-/* (De)constructors */
-
-list_t *list_alloc(list_action_t delete) {
- list_t *list;
-
- list = xmalloc_and_zero(sizeof(list_t));
- list->delete = delete;
-
- return list;
-}
-
-void list_free(list_t *list) {
- free(list);
-}
-
-list_node_t *list_alloc_node(void) {
- return xmalloc_and_zero(sizeof(list_node_t));
-}
-
-void list_free_node(list_t *list, list_node_t *node) {
- if(node->data && list->delete)
- list->delete(node->data);
-
- free(node);
-}
-
-/* Insertion and deletion */
-
-list_node_t *list_insert_head(list_t *list, void *data) {
- list_node_t *node;
-
- node = list_alloc_node();
-
- node->data = data;
- node->prev = NULL;
- node->next = list->head;
- list->head = node;
-
- if(node->next)
- node->next->prev = node;
- else
- list->tail = node;
-
- list->count++;
-
- return node;
-}
-
-list_node_t *list_insert_tail(list_t *list, void *data) {
- list_node_t *node;
-
- node = list_alloc_node();
-
- node->data = data;
- node->next = NULL;
- node->prev = list->tail;
- list->tail = node;
-
- if(node->prev)
- node->prev->next = node;
- else
- list->head = node;
-
- list->count++;
-
- return node;
-}
-
-void list_unlink_node(list_t *list, list_node_t *node) {
- if(node->prev)
- node->prev->next = node->next;
- else
- list->head = node->next;
-
- if(node->next)
- node->next->prev = node->prev;
- else
- list->tail = node->prev;
-
- list->count--;
-}
-
-void list_delete_node(list_t *list, list_node_t *node) {
- list_unlink_node(list, node);
- list_free_node(list, node);
-}
-
-void list_delete_head(list_t *list) {
- list_delete_node(list, list->head);
-}
-
-void list_delete_tail(list_t *list) {
- list_delete_node(list, list->tail);
-}
-
-/* Head/tail lookup */
-
-void *list_get_head(list_t *list) {
- if(list->head)
- return list->head->data;
- else
- return NULL;
-}
-
-void *list_get_tail(list_t *list) {
- if(list->tail)
- return list->tail->data;
- else
- return NULL;
-}
-
-/* Fast list deletion */
-
-void list_delete_list(list_t *list) {
- list_node_t *node, *next;
-
- for(node = list->head; node; node = next) {
- next = node->next;
- list_free_node(list, node);
- }
-
- list_free(list);
-}
-
-/* Traversing */
-
-void list_foreach_node(list_t *list, list_action_node_t action) {
- list_node_t *node, *next;
-
- for(node = list->head; node; node = next) {
- next = node->next;
- action(node);
- }
-}
-
-void list_foreach(list_t *list, list_action_t action) {
- list_node_t *node, *next;
-
- for(node = list->head; node; node = next) {
- next = node->next;
- if(node->data)
- action(node->data);
- }
-}
+++ /dev/null
-/*
- list.h -- header file for list.c
- Copyright (C) 2000-2005 Ivo Timmermans
- 2000-2006 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 __TINC_LIST_H__
-#define __TINC_LIST_H__
-
-typedef struct list_node_t {
- struct list_node_t *prev;
- struct list_node_t *next;
-
- /* Payload */
-
- void *data;
-} list_node_t;
-
-typedef void (*list_action_t)(const void *);
-typedef void (*list_action_node_t)(const list_node_t *);
-
-typedef struct list_t {
- list_node_t *head;
- list_node_t *tail;
- int count;
-
- /* Callbacks */
-
- list_action_t delete;
-} list_t;
-
-/* (De)constructors */
-
-extern list_t *list_alloc(list_action_t) __attribute__ ((__malloc__));
-extern void list_free(list_t *);
-extern list_node_t *list_alloc_node(void);
-extern void list_free_node(list_t *, list_node_t *);
-
-/* Insertion and deletion */
-
-extern list_node_t *list_insert_head(list_t *, void *);
-extern list_node_t *list_insert_tail(list_t *, void *);
-
-extern void list_unlink_node(list_t *, list_node_t *);
-extern void list_delete_node(list_t *, list_node_t *);
-
-extern void list_delete_head(list_t *);
-extern void list_delete_tail(list_t *);
-
-/* Head/tail lookup */
-
-extern void *list_get_head(list_t *);
-extern void *list_get_tail(list_t *);
-
-/* Fast list deletion */
-
-extern void list_delete_list(list_t *);
-
-/* Traversing */
-
-extern void list_foreach(list_t *, list_action_t);
-extern void list_foreach_node(list_t *, list_action_node_t);
-
-#endif /* __TINC_LIST_H__ */
+++ /dev/null
-/* Work around bug on some systems where malloc (0) fails.
- Copyright (C) 1997 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc., Foundation,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
-
-/* written by Jim Meyering */
-
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
-#undef malloc
-
-#include <sys/types.h>
-
-char *malloc ();
-
-/* Allocate an N-byte block of memory from the heap.
- If N is zero, allocate a 1-byte block. */
-
-char *
-rpl_malloc (n)
- size_t n;
-{
- if (n == 0)
- n = 1;
- return malloc (n);
-}
+++ /dev/null
-/* 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
+++ /dev/null
-/*
- pidfile.c - interact with pidfiles
- Copyright (c) 1995 Martin Schulze <Martin.Schulze@Linux.DE>
-
- This file is part of the sysklogd package, a kernel and system log daemon.
-
- 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.
-*/
-
-/* left unaltered for tinc -- Ivo Timmermans */
-/*
- * Sat Aug 19 13:24:33 MET DST 1995: Martin Schulze
- * First version (v0.2) released
- */
-
-#include "system.h"
-
-#include "pidfile.h"
-
-#ifndef HAVE_MINGW
-/* read_pid
- *
- * Reads the specified pidfile and returns the read pid.
- * 0 is returned if either there's no pidfile, it's empty
- * or no pid can be read.
- */
-pid_t read_pid (const char *pidfile)
-{
- FILE *f;
- long pid;
-
- if (!(f=fopen(pidfile,"r")))
- return 0;
- if(fscanf(f,"%20ld", &pid) != 1)
- pid = 0;
- fclose(f);
- return pid;
-}
-
-/* check_pid
- *
- * Reads the pid using read_pid and looks up the pid in the process
- * table (using /proc) to determine if the process already exists. If
- * so the pid is returned, otherwise 0.
- */
-pid_t check_pid (const char *pidfile)
-{
- pid_t pid = read_pid(pidfile);
-
- /* Amazing ! _I_ am already holding the pid file... */
- if ((!pid) || (pid == getpid ()))
- return 0;
-
- /*
- * The 'standard' method of doing this is to try and do a 'fake' kill
- * of the process. If an ESRCH error is returned the process cannot
- * be found -- GW
- */
- /* But... errno is usually changed only on error.. */
- errno = 0;
- if (kill(pid, 0) && errno == ESRCH)
- return 0;
-
- return pid;
-}
-
-/* write_pid
- *
- * Writes the pid to the specified file. If that fails 0 is
- * returned, otherwise the pid.
- */
-pid_t write_pid (const char *pidfile)
-{
- FILE *f;
- int fd;
- pid_t pid;
-
- if ((fd = open(pidfile, O_RDWR|O_CREAT, 0644)) == -1) {
- return 0;
- }
-
- if ((f = fdopen(fd, "r+")) == NULL) {
- close(fd);
- return 0;
- }
-
-#ifdef HAVE_FLOCK
- if (flock(fd, LOCK_EX|LOCK_NB) == -1) {
- fclose(f);
- return 0;
- }
-#endif
-
- pid = getpid();
- if (!fprintf(f,"%ld\n", (long)pid)) {
- fclose(f);
- return 0;
- }
- fflush(f);
-
-#ifdef HAVE_FLOCK
- if (flock(fd, LOCK_UN) == -1) {
- fclose(f);
- return 0;
- }
-#endif
- fclose(f);
-
- return pid;
-}
-
-/* remove_pid
- *
- * Remove the the specified file. The result from unlink(2)
- * is returned
- */
-int remove_pid (const char *pidfile)
-{
- return unlink (pidfile);
-}
-#endif
+++ /dev/null
-/*
- pidfile.h - interact with pidfiles
- Copyright (c) 1995 Martin Schulze <Martin.Schulze@Linux.DE>
-
- This file is part of the sysklogd package, a kernel and system log daemon.
-
- 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 HAVE_MINGW
-/* read_pid
- *
- * Reads the specified pidfile and returns the read pid.
- * 0 is returned if either there's no pidfile, it's empty
- * or no pid can be read.
- */
-extern pid_t read_pid (const char *pidfile);
-
-/* check_pid
- *
- * Reads the pid using read_pid and looks up the pid in the process
- * table (using /proc) to determine if the process already exists. If
- * so 1 is returned, otherwise 0.
- */
-extern pid_t check_pid (const char *pidfile);
-
-/* write_pid
- *
- * Writes the pid to the specified file. If that fails 0 is
- * returned, otherwise the pid.
- */
-extern pid_t write_pid (const char *pidfile);
-
-/* remove_pid
- *
- * Remove the the specified file. The result from unlink(2)
- * is returned
- */
-extern int remove_pid (const char *pidfile);
-#endif
+++ /dev/null
-/* Work around bug on some systems where realloc (NULL, 0) fails.
- Copyright (C) 1997 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc., Foundation,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
-
-/* written by Jim Meyering */
-
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
-#undef realloc
-
-#include <sys/types.h>
-
-char *malloc ();
-char *realloc ();
-
-/* Change the size of an allocated block of memory P to N bytes,
- with error checking. If N is zero, change it to 1. If P is NULL,
- use malloc. */
-
-char *
-rpl_realloc (p, n)
- char *p;
- size_t n;
-{
- if (n == 0)
- n = 1;
- if (p == 0)
- return malloc (n);
- return realloc (p, n);
-}
+++ /dev/null
-/*
- splay_tree.c -- splay tree and linked list convenience
- Copyright (C) 2004-2006 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 "splay_tree.h"
-#include "xalloc.h"
-
-/* Splay operation */
-
-static splay_node_t *splay_top_down(splay_tree_t *tree, const void *data, int *result) {
- splay_node_t left = {0}, right = {0};
- splay_node_t *leftbottom = &left, *rightbottom = &right, *child, *grandchild;
- splay_node_t *root = tree->root;
- int c;
-
- if(!root) {
- if(result)
- *result = 0;
- return NULL;
- }
-
- while((c = tree->compare(data, root->data))) {
- if(c < 0 && (child = root->left)) {
- c = tree->compare(data, child->data);
-
- if(c < 0 && (grandchild = child->left)) {
- rightbottom->left = child;
- child->parent = rightbottom;
- rightbottom = child;
-
- if((root->left = child->right))
- child->right->parent = root;
-
- child->right = root;
- root->parent = child;
-
- child->left = NULL;
- grandchild->parent = NULL;
-
- root = grandchild;
- } else if (c > 0 && (grandchild = child->right)) {
- leftbottom->right = child;
- child->parent = leftbottom;
- leftbottom = child;
-
- child->right = NULL;
- grandchild->parent = NULL;
-
- rightbottom->left = root;
- root->parent = rightbottom;
- rightbottom = root;
-
- root->left = NULL;
-
- root = grandchild;
- } else {
- rightbottom->left = root;
- root->parent = rightbottom;
- rightbottom = root;
-
- root->left = NULL;
- child->parent = NULL;
-
- root = child;
- break;
- }
- } else if(c > 0 && (child = root->right)) {
- c = tree->compare(data, child->data);
-
- if(c > 0 && (grandchild = child->right)) {
- leftbottom->right = child;
- child->parent = leftbottom;
- leftbottom = child;
-
- if((root->right = child->left))
- child->left->parent = root;
-
- child->left = root;
- root->parent = child;
-
- child->right = NULL;
- grandchild->parent = NULL;
-
- root = grandchild;
- } else if (c < 0 && (grandchild = child->left)) {
- rightbottom->left = child;
- child->parent = rightbottom;
- rightbottom = child;
-
- child->left = NULL;
- grandchild->parent = NULL;
-
- leftbottom->right = root;
- root->parent = leftbottom;
- leftbottom = root;
-
- root->right = NULL;
-
- root = grandchild;
- } else {
- leftbottom->right = root;
- root->parent = leftbottom;
- leftbottom = root;
-
- root->right = NULL;
- child->parent = NULL;
-
- root = child;
- break;
- }
- } else {
- break;
- }
- }
-
- /* Merge trees */
-
- if(left.right) {
- if(root->left) {
- leftbottom->right = root->left;
- root->left->parent = leftbottom;
- }
- root->left = left.right;
- left.right->parent = root;
- }
-
- if(right.left) {
- if(root->right) {
- rightbottom->left = root->right;
- root->right->parent = rightbottom;
- }
- root->right = right.left;
- right.left->parent = root;
- }
-
- /* Return result */
-
- tree->root = root;
- if(result)
- *result = c;
-
- return tree->root;
-}
-
-static void splay_bottom_up(splay_tree_t *tree, splay_node_t *node) {
- splay_node_t *parent, *grandparent, *greatgrandparent;
-
- while((parent = node->parent)) {
- if(!(grandparent = parent->parent)) { /* zig */
- if(node == parent->left) {
- if((parent->left = node->right))
- parent->left->parent = parent;
- node->right = parent;
- } else {
- if((parent->right = node->left))
- parent->right->parent = parent;
- node->left = parent;
- }
-
- parent->parent = node;
- node->parent = NULL;
- } else {
- greatgrandparent = grandparent->parent;
-
- if(node == parent->left && parent == grandparent->left) { /* left zig-zig */
- if((grandparent->left = parent->right))
- grandparent->left->parent = grandparent;
- parent->right = grandparent;
- grandparent->parent = parent;
-
- if((parent->left = node->right))
- parent->left->parent = parent;
- node->right = parent;
- parent->parent = node;
- } else if(node == parent->right && parent == grandparent->right) { /* right zig-zig */
- if((grandparent->right = parent->left))
- grandparent->right->parent = grandparent;
- parent->left = grandparent;
- grandparent->parent = parent;
-
- if((parent->right = node->left))
- parent->right->parent = parent;
- node->left = parent;
- parent->parent = node;
- } else if(node == parent->right && parent == grandparent->left) { /* left-right zig-zag */
- if((parent->right = node->left))
- parent->right->parent = parent;
- node->left = parent;
- parent->parent = node;
-
- if((grandparent->left = node->right))
- grandparent->left->parent = grandparent;
- node->right = grandparent;
- grandparent->parent = node;
- } else { /* right-left zig-zag */
- if((parent->left = node->right))
- parent->left->parent = parent;
- node->right = parent;
- parent->parent = node;
-
- if((grandparent->right = node->left))
- grandparent->right->parent = grandparent;
- node->left = grandparent;
- grandparent->parent = node;
- }
-
- if((node->parent = greatgrandparent)) {
- if(grandparent == greatgrandparent->left)
- greatgrandparent->left = node;
- else
- greatgrandparent->right = node;
- }
- }
- }
-
- tree->root = node;
-}
-
-/* (De)constructors */
-
-splay_tree_t *splay_alloc_tree(splay_compare_t compare, splay_action_t delete) {
- splay_tree_t *tree;
-
- tree = xmalloc_and_zero(sizeof(splay_tree_t));
- tree->compare = compare;
- tree->delete = delete;
-
- return tree;
-}
-
-void splay_free_tree(splay_tree_t *tree) {
- free(tree);
-}
-
-splay_node_t *splay_alloc_node(void) {
- return xmalloc_and_zero(sizeof(splay_node_t));
-}
-
-void splay_free_node(splay_tree_t *tree, splay_node_t *node) {
- if(node->data && tree->delete)
- tree->delete(node->data);
-
- free(node);
-}
-
-/* Searching */
-
-void *splay_search(splay_tree_t *tree, const void *data) {
- splay_node_t *node;
-
- node = splay_search_node(tree, data);
-
- return node ? node->data : NULL;
-}
-
-void *splay_search_closest(splay_tree_t *tree, const void *data, int *result) {
- splay_node_t *node;
-
- node = splay_search_closest_node(tree, data, result);
-
- return node ? node->data : NULL;
-}
-
-void *splay_search_closest_smaller(splay_tree_t *tree, const void *data) {
- splay_node_t *node;
-
- node = splay_search_closest_smaller_node(tree, data);
-
- return node ? node->data : NULL;
-}
-
-void *splay_search_closest_greater(splay_tree_t *tree, const void *data) {
- splay_node_t *node;
-
- node = splay_search_closest_greater_node(tree, data);
-
- return node ? node->data : NULL;
-}
-
-splay_node_t *splay_search_node(splay_tree_t *tree, const void *data) {
- splay_node_t *node;
- int result;
-
- node = splay_search_closest_node(tree, data, &result);
-
- return result ? NULL : node;
-}
-
-splay_node_t *splay_search_closest_node_nosplay(const splay_tree_t *tree, const void *data, int *result) {
- splay_node_t *node;
- int c;
-
- node = tree->root;
-
- if(!node) {
- if(result)
- *result = 0;
- return NULL;
- }
-
- for(;;) {
- c = tree->compare(data, node->data);
-
- if(c < 0) {
- if(node->left)
- node = node->left;
- else
- break;
- } else if(c > 0) {
- if(node->right)
- node = node->right;
- else
- break;
- } else {
- break;
- }
- }
-
- if(result)
- *result = c;
- return node;
-}
-
-splay_node_t *splay_search_closest_node(splay_tree_t *tree, const void *data, int *result) {
- return splay_top_down(tree, data, result);
-}
-
-splay_node_t *splay_search_closest_smaller_node(splay_tree_t *tree, const void *data) {
- splay_node_t *node;
- int result;
-
- node = splay_search_closest_node(tree, data, &result);
-
- if(result < 0)
- node = node->prev;
-
- return node;
-}
-
-splay_node_t *splay_search_closest_greater_node(splay_tree_t *tree, const void *data) {
- splay_node_t *node;
- int result;
-
- node = splay_search_closest_node(tree, data, &result);
-
- if(result > 0)
- node = node->next;
-
- return node;
-}
-
-/* Insertion and deletion */
-
-splay_node_t *splay_insert(splay_tree_t *tree, void *data) {
- splay_node_t *closest, *new;
- int result;
-
- if(!tree->root) {
- new = splay_alloc_node();
- new->data = data;
- splay_insert_top(tree, new);
- } else {
- closest = splay_search_closest_node(tree, data, &result);
-
- if(!result)
- return NULL;
-
- new = splay_alloc_node();
- new->data = data;
-
- if(result < 0)
- splay_insert_before(tree, closest, new);
- else
- splay_insert_after(tree, closest, new);
- }
-
- return new;
-}
-
-splay_node_t *splay_insert_node(splay_tree_t *tree, splay_node_t *node) {
- splay_node_t *closest;
- int result;
-
- if(!tree->root)
- splay_insert_top(tree, node);
- else {
- closest = splay_search_closest_node(tree, node->data, &result);
-
- if(!result)
- return NULL;
-
- if(result < 0)
- splay_insert_before(tree, closest, node);
- else
- splay_insert_after(tree, closest, node);
- }
-
- return node;
-}
-
-void splay_insert_top(splay_tree_t *tree, splay_node_t *node) {
- node->prev = node->next = node->left = node->right = node->parent = NULL;
- tree->head = tree->tail = tree->root = node;
-}
-
-void splay_insert_before(splay_tree_t *tree, splay_node_t *before, splay_node_t *node) {
- if(!before) {
- if(tree->tail)
- splay_insert_after(tree, tree->tail, node);
- else
- splay_insert_top(tree, node);
- return;
- }
-
- node->next = before;
- if((node->prev = before->prev))
- before->prev->next = node;
- else
- tree->head = node;
- before->prev = node;
-
- splay_bottom_up(tree, before);
-
- node->right = before;
- before->parent = node;
- if((node->left = before->left))
- before->left->parent = node;
- before->left = NULL;
-
- node->parent = NULL;
- tree->root = node;
-}
-
-void splay_insert_after(splay_tree_t *tree, splay_node_t *after, splay_node_t *node) {
- if(!after) {
- if(tree->head)
- splay_insert_before(tree, tree->head, node);
- else
- splay_insert_top(tree, node);
- return;
- }
-
- node->prev = after;
- if((node->next = after->next))
- after->next->prev = node;
- else
- tree->tail = node;
- after->next = node;
-
- splay_bottom_up(tree, after);
-
- node->left = after;
- after->parent = node;
- if((node->right = after->right))
- after->right->parent = node;
- after->right = NULL;
-
- node->parent = NULL;
- tree->root = node;
-}
-
-splay_node_t *splay_unlink(splay_tree_t *tree, void *data) {
- splay_node_t *node;
-
- node = splay_search_node(tree, data);
-
- if(node)
- splay_unlink_node(tree, node);
-
- return node;
-}
-
-void splay_unlink_node(splay_tree_t *tree, splay_node_t *node) {
- if(node->prev)
- node->prev->next = node->next;
- else
- tree->head = node->next;
-
- if(node->next)
- node->next->prev = node->prev;
- else
- tree->tail = node->prev;
-
- splay_bottom_up(tree, node);
-
- if(node->prev) {
- node->left->parent = NULL;
- tree->root = node->left;
- if((node->prev->right = node->right))
- node->right->parent = node->prev;
- } else if(node->next) {
- tree->root = node->right;
- node->right->parent = NULL;
- } else {
- tree->root = NULL;
- }
-}
-
-void splay_delete_node(splay_tree_t *tree, splay_node_t *node) {
- splay_unlink_node(tree, node);
- splay_free_node(tree, node);
-}
-
-void splay_delete(splay_tree_t *tree, void *data) {
- splay_node_t *node;
-
- node = splay_search_node(tree, data);
-
- if(node)
- splay_delete_node(tree, node);
-}
-
-/* Fast tree cleanup */
-
-void splay_delete_tree(splay_tree_t *tree) {
- splay_node_t *node, *next;
-
- for(node = tree->head; node; node = next) {
- next = node->next;
- splay_free_node(tree, node);
- }
-
- splay_free_tree(tree);
-}
-
-/* Tree walking */
-
-void splay_foreach(const splay_tree_t *tree, splay_action_t action) {
- splay_node_t *node, *next;
-
- for(node = tree->head; node; node = next) {
- next = node->next;
- action(node->data);
- }
-}
-
-void splay_foreach_node(const splay_tree_t *tree, splay_action_t action) {
- splay_node_t *node, *next;
-
- for(node = tree->head; node; node = next) {
- next = node->next;
- action(node);
- }
-}
+++ /dev/null
-/*
- splay_tree.h -- header file for splay_tree.c
- Copyright (C) 2004-2006 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 __SPLAY_TREE_H__
-#define __SPLAY_TREE_H__
-
-typedef struct splay_node_t {
-
- /* Linked list part */
-
- struct splay_node_t *next;
- struct splay_node_t *prev;
-
- /* Tree part */
-
- struct splay_node_t *parent;
- struct splay_node_t *left;
- struct splay_node_t *right;
-
- /* Payload */
-
- void *data;
-
-} splay_node_t;
-
-typedef int (*splay_compare_t)(const void *, const void *);
-typedef void (*splay_action_t)(const void *);
-typedef void (*splay_action_node_t)(const splay_node_t *);
-
-typedef struct splay_tree_t {
-
- /* Linked list part */
-
- splay_node_t *head;
- splay_node_t *tail;
-
- /* Tree part */
-
- splay_node_t *root;
-
- splay_compare_t compare;
- splay_action_t delete;
-
-} splay_tree_t;
-
-/* (De)constructors */
-
-extern splay_tree_t *splay_alloc_tree(splay_compare_t, splay_action_t);
-extern void splay_free_tree(splay_tree_t *);
-
-extern splay_node_t *splay_alloc_node(void);
-extern void splay_free_node(splay_tree_t *tree, splay_node_t *);
-
-/* Insertion and deletion */
-
-extern splay_node_t *splay_insert(splay_tree_t *, void *);
-extern splay_node_t *splay_insert_node(splay_tree_t *, splay_node_t *);
-
-extern void splay_insert_top(splay_tree_t *, splay_node_t *);
-extern void splay_insert_before(splay_tree_t *, splay_node_t *, splay_node_t *);
-extern void splay_insert_after(splay_tree_t *, splay_node_t *, splay_node_t *);
-
-extern splay_node_t *splay_unlink(splay_tree_t *, void *);
-extern void splay_unlink_node(splay_tree_t *tree, splay_node_t *);
-extern void splay_delete(splay_tree_t *, void *);
-extern void splay_delete_node(splay_tree_t *, splay_node_t *);
-
-/* Fast tree cleanup */
-
-extern void splay_delete_tree(splay_tree_t *);
-
-/* Searching */
-
-extern void *splay_search(splay_tree_t *, const void *);
-extern void *splay_search_closest(splay_tree_t *, const void *, int *);
-extern void *splay_search_closest_smaller(splay_tree_t *, const void *);
-extern void *splay_search_closest_greater(splay_tree_t *, const void *);
-
-extern splay_node_t *splay_search_node(splay_tree_t *, const void *);
-extern splay_node_t *splay_search_closest_node(splay_tree_t *, const void *, int *);
-extern splay_node_t *splay_search_closest_node_nosplay(const splay_tree_t *, const void *, int *);
-extern splay_node_t *splay_search_closest_smaller_node(splay_tree_t *, const void *);
-extern splay_node_t *splay_search_closest_greater_node(splay_tree_t *, const void *);
-
-/* Tree walking */
-
-extern void splay_foreach(const splay_tree_t *, splay_action_t);
-extern void splay_foreach_node(const splay_tree_t *, splay_action_t);
-
-#endif
+++ /dev/null
-/*
- utils.c -- gathering of some stupid small functions
- Copyright (C) 1999-2005 Ivo Timmermans
- 2000-2009 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 "../src/logger.h"
-#include "utils.h"
-
-static const char hexadecimals[] = "0123456789ABCDEF";
-
-static int charhex2bin(char c) {
- if(isdigit(c))
- return c - '0';
- else
- return toupper(c) - 'A' + 10;
-}
-
-bool hex2bin(char *src, char *dst, int length) {
- for(int i = 0; i < length; i++) {
- if(!isxdigit(src[i * 2]) || !isxdigit(src[i * 2 + 1]))
- return false;
- dst[i] = charhex2bin(src[i * 2]) * 16 + charhex2bin(src[i * 2 + 1]);
- }
- return true;
-}
-
-void bin2hex(char *src, char *dst, int length) {
- int i;
- for(i = length - 1; i >= 0; i--) {
- dst[i * 2 + 1] = hexadecimals[(unsigned char) src[i] & 15];
- dst[i * 2] = hexadecimals[(unsigned char) src[i] >> 4];
- }
-}
-
-#if defined(HAVE_MINGW) || defined(HAVE_CYGWIN)
-#ifdef HAVE_CYGWIN
-#include <w32api/windows.h>
-#endif
-
-const char *winerror(int err) {
- static char buf[1024], *ptr;
-
- ptr = buf + sprintf(buf, "(%d) ", err);
-
- if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), ptr, sizeof(buf) - (ptr - buf), NULL)) {
- strcpy(ptr, "(unable to format errormessage)");
- };
-
- if((ptr = strchr(buf, '\r')))
- *ptr = '\0';
-
- return buf;
-}
-#endif
-
-unsigned int bitfield_to_int(const void *bitfield, size_t size) {
- unsigned int value = 0;
- if(size > sizeof value)
- size = sizeof value;
- memcpy(&value, bitfield, size);
- return value;
-}
+++ /dev/null
-/*
- utils.h -- header file for utils.c
- Copyright (C) 1999-2005 Ivo Timmermans
- 2000-2009 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 __TINC_UTILS_H__
-#define __TINC_UTILS_H__
-
-extern bool hex2bin(char *src, char *dst, int length);
-extern void bin2hex(char *src, char *dst, int length);
-
-#ifdef HAVE_MINGW
-extern const char *winerror(int);
-#define strerror(x) ((x)>0?strerror(x):winerror(GetLastError()))
-#define sockerrno WSAGetLastError()
-#define sockstrerror(x) winerror(x)
-#define sockwouldblock(x) ((x) == WSAEWOULDBLOCK || (x) == WSAEINTR)
-#define sockmsgsize(x) ((x) == WSAEMSGSIZE)
-#define sockinprogress(x) ((x) == WSAEINPROGRESS || (x) == WSAEWOULDBLOCK)
-#else
-#define sockerrno errno
-#define sockstrerror(x) strerror(x)
-#define sockwouldblock(x) ((x) == EWOULDBLOCK || (x) == EINTR)
-#define sockmsgsize(x) ((x) == EMSGSIZE)
-#define sockinprogress(x) ((x) == EINPROGRESS)
-#endif
-
-extern unsigned int bitfield_to_int(const void *bitfield, size_t size);
-
-#endif /* __TINC_UTILS_H__ */
+++ /dev/null
-#include <sys/types.h>
-
-#ifndef PARAMS
-# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
-# define PARAMS(Args) Args
-# else
-# define PARAMS(Args) ()
-# endif
-#endif
-
-/* Exit value when the requested amount of memory is not available.
- The caller may set it to some other value. */
-extern int xalloc_exit_failure;
-
-/* FIXME: describe */
-extern char *const xalloc_msg_memory_exhausted;
-
-/* FIXME: describe */
-extern void (*xalloc_fail_func) (int);
-
-void *xmalloc PARAMS ((size_t n)) __attribute__ ((__malloc__));
-void *xmalloc_and_zero PARAMS ((size_t n)) __attribute__ ((__malloc__));
-void *xcalloc PARAMS ((size_t n, size_t s));
-void *xrealloc PARAMS ((void *p, size_t n)) __attribute__ ((__malloc__));
-
-char *xstrdup PARAMS ((const char *s)) __attribute__ ((__malloc__));
-
-extern int xasprintf(char **strp, const char *fmt, ...);
-extern int xvasprintf(char **strp, const char *fmt, va_list ap);
+++ /dev/null
-/* xmalloc.c -- malloc with out of memory checking
- Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc., Foundation,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
-
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <errno.h>
-
-#if STDC_HEADERS
-# include <stdlib.h>
-#else
-void *calloc ();
-void *malloc ();
-void *realloc ();
-void free ();
-#endif
-
-#include "dropin.h"
-#include "xalloc.h"
-
-#ifndef EXIT_FAILURE
-# define EXIT_FAILURE 1
-#endif
-
-/* Prototypes for functions defined here. */
-#if defined (__STDC__) && __STDC__
-void *xmalloc (size_t n);
-void *xcalloc (size_t n, size_t s);
-void *xrealloc (void *p, size_t n);
-#endif
-
-/* Exit value when the requested amount of memory is not available.
- The caller may set it to some other value. */
-int xalloc_exit_failure = EXIT_FAILURE;
-
-/* FIXME: describe */
-char *const xalloc_msg_memory_exhausted = "Memory exhausted";
-
-/* FIXME: describe */
-void (*xalloc_fail_func) (int) = NULL;
-
-static void
-xalloc_fail (int size)
-{
- if (xalloc_fail_func)
- (*xalloc_fail_func) (size);
- fprintf(stderr, "%s\n", xalloc_msg_memory_exhausted);
- exit(xalloc_exit_failure);
-}
-
-/* Allocate N bytes of memory dynamically, with error checking. */
-
-void *
-xmalloc (size_t n)
-{
- void *p;
-
- p = malloc (n);
- if (p == NULL)
- xalloc_fail ((int)n);
- return p;
-}
-
-/* Allocate N bytes of memory dynamically, and set it all to zero. */
-
-void *
-xmalloc_and_zero (size_t n)
-{
- void *p;
-
- p = malloc (n);
- if (p == NULL)
- xalloc_fail ((int)n);
- memset (p, '\0', n);
- return p;
-}
-
-/* Change the size of an allocated block of memory P to N bytes,
- with error checking.
- If P is NULL, run xmalloc. */
-
-void *
-xrealloc (void *p, size_t n)
-{
- p = realloc (p, n);
- if (p == NULL)
- xalloc_fail (n);
- return p;
-}
-
-/* Duplicate a string */
-
-char *xstrdup(const char *s)
-{
- char *p;
-
- p = strdup(s);
- if(!p)
- xalloc_fail ((int)strlen(s));
- return p;
-}
-
-#ifdef NOT_USED
-
-/* Allocate memory for N elements of S bytes, with error checking. */
-
-void *
-xcalloc (n, s)
- size_t n, s;
-{
- void *p;
-
- p = calloc (n, s);
- if (p == NULL)
- xalloc_fail ();
- return p;
-}
-
-#endif /* NOT_USED */
-
-int xasprintf(char **strp, const char *fmt, ...) {
- int result;
- va_list ap;
- va_start(ap, fmt);
- result = xvasprintf(strp, fmt, ap);
- va_end(ap);
- return result;
-}
-
-int xvasprintf(char **strp, const char *fmt, va_list ap) {
-#ifdef HAVE_MINGW
- char buf[1024];
- int result = vsnprintf(buf, sizeof buf, fmt, ap);
- if(result < 0)
- exit(xalloc_exit_failure);
- *strp = xstrdup(buf);
-#else
- int result = vasprintf(strp, fmt, ap);
- if(result < 0) {
- fprintf(stderr, "vasprintf() failed: %s\n", strerror(errno));
- exit(xalloc_exit_failure);
- }
-#endif
- return result;
-}
sbin_PROGRAMS = tincd
-EXTRA_DIST = linux/device.c bsd/device.c solaris/device.c cygwin/device.c mingw/device.c mingw/common.h
+tincd_SOURCES = \
+ have.h \
+ system.h \
+ avl_tree.c avl_tree.h \
+ conf.c conf.h \
+ connection.c connection.h \
+ device.h \
+ dropin.c dropin.h \
+ dummy_device.c \
+ edge.c edge.h \
+ ethernet.h \
+ event.c event.h \
+ fake-gai-errnos.h \
+ fake-getaddrinfo.c fake-getaddrinfo.h \
+ fake-getnameinfo.c fake-getnameinfo.h \
+ getopt.c getopt.h \
+ getopt1.c \
+ graph.c graph.h \
+ ipv4.h \
+ ipv6.h \
+ list.c list.h \
+ logger.c logger.h \
+ meta.c meta.h \
+ multicast_device.c \
+ net.c net.h \
+ net_packet.c \
+ net_setup.c \
+ net_socket.c \
+ netutl.c netutl.h \
+ node.c node.h \
+ pidfile.c pidfile.h \
+ process.c process.h \
+ protocol.c protocol.h \
+ protocol_auth.c \
+ protocol_edge.c \
+ protocol_misc.c \
+ protocol_key.c \
+ protocol_subnet.c \
+ raw_socket_device.c \
+ route.c route.h \
+ subnet.c subnet.h \
+ tincd.c \
+ utils.c utils.h \
+ xalloc.h \
+ xmalloc.c
-tincd_SOURCES = conf.c connection.c edge.c event.c graph.c logger.c meta.c net.c net_packet.c net_setup.c \
- net_socket.c netutl.c node.c process.c protocol.c protocol_auth.c protocol_edge.c protocol_misc.c \
- protocol_key.c protocol_subnet.c route.c subnet.c tincd.c \
- dummy_device.c raw_socket_device.c multicast_device.c
-
-if UML
-tincd_SOURCES += uml_device.c
-endif
-
-if VDE
-tincd_SOURCES += vde_device.c
+if LINUX
+tincd_SOURCES += linux/device.c
endif
+if BSD
+tincd_SOURCES += bsd/device.c
if TUNEMU
-tincd_SOURCES += bsd/tunemu.c
+tincd_SOURCES += bsd/tunemu.c bsd/tunemu.h
+endif
endif
-nodist_tincd_SOURCES = device.c
+if SOLARIS
+tincd_SOURCES += solaris/device.c
+endif
-DEFAULT_INCLUDES =
+if MINGW
+tincd_SOURCES += mingw/device.c mingw/common.h
+endif
-INCLUDES = @INCLUDES@ -I$(top_builddir) -I$(top_srcdir)/lib
+if CYGWIN
+tincd_SOURCES += cygwin/device.c
+endif
-noinst_HEADERS = conf.h connection.h device.h edge.h event.h graph.h logger.h meta.h net.h netutl.h node.h process.h \
- protocol.h route.h subnet.h bsd/tunemu.h
+if UML
+tincd_SOURCES += uml_device.c
+endif
-LIBS = @LIBS@
+if VDE
+tincd_SOURCES += vde_device.c
+endif
if TUNEMU
LIBS += -lpcap
endif
-tincd_LDADD = \
- $(top_builddir)/lib/libvpn.a
-
-AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\"
-
-dist-hook:
- rm -f `find . -type l`
+AM_CPPFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\"
--- /dev/null
+/*
+ avl_tree.c -- avl_ tree and linked list convenience
+ Copyright (C) 1998 Michael H. Buselli
+ 2000-2005 Ivo Timmermans,
+ 2000-2006 Guus Sliepen <guus@tinc-vpn.org>
+ 2000-2005 Wessel Dankers <wsl@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.
+
+ Original AVL tree library by Michael H. Buselli <cosine@cosine.org>.
+
+ Modified 2000-11-28 by Wessel Dankers <wsl@tinc-vpn.org> to use counts
+ instead of depths, to add the ->next and ->prev and to generally obfuscate
+ the code. Mail me if you found a bug.
+
+ Cleaned up and incorporated some of the ideas from the red-black tree
+ library for inclusion into tinc (http://www.tinc-vpn.org/) by
+ Guus Sliepen <guus@tinc-vpn.org>.
+*/
+
+#include "system.h"
+
+#include "avl_tree.h"
+#include "xalloc.h"
+
+#ifdef AVL_COUNT
+#define AVL_NODE_COUNT(n) ((n) ? (n)->count : 0)
+#define AVL_L_COUNT(n) (AVL_NODE_COUNT((n)->left))
+#define AVL_R_COUNT(n) (AVL_NODE_COUNT((n)->right))
+#define AVL_CALC_COUNT(n) (AVL_L_COUNT(n) + AVL_R_COUNT(n) + 1)
+#endif
+
+#ifdef AVL_DEPTH
+#define AVL_NODE_DEPTH(n) ((n) ? (n)->depth : 0)
+#define L_AVL_DEPTH(n) (AVL_NODE_DEPTH((n)->left))
+#define R_AVL_DEPTH(n) (AVL_NODE_DEPTH((n)->right))
+#define AVL_CALC_DEPTH(n) ((L_AVL_DEPTH(n)>R_AVL_DEPTH(n)?L_AVL_DEPTH(n):R_AVL_DEPTH(n)) + 1)
+#endif
+
+#ifndef AVL_DEPTH
+static int lg(unsigned int u) __attribute__ ((__const__));
+
+static int lg(unsigned int u)
+{
+ int r = 1;
+
+ if(!u)
+ return 0;
+
+ if(u & 0xffff0000) {
+ u >>= 16;
+ r += 16;
+ }
+
+ if(u & 0x0000ff00) {
+ u >>= 8;
+ r += 8;
+ }
+
+ if(u & 0x000000f0) {
+ u >>= 4;
+ r += 4;
+ }
+
+ if(u & 0x0000000c) {
+ u >>= 2;
+ r += 2;
+ }
+
+ if(u & 0x00000002)
+ r++;
+
+ return r;
+}
+#endif
+
+/* Internal helper functions */
+
+static int avl_check_balance(const avl_node_t *node)
+{
+#ifdef AVL_DEPTH
+ int d;
+
+ d = R_AVL_DEPTH(node) - L_AVL_DEPTH(node);
+
+ return d < -1 ? -1 : d > 1 ? 1 : 0;
+#else
+/* int d;
+ * d = lg(AVL_R_COUNT(node)) - lg(AVL_L_COUNT(node));
+ * d = d<-1?-1:d>1?1:0;
+ */
+ int pl, r;
+
+ pl = lg(AVL_L_COUNT(node));
+ r = AVL_R_COUNT(node);
+
+ if(r >> pl + 1)
+ return 1;
+
+ if(pl < 2 || r >> pl - 2)
+ return 0;
+
+ return -1;
+#endif
+}
+
+static void avl_rebalance(avl_tree_t *tree, avl_node_t *node)
+{
+ avl_node_t *child;
+ avl_node_t *gchild;
+ avl_node_t *parent;
+ avl_node_t **superparent;
+
+ parent = node;
+
+ while(node) {
+ parent = node->parent;
+
+ superparent =
+ parent ? node ==
+ parent->left ? &parent->left : &parent->right : &tree->root;
+
+ switch (avl_check_balance(node)) {
+ case -1:
+ child = node->left;
+#ifdef AVL_DEPTH
+ if(L_AVL_DEPTH(child) >= R_AVL_DEPTH(child)) {
+#else
+ if(AVL_L_COUNT(child) >= AVL_R_COUNT(child)) {
+#endif
+ node->left = child->right;
+ if(node->left)
+ node->left->parent = node;
+
+ child->right = node;
+ node->parent = child;
+ *superparent = child;
+ child->parent = parent;
+#ifdef AVL_COUNT
+ node->count = AVL_CALC_COUNT(node);
+ child->count = AVL_CALC_COUNT(child);
+#endif
+#ifdef AVL_DEPTH
+ node->depth = AVL_CALC_DEPTH(node);
+ child->depth = AVL_CALC_DEPTH(child);
+#endif
+ } else {
+ gchild = child->right;
+ node->left = gchild->right;
+
+ if(node->left)
+ node->left->parent = node;
+ child->right = gchild->left;
+
+ if(child->right)
+ child->right->parent = child;
+ gchild->right = node;
+
+ if(gchild->right)
+ gchild->right->parent = gchild;
+ gchild->left = child;
+
+ if(gchild->left)
+ gchild->left->parent = gchild;
+ *superparent = gchild;
+
+ gchild->parent = parent;
+#ifdef AVL_COUNT
+ node->count = AVL_CALC_COUNT(node);
+ child->count = AVL_CALC_COUNT(child);
+ gchild->count = AVL_CALC_COUNT(gchild);
+#endif
+#ifdef AVL_DEPTH
+ node->depth = AVL_CALC_DEPTH(node);
+ child->depth = AVL_CALC_DEPTH(child);
+ gchild->depth = AVL_CALC_DEPTH(gchild);
+#endif
+ }
+ break;
+
+ case 1:
+ child = node->right;
+#ifdef AVL_DEPTH
+ if(R_AVL_DEPTH(child) >= L_AVL_DEPTH(child)) {
+#else
+ if(AVL_R_COUNT(child) >= AVL_L_COUNT(child)) {
+#endif
+ node->right = child->left;
+ if(node->right)
+ node->right->parent = node;
+ child->left = node;
+ node->parent = child;
+ *superparent = child;
+ child->parent = parent;
+#ifdef AVL_COUNT
+ node->count = AVL_CALC_COUNT(node);
+ child->count = AVL_CALC_COUNT(child);
+#endif
+#ifdef AVL_DEPTH
+ node->depth = AVL_CALC_DEPTH(node);
+ child->depth = AVL_CALC_DEPTH(child);
+#endif
+ } else {
+ gchild = child->left;
+ node->right = gchild->left;
+
+ if(node->right)
+ node->right->parent = node;
+ child->left = gchild->right;
+
+ if(child->left)
+ child->left->parent = child;
+ gchild->left = node;
+
+ if(gchild->left)
+ gchild->left->parent = gchild;
+ gchild->right = child;
+
+ if(gchild->right)
+ gchild->right->parent = gchild;
+
+ *superparent = gchild;
+ gchild->parent = parent;
+#ifdef AVL_COUNT
+ node->count = AVL_CALC_COUNT(node);
+ child->count = AVL_CALC_COUNT(child);
+ gchild->count = AVL_CALC_COUNT(gchild);
+#endif
+#ifdef AVL_DEPTH
+ node->depth = AVL_CALC_DEPTH(node);
+ child->depth = AVL_CALC_DEPTH(child);
+ gchild->depth = AVL_CALC_DEPTH(gchild);
+#endif
+ }
+ break;
+
+ default:
+#ifdef AVL_COUNT
+ node->count = AVL_CALC_COUNT(node);
+#endif
+#ifdef AVL_DEPTH
+ node->depth = AVL_CALC_DEPTH(node);
+#endif
+ }
+ node = parent;
+ }
+}
+
+/* (De)constructors */
+
+avl_tree_t *avl_alloc_tree(avl_compare_t compare, avl_action_t delete)
+{
+ avl_tree_t *tree;
+
+ tree = xmalloc_and_zero(sizeof(avl_tree_t));
+ tree->compare = compare;
+ tree->delete = delete;
+
+ return tree;
+}
+
+void avl_free_tree(avl_tree_t *tree)
+{
+ free(tree);
+}
+
+avl_node_t *avl_alloc_node(void)
+{
+ return xmalloc_and_zero(sizeof(avl_node_t));
+}
+
+void avl_free_node(avl_tree_t *tree, avl_node_t *node)
+{
+ if(node->data && tree->delete)
+ tree->delete(node->data);
+
+ free(node);
+}
+
+/* Searching */
+
+void *avl_search(const avl_tree_t *tree, const void *data)
+{
+ avl_node_t *node;
+
+ node = avl_search_node(tree, data);
+
+ return node ? node->data : NULL;
+}
+
+void *avl_search_closest(const avl_tree_t *tree, const void *data, int *result)
+{
+ avl_node_t *node;
+
+ node = avl_search_closest_node(tree, data, result);
+
+ return node ? node->data : NULL;
+}
+
+void *avl_search_closest_smaller(const avl_tree_t *tree, const void *data)
+{
+ avl_node_t *node;
+
+ node = avl_search_closest_smaller_node(tree, data);
+
+ return node ? node->data : NULL;
+}
+
+void *avl_search_closest_greater(const avl_tree_t *tree, const void *data)
+{
+ avl_node_t *node;
+
+ node = avl_search_closest_greater_node(tree, data);
+
+ return node ? node->data : NULL;
+}
+
+avl_node_t *avl_search_node(const avl_tree_t *tree, const void *data)
+{
+ avl_node_t *node;
+ int result;
+
+ node = avl_search_closest_node(tree, data, &result);
+
+ return result ? NULL : node;
+}
+
+avl_node_t *avl_search_closest_node(const avl_tree_t *tree, const void *data,
+ int *result)
+{
+ avl_node_t *node;
+ int c;
+
+ node = tree->root;
+
+ if(!node) {
+ if(result)
+ *result = 0;
+ return NULL;
+ }
+
+ for(;;) {
+ c = tree->compare(data, node->data);
+
+ if(c < 0) {
+ if(node->left)
+ node = node->left;
+ else {
+ if(result)
+ *result = -1;
+ break;
+ }
+ } else if(c > 0) {
+ if(node->right)
+ node = node->right;
+ else {
+ if(result)
+ *result = 1;
+ break;
+ }
+ } else {
+ if(result)
+ *result = 0;
+ break;
+ }
+ }
+
+ return node;
+}
+
+avl_node_t *avl_search_closest_smaller_node(const avl_tree_t *tree,
+ const void *data)
+{
+ avl_node_t *node;
+ int result;
+
+ node = avl_search_closest_node(tree, data, &result);
+
+ if(result < 0)
+ node = node->prev;
+
+ return node;
+}
+
+avl_node_t *avl_search_closest_greater_node(const avl_tree_t *tree,
+ const void *data)
+{
+ avl_node_t *node;
+ int result;
+
+ node = avl_search_closest_node(tree, data, &result);
+
+ if(result > 0)
+ node = node->next;
+
+ return node;
+}
+
+/* Insertion and deletion */
+
+avl_node_t *avl_insert(avl_tree_t *tree, void *data)
+{
+ avl_node_t *closest, *new;
+ int result;
+
+ if(!tree->root) {
+ new = avl_alloc_node();
+ new->data = data;
+ avl_insert_top(tree, new);
+ } else {
+ closest = avl_search_closest_node(tree, data, &result);
+
+ switch (result) {
+ case -1:
+ new = avl_alloc_node();
+ new->data = data;
+ avl_insert_before(tree, closest, new);
+ break;
+
+ case 1:
+ new = avl_alloc_node();
+ new->data = data;
+ avl_insert_after(tree, closest, new);
+ break;
+
+ default:
+ return NULL;
+ }
+ }
+
+#ifdef AVL_COUNT
+ new->count = 1;
+#endif
+#ifdef AVL_DEPTH
+ new->depth = 1;
+#endif
+
+ return new;
+}
+
+avl_node_t *avl_insert_node(avl_tree_t *tree, avl_node_t *node)
+{
+ avl_node_t *closest;
+ int result;
+
+ if(!tree->root)
+ avl_insert_top(tree, node);
+ else {
+ closest = avl_search_closest_node(tree, node->data, &result);
+
+ switch (result) {
+ case -1:
+ avl_insert_before(tree, closest, node);
+ break;
+
+ case 1:
+ avl_insert_after(tree, closest, node);
+ break;
+
+ case 0:
+ return NULL;
+ }
+ }
+
+#ifdef AVL_COUNT
+ node->count = 1;
+#endif
+#ifdef AVL_DEPTH
+ node->depth = 1;
+#endif
+
+ return node;
+}
+
+void avl_insert_top(avl_tree_t *tree, avl_node_t *node)
+{
+ node->prev = node->next = node->parent = NULL;
+ tree->head = tree->tail = tree->root = node;
+}
+
+void avl_insert_before(avl_tree_t *tree, avl_node_t *before,
+ avl_node_t *node)
+{
+ if(!before) {
+ if(tree->tail)
+ avl_insert_after(tree, tree->tail, node);
+ else
+ avl_insert_top(tree, node);
+ return;
+ }
+
+ node->next = before;
+ node->parent = before;
+ node->prev = before->prev;
+
+ if(before->left) {
+ avl_insert_after(tree, before->prev, node);
+ return;
+ }
+
+ if(before->prev)
+ before->prev->next = node;
+ else
+ tree->head = node;
+
+ before->prev = node;
+ before->left = node;
+
+ avl_rebalance(tree, before);
+}
+
+void avl_insert_after(avl_tree_t *tree, avl_node_t *after, avl_node_t *node)
+{
+ if(!after) {
+ if(tree->head)
+ avl_insert_before(tree, tree->head, node);
+ else
+ avl_insert_top(tree, node);
+ return;
+ }
+
+ if(after->right) {
+ avl_insert_before(tree, after->next, node);
+ return;
+ }
+
+ node->prev = after;
+ node->parent = after;
+ node->next = after->next;
+
+ if(after->next)
+ after->next->prev = node;
+ else
+ tree->tail = node;
+
+ after->next = node;
+ after->right = node;
+
+ avl_rebalance(tree, after);
+}
+
+avl_node_t *avl_unlink(avl_tree_t *tree, void *data)
+{
+ avl_node_t *node;
+
+ node = avl_search_node(tree, data);
+
+ if(node)
+ avl_unlink_node(tree, node);
+
+ return node;
+}
+
+void avl_unlink_node(avl_tree_t *tree, avl_node_t *node)
+{
+ avl_node_t *parent;
+ avl_node_t **superparent;
+ avl_node_t *subst, *left, *right;
+ avl_node_t *balnode;
+
+ if(node->prev)
+ node->prev->next = node->next;
+ else
+ tree->head = node->next;
+ if(node->next)
+ node->next->prev = node->prev;
+ else
+ tree->tail = node->prev;
+
+ parent = node->parent;
+
+ superparent =
+ parent ? node ==
+ parent->left ? &parent->left : &parent->right : &tree->root;
+
+ left = node->left;
+ right = node->right;
+ if(!left) {
+ *superparent = right;
+
+ if(right)
+ right->parent = parent;
+
+ balnode = parent;
+ } else if(!right) {
+ *superparent = left;
+ left->parent = parent;
+ balnode = parent;
+ } else {
+ subst = node->prev;
+
+ if(subst == left) {
+ balnode = subst;
+ } else {
+ balnode = subst->parent;
+ balnode->right = subst->left;
+
+ if(balnode->right)
+ balnode->right->parent = balnode;
+
+ subst->left = left;
+ left->parent = subst;
+ }
+
+ subst->right = right;
+ subst->parent = parent;
+ right->parent = subst;
+ *superparent = subst;
+ }
+
+ 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)
+{
+ avl_unlink_node(tree, node);
+ avl_free_node(tree, node);
+}
+
+void avl_delete(avl_tree_t *tree, void *data)
+{
+ avl_node_t *node;
+
+ node = avl_search_node(tree, data);
+
+ if(node)
+ avl_delete_node(tree, node);
+}
+
+/* Fast tree cleanup */
+
+void avl_delete_tree(avl_tree_t *tree)
+{
+ avl_node_t *node, *next;
+
+ for(node = tree->head; node; node = next) {
+ next = node->next;
+ avl_free_node(tree, node);
+ }
+
+ avl_free_tree(tree);
+}
+
+/* Tree walking */
+
+void avl_foreach(const avl_tree_t *tree, avl_action_t action)
+{
+ avl_node_t *node, *next;
+
+ for(node = tree->head; node; node = next) {
+ next = node->next;
+ action(node->data);
+ }
+}
+
+void avl_foreach_node(const avl_tree_t *tree, avl_action_t action)
+{
+ avl_node_t *node, *next;
+
+ for(node = tree->head; node; node = next) {
+ next = node->next;
+ action(node);
+ }
+}
+
+/* Indexing */
+
+#ifdef AVL_COUNT
+unsigned int avl_count(const avl_tree_t *tree)
+{
+ return AVL_NODE_COUNT(tree->root);
+}
+
+avl_node_t *avl_get_node(const avl_tree_t *tree, unsigned int index)
+{
+ avl_node_t *node;
+ unsigned int c;
+
+ node = tree->root;
+
+ while(node) {
+ c = AVL_L_COUNT(node);
+
+ if(index < c) {
+ node = node->left;
+ } else if(index > c) {
+ node = node->right;
+ index -= c + 1;
+ } else {
+ return node;
+ }
+ }
+
+ return NULL;
+}
+
+unsigned int avl_index(const avl_node_t *node)
+{
+ avl_node_t *next;
+ unsigned int index;
+
+ index = AVL_L_COUNT(node);
+
+ while((next = node->parent)) {
+ if(node == next->right)
+ index += AVL_L_COUNT(next) + 1;
+ node = next;
+ }
+
+ return index;
+}
+#endif
+#ifdef AVL_DEPTH
+unsigned int avl_depth(const avl_tree_t *tree)
+{
+ return AVL_NODE_DEPTH(tree->root);
+}
+#endif
--- /dev/null
+/*
+ avl_tree.h -- header file for avl_tree.c
+ Copyright (C) 1998 Michael H. Buselli
+ 2000-2005 Ivo Timmermans,
+ 2000-2006 Guus Sliepen <guus@tinc-vpn.org>
+ 2000-2005 Wessel Dankers <wsl@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.
+
+ Original AVL tree library by Michael H. Buselli <cosine@cosine.org>.
+
+ Modified 2000-11-28 by Wessel Dankers <wsl@tinc-vpn.org> to use counts
+ instead of depths, to add the ->next and ->prev and to generally obfuscate
+ the code. Mail me if you found a bug.
+
+ Cleaned up and incorporated some of the ideas from the red-black tree
+ library for inclusion into tinc (http://www.tinc-vpn.org/) by
+ Guus Sliepen <guus@tinc-vpn.org>.
+*/
+
+
+#ifndef __AVL_TREE_H__
+#define __AVL_TREE_H__
+
+#ifndef AVL_DEPTH
+#ifndef AVL_COUNT
+#define AVL_DEPTH
+#endif
+#endif
+
+typedef struct avl_node_t {
+
+ /* Linked list part */
+
+ struct avl_node_t *next;
+ struct avl_node_t *prev;
+
+ /* Tree part */
+
+ struct avl_node_t *parent;
+ struct avl_node_t *left;
+ struct avl_node_t *right;
+
+#ifdef AVL_COUNT
+ unsigned int count;
+#endif
+#ifdef AVL_DEPTH
+ unsigned char depth;
+#endif
+
+ /* Payload */
+
+ void *data;
+
+} avl_node_t;
+
+typedef int (*avl_compare_t)(const void *, const void *);
+typedef void (*avl_action_t)(const void *);
+typedef void (*avl_action_node_t)(const avl_node_t *);
+
+typedef struct avl_tree_t {
+
+ /* Linked list part */
+
+ avl_node_t *head;
+ avl_node_t *tail;
+
+ /* Tree part */
+
+ avl_node_t *root;
+
+ avl_compare_t compare;
+ avl_action_t delete;
+
+} avl_tree_t;
+
+/* (De)constructors */
+
+extern avl_tree_t *avl_alloc_tree(avl_compare_t, avl_action_t);
+extern void avl_free_tree(avl_tree_t *);
+
+extern avl_node_t *avl_alloc_node(void);
+extern void avl_free_node(avl_tree_t *tree, avl_node_t *);
+
+/* Insertion and deletion */
+
+extern avl_node_t *avl_insert(avl_tree_t *, void *);
+extern avl_node_t *avl_insert_node(avl_tree_t *, avl_node_t *);
+
+extern void avl_insert_top(avl_tree_t *, avl_node_t *);
+extern void avl_insert_before(avl_tree_t *, avl_node_t *, avl_node_t *);
+extern void avl_insert_after(avl_tree_t *, avl_node_t *, avl_node_t *);
+
+extern avl_node_t *avl_unlink(avl_tree_t *, void *);
+extern void avl_unlink_node(avl_tree_t *tree, avl_node_t *);
+extern void avl_delete(avl_tree_t *, void *);
+extern void avl_delete_node(avl_tree_t *, avl_node_t *);
+
+/* Fast tree cleanup */
+
+extern void avl_delete_tree(avl_tree_t *);
+
+/* Searching */
+
+extern void *avl_search(const avl_tree_t *, const void *);
+extern void *avl_search_closest(const avl_tree_t *, const void *, int *);
+extern void *avl_search_closest_smaller(const avl_tree_t *, const void *);
+extern void *avl_search_closest_greater(const avl_tree_t *, const void *);
+
+extern avl_node_t *avl_search_node(const avl_tree_t *, const void *);
+extern avl_node_t *avl_search_closest_node(const avl_tree_t *, const void *, int *);
+extern avl_node_t *avl_search_closest_smaller_node(const avl_tree_t *, const void *);
+extern avl_node_t *avl_search_closest_greater_node(const avl_tree_t *, const void *);
+
+/* Tree walking */
+
+extern void avl_foreach(const avl_tree_t *, avl_action_t);
+extern void avl_foreach_node(const avl_tree_t *, avl_action_t);
+
+/* Indexing */
+
+#ifdef AVL_COUNT
+extern unsigned int avl_count(const avl_tree_t *);
+extern avl_node_t *avl_get_node(const avl_tree_t *, unsigned int);
+extern unsigned int avl_index(const avl_node_t *);
+#endif
+#ifdef AVL_DEPTH
+extern unsigned int avl_depth(const avl_tree_t *);
+#endif
+
+#endif /* __AVL_TREE_H__ */
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "system.h"
+#include "../system.h"
-#include "conf.h"
-#include "device.h"
-#include "logger.h"
-#include "net.h"
-#include "route.h"
-#include "utils.h"
-#include "xalloc.h"
+#include "../conf.h"
+#include "../device.h"
+#include "../logger.h"
+#include "../net.h"
+#include "../route.h"
+#include "../utils.h"
+#include "../xalloc.h"
#ifdef ENABLE_TUNEMU
-#include "bsd/tunemu.h"
+#include "tunemu.h"
#endif
#define DEFAULT_TUN_DEVICE "/dev/tun0"
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "system.h"
+#include "../system.h"
#include <w32api/windows.h>
#include <w32api/winioctl.h>
-#include "conf.h"
-#include "device.h"
-#include "logger.h"
-#include "net.h"
-#include "route.h"
-#include "utils.h"
-#include "xalloc.h"
+#include "../conf.h"
+#include "../device.h"
+#include "../logger.h"
+#include "../net.h"
+#include "../route.h"
+#include "../utils.h"
+#include "../xalloc.h"
-#include "mingw/common.h"
+#include "../mingw/common.h"
int device_fd = -1;
static HANDLE device_handle = INVALID_HANDLE_VALUE;
--- /dev/null
+/*
+ dropin.c -- a set of drop-in replacements for libc functions
+ 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.
+*/
+
+#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
+
+#ifndef HAVE_USLEEP
+int usleep(long long usec) {
+ struct timeval tv = {usec / 1000000, (usec / 1000) % 1000};
+ select(0, NULL, NULL, NULL, &tv);
+ return 0;
+}
+#endif
--- /dev/null
+/*
+ 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
+
+#ifndef HAVE_USLEEP
+extern int usleep(long long);
+#endif
+
+#endif /* __DROPIN_H__ */
--- /dev/null
+/*
+ ethernet.h -- missing Ethernet related definitions
+ Copyright (C) 2005 Ivo Timmermans
+ 2006 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 __TINC_ETHERNET_H__
+#define __TINC_ETHERNET_H__
+
+#ifndef ETH_ALEN
+#define ETH_ALEN 6
+#endif
+
+#ifndef ARPHRD_ETHER
+#define ARPHRD_ETHER 1
+#endif
+
+#ifndef ETH_P_IP
+#define ETH_P_IP 0x0800
+#endif
+
+#ifndef ETH_P_ARP
+#define ETH_P_ARP 0x0806
+#endif
+
+#ifndef ETH_P_IPV6
+#define ETH_P_IPV6 0x86DD
+#endif
+
+#ifndef ETH_P_8021Q
+#define ETH_P_8021Q 0x8100
+#endif
+
+#ifndef HAVE_STRUCT_ETHER_HEADER
+struct ether_header {
+ uint8_t ether_dhost[ETH_ALEN];
+ uint8_t ether_shost[ETH_ALEN];
+ uint16_t ether_type;
+} __attribute__ ((__packed__));
+#endif
+
+#ifndef HAVE_STRUCT_ARPHDR
+struct arphdr {
+ uint16_t ar_hrd;
+ uint16_t ar_pro;
+ uint8_t ar_hln;
+ uint8_t ar_pln;
+ uint16_t ar_op;
+} __attribute__ ((__packed__));
+
+#define ARPOP_REQUEST 1
+#define ARPOP_REPLY 2
+#define ARPOP_RREQUEST 3
+#define ARPOP_RREPLY 4
+#define ARPOP_InREQUEST 8
+#define ARPOP_InREPLY 9
+#define ARPOP_NAK 10
+#endif
+
+#ifndef HAVE_STRUCT_ETHER_ARP
+struct ether_arp {
+ struct arphdr ea_hdr;
+ uint8_t arp_sha[ETH_ALEN];
+ uint8_t arp_spa[4];
+ uint8_t arp_tha[ETH_ALEN];
+ uint8_t arp_tpa[4];
+} __attribute__ ((__packed__));
+#define arp_hrd ea_hdr.ar_hrd
+#define arp_pro ea_hdr.ar_pro
+#define arp_hln ea_hdr.ar_hln
+#define arp_pln ea_hdr.ar_pln
+#define arp_op ea_hdr.ar_op
+#endif
+
+#endif /* __TINC_ETHERNET_H__ */
--- /dev/null
+/*
+ * fake library for ssh
+ *
+ * This file is included in getaddrinfo.c and getnameinfo.c.
+ * See getaddrinfo.c and getnameinfo.c.
+ */
+
+/* for old netdb.h */
+#ifndef EAI_NODATA
+#define EAI_NODATA 1
+#endif
+
+#ifndef EAI_MEMORY
+#define EAI_MEMORY 2
+#endif
+
+#ifndef EAI_FAMILY
+#define EAI_FAMILY 3
+#endif
--- /dev/null
+/*
+ * fake library for ssh
+ *
+ * This file includes getaddrinfo(), freeaddrinfo() and gai_strerror().
+ * These funtions are defined in rfc2133.
+ *
+ * But these functions are not implemented correctly. The minimum subset
+ * is implemented for ssh use only. For exapmle, this routine assumes
+ * that ai_family is AF_INET. Don't use it for another purpose.
+ */
+
+#include "system.h"
+
+#include "ipv4.h"
+#include "ipv6.h"
+#include "fake-getaddrinfo.h"
+#include "xalloc.h"
+
+#if !HAVE_DECL_GAI_STRERROR
+char *gai_strerror(int ecode)
+{
+ switch (ecode) {
+ case EAI_NODATA:
+ return "No address associated with hostname";
+ case EAI_MEMORY:
+ return "Memory allocation failure";
+ case EAI_FAMILY:
+ return "Address family not supported";
+ default:
+ return "Unknown error";
+ }
+}
+#endif /* !HAVE_GAI_STRERROR */
+
+#if !HAVE_DECL_FREEADDRINFO
+void freeaddrinfo(struct addrinfo *ai)
+{
+ struct addrinfo *next;
+
+ while(ai) {
+ next = ai->ai_next;
+ free(ai);
+ ai = next;
+ }
+}
+#endif /* !HAVE_FREEADDRINFO */
+
+#if !HAVE_DECL_GETADDRINFO
+static struct addrinfo *malloc_ai(uint16_t port, uint32_t addr)
+{
+ struct addrinfo *ai;
+
+ ai = xmalloc_and_zero(sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
+
+ ai->ai_addr = (struct sockaddr *)(ai + 1);
+ ai->ai_addrlen = sizeof(struct sockaddr_in);
+ ai->ai_addr->sa_family = ai->ai_family = AF_INET;
+
+ ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
+ ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
+
+ return ai;
+}
+
+int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
+{
+ struct addrinfo *prev = NULL;
+ struct hostent *hp;
+ struct in_addr in = {0};
+ int i;
+ uint16_t port = 0;
+
+ if(hints && hints->ai_family != AF_INET && hints->ai_family != AF_UNSPEC)
+ return EAI_FAMILY;
+
+ if (servname)
+ port = htons(atoi(servname));
+
+ if (hints && hints->ai_flags & AI_PASSIVE) {
+ *res = malloc_ai(port, htonl(0x00000000));
+ return 0;
+ }
+
+ if (!hostname) {
+ *res = malloc_ai(port, htonl(0x7f000001));
+ return 0;
+ }
+
+ hp = gethostbyname(hostname);
+
+ if(!hp || !hp->h_addr_list || !hp->h_addr_list[0])
+ return EAI_NODATA;
+
+ for (i = 0; hp->h_addr_list[i]; i++) {
+ *res = malloc_ai(port, ((struct in_addr *)hp->h_addr_list[i])->s_addr);
+
+ if(prev)
+ prev->ai_next = *res;
+
+ prev = *res;
+ }
+
+ return 0;
+}
+#endif /* !HAVE_GETADDRINFO */
--- /dev/null
+#ifndef _FAKE_GETADDRINFO_H
+#define _FAKE_GETADDRINFO_H
+
+#include "fake-gai-errnos.h"
+
+#ifndef AI_PASSIVE
+# define AI_PASSIVE 1
+# define AI_CANONNAME 2
+#endif
+
+#ifndef NI_NUMERICHOST
+# define NI_NUMERICHOST 2
+# define NI_NAMEREQD 4
+# define NI_NUMERICSERV 8
+#endif
+
+#ifndef AI_NUMERICHOST
+#define AI_NUMERICHOST 4
+#endif
+
+#ifndef HAVE_STRUCT_ADDRINFO
+struct addrinfo {
+ int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
+ int ai_family; /* PF_xxx */
+ int ai_socktype; /* SOCK_xxx */
+ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+ size_t ai_addrlen; /* length of ai_addr */
+ char *ai_canonname; /* canonical name for hostname */
+ struct sockaddr *ai_addr; /* binary address */
+ struct addrinfo *ai_next; /* next structure in linked list */
+};
+#endif /* !HAVE_STRUCT_ADDRINFO */
+
+#if !HAVE_DECL_GETADDRINFO
+int getaddrinfo(const char *hostname, const char *servname,
+ const struct addrinfo *hints, struct addrinfo **res);
+#endif /* !HAVE_GETADDRINFO */
+
+#if !HAVE_DECL_GAI_STRERROR
+char *gai_strerror(int ecode);
+#endif /* !HAVE_GAI_STRERROR */
+
+#if !HAVE_DECL_FREEADDRINFO
+void freeaddrinfo(struct addrinfo *ai);
+#endif /* !HAVE_FREEADDRINFO */
+
+#endif /* _FAKE_GETADDRINFO_H */
--- /dev/null
+/*
+ * fake library for ssh
+ *
+ * This file includes getnameinfo().
+ * These funtions are defined in rfc2133.
+ *
+ * But these functions are not implemented correctly. The minimum subset
+ * is implemented for ssh use only. For exapmle, this routine assumes
+ * that ai_family is AF_INET. Don't use it for another purpose.
+ */
+
+#include "system.h"
+
+#include "fake-getnameinfo.h"
+#include "fake-getaddrinfo.h"
+
+#if !HAVE_DECL_GETNAMEINFO
+
+int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags)
+{
+ struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+ struct hostent *hp;
+ int len;
+
+ if(sa->sa_family != AF_INET)
+ return EAI_FAMILY;
+
+ if(serv && servlen) {
+ len = snprintf(serv, servlen, "%d", ntohs(sin->sin_port));
+ if(len < 0 || len >= servlen)
+ return EAI_MEMORY;
+ }
+
+ if(!host || !hostlen)
+ return 0;
+
+ if(flags & NI_NUMERICHOST) {
+ len = snprintf(host, hostlen, "%s", inet_ntoa(sin->sin_addr));
+ if(len < 0 || len >= hostlen)
+ return EAI_MEMORY;
+ return 0;
+ }
+
+ hp = gethostbyaddr((char *)&sin->sin_addr, sizeof(struct in_addr), AF_INET);
+
+ if(!hp || !hp->h_name || !hp->h_name[0])
+ return EAI_NODATA;
+
+ len = snprintf(host, hostlen, "%s", hp->h_name);
+ if(len < 0 || len >= hostlen)
+ return EAI_MEMORY;
+
+ return 0;
+}
+#endif /* !HAVE_GETNAMEINFO */
--- /dev/null
+#ifndef _FAKE_GETNAMEINFO_H
+#define _FAKE_GETNAMEINFO_H
+
+#if !HAVE_DECL_GETNAMEINFO
+int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
+ size_t hostlen, char *serv, size_t servlen, int flags);
+#endif /* !HAVE_GETNAMEINFO */
+
+#ifndef NI_MAXSERV
+# define NI_MAXSERV 32
+#endif /* !NI_MAXSERV */
+#ifndef NI_MAXHOST
+# define NI_MAXHOST 1025
+#endif /* !NI_MAXHOST */
+
+#endif /* _FAKE_GETNAMEINFO_H */
--- /dev/null
+/* Getopt for GNU.
+ NOTE: getopt is now part of the C library, so if you don't know what
+ "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
+ before changing it!
+
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97
+ Free Software Foundation, Inc.
+
+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.
+*/
+\f
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+ Ditto for AIX 3.2 and <stdlib.h>. */
+#ifndef _NO_PROTO
+#define _NO_PROTO
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "../config.h"
+#endif
+
+#if !defined (__STDC__) || !__STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <stdio.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2
+#include <gnu-versions.h>
+#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#define ELIDE_CODE
+#endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+ contain conflicting prototypes for getopt. */
+#include <stdlib.h>
+#include <unistd.h>
+#endif /* GNU C library. */
+
+#ifdef VMS
+#include <unixlib.h>
+#if HAVE_STRING_H - 0
+#include <string.h>
+#endif
+#endif
+
+#if defined (WIN32) && !defined (__CYGWIN32__)
+/* It's not Unix, really. See? Capital letters. */
+#include <windows.h>
+#define getpid() GetCurrentProcessId()
+#endif
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+ but it behaves differently for the user, since it allows the user
+ to intersperse the options with the other arguments.
+
+ As `getopt' works, it permutes the elements of ARGV so that,
+ when it is done, all the options precede everything else. Thus
+ all application programs are extended to handle flexible argument order.
+
+ Setting the environment variable POSIXLY_CORRECT disables permutation.
+ Then the behavior is completely standard.
+
+ GNU application programs can use a third alternative mode in which
+ they can distinguish the relative order of options and other arguments. */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+char *optarg = NULL;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns -1, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+/* 1003.2 says this must be 1 before any call. */
+int optind = 1;
+
+/* Formerly, initialization of getopt depended on optind==0, which
+ causes problems with re-calling getopt as programs generally don't
+ know that. */
+
+int __getopt_initialized = 0;
+
+/* The next char to be scanned in the option-element
+ in which the last option character we returned was found.
+ This allows us to pick up the scan where we left off.
+
+ If this is zero, or a null string, it means resume the scan
+ by advancing to the next ARGV-element. */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+ for unrecognized options. */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+ This must be initialized on some systems to avoid linking in the
+ system's own getopt implementation. */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+ If the caller did not specify anything,
+ the default is REQUIRE_ORDER if the environment variable
+ POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+ REQUIRE_ORDER means don't recognize them as options;
+ stop option processing when the first non-option is seen.
+ This is what Unix does.
+ This mode of operation is selected by either setting the environment
+ variable POSIXLY_CORRECT, or using `+' as the first character
+ of the list of option characters.
+
+ PERMUTE is the default. We permute the contents of ARGV as we scan,
+ so that eventually all the non-options are at the end. This allows options
+ to be given in any order, even with programs that were not written to
+ expect this.
+
+ RETURN_IN_ORDER is an option available to programs that were written
+ to expect options and other ARGV-elements in any order and that care about
+ the ordering of the two. We describe each non-option ARGV-element
+ as if it were the argument of an option with character code 1.
+ Using `-' as the first character of the list of option characters
+ selects this mode of operation.
+
+ The special argument `--' forces an end of option-scanning regardless
+ of the value of `ordering'. In the case of RETURN_IN_ORDER, only
+ `--' can cause `getopt' to return -1 with `optind' != ARGC. */
+
+static enum
+{
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+/* Value of POSIXLY_CORRECT environment variable. */
+static char *posixly_correct;
+\f
+#ifdef __GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+ because there are many ways it can cause trouble.
+ On some systems, it contains special magic macros that don't work
+ in GCC. */
+#include <string.h>
+#define my_index strchr
+#else
+
+/* Avoid depending on library functions or files
+ whose names are inconsistent. */
+
+char *getenv ();
+
+static char *
+my_index (str, chr)
+ const char *str;
+ int chr;
+{
+ while (*str)
+ {
+ if (*str == chr)
+ return (char *) str;
+ str++;
+ }
+ return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+ If not using GCC, it is ok not to declare it. */
+#ifdef __GNUC__
+/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
+ That was relevant to code that was here before. */
+#if !defined (__STDC__) || !__STDC__
+/* gcc with -traditional declares the built-in strlen to return int,
+ and has done so at least since version 2.4.5. -- rms. */
+extern int strlen (const char *);
+#endif /* not __STDC__ */
+#endif /* __GNUC__ */
+
+#endif /* not __GNU_LIBRARY__ */
+\f
+/* Handle permutation of arguments. */
+
+/* Describe the part of ARGV that contains non-options that have
+ been skipped. `first_nonopt' is the index in ARGV of the first of them;
+ `last_nonopt' is the index after the last of them. */
+
+static int first_nonopt;
+static int last_nonopt;
+
+#ifdef _LIBC
+/* Bash 2.0 gives us an environment variable containing flags
+ indicating ARGV elements that should not be considered arguments. */
+
+/* Defined in getopt_init.c */
+extern char *__getopt_nonoption_flags;
+
+static int nonoption_flags_max_len;
+static int nonoption_flags_len;
+
+static int original_argc;
+static char *const *original_argv;
+
+extern pid_t __libc_pid;
+
+/* Make sure the environment variable bash 2.0 puts in the environment
+ is valid for the getopt call we must make sure that the ARGV passed
+ to getopt is that one passed to the process. */
+static void
+__attribute__ ((__unused__))
+store_args_and_env (int argc, char *const *argv)
+{
+ /* XXX This is no good solution. We should rather copy the args so
+ that we can compare them later. But we must not use malloc(3). */
+ original_argc = argc;
+ original_argv = argv;
+}
+text_set_element (__libc_subinit, store_args_and_env);
+
+# define SWAP_FLAGS(ch1, ch2) \
+ if (nonoption_flags_len > 0) \
+ { \
+ char __tmp = __getopt_nonoption_flags[ch1]; \
+ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
+ __getopt_nonoption_flags[ch2] = __tmp; \
+ }
+#else /* !_LIBC */
+# define SWAP_FLAGS(ch1, ch2)
+#endif /* _LIBC */
+
+/* Exchange two adjacent subsequences of ARGV.
+ One subsequence is elements [first_nonopt,last_nonopt)
+ which contains all the non-options that have been skipped so far.
+ The other is elements [last_nonopt,optind), which contains all
+ the options processed since those non-options were skipped.
+
+ `first_nonopt' and `last_nonopt' are relocated so that they describe
+ the new indices of the non-options in ARGV after they are moved. */
+
+#if defined (__STDC__) && __STDC__
+static void exchange (char **);
+#endif
+
+static void
+exchange (argv)
+ char **argv;
+{
+ int bottom = first_nonopt;
+ int middle = last_nonopt;
+ int top = optind;
+ char *tem;
+
+ /* Exchange the shorter segment with the far end of the longer segment.
+ That puts the shorter segment into the right place.
+ It leaves the longer segment in the right place overall,
+ but it consists of two parts that need to be swapped next. */
+
+#ifdef _LIBC
+ /* First make sure the handling of the `__getopt_nonoption_flags'
+ string can work normally. Our top argument must be in the range
+ of the string. */
+ if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
+ {
+ /* We must extend the array. The user plays games with us and
+ presents new arguments. */
+ char *new_str = malloc (top + 1);
+ if (new_str == NULL)
+ nonoption_flags_len = nonoption_flags_max_len = 0;
+ else
+ {
+ memcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len);
+ memset (&new_str[nonoption_flags_max_len], '\0',
+ top + 1 - nonoption_flags_max_len);
+ nonoption_flags_max_len = top + 1;
+ __getopt_nonoption_flags = new_str;
+ }
+ }
+#endif
+
+ while (top > middle && middle > bottom)
+ {
+ if (top - middle > middle - bottom)
+ {
+ /* Bottom segment is the short one. */
+ int len = middle - bottom;
+ register int i;
+
+ /* Swap it with the top part of the top segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[top - (middle - bottom) + i];
+ argv[top - (middle - bottom) + i] = tem;
+ SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
+ }
+ /* Exclude the moved bottom segment from further swapping. */
+ top -= len;
+ }
+ else
+ {
+ /* Top segment is the short one. */
+ int len = top - middle;
+ register int i;
+
+ /* Swap it with the bottom part of the bottom segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[middle + i];
+ argv[middle + i] = tem;
+ SWAP_FLAGS (bottom + i, middle + i);
+ }
+ /* Exclude the moved top segment from further swapping. */
+ bottom += len;
+ }
+ }
+
+ /* Update records for the slots the non-options now occupy. */
+
+ first_nonopt += (optind - last_nonopt);
+ last_nonopt = optind;
+}
+
+/* Initialize the internal data when the first call is made. */
+
+#if defined (__STDC__) && __STDC__
+static const char *_getopt_initialize (int, char *const *, const char *);
+#endif
+static const char *
+_getopt_initialize (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ /* Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
+
+ first_nonopt = last_nonopt = optind;
+
+ nextchar = NULL;
+
+ posixly_correct = getenv ("POSIXLY_CORRECT");
+
+ /* Determine how to handle the ordering of options and nonoptions. */
+
+ if (optstring[0] == '-')
+ {
+ ordering = RETURN_IN_ORDER;
+ ++optstring;
+ }
+ else if (optstring[0] == '+')
+ {
+ ordering = REQUIRE_ORDER;
+ ++optstring;
+ }
+ else if (posixly_correct != NULL)
+ ordering = REQUIRE_ORDER;
+ else
+ ordering = PERMUTE;
+
+#ifdef _LIBC
+ if (posixly_correct == NULL
+ && argc == original_argc && argv == original_argv)
+ {
+ if (nonoption_flags_max_len == 0)
+ {
+ if (__getopt_nonoption_flags == NULL
+ || __getopt_nonoption_flags[0] == '\0')
+ nonoption_flags_max_len = -1;
+ else
+ {
+ const char *orig_str = __getopt_nonoption_flags;
+ int len = nonoption_flags_max_len = strlen (orig_str);
+ if (nonoption_flags_max_len < argc)
+ nonoption_flags_max_len = argc;
+ __getopt_nonoption_flags =
+ (char *) malloc (nonoption_flags_max_len);
+ if (__getopt_nonoption_flags == NULL)
+ nonoption_flags_max_len = -1;
+ else
+ {
+ memcpy (__getopt_nonoption_flags, orig_str, len);
+ memset (&__getopt_nonoption_flags[len], '\0',
+ nonoption_flags_max_len - len);
+ }
+ }
+ }
+ nonoption_flags_len = nonoption_flags_max_len;
+ }
+ else
+ nonoption_flags_len = 0;
+#endif
+
+ return optstring;
+}
+\f
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+ given in OPTSTRING.
+
+ If an element of ARGV starts with '-', and is not exactly "-" or "--",
+ then it is an option element. The characters of this element
+ (aside from the initial '-') are option characters. If `getopt'
+ is called repeatedly, it returns successively each of the option characters
+ from each of the option elements.
+
+ If `getopt' finds another option character, it returns that character,
+ updating `optind' and `nextchar' so that the next call to `getopt' can
+ resume the scan with the following option character or ARGV-element.
+
+ If there are no more option characters, `getopt' returns -1.
+ Then `optind' is the index in ARGV of the first ARGV-element
+ that is not an option. (The ARGV-elements have been permuted
+ so that those that are not options now come last.)
+
+ OPTSTRING is a string containing the legitimate option characters.
+ If an option character is seen that is not listed in OPTSTRING,
+ return '?' after printing an error message. If you set `opterr' to
+ zero, the error message is suppressed but we still return '?'.
+
+ If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+ so the following text in the same ARGV-element, or the text of the following
+ ARGV-element, is returned in `optarg'. Two colons mean an option that
+ wants an optional arg; if there is text in the current ARGV-element,
+ it is returned in `optarg', otherwise `optarg' is set to zero.
+
+ If OPTSTRING starts with `-' or `+', it requests different methods of
+ handling the non-option ARGV-elements.
+ See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+ Long-named options begin with `--' instead of `-'.
+ Their names may be abbreviated as long as the abbreviation is unique
+ or is an exact match for some defined option. If they have an
+ argument, it follows the option name in the same ARGV-element, separated
+ from the option name by a `=', or else the in next ARGV-element.
+ When `getopt' finds a long-named option, it returns 0 if that option's
+ `flag' field is nonzero, the value of the option's `val' field
+ if the `flag' field is zero.
+
+ The elements of ARGV aren't really const, because we permute them.
+ But we pretend they're const in the prototype to be compatible
+ with other systems.
+
+ LONGOPTS is a vector of `struct option' terminated by an
+ element containing a name which is zero.
+
+ LONGIND returns the index in LONGOPT of the long-named option found.
+ It is only valid when a long-named option has been found by the most
+ recent call.
+
+ If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+ long-named options. */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+ const struct option *longopts;
+ int *longind;
+ int long_only;
+{
+ optarg = NULL;
+
+ if (optind == 0 || !__getopt_initialized)
+ {
+ if (optind == 0)
+ optind = 1; /* Don't scan ARGV[0], the program name. */
+ optstring = _getopt_initialize (argc, argv, optstring);
+ __getopt_initialized = 1;
+ }
+
+ /* Test whether ARGV[optind] points to a non-option argument.
+ Either it does not have option syntax, or there is an environment flag
+ from the shell indicating it is not an option. The later information
+ is only used when the used in the GNU libc. */
+#ifdef _LIBC
+#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
+ || (optind < nonoption_flags_len \
+ && __getopt_nonoption_flags[optind] == '1'))
+#else
+#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#endif
+
+ if (nextchar == NULL || *nextchar == '\0')
+ {
+ /* Advance to the next ARGV-element. */
+
+ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
+ moved back by the user (who may also have changed the arguments). */
+ if (last_nonopt > optind)
+ last_nonopt = optind;
+ if (first_nonopt > optind)
+ first_nonopt = optind;
+
+ if (ordering == PERMUTE)
+ {
+ /* If we have just processed some options following some non-options,
+ exchange them so that the options come first. */
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (last_nonopt != optind)
+ first_nonopt = optind;
+
+ /* Skip any additional non-options
+ and extend the range of non-options previously skipped. */
+
+ while (optind < argc && NONOPTION_P)
+ optind++;
+ last_nonopt = optind;
+ }
+
+ /* The special ARGV-element `--' means premature end of options.
+ Skip it like a null option,
+ then exchange with previous non-options as if it were an option,
+ then skip everything else like a non-option. */
+
+ if (optind != argc && !strcmp (argv[optind], "--"))
+ {
+ optind++;
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (first_nonopt == last_nonopt)
+ first_nonopt = optind;
+ last_nonopt = argc;
+
+ optind = argc;
+ }
+
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
+
+ if (optind == argc)
+ {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (first_nonopt != last_nonopt)
+ optind = first_nonopt;
+ return -1;
+ }
+
+ /* If we have come to a non-option and did not permute it,
+ either stop the scan or describe it to the caller and pass it by. */
+
+ if (NONOPTION_P)
+ {
+ if (ordering == REQUIRE_ORDER)
+ return -1;
+ optarg = argv[optind++];
+ return 1;
+ }
+
+ /* We have found another option-ARGV-element.
+ Skip the initial punctuation. */
+
+ nextchar = (argv[optind] + 1
+ + (longopts != NULL && argv[optind][1] == '-'));
+ }
+
+ /* Decode the current option-ARGV-element. */
+
+ /* Check whether the ARGV-element is a long option.
+
+ If long_only and the ARGV-element has the form "-f", where f is
+ a valid short option, don't consider it an abbreviated form of
+ a long option that starts with f. Otherwise there would be no
+ way to give the -f short option.
+
+ On the other hand, if there's a long option "fubar" and
+ the ARGV-element is "-fu", do consider that an abbreviation of
+ the long option, just like "--fu", and not "-f" with arg "u".
+
+ This distinction seems to be the most useful approach. */
+
+ if (longopts != NULL
+ && (argv[optind][1] == '-'
+ || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = -1;
+ int option_index;
+
+ for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, nextchar, nameend - nextchar))
+ {
+ if ((unsigned int) (nameend - nextchar)
+ == (unsigned int) strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact)
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' is ambiguous\n",
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ optopt = 0;
+ return '?';
+ }
+
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ optind++;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else
+ {
+ if (opterr)
+ {
+ if (argv[optind - 1][1] == '-')
+ /* --option */
+ fprintf (stderr,
+ "%s: option `--%s' doesn't allow an argument\n",
+ argv[0], pfound->name);
+ else
+ /* +option or -option */
+ fprintf (stderr,
+ "%s: option `%c%s' doesn't allow an argument\n",
+ argv[0], argv[optind - 1][0], pfound->name);
+ }
+
+ nextchar += strlen (nextchar);
+
+ optopt = pfound->val;
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (opterr)
+ fprintf (stderr,
+ "%s: option `%s' requires an argument\n",
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ optopt = pfound->val;
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short
+ option, then it's an error.
+ Otherwise interpret it as a short option. */
+ if (!long_only || argv[optind][1] == '-'
+ || my_index (optstring, *nextchar) == NULL)
+ {
+ if (opterr)
+ {
+ if (argv[optind][1] == '-')
+ /* --option */
+ fprintf (stderr, "%s: unrecognized option `--%s'\n",
+ argv[0], nextchar);
+ else
+ /* +option or -option */
+ fprintf (stderr, "%s: unrecognized option `%c%s'\n",
+ argv[0], argv[optind][0], nextchar);
+ }
+ nextchar = (char *) "";
+ optind++;
+ optopt = 0;
+ return '?';
+ }
+ }
+
+ /* Look at and handle the next short option-character. */
+
+ {
+ char c = *nextchar++;
+ char *temp = my_index (optstring, c);
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*nextchar == '\0')
+ ++optind;
+
+ if (temp == NULL || c == ':')
+ {
+ if (opterr)
+ {
+ if (posixly_correct)
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, "%s: illegal option -- %c\n",
+ argv[0], c);
+ else
+ fprintf (stderr, "%s: invalid option -- %c\n",
+ argv[0], c);
+ }
+ optopt = c;
+ return '?';
+ }
+ /* Convenience. Treat POSIX -W foo same as long option --foo */
+ if (temp[0] == 'W' && temp[1] == ';')
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = 0;
+ int option_index;
+
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (opterr)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, "%s: option requires an argument -- %c\n",
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ return c;
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+
+ /* optarg is now the argument, see if it's in the
+ table of longopts. */
+
+ for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, nextchar, nameend - nextchar))
+ {
+ if ((unsigned int) (nameend - nextchar) == strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+ if (ambig && !exact)
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `-W %s' is ambiguous\n",
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ return '?';
+ }
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else
+ {
+ if (opterr)
+ fprintf (stderr,
+ "%s: option `-W %s' doesn't allow an argument\n",
+ argv[0], pfound->name);
+
+ nextchar += strlen (nextchar);
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (opterr)
+ fprintf (stderr,
+ "%s: option `%s' requires an argument\n",
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+ nextchar = NULL;
+ return 'W'; /* Let the application handle it. */
+ }
+ if (temp[1] == ':')
+ {
+ if (temp[2] == ':')
+ {
+ /* This is an option that accepts an argument optionally. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ optind++;
+ }
+ else
+ optarg = NULL;
+ nextchar = NULL;
+ }
+ else
+ {
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (opterr)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr,
+ "%s: option requires an argument -- %c\n",
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+ nextchar = NULL;
+ }
+ }
+ return c;
+ }
+}
+
+int
+getopt (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ return _getopt_internal (argc, argv, optstring,
+ (const struct option *) 0,
+ (int *) 0,
+ 0);
+}
+
+#endif /* Not ELIDE_CODE. */
+\f
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+ the above definition of `getopt'. */
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+
+ c = getopt (argc, argv, "abc:d:0123456789");
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
--- /dev/null
+/* Declarations for getopt.
+ Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc.
+
+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.
+*/
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns -1, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+ for unrecognized options. */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized. */
+
+extern int optopt;
+
+/* Describe the long-named options requested by the application.
+ The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+ of `struct option' terminated by an element containing a name which is
+ zero.
+
+ The field `has_arg' is:
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
+
+ If the field `flag' is not NULL, it points to a variable that is set
+ to the value given in the field `val' when the option is found, but
+ left unchanged if the option is not found.
+
+ To have a long-named option do something other than set an `int' to
+ a compiled-in constant, such as set a value from `optarg', set the
+ option's `flag' field to zero and its `val' field to a nonzero
+ value (the equivalent single-letter option character, if there is
+ one). For long options that have a zero `flag' field, `getopt'
+ returns the contents of the `val' field. */
+
+struct option
+{
+#if defined (__STDC__) && __STDC__
+ const char *name;
+#else
+ char *name;
+#endif
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'. */
+
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+#if defined (__STDC__) && __STDC__
+#ifdef __GNU_LIBRARY__
+/* Many other libraries have conflicting prototypes for getopt, with
+ differences in the consts, in stdlib.h. To avoid compilation
+ errors, only prototype getopt for the GNU C library. */
+extern int getopt (int argc, char *const *argv, const char *shortopts);
+#else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+#endif /* __GNU_LIBRARY__ */
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+ const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind);
+
+/* Internal only. Users should not call this directly. */
+extern int _getopt_internal (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind,
+ int long_only);
+#else /* not __STDC__ */
+extern int getopt ();
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GETOPT_H */
--- /dev/null
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+ Copyright (C) 1987,88,89,90,91,92,93,94,96,97 Free Software Foundation, Inc.
+
+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.
+*/
+\f
+#ifdef HAVE_CONFIG_H
+#include "../config.h"
+#endif
+
+#include "getopt.h"
+
+#if !defined (__STDC__) || !__STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2
+#include <gnu-versions.h>
+#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#define ELIDE_CODE
+#endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+int
+getopt_long (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+ If an option that starts with '-' (not '--') doesn't match a long option,
+ but does match a short option, it is parsed as a short option
+ instead. */
+
+int
+getopt_long_only (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+
+#endif /* Not ELIDE_CODE. */
+\f
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"add", 1, 0, 0},
+ {"append", 0, 0, 0},
+ {"delete", 1, 0, 0},
+ {"verbose", 0, 0, 0},
+ {"create", 0, 0, 0},
+ {"file", 1, 0, 0},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long (argc, argv, "abc:d:0123456789",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case 0:
+ printf ("option %s", long_options[option_index].name);
+ if (optarg)
+ printf (" with arg %s", optarg);
+ printf ("\n");
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case 'd':
+ printf ("option d with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
#include "system.h"
#include "avl_tree.h"
-#include "config.h"
+#include "conf.h"
#include "connection.h"
#include "device.h"
#include "edge.h"
--- /dev/null
+/*
+ have.h -- include headers which are known to exist
+ Copyright (C) 1998-2005 Ivo Timmermans
+ 2003-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 __TINC_HAVE_H__
+#define __TINC_HAVE_H__
+
+#ifdef HAVE_MINGW
+#ifdef WITH_WINDOWS2000
+#define WINVER Windows2000
+#else
+#define WINVER WindowsXP
+#endif
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifdef HAVE_MINGW
+#include <w32api.h>
+#include <winsock2.h>
+#include <windows.h>
+#include <ws2tcpip.h>
+#endif
+
+#ifdef HAVE_STDBOOL_H
+#include <stdbool.h>
+#endif
+
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+
+/* Include system specific headers */
+
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+
+/* SunOS really wants sys/socket.h BEFORE net/if.h,
+ and FreeBSD wants these lines below the rest. */
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+
+#ifdef HAVE_NET_IF_TYPES_H
+#include <net/if_types.h>
+#endif
+
+#ifdef HAVE_NET_IF_TUN_H
+#include <net/if_tun.h>
+#endif
+
+#ifdef HAVE_NET_TUN_IF_TUN_H
+#include <net/tun/if_tun.h>
+#endif
+
+#ifdef HAVE_NET_IF_TAP_H
+#include <net/if_tap.h>
+#endif
+
+#ifdef HAVE_NET_TAP_IF_TAP_H
+#include <net/tap/if_tap.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_SYSTM_H
+#include <netinet/in_systm.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#ifdef HAVE_NETINET_IP_H
+#include <netinet/ip.h>
+#endif
+
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
+
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+
+#ifdef HAVE_NETINET_IP6_H
+#include <netinet/ip6.h>
+#endif
+
+#ifdef HAVE_NET_ETHERNET_H
+#include <net/ethernet.h>
+#endif
+
+#ifdef HAVE_NET_IF_ARP_H
+#include <net/if_arp.h>
+#endif
+
+#ifdef HAVE_NETINET_IP_ICMP_H
+#include <netinet/ip_icmp.h>
+#endif
+
+#ifdef HAVE_NETINET_ICMP6_H
+#include <netinet/icmp6.h>
+#endif
+
+#ifdef HAVE_NETINET_IF_ETHER_H
+#include <netinet/if_ether.h>
+#endif
+
+#endif /* __TINC_SYSTEM_H__ */
--- /dev/null
+/*
+ ipv4.h -- missing IPv4 related definitions
+ Copyright (C) 2005 Ivo Timmermans
+ 2006-2012 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 __TINC_IPV4_H__
+#define __TINC_IPV4_H__
+
+#ifndef AF_INET
+#define AF_INET 2
+#endif
+
+#ifndef IPPROTO_ICMP
+#define IPPROTO_ICMP 1
+#endif
+
+#ifndef ICMP_DEST_UNREACH
+#define ICMP_DEST_UNREACH 3
+#endif
+
+#ifndef ICMP_FRAG_NEEDED
+#define ICMP_FRAG_NEEDED 4
+#endif
+
+#ifndef ICMP_NET_UNKNOWN
+#define ICMP_NET_UNKNOWN 6
+#endif
+
+#ifndef ICMP_TIME_EXCEEDED
+#define ICMP_TIME_EXCEEDED 11
+#endif
+
+#ifndef ICMP_EXC_TTL
+#define ICMP_EXC_TTL 0
+#endif
+
+#ifndef ICMP_NET_UNREACH
+#define ICMP_NET_UNREACH 0
+#endif
+
+#ifndef ICMP_NET_ANO
+#define ICMP_NET_ANO 9
+#endif
+
+#ifndef IP_MSS
+#define IP_MSS 576
+#endif
+
+#ifndef HAVE_STRUCT_IP
+struct ip {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned int ip_hl:4;
+ unsigned int ip_v:4;
+#else
+ unsigned int ip_v:4;
+ unsigned int ip_hl:4;
+#endif
+ uint8_t ip_tos;
+ uint16_t ip_len;
+ uint16_t ip_id;
+ uint16_t ip_off;
+#define IP_RF 0x8000
+#define IP_DF 0x4000
+#define IP_MF 0x2000
+ uint8_t ip_ttl;
+ uint8_t ip_p;
+ uint16_t ip_sum;
+ struct in_addr ip_src, ip_dst;
+} __attribute__ ((__packed__));
+#endif
+
+#ifndef IP_OFFMASK
+#define IP_OFFMASK 0x1fff
+#endif
+
+#ifndef HAVE_STRUCT_ICMP
+struct icmp {
+ uint8_t icmp_type;
+ uint8_t icmp_code;
+ uint16_t icmp_cksum;
+ union {
+ uint8_t ih_pptr;
+ struct in_addr ih_gwaddr;
+ struct ih_idseq {
+ uint16_t icd_id;
+ uint16_t icd_seq;
+ } ih_idseq;
+ uint32_t ih_void;
+
+
+ struct ih_pmtu {
+ uint16_t ipm_void;
+ uint16_t ipm_nextmtu;
+ } ih_pmtu;
+
+ struct ih_rtradv {
+ uint8_t irt_num_addrs;
+ uint8_t irt_wpa;
+ uint16_t irt_lifetime;
+ } ih_rtradv;
+ } icmp_hun;
+#define icmp_pptr icmp_hun.ih_pptr
+#define icmp_gwaddr icmp_hun.ih_gwaddr
+#define icmp_id icmp_hun.ih_idseq.icd_id
+#define icmp_seq icmp_hun.ih_idseq.icd_seq
+#define icmp_void icmp_hun.ih_void
+#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void
+#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu
+#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs
+#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa
+#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime
+ union {
+ struct {
+ uint32_t its_otime;
+ uint32_t its_rtime;
+ uint32_t its_ttime;
+ } id_ts;
+ struct {
+ struct ip idi_ip;
+ } id_ip;
+ uint32_t id_mask;
+ uint8_t id_data[1];
+ } icmp_dun;
+#define icmp_otime icmp_dun.id_ts.its_otime
+#define icmp_rtime icmp_dun.id_ts.its_rtime
+#define icmp_ttime icmp_dun.id_ts.its_ttime
+#define icmp_ip icmp_dun.id_ip.idi_ip
+#define icmp_radv icmp_dun.id_radv
+#define icmp_mask icmp_dun.id_mask
+#define icmp_data icmp_dun.id_data
+} __attribute__ ((__packed__));
+#endif
+
+#endif /* __TINC_IPV4_H__ */
--- /dev/null
+/*
+ ipv6.h -- missing IPv6 related definitions
+ Copyright (C) 2005 Ivo Timmermans
+ 2006-2012 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 __TINC_IPV6_H__
+#define __TINC_IPV6_H__
+
+#ifndef AF_INET6
+#define AF_INET6 10
+#endif
+
+#ifndef IPPROTO_ICMPV6
+#define IPPROTO_ICMPV6 58
+#endif
+
+#ifndef HAVE_STRUCT_IN6_ADDR
+struct in6_addr {
+ union {
+ uint8_t u6_addr8[16];
+ uint16_t u6_addr16[8];
+ uint32_t u6_addr32[4];
+ } in6_u;
+} __attribute__ ((__packed__));
+#define s6_addr in6_u.u6_addr8
+#define s6_addr16 in6_u.u6_addr16
+#define s6_addr32 in6_u.u6_addr32
+#endif
+
+#ifndef HAVE_STRUCT_SOCKADDR_IN6
+struct sockaddr_in6 {
+ uint16_t sin6_family;
+ uint16_t sin6_port;
+ uint32_t sin6_flowinfo;
+ struct in6_addr sin6_addr;
+ uint32_t sin6_scope_id;
+} __attribute__ ((__packed__));
+#endif
+
+#ifndef IN6_IS_ADDR_V4MAPPED
+#define IN6_IS_ADDR_V4MAPPED(a) \
+ ((((__const uint32_t *) (a))[0] == 0) \
+ && (((__const uint32_t *) (a))[1] == 0) \
+ && (((__const uint32_t *) (a))[2] == htonl (0xffff)))
+#endif
+
+#ifndef HAVE_STRUCT_IP6_HDR
+struct ip6_hdr {
+ union {
+ struct ip6_hdrctl {
+ uint32_t ip6_un1_flow;
+ uint16_t ip6_un1_plen;
+ uint8_t ip6_un1_nxt;
+ uint8_t ip6_un1_hlim;
+ } ip6_un1;
+ uint8_t ip6_un2_vfc;
+ } ip6_ctlun;
+ struct in6_addr ip6_src;
+ struct in6_addr ip6_dst;
+} __attribute__ ((__packed__));
+#define ip6_vfc ip6_ctlun.ip6_un2_vfc
+#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow
+#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen
+#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt
+#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim
+#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim
+#endif
+
+#ifndef HAVE_STRUCT_ICMP6_HDR
+struct icmp6_hdr {
+ uint8_t icmp6_type;
+ uint8_t icmp6_code;
+ uint16_t icmp6_cksum;
+ union {
+ uint32_t icmp6_un_data32[1];
+ uint16_t icmp6_un_data16[2];
+ uint8_t icmp6_un_data8[4];
+ } icmp6_dataun;
+} __attribute__ ((__packed__));
+#define ICMP6_DST_UNREACH_NOROUTE 0
+#define ICMP6_DST_UNREACH 1
+#define ICMP6_PACKET_TOO_BIG 2
+#define ICMP6_TIME_EXCEEDED 3
+#define ICMP6_DST_UNREACH_ADMIN 1
+#define ICMP6_DST_UNREACH_ADDR 3
+#define ICMP6_TIME_EXCEED_TRANSIT 0
+#define ND_NEIGHBOR_SOLICIT 135
+#define ND_NEIGHBOR_ADVERT 136
+#define icmp6_data32 icmp6_dataun.icmp6_un_data32
+#define icmp6_data16 icmp6_dataun.icmp6_un_data16
+#define icmp6_data8 icmp6_dataun.icmp6_un_data8
+#define icmp6_mtu icmp6_data32[0]
+#endif
+
+#ifndef HAVE_STRUCT_ND_NEIGHBOR_SOLICIT
+struct nd_neighbor_solicit {
+ struct icmp6_hdr nd_ns_hdr;
+ struct in6_addr nd_ns_target;
+} __attribute__ ((__packed__));
+#define ND_OPT_SOURCE_LINKADDR 1
+#define ND_OPT_TARGET_LINKADDR 2
+#define nd_ns_type nd_ns_hdr.icmp6_type
+#define nd_ns_code nd_ns_hdr.icmp6_code
+#define nd_ns_cksum nd_ns_hdr.icmp6_cksum
+#define nd_ns_reserved nd_ns_hdr.icmp6_data32[0]
+#endif
+
+#ifndef HAVE_STRUCT_ND_OPT_HDR
+struct nd_opt_hdr {
+ uint8_t nd_opt_type;
+ uint8_t nd_opt_len;
+} __attribute__ ((__packed__));
+#endif
+
+#endif /* __TINC_IPV6_H__ */
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "system.h"
+#include "../system.h"
#ifdef HAVE_LINUX_IF_TUN_H
#include <linux/if_tun.h>
#define DEFAULT_DEVICE "/dev/tap0"
#endif
-#include "conf.h"
-#include "device.h"
-#include "logger.h"
-#include "net.h"
-#include "route.h"
-#include "utils.h"
-#include "xalloc.h"
+#include "../conf.h"
+#include "../device.h"
+#include "../logger.h"
+#include "../net.h"
+#include "../route.h"
+#include "../utils.h"
+#include "../xalloc.h"
typedef enum device_type_t {
DEVICE_TYPE_ETHERTAP,
--- /dev/null
+/*
+ list.c -- functions to deal with double linked lists
+ Copyright (C) 2000-2005 Ivo Timmermans
+ 2000-2006 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 "list.h"
+#include "xalloc.h"
+
+/* (De)constructors */
+
+list_t *list_alloc(list_action_t delete) {
+ list_t *list;
+
+ list = xmalloc_and_zero(sizeof(list_t));
+ list->delete = delete;
+
+ return list;
+}
+
+void list_free(list_t *list) {
+ free(list);
+}
+
+list_node_t *list_alloc_node(void) {
+ return xmalloc_and_zero(sizeof(list_node_t));
+}
+
+void list_free_node(list_t *list, list_node_t *node) {
+ if(node->data && list->delete)
+ list->delete(node->data);
+
+ free(node);
+}
+
+/* Insertion and deletion */
+
+list_node_t *list_insert_head(list_t *list, void *data) {
+ list_node_t *node;
+
+ node = list_alloc_node();
+
+ node->data = data;
+ node->prev = NULL;
+ node->next = list->head;
+ list->head = node;
+
+ if(node->next)
+ node->next->prev = node;
+ else
+ list->tail = node;
+
+ list->count++;
+
+ return node;
+}
+
+list_node_t *list_insert_tail(list_t *list, void *data) {
+ list_node_t *node;
+
+ node = list_alloc_node();
+
+ node->data = data;
+ node->next = NULL;
+ node->prev = list->tail;
+ list->tail = node;
+
+ if(node->prev)
+ node->prev->next = node;
+ else
+ list->head = node;
+
+ list->count++;
+
+ return node;
+}
+
+void list_unlink_node(list_t *list, list_node_t *node) {
+ if(node->prev)
+ node->prev->next = node->next;
+ else
+ list->head = node->next;
+
+ if(node->next)
+ node->next->prev = node->prev;
+ else
+ list->tail = node->prev;
+
+ list->count--;
+}
+
+void list_delete_node(list_t *list, list_node_t *node) {
+ list_unlink_node(list, node);
+ list_free_node(list, node);
+}
+
+void list_delete_head(list_t *list) {
+ list_delete_node(list, list->head);
+}
+
+void list_delete_tail(list_t *list) {
+ list_delete_node(list, list->tail);
+}
+
+/* Head/tail lookup */
+
+void *list_get_head(list_t *list) {
+ if(list->head)
+ return list->head->data;
+ else
+ return NULL;
+}
+
+void *list_get_tail(list_t *list) {
+ if(list->tail)
+ return list->tail->data;
+ else
+ return NULL;
+}
+
+/* Fast list deletion */
+
+void list_delete_list(list_t *list) {
+ list_node_t *node, *next;
+
+ for(node = list->head; node; node = next) {
+ next = node->next;
+ list_free_node(list, node);
+ }
+
+ list_free(list);
+}
+
+/* Traversing */
+
+void list_foreach_node(list_t *list, list_action_node_t action) {
+ list_node_t *node, *next;
+
+ for(node = list->head; node; node = next) {
+ next = node->next;
+ action(node);
+ }
+}
+
+void list_foreach(list_t *list, list_action_t action) {
+ list_node_t *node, *next;
+
+ for(node = list->head; node; node = next) {
+ next = node->next;
+ if(node->data)
+ action(node->data);
+ }
+}
--- /dev/null
+/*
+ list.h -- header file for list.c
+ Copyright (C) 2000-2005 Ivo Timmermans
+ 2000-2006 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 __TINC_LIST_H__
+#define __TINC_LIST_H__
+
+typedef struct list_node_t {
+ struct list_node_t *prev;
+ struct list_node_t *next;
+
+ /* Payload */
+
+ void *data;
+} list_node_t;
+
+typedef void (*list_action_t)(const void *);
+typedef void (*list_action_node_t)(const list_node_t *);
+
+typedef struct list_t {
+ list_node_t *head;
+ list_node_t *tail;
+ int count;
+
+ /* Callbacks */
+
+ list_action_t delete;
+} list_t;
+
+/* (De)constructors */
+
+extern list_t *list_alloc(list_action_t) __attribute__ ((__malloc__));
+extern void list_free(list_t *);
+extern list_node_t *list_alloc_node(void);
+extern void list_free_node(list_t *, list_node_t *);
+
+/* Insertion and deletion */
+
+extern list_node_t *list_insert_head(list_t *, void *);
+extern list_node_t *list_insert_tail(list_t *, void *);
+
+extern void list_unlink_node(list_t *, list_node_t *);
+extern void list_delete_node(list_t *, list_node_t *);
+
+extern void list_delete_head(list_t *);
+extern void list_delete_tail(list_t *);
+
+/* Head/tail lookup */
+
+extern void *list_get_head(list_t *);
+extern void *list_get_tail(list_t *);
+
+/* Fast list deletion */
+
+extern void list_delete_list(list_t *);
+
+/* Traversing */
+
+extern void list_foreach(list_t *, list_action_t);
+extern void list_foreach_node(list_t *, list_action_node_t);
+
+#endif /* __TINC_LIST_H__ */
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "system.h"
+#include "../system.h"
#include <windows.h>
#include <winioctl.h>
-#include "conf.h"
-#include "device.h"
-#include "logger.h"
-#include "net.h"
-#include "route.h"
-#include "utils.h"
-#include "xalloc.h"
+#include "../conf.h"
+#include "../device.h"
+#include "../logger.h"
+#include "../net.h"
+#include "../route.h"
+#include "../utils.h"
+#include "../xalloc.h"
-#include "mingw/common.h"
+#include "common.h"
int device_fd = -1;
static HANDLE device_handle = INVALID_HANDLE_VALUE;
--- /dev/null
+/*
+ pidfile.c - interact with pidfiles
+ Copyright (c) 1995 Martin Schulze <Martin.Schulze@Linux.DE>
+
+ This file is part of the sysklogd package, a kernel and system log daemon.
+
+ 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.
+*/
+
+/* left unaltered for tinc -- Ivo Timmermans */
+/*
+ * Sat Aug 19 13:24:33 MET DST 1995: Martin Schulze
+ * First version (v0.2) released
+ */
+
+#include "system.h"
+
+#include "pidfile.h"
+
+#ifndef HAVE_MINGW
+/* read_pid
+ *
+ * Reads the specified pidfile and returns the read pid.
+ * 0 is returned if either there's no pidfile, it's empty
+ * or no pid can be read.
+ */
+pid_t read_pid (const char *pidfile)
+{
+ FILE *f;
+ long pid;
+
+ if (!(f=fopen(pidfile,"r")))
+ return 0;
+ if(fscanf(f,"%20ld", &pid) != 1)
+ pid = 0;
+ fclose(f);
+ return pid;
+}
+
+/* check_pid
+ *
+ * Reads the pid using read_pid and looks up the pid in the process
+ * table (using /proc) to determine if the process already exists. If
+ * so the pid is returned, otherwise 0.
+ */
+pid_t check_pid (const char *pidfile)
+{
+ pid_t pid = read_pid(pidfile);
+
+ /* Amazing ! _I_ am already holding the pid file... */
+ if ((!pid) || (pid == getpid ()))
+ return 0;
+
+ /*
+ * The 'standard' method of doing this is to try and do a 'fake' kill
+ * of the process. If an ESRCH error is returned the process cannot
+ * be found -- GW
+ */
+ /* But... errno is usually changed only on error.. */
+ errno = 0;
+ if (kill(pid, 0) && errno == ESRCH)
+ return 0;
+
+ return pid;
+}
+
+/* write_pid
+ *
+ * Writes the pid to the specified file. If that fails 0 is
+ * returned, otherwise the pid.
+ */
+pid_t write_pid (const char *pidfile)
+{
+ FILE *f;
+ int fd;
+ pid_t pid;
+
+ if ((fd = open(pidfile, O_RDWR|O_CREAT, 0644)) == -1) {
+ return 0;
+ }
+
+ if ((f = fdopen(fd, "r+")) == NULL) {
+ close(fd);
+ return 0;
+ }
+
+#ifdef HAVE_FLOCK
+ if (flock(fd, LOCK_EX|LOCK_NB) == -1) {
+ fclose(f);
+ return 0;
+ }
+#endif
+
+ pid = getpid();
+ if (!fprintf(f,"%ld\n", (long)pid)) {
+ fclose(f);
+ return 0;
+ }
+ fflush(f);
+
+#ifdef HAVE_FLOCK
+ if (flock(fd, LOCK_UN) == -1) {
+ fclose(f);
+ return 0;
+ }
+#endif
+ fclose(f);
+
+ return pid;
+}
+
+/* remove_pid
+ *
+ * Remove the the specified file. The result from unlink(2)
+ * is returned
+ */
+int remove_pid (const char *pidfile)
+{
+ return unlink (pidfile);
+}
+#endif
--- /dev/null
+/*
+ pidfile.h - interact with pidfiles
+ Copyright (c) 1995 Martin Schulze <Martin.Schulze@Linux.DE>
+
+ This file is part of the sysklogd package, a kernel and system log daemon.
+
+ 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 HAVE_MINGW
+/* read_pid
+ *
+ * Reads the specified pidfile and returns the read pid.
+ * 0 is returned if either there's no pidfile, it's empty
+ * or no pid can be read.
+ */
+extern pid_t read_pid (const char *pidfile);
+
+/* check_pid
+ *
+ * Reads the pid using read_pid and looks up the pid in the process
+ * table (using /proc) to determine if the process already exists. If
+ * so 1 is returned, otherwise 0.
+ */
+extern pid_t check_pid (const char *pidfile);
+
+/* write_pid
+ *
+ * Writes the pid to the specified file. If that fails 0 is
+ * returned, otherwise the pid.
+ */
+extern pid_t write_pid (const char *pidfile);
+
+/* remove_pid
+ *
+ * Remove the the specified file. The result from unlink(2)
+ * is returned
+ */
+extern int remove_pid (const char *pidfile);
+#endif
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
-#include "system.h"
+#include "../system.h"
#include <sys/stropts.h>
#include <sys/sockio.h>
#include <net/if_tun.h>
-#include "conf.h"
-#include "device.h"
-#include "logger.h"
-#include "net.h"
-#include "utils.h"
-#include "xalloc.h"
+#include "../conf.h"
+#include "../device.h"
+#include "../logger.h"
+#include "../net.h"
+#include "../utils.h"
+#include "../xalloc.h"
#define DEFAULT_DEVICE "/dev/tun"
--- /dev/null
+/*
+ splay_tree.c -- splay tree and linked list convenience
+ Copyright (C) 2004-2006 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 "splay_tree.h"
+#include "xalloc.h"
+
+/* Splay operation */
+
+static splay_node_t *splay_top_down(splay_tree_t *tree, const void *data, int *result) {
+ splay_node_t left = {0}, right = {0};
+ splay_node_t *leftbottom = &left, *rightbottom = &right, *child, *grandchild;
+ splay_node_t *root = tree->root;
+ int c;
+
+ if(!root) {
+ if(result)
+ *result = 0;
+ return NULL;
+ }
+
+ while((c = tree->compare(data, root->data))) {
+ if(c < 0 && (child = root->left)) {
+ c = tree->compare(data, child->data);
+
+ if(c < 0 && (grandchild = child->left)) {
+ rightbottom->left = child;
+ child->parent = rightbottom;
+ rightbottom = child;
+
+ if((root->left = child->right))
+ child->right->parent = root;
+
+ child->right = root;
+ root->parent = child;
+
+ child->left = NULL;
+ grandchild->parent = NULL;
+
+ root = grandchild;
+ } else if (c > 0 && (grandchild = child->right)) {
+ leftbottom->right = child;
+ child->parent = leftbottom;
+ leftbottom = child;
+
+ child->right = NULL;
+ grandchild->parent = NULL;
+
+ rightbottom->left = root;
+ root->parent = rightbottom;
+ rightbottom = root;
+
+ root->left = NULL;
+
+ root = grandchild;
+ } else {
+ rightbottom->left = root;
+ root->parent = rightbottom;
+ rightbottom = root;
+
+ root->left = NULL;
+ child->parent = NULL;
+
+ root = child;
+ break;
+ }
+ } else if(c > 0 && (child = root->right)) {
+ c = tree->compare(data, child->data);
+
+ if(c > 0 && (grandchild = child->right)) {
+ leftbottom->right = child;
+ child->parent = leftbottom;
+ leftbottom = child;
+
+ if((root->right = child->left))
+ child->left->parent = root;
+
+ child->left = root;
+ root->parent = child;
+
+ child->right = NULL;
+ grandchild->parent = NULL;
+
+ root = grandchild;
+ } else if (c < 0 && (grandchild = child->left)) {
+ rightbottom->left = child;
+ child->parent = rightbottom;
+ rightbottom = child;
+
+ child->left = NULL;
+ grandchild->parent = NULL;
+
+ leftbottom->right = root;
+ root->parent = leftbottom;
+ leftbottom = root;
+
+ root->right = NULL;
+
+ root = grandchild;
+ } else {
+ leftbottom->right = root;
+ root->parent = leftbottom;
+ leftbottom = root;
+
+ root->right = NULL;
+ child->parent = NULL;
+
+ root = child;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
+ /* Merge trees */
+
+ if(left.right) {
+ if(root->left) {
+ leftbottom->right = root->left;
+ root->left->parent = leftbottom;
+ }
+ root->left = left.right;
+ left.right->parent = root;
+ }
+
+ if(right.left) {
+ if(root->right) {
+ rightbottom->left = root->right;
+ root->right->parent = rightbottom;
+ }
+ root->right = right.left;
+ right.left->parent = root;
+ }
+
+ /* Return result */
+
+ tree->root = root;
+ if(result)
+ *result = c;
+
+ return tree->root;
+}
+
+static void splay_bottom_up(splay_tree_t *tree, splay_node_t *node) {
+ splay_node_t *parent, *grandparent, *greatgrandparent;
+
+ while((parent = node->parent)) {
+ if(!(grandparent = parent->parent)) { /* zig */
+ if(node == parent->left) {
+ if((parent->left = node->right))
+ parent->left->parent = parent;
+ node->right = parent;
+ } else {
+ if((parent->right = node->left))
+ parent->right->parent = parent;
+ node->left = parent;
+ }
+
+ parent->parent = node;
+ node->parent = NULL;
+ } else {
+ greatgrandparent = grandparent->parent;
+
+ if(node == parent->left && parent == grandparent->left) { /* left zig-zig */
+ if((grandparent->left = parent->right))
+ grandparent->left->parent = grandparent;
+ parent->right = grandparent;
+ grandparent->parent = parent;
+
+ if((parent->left = node->right))
+ parent->left->parent = parent;
+ node->right = parent;
+ parent->parent = node;
+ } else if(node == parent->right && parent == grandparent->right) { /* right zig-zig */
+ if((grandparent->right = parent->left))
+ grandparent->right->parent = grandparent;
+ parent->left = grandparent;
+ grandparent->parent = parent;
+
+ if((parent->right = node->left))
+ parent->right->parent = parent;
+ node->left = parent;
+ parent->parent = node;
+ } else if(node == parent->right && parent == grandparent->left) { /* left-right zig-zag */
+ if((parent->right = node->left))
+ parent->right->parent = parent;
+ node->left = parent;
+ parent->parent = node;
+
+ if((grandparent->left = node->right))
+ grandparent->left->parent = grandparent;
+ node->right = grandparent;
+ grandparent->parent = node;
+ } else { /* right-left zig-zag */
+ if((parent->left = node->right))
+ parent->left->parent = parent;
+ node->right = parent;
+ parent->parent = node;
+
+ if((grandparent->right = node->left))
+ grandparent->right->parent = grandparent;
+ node->left = grandparent;
+ grandparent->parent = node;
+ }
+
+ if((node->parent = greatgrandparent)) {
+ if(grandparent == greatgrandparent->left)
+ greatgrandparent->left = node;
+ else
+ greatgrandparent->right = node;
+ }
+ }
+ }
+
+ tree->root = node;
+}
+
+/* (De)constructors */
+
+splay_tree_t *splay_alloc_tree(splay_compare_t compare, splay_action_t delete) {
+ splay_tree_t *tree;
+
+ tree = xmalloc_and_zero(sizeof(splay_tree_t));
+ tree->compare = compare;
+ tree->delete = delete;
+
+ return tree;
+}
+
+void splay_free_tree(splay_tree_t *tree) {
+ free(tree);
+}
+
+splay_node_t *splay_alloc_node(void) {
+ return xmalloc_and_zero(sizeof(splay_node_t));
+}
+
+void splay_free_node(splay_tree_t *tree, splay_node_t *node) {
+ if(node->data && tree->delete)
+ tree->delete(node->data);
+
+ free(node);
+}
+
+/* Searching */
+
+void *splay_search(splay_tree_t *tree, const void *data) {
+ splay_node_t *node;
+
+ node = splay_search_node(tree, data);
+
+ return node ? node->data : NULL;
+}
+
+void *splay_search_closest(splay_tree_t *tree, const void *data, int *result) {
+ splay_node_t *node;
+
+ node = splay_search_closest_node(tree, data, result);
+
+ return node ? node->data : NULL;
+}
+
+void *splay_search_closest_smaller(splay_tree_t *tree, const void *data) {
+ splay_node_t *node;
+
+ node = splay_search_closest_smaller_node(tree, data);
+
+ return node ? node->data : NULL;
+}
+
+void *splay_search_closest_greater(splay_tree_t *tree, const void *data) {
+ splay_node_t *node;
+
+ node = splay_search_closest_greater_node(tree, data);
+
+ return node ? node->data : NULL;
+}
+
+splay_node_t *splay_search_node(splay_tree_t *tree, const void *data) {
+ splay_node_t *node;
+ int result;
+
+ node = splay_search_closest_node(tree, data, &result);
+
+ return result ? NULL : node;
+}
+
+splay_node_t *splay_search_closest_node_nosplay(const splay_tree_t *tree, const void *data, int *result) {
+ splay_node_t *node;
+ int c;
+
+ node = tree->root;
+
+ if(!node) {
+ if(result)
+ *result = 0;
+ return NULL;
+ }
+
+ for(;;) {
+ c = tree->compare(data, node->data);
+
+ if(c < 0) {
+ if(node->left)
+ node = node->left;
+ else
+ break;
+ } else if(c > 0) {
+ if(node->right)
+ node = node->right;
+ else
+ break;
+ } else {
+ break;
+ }
+ }
+
+ if(result)
+ *result = c;
+ return node;
+}
+
+splay_node_t *splay_search_closest_node(splay_tree_t *tree, const void *data, int *result) {
+ return splay_top_down(tree, data, result);
+}
+
+splay_node_t *splay_search_closest_smaller_node(splay_tree_t *tree, const void *data) {
+ splay_node_t *node;
+ int result;
+
+ node = splay_search_closest_node(tree, data, &result);
+
+ if(result < 0)
+ node = node->prev;
+
+ return node;
+}
+
+splay_node_t *splay_search_closest_greater_node(splay_tree_t *tree, const void *data) {
+ splay_node_t *node;
+ int result;
+
+ node = splay_search_closest_node(tree, data, &result);
+
+ if(result > 0)
+ node = node->next;
+
+ return node;
+}
+
+/* Insertion and deletion */
+
+splay_node_t *splay_insert(splay_tree_t *tree, void *data) {
+ splay_node_t *closest, *new;
+ int result;
+
+ if(!tree->root) {
+ new = splay_alloc_node();
+ new->data = data;
+ splay_insert_top(tree, new);
+ } else {
+ closest = splay_search_closest_node(tree, data, &result);
+
+ if(!result)
+ return NULL;
+
+ new = splay_alloc_node();
+ new->data = data;
+
+ if(result < 0)
+ splay_insert_before(tree, closest, new);
+ else
+ splay_insert_after(tree, closest, new);
+ }
+
+ return new;
+}
+
+splay_node_t *splay_insert_node(splay_tree_t *tree, splay_node_t *node) {
+ splay_node_t *closest;
+ int result;
+
+ if(!tree->root)
+ splay_insert_top(tree, node);
+ else {
+ closest = splay_search_closest_node(tree, node->data, &result);
+
+ if(!result)
+ return NULL;
+
+ if(result < 0)
+ splay_insert_before(tree, closest, node);
+ else
+ splay_insert_after(tree, closest, node);
+ }
+
+ return node;
+}
+
+void splay_insert_top(splay_tree_t *tree, splay_node_t *node) {
+ node->prev = node->next = node->left = node->right = node->parent = NULL;
+ tree->head = tree->tail = tree->root = node;
+}
+
+void splay_insert_before(splay_tree_t *tree, splay_node_t *before, splay_node_t *node) {
+ if(!before) {
+ if(tree->tail)
+ splay_insert_after(tree, tree->tail, node);
+ else
+ splay_insert_top(tree, node);
+ return;
+ }
+
+ node->next = before;
+ if((node->prev = before->prev))
+ before->prev->next = node;
+ else
+ tree->head = node;
+ before->prev = node;
+
+ splay_bottom_up(tree, before);
+
+ node->right = before;
+ before->parent = node;
+ if((node->left = before->left))
+ before->left->parent = node;
+ before->left = NULL;
+
+ node->parent = NULL;
+ tree->root = node;
+}
+
+void splay_insert_after(splay_tree_t *tree, splay_node_t *after, splay_node_t *node) {
+ if(!after) {
+ if(tree->head)
+ splay_insert_before(tree, tree->head, node);
+ else
+ splay_insert_top(tree, node);
+ return;
+ }
+
+ node->prev = after;
+ if((node->next = after->next))
+ after->next->prev = node;
+ else
+ tree->tail = node;
+ after->next = node;
+
+ splay_bottom_up(tree, after);
+
+ node->left = after;
+ after->parent = node;
+ if((node->right = after->right))
+ after->right->parent = node;
+ after->right = NULL;
+
+ node->parent = NULL;
+ tree->root = node;
+}
+
+splay_node_t *splay_unlink(splay_tree_t *tree, void *data) {
+ splay_node_t *node;
+
+ node = splay_search_node(tree, data);
+
+ if(node)
+ splay_unlink_node(tree, node);
+
+ return node;
+}
+
+void splay_unlink_node(splay_tree_t *tree, splay_node_t *node) {
+ if(node->prev)
+ node->prev->next = node->next;
+ else
+ tree->head = node->next;
+
+ if(node->next)
+ node->next->prev = node->prev;
+ else
+ tree->tail = node->prev;
+
+ splay_bottom_up(tree, node);
+
+ if(node->prev) {
+ node->left->parent = NULL;
+ tree->root = node->left;
+ if((node->prev->right = node->right))
+ node->right->parent = node->prev;
+ } else if(node->next) {
+ tree->root = node->right;
+ node->right->parent = NULL;
+ } else {
+ tree->root = NULL;
+ }
+}
+
+void splay_delete_node(splay_tree_t *tree, splay_node_t *node) {
+ splay_unlink_node(tree, node);
+ splay_free_node(tree, node);
+}
+
+void splay_delete(splay_tree_t *tree, void *data) {
+ splay_node_t *node;
+
+ node = splay_search_node(tree, data);
+
+ if(node)
+ splay_delete_node(tree, node);
+}
+
+/* Fast tree cleanup */
+
+void splay_delete_tree(splay_tree_t *tree) {
+ splay_node_t *node, *next;
+
+ for(node = tree->head; node; node = next) {
+ next = node->next;
+ splay_free_node(tree, node);
+ }
+
+ splay_free_tree(tree);
+}
+
+/* Tree walking */
+
+void splay_foreach(const splay_tree_t *tree, splay_action_t action) {
+ splay_node_t *node, *next;
+
+ for(node = tree->head; node; node = next) {
+ next = node->next;
+ action(node->data);
+ }
+}
+
+void splay_foreach_node(const splay_tree_t *tree, splay_action_t action) {
+ splay_node_t *node, *next;
+
+ for(node = tree->head; node; node = next) {
+ next = node->next;
+ action(node);
+ }
+}
--- /dev/null
+/*
+ splay_tree.h -- header file for splay_tree.c
+ Copyright (C) 2004-2006 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 __SPLAY_TREE_H__
+#define __SPLAY_TREE_H__
+
+typedef struct splay_node_t {
+
+ /* Linked list part */
+
+ struct splay_node_t *next;
+ struct splay_node_t *prev;
+
+ /* Tree part */
+
+ struct splay_node_t *parent;
+ struct splay_node_t *left;
+ struct splay_node_t *right;
+
+ /* Payload */
+
+ void *data;
+
+} splay_node_t;
+
+typedef int (*splay_compare_t)(const void *, const void *);
+typedef void (*splay_action_t)(const void *);
+typedef void (*splay_action_node_t)(const splay_node_t *);
+
+typedef struct splay_tree_t {
+
+ /* Linked list part */
+
+ splay_node_t *head;
+ splay_node_t *tail;
+
+ /* Tree part */
+
+ splay_node_t *root;
+
+ splay_compare_t compare;
+ splay_action_t delete;
+
+} splay_tree_t;
+
+/* (De)constructors */
+
+extern splay_tree_t *splay_alloc_tree(splay_compare_t, splay_action_t);
+extern void splay_free_tree(splay_tree_t *);
+
+extern splay_node_t *splay_alloc_node(void);
+extern void splay_free_node(splay_tree_t *tree, splay_node_t *);
+
+/* Insertion and deletion */
+
+extern splay_node_t *splay_insert(splay_tree_t *, void *);
+extern splay_node_t *splay_insert_node(splay_tree_t *, splay_node_t *);
+
+extern void splay_insert_top(splay_tree_t *, splay_node_t *);
+extern void splay_insert_before(splay_tree_t *, splay_node_t *, splay_node_t *);
+extern void splay_insert_after(splay_tree_t *, splay_node_t *, splay_node_t *);
+
+extern splay_node_t *splay_unlink(splay_tree_t *, void *);
+extern void splay_unlink_node(splay_tree_t *tree, splay_node_t *);
+extern void splay_delete(splay_tree_t *, void *);
+extern void splay_delete_node(splay_tree_t *, splay_node_t *);
+
+/* Fast tree cleanup */
+
+extern void splay_delete_tree(splay_tree_t *);
+
+/* Searching */
+
+extern void *splay_search(splay_tree_t *, const void *);
+extern void *splay_search_closest(splay_tree_t *, const void *, int *);
+extern void *splay_search_closest_smaller(splay_tree_t *, const void *);
+extern void *splay_search_closest_greater(splay_tree_t *, const void *);
+
+extern splay_node_t *splay_search_node(splay_tree_t *, const void *);
+extern splay_node_t *splay_search_closest_node(splay_tree_t *, const void *, int *);
+extern splay_node_t *splay_search_closest_node_nosplay(const splay_tree_t *, const void *, int *);
+extern splay_node_t *splay_search_closest_smaller_node(splay_tree_t *, const void *);
+extern splay_node_t *splay_search_closest_greater_node(splay_tree_t *, const void *);
+
+/* Tree walking */
+
+extern void splay_foreach(const splay_tree_t *, splay_action_t);
+extern void splay_foreach_node(const splay_tree_t *, splay_action_t);
+
+#endif
--- /dev/null
+/*
+ system.h -- system headers
+ Copyright (C) 1998-2005 Ivo Timmermans
+ 2003-2006 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 __TINC_SYSTEM_H__
+#define __TINC_SYSTEM_H__
+
+#include "../config.h"
+
+#include "have.h"
+
+#ifndef HAVE_STDBOOL_H
+typedef int bool;
+#define true 1
+#define false 0
+#endif
+
+#ifndef HAVE_STRSIGNAL
+# define strsignal(p) ""
+#endif
+
+/* Other functions */
+
+#include "dropin.h"
+
+#ifndef HAVE_SOCKLEN_T
+typedef int socklen_t;
+#endif
+
+#endif /* __TINC_SYSTEM_H__ */
--- /dev/null
+/*
+ utils.c -- gathering of some stupid small functions
+ Copyright (C) 1999-2005 Ivo Timmermans
+ 2000-2009 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 "../src/logger.h"
+#include "utils.h"
+
+static const char hexadecimals[] = "0123456789ABCDEF";
+
+static int charhex2bin(char c) {
+ if(isdigit(c))
+ return c - '0';
+ else
+ return toupper(c) - 'A' + 10;
+}
+
+bool hex2bin(char *src, char *dst, int length) {
+ for(int i = 0; i < length; i++) {
+ if(!isxdigit(src[i * 2]) || !isxdigit(src[i * 2 + 1]))
+ return false;
+ dst[i] = charhex2bin(src[i * 2]) * 16 + charhex2bin(src[i * 2 + 1]);
+ }
+ return true;
+}
+
+void bin2hex(char *src, char *dst, int length) {
+ int i;
+ for(i = length - 1; i >= 0; i--) {
+ dst[i * 2 + 1] = hexadecimals[(unsigned char) src[i] & 15];
+ dst[i * 2] = hexadecimals[(unsigned char) src[i] >> 4];
+ }
+}
+
+#if defined(HAVE_MINGW) || defined(HAVE_CYGWIN)
+#ifdef HAVE_CYGWIN
+#include <w32api/windows.h>
+#endif
+
+const char *winerror(int err) {
+ static char buf[1024], *ptr;
+
+ ptr = buf + sprintf(buf, "(%d) ", err);
+
+ if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), ptr, sizeof(buf) - (ptr - buf), NULL)) {
+ strcpy(ptr, "(unable to format errormessage)");
+ };
+
+ if((ptr = strchr(buf, '\r')))
+ *ptr = '\0';
+
+ return buf;
+}
+#endif
+
+unsigned int bitfield_to_int(const void *bitfield, size_t size) {
+ unsigned int value = 0;
+ if(size > sizeof value)
+ size = sizeof value;
+ memcpy(&value, bitfield, size);
+ return value;
+}
--- /dev/null
+/*
+ utils.h -- header file for utils.c
+ Copyright (C) 1999-2005 Ivo Timmermans
+ 2000-2009 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 __TINC_UTILS_H__
+#define __TINC_UTILS_H__
+
+extern bool hex2bin(char *src, char *dst, int length);
+extern void bin2hex(char *src, char *dst, int length);
+
+#ifdef HAVE_MINGW
+extern const char *winerror(int);
+#define strerror(x) ((x)>0?strerror(x):winerror(GetLastError()))
+#define sockerrno WSAGetLastError()
+#define sockstrerror(x) winerror(x)
+#define sockwouldblock(x) ((x) == WSAEWOULDBLOCK || (x) == WSAEINTR)
+#define sockmsgsize(x) ((x) == WSAEMSGSIZE)
+#define sockinprogress(x) ((x) == WSAEINPROGRESS || (x) == WSAEWOULDBLOCK)
+#else
+#define sockerrno errno
+#define sockstrerror(x) strerror(x)
+#define sockwouldblock(x) ((x) == EWOULDBLOCK || (x) == EINTR)
+#define sockmsgsize(x) ((x) == EMSGSIZE)
+#define sockinprogress(x) ((x) == EINPROGRESS)
+#endif
+
+extern unsigned int bitfield_to_int(const void *bitfield, size_t size);
+
+#endif /* __TINC_UTILS_H__ */
--- /dev/null
+#include <sys/types.h>
+
+#ifndef PARAMS
+# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
+# define PARAMS(Args) Args
+# else
+# define PARAMS(Args) ()
+# endif
+#endif
+
+/* Exit value when the requested amount of memory is not available.
+ The caller may set it to some other value. */
+extern int xalloc_exit_failure;
+
+/* FIXME: describe */
+extern char *const xalloc_msg_memory_exhausted;
+
+/* FIXME: describe */
+extern void (*xalloc_fail_func) (int);
+
+void *xmalloc PARAMS ((size_t n)) __attribute__ ((__malloc__));
+void *xmalloc_and_zero PARAMS ((size_t n)) __attribute__ ((__malloc__));
+void *xcalloc PARAMS ((size_t n, size_t s));
+void *xrealloc PARAMS ((void *p, size_t n)) __attribute__ ((__malloc__));
+
+char *xstrdup PARAMS ((const char *s)) __attribute__ ((__malloc__));
+
+extern int xasprintf(char **strp, const char *fmt, ...);
+extern int xvasprintf(char **strp, const char *fmt, va_list ap);
--- /dev/null
+/* xmalloc.c -- malloc with out of memory checking
+ Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc., Foundation,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+#if HAVE_CONFIG_H
+# include "../config.h"
+#endif
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#if STDC_HEADERS
+# include <stdlib.h>
+#else
+void *calloc ();
+void *malloc ();
+void *realloc ();
+void free ();
+#endif
+
+#include "dropin.h"
+#include "xalloc.h"
+
+#ifndef EXIT_FAILURE
+# define EXIT_FAILURE 1
+#endif
+
+/* Prototypes for functions defined here. */
+#if defined (__STDC__) && __STDC__
+void *xmalloc (size_t n);
+void *xcalloc (size_t n, size_t s);
+void *xrealloc (void *p, size_t n);
+#endif
+
+/* Exit value when the requested amount of memory is not available.
+ The caller may set it to some other value. */
+int xalloc_exit_failure = EXIT_FAILURE;
+
+/* FIXME: describe */
+char *const xalloc_msg_memory_exhausted = "Memory exhausted";
+
+/* FIXME: describe */
+void (*xalloc_fail_func) (int) = NULL;
+
+static void
+xalloc_fail (int size)
+{
+ if (xalloc_fail_func)
+ (*xalloc_fail_func) (size);
+ fprintf(stderr, "%s\n", xalloc_msg_memory_exhausted);
+ exit(xalloc_exit_failure);
+}
+
+/* Allocate N bytes of memory dynamically, with error checking. */
+
+void *
+xmalloc (size_t n)
+{
+ void *p;
+
+ p = malloc (n);
+ if (p == NULL)
+ xalloc_fail ((int)n);
+ return p;
+}
+
+/* Allocate N bytes of memory dynamically, and set it all to zero. */
+
+void *
+xmalloc_and_zero (size_t n)
+{
+ void *p;
+
+ p = malloc (n);
+ if (p == NULL)
+ xalloc_fail ((int)n);
+ memset (p, '\0', n);
+ return p;
+}
+
+/* Change the size of an allocated block of memory P to N bytes,
+ with error checking.
+ If P is NULL, run xmalloc. */
+
+void *
+xrealloc (void *p, size_t n)
+{
+ p = realloc (p, n);
+ if (p == NULL)
+ xalloc_fail (n);
+ return p;
+}
+
+/* Duplicate a string */
+
+char *xstrdup(const char *s)
+{
+ char *p;
+
+ p = strdup(s);
+ if(!p)
+ xalloc_fail ((int)strlen(s));
+ return p;
+}
+
+#ifdef NOT_USED
+
+/* Allocate memory for N elements of S bytes, with error checking. */
+
+void *
+xcalloc (n, s)
+ size_t n, s;
+{
+ void *p;
+
+ p = calloc (n, s);
+ if (p == NULL)
+ xalloc_fail ();
+ return p;
+}
+
+#endif /* NOT_USED */
+
+int xasprintf(char **strp, const char *fmt, ...) {
+ int result;
+ va_list ap;
+ va_start(ap, fmt);
+ result = xvasprintf(strp, fmt, ap);
+ va_end(ap);
+ return result;
+}
+
+int xvasprintf(char **strp, const char *fmt, va_list ap) {
+#ifdef HAVE_MINGW
+ char buf[1024];
+ int result = vsnprintf(buf, sizeof buf, fmt, ap);
+ if(result < 0)
+ exit(xalloc_exit_failure);
+ *strp = xstrdup(buf);
+#else
+ int result = vasprintf(strp, fmt, ap);
+ if(result < 0) {
+ fprintf(stderr, "vasprintf() failed: %s\n", strerror(errno));
+ exit(xalloc_exit_failure);
+ }
+#endif
+ return result;
+}
+++ /dev/null
-/*
- system.h -- system headers
- Copyright (C) 1998-2005 Ivo Timmermans
- 2003-2006 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 __TINC_SYSTEM_H__
-#define __TINC_SYSTEM_H__
-
-#include "config.h"
-
-#include "have.h"
-
-#ifndef HAVE_STDBOOL_H
-typedef int bool;
-#define true 1
-#define false 0
-#endif
-
-#ifndef HAVE_STRSIGNAL
-# define strsignal(p) ""
-#endif
-
-/* Other functions */
-
-#include "dropin.h"
-
-#ifndef HAVE_SOCKLEN_T
-typedef int socklen_t;
-#endif
-
-#endif /* __TINC_SYSTEM_H__ */